内容
利用win32汇编弹窗显示kernel32.dll的首地址和GetKernelBase函数的地址
在win7下编译通过,需要masm安装目录为c:\masm32
代码
.586
.model flat,stdcall
option casemap:none
include c:\masm32\include\windows.inc
include c:\masm32\include\comctl32.inc
includelib c:\masm32\lib\comctl32.lib
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\user32.lib
GetApiA proto:DWORD,:DWORD ;函数原型
.code
VCode:
szMsg db "xxxxxxx",0
val db "abcdefgh",0 ;address of functions in Ascii
;--------------------------------------------------------------------------------------------------
;code start
;--------------------------------------------------------------------------------------------------
;------proc to save eax into Ascii value 'val' for messagebox-----------
binToAscii proc near ; change al into Ascii
push eax
and eax,0fh
add al,30h
cmp al,39h
jbe @f
add al,7
@@:
stosb ;save ax into [edi]
pop eax
ret
binToAscii endp
saveEax proc near ;save eax to val in Ascii mode
push ecx
push edi
push eax
mov ecx,8
cld
lea edi,val
L1:
rol eax,4
call binToAscii
loop L1
pop eax
pop edi
pop ecx
ret
saveEax endp
;-------------------------------------------------------------------
_Start0:
invoke InitCommonControls
jmp _Start
K32_api_ordinal_retrieve proc Base:DWORD,sApi:DWORD ;****从kernel32.dll中查找函数序号****
push edx ;保存edx
xor eax,eax ;此时esi=sApi
Next_Api: ;edi=AddressOfNames
mov esi,sApi
xor edx,edx
dec edx
Match_Api_name:
mov bl,byte ptr [esi]
inc esi
cmp bl,0
jz foundit
inc edx
push eax
mov eax,[edi+eax*4] ;AddressOfNames的指针,递增
add eax,Base ;注意是RVA,一定要加Base值
cmp bl,byte ptr [eax+edx] ;逐字符比较
pop eax
jz Match_Api_name ;继续搜寻
inc eax ;不匹配,下一个api
loop Next_Api
jmp no_exist ;若全部搜完,即未存在
foundit:
pop edx ;edx=AddressOfNameOrdinals
shl eax,1 ;*2得到AddressOfNameOrdinals的指针
movzx eax,word ptr [edx+eax] ;eax返回指向AddressOfFunctions的指针
ret
no_exist:
pop edx
xor eax,eax
ret
K32_api_ordinal_retrieve endp
GetApiA proc Base:DWORD,sApi:DWORD ;已知DLL Base 及API函数名,查找该DLL的多个API地址*****
local ADDRofFun:DWORD
pushad
mov edi,Base
add edi,IMAGE_DOS_HEADER.e_lfanew
mov edi,[edi] ;现在edi=off PE_HEADER
add edi,Base ;得到IMAGE_NT_HEADERS的偏移
mov ebx,edi
mov edi,[edi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress]
add edi,Base ;得到edi=IMAGE_EXPORT_DIRECTORY入口
mov eax,[edi+1ch] ;AddressOfFunctions的地址
add eax,Base
mov ADDRofFun,eax
;ecx=NumberOfNames
mov ecx,[edi+18h]
mov edx,[edi+24h]
add edx,Base ;edx=AddressOfNameOrdinals
mov edi,[edi+20h]
add edi,Base ;edi=AddressOfNames
invoke K32_api_ordinal_retrieve,Base,sApi
mov ebx,ADDRofFun
shl eax,2 ;要*4才得到偏移
add eax,ebx
mov eax,[eax]
add eax,Base ;加上Base!
mov [esp+7*4],eax ;eax返回api地址
popad
ret
GetApiA endp
appBase dd ?
k32Base dd ?
lpApiAddrs label near
dd offset sGetProcAddress
dd offset sLoadLibrary
dd 0,0
sGetProcAddress db "GetProcAddress",0
sLoadLibrary db "LoadLibrary",0
aGetProcAddress dd 0
aLoadLibrary dd 0
;
_Start:
call _delta ;-----重定位-------
_delta:
pop ebp
sub ebp,offset _delta
mov dword ptr[ebp+appBase],ebp
mov ecx,[esp] ;返回地址
xor edx,edx
getK32Base:
assume fs:nothing
mov eax,fs:[30h] ;获取PEB所在地址
mov eax,[eax+0ch] ;获取PEB_LDR_DATA 结构指针
mov esi,[eax+1ch] ;获取InInitializationOrderModuleList 链表头
lodsd ;获取双向链表当前节点后继的指针
mov eax,[eax+8] ;获取kernel32.dll的基地址
mov [ebp+k32Base],eax
lea edi,[ebp+aGetProcAddress] ;-----seach Kernel32.dll for two api address
lea esi,[ebp+lpApiAddrs]
lop_get:
lodsd ;get api name address offset into eax
cmp eax,0 ;is it end?
jz End_Get
add eax,ebp ;get api name
push eax ;arg of GetApiA
push dword ptr[ebp+k32Base] ;arg of GetApiA
call GetApiA ;Call GetApiA to retrive two functions address from Kerenel32.dll
stosd ;return value:eax 存入edi指向地址
call saveEax ;Save Eax into val
invoke MessageBox, NULL, addr val, addr szMsg, MB_OK ;MessageBox for two api ,here just use user32.dll
jmp lop_get
End_Get:
_Exit:
;push 0
invoke ExitProcess, NULL
end _Start0
欢迎指正