beijingren
发表于 2014-7-16 20:56:15
收藏了,最近在搞14版,略有进展,不过很缓慢,这些文字还是很有帮助的,再多看几遍。有研究这个的朋友希望能交流交流
阳光宅男
发表于 2014-7-16 21:08:42
学习了,分析的很棒,感谢分享了
findto
发表于 2014-7-22 22:58:17
学习~~~~~~~~~~~~~
beijingren
发表于 2014-8-25 16:57:08
补充一个UPK的:
【破解作者】 黄玉米
【使用工具】 peid,OD,ProtectionID,Die,XMemPatch
【破解平台】 WinXP
【软件名称】 职称计算机考试宝典
【下载地址】 受人之托,不知道哪儿下的!请自行搜索!
【软件简介】 未注册版功能试用仅限一条
【破解声明】 转载请保持完整!
===================================================================================
【破解内容】
1. 查壳
PEID查壳:啥没看见!
Die查壳:Delphi编译!
ProtectionID:[!] Safengine Licensor v1.7.2.0 (or newer) detected !
很牛!
OD一载入即退出!装上StrongOD插件,终于能载入了!入口是一CALL,F7进去,从堆栈最顶跟随到数据区,有一字符串:Safengine Protector v1.8.0.0,看样子这才是真正的壳名,这个壳名其实就存在入口那个CALL后面。这类壳其实没啥技术,就是用海量的垃圾代码消耗破解者的精力,纯属一种无耻的疲劳战术。因为垃圾代码太多,只能一些价值不大的小程序使用,大程序用了岂不累死,还干活不。由于有SDK,要想脱壳、修复,恐怕要让人崩溃。
退出杀毒软件、QQ,减少意外死亡的机会。否则会时不时提醒你有监视器或调试工具。
如果程序提示发现有调试工具了,先独立运行程序,再用OD挂接(有人叫附加),终止后再载入就可以了。
另外不要用Ctrl-G,好像某些插件有冲突。一用就导致OD死亡。劳驾手动去你想去的地方。
还有,只能用硬件断点。其它断点可以临时用一下,小范围内跟踪可用。一则容易被发现,二则重载就没有了。
2. 查找注册码算法
鉴于前面所述,脱壳就免了。因为注册码验证过程淹没在垃圾代码海洋中,所以无意跟踪其过程。直接破解。
OD载入后,直接运行。
随手敲了两个数字,点“注册”,提示“您输入的注册码不正确,请正确填写注册码!”
有提示就好办了!
进入模块USER32.DLL,Ctrl-N查找函数名称,找到MessageBoxA函数,双击来到其入口,F2下断点。
输入一串数字,进行注册,断下,看堆栈:
0012ED48 004C7E7E/CALL 到 MessageBoxA 来自 OSTeache.004C7E79
0012ED4C 000C0828|hOwner = 000C0828 ('填写注册信息',class='TfrmUserRegInfo')
0012ED50 00561DAC|Text = "注册失败:您输入的注册码不正确。如果您还没有购买注册码,请联系我们购买!如要试用,请先关闭此窗口。"
0012ED54 00501AD8|Title = "提示"
0012ED58 00000040\Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
┊
双击堆栈顶部,来到程序空间004C7E7E处。往前找入口:
004C7D80 55 PUSH EBP
004C7D81 8BEC MOV EBP,ESP
004C7D83 83C4 A8 ADD ESP,-58
004C7D86 53 PUSH EBX
004C7D87 56 PUSH ESI
004C7D88 57 PUSH EDI
004C7D89 894D F8 MOV DWORD PTR SS:,ECX
004C7D8C 8BFA MOV EDI,EDX
┊
┊
┊
在入口004C78D0下硬件断点(硬件断点的好处是如果意外死亡,下次重载还在,省得反复这样找。因为这个壳加的程序死亡后,OD的断点、注释都会消失,一切都得重来。),取消MessageBoxA的断点,再进行注册,断下,堆栈:
0012EDD0 00501AB6返回到 OSTeache.00501AB6 来自 OSTeache.004C7D80
0012EDD4 00000040
0012EDD8 0012EDF0指向下一个 SEH 记录的指针
0012EDDC 00501ACCSE 处理器
┊
双击堆栈顶部,来到程序空间00501AB6处。往前找入口:
00561C7C 55 PUSH EBP
00561C7D 8BEC MOV EBP,ESP
00561C7F 81C4 FCFDFFFF ADD ESP,-204
00561C85 53 PUSH EBX
┊
┊
┊
在入口00561C7C下硬件断点,重新注册,断下:
00561C7C 55 PUSH EBP
00561C7D 8BEC MOV EBP,ESP
00561C7F 81C4 FCFDFFFF ADD ESP,-204
00561C85 53 PUSH EBX
00561C86 33D2 XOR EDX,EDX
00561C88 8955 FC MOV DWORD PTR SS:,EDX
00561C8B 8BD8 MOV EBX,EAX
00561C8D 33C0 XOR EAX,EAX
00561C8F 55 PUSH EBP
00561C90 68 281D5600 PUSH OSTeache.00561D28
00561C95 64:FF30 PUSH DWORD PTR FS:
00561C98 64:8920 MOV DWORD PTR FS:,ESP
00561C9B 8BD3 MOV EDX,EBX ; 注册码
00561C9D A1 900D6300 MOV EAX,DWORD PTR DS: ; TSoftReg
00561CA2 E8 79D9FFFF CALL OSTeache.0055F620 ; 将注册码写入数据库
00561CA7 8D45 FC LEA EAX,DWORD PTR SS:
00561CAA E8 B9E3FFFF CALL OSTeache.00560068 ; 计算机器码
00561CAF E8 B8F7FFFF CALL OSTeache.0056146C ; 创建文件temp.db
00561CB4 8D85 FCFEFFFF LEA EAX,DWORD PTR SS:
00561CBA 8BD3 MOV EDX,EBX ; 注册码
00561CBC B9 FF000000 MOV ECX,0FF
00561CC1 E8 BA3CEAFF CALL OSTeache.00405980 ; 将注册码移到处
00561CC6 8D85 FCFEFFFF LEA EAX,DWORD PTR SS: ; 注册码
00561CCC 50 PUSH EAX
00561CCD 8D85 FCFDFFFF LEA EAX,DWORD PTR SS:
00561CD3 8B55 FC MOV EDX,DWORD PTR SS: ; 机器码
00561CD6 B9 FF000000 MOV ECX,0FF
00561CDB E8 A03CEAFF CALL OSTeache.00405980 ; 将机器码移到处
00561CE0 8D85 FCFDFFFF LEA EAX,DWORD PTR SS:
00561CE6 5A POP EDX
00561CE7 E8 80F5FFFF CALL OSTeache.0056126C ; 跟入
00561CEC 8BD8 MOV EBX,EAX
00561CEE 84DB TEST BL,BL
00561CF0 74 16 JE SHORT OSTeache.00561D08 ; 跳则提示注册失败
┊
┊
┊
-----------------------------------------------------------------------
跟入00561CE7 E8 80F5FFFF CALL OSTeache.0056126C到此:
┊
┊
┊
005612B3 33DB XOR EBX,EBX
005612B5 8BC6 MOV EAX,ESI
005612B7 E8 E8F9FFFF CALL OSTeache.00560CA4 ; 验证机器码
005612BC 84C0 TEST AL,AL
005612BE 0F84 26010000 JE OSTeache.005613EA ; 跳则提示注册失败
005612C4 8BC7 MOV EAX,EDI ; 注册码
005612C6 E8 31F8FFFF CALL OSTeache.00560AFC ; 跟入
005612CB 84C0 TEST AL,AL
005612CD 0F84 17010000 JE OSTeache.005613EA ; 跳则提示注册失败
┊
┊
┊
--------------------------------------
跟入005612C6 E8 31F8FFFF CALL OSTeache.00560AFC到此:
┊
┊
┊
00560BE1 8D85 F0FEFFFF LEA EAX,DWORD PTR SS:
00560BE7 50 PUSH EAX
00560BE8 8D85 ECFEFFFF LEA EAX,DWORD PTR SS:
00560BEE E8 75F4FFFF CALL OSTeache.00560068 ; 计算 机器码
00560BF3 8B85 ECFEFFFF MOV EAX,DWORD PTR SS: ; 机器码
00560BF9 B9 01000000 MOV ECX,1
00560BFE BA 0D000000 MOV EDX,0D
00560C03 E8 D44FEAFF CALL OSTeache.00405BDC ; 取最后一位
00560C08 8B85 F0FEFFFF MOV EAX,DWORD PTR SS: ; 最后一位
00560C0E BA A00C5600 MOV EDX,OSTeache.00560CA0
00560C13 E8 F44EEAFF CALL OSTeache.00405B0C ; 比较
00560C18 75 38 JNZ SHORT OSTeache.00560C52 ; 跳则注册失败
00560C1A 803E 1E CMP BYTE PTR DS:,1E ; 注册码长度与1E比较
00560C1D 76 2D JBE SHORT OSTeache.00560C4C ; 跳则注册失败
00560C1F 8D85 E4FEFFFF LEA EAX,DWORD PTR SS:
00560C25 8BD6 MOV EDX,ESI ; 注册码
00560C27 E8 004DEAFF CALL OSTeache.0040592C
00560C2C 8B85 E4FEFFFF MOV EAX,DWORD PTR SS: ; 注册码
00560C32 8D95 E8FEFFFF LEA EDX,DWORD PTR SS:
00560C38 E8 030C0000 CALL OSTeache.00561840 ; 将注册码移到
00560C3D 8B85 E8FEFFFF MOV EAX,DWORD PTR SS: ; 注册码
00560C43 E8 C80D0000 CALL OSTeache.00561A10 ; 跟入
00560C48 84C0 TEST AL,AL
00560C4A 75 04 JNZ SHORT OSTeache.00560C50 ; 不跳则注册失败
00560C4C 33DB XOR EBX,EBX
00560C4E EB 02 JMP SHORT OSTeache.00560C52
00560C50 B3 01 MOV BL,1
00560C52 33C0 XOR EAX,EAX
┊
┊
┊
--------------------------------------
-----------------------------------------------------------------------
从前面这段过程过程可以看出,注册码的长度不得小于31位,注册码除最后一位外其他位的ASCII码求和,和的最后一位应与注册码最后一位相等。
用“12345678900987654321123456789003”进行注册,提示成功,要求重新运行。看样子有重启验证。
重启后,标题已变成正式版了,但功能依然受限。
3. 进行爆破
删除OD所有断点,进入00401000的TXT段(因为加密,程序一般都不在这里运行。在堆栈中找一位于该段的地址,双击即进入了),查找字符串(别的段是找不到有用的),找出好多,有兴趣的话可以好好研究。其中有一行:
0055F6F1 MOV EDX,OSTeache.0055F76C SELECT FROM
从字面意思上看似乎是从数据库取注册码。双击到达0055F6F1,下硬件断点。重载,断下。
┊
┊
┊
0055F6F1 BA 6CF75500 MOV EDX,OSTeache.0055F76C ; ASCII "SELECT FROM "
0055F6F6 E8 69E5FFFF CALL OSTeache.0055DC64
0055F6FB 8945 FC MOV DWORD PTR SS:,EAX
0055F6FE 33C0 XOR EAX,EAX
0055F700 55 PUSH EBP
0055F701 68 40F75500 PUSH OSTeache.0055F740
0055F706 64:FF30 PUSH DWORD PTR FS:
0055F709 64:8920 MOV DWORD PTR FS:,ESP
0055F70C 8B45 FC MOV EAX,DWORD PTR SS:
0055F70F 8378 08 00 CMP DWORD PTR DS:,0
0055F713 76 0F JBE SHORT OSTeache.0055F724
0055F715 8BCE MOV ECX,ESI
0055F717 BA 98F75500 MOV EDX,OSTeache.0055F798 ; ASCII "RegNum"
0055F71C 8B45 FC MOV EAX,DWORD PTR SS:
0055F71F E8 F4EDFFFF CALL OSTeache.0055E518
0055F724 33C0 XOR EAX,EAX
┊
┊
┊
删除硬件断点,一路跟踪到达
┊
┊
┊
004059B4 8B08 MOV ECX,DWORD PTR DS:
004059B6 85C9 TEST ECX,ECX
004059B8^ 0F84 4EFDFFFF JE OSTeache.0040570C
┊
┊
┊
在004059B6下硬件断点,不停F9,同时监视,当出现下列字串时停止:
SELECT ,,,,,,,,,,,, FROM ORDER BY TestID LIMIT 1 8BC7FD823DDCBCA3
注意那个“ LIMIT 1 ”这应该就是限制使用一条的地方了。用0填充试运行一下,确实去限制了。
删除硬件断点。现在依照前面的反推法,从堆栈反查找到一个入口00589B10,在此处下硬件断点。重载运行。断下:
00589B10 55 PUSH EBP
00589B11 8BEC MOV EBP,ESP
00589B13 53 PUSH EBX
00589B14 56 PUSH ESI
00589B15 57 PUSH EDI
00589B16 8BF9 MOV EDI,ECX
00589B18 8BF2 MOV ESI,EDX
00589B1A 8BD8 MOV EBX,EAX
┊
┊
┊
从堆栈可以看出,程序是从加密段里到此的。而就是字串SELECT ,,,,,,,,,,,, FROM ORDER BY TestID LIMIT 1 8BC7FD823DDCBCA3。
好,我们现在开始爆破。我们先改该入口的代码,将其跳向本段代码末尾的空白处:
00589B10 /E9 EBE31500 JMP OSTeache.006E7F00 ; 跳向末尾空白
00589B15 |57 PUSH EDI
00589B16 |8BF9 MOV EDI,ECX
00589B18 |8BF2 MOV ESI,EDX
┊
┊
┊
再到末尾,写如下代码:
006E7EF6 204C494D495420312000 ; “ LIMIT 1 ”,用于查找比较
006E7F00 55 PUSH EBP ; 原入口语句
006E7F01 8BEC MOV EBP,ESP
006E7F03 53 PUSH EBX
006E7F04 56 PUSH ESI
006E7F05 53 PUSH EBX ; 保护现场
006E7F06 51 PUSH ECX
006E7F07 52 PUSH EDX
006E7F08 56 PUSH ESI
006E7F09 57 PUSH EDI
006E7F0A 8BD8 MOV EBX,EAX ; 取需修改的字串
006E7F0C BE F67E6E00 MOV ESI,OSTeache.006E7EF6 ; ASCII " LIMIT 1 "
006E7F11 BF 09000000 MOV EDI,9 ; 长度
006E7F16 43 INC EBX
006E7F17 8A4B FF MOV CL,BYTE PTR DS:
006E7F1A 8A16 MOV DL,BYTE PTR DS:
006E7F1C 3ACA CMP CL,DL
006E7F1E^ 75 F6 JNZ SHORT OSTeache.006E7F16 ; 先找到第一位,即空格,找到了不跳
006E7F20 46 INC ESI
006E7F21 43 INC EBX
006E7F22 4F DEC EDI
006E7F23 85FF TEST EDI,EDI
006E7F25 74 10 JE SHORT OSTeache.006E7F37 ; 9位全比较对了即跳
006E7F27 8A4B FF MOV CL,BYTE PTR DS:
006E7F2A 8A16 MOV DL,BYTE PTR DS:
006E7F2C 3ACA CMP CL,DL
006E7F2E^ 74 F0 JE SHORT OSTeache.006E7F20 ; 循环比较“ LIMIT 1 ”每位
006E7F30 83EB 09 SUB EBX,9
006E7F33 03DF ADD EBX,EDI
006E7F35^ EB D5 JMP SHORT OSTeache.006E7F0C ; 去找下一个空格
006E7F37 83EB 0A SUB EBX,0A ; “ LIMIT 1 ”的位置
006E7F3A C703 00000000 MOV DWORD PTR DS:,0 ; 置0
006E7F40 5F POP EDI ; 恢复现场
006E7F41 5E POP ESI
006E7F42 5A POP EDX
006E7F43 59 POP ECX
006E7F44 5B POP EBX
006E7F45^ E9 CB1BEAFF JMP OSTeache.00589B15 ; 回原入口下一句
运行,全部限制没有了。爆破成功。
4. 制作补丁
由于程序运行会对原程序进行校验,所以不能修改原程序,只能制作内存补丁了。
运行XMemPatch。添加如下数据:
内存地址 原始指令 修改指令
00589B10 558BEC53 E9EBE315
00589B14 56578BF9 00578BF9
006E7EF6 00000000 204C494D
006E7EFA 00000000 49542031
006E7EFE 00000000 2000558B
006E7F02 00000000 EC535653
006E7F06 00000000 51525657
006E7F0A 00000000 8BD8BEF6
006E7F0E 00000000 7E6E00BF
006E7F12 00000000 09000000
006E7F16 00000000 438A4BFF
006E7F1A 00000000 8A163ACA
006E7F1E 00000000 75F64643
006E7F22 00000000 4F85FF74
006E7F26 00000000 108A4BFF
006E7F2A 00000000 8A163ACA
006E7F2E 00000000 74F083EB
006E7F32 00000000 0903DFEB
006E7F36 00000000 D583EB0A
006E7F3A 00000000 C7030000
006E7F3E 00000000 00005F5E
006E7F42 00000000 5A595BE9
006E7F46 00000000 CB1BEAFF
生成EXE补丁。由于原程序启动时间较长,等程序界面出来,有可能补丁已运行完毕了,这就达不到目的了。我们改一下补丁:
用OD载入补丁,跟踪到此:
┊
┊
┊
004014BD|.6A 10 |PUSH 10
004014BF|.FFD7 |CALL EDI ;kernel32.Sleep
┊
┊
┊
004014BD处PUSH的是补丁等待的时间,原来只有十六秒,有点儿短。我们将改为100秒应该够了吧:
004014BD|.6A 64 |PUSH 64
004014BF|.FFD7 |CALL EDI ;kernel32.Sleep
保存,运行。成功。
heizihui
发表于 2014-8-28 16:52:57
谢谢收集,,,我再看看 那个 限制
bansjs
发表于 2014-8-28 19:39:09
嘿嘿,2015版考试宝典破解版的我都有,论坛里面还有一个破解文章,可惜权限不够,看不了,唉!!!
beijingren
发表于 2014-8-28 20:03:42
bansjs 发表于 2014-8-28 19:39
嘿嘿,2015版考试宝典破解版的我都有,论坛里面还有一个破解文章,可惜权限不够,看不了,唉!!!
膜拜大神~~~~可以问下怎么做到的么?
heizihui
发表于 2014-8-28 22:02:37
bansjs 发表于 2014-8-28 19:39
嘿嘿,2015版考试宝典破解版的我都有,论坛里面还有一个破解文章,可惜权限不够,看不了,唉!!!
能讲解一下吗???
heizihui
发表于 2014-8-28 22:05:47
bansjs 发表于 2014-8-28 19:39
嘿嘿,2015版考试宝典破解版的我都有,论坛里面还有一个破解文章,可惜权限不够,看不了,唉!!!
发一份出来吧
bansjs
发表于 2014-8-28 23:24:52
本帖最后由 bansjs 于 2014-8-28 23:27 编辑
今天研究了一天的成果: