日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 Go(又稱Golang)是Google公司于2007年設(shè)計的一種開源編程語言,并于2012年向公眾開放。多年來,它在開發(fā)者中廣受歡迎,但它并不總是被用于“善意”的用途。正如經(jīng)常發(fā)生的那樣,它也吸引了惡意軟件開發(fā)者的注意。

成都創(chuàng)新互聯(lián)公司10多年企業(yè)網(wǎng)站建設(shè)服務(wù);為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及高端網(wǎng)站定制服務(wù),企業(yè)網(wǎng)站建設(shè)及推廣,對成都餐廳設(shè)計等多個領(lǐng)域擁有多年的網(wǎng)站推廣經(jīng)驗(yàn)的網(wǎng)站建設(shè)公司。

對于惡意軟件開發(fā)者來說,使用Go語言是一個誘人的選擇,因?yàn)樗С纸徊婢幾g,也就是說,可以把Go語言編寫的代碼編譯成在不同操作系統(tǒng)上運(yùn)行的二進(jìn)制文件。這樣的話,就能夠讓攻擊者的生活變得更加輕松,因?yàn)樗麄儾槐貫槊總€目標(biāo)環(huán)境開發(fā)和維護(hù)不同的代碼庫了,豈不快哉。

對Go二進(jìn)制程序進(jìn)行逆向分析的必要性

由于Go編程語言的某些特性的原因,逆向工程師在處理Go二進(jìn)制文件時通常會遇到許多阻力。盡管目前的逆向分析工具(例如反匯編器)可以很好地分析非常流行的語言(例如C、C++、.NET)編寫的二進(jìn)制文件,但是Go語言卻帶來了新的挑戰(zhàn),使得分析工作變得更加繁瑣。

Go二進(jìn)制文件通常是靜態(tài)鏈接的,這意味著所有必要的庫都包含在編譯后的二進(jìn)制文件中。這會導(dǎo)致二進(jìn)制文件的塊頭變大,從而使得惡意軟件的分發(fā)對攻擊者來說更加困難。另一方面,一些安全產(chǎn)品在處理大文件時也存在問題。這意味著大型二進(jìn)制文件可以幫助惡意軟件避開檢測。靜態(tài)鏈接的二進(jìn)制文件對攻擊者的另一個好處是,惡意軟件可以直接在目標(biāo)系統(tǒng)上運(yùn)行,而不會遇到依賴問題。

當(dāng)我們看到用Go編寫的惡意軟件持續(xù)增長,并預(yù)計會出現(xiàn)更多的惡意軟件家族時,我們決定更深入地研究Go編程語言,并增強(qiáng)我們的工具集,以便更有效地調(diào)查Go惡意軟件。

在本文中,我將討論逆向工程師在分析Go二進(jìn)制代碼的過程中所面臨的兩個難題,以及相應(yīng)的解決方案。

Ghidra是美國國家安全局開發(fā)的一個開源逆向分析工具,我們經(jīng)常使用它來進(jìn)行惡意軟件的靜態(tài)分析。我們可以為Ghidra創(chuàng)建自定義腳本和插件,以按需實(shí)現(xiàn)特定的功能。在這里,我們將利用Ghidra的這個特性,通過創(chuàng)建自定義的腳本來幫助我們分析Go二進(jìn)制程序。

本文討論的主題是在Hacktivity2020在線會議上公布的,相關(guān)的幻燈片和其他材料可以在我們的Github存儲庫中下載。

剝離型二進(jìn)制代碼中丟失的函數(shù)名

實(shí)際上,我們面對的第一個問題并不是Go二進(jìn)制文件所特有的,而是所有剝離型二進(jìn)制代碼(stripped binaries,譯者注:就是去掉調(diào)試信息后的二進(jìn)制代碼)所共同面對的一個問題。實(shí)際上,編譯后的可執(zhí)行文件是可以包含調(diào)試符號的,這能讓調(diào)試和分析工作變得更加容易。當(dāng)分析人員逆向分析帶有調(diào)試信息的二進(jìn)制代碼時,他們不僅可以看到內(nèi)存地址,還可以看到函數(shù)和變量的名稱。然而,惡意軟件作者通常在編譯代碼時剝離這些調(diào)試信息,從而創(chuàng)建所謂的剝離型二進(jìn)制代碼。他們這樣做的目的有兩個,一是為了減小文件的大小,二是增加逆向分析的難度。在使用剝離型二進(jìn)制文件時,分析人員無法依賴函數(shù)名來幫助他們在代碼中找到自己感興趣的函數(shù)。在處理使用靜態(tài)鏈接的Go二進(jìn)制文件(其中包含所有必需的庫)時,逆向分析的過程會顯著減慢。

