逆向分析之路-從運算碼開始-07


範例一:「mov r8,r8」產生的是88還是8A

  1. 打開Visual Studio使用C++並且輸入以下程式碼,設定中斷點進行驗證。為了方便,我們不再依本章一開頭的方式慢慢驗證,而是一次就把正向及反向的程式碼都先輸入,再一次驗證:

    

發現正向產生出來的運算碼是8A C0,而反向的opcode2asm片段可以看出88 C0與8A C0都是對應mov al, al。所以可以確定在Windows平台的Visual Studio C++ 8位元暫存器的編譯都是8A開頭的。那88到底是怎麼回事呢?

  1. 打開瀏覽器,連到網址:https://defuse.ca/online-x86-assembler.htm#disassembly

我們藉由線上反組譯的功能來輸入同樣的程式碼。

各位可以發現,他編譯出來的運算碼是88 C0,原來他用的是GCC的編譯器。

  1. 同樣的下方也有反組譯的輸入框,我們輸入88 C0及8A C0,發現他反組譯碼都是對到同一個mov al, al。

因此,得到了一個啟示,除了編譯器不同產生的運算碼選擇不同外,是不是當我們拿到一個執行檔,直接用編輯軟體去看底層的運算碼時,可不可以推論他最原先是用何種編譯器去編譯出來的呢? 但目前我們只察覺到8位元暫存器對暫存器有這個情況。

 

不過GCC這不在我們的討論範圍,如有興趣的讀者,可以考慮尋找GCC在Win上的支援(MinGW)http://www.mingw.org/ 或觀看https://youtu.be/k3w0igwp-FM的影片介紹

 

  1. 那C0又怎麼來的? 這時我們得去查16位元或32位元定址的Mod R/M圖表,這兩張圖表在Mod是11的情況下資料是重疊的,所以,MOV AL, AL得到8A C0的運算碼。

至於剩下的各種組合就由各位當作練習。

發表留言

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料