自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

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

[[347062]]

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

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

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

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

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

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

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

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

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

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

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

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

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

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

圖15 go_func.py

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

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

 

利用Ghidra逆向分析Go二進(jìn)制程序(上篇)

 

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

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

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

小結(jié)

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

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

責(zé)任編輯:姜華 來(lái)源: 嘶吼網(wǎng)
相關(guān)推薦

2020-10-21 09:49:31

Ghidra逆向分析

2020-05-22 18:00:26

Go二進(jìn)制文件編程語(yǔ)言

2021-01-14 09:40:54

漏洞macOS屬性表文件

2024-10-30 09:50:51

WebGo語(yǔ)言

2018-10-22 14:37:16

二進(jìn)制數(shù)據(jù)存儲(chǔ)

2009-02-27 09:37:33

Google二進(jìn)制代碼

2022-10-31 08:02:42

二進(jìn)制計(jì)算乘法

2009-12-16 10:49:42

Ruby操作二進(jìn)制文件

2017-04-11 10:48:53

JS二進(jìn)制

2022-07-26 13:00:01

安全符號(hào)源代碼

2020-05-06 09:51:37

二進(jìn)制Linux命令行工具

2009-08-12 18:06:53

C#讀取二進(jìn)制文件

2010-10-13 15:45:23

MySQL二進(jìn)制日志

2010-06-09 13:02:29

MySQL啟用二進(jìn)制日

2021-02-01 15:11:08

Radare2開源開源工具

2011-05-25 14:10:38

浮點(diǎn)數(shù)

2021-11-10 09:15:00

CPU01 二進(jìn)制Linux

2013-04-28 15:37:35

JBoss

2013-07-29 11:19:16

iOS開發(fā)iOS開發(fā)學(xué)習(xí)FMDB更新二進(jìn)制圖片

2024-02-01 09:04:12

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)