【 关键词 】: 英语软件,英语通,注册码,注册,算法,破解,绿色,注册机,英语听力软件
【文章作者】: 黄仁来
【作者邮箱】: futuring@126.com
【作者主页】: http://hi.baidu.com/beyond0769
【软件名称】: 《UP英语通》V2.16
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
并不是跟这个软件过不去要这么做,而是太喜欢这个软件了。首先它提供丰富的教程内容,最令我欣赏的是朗读过程一句一句,清清楚楚,标准真人发音,对于学习英语口语和听力的同学来说,这个软件确实是不可多得的。惜没有注册的只能用很少一部分教材,因此,便尝试解开它的算法。但是还没有开始就碰了一脸灰:程序在启动过程中有父进程检测、主程序的CRC32校验、Dll文件的完整性检测加上一个现在还未弄懂的算法注册检测。
算法就暂时不去研究那么多,反而对如何突破它的各种检测很感兴趣。于是就有了下文:
第一步:脱壳子
PEid查得:ASPack 2.12 -> Alexey Solodovnikov,压缩壳,很容易就脱掉,这里略过。 ========================================================================================
第二步:去父进程检测。
脱壳后用汉化版OD加载运行,只见OD一闪,就不见了,明显是进行了父进程的检测。以前有过经验,可以用“野猪OD”注入Explorer运行就可以了;但今天偏要用非野猪版本OD弄它。
几种方法可以达到程序检测父进程的过程。
重新OD载入,停在入口处:
005904A4 > $ 55 PUSH EBP ; 加载后OD停在这里
005904A5 . 8BEC MOV EBP,ESP
005904A7 . 83C4 F0 ADD ESP,-10
005904AA . 53 PUSH EBX
005904AB . 56 PUSH ESI
005904AC . B8 2CFD5800 MOV EAX,p51877_.0058FD2C
005904B1 . E8 D266E7FF CALL p51877_.00406B88
005904B6 . 8B35 08685A00 MOV ESI,DWORD PTR DS:[5A6808] ; p51877_.005A7C1C
005904BC . E8 03FEF1FF CALL p51877_.004B02C4 ; 单步到这里,F7进入,否则OD被关闭。
005904C1 . E8 EA00F2FF CALL p51877_.004B05B0
005904C6 . 84C0 TEST AL,AL
005904C8 . 74 02 JE SHORT p51877_.005904CC
005904CA >- EB FE JMP SHORT p51877_.005904CA
005904CC > 33C9 XOR ECX,ECX
=======================================
004B02C4 /$ 55 PUSH EBP ; 父进程检测过程
004B02C5 |. 8BEC MOV EBP,ESP ; 向下F8单步
004B02C7 |. 81C4 84F8FFFF ADD ESP,-77C
004B02CD |. 53 PUSH EBX
……以下省略N代码……
004B0347 |. 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10]
004B034A |. B9 94054B00 MOV ECX,p51877_.004B0594 ; \explorer.exe
004B034F |. E8 4044F5FF CALL p51877_.00404794 ; 获得exoplorer的绝对路径
……以下省略N代码……
004B04DF |. E8 B043F5FF |CALL p51877_.00404894
004B04E4 |. 75 09 |JNZ SHORT p51877_.004B04EF
004B04E6 |. 8B85 CCFEFFFF |MOV EAX,DWORD PTR SS:[EBP-134]
004B04EC |. 8945 F8 |MOV DWORD PTR SS:[EBP-8],EAX ; 循环读取本程序的进程ID及以Explorer的进程ID
004B04EF |> 8D85 E8FEFFFF |LEA EAX,DWORD PTR SS:[EBP-118]
004B04F5 |. 33C9 |XOR ECX,ECX
004B04F7 |. BA 04010000 |MOV EDX,104
004B04FC |. E8 A72AF5FF |CALL p51877_.00402FA8
004B0501 |. 8D95 C4FEFFFF |LEA EDX,DWORD PTR SS:[EBP-13C]
004B0507 |. 8BC6 |MOV EAX,ESI
004B0509 |. E8 D6ECFFFF |CALL p51877_.004AF1E4
004B050E |. 83F8 01 |CMP EAX,1
004B0511 |. 1BDB |SBB EBX,EBX
004B0513 |. 43 |INC EBX
004B0514 |> 84DB TEST BL,BL
004B0516 |.^ 0F85 9FFEFFFF \JNZ p51877_.004B03BB
004B051C |. 85F6 TEST ESI,ESI
004B051E |. 76 06 JBE SHORT p51877_.004B0526
004B0520 |. 56 PUSH ESI ; /hObject
004B0521 |. E8 C268F5FF CALL <JMP.&kernel32.CloseHandle> ; \CloseHandle
004B0526 |> 3B7D F8 CMP EDI,DWORD PTR SS:[EBP-8] ; EDI=Explorer进程ID,[EBP-8]=本程序进程ID,在这里进行进程的ID比较
004B0529 74 17 JE SHORT p51877_.004B0542 ; 关键跳转,修改JE为JMP跳过TerminateProcess函数
004B052B |. 6A 00 PUSH 0 ; /ExitCode = 0
004B052D |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; |
004B0530 |. 50 PUSH EAX ; |hProcess (父进程ID)
004B0531 |. E8 526CF5FF CALL <JMP.&kernel32.TerminateProcess> ; \TerminateProcess
……以下省略N代码……
004B057C \. C3 RETN
原理十分简单,循环读取当前所有进程的ID,把Exporer.exe和自身进程ID进行比较,如果相等则通过,否则把父进程关闭,同时把自己关闭。
用Delphi还原即以下:
{ 注意加载TlHelp32.pas单元 }
procedure CheckParentProc;
var //检查自己的进程的父进程
Pn: TProcesseNtry32;
sHandle: THandle;
H, ExplProc, ParentProc: Hwnd;
Found: Boolean;
Buffer: array[0..1023] of Char;
Path: string;
begin
H := 0;
ExplProc := 0;
ParentProc := 0;
//得到Windows的目录
SetString(Path,Buffer,GetWindowsDirectory(Buffer, Sizeof(Buffer) - 1));
Path := UpperCase(Path) + '\Explorer\.exe'; //得到Explorer的路径
sHandle := CreateToolHelp32SnapShot(TH32CS_SNAPALL, 0); //得到所有进程的列表快照
Found := Process32First(sHandle, Pn); //查找进程
while Found do //遍历所有进程
begin
if Pn.szExeFile = ParamStr(0) then //自己的进程
begin
ParentProc := Pn.th32ParentProcessID; //得到父进程的进程ID
H := OpenProcess(PROCESS_ALL_ACCESS, True, Pn.th32ParentProcessID); //父进程的句柄
end
else if UpperCase(Pn.szExeFile) = Path then
ExplProc := Pn.th32ProcessID; //Explorer的PID
Found := Process32Next(sHandle, Pn); //查找下一个
end;
//父进程不是Explorer,是调试器……
if ParentProc <> ExplProc then
begin
TerminateProcess(H, 0); //杀之!
Close; //好在作者没有在这里继续加入病毒代码。
end;
end;
这种伎俩在很多软件自我保护中已经在应用,早已被N多Cracker们研究透,基本上已经失去保护能力了。
========================================================================================
第三步:突破文件大小对比。
突破父进程后,重新OD载入,却出现一个大大的红叉叉,如图:
看来这是作者友善的提示,看到它第一反应便猜到它对文件大小或者属性等进行了检测,
于是OD重新加载,在命令行里输入 bp CreateFileA 回车进行内存下断,尝试捕获它读取文件的动作,按F9马上被中断,
总共连续按F9七次,就会出现错误对话框,于是重新载入,bp CreateFileA后按六次F9,停下。然后按 alt + F9 回到程序领空。再按一次 Alt + F10 跳出到以下过程:
0049CE24 /$ 53 PUSH EBX ; 文件大小校验过程
0049CE25 |. 56 PUSH ESI
……以下省略N代码……
0049CF19 |. 8B46 78 MOV EAX,DWORD PTR DS:[ESI+78]
0049CF1C |. E8 1FE9FFFF CALL p51877_1.0049B840 ; 对备份文件进行(文件名.dat)大小进行检测
0049CF21 |. 84C0 TEST AL,AL
0049CF23 |. 75 04 JNZ SHORT p51877_1.0049CF29
0049CF25 |> 33C0 XOR EAX,EAX
0049CF27 |. EB 02 JMP SHORT p51877_1.0049CF2B
0049CF29 |> B0 01 MOV AL,1
0049CF2B |> 8846 70 MOV BYTE PTR DS:[ESI+70],AL
0049CF2E |. 807E 38 00 CMP BYTE PTR DS:[ESI+38],0
0049CF32 |. 74 5E JE SHORT p51877_1.0049CF92 ; 爆破点之一,改为JMP直接跳过错误对话框
0049CF34 |. 807E 3B 00 CMP BYTE PTR DS:[ESI+3B],0
0049CF38 |. 74 58 JE SHORT p51877_1.0049CF92 ; 此处也可以爆
0049CF3A |. 807E 70 00 CMP BYTE PTR DS:[ESI+70],0
……以下省略N代码……
0049CF8A |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
0049CF8C |. 59 POP ECX
0049CF8D |. E8 4AD3FFFF CALL p51877_1.0049A2DC ; 这里弹出错误对话框:“文件被非法修改……”
0049CF92 |> 66:837E 52 00 CMP WORD PTR DS:[ESI+52],0
……以下省略N代码……
0049CFA8 \. C3 RETN
很明显,0049CF32和0049CF38处,只要把JE指令改成JMP即可跳过出错提示,搞定这一关。
========================================================================================
第四步:突破CRC32校验。
紧接着继续运行,却发现又弹出一个错误对话框,
看来作者在保护自己软件上真是花了不少心机。
重新加载,运行到上述第三步过程最后, 0049CFA8 处继续跳出该过程,即可来到
005904F3 . E8 2CC9F0FF CALL p51877_1.0049CE24 ; 第三步的文件大小校验过程
005904F8 . 8BC3 MOV EAX,EBX ; 继续单步向下。
005904FA . E8 3931E7FF CALL p51877_1.00403638
……以下省略N代码……
00590517 >- EB FE JMP SHORT p51877_1.00590517
00590519 > E8 7EFAF1FF CALL p51877_1.004AFF9C ; F8单步过会弹出CRC32校验错误提示,F7进入分析
0059051E . 84C0 TEST AL,AL
00590520 . 0F84 C2000000 JE p51877_1.005905E8
00590526 . B2 01 MOV DL,1
00590528 . A1 D4AA5700 MOV EAX,DWORD PTR DS:[57AAD4]
0059052D . E8 2EA6FEFF CALL p51877_1.0057AB60
F7进入CALL 004AFF9C 处看看,好戏在里面:
004AFF9C /$ 55 PUSH EBP ; 系列文件校验过程
004AFF9D |. 8BEC MOV EBP,ESP
004AFF9F |. B9 07000000 MOV ECX,7
……以下省略N代码……
004B00B9 |. E8 8A48F5FF CALL p51877_1.00404948
004B00BE |. 50 PUSH EAX
004B00BF |. E8 10EBFFFF CALL <JMP.&makelib.FileVerionCheck> ; 文件版本检查?
004B00C4 |. 59 POP ECX
004B00C5 |. 66:8945 FE MOV WORD PTR SS:[EBP-2],AX
004B00C9 |> 66:817D FE A0>CMP WORD PTR SS:[EBP-2],4FA0
004B00CF |. 74 5E JE SHORT p51877_1.004B012F
004B00D1 |. 8D45 D4 LEA EAX,DWORD PTR SS:[EBP-2C]
004B00D4 |. 50 PUSH EAX
004B00D5 |. 8D45 D0 LEA EAX,DWORD PTR SS:[EBP-30]
004B00D8 |. 50 PUSH EAX
004B00D9 |. 68 40024B00 PUSH p51877_1.004B0240 ; ASCII "anfei.com"
004B00DE |. A1 C04B5A00 MOV EAX,DWORD PTR DS:[5A4BC0]
004B00E3 |. E8 6048F5FF CALL p51877_1.00404948
004B00E8 |. 50 PUSH EAX
004B00E9 |. E8 06EBFFFF CALL <JMP.&ToolLIB.ECKeyCode>
004B00EE |. 83C4 08 ADD ESP,8
004B00F1 |. 8945 E0 MOV DWORD PTR SS:[EBP-20],EAX ; ||
004B00F4 |. C645 E4 06 MOV BYTE PTR SS:[EBP-1C],6 ; ||
004B00F8 |. 8D55 E0 LEA EDX,DWORD PTR SS:[EBP-20] ; ||
004B00FB |. 33C9 XOR ECX,ECX ; ||
004B00FD |. B8 54024B00 MOV EAX,p51877_1.004B0254 ; ||ASCII "%s"
004B0102 |. E8 81A8F5FF CALL p51877_1.0040A988 ; |\p51877_1.0040A988
004B0107 |. 8B45 D0 MOV EAX,DWORD PTR SS:[EBP-30] ; |
004B010A |. 0FB755 FE MOVZX EDX,WORD PTR SS:[EBP-2] ; |
004B010E |. 8955 E0 MOV DWORD PTR SS:[EBP-20],EDX ; |
004B0111 |. C645 E4 00 MOV BYTE PTR SS:[EBP-1C],0 ; |
004B0115 |. 8D55 E0 LEA EDX,DWORD PTR SS:[EBP-20] ; |
004B0118 |. 33C9 XOR ECX,ECX ; |
004B011A |. E8 69A8F5FF CALL p51877_1.0040A988 ; \p51877_1.0040A988
004B011F |. 8B55 D4 MOV EDX,DWORD PTR SS:[EBP-2C]
……以下省略N代码……
004B01B6 |. B9 80024B00 MOV ECX,p51877_1.004B0280
004B01BB |. E8 D445F5FF CALL p51877_1.00404794
004B01C0 |> 837D F4 00 CMP DWORD PTR SS:[EBP-C],0
004B01C4 |. 74 2B JE SHORT p51877_1.004B01F1 ; 关键跳转,改为JMP,跳过下面错误提示。
004B01C6 |. 6A 00 PUSH 0
004B01C8 |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
004B01CB |. E8 7847F5FF CALL p51877_1.00404948
004B01D0 |. 8BD0 MOV EDX,EAX
004B01D2 |. B9 88024B00 MOV ECX,p51877_1.004B0288 ; ASCII "Error" //错误对话框出现
004B01D7 |. A1 08685A00 MOV EAX,DWORD PTR DS:[5A6808]
……以下省略N代码……
004B0215 |. E8 9242F5FF CALL p51877_1.004044AC
004B021A \. C3 RETN
原来只需要把004B01C4处的JE改成JMP跳过错误提示即可突破这一层防线。OK,这时候可以把主程序保存为一个新文件了,暂时命名为p51877_1.exe吧。
试一下直接运行,没问题,没有出现错误对话框了。
========================================================================================
第五步:突破NAG注册窗口提示!
虽然没有了错误提示,真正的好戏还在后头,出现了注册窗口,这一关看怎么过?如图:
我的想法并非搞它的算法,而是把这个窗口当NAG窗口来去掉。我们继续在完成上一步后,跳出 CALL 004AFF9C(系列文件校验过程),
来到以下代码我们继续F8前进,看有没有什么新发现。
00590519 > \E8 7EFAF1FF CALL p51877_1.004AFF9C ; F8跳过会弹出CRC32校验错误提示,F7进入分析
0059051E . 84C0 TEST AL,AL
00590520 . 0F84 C2000000 JE p51877_1.005905E8
……以下省略N代码……
00590591 . E8 369BF0FF CALL p51877_1.0049A0CC
00590596 . 8B0D CC685A00 MOV ECX,DWORD PTR DS:[5A68CC] ; p51877_1.005A8A14
0059059C . 8B06 MOV EAX,DWORD PTR DS:[ESI]
0059059E . 8B15 A40B5800 MOV EDX,DWORD PTR DS:[580BA4] ; p51877_1.00580BF0
005905A4 . E8 239BF0FF CALL p51877_1.0049A0CC ; F8单步至此,将弹出注册窗口,必须F7进入
005905A9 . 8B0D E0635A00 MOV ECX,DWORD PTR DS:[5A63E0] ; p51877_1.005A8A1C
005905AF . 8B06 MOV EAX,DWORD PTR DS:[ESI]
看提示,F8单步至偏移 005905A4 处,将弹出注册窗口。那就F7进入吧,看看怎么弹出窗口:但令人抓狂的是,这个Call 是个巨型CALL,单步F8无数次都未能达到关键处,看来这种靠单步的方法效率很低,必须得想别的办法了。
由于OD在加载程序的时候会提示几个.dll已经被压缩,再加上在主程序里查找ASCII没有查到任何关于注册的信息,因此判断 注册函数可能藏在dll文件里,于是目光转移到一个叫toollib.dll的文件中,先把它的壳子脱掉,用 "DLL导出函数查看器”一查,如图

