首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

Windows 反組譯實戰:W32Dasm 分析 GetCommandLine + MessageBox 程式,解析 IAT Thunk 機制與載入器重定位

     編輯:組合語言

測試程式:6.asm - 取得命令列參數並彈窗顯示

.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib

.data
szCaption db "命令行參數",0

.code
start:
    invoke GetCommandLine
    invoke MessageBox, NULL, eax, addr szCaption, MB_OK
    invoke ExitProcess, NULL
end start

編譯與 W32Dasm 反組譯輸出

Disassembly of File: 6.exe
Code Offset = 00000400, Code Size = 00000200
Data Offset = 00000800, Data Size = 00000200
Number of Objects = 0003 (dec), Imagebase = 00400000h

Object01: .text RVA: 00001000 Offset: 00000400 Size: 00000200 Flags: 60000020
Object02: .rdata RVA: 00002000 Offset: 00000600 Size: 00000200 Flags: 40000040
Object03: .data RVA: 00003000 Offset: 00000800 Size: 00000200 Flags: C0000040

+++++++++++++++++++ IMPORTED FUNCTIONS ++++++++++++++++++
Number of Imported Modules = 2 (decimal)
Import Module 001: KERNEL32.dll
Import Module 002: USER32.dll

Import Module 001: KERNEL32.dll
Addr:00002072 hint(00B6) Name: GetCommandLineA
Addr:00002064 hint(0075) Name: ExitProcess

Import Module 002: USER32.dll
Addr:00002092 hint(01BB) Name: MessageBoxA

+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object .text **************
Program Entry Point = 00401000 (6.exe File Offset:00001600)

* Reference To: KERNEL32.GetCommandLineA, Ord:00B6h
//******************** Program Entry Point ********
:00401000 E81D000000 Call 00401022
:00401005 6A00        push 00000000
:00401007 680E304000  push 0040300E        ; szCaption 位址
:0040100C 50          push eax             ; GetCommandLine 返回值
:0040100D 6A00        push 00000000

* Reference To: USER32.MessageBoxA, Ord:01BBh
:0040100F E814000000 Call 00401028
:00401014 6A00        push 00000000

* Reference To: KERNEL32.ExitProcess, Ord:0075h
:00401016 E801000000 Call 0040101C
:0040101B CC          int 3

* Referenced by a CALL at Address: |:00401016
* Reference To: KERNEL32.ExitProcess, Ord:0075h
:0040101C FF2504204000 Jmp dword ptr [00402004]  ; **IAT Thunk: ExitProcess**

* Referenced by a CALL at Address: |:00401000
* Reference To: KERNEL32.GetCommandLineA, Ord:00B6h
:00401022 FF2500204000 Jmp dword ptr [00402000]  ; **IAT Thunk: GetCommandLineA**

* Reference To: USER32.MessageBoxA, Ord:01BBh
:00401028 FF250C204000 Jmp dword ptr [0040200C]  ; **IAT Thunk: MessageBoxA**

核心疑問:為什麼不是直接 CALL [IAT]?

觀察入口點:

:00401000 E81D000000 Call 00401022   ; Call 近似相對跳轉到 Thunk
...
:00401022 FF2500204000 Jmp dword ptr [00402000] ; 間接跳轉 IAT

原因:載入器重定位效率 (Relocation Efficiency)。

兩種呼叫外部 API 的編碼方式對比

方式機器碼範例載入器修補點數代碼大小
直接 CALL [IAT]FF 15 00 20 40 00 (6 bytes)每個呼叫點皆需修補 (若呼叫 100 次,修補 100 處)每次 6 bytes
CALL Thunk -> JMP [IAT]E8 xx xx xx xx (5 bytes) + Thunk FF 25 yy yy yy yy (6 bytes)僅修補 Thunk 處的 IAT 位址 (1 處)共用 Thunk 時極省空間

Thunk 機制優勢

  1. 載入器工作量極小:只需遍歷 IAT 表 (每個匯入函式 1 項),填入實際位址。程式碼區段 (.text) **完全不動**,支援**代碼頁共享** (Code Sharing) — 多進程載入同一 DLL/EXE 映像,物理記憶體只佔一份 .text 頁框。
  2. 支援 ASLR (Address Space Layout Randomization):現代 OS 隨機化 ImageBase,只需重定位 IAT 表 (在 .rdata/.data 可寫區段),.text 區段保持唯讀共享。
  3. 編譯器最佳化:同一函式多處呼叫,共用單一 Thunk (如 ExitProcess 常只有一個 Thunk)。

DEBUG 工具驗證 (附錄)

文中提到使用 DEBUG (或 SoftICE/TRW/IDA/Hiew) 載入進程除錯:

debug /Load Process
; 輸入命令列參數 (可選) -> 進入除錯視窗
; 單步追蹤 (F8), 觀察呼叫流程

在 DOS 年代 DEBUG 是神器;Win32 時代建議使用 x64dbg / x32dbg (開源、現代 UI、支援符號)、WinDbg (微軟官方、核心除錯)、IDA Pro (靜態分析之王)。

現代視角補充

  • W32Dasm 為 16/32-bit 混合時代產物 (最後版本 2003),已停止更新,**無法正確分析 64-bit PE、.NET、加殼、控制流平坦化** 等現代二進位制。
  • IAT Hooking 原理即修改 [00402000] 等 IAT 項目指向自訂函式,實現 API 截獲 (用戶模式 Hook)。
  • 延遲載入 (/DELAYLOAD) 會生成特殊 Thunk,首次呼叫時由載入器輔助程式碼動態 LoadLibrary/GetProcAddress 並修補 IAT,之後直呼。
  • CFG (Control Flow Guard):編譯器在間接呼叫 (CALL/JMP [reg/mem]) 前插入檢查,驗證目標位址是否在合法靶點表中,防禦 ROP/JOP 攻擊。Thunk 位址需在 CFG 表中。

總結

「為什麼 invoke GetCommandLine 不直接編譯成 Call dword ptr [00402000]?」
答案:**為了讓載入器只修補一個 IAT 表項,而非成百上千個呼叫點,實現代碼區段唯讀共享與 ASLR 友善。** 這是 PE 格式設計的核心智慧之一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved