通过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