.586p
.model flat,stdcall
option casemap:none;
include include\windows.inc
include include\kernel32.inc
includelib lib\kernel32.lib
include include\user32.inc
includelib lib\user32.lib
GetApiAddress PROTO:DWORD,:DWORD
.data
Kernel32Addr dd ?
ExportKernel dd ?
GetProcAddr dd ?
LoadLibraryAddr dd ?
aGetProcAddr db "GetProcAddress", 0
GetProcAddLen equ $-aGetProcAddr-1
aLoadLibrary db "LoadLibraryA" , 0
LoadLibraryLen equ $-aLoadLibrary-1
szTitle db "检测结果", 0
temp1 db "Kernel32.dll 基本地址:%8x" , 0dh , 0ah
db "LoadLibrary 地址: %8x" ,0dh, 0ah
db "GetProcAddress 地址: %8x" , 0dh , 0ah , 0
temp2 db 0 dup(100)
.code
main:
Start:
mov esi,[esp] ;获取得堆栈指针中ExitThread地址
and esi,0fffff000h ;因为kernel32.dll是以00001000为对齐大小
LoopFindKernel32:
sub esi,1000h
cmp word ptr[esi], 'ZM' ;判断这个地址的前两个字节是否是"MZ"
jnz short LoopFindKernel32
GetPeHeader:
mov edi,dword ptr[esi+3ch]
add edi, esi
cmp word ptr[edi], 4550h ;定位到PE头
jnz short LoopFindKernel32
mov Kernel32Addr,esi
invoke GetApiAddress,Kernel32Addr,addr aLoadLibrary ;获取LoadLibrary的地址
mov LoadLibraryAddr,eax
invoke GetApiAddress , Kernel32Addr, addr aGetProcAddr ;获得GetProcAddr的地址
mov GetProcAddr , eax
invoke wsprintf,addr temp2,addr temp1,Kernel32Addr,LoadLibraryAddr,GetProcAddr
invoke MessageBoxA,0,addr temp2,addr szTitle,0
invoke ExitProcess,0
GetApiAddress proc uses ecx ebx edx esi edi hModule:DWORD ,szApiName:DWORD
LOCAL dwReturn:DWORD
LOCAL dwApiLength:DWORD
mov dwReturn,0
mov esi,szApiName
mov edx,esi
Continue_Searching_Null:
cmp byte ptr[esi],0
jz We_Got_The_Length
inc esi
jmp Continue_Searching_Null
We_Got_The_Length:
inc esi
sub esi,edx
mov dwApiLength ,esi ;获取API长度
mov esi,hModule
add esi,[esi+3ch]
assume esi:ptr IMAGE_NT_HEADERS ;定位到PE头
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,szApiName
mov ecx,dwApiLength
cld
repz cmpsb ;让ds:si和es:di所指向的两个字节相等,则继续比较,如果不等,则停止循环
.if ZERO? ;如果没有找到匹配的函数就继续循环
pop esi
jmp _Find_Index
.endif
pop esi
add ebx,4
inc edx
.until edx >= [esi].NumberOfNames ;直到查找完所有的被掉用过的函数
jmp _Exit
_Find_Index: ;通过序号找到函数地址
sub ebx,[esi].AddressOfNames
sub ebx,hModule ;指向kernel32.dll名字
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
_Exit:
mov eax,dwReturn
ret
GetApiAddress endp
end main