..考研词汇 1.0 InlineHook API 爆破之解文
本帖最后由 GUC 于 2009-12-16 19:04 编辑原版:http://www.onlinedown.net/soft/82461.htm
破解不是本文的重点,这里简略带过。
软件会找目录下的key.bb文件,其实就是个记事本文件,里面写上16个数字就可以了,接下来关键点如下:
004EED6B 55 push ebp ; 这是关键call内部,eax返回非0就是注册成功
004EED6C 8BEC mov ebp, esp
004EED6E 8B4D 0C mov ecx, dword ptr
004EED71 E8 B4FDFFFF call 004EEB2A
004EED76 50 push eax
004EED77 8B4D 08 mov ecx, dword ptr
004EED7A E8 E4FDFFFF call 004EEB63
004EED7F F7D8 neg eax ; 爆破方式n多,我用这里的三行共5个字节写mov eax,-1
004EED81 1BC0 sbb eax, eax ; 爆破方式n多,我用这里的三行共5个字节写mov eax,-1
004EED83 40 inc eax ; 爆破方式n多,我用这里的三行共5个字节写mov eax,-1
004EED84 5D pop ebp
004EED85 C2 0800 retn 8
这个地方共被11个地方调用。
软件的壳很少见,是PEX 0.99 -> bart/CrackPl,脱壳后本机运行成功,但在虚拟机里测试发现不能跨平台,看一下,原来这个壳处理后程序调用api的方式都是:
00866780 - E9 1077FA7B jmp 7C80DE95 ; kernel32.7C80DE95
00866785 - E9 85C1FC7B jmp 7C83290F ; kernel32.ResumeThread
0086678A - E9 9440FA7B jmp 7C80A823 ; kernel32.GetThreadPriority
0086678F - E9 045AFA7B jmp 7C80C198 ; kernel32.SetThreadPriority
00866794 - E9 D1AAFA7B jmp 7C81126A ; kernel32.GetVersion
。。。
彻底晕倒。
放弃脱壳,可以通过多层SMC去搞定他,也可以简单地用loader、lpk,但本文讲另外一个思路:InlineHook API进行爆破。
但是找哪个api呢?
我们通过esp定律发现他在OEP之前第一次用了VirtualFree函数,那时候代码全已出现但未执行,时机很perfect!就它了!
载入程序,Ctrl+N看一下:
Address Section Type Name Comment
00866379 Import KERNEL32.ExitProcess
00866371 Import KERNEL32.GetProcAddress
00866375 Import KERNEL32.LoadLibraryA
00866369 Import USER32.MessageBoxA
008DB000 Export <ModuleEntryPoint>
0086637D Import KERNEL32.VirtualAlloc
00866381 Import KERNEL32.VirtualFree
已经有KERNEL32.LoadLibraryA和KERNEL32.GetProcAddress的地址了(分别在dword 和dword ),有这对搭档在足够我们干很多事了!乐啊
这里还已经有了KERNEL32.VirtualFree,在dword ,可以直接拿来用(即使没有,咱们也可以通过LoadLibraryA跟GetProcAddress获取)。
强调,下面的代码里,KERNEL32.VirtualFree的地址dword 是直接拿来用的,不要看到dword 感到莫名其妙。。。
基本信息有了,咱们开工!
1、首先找个空地。
程序空地不少,但是我仍喜欢加个区段,所以我加了个区段,大小只要200个字节左右就行了,因为补丁的代码只需要大概170个字节。
我加的段VA:008DB000
2、用LordPE修改程序的入口为新段的地址008DB000,OD载入,开始写代码:
PS:008DB026这里call eax ; VirtualProtect是为了使VirtualFree函数前6个字节可写可读,防止api地址不可写导致我们挂钩失败。不清楚的自己去查下api手册。
008DB000 > $ 68 92B08D00 push 8DB092 ; /ASCII "kernel32.dll" 8DB092这里你自己去写下ASCII "kernel32.dll"
008DB005 . FF15 75638600 call dword ptr ; \kernel32.LoadLibraryA 返回基址到eax
008DB00B . 68 A2B08D00 push 8DB0A2 ; /ASCII "VirtualProtect" 8DB0A2这里你自己去写下ASCII "VirtualProtect"
008DB010 . 50 push eax ; |这里是刚得到的kernel32.dll的基址
008DB011 . FF15 71638600 call dword ptr ; \kernel32.GetProcAddress 返回VirtualProtect的函数的地址到eax
008DB017 . 68 B2B08D00 push 8DB0B2 ; 原来的属性暂放空地8DB0B2
008DB01C . 6A 40 push 40 ; 可读可写属性40
008DB01E . 6A 06 push 6 ; size = 6
008DB020 . FF35 81638600 push dword ptr ; 程序初始化后dword ptr 里面就是VirtualFree函数的地址了
008DB026 . FFD0 call eax ; call刚得到的VirtualProtect的函数,使VirtualFree函数前6个字节可写可读,以便挂钩
008DB028 . A1 81638600 mov eax, dword ptr ; VirtualFree函数的地址给eax(开始保存api VirtualFree的前6个字节)
008DB02D . 8B08 mov ecx, dword ptr ; VirtualFree函数的前4个字节给ecx
008DB02F . 66:8B58 04 mov bx, word ptr ; VirtualFree函数的第5-第6个字节给bx
008DB033 . 890D B6B08D00 mov dword ptr , ecx ; 把得到的前6个字节保存起来,前4个字节保存到空地8DB0B6
008DB039 . 66:891D BAB08D00 mov word ptr , bx ; 把得到的前6个字节保存起来,第5-第6个字节保存到空地8DB0BA(保存前6个字节完毕)
008DB040 . C600 68 mov byte ptr , 68 ; 写下钩子,68是push的机器码(开始写钩子)
008DB043 . 40 inc eax ; 上面刚写完1个byte,所以要加1,继续写下面的
008DB044 . C700 55B08D00 mov dword ptr , 8DB055 ; 写上8DB055,让VirtualFree函数执行的时候返回到8DB055
008DB04A . 83C0 04 add eax, 4 ; 上面刚写完4个byte,所以要加4,继续写下面的
008DB04D . C600 C3 mov byte ptr , 0C3 ; 写上0C3,配合上面写入的push 8DB055就会回到8DB055,patch时机就到了(钩子写完毕)
008DB050 .- E9 A5B0F8FF jmp 008660FA ; 程序原来入口就是跳到008660FA开始执行的,我们照搬
;-------------------------钩子到了之后就会来到下面-----------------------
008DB055 . C705 7FED4E00 B8FFFFFF mov dword ptr , -48 ; VirtualFree函数执行的时候由于我们的钩子所以会来到这里,开始写入爆破的代码
008DB05F . C605 83ED4E00 FF mov byte ptr , 0FF ; 继续写入第5个,mov eax,-1总共是5个字节
008DB066 . 8B0D B6B08D00 mov ecx, dword ptr ; 把我们前面保存起来的VirtualFree函数的前4个字节给ecx(开始还原钩子)
008DB06C . 66:8B1D BAB08D00 mov bx, word ptr ; VirtualFree函数的第5-第6个字节给bx
008DB073 . A1 81638600 mov eax, dword ptr ; dword ptr 里面是VirtualFree函数的头部地址
008DB078 . 8908 mov dword ptr , ecx ; 把ecx里的VirtualFree函数的前4个字节给写回去
008DB07A . 83C0 04 add eax, 4 ; 上面写完4个字节,所以加4继续写下面的
008DB07D . 66:8918 mov word ptr , bx ; 把bx里的VirtualFree函数的第5-第6个字节给写回去(还原钩子完毕)
008DB080 . 83E8 04 sub eax, 4 ; 回到VirtualFree函数头部准备执行VirtualFree
008DB083 . 83C4 04 add esp, 4 ; 平栈
008DB086 . FFD0 call eax ; 这里call的就是VirtualFree函数了等于回到程序原路了
008DB088 . 68 07608600 push 866007 ; 原文件call VirtualFree之后就是回到866007的,我们照搬
008DB08D . C3 retn ; push+retn 都知道干嘛的吧
008DB08E 00 db 00
008DB08F 00 db 00
008DB090 00 db 00
008DB091 00 db 00
008DB092 . 6B 65 72 6E 65 6C 33 32 >ascii "kernel32.dll",0 ; 这个是自己写的
008DB09F 00 db 00
008DB0A0 00 db 00
008DB0A1 00 db 00
008DB0A2 . 56 69 72 74 75 61 6C 50 >ascii "VirtualProtect",0 ; 这个是自己写的
008DB0B1 00 db 00
008DB0B2 00 db 00
008DB0B3 00 db 00
008DB0B4 00 db 00
008DB0B5 00 db 00
008DB0B6 . 00000000 dd 00000000
008DB0BA . 0000 dw 0000
008DB0BC 00 db 00
008DB0BD 00 db 00
所有的代码我都写了注释,不要嫌我罗嗦,写的很土,可能还有错误的地方,请多多海涵,偶是文盲。
保存代码,在本机xp,虚拟机xp、win7都测试完毕,破解成功。
推销下偶的皮肤,有兴趣的找我。
GUC兄弟来吾爱第一篇破文,加精鼓励! 谢谢Hmily GG,Squn MM
Squn就是小芊芊啊? 没留下什么联系方式啊?怎么得到皮肤? 4# ericalan
还是直接发到这里好了,一个个发很麻烦。。。 你是牛魔王他大爷! 好文支持下,lz应该素来自upk的大侠啊。。。 这个得学,感谢感谢 本帖最后由 GUC 于 2009-12-17 12:05 编辑
澄清下
不知道昨天怎么回事,1级修复后不能跨平台,今天试了下,1级修复后是可以跨平台的,没那么复杂,2000 xp win7都能运行,怪异,应该是昨天哪里操作错误了。。。
太壳盲了,努力学习:dizzy:
=====
明白了,昨天1级修复后忘记再次点“Show Invalid”了,导致剪切的时候把1级修复成功修复的那部分iat也给切了,结果就等于跟没用1级修复一样,唉,粗心害死人。 拜读了。。。。
页:
[1]
2