banner
lca

lca

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

《從零開始學IDA逆向》學習筆記-4(棧學習)

image

XCHG#

xchg  A,B #指令用於將A和B的值互換

將鼠標放置到0x4013d8,這裡有個xor eax,eax指令,此處演示修改0x4013d8地址出的指令,點擊菜單欄Edit-Patch program-Assemble

image

彈出如下窗口。
image
輸入需要修改的指令,即可修改

xchg eax,esi

image

寫入了新的指令後,原先的函數被打斷了。

image

0xc0改寫為NOPNOP(NO OPERATION)指令什麼也不做,沒有任何操作,修改後內容如下:

image

image

上述例子中,只涉及了一個字節,原先的數據類型是 db,值為0xc0h

但修改後,此時函數處於打斷狀態,可以在函數起始地址 0x4013d8 右鍵Create function(創建函數)

image

函數創建完成後,內容如下:

image

IDA 將前置的loc_(表示普通指令)改為sub_(表示函數起點)。現在它已經重新識別為一個函數,按空格鍵切換到圖形視圖。

image

再重新關注這裡的 XCHG 指令。假設EAX = 12345678,ESI = 55,那麼指令執行之後 EAX = 55 而 ESI = 12345678。

PATCH菜單上有一個PATCHED BYTES功能,能夠顯示所有修改的字節,同時也可以將修改取消。

image

image

xchg 指令也可以對一個寄存器的值和另一個寄存器指向的內存存儲的值進行交換。

如指令:xchg eax,[esi]

如果 eax=55,esi=0x10000,程序會查找 0x10000 存儲的值,如果地址有寫入權限的話,就存入 55,原先 0x10000 的值寫入 eax。

4.3 堆疊操作指令#

Stack(堆疊)是由於函數運行而臨時佔用的內存區域,內存存取模式是先進後出(FILO,FIRST IN LAST OUT),通過這種方式來存儲和讀取數據。

Stack(堆疊)的特點就是,最晚入堆疊的幀最早出堆疊(因為最內層的函數調用,最先結束運行),這就叫做後進先出的數據結構。

對於堆疊的數據操作有 2 個基本的操作命令

  • PUSH 將一個對象保存在堆疊的頂部 (壓堆疊)

  • POP 將最後存入堆疊頂部的對象取出。

  • 在任何時刻,只能對堆疊的頂部或者最後一個壓堆疊的對象進行操作。

image

POP 操作將最後存入堆疊頂部的對象取出,然後這個對象下方 (倒數第二次壓堆疊操作存入) 的對象變成最後一次壓堆疊操作存入的對象,能夠進行後續操作。

image

Stack 是由內存區域的結束地址開始,從高位(地址)向低位(地址)分配。比如,內存區域的結束地址是 0x00001000 ,第一幀假定是 4 字節,那麼下一次分配的地址就會從 0x00000FFC 開始;如上面的圖所示 。

image

push#

通常在 32 位程序中,PUSH 用於在調用函數之前向堆疊傳遞參數,例如在上圖0x40104f處的指令。PUSH 64指令將 64 (dword) 壓入堆疊頂部,PUSH EAX將 EAX 的值壓堆疊,存儲在之前 64 (dword) 的上方,現在 EAX 的值在堆疊的最頂部。

PUSH 可以操作不同的對象,除常數外,還可以對地址進行操作。

image

可以發現字符串名稱前面的 OFFSET 關鍵詞,這條指令會將這個字符串或者字符數組的地址壓堆疊。

雙擊字符串名稱,跳轉到下圖中。

image

一般 C 語言源代碼中,字符數組是這樣定義的: Char mystring[] = "Hello"

D鍵會改變windowname變量的數據類型,強制 IDA 不將它視作字符數組而作為 db 或者說字節。

image

修改之後,引用這個地址的一些指令會隨之改變,在下圖中,offset 關鍵字確保傳入的還是 0x004020e7 這個地址,但地址上存儲的不再是字符數組,而是字節。

image

整個指令變成了push offset byte_4020E7,查找 `byte_4020E7`` 的內容,變成了 db 類型。

image

A鍵將其轉換為 ASCII 字符串,恢復到初始顯示。

image

當發現其他作為單獨字符顯示的字符串時,都可以進行該操作。找到字符串的起點按 “A” 鍵,使顯示更加易讀。

如下內容:

image

按 A 鍵之後,變成如下內容:

image

0x402110處按D鍵, 將 amenu 字符串分成單個字節。再按A鍵重新組合成字符串。

image

普通字符串示例

image

X鍵查找引用字符串的位置。

image

一般在向函數傳遞參數的時候,一般都會使用PUSH offset xxxxx指令,將字符串的地址傳遞給函數。如果沒有 offset 關鍵詞,傳遞進去的就是0x402110地址上存儲的內容,就是字符串的具體字節55 4E 45 4D。但是 API 函數不是這樣運行的,他們一般接受指針或者字符串的起始地址作為參數。

在以上的指令中,DS: 這個標記表示程序將在數據區塊 (DS=DATA) 的內存上寫入。

pop 指令#

POP 指令會讀取堆疊頂上的值,並且將它傳輸到目標寄存器上。如下圖所示,POP EDI將讀取堆疊頂上的第一個值並將其傳給 EDI 寄存器,並將 ESP 的值指向已讀取值下方的那個值,並把它作為堆疊的頂部。

image

通過 Text 搜索 pop,發現 pop 指令的使用方式沒什麼改變,而且沒有將值 pop 存入一個地址中。

image

參考:匯編語言入門教程 - 阮一峰的網絡日誌

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