此係列是本人一個字一個字碼出來的,包括範例和實驗截圖。本人非計算機專業,可能對本教學涉及的事物沒有了解的足夠深入,如有錯誤,歡迎批評指正。 如有好的建議,歡迎反饋。碼字不易,如果本篇文章有幫助你的,如有閒錢,可以打賞支援我的創作。如想轉載,請把我的轉載資訊附在文章後面,並宣告我的個人資訊和本人部落格地址即可,但必須事先通知我。
你如果是從中間插過來看的,請仔細閱讀 跟羽夏學 Ghidra ——簡述 ,方便學習本教學。請認準 部落格園 的 寂靜的羽夏 ,目前僅在該平臺釋出。
雖然標題起的是「參照」,但不會僅僅講這個。我們將會涉及函數、交叉參照相關的知識。話不多說,下面開始。
先講最簡單的:交叉參照。我們經常在Ghidra
看到有這樣的註釋:
************************************************
* FUNCTION *
************************************************
undefined variable()
undefined AL:1 <RETURN>
tstruct Stack[-0x18]:16 lstruct XREF[1,3]:00401185(W),
00401189(W),
0040118f(W),
00401196(W)
variable XREF[4]: Entry Point(*),
main:0040137c(c),
00402238, 00402318(*)
00401162 55 PUSH RBP
其中XREF
就是所謂的交叉參照。如果你在某個函數中呼叫了其他函數,或者參照了其他資料,這都屬於交叉參照的範圍。好,寂靜的羽夏講完了這,下面輪到函數。
函數,是一個十分簡單又十分複雜又十分重要的東西。從組合層面,函數就是一個重複使用的一個組合程式碼片段,可以傳參,完成功能,也可以返回一個值作為結果。
在逆向過程中,我們有時候遇到過這樣的問題,比如一串程式碼被識別為資料(ShellCode 會經常遇到),我們轉化為程式碼之後,我們還需要將其轉為函數,方便分析:
點選之後,我們就可以建立一個函數。
在分析一個函數的功能之後,我們會習慣加個註釋,以後的時候方便繼續或者回顧,Ghidra
有新增註釋的功能,熱鍵是;
,一個英文狀態的分號。註釋有五種,下面介紹一下:
EOL Comments
:這個也許是最常用的註釋型別是行結束EOL
註釋,它位於列表視窗中現有行的末尾。若要新增註釋,請使用分號喚出對話方塊,並選擇EOL Comments
索引標籤。預設情況下,EOL
註釋顯示為藍色文字,如果在「註釋」文字方塊中輸入多行,則將跨越多行。每一行都將縮排,以便在反組合的右側對齊,現有內容將向下移動,以便為新註釋留出空間。您可以通過重新開啟對話方塊隨時編輯註釋。刪除註釋的最快方法是單擊列表視窗中的註釋,然後按Delete
鍵。Ghidra
本身在自動分析期間新增了許多EOL
註釋。只有在擁有與特定資料型別相關聯的資訊時才能這樣做。這些資訊通常包含在型別庫中,這些型別庫顯示在資料型別管理器視窗中。
Pre/Post Comments
:預註釋Pre Comments
和後註釋Post Comments
是在給定反組合行之前或之後出現的完整行註釋。將滑鼠懸停在截斷的註釋上,將顯示完整的註釋。預設情況下,預註釋顯示為紫色,後註釋顯示為藍色,以便輕鬆地將它們與列表中的正確地址關聯。
Plate Comments
:它允許您對註釋進行分組,以便在列表視窗中的任何位置顯示。該註釋居中並放置在以星號為界的矩形內。我們檢查過的許多清單都包括一個簡單的板註釋Plate Comments
,在邊界框中包含單詞函數。當在所選函數中的第一個地址開啟註釋對話方塊時,你可以選擇用您自己的、資訊更豐富的註釋替換此通用板註釋。除了替換預設板註釋之外,Ghidra
還將註釋新增為反編譯器視窗頂部。如果建立Plate Comments
時遊標位於反編譯器視窗的頂部,結果將是相同的。
Repeatable Comments
:可重複註釋輸入一次,但在整個反組合過程中可能會自動出現在許多位置。可重複註釋的行為與交叉參照的概念有關。基本上,在交叉參照的目標輸入的可重複評論在交叉參照源處得到迴應。因此,單個可重複註釋可能會在反組合中的多個位置得到響應(因為交叉參照可以是多對一)。在反組合列表中,可重複註釋的預設顏色為橙色,迴應註釋為灰色,使其易於與其他型別的註釋區分開來。
當EOL
註釋和可重複註釋在同一地址時,只有EOL
註釋在列表中可見。如果刪除EOL
註釋,可重複註釋將在列表中顯示。
其實,在Ghidra
還有一種註釋:附註Annotations
。它可以在其設定註釋對話方塊中通過指向程式、URL
、地址和符號的連結註釋做註釋。符號名稱更改時,註釋中的符號資訊將自動更新。當使用註釋來啟動指定的可執行檔案時,你可以提供可選引數以獲得更多控制。
其實,本練習還有函數相關的,體現如何傳遞引數的,這就當課外練習了,這個不是我們本教學的重點,這個是前置知識。
有關本篇博文寂靜的羽夏就介紹這些,下面開始動手,破解crakeMe
,也就是第四個練習。這次先從原始碼的角度,來分析這個破解這個練習。下一篇部落格園博文,我們將從逆向者的角度,來分析這個程式。
通過比對原始碼,我們看到如下虛擬碼:
if (local_14 != 4) break;
iVar1 = crackMe();
if (iVar1 == 0) {
puts("抱歉,沒成功哦,再試一次!");
}
else {
puts(">> 祝賀破解成功!");
}
也就是說,第四個練習是呼叫crackMe
,判斷是否非零決定是否成功。我們跟進去:
bool crackMe(void)
{
int iVar1;
iVar1 = getKey();
return iVar1 == 0x123456;
}
這個函數很簡單,呼叫getKey
函數,看看是否返回值是0x123456
,如果是返回真,反之為假,這個是判斷是否破解成功的依據。接下來我們看看getKey
幹了啥:
int getKey(void)
{
int local_c;
puts("請輸入金鑰:");
__isoc99_scanf("%d",&local_c);
return local_c;
}
可以看到,該函數只是讀取一下輸入內容,作為整數返回到呼叫者。
至此,簡單的博文就到此結束。
跟羽夏學 Ghidra ——導航