通过PEB得到Kernel32的基址,及遍历导出表寻找GetProcAddress

 

 

通过Windbg可以看到上面结果的成员及关系, 然后我OD调试看看  在windows7调试的

上图中是PEB的起始位置

这里是PEB_LDR_DATA

 

这里就可以看到第一个载入的dll是ntdll.dll

第二个是kernelbase.dll

这里就是我们所需要的Kernel32.dll的地址了

 

下面是通过遍历导出表得到相应的函数

_getApi proc _hModule,_lpApi
   local @ret
   local @dwLen

   pushad
   mov @ret,0
   ;计算API字符串的长度,含最后的零
   mov edi,_lpApi
   mov ecx,-1
   xor al,al
   cld
   repnz scasb
   mov ecx,edi
   sub ecx,_lpApi
   mov @dwLen,ecx

   ;从pe文件头的数据目录获取导出表地址
   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,_lpApi
     mov ecx,@dwLen
     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 @ret,eax

_ret:
   assume esi:nothing
   popad
   mov eax,@ret
   ret
_getApi endp

 

szUnKernel32        db         06Bh, 000h, 065h, 000h, 072h, 000h, 06Eh, 000h, 065h, 000h, 06Ch, 000h, 033h, 000h, 032h, 000h
                    db         02Eh, 000h, 064h, 000h, 06Ch, 000h, 06Ch, 000h, 0,0      ; 定义的UNICODE字符串

_getKernelBase  proc _dwKernelRetAddress

    LOCAL @ret:dword
    pushad
    pushfd
    assume fs:nothing          ;;  这个必须要加  要不然后面的会报错
        mov eax, fs:[30h]         ;PEB的地址
        mov eax, [eax+0ch]        ;Ldr的地址
        mov esi, [eax +1ch]       ;Flink地址
@A:     
        mov edi, [esi+20h]
        push edi
        xor ecx, ecx
        dec ecx            ;; 设置循环次数-1
        xor eax, eax        ;;   设置搜索内容0
           repne scasw      ;; 一直重复搜索到EDI字符串末尾的0   这里要用scasw  因为是UNICODE
           not ecx         ;;得到搜索次数,也就是字符串的完整长度
           dec ecx         ;; -1得到字符串不包含末尾0的长度
           
           pop edi
           push esi
           mov esi, offset szUnKernel32
        repe cmpsb
        pop esi
        mov @ret, esi
        mov esi, [esi]
        jnz @A
        
        mov esi,   @ret
        mov eax, [esi + 08h]         ;eax就是kernel32.dll的地址
        mov @ret, eax
        popfd
        popad
        mov eax, @ret
    
   ret
_getKernelBase  endp  

 

你可能感兴趣的:(通过PEB得到Kernel32的基址,及遍历导出表寻找GetProcAddress)