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文件 · 17.6 应用实例(1) 下页:第17章 PE文件 · 17.6 应用实例(3)

第17章 PE文件

版权所有 © 云南伯恩科技 证书:粤ICP备09170368号