首页
社区
课程
招聘
[原创]笑解 API 函数 -- API 绝密档案系列之三
发表于: 2006-3-9 06:54 38925

[原创]笑解 API 函数 -- API 绝密档案系列之三

2006-3-9 06:54
38925

笑解 API 函数 -- API 绝密档案系列之三  高处不胜寒

"怎么又笑了,防热涂的血" -- 摘自悍匪座山雕语录。
在这一篇中,我们首先简单介绍另一个函数 GetProcAddress, GetProcAddress 和 GetModuleHandle 函数是兄弟的关系,我个人认为这两个函数的命名非常容易让用户产生混乱,而且有些颠倒的感觉,似乎如下命名更好:

将 GetModuleHandle 改为
GetProcBaseAddress        //GetModuleHandle 实质是获取进程加载的基地址
将 GetProcAddress 改为
GetFunctionAddress        //GetProcAddress  实质是获取函数的调用地址
db  "GetProcAddress",0
在内存中的映象为:
47 65 74 50 72 6F 63 41 64 64 72 65 73 73 00
如果是Uncode在内存中的映象为:
47 00 65 00 74 00 50 00 72 00 6F 00 63 00 41 00 64 00 64 00 72 00 65 00 73 00 73 00
77E80CAB ; Exported entry 344. GetProcAddress
77E80CAB ; ======== S U B R O U T I N E ====================
77E80CAB ; FARPROC __stdcall GetProcAddress(HMODULE hModule,LPCSTR lpProcName)
77E80CAB       public _GetProcAddress@8
77E80CAB _GetProcAddress@8 proc near
77E80CAB ProcNameString= dword ptr -8
77E80CAB hModule= dword ptr  8
77E80CAB lpProcName= dword ptr  0Ch
77E80CAB       push ebp
77E80CAC       mov ebp, esp
77E80CAE       push ecx
77E80CAF       push ecx
77E80CB0       push ebx
77E80CB1       push edi
77E80CB2       mov edi, [ebp+lpProcName]           ; 获取指向函数名的指针(地址)
77E80CB5       mov ebx, 0FFFFh
77E80CBA       cmp edi, ebx                        ; 如果lpProcName是字符串,这指向这个字符串的地址一定
77E80CBA                                           ; 大于 0FFFFh
77E80CBC       jbe short IfProcNameIsNull
77E80CBE       lea eax, [ebp+ProcNameString]
77E80CC1       push edi                            ; SourceString
77E80CC2       push eax                            ; DestinationString
77E80CC3       call ds:__imp__RtlInitString@8      ; __declspec(dllimport) RtlInitString(x,x)
77E80CC9       lea eax, [ebp+lpProcName]           ; 将 lpProcName 作为变量使用
77E80CCC       push eax                            ; ProcedureAddress
77E80CCD       lea eax, [ebp+ProcNameString]
77E80CD0       push 0                              ; Ordinal
77E80CD2       push eax                            ; Name
77E80CD3       jmp short GetProcAddress
77E80CD5 IfProcNameIsNull:
77E80CD5       lea eax, [ebp+lpProcName]
77E80CD8       push eax                            ; ProcedureAddress
77E80CD9       push edi                            ; Ordinal
77E80CDA       push 0                              ; Name
77E80CDC GetProcAddress:                           ; flag
77E80CDC       push 0
77E80CDE       push [ebp+hModule]                  ; hModule
77E80CE1       call _BasepMapModuleHandle@8        ; BasepMapModuleHandle(x,x)
77E80CE6       push eax                            ; BaseAddress
77E80CE7       call _LdrGetProcedureAddress@16     ; LdrGetProcedureAddress(x,x,x,x)
77E80CEC       test eax, eax
77E80CEE       jl short IfFunAddrEquZero
77E80CF0       push 0                              ; flag
77E80CF2       push [ebp+hModule]                  ; hModule
77E80CF5       call _BasepMapModuleHandle@8        ; BasepMapModuleHandle(x,x)
77E80CFA       cmp [ebp+lpProcName], eax
77E80CFD       jnz short IfFunAddrIsOk
77E80CFF       cmp ebx, edi
77E80D01       sbb eax, eax
77E80D03       neg eax
77E80D05       add eax, STATUS_ORDINAL_NOT_FOUND
77E80D0A IfFunAddrEquZero:
77E80D0A       push eax                            ; Status
77E80D0B       call _BaseSetLastNTError@4          ; BaseSetLastNTError(x)
77E80D10       xor eax, eax
77E80D12       jmp short Exit
77E80D14 IfFunAddrIsOk:                            ; 变量参数lpProcName的内容为 ProcAddress
77E80D14       mov eax, [ebp+lpProcName]           ; 变量参数lpProcName的内容为 ProcAddress
77E80D17 Exit:
77E80D17       pop edi
77E80D18       pop ebx
77E80D19       leave
77E80D1A       retn 8
77E80D1A _GetProcAddress@8 endp

