banner
lca

lca

真正的不自由,是在自己的心中设下牢笼。

《從零開始學IDA逆向》學習筆記-10(IDA調試器)

image

選擇 IDA 調試器#

ida 支援多個調試器。

image

ida 支援的調試器

選擇 Local Windows debugger 調試器

打開菜單欄調試器 - 調試器選項,可以設置一些調試器的功能。

image

ida 調試器選項

調試器介面功能#

勾選 進程入口點暫停,並選擇事件條件,點擊確定。

image

對之前的關鍵代碼 jinx 重命名及改色

image

修改後如下,按 X 鍵查看哪裡引用了這個函數:

image

對引用點進行著色。

image

在 0x00401243 處設置斷點,鼠標放到這一行,右鍵 - 添加斷點,添加斷點後變成紅色背景。

image

通過菜單欄 調試器-啟動進程(F9),開啟調試。如果在本地調試可執行程序會彈出如下警告窗口。

image

注:

在加載器分析程序的時候,程序不會在本地執行,但是調試則不是。如果程序是一個病毒或者其他危險的惡意軟件時,需要特別的當心。這時候需要使用遠程調試器 (REMOTE DEBUGGER) 在虛擬機中執行程序。

點擊 繼續調試。

由於設置了讓調試器在入口處暫停,如下圖,ida 暫停在入口處(0x00401000)。

image

調整右上角的通用寄存器和標誌寄存器窗口,以便查看。

image

上圖中,可以看到這些寄存器的值。調整正常之後,打開菜單欄 窗口-保存桌面 並勾選 default 選項,保存為調試器默認的窗口設置。那麼之後,運行調試器的時候,程序按照默認設置運行,如需修改也可以。

在通用寄存器下方可放置堆棧視圖。

image

左側和最下方是反匯編及 16 進制窗口。

image

在反匯編視圖下方是當前的內存地址以及文件偏移(FILE OFFSET),這個偏移是指可執行文件偏移。

image

在 ida 中,默認 G 鍵是轉向一個內存地址的快捷鍵,按 G 輸入 0x401389,轉向之前設置的斷點。

image

所有靜態分析、重命名等改變的內容都會保存。

image

打開菜單欄視圖 - 打開子視圖 - 段,發現加載器加載了 3 個區段。

image

加載了 0x401000 上的 code 字段,以及下方的 data 和 .idata 字段,對這些區段的修改都會保存,除此之外的修改都不會保存,因為它們是調試器加載的區段,不會保存到 IDA 數據庫中。

上圖中的 L 標誌,表示這個程序被加載器和調試器同時加載,既能實施靜態分析,同時在動態調試時也不會丟失靜態分析的信息。

下面介紹了一些小工具欄。

1、菜單欄 view(視圖)-toolbars(工具類)-jump(跳轉),再通過保存桌面功能將它設置為默認啟用。

image

按返回鍵可以返回之前的程序入口處。

image

在菜單欄 debugger(調試器)-breakpoints(斷點)-breakpoint list(斷點列表)中,能夠查看所有的程序斷點。

image

點擊任意一處就可以跳轉到對應的斷點處。

條件跳轉指令與標誌寄存器#

目前調試器執行到了程序入口,並且設置了兩個斷點,按 F9 繼續運行。

image

此時運行了 crackme.exe 程序,打開目標程序 Help-register 菜單欄輸入用戶名和密碼。

image

點擊 ok

image

上圖中,左邊閃爍的紅色箭頭表示程序繼續執行的路徑,此時 eax 的值是 0x6c。

image

0x6c 轉換為字符串就是 l。

image

image

上圖中,al 寄存器與 0x41 進行比較,判斷是否小於 0x41(A),下方的綠色代碼塊中 al 寄存器也和 0x5a 進行了比較。

asmconditionoperation
JAz=0 and c=0jump if above(如果大於則跳轉)
JAEc=0jump if above or equal(如果大於或等於則跳轉)
JBc=1jump if below (如果低於則跳轉)
JBEz=1 or c=1jump if below or equal(如果小於等於則跳轉)
JCc=1jump if carry(如果進位則跳轉)
JECXZecx=0jump if ecx is 0 (如果 ecx 為 0,則跳轉)
JEz=1jump if equal(如果相等就跳轉)
JZz=1jump if zero (如果為零則跳轉)
JNEz=0jump if not equal (如果不相等就跳轉)
JNZz=0jump if not zero (如果非零則跳轉)
JO超出範圍jump if overflow
JP有偶數個 1 位(操作結果中二進制中 1 的個數,01110000)jump if parity
JPE偶數校驗jump if parity even
JNP沒有偶數個 1 位jump if not parity
JPO奇數校驗jump if parity odd
JS符號位為 1jump if sign(如果有標誌則跳轉)
JNS符號位為 0jump if not sign(如果沒有標誌則跳轉)
JL/JNGE符號位與溢出位相同jump if less or not greater/equal
JLE/JNGz=1 or 符號位與溢出位相同jump if less or equal/not greater
JG/JNLEz=0 and 符號位與溢出位相同jump is greater/not less or equal

條件跳轉指令及跳轉條件

下面轉到 ida 標誌寄存器視圖,如下圖所示。

