带你经历破解的三重境界
程序员文章站
2024-01-09 17:41:42
破解,在很多人的眼里都觉得这个很神秘,对,的确神秘,因为懂的人不多,而且个人认为比编程还难学。
在正式开始之前,我们先来谈谈本文所谓的三重境界。第一重境界:爆破,基本属于菜鸟的专利,也是初学...
在正式开始之前,我们先来谈谈本文所谓的三重境界。第一重境界:爆破,基本属于菜鸟的专利,也是初学者所喜欢的方式。因为不需要你有很深的汇编功力,只要能用现成的查壳脱壳软件查壳脱壳,大概了解程序注册流程,能找到关键跳就OK了。这个阶段经常使用的工具是查壳工具、静态反汇编工具W32Dasm、C32Asm,程序修改工具UltraEdit等。第二重境界:追出注册码,编写注册机。在有了一定爆破经历和一些简单的汇编基础后,我们的菜鸟爆破手就可以升级为经验丰富的老鸟了。这个阶段经常用到的工具要在前一阶段的基础上增加动态反汇编程序OllyDBG和一些简单的注册机编辑工具Keymaker等。如果编写注册机的话,就要求有深厚的汇编功力,精湛的编程技术,能清楚分析出程序的注册流程和算法,并独立编写出程序算法注册机。第三重境界:逆向。本人没达到这一层次,写不出好的心得,骨灰级老鸟常玩的。介绍完三重境界后,你处于哪重境界,应该心里有数啦。好了,下面开始我们的旅程。
第一重境界:爆破
首先按软件破解的一般步骤:先查壳,有壳就脱壳,无壳当然最好了,然后分析、爆破。我们用常用的PEiD查这个CrackMe的壳,结果如图1所示。见到这种情况,不要匆忙下无壳的结论,再试试另外一种查壳工具,如DiE。我们用DiE试试,结果如图2所示,看看,加了ASPack 2.12壳,还好不是什么强壳。
图1
图2
下面对这个CrackMe脱壳。用OD载入程序,如图3所示,载入后点上一行的PUSHAD,明显表示加了壳,寄存器窗口的ESP变红了,我们用经典的ESP定律脱壳。
图3
右击ESP变红的数据,在弹出菜单中选“跟随到数据窗口”,然后在数据窗口右击D7,在弹出菜单中选“断点->硬件访问->Word”,下好断点后,在OD中运行,程序断在如下代码处。
004053B0 /75 08 JNZ SHORT crackme6.004053BA //断在这里 004053B2 |B8 01000000 MOV EAX,1 004053B7 |C2 0C00 RETN 0C 004053BA 68 CB114000 PUSH crackme6.004011CB 004053BF C3 RETN
当按F8单步向下,经过004053BF时,程序返回到了004011CB,这时大家要注意了,这一大块全是灰色,不要按F8继续,可在004011CB这一行右击,选“分析->从模块删除分析”。
004011CB 64 DB 64;CHAR d 004011CC A1 DB A1 004011CD 01 DB 01 004011CE 00 DB 00 004011CF 00 DB 00 004011D0 00 DB 00 004011D1 55 DB 55;CHAR U
看看,到达了光明之顶,程序的OEP出现了。
004011CB 64:A1 01000000 MOV EAX,DWORD PTR FS:[1] 004011D1 55 PUSH EBP //OEP 004011D2 89E5 MOV EBP,ESP 004011D4 6A FF PUSH -1
接下来,接触过破解的兄弟都知道怎样做了。对,用OD自带的插件DUMP掉。右击004011D1这一行,从弹出的菜单中选“用OllyDump脱壳调试进程”,弹出一个对话框,如图4所示,点“脱壳”保存文件,文件名为dump.exe。运行脱壳的文件,呀,不能运行,别紧张,修复一下就可以了。
图4
运行CrackMe,再运行Import Fix 1.6,选中CrackMe进程,在“OEP”中填入11CB,点“自动查找IAT”,然后再点“获取输入表”,发现“找到的输入表函数”中,只有一项,有问题。我们尝试将RAV改为3000,大小改为1000,OEP为11CB,再点“获取输入表”,结果如图5所示。将无效的指针剪切,然后点“修复转储文件”,选dump.exe,程序将自动生成dump_.exe,再运行dump_.exe就能运行了。看,这个壳脱起来就这么简单,下面我们进行爆破。
图5
先运行程序,试着注册看能不能找到有用的信息。运行程序,在用户名处输入lvcaolhx,在注册码处输入788559966,点Check,没反应,找不到有用的信息。这种情况下,我们要想到万能断点。用OD载入脱壳后的程序:
004011CB >/$ 64:A1 0100000>MOV EAX,DWORD PTR FS:[1] //载入后到这里 004011D1 |. 55 PUSH EBP 004011D2 |. 89E5 MOV EBP,ESP 004011D4 |. 6A FF PUSH -1
运行,输入lvcaolhx、788559966下万能断点,点运行。
77D3352D F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
//断在这里
注意看标题,程序到了User32领空,我们要返回程序领空,按ALT+F9。
0040153E |. 89C3 MOV EBX,EAX ;返回到这里
程序返回后,我们按F8单步前进,前进时注意观察寄存器窗口和信息窗口的内容,爆破的关键在于找到关键CALL,关键CALL后的跳转就是关键跳了,修改关键跳就可以达到爆破目的。下面我们粗略地看看这段代码,只有一个CALL,还有一个明显的标志位比较,不用说就是它了。
00401540 |. 09DB OR EBX,EBX;检查用户名是否为空 00401542 |. 75 04 JNZ SHORT unpacked.00401548 00401544 |. 31C0 XOR EAX,EAX 00401546 |. EB 50 JMP SHORT unpacked.00401598 00401548 |> BF BC020000 MOV EDI,2BC 0040154D |. BE 30000000 MOV ESI,30 00401552 |. B8 48000000 MOV EAX,48 00401557 |. 99 CDQ 00401558 |. F7FB IDIV EBX 0040155A |. 29C6 SUB ESI,EAX 0040155C |. 8D34B6 LEA ESI,DWORD PTR DS:[ESI+ESI*4] 0040155F |. 29F7 SUB EDI,ESI 00401561 |. 6BFF 6B IMUL EDI,EDI,6B 00401564 |. 81EF 6CCF0000 SUB EDI,0CF6C 0040156A |. 81FF 00230000 CMP EDI,2300 00401570 |. 7F 08 JG SHORT unpacked.0040157A 00401572 |. 81FF 90010000 CMP EDI,190 00401578 |. 7D 04 JGE SHORT unpacked.0040157E 0040157A |> 31C0 XOR EAX,EAX 0040157C |. EB 1A JMP SHORT unpacked.00401598 0040157E |> 8D85 00FFFFFF LEA EAX,DWORD PTR SS:[EBP-100] 00401584 |. 50 PUSH EAX 00401585 |. 53 PUSH EBX 00401586 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] 00401589 |. E8 77FDFFFF CALL unpacked.00401305 //关键CALL 0040158E |. 83C4 0C ADD ESP,0C 00401591 |. 09C0 OR EAX,EAX //标志位比较 00401593 74 03 JE SHORT unpacked.00401598
看到上面的代码,大家应该高兴,不错,下面的跳转就是关键跳了,尽情的改吧。
将“JE SHORT unpacked.00401598”NOP掉即可。修改操作为:选定00401593这一行,右击,选“二进制->使用NOP填充”,然后右击改过后的这一行,选“复制到可执行文件->所有修改”,在弹出的“复制选定内容到可执行文件”窗口中点“全部复制”,弹出“文件D...”窗口,关掉这个窗口,弹出保存文件窗口,输入文件名Cr_umpacked.exe,保存即可。
运行Cr-unpack.exe,任意输入Name和Serial值,看,成功了!如图6所示。好了,我们第一站的终点到了,下面继续朝第二站前进。
图6
第二重境界:追出注册码,编写注册机
这一阶段要面对大量的代码,复杂的跳转,希望大家耐心看下去。下面我们对CrackMe进行算法分析,用OD载入程序。
00405001 > E8 03000000 CALL crackme6.00405009//载入点 00405006 - E9 EB045D45 JMP 459D54F6 0040500B 55 PUSH EBP 0040500C C3 RETN
运行,输入lvcaolhx和788559966下万能断点,点运行,注意看标题,程序到了User32领空,我们要返回程序领空,按ALT+F9,然后F8单步前进,前进时注意观察寄存器窗口和信息窗口的内容。
00401539 E8 FA010000 CALL crackme6.00401738 ;JMP 到 GetDlgItemTextA 0040153E 89C3 MOV EBX,EAX;返回这里 00401540 09DB OR EBX,EBX;EBX为用户名长度,记为name_len 00401542 75 04 JNZ SHORT crackme6.00401548;用户名不空就跳,否则就挂 00401544 31C0 XOR EAX,EAX 00401546 EB 50 JMP SHORT crackme6.00401598
这几行代码就是检查用户名是否为空,如果是空,就挂掉了。
00401548 BF BC020000 MOV EDI,2BC ;EDI=2BC 0040154D BE 30000000 MOV ESI,30 ; ESI=30 00401552 B8 48000000 MOV EAX,48 ;EAX=48 00401557 99 CDQ 字符扩展 00401558 F7FB IDIV EBX ; EAX/namelen
这一句代码的意思是用EAX除以EBX,商放在EAX中,余数放在EDX中。注意一点,这里的数值都是十六进制。
0040155A 29C6 SUB