假設讀者了解 DOS 病毒與 386 保護模式基礎。本文探討 Win32 環境下病毒核心技術:PE 檔案感染、系統記憶體駐留、檔案 I/O 掛鉤、API 位址動態解析。
PE 典型結構:MZ Header → DOS Stub → PE Header → Optional Header → Section Table → Sections (代碼/資料/導入表/導出表…)。區段在檔案中按 4KB 對齊,載入記憶體基址通常 0x400000,第一區段 0x401000,入口點同在 0x401000。高級語言編譯產生的區段長度常非 4KB 倍數,區段末尾會有未使用空間(Physical Size - Virtual Size),可藏置病毒代碼。此外,表頭區塊(MZ+Stub+PE+Optional+Section Table)約 1KB,第一區段從 4KB 開始,中間空出約 3KB,CIH 即利用此空間。
DOS 下所有程式共享線性位址空間,普通記憶體分配即可。Win32 每進程擁有獨立 4GB 虛擬空間,病毒需分配 2GB 以上共享系統區域。典型 API:VxD Service _PageAllocate、Kernel32 VxDCall _PageReserve(參考 Win98 DDK 與 HPS 原始碼註解)。
駐留型病毒透過掛鉤檔案 I/O 攔截檔案存取以啟動感染。兩條路徑:
IFSMgr_InstallFileSystemApiHook(如 CIH)VxDCall 中的 DOS Services Callback(如 HPS)Win32 系統調用不再用中斷,而是由 DLL(Kernel32、GDI32、User32)導出。同版本 Windows 核心函數入口固定,可用以下組合語言技巧在初始化階段動態解析:
.386p .model flat,stdcall extrn GetModuleHandleA:proc extrn GetProcAddress:proc extrn ExitProcess:proc .data szKernel db 'KERNEL32.DLL',0 szFindFirst db 'FindFirstFileA',0 ... hKernel dd 0 .code start: push szKernel call GetModuleHandleA mov hKernel,eax push szFindFirst push hKernel call GetProcAddress mov FindFirstFile,eax ... jmp VirusStart
初始化代碼將所需 API 位址填入病毒資料區,病毒本體執行時直接呼叫,無需靜態導入表,極難被靜態分析發現。