今天要做的實驗是CTF REVERSE練習之API定位。
Windows這個多作業系統除了協調應用程序的執行、分配內存、管理資源之外, 它同時也是一個很大的服務中心,調用這個服務中心的各種服務(每一種服務就是一個函數),可以幫應用程式達到開啓視窗、描繪圖形、使用周邊設備等目的,由於這些函數服務的對象是應用程序(Application),所以便稱之爲 Application Programming Interface,簡稱 API 函數。
另外需要注意的是兩種編碼,ANSI與Unicode,ANSI的ASCII字符集及其派生字符集(也稱多字節字符集)比較舊,而Unicode字符集比較新,固定以雙字節表示一個字。Windows操作系統在聲明一個API時,如果這個API存在字符串參數,便會指定字符集。每個含有字符串參數的API同時有兩個版本:即ANSI,Unicode。尾部帶A的API是ANSI版本,帶W的API是Unicode版本。
例如:我們在編程時使用的MessageBox實際上是一個宏,根據字符集的不同被定義爲不同版本的MessageBox,如果是UNICODE字符集,則實際上爲MessasgeBoxW,如果是ANSI字符集,則實際上爲MessageBoxA:
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
交叉引用。
通過交叉引用(XREF)可以知道指令代碼相互調用的關係,如下圖所示:
這句“CODE XREF: WinMain(x,x,x,x)+10↑p”,表示調用sub_41BD0D這個函數的地方爲WinMain函數,p表示是以函數調用(procedure)的方式跳轉到當前的位置的,其他的一些符號:o表示偏移值(offset),j表示跳轉(jump)。
在sub_41BD0D上面按X鍵,可以打開交叉引用窗口,這裏會列出所有調用了sub_41BD0D這個函數的地方,如圖所示:
從圖中可以看到,只有在WinMain函數中調用了sub_41BD0D這個函數。
現在我們開始進行實驗,進入實驗鏈接《CTF REVERSE練習之API定位》。
先看題目描述,主機C:\Reverse\2目錄下有一個CrackMe2.exe程序,運行這個程序的時候會提示輸入一個密碼,當輸入正確的密碼時,會彈出過關提示消息框,請對CrackMe2.exe程序進行逆向分析和調試,找到正確的過關密碼。
不管在什麼場景下,相信大家在剛接觸一個新事物的時候,都會仔細觀察事物的外部特徵,CTF做題也是一樣的,在拿到題目之後可以運行程序,觀察程序都有哪些地方可以輸入數據,哪些按鈕點擊了會有什麼樣的反應,在操作過程中出現了哪些提示等。
通過對CrackMe2.exe程序的觀察,我們知道程序需要輸入一個密碼,當不輸入任何數據就點擊按鈕時,提示如下信息:
當輸入一串測試數據時,提示如下信息:
通過這些操作後,我們可以猜測程序的意圖是輸入一個正確的密碼。
在對一個程序進行逆向分析之前,除了程序的動態行爲之外,查看程序是否加殼(被何種程序加殼?是什麼編譯器編譯的?)也是一個非常關鍵的步驟。我們選中程序後單擊右鍵,在右鍵菜單中選擇“Scan with PEiD”選項,就可以查看加殼信息了。我們這裏看到的是Microsoft Visual C++ 6.0,說明CrackMe2.exe沒有加殼,且它是使用VC6編譯的。
我們來試一試使用OD載入CrackMe2.exe程序,如果繼續使用實驗《CTF REVERSE練習之逆向初探》中提到的方法查找字符串,是找不到的,會有如下提示:
繼續看我們在反彙編指令列表中單擊右鍵,在右鍵菜單中依次選擇“查找”——“當前模塊中的名稱(標籤)”,如圖所示:
點擊彈出的名稱窗口,在鍵盤上敲下MESSAGEBOXA,就會自動定位到MessageBoxA,點擊鼠標選中MessageBoxA這一行,單擊右鍵,在彈出的右鍵菜單中選擇“在每個參考上設置斷點”,如圖所示:
在OD最下方的狀態欄上可以看到“已設置 2 個斷點”的提示。
現在按F9運行程序,隨便給程序輸入一個密碼(如test),單擊確定按鈕後程序將在OD中斷下,斷下的位置爲對MessageBoxA的調用的位置,如圖所示:
這就是我們要找的關鍵函數,現在我們查看附近的代碼,就找到了密碼明文,如圖所示:
用OD解題之後,我們繼續用IDA來解題一下。
使用IDA載入CrackMe2.exe程序進行分析,等待分析完畢後,選擇主窗口面板上的Imports TAB頁面,然後在鍵盤上敲下MESSAGEBOXA,就可以自動定位到MessageBoxA函數,如圖所示:
前面提到了交叉引用這裏我們可以用到雙擊00422420這個條目,來到MessageBoxA定義的位置,選中後按下X鍵,彈出交叉引用列表窗口,我們看到一共有四個條目,如圖所示:
我們並不能直接看出哪一個引用就是我們所要找的引用,所以需要一個一個進行查看,根據前面使用OD對程序的分析,我們知道在MessageBoxA之前有許多對LoadString的調用,因此通過對比幾個交叉引用,可以斷定sub_401450就是我們要找的函數。
使用F5還原sub_401450函數的僞代碼,我們斷定LoadString加載資源ID爲0x6A的字符串就是我們要找的密碼,僞代碼如下:
接下來我們使用Restorator打開CrackMe2.exe程序來查看字符串資源,如圖所示,0x6A的十進制即106,因此可以知道密碼就是HeeTianLab了。
那今天的實驗就介紹到這裏。我們需要好好掌握API還有後面的實驗內容。