呵呵,别说你不懂英文啊,第6个导出函数“StartForm”是什么意思?当然其它几个函数明显就是注册码加密和解密过程了。 现在只对“StartForm”感兴趣,知道了导出函数名就容易办了。
回到OD,右键菜单“查看”-“查看模块间的调用”,即可查得StartForm函数在主程序中被调用处的偏移。如图
有两个,都下断吧。重新载入,一路运行直到下断处:005820CE,纵观这个过程如下:
005820B4 /$ 53 PUSH EBX ; NAG窗口弹出过程
005820B5 |. 56 PUSH ESI
005820B6 |. 8BF0 MOV ESI,EAX
005820B8 |. B3 01 MOV BL,1
005820BA |. E8 65D6F2FF CALL p51877_1.004AF724 ; 主算法过程,略过
005820BF |. 84C0 TEST AL,AL
005820C1 74 09 JE SHORT p51877_1.005820CC ; 关键跳转,直跳弹出窗口过程;把它NOP掉或改为JNE。
005820C3 |. E8 3CCBF2FF CALL <JMP.&ToolLIB.CheKeyCode>
005820C8 |. 84C0 TEST AL,AL
005820CA 75 49 JNZ SHORT p51877_1.00582115 ; 关键跳转,改为JMP,直接跳过StartForm过程
005820CC |> 33DB XOR EBX,EBX
005820CE |. E8 19CBF2FF CALL <JMP.&ToolLIB.StartForm>
005820D3 |. 83E8 01 SUB EAX,1 ; Switch (cases 0..2)
005820D6 |. 72 07 JB SHORT p51877_1.005820DF
……以下省略N代码……
00582118 |. 5B POP EBX
00582119 \. C3 RETN
看来搞定这个NAG也比较轻松,只需修改两个跳转指令:
第一处:005820C1 处的JE 把它NOP掉或改为JNE; 第二处:005820CA 处JNZ 改为JMP,直接跳过(上述两并非标志位),保存文件,重新运行一下保存后的文件,程序一路直达主界面,没有任何提示了,而且标题栏处也没有了“未注册”字样。爽。
========================================================================================
第六步:彻底爆破注册验证过程!!
虽然标题栏没有了“未注册”字样,但并不代表已经成功注册了,试一下下载一个需要注册才能用的教程来看看,在播放时仍然后提示“请注册软件”等字样。

