GUC 发表于 2009-12-16 20:29:04

..考研词汇 1.0 InlineHook API 爆破之解文

原来我注册过这里的号啊。。。追踪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
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            ImportKERNEL32.ExitProcess
00866371            ImportKERNEL32.GetProcAddress
00866375            ImportKERNEL32.LoadLibraryA
00866369            ImportUSER32.MessageBoxA
008DB000            Export<ModuleEntryPoint>
0086637D            ImportKERNEL32.VirtualAlloc
00866381            ImportKERNEL32.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 于 2009-12-16 20:30 编辑 ]

GGLHY 发表于 2009-12-16 20:37:55

呵呵,学习一下了!

Nisy 发表于 2009-12-16 21:11:45

不错 补区段来Patch关键点 VirtualFree利用的很好 /:good

wan 发表于 2009-12-16 21:33:44

热心团~~~希望多发好文多多来指点我等学习啊

hk35544 发表于 2009-12-16 21:54:20

好文章啊,学习了。

GUC 发表于 2009-12-16 22:03:16

原帖由 Nisy 于 2009-12-16 21:11 发表 https://www.chinapyg.com/images/common/back.gif
不错 补区段来Patch关键点 VirtualFree利用的很好 /:good
多谢nisy鼓励。

原帖由 wan 于 2009-12-16 21:33 发表 https://www.chinapyg.com/images/common/back.gif
热心团~~~希望多发好文多多来指点我等学习啊
你太谦虚了,我是来学习你们的。

1级修复后看着应该可以跨平台了,但2000跟win7都运行失败,不知道哪里问题,不跟了,不会解决跨平台问题。。。/:L

感觉应该差不多可以写一个Inline Patching PEX Tool了,整合点改入口和加区段的代码。
008DB088   .68 07608600            push    866007
这个返回的地址866007其实在钩子返回的时候可以在堆栈得到,mov r32,dword 再保存到buffer,结尾写push dword , retn,这样可以通用了。
想想觉得可行,但太菜没实力着手实现,而且PEX这壳实在太少见了,开发这个PEX通用补丁工具似乎没啥大的用武之地。

[ 本帖最后由 GUC 于 2009-12-16 22:37 编辑 ]

assume 发表于 2009-12-16 22:07:40

学习了,/:good

lacoucou 发表于 2009-12-16 23:10:16

加区段是不是还要重建PE,修改区段属性?这个新加的区段怎样让他在运行之前读取内存?

HDd1145 发表于 2009-12-17 02:43:32

非常需要学习

yayazhi 发表于 2009-12-17 08:33:47

很强大/:good
页: [1] 2 3
查看完整版本: ..考研词汇 1.0 InlineHook API 爆破之解文