iTutor口语小教练详细算法破解与Delphi注册机(图)
【文章作者】: 海浪轻风(黄仁来)【下载地址】: http://ha.newhua.com/down/iTutorSetup.zip
【操作平台】: 盗版XP
【软件介绍】: 一个高效的口语练习辅导工具
【作者声明】: 本文原创于看雪技术论坛
【详细过程】
最近很忙,但再忙也要继续学算法分析,趁现在兴趣正浓~~~
网上又抓到一个感觉不错的英语软件,提供丰富的听力教材,对练习口语和听力很有用。里面还有在线英文电台等,感觉也不错。
软件说需要注册,但发现不注册和注册没有很大不同。没什么时间测试它的功能了,开工!
OD载入,运行注册输入假码9876543210,弹出“注册失败”提示,查找超级字符串,很快定位到算法主过程大致如下:
0045E420 . 6A FF PUSH -1
0045E422 . 68 68E14900 PUSH iTutor.0049E168 ; 膏-k; SE 处理程序安装
0045E427 . 64:A1 0000000>MOV EAX,DWORD PTR FS:
……中间省略N多代码……
0045E454 . 8D8E 28010000 LEA ECX,DWORD PTR DS:[ESI+128]
0045E45A . E8 8C490200 CALL iTutor.00482DEB ; 读取假码
0045E45F . 8B5424 04 MOV EDX,DWORD PTR SS:[ESP+4]
0045E463 . 52 PUSH EDX
0045E464 . E8 CD330000 CALL <JMP.&SAEGNR.#23> ; 不知干什么,懒得理
0045E469 . 83C4 04 ADD ESP,4
0045E46C . E8 B9330000 CALL <JMP.&SAEGNR.#21> ; 关键算法,F7进入
0045E471 . 5E POP ESI
0045E472 . 83F8 01 CMP EAX,1
0045E475 . 6A 00 PUSH 0 ; /Arg3 = 00000000
0045E477 . 75 2C JNZ SHORT iTutor.0045E4A5 ; |
0045E479 . 6A 40 PUSH 40 ; |Arg2 = 00000040
0045E47B . 68 C43A4C00 PUSH iTutor.004C3AC4 ; |注册成功!
0045E480 . E8 E3C60200 CALL iTutor.0048AB68 ; \iTutor.0048AB68
0045E485 . E8 E8650300 CALL iTutor.00494A72
0045E48A . 8B4C24 00 MOV ECX,DWORD PTR SS:[ESP]
0045E48E . 8B40 04 MOV EAX,DWORD PTR DS:[EAX+4]
0045E491 . 51 PUSH ECX ; /Arg3
0045E492 . 68 78354C00 PUSH iTutor.004C3578 ; |regcode
0045E497 . 68 6C354C00 PUSH iTutor.004C356C ; |settings
0045E49C . 8BC8 MOV ECX,EAX ; |
0045E49E . E8 2EE80200 CALL iTutor.0048CCD1 ; \iTutor.0048CCD1
0045E4A3 . EB 0C JMP SHORT iTutor.0045E4B1
0045E4A5 > 6A 30 PUSH 30 ; |Arg2 = 00000030
0045E4A7 . 68 B83A4C00 PUSH iTutor.004C3AB8 ; |注册失败!
0045E4AC . E8 B7C60200 CALL iTutor.0048AB68 ; \iTutor.0048AB68
……中间省略N多代码……
0045E4D0 . C3 RETN
0045E46C处为关键算法过程,按一次F7,来到
0046182A $- FF25 00054A00 JMP DWORD PTR DS:[<&SAEGNR.#21>] ; SAEGNR.#21
明显,这里程序调用了外部DLL(文件名是SAEGNR.dll)进行算法加密,这是个非常重要的提示!!
赶快用PEid的Krypto ANALyzer插件查一下,发现有MD5和BASE64加密算法,思路顿时清晰~~~~
继续F7吧,进入算法过程
003A1480 > 81EC 00030000 SUB ESP,300
003A1486 B9 40000000 MOV ECX,40
……中间省略N多代码……
003A14A2 BE E0D83B00 MOV ESI,SAEGNR.003BD8E0 ; 假码
003A14A7 8D7C24 0C LEA EDI,DWORD PTR SS:[ESP+C]
003A14AB C705 E0DE3B00 0>MOV DWORD PTR DS:,0
003A14B5 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
003A14B7 BF E0DB3B00 MOV EDI,SAEGNR.003BDBE0 ; 机器码
003A14BC 83C9 FF OR ECX,FFFFFFFF
……中间省略N多代码……
003A14D7 8D8C24 0C010000 LEA ECX,DWORD PTR SS:[ESP+10C]
003A14DE 51 PUSH ECX
003A14DF E8 7CFDFFFF CALL SAEGNR.#11 ; 关键算法过程,F7进入
003A14E4 8BF8 MOV EDI,EAX ; 到这一步,寄存器EAX已经出现真正注册码了
003A14E6 83C9 FF OR ECX,FFFFFFFF ; 可以制作内存注册机
003A14E9 33C0 XOR EAX,EAX
…… 以下省略N多代码……
003A1555 5B POP EBX
003A1556 81C4 00030000 ADD ESP,300
明显003A14DF处继续调用外部dll序号为11的函数了。
而这个函数F8步过后,寄存器EAX已经出现真正注册码了,可以制作内存注册机。但本人对内存注册机不感兴趣。 继续F7单步进入关键算法过程吧,看看 #11 函数,来到真正注册码算法核心部分,激动人心的时刻即将来临 ~~~~
003A1260 > 6A FF PUSH -1
003A1262 68 61593B00 PUSH SAEGNR.003B5961
……中间省略N多代码……
003A12CB 8D4C24 28 LEA ECX,DWORD PTR SS:[ESP+28]
003A12CF 51 PUSH ECX
003A12D0 52 PUSH EDX
003A12D1 E8 BA150000 CALL SAEGNR.003A2890 ; 把机器码进行标准MD5加密,结果记为M1(小写状态)
003A12D6 83C4 0C ADD ESP,0C
003A12D9 50 PUSH EAX
……中间省略N多代码……
003A1339 E8 52150000 CALL SAEGNR.003A2890 ; 把M1再进行MD5加密,结果记为M2
003A133E 83C4 0C ADD ESP,0C
003A1341 50 PUSH EAX
003A1342 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+14]
……中间省略N多代码……
003A13A3 3BFB CMP EDI,EBX
003A13A5 8D4C3C 24 LEA ECX,DWORD PTR SS:[ESP+EDI+2>; 截M2后16位字符串,记为S2
003A13A9 894C24 1C MOV DWORD PTR SS:[ESP+1C],ECX ; (则M2前16位字符串,记为S1)
003A13AD 7E 76 JLE SHORT SAEGNR.003A1425 ; 循环↓ for i:=1 to 16 do begin
003A13AF 55 PUSH EBP
003A13B0 897C24 18 MOV DWORD PTR SS:[ESP+18],EDI
003A13B4 8A16 MOV DL,BYTE PTR DS:[ESI]
003A13B6 8D4424 24 LEA EAX,DWORD PTR SS:[ESP+24]
003A13BA 6A 10 PUSH 10
003A13BC 8D4C24 16 LEA ECX,DWORD PTR SS:[ESP+16]
003A13C0 50 PUSH EAX
003A13C1 51 PUSH ECX
003A13C2 885424 1E MOV BYTE PTR SS:[ESP+1E],DL ; 取S1第i位ASCII值,记为S1
003A13C6 885C24 1F MOV BYTE PTR SS:[ESP+1F],BL ; BL=0
003A13CA E8 BF330000 CALL SAEGNR.003A478E ; 把S1转化为数值型,记为T1
003A13CF 8A1437 MOV DL,BYTE PTR DS:[EDI+ESI]
003A13D2 8BE8 MOV EBP,EAX
003A13D4 8D4424 30 LEA EAX,DWORD PTR SS:[ESP+30]
003A13D8 6A 10 PUSH 10
003A13DA 8D4C24 22 LEA ECX,DWORD PTR SS:[ESP+22]
003A13DE 50 PUSH EAX
003A13DF 51 PUSH ECX
003A13E0 885424 2A MOV BYTE PTR SS:[ESP+2A],DL ; 取S2第i位ASCII值,记为S2
003A13E4 885C24 2B MOV BYTE PTR SS:[ESP+2B],BL ; BL=0
003A13E8 E8 A1330000 CALL SAEGNR.003A478E ; 把S2转化为数值型,记为T2
003A13ED 03C5 ADD EAX,EBP ; T1 + T2,结果记为T3
003A13EF 25 0F000080 AND EAX,8000000F ; T3:=T3 and $8000000F(相当于取计算结果的最后一位)
003A13F4 79 05 JNS SHORT SAEGNR.003A13FB
003A13F6 48 DEC EAX
003A13F7 83C8 F0 OR EAX,FFFFFFF0
003A13FA 40 INC EAX
003A13FB 8D5424 2A LEA EDX,DWORD PTR SS:[ESP+2A]
003A13FF 6A 10 PUSH 10
003A1401 52 PUSH EDX
003A1402 50 PUSH EAX
003A1403 E8 A7C50000 CALL SAEGNR.003AD9AF ; 再转换为字符串
003A1408 0FBE4424 36 MOVSX EAX,BYTE PTR SS:[ESP+36]
003A140D 50 PUSH EAX
003A140E E8 6B390000 CALL SAEGNR.003A4D7E ; 变大写,记为T4,累加结果为真正注册码
003A1413 8806 MOV BYTE PTR DS:[ESI],AL
003A1415 8B4424 40 MOV EAX,DWORD PTR SS:[ESP+40]
003A1419 83C4 28 ADD ESP,28
003A141C 46 INC ESI
003A141D 48 DEC EAX
003A141E 894424 18 MOV DWORD PTR SS:[ESP+18],EAX
003A1422 ^ 75 90 JNZ SHORT SAEGNR.003A13B4 ; 循环↑
003A1424 5D POP EBP
003A1425 8B4C24 1C MOV ECX,DWORD PTR SS:[ESP+1C]
003A1429 8D7C24 24 LEA EDI,DWORD PTR SS:[ESP+24]
003A142D 33C0 XOR EAX,EAX
003A142F C78424 2C010000>MOV DWORD PTR SS:[ESP+12C],-1
003A143A 8819 MOV BYTE PTR DS:[ECX],BL
003A143C 83C9 FF OR ECX,FFFFFFFF
003A143F F2:AE REPNE SCAS BYTE PTR ES:[EDI]
003A1441 F7D1 NOT ECX
003A1443 2BF9 SUB EDI,ECX
003A1445 8BD1 MOV EDX,ECX
003A1447 8BF7 MOV ESI,EDI
003A1449 BF E0DC3B00 MOV EDI,SAEGNR.003BDCE0 ; ASCII "364B1B71E950FDDE"
003A144E C1E9 02 SHR ECX,2 ; 以上OD自动的“注释”即真正注册码
……中间省略N多代码……
003A147F C3 RETN
【算法总结】
Step1: 两次MD5加密机器码,结果保存为M1 (注意是小写状态)
Step2: 把M1截分为两段,前16位记为S1,后16位记为S2
Step3: 循环开始→ 取M1的第i位记为T1,取M2的第i位记为T2,将T1和T2转换为十六进制后相加,结果记为T3
Step4: 运算 T3 AND $8000000F 结果转换成字符串,并转换成大写,记为T4
Step5: 累加T4为真正注册码 ←循环结束
【Delphi重现算法过程】
uses MD5;//自己查找MD5标准加密算法单元
{$R *.dfm}
function TransChar(AChar: Char): Integer;
begin
if AChar in ['0'..'9'] then
Result := Ord(AChar) - Ord('0')
else
Result := 10 + Ord(AChar) - Ord('A');
end;
function GetSN(MachineCode:string):string;
var
R: string;
S1, S2: string;
T1 : Integer;
T2:string;
I: Integer;
Reg: string;
begin
R := MD5Print(MD5String(MachineCode)); //第一次MD5加密;
R := UpperCase(MD5Print(MD5String(R))); //第二次MD5加密
S1 := Copy(R, 1, 16); //取前16位;
S2 := Copy(R, 17, 16); //取后16位;
for I := 1 to 16 do
begin
T1:=TransChar(S1)+TransChar(S2) ; //分别取第i位ASCII值相加
T2:=IntToHex(T1 and $8000000F,1); //如果T1为双位,则取后一位变字符串;
Reg:=Reg+T2;
//以上两步,可以表达为:
//T2:=IntToHex(T1,1); //转化为十六进制字符;
//Reg:=Reg+ Copy(T2,Length(T2),1); //取取最后一位字符串,累加;
end;
Result:=Reg;
end;
--------------------------------------------------------------------------------
【经验总结】
本人在一个非常简单的过程差点弄晕,就是在Delphi中如何实现字符串、十六进制以及ASCII码三者之间的相互转换问题。
现在还有有点晕。不知哪位高人能提供完整的源代码关于以上三者的相互转换的函数??
http://www.anqn.com/pic/3/66c6331350afd6916438dbdf.jpg
好东西。。。
那个下载地址是破解了的么 学习了
谢谢楼主 这个我收藏了.!! 注册机在哪呢 算法让人看得郁闷,很复杂呀,收藏以后慢慢看
页:
[1]