為了說明這個問題,我們將分別通過C語言和Go語言編寫一個簡單的“Hello Hacktivity”示例代碼,并將它們編譯成剝離型的二進(jìn)制代碼。在這里,請大家注意兩個可執(zhí)行文件在大小方面的差異。

Ghidra的Functions窗口列出了二進(jìn)制文件中已經(jīng)定義的所有函數(shù)。在非剝離型的編譯版本中,函數(shù)名稱都會顯示出來,這對逆向工程師來說具有很大的幫助。

圖1 hello_c的函數(shù)列表

圖2 hello_go的函數(shù)列表

對于剝離型的二進(jìn)制文件來說,其函數(shù)列表如下所示:

圖3 hello_c_strip的函數(shù)列表

圖4 hello_go_strip的函數(shù)列表

這些例子清楚地表明,即使像“hello world”這樣簡單的G0程序的二進(jìn)制代碼,它們的體積也是非常龐大的:竟然含有一千多個函數(shù)。而在剝離型的二進(jìn)制版本中,逆向工程師則無法依靠函數(shù)名來進(jìn)行輔助分析。

注:由于剝離了調(diào)試信息,不僅函數(shù)名消失了,Ghidra也只能識別出1790個函數(shù)中的1139個。

我們感興趣的是,是否有辦法恢復(fù)剝離型二進(jìn)制文件中的函數(shù)名。首先,我們運(yùn)行了一個簡單的字符串搜索來檢查二進(jìn)制文件中是否還有函數(shù)名。在C語言的例子中,我們找到了函數(shù)“main”,而在Go語言的例子中找到的則是“main.main”。

圖5 在hello_c中,可以找到字符串“main”

圖6 在hello_c_strip中,無法找到字符串“main”

圖7 在hello_go中,可以找到字符串“main.main”

圖8 在hello_go_strip中,可以找到字符串“main.main”

我們可以看到,雖然strings工具無法在C語言的剝離型二進(jìn)制文件中找到函數(shù)名,但是,我們卻可以在Go語言的剝離型二進(jìn)制文件中找到字符串“main.main”。這個發(fā)現(xiàn)給我們帶來了一絲希望,即在剝離型的Go二進(jìn)制文件中可以恢復(fù)函數(shù)名。

實(shí)際上,將二進(jìn)制文件加載到Ghidra中,然后搜索“main.main”字符串,就可以看到它的確切位置。如下圖所示,函數(shù)名字符串位于.gopclntab段。

圖9 Ghidra顯示的hello_go_strip的main.main字符串

眾所周知,從Go 1.2開始,就開始提供pclntab結(jié)構(gòu)體了,并且提供了詳盡的說明文檔。該結(jié)構(gòu)體以一個魔力值開頭,后面是架構(gòu)信息,再往后,是函數(shù)符號表,用于保存二進(jìn)制代碼中的函數(shù)信息,每個函數(shù)的入口點(diǎn)地址后面是函數(shù)元數(shù)據(jù)表。

在函數(shù)元數(shù)據(jù)表中,除其他重要信息外,還存儲了函數(shù)名稱的偏移量。

也就是說,我們可以通過這些信息來恢復(fù)函數(shù)名。為此,我們的團(tuán)隊(duì)為Ghidra創(chuàng)建了一個腳本(go_func.py),通過執(zhí)行以下步驟來恢復(fù)剝離型Go ELF文件中的函數(shù)名:

  • 找到pclntab結(jié)構(gòu)體
  •  提取函數(shù)地址
  •  查找函數(shù)名偏移量

執(zhí)行我們的腳本后,不僅可以恢復(fù)函數(shù)名,而且還可以定義以前未被識別的函數(shù)。

圖10 執(zhí)行g(shù)o_func.py腳本后的hello_go_strip的函數(shù)列表

接下來,我們將以真實(shí)世界中的樣本(eCh0raix勒索軟件)為例,來展示該腳本的威力:

圖11 eCh0raix的函數(shù)列表

圖12 執(zhí)行g(shù)o_func.py腳本后eCh0raix的函數(shù)列表

這個例子展示了函數(shù)名恢復(fù)腳本在逆向工程中所帶來的巨大幫助:安全分析師只需瞄一眼函數(shù)名,就可以判斷出當(dāng)前處理的是一個勒索軟件。

