Soundnailsd的破解教程(二) (6千字)
Soundnailsd的破解教程(二)休息好了,我们接着上一篇继续来 :-)
话说上回讲到要想得到注册码的算法,必须要在追进0167:004579D5 CALL 00457320 和
0167:00457A67 CALL 00403ECC 这两个CALL中.好,我们就先来看看 CALL 00457320。
下面与计算注册码无关的代码我就不进行说明了. :-)
代码如下:
0167:00457320 PUSH EBP
0167:00457321 MOV EBP,ESP
0167:00457323 ADD ESP,BYTE -0C
0167:00457326 PUSH EBX
0167:00457327 XOR ECX,ECX
0167:00457329 MOV [EBP-0C],ECX
0167:0045732C MOV [EBP-08],EDX
0167:0045732F MOV [EBP-04],EAX
0167:00457332 MOV EAX,[EBP-04]
0167:00457335 CALL 00403FC0
0167:0045733A MOV EAX,[EBP-08]
0167:0045733D CALL 00403FC0
0167:00457342 XOR EAX,EAX
0167:00457344 PUSH EBP
0167:00457345 PUSH DWORD 004573C6
0167:0045734A PUSH DWORD [FS:EAX]
0167:0045734D MOV [FS:EAX],ESP
0167:00457350 LEA EAX,[EBP-04]
0167:00457353 MOV EDX,004573DC
0167:00457358 CALL 00403E14
0167:0045735D MOV EAX,[EBP-04]
0167:00457360 CALL 00403E0C --->在用户名后加上字符串"SNL".如:"pojieyongSNL"
0167:00457365 PUSH EAX --->EAX为用户名+SNL的个数
0167:00457366 LEA EAX,[EBP-04]
0167:00457369 CALL 00403FDC
0167:0045736E MOV ECX,FFFF2012 -->FFFF2012送ECX ─────┐
0167:00457373 POP EDX ---->用户名+SNL的个数弹到EDX │
0167:00457374 CALL 00456F2C ------>一个关键的计算的 CALL │
0167:00457379 MOV EBX,EAX ------->EAX送EBX │
0167:0045737B MOV EDX,07---------->07送EDX │
0167:00457380 MOV EAX,EBX -------->EBX送EAX │
0167:00457382 CALL 004565BC ----->将EAX移位的CALL. │
0167:00457387 XOR EAX,A4529D37---->异或 │─>这一段过程就是算码的过程.
0167:0045738C MOV EBX,EAX ---->EAX送EBX │ (下面将详细介绍)
0167:0045738E MOV EAX,EBX ---->EBX送EAX │
0167:00457390 CDQ ----->扩展EAX的符号位至EDX │
0167:00457391 PUSH EDX │
0167:00457392 PUSH EAX │
0167:00457393 LEA EAX,[EBP-0C] │
0167:00457396 CALL 00457FC8 ----->最后算出注册码的CALL**────┘
0167:0045739B MOV EAX,[EBP-0C]---->将真注册码的首地址送EAX.
0167:0045739E MOV EDX,[EBP-08]---->将假注册码的首地址送EDX.
0167:004573A1 CALL 00403F1C-------->判断真假注册码CALL
0167:004573A6 SETZ AL -------->就是它 嘿嘿..狐狸尾巴.
0167:004573A9 MOV EBX,EAX
0167:004573AB XOR EAX,EAX
0167:004573AD POP EDX
0167:004573AE POP ECX
0167:004573AF POP ECX
0167:004573B0 MOV [FS:EAX],EDX
0167:004573B3 PUSH DWORD 004573CD
0167:004573B8 LEA EAX,[EBP-0C]
0167:004573BB MOV EDX,03
0167:004573C0 CALL 00403BB0
0167:004573C5 RET
0167:004573C6 JMP 004035A0
0167:004573CB JMP SHORT 004573B8
0167:004573CD MOV EAX,EBX
0167:004573CF POP EBX
0167:004573D0 MOV ESP,EBP
0167:004573D2 POP EBP
0167:004573D3 RET
这个子程序的大体流程是这样的,(与算码无关的代码这里就不介绍了),将ffff2012送ECX,
然后经过0167:00457374 CALL 00456F2C 根据填的(用户名+SNL)计算得到一个值,
然后再经过0167:00457382 CALL 004565BC 将这个值 (在EAX中)进行移位,移位的个数为7,
这个CALL的上面有指令 MOV EDX,07 ;这就是移位的个数.
这个值经过移位以后,再与A4529D37异或,结果在 EAX中..然后再经过 0167:00457396 CALL 00457FC8
计算出正确的注册码.
最后再通过0167:004573A1 CALL 00403F1C来判断真假注册码.
好了,让我们来仔细分析一下计算注册码的流程:
① 首先,在用户名后面加上"SNL",例如,用户名为"pojieyong",加上"SNL"形成"pojieyongSNL".
FFFF2012送ECX,用户名+SNL的个数送EDX.然后经过0167:00457374 CALL 00456F2C 根据填的(用户名+SNL)
计算得到一个值.让我们来看看 0167:00457374 CALL 00456F2C.
代码如下 :
其中EAX指向 "用户名+SNL"的首地址, ECX=FFFF2012, EDX=用户名+SNL的个数.
0167:00456F2C PUSH EBX
0167:00456F2D PUSH ESI
0167:00456F2E TEST EAX,EAX
0167:00456F30 JNZ 00456F36
0167:00456F32 XOR ECX,ECX
0167:00456F34 JMP SHORT 00456F66
0167:00456F36 NOT ECX ------>ECX取反.即FFFF2012取反
0167:00456F38 TEST EDX,EDX ------>测试EDX
0167:00456F3A JNG 00456F64
0167:00456F3C XOR EBX,EBX ----->EBX清零<<───────────┐
0167:00456F3E MOV BL,[EAX] ---->取用户名 │
0167:00456F40 MOV ESI,ECX ------>ECX送ESI │
0167:00456F42 XOR EBX,ESI ------>异或 │
0167:00456F44 AND EBX,FF ------>EBX和ff进行与运算. │循
0167:00456F4A MOV EBX,[EBX*4+0047ECC8] │环
0167:00456F51 SHR ESI,08 ------>ESI逻辑右移8位 │
0167:00456F54 AND ESI,00FFFFFF -->ESI和00FFFFFF进行与运算 │
0167:00456F5A XOR EBX,ESI ---->异或 │
0167:00456F5C MOV ECX,EBX ---->EBX送ECX │
0167:00456F5E DEC EDX ---->EDX-1(个数减1) │
0167:00456F5F INC EAX ---->EAX+1 │
0167:00456F60 TEST EDX,EDX ----->测试EDX │
0167:00456F62 JG 00456F3C ----->循环,直到EDX=0 ──────┘
0167:00456F64 NOT ECX ----->ECX取反
0167:00456F66 MOV EAX,ECX ----->ECX送EAX
0167:00456F68 POP ESI
0167:00456F69 POP EBX
0167:00456F6A RET
经过上面的运算得到一个值,送到EAX中。
② 将这个值再经过0167:00457382 CALL 004565BC 进行移位.
代码如下:
其中EDX=7 .
0167:004565BC MOV CL,DL ----->7送CL
0167:004565BE ROL EAX,CL----->将EAX循环左移
0167:004565C0 RET
EAX循环左移以后,再与 A4529D37 进行异或,结果在EAX中. 然后再用CDQ指令扩展EAX的符号位至EDX.
③ 再往下来就是最后算出注册码的CALL了,这个CALL就是0167:00457396 CALL 00457FC8
代码如下:
0167:00457FC8 PUSH EBP
0167:00457FC9 MOV EBP,ESP
0167:00457FCB PUSH EBX
0167:00457FCC MOV EBX,EAX
0167:00457FCE PUSH DWORD [EBP+0C]
0167:00457FD1 PUSH DWORD [EBP+08]
0167:00457FD4 MOV EDX,EBX
0167:00457FD6 MOV EAX,[0047F0F0]--->0047F0F0处存放的是一个指针,送到eax.
该指针指向"M65DCBEL2NZPT8RW34HXK71Y9AF"
0167:00457FDB CALL 00457004 ------>真正计算码的CALL.
0167:00457FE0 POP EBX
0167:00457FE1 POP EBP
0167:00457FE2 RET 08
其实EAX所指向的字符串"M65DCBEL2NZPT8RW34HXK71Y9AF" 就是注册码取值范围,即注册码是从这个字符串
中取值. 那么,注册码是按什么规律来取值的呢? 算法就在0167:00457FDB CALL 00457004里,看来我们还要
继续往里追 :-)
再偷懒一下, 闪先 *^_^*
