跟羽夏學 Ghidra ——導航

2022-09-16 12:02:04

寫在前面

  此係列是本人一個字一個字碼出來的,包括範例和實驗截圖。本人非計算機專業,可能對本教學涉及的事物沒有了解的足夠深入,如有錯誤,歡迎批評指正。 如有好的建議,歡迎反饋。碼字不易,如果本篇文章有幫助你的,如有閒錢,可以打賞支援我的創作。如想轉載,請把我的轉載資訊附在文章後面,並宣告我的個人資訊和本人部落格地址即可,但必須事先通知我

你如果是從中間插過來看的,請仔細閱讀 跟羽夏學 Ghidra ——簡述 ,方便學習本教學。請認準 部落格園寂靜的羽夏 ,目前僅在該平臺釋出。

前言

  導航瀏覽是逆向者的基本能力,在原始碼完全未知的情況下,該能力是十分重要的。在介紹完如何導航分析二進位制之後,我們會以逆向的角度,來審視crakeMe這個函數。

來回橫跳

  在我們在不同的函數之間進行切換的時候,有時候錯過想回去看看的時候,再重新點回去一是麻煩,二是不準,那麼咋辦呢?

  圖中,高亮的兩個按鈕就是負責這個事情的。向左的箭頭是回到上一次的位置Alt + 左方向鍵,向右的反之Alt + 右方向鍵。這兩個功能會在之後經常用到。

搜尋

  搜尋和蒐集資訊的能力是在逆向中最常用也是最重要的能力之一。
  在程式中,我們可以搜尋字串,定位函數位置:

  裡面有很多選項,英文不會的話翻譯一下,然後記住,因為專業常用的單詞就幾個,會了就會了。
  其次,我們還可以搜記憶體的資料,來進行定位:

  當然,這些功能應該不會特別常用,不過在特殊的場合還是有用的,比如通過特徵碼搜尋指定函數、字串等等。這所有的功能全部在Search選單當中。

蒐集資訊

  在逆向過程中,蒐集資訊也是十分重要的,比如字串。
  在Search選單中選中For Strings...,將會彈出表單:

  這個是設定搜尋屬性的,如果有特殊的自行設定,如果沒有,直接預設搜尋,在本範例會得到如下內容:

  Ghidra也能搜尋常數,在Search選單中選中For Scalars...

  選好常數範圍後,然後點選搜尋,會得到如下結果:

  不過,搜尋常數似乎用處不大。
  對於某個位置的參照,我想獲得分析得到的所有直接參照,並選擇跳轉到哪一個,在Search選單中選中For Direct Reference...

  不過查參照的時候一般不會用這個,我們更偏愛使用這種方式查詢:

  我們既可以獲取該地址的參照,如果是函數地址,也能獲取到函數的參照。
  Ghidra與此同時也支援指令模式搜尋,在Search選單中選中For Instruction Patterns...

  不過,要使用這個,首先需要要點選編輯按鈕(筆的圖示),輸入寫死之後確認,然後點選搜尋即可:

其他

  不知道你有沒有注意到工具列上幾個小小的字母圖示:

  這幾個圖示有自己的作用,不過通過工具英文提示也明白啥作用,這裡就總結一下(從左到右依次):

  • 設定方向:通過該按鈕可以更改跳轉的方向,這個僅對圖上的按鈕有效,方向指示和圖示一致。
  • 下一條指令:跳轉到下一條指令。通過實驗得知,它會跳轉到匹配到非上一條為指令的指令。The Ghidra Book並沒有解釋清楚。
  • 下一條資料:跳轉到下一條資料。
  • 下一個未定義:跳轉到下一個未定義型別的資料。
  • 下一個標籤:跳轉到下一個標籤。
  • 下一個函數:跳轉到下一個函數。
  • 下一個非函數指令:跳轉到下一個不屬於函數內部的指令。
  • 下一個不同位元組值:跳轉到下一個不同的位元組的值。
  • 下一個書籤:跳轉到下一個書籤。

實驗

  學習了這些,我們開始從逆向者的角度,來開始分析。
  在開始破解實驗的時候,我們看到顯示了一個字串請輸入金鑰:,這個是我們的一個關鍵突破口,如果能找到,會有一定的概率破解(不排除有假的)。
  然後,我們開始選單Search-For Strings...,開始搜尋,最終我們定位到位置:

  跳轉到這個位置:

                      s__004021ff                           XREF[2]:  getKey:004014b4(*), 
                                                                      getKey:004014b4(*)  
     004021ff e8 af       ds       u8"請輸入金鑰:"
             b7 e8 
             be 93 
                      //
                      // .eh_frame_hdr 
                      // SHT_PROGBITS  [0x402214 - 0x40228f]
                      // ram:00402214-ram:0040228f
                      //
                        ************************************************
                        * Exception Handler Frame Header               *
                        ************************************************
                      __GNU_EH_FRAME_HDR                    XREF[2]:  00400210(*), 
                                                                      _elfSectionHeaders::00000
     00402214 01 1b       eh_fra                                         Exception Handler Frame H
             03 3b

  我們看到這裡有交叉參照,是從getKey函數來的,跟過去:

int getKey(void)
{
  int local_c;
  
  puts("請輸入金鑰:");
  __isoc99_scanf("%d",&local_c);
  return local_c;
}

  根據反編譯結果,理解了該函數的功能,我們需要分析一下該函數的參照:

  通過簡單的分析,我們推測CALL getKey這個地址最有嫌疑,我們跟過去:

bool crackMe(void)
{
  int iVar1;
  
  iVar1 = getKey();
  return iVar1 == 0x123456;
}

  可以看出,拿到返回值之後,會判斷是否和0x123456相等,並將比較結果返回。
  我們如法炮製,最終跟到了這個位置(區域性):

iVar1 = crackMe();
if (iVar1 == 0) {
  puts("抱歉,沒成功哦,再試一次!");
}
else {
  puts(">> 祝賀破解成功!");
}

  此時,我們明白了結果。只要輸入的值與0x123456相等就通過,由於是十進位制輸入,就是1193046。輸進去就是下面的結果:

  至此,該實驗結束。

小結

  本篇博文我們介紹瞭如何導航並蒐集自己所需要的資訊。不過逆向並沒有這麼簡單,該範例並不難,且有原始碼,有前面教學分析的基礎上,看起來相當簡單,不信?你直接搜字串都不一定搜得到。

下一篇

  跟羽夏學 Ghidra ——偵錯