2.1 解讀內存轉儲
2.1.1 遊戲規則
- 可修改數值參數:
- SCORE
- ENERGY
2.1.2 修改4個字節就能得高分
- 使用工具:OllyDbg
首先查看ESP位址,也就是堆疊地址的起點
- 在堆疊視窗尋找當前SCORE,例如29,16進制為1D
- 找出來可能不止一個1D,因此可以試著改變實際得分看堆疊的值是否會跟著變動以確認是在哪個位址
最後我們確定了SCORE (0012FD88)和ENERGY (0012FD80)的位址,並嘗試修改它們
最後SCORE和ENERGY分別被修改為FDC4 (64964)和FFFF (65535)
2.1.3 獲取內存轉儲(memory dump)
- 修改完數據後,若要保存某個時間點的狀態,我們就需要內存轉儲
- 使用工具:Windows 7 工作管理員 → 處理程序 → 右鍵程序名稱 → 建立傾印檔案(dmp檔)
2.1.4 從進程異常終止瞬間的狀態查找崩潰的原因
- 分析Dr. Watson工具產生出來的drwtsn32.log檔
2.1.5 有效運用即時偵錯
- 使用工具:OllyDbg → Options → Just-in-time debugging → Make OllyDbg just-in-time debugger
- 當程式crash時,OllyDbg會自動開啟並掛載到崩潰的進程上
2.1.6 通過轉儲文件尋找出錯原因
- 第一時間啟動調試器或是從留下的轉儲文件找出錯原因
- 使用工具:WinDbg
- 開啟dmp檔(guitest2的user_small.dmp)
- 一開始只有Command視窗
Alt+6
: Call Stack視窗Alt+7
: Disassembly視窗- 點擊Calls視窗的
0x0
:應該要顯示反組譯後的程式碼,但由於EIP的值為00000000,只顯示一堆問號,代表某些原因導致跳轉到00000000位址了 - 點擊Calls視窗的
guitest2+0x12d0
:顯示當前位址為004012d0
- 點擊Calls視窗的
- 接著查看前一條指令call eax暫存器的值,我們按下
Alt+4
查看暫存器的值,內容果然為00000000- 也就是說,004012ce call eax指令調用了00000000這個位址,引起crash
- 而004012c8也執行了call指令,而它的return address存在eax中
- 那麼00402004是調用什麼函數呢? 輸入
Alt+5
打開Memory視窗,在Virtual的地方輸入00402004 - 地址00402004的值為04 24 00 00 (=00002404)
04 24 00 00是怎麼來的??? 應該就是記憶體上的值,但與書本不符
- 那麼00402004是調用什麼函數呢? 輸入
- 這邊的值是相對於基地址的偏移量,因此為0400000+2404=00402404,這時顯示出調用的函數名稱,GetProcAddress
- 同樣,004012bc所call的函數為LoadLibraryW
- 最後改寫為易懂的形式
004012b7 6844214000 push "kernel31.dll" 004012bc ff1500204000 call LoadLibraryW 004012c2 6860214000 push "GetCurrentProcessId" 004012c7 50 push eax 004012c8 ff1504204000 call GetProcAddress 004012ce ffd0 call eax 004012d0 8b4d08 mov ecx,dword ptr [ebp+8] <= crash point 004012d3 0fb7c6 movzx eax,si