ASProtect.SKE.2.11.Build.03.13-RES-crk(看雪工具下载)对部分系统函数的处理
外壳将部分系统函数的前几个字节放到用自己分配的空间,然后再转到系统函数运行
如:
003D0000 8BFF mov edi, edi
003D0002 55 push ebp
003D0003 8BEC mov ebp, esp
003D0005 837D 08 00 cmp dword ptr [ebp+8], 0
003D0009 53 push ebx
003D000A 56 push esi
003D000B 68 821D807C push 7C801D82
003D0010 C3 retn
7C801D77 > 8BFF mov edi, edi
7C801D79 55 push ebp
7C801D7A 8BEC mov ebp, esp
7C801D7C 837D 08 00 cmp dword ptr [ebp+8], 0
7C801D80 53 push ebx
7C801D81 56 push esi
7C801D82 74 14 je short 7C801D98
以上两段是不是很象呢?第二段是系统函数LoadLibraryA的代码,第一段是外壳分配的空间,并将LoadLibraryA的前10个字节搬了进去,在地址003D000B处push 7C801D82,
Retn后回到系统代码。
怎样找到所有被这样处理过的函数呢?
对VirtualAlloc设断,得到:
返回地址 Address Size 分配地址
VirtualAlloc: 40A537 0 43000 A10000
VirtualAlloc: 40A565 0 43000 A60000
VirtualFree: 40A646 A10000
VirtualAlloc: AA10CA 0 546 3C0000
VirtualFree: AA1101 3C0000
VirtualAlloc: AA1349 0 31400 3C0000
VirtualFree: AA13E5 3C0000
VirtualAlloc: AA1349 0 A00 3C0000
VirtualFree: AA13E5 3C0000
VirtualAlloc: AA1349 0 1000 3C0000
VirtualFree: AA13E5 3C0000
VirtualAlloc: AA1349 0 2600 3C0000
VirtualFree: AA13E5 3C0000
VirtualAlloc: A61404 0 100000 AB0000
VirtualAlloc: A615D6 AB0000 4000 AB0000
VirtualAlloc: A615D6 AB4000 14000 AB4000
VirtualFree: A61657 AC4000
VirtualAlloc: A615D6 AC4000 8000 AC4000
VirtualAlloc: A615D6 ACC000 8000 ACC000
VirtualFree: A61657 AC4000
VirtualAlloc: A615D6 AD4000 8000 AD4000
VirtualFree: A61657 AD0000
VirtualFree: A61657 AC8000
VirtualAlloc: A7E7C2 0 1D 3C0000
VirtualAlloc: A7E7C2 0 15 3D0000
VirtualAlloc: A7E7C2 0 25 3E0000
VirtualAlloc: A7E7C2 0 16 3F0000
VirtualAlloc: A7E7C2 0 16 BB0000
VirtualAlloc: A7E7C2 0 22 BC0000
VirtualAlloc: A7E7C2 0 1E BD0000
VirtualAlloc: A7E7C2 0 17 BE0000
VirtualAlloc: A7E7C2 0 17 BF0000
VirtualAlloc: A7E7C2 0 15 C00000
VirtualAlloc: A7E7C2 0 29 C10000
VirtualAlloc: A7E7C2 0 22 C20000
看看最下面这几行,分配的空间不是很大,很可能是,事实确实这样。你可已找一两个地方看看嘛。。。
随便找一个,比如对3D0000设内存写入断点(要确定它已分配),为此可写个脚本:
var VirtualAllocaddr
checkver:
//check ollyscript's version
cmp $VERSION,"0.9"
ja start
msg "version bad!"
ret
start:
gpa "VirtualAlloc","kernel32.dll"
mov VirtualAllocaddr,$RESULT
bp VirtualAllocaddr //在VirtualAlloc设断
continue:
run
rtr
cmp eax,003D0000
jne continue
ret
虽然对3D0000设内存写入断点并断下,你不会知道它是哪个函数,只有在下一个VirtualAlloc调用前仔细跟踪。
Olly的run跟踪到调用下一个VirtualAlloc前的代码为:
00A87337 主 cmp ebx, 700 FL=CS
00A8733D 主 jbe short 00A87349
00A87349 主 lea eax, [ebp-10] EAX=0012FDE4
00A8734C 主 mov edx, ebx EDX=00000016
00A8734E 主 call 00A7E7A8 ESP=0012FDC8 //call ,在上面最近的ret处设断,查看是否有熟悉的函数名字出现。。。。
00A7E7A8 主 push ebx ESP=0012FDC4
00A7E7A9 主 push esi ESP=0012FDC0
00A7E7AA 主 mov esi, edx ESI=00000016
00A7E7AC 主 mov ebx, eax EBX=0012FDE4
00A7E7AE 主 push 40 ESP=0012FDBC
00A7E7B0 主 push 1000 ESP=0012FDB8
00A7E7B5 主 push esi ESP=0012FDB4
00A7E7B6 主 push 0 ESP=0012FDB0
00A7E7B8 主 mov eax, [A937F0] EAX=00A94748
00A7E7BD 主 mov eax, [eax+2C] EAX=00A65EC0 //[eax+2C]VirtualAlloc的地址
00A7E7C0 主 call eax ESP=0012FDAC //call VirtualAlloc了
00A65EC0 主 jmp [A9C260]
用这种方法跟踪。
很easy啊,上面不远就找到一个:
00A871EC 8D55 E8 lea edx, [ebp-18]
00A871EF 8BC7 mov eax, edi
00A871F1 E8 FAB9FFFF call 00A82BF0 //中断在此,EAX中可得函数名
但按F9后又中段在此,eax中不再看见函数名了,但VirtualAlloc还没调用,一直但按F9,
在VirtualAlloc中断并返回后,对刚刚返回的地址设内存写入断点,执行后发现:写入的数据就是刚刚在00A871F1处eax中显示函数的前几个字节。这说明这样找是正确的,不过在00A871F1处你无法轻易得到函数名,因为00A871F1在写入之前中断不止一次,eax中内容不稳定。再向前找找吧。。。。。
我找到了一处:
00A86695 8945 F4 mov [ebp-C], eax
00A86698 8B45 F4 mov eax, [ebp-C]
00A8669B E8 C4FEFFFF call 00A86564
00A866A0 3B45 FC cmp eax, [ebp-4]
00A866A3 75 40 jnz short 00A866E5 +++++++++不是要处理的函数就跳,否则处理++++
00A866A5 53 push ebx
00A866A6 8B45 F8 mov eax, [ebp-8]
00A866A9 50 push eax
00A866AA 56 push esi
00A866AB E8 6CFFFFFF call 00A8661C +++++在此设断,ebp-c中可看到函数名+++++
在00A866AB处设断可以得到所有的函数。。。。。。哈哈
这样你可以记录下哪个函数被处理在哪个空间了。
不过,不过。。。。。
问题出现了。。。
当我编了个脚本来得到所有这些函数时出现:
看看记录:
我发现在最后处理了VirtualAlloc后,其处理后的地址是00C20000
00C20000处为:
00C20000 CC int3 //可恶吧。。。。。
00C20001 FF55 8B call [ebp-75]
00C20004 EC in al, dx
00C20005 FF75 14 push dword ptr [ebp+14]
00C20008 FF75 10 push dword ptr [ebp+10]
00C2000B FF75 0C push dword ptr [ebp+C]
00C2000E FF75 08 push dword ptr [ebp+8]
00C20011 6A FF push -1
00C20013 68 999A807C push 7C809A99
00C20018 68 A29A807C push kernel32.VirtualAllocEx
00C2001D C3 retn
我想,在处理了VirtualAlloc后,下面分配内存的任务就应该由00C20000处代码来执行了吧,再看一下调用VirtualAlloc前的那段代码:
00A7E7B6 主 push 0 ESP=0012FDB0
00A7E7B8 主 mov eax, [A937F0] EAX=00A94748
00A7E7BD 主 mov eax, [eax+2C] EAX=00A65EC0 //[eax+2C]VirtualAlloc的地址
00A7E7C0 主 call eax ESP=0012FDAC //call VirtualAlloc了
00A65EC0 主 jmp [A9C260]
我发现在处理了VirtualAlloc后,00A7E7C0 call eax处的eax为00C20000了,看看00A7E7BD mov eax, [eax+2C] ,eax+2C处肯定是调用VirtualAlloc的地址,过去看看:我机器eax+2C=00A94748+2C
再看看处理前的:
00A65EC0处是什么呢?
开始时外壳会生成每个函数的调用表:
由上图可知A9C258~A9c26C这部分内存块应该是导入函数表。
这样啊。。。。。。
在处理了VirtualAlloc后将00A94748+2C处的数据改回去吧。
外壳共处理了从00A94748到00A9477C的14个特殊函数,它们是:
似乎又有问题了。。。。
在log中我发现后面还有好多的内存分配,且里面也是函数,可能是外壳函数,这个问题以后再探索。。。。。。。。。。。。。。。。。。。。。。。
程序入口点!
ASProtect.SKE.2.11.Build.03.13-RES-crk对入口点的保护只要找到关键call,在最后一次seh后,找到关键call:
00A8FB9F B8 32000000 mov eax, 32
00A8FBA4 E8 1B2DFDFF call 00A628C4
00A8FBA9 2905 20B6A900 sub [A9B620], eax
00A8FBAF B8 64000000 mov eax, 64
00A8FBB4 E8 0B2DFDFF call 00A628C4
00A8FBB9 014424 04 add [esp+4], eax
00A8FBBD A1 20B6A900 mov eax, [A9B620]
00A8FBC2 894424 0C mov [esp+C], eax
00A8FBC6 8B4424 04 mov eax, [esp+4]
00A8FBCA 894424 18 mov [esp+18], eax
00A8FBCE A1 0CB6A900 mov eax, [A9B60C]
00A8FBD3 E8 3C30FDFF call 00A62C14
00A8FBD8 A1 B837A900 mov eax, [A937B8]
00A8FBDD C600 E3 mov byte ptr [eax], 0E3
00A8FBE0 8D5424 08 lea edx, [esp+8]
00A8FBE4 A1 2CB6A900 mov eax, [A9B62C]
00A8FBE9 E8 7695FFFF call 00A89164
00A8FBEE E8 3160FFFF call 00A85C24
00A8FBF3 8BC6 mov eax, esi
00A8FBF5 E8 1A30FDFF call 00A62C14
00A8FBFA E8 B5D0FFFF call 00A8CCB4 //关键call
执行到返回后就是入口点。
Wak
2006.4.11[B]