77E68210 ; ======== S U B R O U T I N E ====================
77E68210 ; int __stdcall BasepMapModuleHandle(HMODULE hModule,BOOLEAN flag)
77E68210 _BasepMapModuleHandle@8 proc near
77E68210 hModule= dword ptr  8
77E68210 flag  = byte ptr  0Ch
77E68210       push ebp
77E68211       mov ebp, esp
77E68213       mov eax, [ebp+hModule]
77E68216       test eax, eax
77E68218       jz short loc_77E68229
77E6821A       test al, 1
77E6821C       jz short loc_77E68235
77E6821E                                            ;if flag == 0
77E6821E                                            ;  ecx = 0
77E6821E                                            ;else
77E6821E                                            ;  ecx = 0xFFFFFFFF
77E6821E       mov cl, [ebp+flag]
77E68221       neg cl
77E68223       sbb ecx, ecx
77E68225       and eax, ecx
77E68227       jmp short loc_77E68235
77E68229 loc_77E68229:
77E68229       mov eax, large fs:18h
77E6822F       mov eax, [eax+TEB.Peb]
77E68232       mov eax, [eax+PEB.ImageBaseAddress]
77E68235 loc_77E68235:
77E68235       pop ebp
77E68236       retn 8
77E68236 _BasepMapModuleHandle@8 endp
77E80CB2       mov edi, [ebp+lpProcName]           ; 获取指向函数名的指针(地址)
77E80CB5       mov ebx, 0FFFFh
77E80CBA       cmp edi, ebx                        ; 如果lpProcName是字符串,这指向这个字符串的地址一定
77E80CBA                                           ; 大于 0FFFFh
77E80CBC       jbe short IfProcNameIsNull
77E80CBE       lea eax, [ebp+ProcNameString]
77E80CC1       push edi                            ; SourceString
77E80CC2       push eax                            ; DestinationString
77E80CC3       call ds:__imp__RtlInitString@8      ; __declspec(dllimport) RtlInitString(x,x)
               ;下面是为调用 LdrGetProcedureAddress(x,x,x,x) 而设置入口参数
77E80CC9       lea eax, [ebp+lpProcName]           ; 将 lpProcName 作为变量使用
77E80CCC       push eax                            ; ProcedureAddress
77E80CCD       lea eax, [ebp+ProcNameString]
77E80CD0       push 0                              ; Ordinal
77E80CD2       push eax                            ; Name
77E80CD3       jmp short GetProcAddress						 ; 跳到获取函数地址的具体调用
UNICODE_STRING struc ; (sizeof=0X8, standard type)
	Length 					dw ?
	MaximumLength 	dw ?
	Buffer 					dd ?                             ;指向字符串的指针
UNICODE_STRING ends

STRING struc ; (sizeof=0X8)
	Length 					dw ?
	MaximumLength 	dw ?
	Buffer 					dd ?                             ;指向字符串的指针
STRING ends
strings struc ; (sizeof=0X8, variable size)
	top 	dd ?
	Len 	dd ?
	Text 	db 0 dup(?)                        ; string(C)
strings ends

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (26)
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
2
早上好!
2006-3-9 09:09
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
强,这么快都出三了!

向高手学习!
2006-3-9 09:21
0
雪    币: 238
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
4
最初由 viviann 发布
强,这么快都出三了!

向高手学习!

请仔细读我第二篇文章中对我的定义,我乃中手也,哈哈。
2006-3-9 09:23
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
5
最初由 viviann 发布
强,这么快都出三了!

向高手学习!


估计是已经写到好几十了,然后一天一个的放出来
2006-3-9 09:27
0
雪    币: 242
活跃值: (163)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
6
最初由 北极星2003 发布
估计是已经写到好几十了,然后一天一个的放出来