注意:在Windows Go二進(jìn)制文件中,并沒有專門為pclntab結(jié)構(gòu)體提供相應(yīng)的段,因此,研究人員需要顯式地搜索該結(jié)構(gòu)體的相關(guān)字段(如魔力值、可能的字段值)。對于macOS系統(tǒng)來說,_gopclntab段是可用的,類似于Linux二進(jìn)制文件中的.gopclntab段。

挑戰(zhàn):未定義的函數(shù)名字符串

如果一個函數(shù)名字符串沒有被Ghidra定義,那么函數(shù)名恢復(fù)腳本將無法重命名該特定函數(shù),因?yàn)樗鼰o法在給定位置找到函數(shù)名字符串。為了解決這個問題,我們的腳本總是檢查函數(shù)名地址是否有定義的數(shù)據(jù)類型,如果沒有,則嘗試在重命名函數(shù)之前在給定的地址定義一個字符串?dāng)?shù)據(jù)類型。

在下面的例子中,eCh0raix勒索軟件樣本中并沒有定義函數(shù)名字符串“l(fā)og.New”,所以在沒有事先創(chuàng)建字符串的情況下,是無法重命名相應(yīng)的函數(shù)的。

圖13 eCh0raix中l(wèi)og.New的函數(shù)名未定義

圖14 eCh0raix中l(wèi)og.New函數(shù)無法重命名

在我們的腳本中,以下幾行代碼專門用于解決這個問題:

圖15 go_func.py

Go二進(jìn)制文件中無法識別的字符串

我們的腳本要解決的第二個問題與Go二進(jìn)制文件內(nèi)的字符串有關(guān)。讓我們回到“Hello Hacktivity”的例子,看看Ghidra內(nèi)定義的字符串。

在C語言編譯而成的二進(jìn)制代碼中定義了70個字符串,“Hello, Hacktivity!”就在其中。同時,Go語言版本的二進(jìn)制代碼中則包含了6,540個字符串,但搜索 “hacktivity”字符串卻沒有任何結(jié)果。如此多的字符串已經(jīng)讓逆向工程師很難找靠肉眼到相關(guān)的字符串,但是,我們期望找到的字符串甚至沒有被Ghidra識別出來。

圖16 hello_c中定義的字符串中含有“Hello, Hacktivity!”

圖17 hello_go中定義的字符串中未含有“hacktivity”

要理解這是怎么回事,您需要知道Go語言處理字符串的方式。在類似C這樣的編程語言中,字符串是以空字符結(jié)尾的字符序列;而在Go語言中,字符串則被視為具有固定長度的字節(jié)序列。也就是說,對于Go語言來說,字符串是一種特殊的數(shù)據(jù)結(jié)構(gòu),由指向字符串位置的指針和整數(shù)(即字符串的長度)構(gòu)成。

在Go二進(jìn)制文件中,這些字符串將以大字符串blob的形式存儲,而blob則是由多個字符串串聯(lián)而組成的,并且字符串之間沒有空字符。因此,在搜索“Hacktivity”時,對于C語言版本的二進(jìn)制代碼來說,能夠得到預(yù)期的結(jié)果;對于Go語言版本的二進(jìn)制代碼來說,則會返回一個包含“hacktivity”的巨型字符串blob。

圖18 在hello_c中搜索“Hacktivity”字符串

圖19 在hello_go中串搜索字符“hacktivity”

由于Go語言對字符串的定義不同于其他語言,并且在匯編代碼中引用它們的結(jié)果也與通常的類似C語言的解決方案不同,因此Ghidra在處理Go二進(jìn)制文件中的字符串方面,會面臨較大的困難。

字符串結(jié)構(gòu)的分配方式有很多種,它既可以是靜態(tài)創(chuàng)建的,也可以是運(yùn)行時動態(tài)創(chuàng)建的;同時,在不同的架構(gòu)中,具體的分配方式也是不同的,甚至在同一架構(gòu)中可能存在多種解決方案。為了解決這個問題,我們團(tuán)隊(duì)創(chuàng)建了兩個腳本來幫助識別字符串。

小結(jié)

在本文中,我討論了逆向工程師在分析Go二進(jìn)制代碼的過程中所面臨的兩個難題及其解決方案,由于篇幅較長,我們將分為兩篇進(jìn)行介紹。更多精彩內(nèi)容,我們將在下篇中進(jìn)行介紹。

本文翻譯自:https://cujo.com/reverse-engineering-go-binaries-with-ghidra/如若轉(zhuǎn)載,請注明原文地址:


本文標(biāo)題:利用Ghidra逆向分析Go二進(jìn)制程序(上篇)
鏈接分享:http://m.5511xx.com/article/dpgchpi.html