护花使者 2.0算法分析
作者:onlyu[FCG]
软件大小:
软件语言: 中文
软件类别: 共享版
应用平台: Win9x/NT/2000/XP
下载地址:
软件介绍:
【作者声明】:本人是个初学者,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!
【破解工具】:softice 4.01
【过 程】:
运行C:WINDOWSiflower.exe,点右键选注册软件,出来一个对话框,对话框告诉你序列号了,然后要你输入用户名和注册号,好,就从这里入手了,我的相关信息如下:
序列号:033014D6
用户名:onlyu
注册号:78787878
按ctrl+d调出softice,下断点bpx hmemcpy,回到护花使者 2.0注册对话框,按确定,进入softice,下bd *,一路按F10,来到:
0167:00492F2F 8B45FC MOV EAX,[EBP-04]
0167:00492F32 50 PUSH EAX
0167:00492F33 8D45F8 LEA EAX,[EBP-08]
0167:00492F36 E88523FCFF CALL 004552C0-----------------注册码计算函数
0167:00492F3B 8B55F8 MOV EDX,[EBP-08]
0167:00492F3E 58 POP EAX
0167:00492F3F E81810F7FF CALL 00403F5C-----------------注册码对比函数
0167:00492F44 7505 JNZ 00492F4B
0167:00492F46 83CEFF OR ESI,BYTE -01
0167:00492F49 EB02 JMP SHORT 00492F4D
0167:00492F4B 33F6 XOR ESI,ESI
0167:00492F4D 8BC6 MOV EAX,ESI
0167:00492F4F F7D8 NEG EAX
0167:00492F51 1BC0 SBB EAX,EAX
0167:00492F53 F7D8 NEG EAX
0167:00492F55 3C01 CMP AL,01
0167:00492F57 0F85D7000000 JNZ NEAR 00493034
0167:00492F5D BAF0304900 MOV EDX,004930F0
0167:00492F62 8BC3 MOV EAX,EBX
0167:00492F64 E8ABBEF9FF CALL 0042EE14
运行到call 403d5c时,按F8进入函数来到:
0167:00403F5C 53 PUSH EBX
0167:00403F5D 56 PUSH ESI
0167:00403F5E 57 PUSH EDI
0167:00403F5F 89C6 MOV ESI,EAX
0167:00403F61 89D7 MOV EDI,EDX
0167:00403F63 39D0 CMP EAX,EDX
0167:00403F65 0F848F000000 JZ NEAR 00403FFA
0167:00403F6B 85F6 TEST ESI,ESI
0167:00403F6D 7468 JZ 00403FD7
0167:00403F6F 85FF TEST EDI,EDI
0167:00403F71 746B JZ 00403FDE
0167:00403F73 8B46FC MOV EAX,[ESI-04]
0167:00403F76 8B57FC MOV EDX,[EDI-04]
0167:00403F79 29D0 SUB EAX,EDX
0167:00403F7B 7702 JA 00403F7F
0167:00403F7D 01C2 ADD EDX,EAX
0167:00403F7F 52 PUSH EDX
0167:00403F80 C1EA02 SHR EDX,02
0167:00403F83 7426 JZ 00403FAB
0167:00403F85 8B0E MOV ECX,[ESI]--------------------我输入的注册码
0167:00403F87 8B1F MOV EBX,[EDI]--------------------真正的注册码
0167:00403F89 39D9 CMP ECX,EBX---------------------典型的比较方式
0167:00403F8B 7558 JNZ 00403FE5
0167:00403F8D 4A DEC EDX
0167:00403F8E 7415 JZ 00403FA5
0167:00403F90 8B4E04 MOV ECX,[ESI+04]
0167:00403F93 8B5F04 MOV EBX,[EDI+04]
0167:00403F96 39D9 CMP ECX,EBX
0167:00403F98 754B JNZ 00403FE5
0167:00403F9A 83C608 ADD ESI,BYTE +08
0167:00403F9D 83C708 ADD EDI,BYTE +08
0167:00403FA0 4A DEC EDX
0167:00403FA1 75E2 JNZ 00403F85
0167:00403FA3 EB06 JMP SHORT 00403FAB
0167:00403FA5 83C604 ADD ESI,BYTE +04
0167:00403FA8 83C704 ADD EDI,BYTE +04
0167:00403FAB 5A POP EDX
0167:00403FAC 83E203 AND EDX,BYTE +03
0167:00403FAF 7422 JZ 00403FD3
0167:00403FB1 8B0E MOV ECX,[ESI]
0167:00403FB3 8B1F MOV EBX,[EDI]
0167:00403FB5 38D9 CMP CL,BL
0167:00403FB7 7541 JNZ 00403FFA
0167:00403FB9 4A DEC EDX
0167:00403FBA 7417 JZ 00403FD3
0167:00403FBC 38FD CMP CH,BH
0167:00403FBE 753A JNZ 00403FFA
0167:00403FC0 4A DEC EDX
0167:00403FC1 7410 JZ 00403FD3
0167:00403FC3 81E30000FF00 AND EBX,00FF0000
0167:00403FC9 81E10000FF00 AND ECX,00FF0000
0167:00403FCF 39D9 CMP ECX,EBX
0167:00403FD1 7527 JNZ 00403FFA
0167:00403FD3 01C0 ADD EAX,EAX
0167:00403FD5 EB23 JMP SHORT 00403FFA
0167:00403FD7 8B57FC MOV EDX,[EDI-04]
0167:00403FDA 29D0 SUB EAX,EDX
0167:00403FDC EB1C JMP SHORT 00403FFA
0167:00403FDE 8B46FC MOV EAX,[ESI-04]
0167:00403FE1 29D0 SUB EAX,EDX
0167:00403FE3 EB15 JMP SHORT 00403FFA
0167:00403FE5 5A POP EDX
0167:00403FE6 38D9 CMP CL,BL
0167:00403FE8 7510 JNZ 00403FFA
0167:00403FEA 38FD CMP CH,BH
0167:00403FEC 750C JNZ 00403FFA
0167:00403FEE C1E910 SHR ECX,10
0167:00403FF1 C1EB10 SHR EBX,10
0167:00403FF4 38D9 CMP CL,BL
0167:00403FF6 7502 JNZ 00403FFA
0167:00403FF8 38FD CMP CH,BH
0167:00403FFA 5F POP EDI
0167:00403FFB 5E POP ESI
0167:00403FFC 5B POP EBX
0167:00403FFD C3 RET
我们来看看这个注册码到底是怎么生成的,运行到 CALL 004552C0的时候按F8进入,来到:
0167:004552C0 55 PUSH EBP
0167:004552C1 8BEC MOV EBP,ESP
0167:004552C3 81C4F4FDFFFF ADD ESP,FFFFFDF4
0167:004552C9 53 PUSH EBX
0167:004552CA 56 PUSH ESI
0167:004552CB 57 PUSH EDI
0167:004552CC 8BF8 MOV EDI,EAX
0167:004552CE C745FCD2040000 MOV DWORD [EBP-04],04D2
0167:004552D5 68FF000000 PUSH DWORD FF
0167:004552DA 8D85F4FDFFFF LEA EAX,[EBP+FFFFFDF4]
0167:004552E0 50 PUSH EAX
0167:004552E1 8D45F4 LEA EAX,[EBP-0C]
0167:004552E4 50 PUSH EAX
0167:004552E5 8D45F8 LEA EAX,[EBP-08]
0167:004552E8 50 PUSH EAX
0167:004552E9 8D45FC LEA EAX,[EBP-04]
0167:004552EC 50 PUSH EAX
0167:004552ED 68FF000000 PUSH DWORD FF
0167:004552F2 8D85F4FEFFFF LEA EAX,[EBP+FFFFFEF4]
0167:004552F8 50 PUSH EAX
0167:004552F9 684C534500 PUSH DWORD 0045534C
0167:004552FE E8F917FBFF CALL `KERNEL32!GetVolumeInformationA`
0167:00455303 8B45FC MOV EAX,[EBP-04]------------------------eax的值为对话框中的序列号
0167:00455306 05E1100000 ADD EAX,10E1---------------------eax=eax+10E1
0167:0045530B 6BC00D IMUL EAX,EAX,BYTE +0D----------eax=eax*D
0167:0045530E B907000000 MOV ECX,07
0167:00455313 33D2 XOR EDX,EDX
0167:00455315 F7F1 DIV ECX--------------------------------eax=eax/7
0167:00455317 8BD8 MOV EBX,EAX------------------------把eax的值赋给ebx
0167:00455319 8B45FC MOV EAX,[EBP-04]------------------eax重新获得对话框中的序列号
0167:0045531C 2DD2040000 SUB EAX,04D2--------------------eax=eax-4d2
0167:00455321 8BD0 MOV EDX,EAX------------------------把eax的值赋给edx
0167:00455323 C1E003 SHL EAX,03---------------------------eax=eax<<3
0167:00455326 2BC2 SUB EAX,EDX--------------------------eax=eax-edx
0167:00455328 B90D000000 MOV ECX,0D
0167:0045532D 33D2 XOR EDX,EDX
0167:0045532F F7F1 DIV ECX---------------------------------eax=eax/D
0167:00455331 8BF0 MOV ESI,EAX
0167:00455333 8BCF MOV ECX,EDI
0167:00455335 8D141E LEA EDX,[ESI+EBX]-------------------edx=esi+ebx就是上面两次相除之和
0167:00455338 B858534500 MOV EAX,00455358
0167:0045533D E89E060000 CALL 004559E0---------------------按F8进入查看
0167:00455342 5F POP EDI
0167:00455343 5E POP ESI
0167:00455344 5B POP EBX
0167:00455345 8BE5 MOV ESP,EBP
0167:00455347 5D POP EBP
0167:00455348 C3 RET
按F8进入CALL 004559E0,来到:
0167:004559E0 55 PUSH EBP
0167:004559E1 8BEC MOV EBP,ESP
0167:004559E3 83C4C8 ADD ESP,BYTE -38
0167:004559E6 53 PUSH EBX
0167:004559E7 33DB XOR EBX,EBX
0167:004559E9 895DC8 MOV [EBP-38],EBX
0167:004559EC 895DEC MOV [EBP-14],EBX
0167:004559EF 894DF4 MOV [EBP-0C],ECX
0167:004559F2 8955F8 MOV [EBP-08],EDX-----------------把上面运行结果存储在[ebp-8]中
0167:004559F5 8945FC MOV [EBP-04],EAX
0167:004559F8 8B45FC MOV EAX,[EBP-04]
0167:004559FB E800E6FAFF CALL 00404000
0167:00455A00 33C0 XOR EAX,EAX
0167:00455A02 55 PUSH EBP
0167:00455A03 68F95A4500 PUSH DWORD 00455AF9
0167:00455A08 64FF30 PUSH DWORD [FS:EAX]
0167:00455A0B 648920 MOV [FS:EAX],ESP
0167:00455A0E 33C0 XOR EAX,EAX
0167:00455A10 8945F0 MOV [EBP-10],EAX
0167:00455A13 33DB XOR EBX,EBX
0167:00455A15 8B45FC MOV EAX,[EBP-04]
0167:00455A18 E82FE4FAFF CALL 00403E4C
0167:00455A1D 85C0 TEST EAX,EAX
0167:00455A1F 7E13 JNG 00455A34
0167:00455A21 BA01000000 MOV EDX,01
0167:00455A26 8B4DFC MOV ECX,[EBP-04]---------------------[ecx]="hazz"
0167:00455A29 0FB64C11FF MOVZX ECX,BYTE [ECX+EDX-01]
0167:00455A2E 03D9 ADD EBX,ECX
0167:00455A30 42 INC EDX
0167:00455A31 48 DEC EAX-----------------------------------这个循环功能就是把上面四个字符ASCII
0167:00455A32 75F2 JNZ 00455A26 码加起来
0167:00455A34 035DF8 ADD EBX,[EBP-08]---------------------与序列号运行结果相加
0167:00455A37 6BC30D IMUL EAX,EBX,BYTE +0D------------把上面结果与D相乘赋给eax
0167:00455A3A 8945F8 MOV [EBP-08],EAX--------------------把eax的值存进[eip-8]
0167:00455A3D 8D45EC LEA EAX,[EBP-14]
0167:00455A40 BA105B4500 MOV EDX,00455B10
0167:00455A45 E81AE2FAFF CALL 00403C64
0167:00455A4A 33D2 XOR EDX,EDX
0167:00455A4C 8D45CC LEA EAX,[EBP-34]
0167:00455A4F 8B4DEC MOV ECX,[EBP-14]
0167:00455A52 0FB60C11 MOVZX ECX,BYTE [ECX+EDX]------循环第一次时[ecx+edx]="delphi"
0167:00455A56 8908 MOV [EAX],ECX
0167:00455A58 42 INC EDX
0167:00455A59 83C004 ADD EAX,BYTE +04
0167:00455A5C 83FA06 CMP EDX,BYTE +06
0167:00455A5F 75EE JNZ 00455A4F
0167:00455A61 C745E808000000 MOV DWORD [EBP-18],08-------置大循环的次数
0167:00455A68 8B45DC MOV EAX,[EBP-24]-----------------------|
0167:00455A6B 2B45E0 SUB EAX,[EBP-20] |
0167:00455A6E 99 CDQ |
0167:00455A6F 33C2 XOR EAX,EDX |
0167:00455A71 2BC2 SUB EAX,EDX |
0167:00455A73 8B4DCC MOV ECX,[EBP-34] |
0167:00455A76 034DD0 ADD ECX,[EBP-30] |
0167:00455A79 8B55D4 MOV EDX,[EBP-2C] |
0167:00455A7C 3355D8 XOR EDX,[EBP-28] |
0167:00455A7F 03CA ADD ECX,EDX |
0167:00455A81 2BC8 SUB ECX,EAX |
0167:00455A83 894DE4 MOV [EBP-1C],ECX |这里循环8次
0167:00455A86 8B45F8 MOV EAX,[EBP-08] |
0167:00455A89 33C1 XOR EAX,ECX |
0167:00455A8B 0145F0 ADD [EBP-10],EAX |
0167:00455A8E 0FAF4DF0 IMUL ECX,[EBP-10] |
0167:00455A92 894DE4 MOV [EBP-1C],ECX |
0167:00455A95 BA06000000 MOV EDX,06 |
0167:00455A9A 8D45D0 LEA EAX,[EBP-30] |
0167:00455A9D 8B08 MOV ECX,[EAX]---------| |
0167:00455A9F 8948FC MOV [EAX-04],ECX | |
0167:00455AA2 83C004 ADD EAX,BYTE +04 | 循环6次 |
0167:00455AA5 4A DEC EDX | |
0167:00455AA6 75F5 JNZ 00455A9D------------| |
0167:00455AA8 FF4DE8 DEC DWORD [EBP-18] |
0167:00455AAB 75BB JNZ 00455A68--------------------------------|
0167:00455AAD 8B45F4 MOV EAX,[EBP-0C]
0167:00455AB0 50 PUSH EAX
0167:00455AB1 8D4DC8 LEA ECX,[EBP-38]
0167:00455AB4 BA08000000 MOV EDX,08
0167:00455AB9 8B45F0 MOV EAX,[EBP-10]----------------[ebp-10]就是注册码的数值了
0167:00455ABC E8972EFBFF CALL 00408958
0167:00455AC1 8B45C8 MOV EAX,[EBP-38]
0167:00455AC4 B908000000 MOV ECX,08
0167:00455AC9 BA01000000 MOV EDX,01
0167:00455ACE E881E5FAFF CALL 00404054
0167:00455AD3 33C0 XOR EAX,EAX
0167:00455AD5 5A POP EDX
0167:00455AD6 59 POP ECX
0167:00455AD7 59 POP ECX
0167:00455AD8 648910 MOV [FS:EAX],EDX
0167:00455ADB 68005B4500 PUSH DWORD 00455B00
0167:00455AE0 8D45C8 LEA EAX,[EBP-38]
0167:00455AE3 E8E4E0FAFF CALL 00403BCC
0167:00455AE8 8D45EC LEA EAX,[EBP-14]
0167:00455AEB E8DCE0FAFF CALL 00403BCC
0167:00455AF0 8D45FC LEA EAX,[EBP-04]
0167:00455AF3 E8D4E0FAFF CALL 00403BCC
0167:00455AF8 C3 RET
下面就把上面大循环和小循环运行的示意图表示出来:
这里有var1表示[eip-8]所指的值,var2初值为0另外有六个变量,分别为a1,a2,a3,a4,a5,a6,初值为'd','e','l','p','h','i'。
每次循环都是先求var2=var2+(((a1+a2)+(a3 xor a4)-|a5-a6|) xor var1),var3=var2*((a1+a2)+(a3 xor a4)-|a5-a6|),再对a1,a2,a3,a4,a5,a6进行置换,置换规则为:
a1=a2
a2=a3
a3=a4
a4=a5
a5=a6
a6=var3
经过这八次大循环后得到的var2的16进制数值的8个字符就是注册码了。通过分析我们可以发现,这个软件的注册算法没有用到注册名,也就是说得到的注册码与注册名无关。
好了,算法的分析就是这样,用Borland c++ 5.0编写注册机代码如下:
#include<stdio.h>
long jdz(long x)
{
if(x>=0) return(x);
else return(-x);
}
void main()
{
int i;
long var1,var2=0,var3,a1,a2,a3,a4,a5,a6,t1,t2;
printf("Please Iput xu lie hao shu zhi:");
scanf("%x",&var1);
t1=((var1+0x10e1)*0xd)/7;
t2=((var1-0x4d2)*8-(var1-0x4d2))/0xd;
var1=t1+t2;
t1='h'+'a'+'z'+'z';
var1=(var1+t1)*0xd;
a1='d';a2='e';a3='l';a4='p';a5='h';a6='i';
for(i=0;i<8;i++)
{
var2=var2+((a1+a2+(a3^a4)-jdz(a5-a6))^var1);
var3=var2*(a1+a2+(a3^a4)-jdz(a5-a6));
a1=a2;a2=a3;a3=a4;a4=a5;a5=a6;a6=var3;
}
printf("zhu ce ma wei:%0x
",var2);
getchar();
}