>>04)
目录整体调用逻辑源码实现部分整体调用逻辑start (程序入口) ↓ INVOKE LoadPE ↓ 1. 获取自身 ImageBase ↓ 2. 打开 PlantsVsZombies.exe → CreateFile → CreateFileMapping → MapViewOfFile ↓ 3. 解析 PE 结构 ├── DOS Header ├── NT Header获取区段数量、入口点、SizeOfHeaders 等 └── Section Table 位置 ↓ 4. VirtualProtect把自己内存改成可写可执行 ↓ 5. 拷贝 PE Headers 到自身内存 ↓ 6. 循环拷贝所有 Section.text、.data、.rsrc 等 ↓ 7. 手动修复 Import TableIAT ├── 遍历每个 DLL ├── LoadLibrary 加载 DLL └── GetProcAddress 填充 IAT ↓ 8. 清理文件映射和句柄 ↓ 9. JMP dwEP ← 跳转到 PlantsVsZombies.exe 的原始入口点源码实现部分.386 .model flat, c option casemap:none include windows.inc include msvcrt.inc include kernel32.inc include user32.inc includelib msvcrt.lib includelib kernel32.lib includelib user32.lib .const IMAGE_SIZE EQU 394000H ; 自身预留内存大小可后续优化为动态 .data g_szFile db PlantsVsZombies.exe, 0 ; 要加载的目标程序 .code db 90h ; NOP 占位 ORG IMAGE_SIZE ; 代码放在高地址避免覆盖自身 ; ; 主加载函数 ; LoadPE PROC ; 局部变量 LOCAL hFILE:HANDLE LOCAL hFileMap:HANDLE LOCAL szPeBuffer:LPVOID ; 文件映射指针 LOCAL pDosHeader:PTR IMAGE_DOS_HEADER LOCAL pNtHeader:PTR IMAGE_NT_HEADERS LOCAL pSectionHeader:PTR IMAGE_SECTION_HEADER LOCAL dwNumberSec:DWORD LOCAL dwSizeOfHeader:DWORD LOCAL dwEP:DWORD ; 目标 OEP (Original Entry Point) LOCAL pImageImpHeader:PTR IMAGE_IMPORT_DESCRIPTOR LOCAL ZeroHeadImp: IMAGE_IMPORT_DESCRIPTOR LOCAL dwImageBase:DWORD ; 自身 ImageBase LOCAL dwMod:HANDLE ; DLL 句柄 LOCAL dwOld:DWORD ; 旧内存保护属性 ; 1. 获取自身模块基址 INVOKE GetModuleHandle, NULL MOV dwImageBase, EAX ; 2. 打开并映射目标 PE 文件到内存 INVOKE CreateFile, offset g_szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL MOV hFILE, EAX INVOKE CreateFileMapping, hFILE, NULL, PAGE_READONLY, 0, 0, NULL MOV hFileMap, EAX INVOKE MapViewOfFile, hFileMap, FILE_MAP_READ, 0, 0, 0 MOV szPeBuffer, EAX ; 内存中的 PE 文件镜像 ; 3. 解析 PE Header MOV pDosHeader, EAX ASSUME ESI :PTR IMAGE_DOS_HEADER MOV ESI, EAX ADD EAX, [ESI].e_lfanew ; 定位 NT Header MOV pNtHeader, EAX ASSUME ESI :PTR IMAGE_NT_HEADERS MOV ESI, pNtHeader MOV EAX, [ESI].OptionalHeader.SizeOfHeaders MOV dwSizeOfHeader, EAX MOVZX EAX, [ESI].FileHeader.NumberOfSections MOV dwNumberSec, EAX ; 计算目标入口点 OEP MOV EAX, [ESI].OptionalHeader.AddressOfEntryPoint ADD EAX, dwImageBase MOV dwEP, EAX ; 定位 Section Table MOVZX EAX, [ESI].FileHeader.SizeOfOptionalHeader LEA EBX, [ESI].OptionalHeader ADD EAX, EBX MOV pSectionHeader, EAX ; 4. 修改自身内存保护权限关键步骤 INVOKE VirtualProtect, dwImageBase, IMAGE_SIZE, PAGE_EXECUTE_READWRITE, ADDR dwOld ; 5. 拷贝 PE Headers INVOKE crt_memcpy, dwImageBase, szPeBuffer, dwSizeOfHeader ; 6. 拷贝所有 Sections MOV ESI, pSectionHeader ASSUME ESI :PTR IMAGE_SECTION_HEADER XOR ECX, ECX .WHILE ECX dwNumberSec MOV EDI, dwImageBase ADD EDI, [ESI].VirtualAddress ; 目标地址 MOV EDX, szPeBuffer ADD EDX, [ESI].PointerToRawData ; 源地址 PUSH ECX PUSH EDX INVOKE crt_memcpy, EDI, EDX, [ESI].SizeOfRawData POP EDX POP ECX INC ECX ADD ESI, SIZEOF IMAGE_SECTION_HEADER .ENDW ; 7. 修复 Import TableIAT MOV ESI, pNtHeader MOV EAX, [ESI].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT * 8].VirtualAddress ADD EAX, dwImageBase MOV pImageImpHeader, EAX MOV ESI, pImageImpHeader ASSUME ESI:PTR IMAGE_IMPORT_DESCRIPTOR .WHILE TRUE INVOKE crt_memcmp, ESI, ADDR ZeroHeadImp, SIZEOF IMAGE_IMPORT_DESCRIPTOR .IF EAX 0 .BREAK .ENDIF .IF [ESI].Name1 NULL || [ESI].FirstThunk NULL || [ESI].OriginalFirstThunk NULL .BREAK .ENDIF ; LoadLibrary 加载 DLL MOV EAX, [ESI].Name1 ADD EAX, dwImageBase PUSH ECX PUSH EDX INVOKE LoadLibrary, EAX POP EDX POP ECX MOV dwMod, EAX ; 修复该 DLL 的 IAT MOV EBX, [ESI].FirstThunk ADD EBX, dwImageBase MOV EDI, [ESI].OriginalFirstThunk ADD EDI, dwImageBase .while DWORD PTR[EDI] ! 0 .IF dword PTR[EDI] 80000000h MOV EDX, DWORD PTR[EDI] AND EDX, 0FFFFH .ELSE MOV EDX, DWORD PTR[EDI] ADD EDX, dwImageBase ADD EDX, 2 .endif PUSH ECX PUSH EDX INVOKE GetProcAddress, dwMod, EDX POP EDX POP ECX MOV DWORD PTR[EBX], EAX ADD EBX, 4 ADD EDI, 4 .endw ADD ESI, SIZEOF IMAGE_IMPORT_DESCRIPTOR .ENDW ; 8. 清理资源 INVOKE UnmapViewOfFile, szPeBuffer INVOKE CloseHandle, hFileMap INVOKE CloseHandle, hFILE ; 9. 跳转执行目标程序 JMP dwEP ret LoadPE ENDP ; start: INVOKE LoadPE invoke ExitProcess, 0 ret end start