Win32 模拟GetProcAddress

 1 ;=======================
2 ;模拟GetProcAddress
3 ;函数功能:根据基址和函数名获取函数地址
4 ;参数:_lpBase为基址,_lpBuf为字符串地址
5 ;返回值:函数VA
6 ;=======================
7 _GetApiFromName proc _lpBase,_lpBuf
8 local lRet
9 pushad
10
11 mov edi,_lpBuf
12 xor eax,eax
13 mov ecx,-1
14 repz scasb
15 sub edi,_lpBuf ;获取字符出长度
16 mov ecx,edi
17
18
19 mov esi,_lpBase
20 assume esi : ptr IMAGE_DOS_HEADER
21 add esi , [esi].e_lfanew
22 assume esi : ptr IMAGE_NT_HEADERS
23 mov esi,dword ptr [esi+78h] ;获取导出表偏移
24 add esi,_lpBase ;获取导出表文件内地址
25 assume esi : ptr IMAGE_EXPORT_DIRECTORY
26 mov edi ,[esi].AddressOfNames
27 add edi,_lpBase
28 xor ebx,ebx ;计数
29 ;========================
30 ;当前寄存器内 ecx,为字符串长度
31 ;ebx为0 做计数用
32 ;esi 为导出表地址 下面刚用到比较当中
33 ;edi 为函数名地址表
34 ;========================
35 .repeat
36 push esi ;保存esi
37 mov edi ,[edi] ;导出函数名称地址内指向了一个地址内存放的是函数名所以要去取出这个地址
38 add edi,_lpBase
39 mov esi,_lpBuf ; esi 为传入字符串参数地址
40 repz cmpsb ;edi 和 esi 比较
41 .if ZERO? ;如果比较的字符串全部相等,那么执行下面操作
42 pop esi
43 jmp _Address
44
45 .endif
46 add edi,4 ; 导出函数地址表内的指向的内容是一个连续的4字节地址 ,内存放的都是函数名
47 pop esi
48 inc ebx
49
50 .until ebx >= [esi].NumberOfNames
51 mov lRet,-1
52 jmp _Ret
53 ;取函数地址
54 _Address:
55 sub edi,[esi].AddressOfNames
56 sub edi , _lpBase
57 ;以上是为了获取距离函数名地址表字节数,好为了下面获取序号,
58 shr edi ,1 ; 这里除以2是为了 获取到序号 序号是和 函数名地址一一相对的,序号存放是2字节,而地址是4字节
59 mov ebx,[esi].AddressOfNameOrdinals
60 add ebx,_lpBase
61 add ebx,edi
62 movzx ebx,word ptr [ebx] ;获取到函数名想对应的序号
63 shl ebx,2 ; 乘以4是为了 获取函数地址
64 mov edx,[esi].AddressOfFunctions
65 add edx,_lpBase
66 mov eax,dword ptr [ edx + ebx ]
67 mov lRet,eax
68
69 ;退出出口
70 _Ret:
71 popad
72 mov eax,lRet
73 ret
74 _GetApiFromName endp

 

你可能感兴趣的:(Win32)