- UID
- 64840
注册时间2009-12-8
阅读权限10
最后登录1970-1-1
周游历练
该用户从未签到
|
原来我注册过这里的号啊。。。追踪hc、大Z,来PYG逛逛。。。
原版: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 [ebp+C]
004EED71 E8 B4FDFFFF call 004EEB2A
004EED76 50 push eax
004EED77 8B4D 08 mov ecx, dword ptr [ebp+8]
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 [00866375]和dword [00866371]),有这对搭档在足够我们干很多事了!乐啊
这里还已经有了KERNEL32.VirtualFree,在dword [00866381],可以直接拿来用(即使没有,咱们也可以通过LoadLibraryA跟GetProcAddress获取)。
强调,下面的代码里,KERNEL32.VirtualFree的地址dword [00866381]是直接拿来用的,不要看到dword [00866381]感到莫名其妙。。。
基本信息有了,咱们开工!
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 [866375] ; \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 [866371] ; \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 [866381] ; 程序初始化后dword ptr [866381]里面就是VirtualFree函数的地址了
008DB026 . FFD0 call eax ; call刚得到的VirtualProtect的函数,使VirtualFree函数前6个字节可写可读,以便挂钩
008DB028 . A1 81638600 mov eax, dword ptr [866381] ; VirtualFree函数的地址给eax(开始保存api VirtualFree的前6个字节)
008DB02D . 8B08 mov ecx, dword ptr [eax] ; VirtualFree函数的前4个字节给ecx
008DB02F . 66:8B58 04 mov bx, word ptr [eax+4] ; VirtualFree函数的第5-第6个字节给bx
008DB033 . 890D B6B08D00 mov dword ptr [8DB0B6], ecx ; 把得到的前6个字节保存起来,前4个字节保存到空地8DB0B6
008DB039 . 66:891D BAB08D00 mov word ptr [8DB0BA], bx ; 把得到的前6个字节保存起来,第5-第6个字节保存到空地8DB0BA(保存前6个字节完毕)
008DB040 . C600 68 mov byte ptr [eax], 68 ; 写下钩子,68是push的机器码(开始写钩子)
008DB043 . 40 inc eax ; 上面刚写完1个byte,所以要加1,继续写下面的
008DB044 . C700 55B08D00 mov dword ptr [eax], 8DB055 ; 写上8DB055,让VirtualFree函数执行的时候返回到8DB055
008DB04A . 83C0 04 add eax, 4 ; 上面刚写完4个byte,所以要加4,继续写下面的
008DB04D . C600 C3 mov byte ptr [eax], 0C3 ; 写上0C3,配合上面写入的push 8DB055就会回到8DB055,patch时机就到了(钩子写完毕)
008DB050 .- E9 A5B0F8FF jmp 008660FA ; 程序原来入口就是跳到008660FA开始执行的,我们照搬
;-------------------------钩子到了之后就会来到下面-----------------------
008DB055 . C705 7FED4E00 B8FFFFFF mov dword ptr [4EED7F], -48 ; VirtualFree函数执行的时候由于我们的钩子所以会来到这里,开始写入爆破的代码
008DB05F . C605 83ED4E00 FF mov byte ptr [4EED83], 0FF ; 继续写入第5个,mov eax,-1总共是5个字节
008DB066 . 8B0D B6B08D00 mov ecx, dword ptr [8DB0B6] ; 把我们前面保存起来的VirtualFree函数的前4个字节给ecx(开始还原钩子)
008DB06C . 66:8B1D BAB08D00 mov bx, word ptr [8DB0BA] ; VirtualFree函数的第5-第6个字节给bx
008DB073 . A1 81638600 mov eax, dword ptr [866381] ; dword ptr [866381]里面是VirtualFree函数的头部地址
008DB078 . 8908 mov dword ptr [eax], ecx ; 把ecx里的VirtualFree函数的前4个字节给写回去
008DB07A . 83C0 04 add eax, 4 ; 上面写完4个字节,所以加4继续写下面的
008DB07D . 66:8918 mov word ptr [eax], 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 于 2009-12-16 20:30 编辑 ] |
评分
-
查看全部评分
|