在弄外壳,打算自己实现GetProcAdress函数。下面是该函数的汇编代码,支持函数名和序号。
自己测试成功,不论通过函数名还是通过序号都可以成功获取指定函数。但在使用该函数恢复输入表时,总是出错,不晓得哪里除了问题。是代码有错,还是和函数转发器有关系?
;========================================================================
;下面为外壳自带的GetProcAddress函数
;========================================================================
MyGetApi proc _hModule,_lpszApi
local @dwReturn,@dwStringLength
pushad
mov @dwReturn,0
;********************************************************************
; 计算 API 字符串的长度(带尾部的0)
;********************************************************************
mov edi,_lpszApi
cmp edi,0FFFFh ;如果是按序号导入
jg IsFunName
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
sub edi,[esi].nBase
shl edi,2
add edi,[esi].AddressOfFunctions
add edi,_hModule
mov eax,[edi]
add eax,_hModule
mov @dwReturn,eax
jmp _Error
IsFunName:
mov ecx,-1
xor al,al ;al清零。xor: 1 xor 1=0,0 xor 0=0,1 xor 0=1,0 xor 1=1
cld
repnz scasb ;( AL ) - (( DI )), ( DI ) ← ( DI ) ± 1
mov ecx,edi
sub ecx,_lpszApi
mov @dwStringLength,ecx
;********************************************************************
; 从 PE 文件头的数据目录获取导出表地址
;********************************************************************
assume esi:nothing
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 ;保存esi
mov edi,[ebx]
add edi,_hModule
mov esi,_lpszApi
mov ecx,@dwStringLength
repz cmpsb
.if ZERO?
pop esi
jmp @F
.endif
pop esi
add ebx,4
inc edx
.until edx >= [esi].NumberOfNames
jmp _Error
@@:
;********************************************************************
; API名称索引 --> 序号索引 --> 地址索引
;********************************************************************
sub ebx,[esi].AddressOfNames
sub ebx,_hModule
shr ebx,1 ;ebx = 序号索引, AddressOfNameOrdinals是WORD型数组,AddressOfFunctions是DWORD数组,所以除以2
add ebx,[esi].AddressOfNameOrdinals
add ebx,_hModule ;ebx = 指定函数的序号的地址
movzx eax,word ptr [ebx]
shl eax,2
add eax,[esi].AddressOfFunctions
add eax,_hModule
;********************************************************************
; 从地址表得到导出函数地址
;********************************************************************
mov eax,[eax]
add eax,_hModule
mov @dwReturn,eax
_Error:
;pop fs:[0]
;add esp,0ch
assume esi:nothing
popad
mov eax,@dwReturn
ret
MyGetApi endp
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课