.586
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data
szSeach db "GetProcAddress",0
.data?
call @F
@@:
pop ebx
sub ebx,offset @B
assume fs:nothing
mov eax,fs:[030h] ;PEB结构
mov eax,[eax + 0ch] ;LDR_DATA结构
mov esi,[eax + 01ch]
lodsd
mov eax,[eax + 08h]
mov esi,[ebx + offset szSeach]
mov ebx, [eax + 3Ch];指向PE头,eax = Kernel32.dll基地址
add ebx, eax ;计算PE头的虚拟地址,ebx = PE头
add ebx, 120 ;获取DataDirectory[0]
mov ebx, [ebx] ;获取DataDirectory[0].VirtualAddress,ebx = 导出表的RAV地址
add ebx, eax ;ebx=引出表地址
xor edx, edx ;edx = 0
mov ecx, [ebx + 32];AddressOfNames
add ecx, eax ;eax = Kernel32.dll基地址
push esi ;esi = 将要比较的字符串地址
push edx ;索引值压栈
CompareNext: 在函数名数组中查找下一个函数名
pop edx ;edx ;弹出索引值
pop esi ;esi ;弹出源函数名地址
inc edx ;edx++ ;edx = 保存函数名位置索引,索引值加1
mov edi, [ecx] ;ecx 指向AddressOfNames首地址,[ecx]取出一个函数名地址RAV -> edi
add edi, eax ;计算出函数名地址,eax = Kernel32.dll首地址
add ecx, 4 ;指针移动下一个函数名
push esi ;下面要进行比较时会改变它们的值,源函数名地址
push edx ;下面要进行比较时会改变它们的值,保存索引值
CompareName: ;比较要查找的函数名是否于函数名数组中的一致
mov dl, [edi] ;[edi]取出函数名的第一个字符给dl
mov dh, [esi] ;[esi]对比的源函数名第一个字符给dh
cmp dl, dh ;查找到的字符和源函数名比较
jne CompareNext ;第一个字符不相同则跳转继续查找
inc edi ;查找到的字符串地址向后移动一个字符
inc esi ;要比较字符串地址向后移动一个字符
cmp byte ptr [esi], 0 ;字符是否到达未尾?
je GetAddress ;如果到达未尾则跳转
jmp CompareName ;继续比较字符串
GetAddress: ;找到想要的字符串
pop edx ;弹出函数名位置索引
pop esi ;弹出源函数名地址
dec edx ;函数名位置索引 + 1
shl edx, 1;乘2 ;edx = edx * 2; 由于序号表是word类型的
mov ecx, [ebx + 36] ;AddressOfNameOrdinals ;ebx导出表地址 + 36 -> ecx,获取AddressOfNameOrdinals的
RAV
add ecx, eax ;获取AddressOfNameOrdinals的虚拟地址,eax = Kernel32.dll基地址
add ecx, edx ;获取对应的序号表位置,edx = 序号表的偏移,ecx = 对应的序号表虚拟地址
xor edx, edx ;edx清零
mov dx, [ecx] ;取出序号表的值,dx = 序号表的值
shl edx, 2;乘4 ;序号表的值 * 2 *********************??**********************
mov ecx, [ebx + 28] ;获取AddressOfFunction的RAV ,ebx = 导出表的虚拟地址
add ecx, eax ;获取AddressOfFunction的虚拟地址, eax = Kernel32.dll基地址
add ecx, edx
add eax, [ecx]
ret
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!