WIN32汇编语言教程:第17章 PE文件 · 17.6 应用实例(2)
这个程序的主要功能是用前面描述的方法获取Kernel32.dll的基址,并扫描导出表得到GetProcAddress函数的地址,然后调用这个函数得到LoadLibrary函数的地址。获得这两个关键函数的地址后,程序使用LoadLibrary函数装入User32.dll并获取MessageBox函数的地址,在显示了一个消息框以后用Ret指令结束程序。
如果用第17章的查看导入表的例子程序去查看这个NoImport.exe文件,就可以发现文件中没有导入表部分。
由于获取Kernel32.dll基址和GetProcAddress入口地址的功能在17.6.2节的例子中还要用到,在本例中将它们分离出来放在_GetKernel.asm文件中,并在主程序中用include伪指令将它包含到程序中,_GetKernel.asm文件的内容如下:
;#################################################################### ; 错误 Handler ;#################################################################### _SEHHandler proc _lpExceptionRecord,_lpSEH,\ _lpContext,_lpDispatcherContext pushad mov esi,_lpExceptionRecord mov edi,_lpContext assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT mov eax,_lpSEH push [eax + 0ch] pop [edi].regEbp push [eax + 8] pop [edi].regEip push eax pop [edi].regEsp assume esi:nothing,edi:nothing popad mov eax,ExceptionContinueExecution ret _SEHHandler endp ;#################################################################### ; 在内存中扫描 Kernel32.dll 的基址 ;#################################################################### _GetKernelBase proc _dwKernelRet local @dwReturn pushad mov @dwReturn,0 ;******************************************************************** ; 重定位 ;******************************************************************** call @F @@: pop ebx sub ebx,offset @B ;******************************************************************** ; 创建用于错误处理的 SEH 结构 ;******************************************************************** assume fs:nothing push ebp lea eax,[ebx + offset _PageError] push eax lea eax,[ebx + offset _SEHHandler] push eax push fs:[0] mov fs:[0],esp ;******************************************************************** ; 查找 Kernel32.dll 的基地址 ;******************************************************************** mov edi,_dwKernelRet and edi,0ffff0000h .while TRUE .if word ptr [edi] == IMAGE_DOS_SIGNATURE mov esi,edi add esi,[esi+003ch] .if word ptr [esi] == IMAGE_NT_SIGNATURE mov @dwReturn,edi .break .endif .endif _PageError: sub edi,010000h . break .if edi < 070000000h .endw pop fs:[0] add esp,0ch popad mov eax,@dwReturn ret _GetKernelBase endp ;#################################################################### ; 从内存中模块的导出表中获取某个 API 的入口地址 ;#################################################################### _GetApi proc _hModule,_lpszApi local @dwReturn,@dwStringLength pushad mov @dwReturn,0 ;******************************************************************** ; 重定位 ;******************************************************************** call @F @@: pop ebx sub ebx,offset @B ;******************************************************************** ; 创建用于错误处理的 SEH 结构 ;******************************************************************** assume fs:nothing push ebp lea eax,[ebx + offset _Error] push eax lea eax,[ebx + offset _SEHHandler] push eax push fs:[0] mov fs:[0],esp ;******************************************************************** ; 计算 API 字符串的长度(带尾部的0) ;******************************************************************** mov edi,_lpszApi mov ecx,-1 xor al,al cld
第17章 PE文件
版权所有 © 云南伯恩科技 证书:粤ICP备09170368号