实战 API 函数 -- API绝密档案系列之五
本来没有这个续篇,因为两个原因,催生了这篇不该出现的东西。上面第四篇谈的都是自己打造的函数,我觉得有必要给各位欣赏一下,现在流行猛壳是如何打造这个函数的。
我将选择顶级猛壳 Themida 的 GetFunctionAddress 来展示在实际中是如何实现获取函数调用地址的。
代码很长,大多是垃圾代码,我对代码做了详细的解释,对有用的代码都加了注解,并加了编号,没有编号的就是垃圾代码了,你可以完全不看,如果你觉得垃圾代码干扰你的思维,可以将凡是没有注解的地方都删除,余下的就是真正的程序了。
这段代码是从 Themida 加密的 notepad.exe 壳中挖出来的。我在IDA中进行了整理,你所看到的和你自己在IDA或Debug中看到的可能在感觉上完全不同。在回答我的前几篇帖子中,我看到有朋友希望我能讲讲怎样使用IDA,不是谦虚,我对IDA所知甚少,离著作还差的远,我想大家不仿要求在论坛注册名为 bpx 的高手来阐述,IDA 对于分割线不支持中文操作系统的一个 Plugin 就出自这位大侠之手。或者请看雪老大亲自出手,也比我强的多。
分析这些代码对于新手来说可能是非常困难的一件事,这个你不用自卑,我干这个工作已经超过20年,如果你也干了这么长的时间,非常坦白的说,你肯定比我强。
论坛上有许多朋友对破解彼有心得和建树,但许多朋友并不擅长分析,所谓“知己知彼,百战不殆”,了解一下壳是怎样具体工作的,对你一定有帮助。
这篇文章是以非常严肃的态度来处理的,原因是面对创造 Themida 这样强壳的作者,应该给予尊敬。
Themida 的 GetFunctionAddress 入口参数有三个,其中一个是通过变量 APIFristChar 来传递 API 函数的第一个字母,目的可能是为了加快运行速度。
010D505D ; int __stdcall GetFunctionAddress(int BaseAddress,int CryptCode) 010D505D GetFunctionAddress proc near 010D505D 010D505D FunctionAddress= dword ptr -4 010D505D BaseAddress= dword ptr 4 010D505D CryptCode= dword ptr 8 010D505D 010D505D pusha ; 1 010D505E push eax 010D505F push edx 010D5060 push ecx 010D5061 push ecx 010D5062 pusha 010D5063 popa 010D5064 sidt qword ptr [esp-2] 010D5069 pop ecx 010D506A jmp loc_10D507E 010D506F db 11h, 0AAh, 58h, 8Eh, 9Bh, 0E4h, 0CFh, 16h, 67h, 0C0h, 0DDh 010D506F db 0F7h, 0F8h, 13h, 0C5h 010D507E 010D507E loc_10D507E: 010D507E pop ecx 010D507F rdtsc 010D5081 jnb loc_10D5089 010D5087 pusha 010D5088 popa 010D5089 010D5089 loc_10D5089: 010D5089 pop edx 010D508A pop eax 010D508B mov eax, 0 ; 2 010D5090 pusha 010D5091 movsx ecx, cx 010D5094 add [ebp+153E2D91h], edi 010D509A popa 010D509B mov edx, [esp+20h+CryptCode] ; 3 CryptCode 函数名加密代码 010D509F stc 010D50A0 mov ss:(dwFunctionsCount+1531F38Ah - ThemidaSeg)[ebp], eax ; 4 010D50A6 pusha 010D50A7 mov edi, [ebp+153E23DDh] 010D50AD mov edx, [ebp+153E2DB9h] 010D50B3 popa 010D50B4 push edx 010D50B5 push edx 010D50B6 mov [ebp+153E11CDh], edx 010D50BC sidt qword ptr [esp-2] 010D50C1 pop edx 010D50C2 push eax 010D50C3 push edx 010D50C4 stc 010D50C5 rdtsc 010D50C7 010D50C7 loc_10D50C7: 010D50C7 sub [ebp+153E04B5h], edx 010D50CD pop edx 010D50CE pop eax 010D50CF pop edx 010D50D0 mov esi, IMAGE_DOS_HEADER.e_lfanew ; 5 PE 文件头的偏移量 010D50D5 push eax 010D50D6 push edx 010D50D7 jle loc_10D50E3 010D50DD jle $+6 010D50E3 010D50E3 loc_10D50E3: 010D50E3 rdtsc 010D50E5 jmp loc_10D50FB 010D50EA db 6Fh, 95h, 0D0h, 51h, 69h, 31h, 0ECh, 0CEh, 9Fh, 65h, 0FEh, 2Bh 010D50EA db 0B8h, 0Ch, 0DEh, 40h, 18h 010D50FB 010D50FB loc_10D50FB: 010D50FB pop edx 010D50FC pop eax 010D50FD add esi, [esp+20h+BaseAddress] ; 6 DosHeader.e_lfanew + BaseAddress 010D5101 mov [ebp+153E0021h], edi 010D5107 pusha 010D5108 call loc_10D5119 010D510D db 2 dup(53h), 0AFh, 7Ah, 0B8h, 0A5h, 8Ah, 20h, 58h, 84h, 8Fh 010D510D db 91h 010D5119 010D5119 loc_10D5119: 010D5119 jb $+6 010D511F pop eax 010D5120 mov [ebp+153E029Dh], ebx 010D5126 popa 010D5127 lodsw ; 7 获取PE头的偏移量 010D5129 sub [ebp+153E271Dh], ebx 010D512F add eax, [esp+20h+BaseAddress] ; 8 加上基地址得到 PE 头的起始位置 010D5133 jmp loc_10D5142 010D5138 db 3Dh, 0BCh, 69h, 0B6h, 4Bh, 0ADh, 0AEh, 0E2h, 79h, 2Bh 010D5142 010D5142 loc_10D5142: 010D5142 nop 010D5143 jle loc_10D5157 010D5149 pusha 010D514A jg $+6 010D5150 jl $+6 010D5156 popa 010D5157 010D5157 loc_10D5157: 010D5157 push eax ; 9 010D5158 jnp loc_10D5164 010D515E pusha 010D515F mov esi, edx 010D5161 mov ah, dl 010D5163 popa 010D5164 010D5164 loc_10D5164: 010D5164 nop 010D5165 pusha 010D5166 clc 010D5167 call loc_10D5171 010D516C db 0D2h, 1, 94h, 0ECh, 0E3h 010D5171 010D5171 loc_10D5171: 010D5171 xor eax, [ebp+153E2071h] 010D5177 pop ecx 010D5178 popa 010D5179 mov eax, [eax+IMAGE_NT_HEADERS.OptionalHeader.DirectoryExport.VirtualAddress] ; 10 010D517C jnb loc_10D5190 010D5182 pusha 010D5183 push eax 010D5184 push edx 010D5185 rdtsc 010D5187 pop edx 010D5188 pop eax 010D5189 or [ebp+153E1569h], edx 010D518F popa 010D5190 010D5190 loc_10D5190: 010D5190 stc 010D5191 add eax, [esp+24h+BaseAddress] ; 11, Export.VirtualAddress + BaseAddress 010D5195 sub [ebp+153E1965h], edi 010D519B mov eax, [eax+IMAGE_EXPORT_DIRECTORY.NumberOfNames] ; 12 010D519E jb loc_10D51AA 010D51A4 mov [ebp+153E0D35h], ecx 010D51AA 010D51AA loc_10D51AA: 010D51AA inc eax ; 13 010D51AB jbe loc_10D51BE 010D51B1 push eax 010D51B2 push edx 010D51B3 cmc 010D51B4 rdtsc 010D51B6 push eax 010D51B7 push edx 010D51B8 rdtsc 010D51BA pop edx 010D51BB pop eax 010D51BC pop edx 010D51BD pop eax 010D51BE 010D51BE loc_10D51BE: ; 14 010D51BE mov ss:(dwNumeberOfName+1531F38Ah - ThemidaSeg)[ebp], eax 010D51C4 sub [ebp+153E199Dh], esi 010D51CA pop eax ; 15 010D51CB pusha 010D51CC mov eax, [ebp+153E0181h] 010D51D2 jmp loc_10D51E2 010D51D7 db 1Fh, 5Ch, 94h, 99h, 29h, 91h, 49h, 0Dh, 0B6h, 97h, 8Eh 010D51E2 010D51E2 loc_10D51E2: 010D51E2 popa 010D51E3 mov esi, [eax+IMAGE_NT_HEADERS.OptionalHeader.DirectoryExport.VirtualAddress] ; 16 010D51E6 jb loc_10D51F2 010D51EC or [ebp+153E2ED9h], ebx 010D51F2 010D51F2 loc_10D51F2: 010D51F2 add esi, IMAGE_EXPORT_DIRECTORY.AddressOfFunctions ; 17 010D51F5 jnp loc_10D5210 010D51FB push eax 010D51FC push edx 010D51FD push esi 010D51FE push esi 010D51FF sidt qword ptr [esp-2] 010D5204 pop esi 010D5205 pop esi 010D5206 rdtsc 010D5208 sub [ebp+153E2869h], edi 010D520E pop edx 010D520F pop eax 010D5210 010D5210 loc_10D5210: ; 18, AddressOfFunctions + BaseAddress 010D5210 add esi, [esp+20h+BaseAddress] 010D5214 jmp loc_10D521F 010D5219 db 88h, 0C1h, 0A4h, 6Ah, 85h, 17h 010D521F 010D521F loc_10D521F: 010D521F clc 010D5220 lea edi, (dwAddressOfFunctions+1531F38Ah - ThemidaSeg)[ebp] ; 19 010D5220 ; 取 AddressOfFunctions 变量地址 010D5226 pusha 010D5227 and eax, [ebp+153E2411h] 010D522D mov esi, [ebp+153E2285h] 010D5233 popa 010D5234 lodsd ; 20 取AddressOfFunctions 的偏移量 010D5235 mov [ebp+153E15F9h], eax 010D523B add eax, [esp+20h+BaseAddress] ; 21 + BaseAddress 010D523F jmp loc_10D524F 010D5244 db 3Ch, 69h, 36h, 4, 0A3h, 0C9h, 88h, 19h, 0CBh, 3Fh, 7Fh 010D524F 010D524F loc_10D524F: 010D524F stosd ; 22 保存 AddressOfFunctions 010D5250 jmp loc_10D5267 010D5255 db 0ABh, 37h, 2 dup(50h), 53h, 9Ah, 68h, 0C4h, 36h, 69h, 0B8h 010D5255 db 2Ah, 7Ah, 0F5h, 52h, 0E6h, 33h, 0E7h 010D5267 010D5267 loc_10D5267: 010D5267 jmp loc_10D5271 010D526C db 62h, 0CCh, 5Dh, 5Ah, 0BAh 010D5271 010D5271 loc_10D5271: 010D5271 lea edi, (dwAddressOfNames+1531F38Ah - ThemidaSeg)[ebp] ; 23 010D5271 ; 取保存 AddressOfNames 变量地址 010D5277 mov [ebp+153E2219h], edi 010D527D lodsd ; 24 取 AddressOfNames 的偏移量 010D527E pusha 010D527F mov ebx, [ebp+153E044Dh] 010D5285 mov ecx, [ebp+153E1A51h] 010D528B popa 010D528C add eax, [esp+20h+BaseAddress] ; 25 + BaseAddress 010D5290 pusha 010D5291 or [ebp+153E133Dh], ecx 010D5297 cmc 010D5298 popa 010D5299 push eax ; 26 010D529A push eax 010D529B push edx 010D529C jmp loc_10D52B4 010D52A1 db 4Dh, 0AEh, 42h, 0B7h, 0AEh, 0E4h, 0B0h, 3Ah, 0CCh, 15h, 0EEh 010D52A1 db 31h, 6Bh, 0F2h, 4Eh, 96h, 0E6h, 3Fh, 0A0h 010D52B4 010D52B4 loc_10D52B4: 010D52B4 rdtsc 010D52B6 push eax 010D52B7 push edx 010D52B8 jmp loc_10D52C8 010D52BD db 0B8h, 21h, 0F6h, 3Ah, 0D2h, 0D3h, 0ADh, 66h, 0D6h, 0F6h, 0D1h 010D52C8 010D52C8 loc_10D52C8: 010D52C8 rdtsc 010D52CA pusha 010D52CB popa 010D52CC pop edx 010D52CD pop eax 010D52CE pop edx 010D52CF pop eax 010D52D0 mov [esp], eax 010D52D3 mov [ebp+153E1895h], esi 010D52D9 stosd ; 27 保存 AddressOfNames 地址 010D52DA jnz loc_10D52F9 010D52E0 jmp loc_10D52F9 010D52E5 db 9Eh, 3Ah, 2Ah, 0E4h, 0BCh, 46h, 8Bh, 5, 7Dh, 0C5h, 9, 0C0h 010D52E5 db 0AFh, 61h, 0A4h, 0Ah, 0FAh, 84h, 0A1h, 0D4h 010D52F9 010D52F9 loc_10D52F9: 010D52F9 lea edi, (dwAddressOfNamesOrdinals+1531F38Ah - ThemidaSeg)[ebp] ; 28 010D52F9 ; 取 AddressOfNameOrdinals 变量地址 010D52FF stc 010D5300 cld ; 29 010D5301 lodsd ; 30 读 AddressNameOrdinals 的偏移量 010D5302 push eax 010D5303 push edx 010D5304 jnz loc_10D5320 010D530A jmp loc_10D5320 010D530F db 6Ch, 29h, 0AEh, 0E6h, 87h, 64h, 49h, 7Ah, 92h, 0Ch, 38h, 5 010D530F db 0CCh, 0CEh, 3Fh, 18h, 0F2h 010D5320 010D5320 loc_10D5320: 010D5320 rdtsc 010D5322 cld 010D5323 pop edx 010D5324 pop eax 010D5325 pusha 010D5326