image

根據表格可知,如果 CF=0,就不跳轉,程序往綠色代碼塊執行,那麼觸發這個 C 標誌的數學條件是什麼呢?

C 標誌代表無符號整數運算有錯誤這一信息,如果把 cmp 指令看作是不保存結果的減法算法,那麼 0x6c - 0x41 = 0x2b,結果是正數,如果 al 是 0x30,那麼 0x30 - 0x41 = -0x11

image

-0x11 是一個負數,程序只能繼續使用它對應的 16 進制運行。

image

如上圖所示,-0x11 的 16 進制是 0xffffffef,10 進制是 4294967279,這個值很大,而且 0x30-0x41 也不會是正數。

那麼如何知道操作中有沒有考慮正負號呢。這取決於使用的跳轉類型, JB 是用於無符號數比較後的跳轉指令,對應的有符號數的指令是 JL。

當使用 JB 指令時,通常是用它來檢測無符號整數是否小於某個值。如果運算結果產生了借位,就表示第二個操作數(被比較數)比第一個操作數(比較數)大,此時 JB 標誌位為 1,就可以進行跳轉。否則,如果運算結果沒有產生借位,則 JB 標誌位為 0,即不滿足條件,就不進行跳轉。

示例:

mov al, 150    ; 150 賦值給 al 
cmp al, 255    ;比較 al 255
jb  smaller    ;如果 al 小於 255,就跳轉到 smaller 標籤處
   ;執行其他操作
   smaller:
   ;如果 al 小於等於 255,就會跳轉到這裡

在這個示例中,如果 al 中的值小於 255,則 CF 標誌位為 1,就會跳轉到 smaller 標籤處。否則,如果 al 中的值大於 255,則 CF 標誌位為 0,不跳轉,執行其他操作。(總而言之,如果 al 比 255 小,則跳轉)

對於比較是否帶符號需要通過它後面的條件跳轉指令來確定。

無符號跳轉

符號描述標誌位
JE/JZJumps if equal or zerozf
JNE/JNZJumps if not equal or zerozf
JA/JNBEJumps if above or not below or equalzf,cf
JB/JNAEJumps if below or not above or equalcf
JBE/JNAJumps if below or equal or not abovecf,af

無符號跳轉

上圖中的指令都不考慮正負號,每一種跳轉都有對應的有符號跳轉。

符號描述標誌位
JE/JZJumps if equal or zerozf
JNE/JNZJumps if not equal or zerozf
JG/JNLEJumps if greater or not less or equalzf,sf,of
JGE/JNLJumps if greater or not equal or lesssf,of
JL/JNGEJumps if less or not greater or equalsf,of
JLE/JNGJumps if less or equal or not greaterzf,sf,of

有符號跳轉

上面兩個圖中,JE(是否相等) 出現在兩個圖中,因為在這個特例中,符號並不重要,如果兩個數相等,zf=1,意味著標誌觸發。
有符號跳轉中 JG = Jumps if greater,在無符號跳轉中它對應的指令是 JA,Jumps if above

繼續調試程序發現,ida 會在每一個設置的斷點上暫停,執行了一個循環,每個循環會讀取在目標程序輸入的用戶名的一個字符並和 0x41 進行比較,如果任何一個字符小於 0x41,就會報錯,由於輸入的是 lca,每個值都比 0x41 大,所以不顯示報錯。

嘗試輸入數字看看。

image

此時,就跳轉到紅色區塊,也就是 jb 跳轉的地方,因為第一個比較的字符是 2(0x32),2 肯定比 0x41 小。

image

image

同時觸發了 C 標誌位,CF=1,因為 0x32 - 0x41 無符號數相減,結果是負數,這將觸發 C 標誌位。

image

在 C 標誌位右鍵單擊,選擇 Zero Value 將 C 標誌清 0。

image

image

按 F9 繼續進程,程序讀取 22lca 的第二個字符,左側紅色箭頭又開始閃爍。繼續將 CF 標誌位設為 0,之後的字符 lca 都會大於 0x41,不會觸發標誌位,程序都走左側紅色箭頭。

字符檢測完成後,程序來到最後一個跳轉。

image

上圖的 cmp 指令比較 eax 和 ebx,jz 判斷比較是否相等,無符號,程序走向紅色區塊,因為這兩個寄存器不相等。

image

由於不相等,所以 zf 標誌未被觸發。

image

如果手動觸發 zf 標誌,改變跳轉方向,程序會轉向綠色區塊,顯示註冊成功。

image

image

SET IP#

set ip 只有在調試器模式下才有。

有時候也可以不直接修改跳轉,可以將鼠標移動至想要執行的那個代碼塊上,右鍵單擊,選擇 SET EIP。

在 0x40124c 處,set eip,程序會從 0x40124c 處開始運行。

image

注:在 7.7 中這樣操作,執行多次後報錯如下:

image

提示 “嘗試執行非法指令”

image

image

報錯信息提示內存不可寫,也許讀取內容超出了範圍。

總結#

通過使用 IDA 調試器,可以進行動態調試和靜態分析,深入了解程序的結構和運行過程,但這章未對源程序進行修改,只是在調試器中改變了標誌寄存器的值。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。