好友
阅读权限10
听众
最后登录1970-1-1
|
GUC
发表于 2009-12-16 17:04
本帖最后由 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 [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都测试完毕,破解成功。
推销下偶的皮肤,有兴趣的找我。
|
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|