【文章标题】: rOYALaCCEZZCRACKME算法分析
【软件名称】: rOYALaCCEZZCRACKME
【软件大小】: 35.5K
【下载地址】: http://ocn.e5v.com/bbs1/attachment.php?aid=920&checkid=f8a85&download=1
【编写语言】: ASM
【使用工具】: OLLYDBG
【操作平台】: WIN2000
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
1、peid查看为MASM32 / TASM32,无壳,ASM程序,省了不少事。
2、OD载入,查看字符串,“you got the serial (puuh, that was hard”,嘿嘿,很好的切入点,双击,向上查找,在关键的地方00401096下断,运行,随便输入用户名和注册码,点确定,被断下:
00401087 |. 6A 40 PUSH 40 ; /Count = 40 (64.)
00401089 |. 68 84304000 PUSH rOYALaCC.00403084 ; |Buffer = rOYALaCC.00403084
0040108E |. 68 EA030000 PUSH 3EA ; |ControlID = 3EA (1002.)
00401093 |. FF75 08 PUSH [ARG.1] ; |hWnd
00401096 |. E8 A1020000 CALL <JMP.&USER32.GetDlgItemTextA> ; \取注册码长度
0040109B |. 8BD8 MOV EBX,EAX
0040109D |. 6A 40 PUSH 40 ; /Count = 40 (64.)
0040109F |. 68 44304000 PUSH rOYALaCC.00403044 ; |Buffer = rOYALaCC.00403044
004010A4 |. 68 E8030000 PUSH 3E8 ; |ControlID = 3E8 (1000.)
004010A9 |. FF75 08 PUSH [ARG.1] ; |hWnd
004010AC |. E8 8B020000 CALL <JMP.&USER32.GetDlgItemTextA> ; \取用户名长度
004010B1 |. 83F8 05 CMP EAX,5 ; 是否大于5
004010B4 |. 72 28 JB SHORT rOYALaCC.004010DE ; 小于则跳到提示用户名不够的地方
004010B6 |. 83F8 20 CMP EAX,20 ; 是否大于20
004010B9 |. 77 23 JA SHORT rOYALaCC.004010DE ; 大于则跳到提示用户名太多
004010BB |. 0BDB OR EBX,EBX ; 注册码长度与用户名长度对比
004010BD |. 74 1F JE SHORT rOYALaCC.004010DE ; 相同就跳死
004010BF |. 53 PUSH EBX
004010C0 |. 50 PUSH EAX
004010C1 |. E8 7B000000 CALL rOYALaCC.00401141 ; 算法,跟入
004010C6 |. 83F8 01 CMP EAX,1 ; 返回的EAX是否为1
004010C9 |. 75 13 JNZ SHORT rOYALaCC.004010DE ; 不是就跳错
004010CB |. 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004010CD |. 68 34304000 PUSH rOYALaCC.00403034 ; |Title = "You打e 1337 ;)"
004010D2 |. 68 0B304000 PUSH rOYALaCC.0040300B ; |you got the serial (puuh, that was hard)
004010D7 |. 6A 00 PUSH 0 ; |hOwner = NULL
004010D9 |. E8 64020000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
=============================================================================================
跟进算法CALL 00401141
00401141 /$ 55 PUSH EBP
00401142 |. 8BEC MOV EBP,ESP
00401144 |. 8B45 08 MOV EAX,[ARG.1] ; 用户名长度
00401147 |. C705 C4304000>MOV DWORD PTR DS:[4030C4],0 ; 段寄存器4030C4赋值0
00401151 |. BB 01000000 MOV EBX,1 ; EBX赋值1
00401156 |. EB 1D JMP SHORT rOYALaCC.00401175
00401158 |> 48 /DEC EAX ; 用户名位数减1
00401159 |. 0FB690 443040>|MOVZX EDX,BYTE PTR DS:[EAX+403044] ; 逐个倒取用户名ASCII的十六进制码
00401160 |. 33D3 |XOR EDX,EBX ; 异或HEX码和EBX的值(初始为1),放到EDX中
00401162 |. 0FAFD3 |IMUL EDX,EBX ; 结果和EBX值相乘
00401165 |. 83C3 05 |ADD EBX,5 ; EBX+5
00401168 |. 3115 C4304000 |XOR DWORD PTR DS:[4030C4],EDX ; EDX的值异或段寄存器4030C4的值(初始为0)
0040116E |. C105 C4304000>|ROL DWORD PTR DS:[4030C4],5 ; 结果循环左移5位
00401175 |> 0BC0 OR EAX,EAX ; 用户名位数是否取完
00401177 |.^ 75 DF \JNZ SHORT rOYALaCC.00401158 ; 没有则继续循环
00401179 |. F715 C4304000 NOT DWORD PTR DS:[4030C4] ; 计算结果取反,用户名最终结果在地址4030C4里
0040117F |. 33C9 XOR ECX,ECX ; ECX清空
00401181 |. 8B4D 08 MOV ECX,[ARG.1] ; 赋值用户名长度
00401184 |. D30D C4304000 ROR DWORD PTR DS:[4030C4],CL ; 赋值用户名长度循环左移5位
0040118A |. 33C0 XOR EAX,EAX ; EAX清空
0040118C |. C605 C8304000>MOV BYTE PTR DS:[4030C8],0 ; 4030C8地址赋值0
00401193 |. EB 17 JMP SHORT rOYALaCC.004011AC
00401195 |> 0FB690 843040>/MOVZX EDX,BYTE PTR DS:[EAX+403084] ; 逐个取注册码HEX码
0040119C |. 40 |INC EAX ; EAX=EAX+1(EAX初始为0)
0040119D |. 83FA 2D |CMP EDX,2D ; 注册码是否为“-”
004011A0 |. 75 0A |JNZ SHORT rOYALaCC.004011AC ; 不是就跳
004011A2 |. FEC8 |DEC AL ; EAX=EAX-1
004011A4 |. A2 C8304000 |MOV BYTE PTR DS:[4030C8],AL ; EAX的值放入4030C8地址
004011A9 |. 8B45 0C |MOV EAX,[ARG.2] ; 注册码长度放入EAX
004011AC |> 3B45 0C CMP EAX,[ARG.2] ; EAX的值(初始为0)与注册码长度对比
004011AF |.^ 75 E4 \JNZ SHORT rOYALaCC.00401195 ; 不等就循环
004011B1 |. 803D C8304000>CMP BYTE PTR DS:[4030C8],0 ; 结果是否为0
004011B8 |. 75 06 JNZ SHORT rOYALaCC.004011C0 ; 一定要跳
004011BA |. 33C0 XOR EAX,EAX
004011BC |. C9 LEAVE
004011BD |. C2 0800 RETN 8
-------注册码中必须含有“-”号,并判断“-”号是第几位
004011C0 |> \33C9 XOR ECX,ECX ; ECX清空
004011C2 |. 8A0D C8304000 MOV CL,BYTE PTR DS:[4030C8] ; 上面的计算结果放入CL(-号的位置)
004011C8 |. 33C0 XOR EAX,EAX ; EAX清空
004011CA |. 33DB XOR EBX,EBX ; EBX清空
004011CC |. EB 14 JMP SHORT rOYALaCC.004011E2
004011CE |> FEC9 /DEC CL ; “-”号前的注册码长度减1
004011D0 |. 0FB691 843040>|MOVZX EDX,BYTE PTR DS:[ECX+403084] ; 倒取“-”号前的注册码的十六进制码
004011D7 |. 83FA 3F |CMP EDX,3F ; 是否大于3F,就是判断是否大于A(41)
004011DA |. 76 0E |JBE SHORT rOYALaCC.004011EA
004011DC |. 83FA 5B |CMP EDX,5B ; 是否小于5B,判断是否小于Z(5A)
004011DF |. 73 09 |JNB SHORT rOYALaCC.004011EA
004011E1 |. 90 |NOP
004011E2 |> 0AC9 OR CL,CL ; “-”号前的注册码长度是否取完
004011E4 |.^ 75 E8 \JNZ SHORT rOYALaCC.004011CE ; 不等就循环
004011E6 |. 90 NOP
004011E7 |. 90 NOP
004011E8 |. EB 06 JMP SHORT rOYALaCC.004011F0
004011EA |> 33C0 XOR EAX,EAX
004011EC |. C9 LEAVE
004011ED |. C2 0800 RETN 8
------------“-”号前的注册码必须为大写字母
004011F0 |> \33C9 XOR ECX,ECX ; ECX清空
004011F2 |. 8A0D C8304000 MOV CL,BYTE PTR DS:[4030C8] ; “-”号前的注册码长度
004011F8 |. 33C0 XOR EAX,EAX ; EAX清空
004011FA |. 33DB XOR EBX,EBX ; EBX清空
004011FC |. EB 11 JMP SHORT rOYALaCC.0040120F
004011FE |> FEC9 /DEC CL ; “-”号前的注册码长度减1
00401200 |. 6BDB 1A |IMUL EBX,EBX,1A ; EBX=EBX*1A,EBX,初始为0
00401203 |. 0FB691 843040>|MOVZX EDX,BYTE PTR DS:[ECX+403084] ; 倒取“-”号前的注册码的十六进制码
0040120A |. 83EA 41 |SUB EDX,41 ; 减41H
0040120D |. 03DA |ADD EBX,EDX ; 加EBX的值
0040120F |> 0AC9 OR CL,CL ; “-”号前的注册码长度是否取完
00401211 |.^ 75 EB \JNZ SHORT rOYALaCC.004011FE ; 没有就继续循环
00401213 |. 3B1D C4304000 CMP EBX,DWORD PTR DS:[4030C4] ; 计算结果与401179处的用户名计算结果的值对比,4030C4放的是上面的用户名计算结果
00401219 74 06 JE SHORT rOYALaCC.00401221 ; 必须要相等,要跳
0040121B |. 33C0 XOR EAX,EAX
0040121D |. C9 LEAVE
0040121E |. C2 0800 RETN 8
------------倒取“-”号前的注册码的HEX码减41,加1A结果要与用户名的最终计算结果相等
00401221 |> 8B45 0C MOV EAX,[ARG.2] ; 注册码长度放入EAX
00401224 |. 2A05 C8304000 SUB AL,BYTE PTR DS:[4030C8] ; 减“-”号前的注册码长度
0040122A |. 83F8 04 CMP EAX,4 ; 是否为4
0040122D 74 06 JE SHORT rOYALaCC.00401235 ; 不是就跳错,必须跳,要等于-号前要为4位
0040122F |. 33C0 XOR EAX,EAX
00401231 |. C9 LEAVE
00401232 |. C2 0800 RETN 8
-------------注册码“-”号必须为4位注册码
00401235 |> \33DB XOR EBX,EBX ; EBX清空
00401237 |. 8A1D C8304000 MOV BL,BYTE PTR DS:[4030C8] ; “-”号前的注册码长度放入BL
0040123D |. FEC3 INC BL ; BL=BL+1,BL为“-”号的位置
0040123F |. 0FB693 843040>MOVZX EDX,BYTE PTR DS:[EBX+403084] ; 取“-”号后第一位注册码的十六进制码
00401246 |. 8815 C9304000 MOV BYTE PTR DS:[4030C9],DL ; 放入段寄存器地址4030C9
0040124C |. FEC3 INC BL ; 取下一位
0040124E |. 0FB693 843040>MOVZX EDX,BYTE PTR DS:[EBX+403084] ; 取“-”号后第二位注册码的十六进制码
00401255 |. 8815 CA304000 MOV BYTE PTR DS:[4030CA],DL ; 放入段寄存器地址4030CA
0040125B |. FEC3 INC BL ; 取下一位
0040125D |. 0FB693 843040>MOVZX EDX,BYTE PTR DS:[EBX+403084] ; 取“-”号后第三位注册码的十六进制码
00401264 |. 8815 CB304000 MOV BYTE PTR DS:[4030CB],DL ; 放入段寄存器地址4030CB
0040126A |. 33C0 XOR EAX,EAX ; EAX清空
0040126C |. A0 C9304000 MOV AL,BYTE PTR DS:[4030C9] ; “-”号后第一位注册码的十六进制码放入AL
00401271 |. 6BC0 03 IMUL EAX,EAX,3 ; 乘3
00401274 |. A3 CC304000 MOV DWORD PTR DS:[4030CC],EAX ; 放入段寄存器地址4030CC
00401279 |. 33C0 XOR EAX,EAX ; EAX清空
0040127B |. 8A1D C9304000 MOV BL,BYTE PTR DS:[4030C9] ; “-”号后第一位注册码的十六进制码放入AL
00401281 |. 6BDB 07 IMUL EBX,EBX,7 ; 乘7
00401284 |. 2BC3 SUB EAX,EBX ; 减EAX(0)的值
00401286 |. A3 D0304000 MOV DWORD PTR DS:[4030D0],EAX ; 结果放入段寄存器地址4030D0
0040128B |. 33C0 XOR EAX,EAX ; EAX清空
0040128D |. A0 C9304000 MOV AL,BYTE PTR DS:[4030C9] ; “-”号后第一位注册码的十六进制码放入AL
00401292 |. A3 D4304000 MOV DWORD PTR DS:[4030D4],EAX ; 结果放入段寄存器地址4030D4
00401297 |. 33C0 XOR EAX,EAX ; EAX清空
00401299 |. A0 CA304000 MOV AL,BYTE PTR DS:[4030CA] ; “-”号后第二位注册码的十六进制码放入AL
0040129E |. 2905 CC304000 SUB DWORD PTR DS:[4030CC],EAX ; 减4030CC的值(“-”号后第一位注册码的十六进制码乘3)
004012A4 |. 33C0 XOR EAX,EAX ; EAX清空
004012A6 |. A0 CA304000 MOV AL,BYTE PTR DS:[4030CA] ; “-”号后第二位注册码的十六进制码放入AL
004012AB |. 6BC0 02 IMUL EAX,EAX,2 ; 乘2
004012AE |. 0105 D0304000 ADD DWORD PTR DS:[4030D0],EAX ; 加4030D0地址的值(“-”号后第一位注册码的十六进制码乘7)
004012B4 |. 33C0 XOR EAX,EAX ; EAX清空
004012B6 |. A0 CA304000 MOV AL,BYTE PTR DS:[4030CA] ; “-”号后第二位注册码的十六进制码放入AL
004012BB |. 0105 D4304000 ADD DWORD PTR DS:[4030D4],EAX ; 加“-”号后第一位注册码的十六进制码
004012C1 |. 33C0 XOR EAX,EAX ; EAX清空
004012C3 |. A0 CB304000 MOV AL,BYTE PTR DS:[4030CB] ; “-”号后第三位注册码的十六进制码放入AL
004012C8 |. 6BC0 05 IMUL EAX,EAX,5 ; 乘5
004012CB |. 0105 CC304000 ADD DWORD PTR DS:[4030CC],EAX ; 加4030CC的值(“-”号后第一位注册码的十六进制码乘3)
004012D1 |. 33C0 XOR EAX,EAX ; EAX清空
004012D3 |. A0 CB304000 MOV AL,BYTE PTR DS:[4030CB] ; “-”号后第三位注册码的十六进制码放入AL
004012D8 |. 6BC0 07 IMUL EAX,EAX,7 ; 乘7
004012DB |. 0105 D0304000 ADD DWORD PTR DS:[4030D0],EAX ; 加4030D0地址的值(“-”号后第一位注册码的十六进制码乘7)
004012E1 |. 33C0 XOR EAX,EAX ; EAX清空
004012E3 |. A0 CB304000 MOV AL,BYTE PTR DS:[4030CB] ; “-”号后第三位注册码的十六进制码放入AL
004012E8 |. 6BC0 02 IMUL EAX,EAX,2 ; 乘2
004012EB |. 2905 D4304000 SUB DWORD PTR DS:[4030D4],EAX ; 计算结果减地址4030D4的值(“-”号后第一位注册码的十六进制码)
004012F1 |. 813D CC304000>CMP DWORD PTR DS:[4030CC],204 ; 是否为204H
004012FB 74 06 JE SHORT rOYALaCC.00401303 ; 不等就死,必须跳
004012FD |. 33C0 XOR EAX,EAX
004012FF |. C9 LEAVE
00401300 |. C2 0800 RETN 8
00401303 |> 833D D0304000>CMP DWORD PTR DS:[4030D0],19 ; 4030D0地址的值(“-”号后第一位注册码的十六进制码乘7)是否为19H,从这里可以推出“-”号后第一位注册码
0040130A 74 06 JE SHORT rOYALaCC.00401312 ; 不等就死,必须跳
0040130C |. 33C0 XOR EAX,EAX
0040130E |. C9 LEAVE
0040130F |. C2 0800 RETN 8
00401312 |> 833D D4304000>CMP DWORD PTR DS:[4030D4],0D ; 地址4030D4的值(“-”号后第一位注册码的十六进制码)是否为0D,
00401319 |. 74 06 JE SHORT rOYALaCC.00401321 ; 不等会死,一定要跳
0040131B |. 33C0 XOR EAX,EAX ; EAX清空
0040131D |. C9 LEAVE
0040131E |. C2 0800 RETN 8
00401321 |> B8 01000000 MOV EAX,1 ; 成功则赋标志位1
00401326 |. C9 LEAVE
00401327 \. C2 0800 RETN 8 ; 成功返回
================================================================================================
算法总结:倒取用户名ASCII的十六进制码异或用户名位数,并乘用户名位数,再加5,结果左移5位,然后取反,结果假设为A。
注册码中必须含有“-”号,“-”号前为4位,并且都为大写字母,倒取“-”号前的注册码的HEX码减41,加1A结果要与用户名的最终计算A结果相等。
注册码“-”号后有三位参与计算,可以用逆推法计算出三位注册码。
贴个C语言注册机源码:
#include <stdio.h>
#include <string.h>
main()
{
char name[100];
char SN[100];
unsigned long mem,edx,sum;
int c,count,ebx,regcode;
ebx=1;
mem=0;
printf("\t\t KeyGen For rOYALaCCEZZCRACKME\n");
printf("\t\t =========================\n");
printf("Please Input Your Name:\n");
gets(name);
count=strlen(name);
c=count-1;
for(c;c>=0;c--)
{
edx=name[c];
edx=edx ^ ebx;
edx=edx * ebx;
ebx=ebx + 5;
mem=mem ^ edx;
mem=mem << 5 | mem >> 27;
}
mem=~mem;
mem=mem>>strlen(name) | mem << (32-strlen(name));
sum=mem;
while(mem>0)
{
regcode=mem%0x1a+0x41;
printf("%c",regcode);
mem=mem/0x1a;
}
printf("-RAC");
getchar();
}
并感谢lnn1123[OCN]的帮助。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年03月08日 下午 04:40:47
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!