强!!
2006-3-9 09:33
0
雪    币: 228
活跃值: (119)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
提个建议:
M$的ring 3层函数就是定义的特复杂,其实就一接口而已.关键的VMM-FSD交互还是要看ring 0,在ring 3费力解读看上去还是挺费劲的,可能还是没讲到最重要的东西,比如image section与data section的区别.楼主要是能像<<UNIX操作系统原理>>那样分析一下windows可能帮助更大,把结构链表都给它拉出来开肠破肚.的讲解.那样才不容易忘记.哈哈,肯定要挨砖了.看偶这个大嘴:>
2006-3-9 10:28
0
雪    币: 238
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
8
prince
早上好!

我住在GMT-8区,你住在GMT+8,所以我这里是中午好。
machoman
楼主要是能像<<UNIX操作系统原理>>那样分析一下windows可能帮助更大

见笑了,其实写这个东西是看到 qduwg 老师翻译这几个函数而随便写来玩的,目标明确,骗点“加精”而已,当不得真。真正要写windows底层的东西不但费力,而且肯定没有几个人看。其结果必然是,懂的人说你胡说八道,不懂的人说你八道胡说,哈哈。
2006-3-9 10:47
0
雪    币: 238
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
9
实际上论坛有许多潜水的高手,应该写点东西帮助后来者。我以前听说过一句很好的话:“一个人的责任是多方面的,包括社会责任”。
2006-3-9 10:48
0
雪    币: 234
活跃值: (370)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
10
好,学习
2006-3-9 11:27
0
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
11
【即生谕,何生亮,无事生非】
2006-3-9 11:35
0
雪    币: 1334
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
最初由 laoqian 发布
【即生谕,何生亮,无事生非】


你答错了,哈哈
应该是 季氏、何氏、吴氏, 你上面的回答没有那个字的姓氏
2006-3-9 11:59
0
雪    币: 21
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
顶一下!
2006-3-9 12:41
0
雪    币: 10627
活跃值: (2324)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
仰视 看不懂 不过慢慢看总有懂的一天
为中华之崛起而看文章
2006-3-9 13:05
0
雪    币: 2506
活跃值: (1030)
能力值: (RANK:990 )
在线值:
发帖
回帖
粉丝
15
最初由 gzgzlxg 发布
实际上论坛有许多潜水的高手,应该写点东西帮助后来者。我以前听说过一句很好的话:“一个人的责任是多方面的,包括社会责任”。

同感,支持!
2006-3-9 14:00
0
雪    币: 175
活跃值: (2531)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
太好了学习。
2006-3-9 16:30
0
雪    币: 250
活跃值: (103)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
好,学习
2006-3-9 17:02
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
不错,学习了。
2006-3-9 21:31
0
雪    币: 615
活跃值: (1217)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
19
第一篇看着还可以,能看懂,第2篇需要点工夫,这一篇要仔细的研究了.
妈眯妈眯HOME~
2006-3-10 09:52
0
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
20
最初由 Ivanov 发布
你答错了,哈哈
应该是 季氏、何氏、吴氏, 你上面的回答没有那个字的姓氏

看来,你是不太灵活了。
管他姓什么呢,反正即生的亮,何生的谕,无事生的非,古代的人的名字都很怪的说!至于姓什么不知道,但我们知道她们的名字,呵呵!
2006-3-10 10:02
0
雪    币: 671
活跃值: (723)
能力值: ( LV9,RANK:1060 )
在线值:
发帖
回帖
粉丝
21
晕,才看到,也不知道是第几层了。

是男人就下一百层
2006-3-10 15:55
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
恩,建议楼主写写IDA相关的,你那个不错,比这三篇好。
2006-3-10 17:21
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
顶一下!
2006-3-10 18:40
0
雪    币: 215
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
24
我觉得老兄有一个地方写的不太确切:
就是那个:

77E80CBC       jbe short IfProcNameIsNull

的rename 应该是 IfCallByOrder
就是考序号调用的情形...

顶着翻老贴的罪名冒昧提出...kanxue老大不要"下毒手啊"...
2006-9-16 11:08
0
雪    币: 109
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
api真的是很厉害
支持一下
回头好好的学习一下
2008-11-4 19:52
0
游客
登录 | 注册 方可回帖
返回
//