看来这已经是最后一道防线了。
既然已经出现了文字提示,那就顺藤摸瓜,用文字来查找关键代码处。即可查得以下信息:
超级字串参考+ , 条目 566 地址=004B30A3 反汇编=MOV EAX,p51877_1.004B336C 文本字串="%s" 为注册用户专用课件或收费课件,%s请您注册软件!
下断在004B30A3 处,前后查看,即可迅速定位关键跳转
……以上省略N行代码……
004B3030 . 50 PUSH EAX
004B3031 . 68 07010001 PUSH 1000107
004B3036 . 68 00020000 PUSH 200
004B303B . E8 74BBFFFF CALL <JMP.&makelib.CheckFCH>
004B3040 . 83C4 0C ADD ESP,0C
004B3043 . 66:85C0 TEST AX,AX
004B3046 76 72 JBE SHORT p51877_1.004B30BA ; 完美爆破点,改JBE为JMP,跳过CheKeyCode过程
004B3048 . E8 B7BBFFFF CALL <JMP.&ToolLIB.CheKeyCode>
004B304D . 84C0 TEST AL,AL
……以下省略N代码……
004B3080 . E8 DF6FF5FF CALL p51877_1.0040A064
004B3085 . 8B45 B4 MOV EAX,DWORD PTR SS:[EBP-4C] ; |
004B3088 . 8945 B8 MOV DWORD PTR SS:[EBP-48],EAX ; |
004B308B . C645 BC 0B MOV BYTE PTR SS:[EBP-44],0B ; |
004B308F . B8 5C334B00 MOV EAX,p51877_1.004B335C ; |\n\n\n\n
004B3094 . 8945 C0 MOV DWORD PTR SS:[EBP-40],EAX ; |
004B3097 . C645 C4 0B MOV BYTE PTR SS:[EBP-3C],0B ; |
004B309B . 8D55 B8 LEA EDX,DWORD PTR SS:[EBP-48] ; |
004B309E . B9 01000000 MOV ECX,1 ; |
004B30A3 . B8 6C334B00 MOV EAX,p51877_1.004B336C ; |"%s" 为注册用户专用课件或收费课件,%s请您注册软件!
004B30A8 . E8 DB78F5FF CALL p51877_1.0040A988 ; \p51877_1.0040A988
004B30AD . 8B45 C8 MOV EAX,DWORD PTR SS:[EBP-38]
004B30B0 . E8 A7BDFFFF CALL p51877_1.004AEE5C
004B30B5 . E9 E2010000 JMP p51877_1.004B329C
004B30BA > 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] ; 004B3046处修改后,程序跳至此,直达成功彼岸
004B30BD . 83C0 3C ADD EAX,3C
004B30C0 . 8BD3 MOV EDX,EBX
004B30C2 . E8 1514F5FF CALL p51877_1.004044DC
004B30C7 . 8BC3 MOV EAX,EBX
最后一道防线也在004B3046处被修改为JMP后成功告破。保存为新文件“完美爆破.exe”,运行,没有任何错误,而且已经是完美注册版了。呵呵
来个总结吧:程序脱壳后修改以下几个地方即可完美告破:
1、004B0529 处 JE SHORT p51877_.004B0542 ; 关键跳转,修改JE为JMP跳过TerminateProcess函数;
2、0049CF32 处 JE SHORT p51877_1.0049CF92 ; 爆破点之一,改为JMP直接跳过错误对话框
3、004B01C4 处 JE SHORT p51877_1.004B01F1 ; 关键跳转,改为JMP,跳过下面错误提示。
4、005820C1 处 JE SHORT p51877_1.005820CC ; 关键跳转,直跳弹出窗口过程;把它NOP掉或改为JNE。
005820CA 处 JNZ SHORT p51877_1.00582115 ; 关键跳转,改为JMP,直接跳过StartForm过程
5、004B3046 处 JBE SHORT p51877_1.004B30BA ; 完美爆破点,改JBE为JMP,跳过CheKeyCode过程
到此,可以做一个文件型补丁,或者内存补丁了,留给大家去做。
还有它的算法,大侠们帮忙分析吧。
收工。
--------------------------------------------------------------------------------
【经验总结】
软件拆解,其乐无穷!
希望作者能写出更完美的英语软件,市场需求很大~~
--------------------------------------------------------------------------------
【版权声明】: 本文原创于http://www.unpack.cn, 转载请注明作者并保持文章的完整, 谢谢!
2008年07月18日 9:11:26