Dynamic loading technology

Dynamic loading technology

Dynamic loading technology allows programmers from complex import table structure, constructed in the space program similar to calling the import table function mechanism is introduced.

Before understanding that knowledge is best to understand the windows virtual memory management, as detailed in my blog

Dynamic library technology

DLL static call

Also known as implicit invocation. Call a dynamic link library function is usually taken is: the addition of ".lib" library file produced when generating dynamic link library and ".inc" file contains the project application, when you want to use the DLL function , direct use of the function name. For example, adding user32.lib user32.inc call the MessageBox function, you can see examples of my another blog ;

DLL Dynamic Invocation

Also known as an explicit call. Load and unload DLL to achieve the purpose of calling DLL functions through the API function. Function and dynamic library calls related mainly includes:

  1. LoadLibrary (or the MFC AfxLoadLibrary), loaded dynamic link library
  2. GetProcAddress, acquire VA (virtual memory address) to introduce the function, the symbolic name or identification number to a DLL internal address
  3. FreeLibrary (or the MFC AfxFreeLibrary), the release of dynamic link library

Export function start address

Program to introduce dynamic link library ultimate goal is to call the dynamic link library function of the code, so to get the key derivation function starting address is dynamic link library dynamic loading technology.

Assuming now that user32.dll is dynamically loaded into memory at 0x77DF0000, then the entry is the address VA MessageBoxA:
0x77DF000 + 0x00026544 = 0x7E16544

If the VA after a function in the process of determining the space, the easiest way is to take the call by call it hard-coded

push xx		    ;显示往栈里压入该函数的参数,个数由调用的函数决定
......
mov eax,77E16544;
call eax

Loading techniques using dynamic programming in

Three steps:
1. Get the base address of kernel32.dll
2. Get the address of the function GetProcAddress (LoadLibrary function and obtain the address by this function)
3. using the acquired function address in the program code

1. Find the base address of kernel32.dll
    .386
    .model flat,stdcall
    option casemap:none

include    windows.inc
include    user32.inc
includelib user32.lib
include    kernel32.inc
includelib kernel32.lib

;数据段
    .data
szText         db  'kernel32.dll在本程序地址空间的基地址为:%08x',0dh,0ah,0
kernel32Base   dd  ?
szBuffer       db 256 dup(0)

;代码段
    .code
_getKernelBase  proc _dwKernelRetAddress
   local @dwRet

   pushad
   mov @dwRet,0
   
   mov edi,_dwKernelRetAddress
   and edi,0ffff0000h  ;查找指令所在页的边界,以1000h对齐

   .repeat
     .if word ptr [edi]==IMAGE_DOS_SIGNATURE  ;找到kernel32.dll的dos头
        mov esi,edi
        add esi,[esi+003ch]
        .if word ptr [esi]==IMAGE_NT_SIGNATURE ;找到kernel32.dll的PE头标识
          mov @dwRet,edi
          .break
        .endif
     .endif
     sub edi,010000h
     .break .if edi<070000000h
   .until FALSE
   popad
   mov eax,@dwRet
   ret
_getKernelBase  endp   


start:
    mov eax,dword ptr [esp]
    invoke _getKernelBase,eax
    invoke wsprintf,addr szBuffer,addr szText,eax
    invoke MessageBox,NULL,addr szBuffer,NULL,MB_OK
    ret
    end start
2. Get GetProcAddress address

By _getApi, until the base address of a dynamic link library, and knowing the calling function name, address can be obtained by calling the function

;------------------------------------------------
; 从内存中模块的导出表中获取某个 API 的入口地址
;------------------------------------------------
_getApi  proc  _hModule,_lpszApi
  local @dwReturn,@dwStringLen
  
  pushad
  mov @dwReturn,0
  call @F
@@:
  pop ebx
  sub ebx,offset @B

  ;创建用于错误处理的SEH结构
  assume fs:nothing
  push ebp
  lea eax,[ebx+offset _ret]
  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
  repnz scasb
  mov ecx,edi
  sub ecx,_lpszApi
  mov @dwStringLen,ecx
  ;从DLL文件头的数据目录中获取导出表的位置
  mov esi,_hModule
  add esi,[esi+3ch]
  assume esi:ptr IMAGE_NT_HEADERS
  mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
  add esi,_hModule
  assume esi:ptr IMAGE_EXPORT_DIRECTORY
  mov ebx,[esi].AddressOfNames
  add ebx,_hModule
  xor edx,edx
  .repeat
    push esi
    mov edi,[ebx]
    add edi,_hModule
    mov esi,_lpszApi
    mov ecx,@dwStringLen
    repz cmpsb
    .if ZERO?
      pop esi
      jmp @F
    .endif
    pop esi
    add ebx,4
    inc edx
  .until edx>=[esi].NumberOfNames
  jmp _ret
@@:
  ;API名称索引->序号索引->地址索引
  sub ebx,[esi].AddressOfNames
  sub ebx,_hModule
  shr ebx,1
  add ebx,[esi].AddressOfNameOrdinals
  add ebx,_hModule
  movzx eax,word ptr [ebx]
  shl eax,2
  add eax,[esi].AddressOfFunctions
  add eax,_hModule
  ;从地址表得到导出函数地址
  mov eax,[eax]
  add eax,_hModule
  mov @dwReturn,eax
_ret:
  pop fs:[0]
  add esp,0ch
  assume esi:nothing
  popad
  mov eax,@dwReturn
  ret
_getApi  endp

start:
    invoke _getApi,hDllKernel32,addr szGetProcAddress   ;获取GetProcAddress函数的内存地址
    mov _GetProcAddress,eax
    ...
    ret
    end start

3. Use the programming function address acquired in the code
	;声明函数
	_QLMessageBoxA  typedef  proto :dword,:dword,:dword,:dword
	;声明函数引用
	_ApiMessageBoxA  typedef  ptr _QLMessageBoxA
	...
	;定义函数
	_messageBox  _ApiMessageBoxA  ?
	...;动态获取_messageBox的地址
	;调用函数
	invoke _messageBox,NULL,offset szText,NULL,MB_OK
Published 43 original articles · won praise 16 · views 10000 +

Guess you like

Origin blog.csdn.net/include_IT_dog/article/details/89320215