一款图象处理软件 PhoXo v6.0 的注册算法分析 + 注册机源代码
一款图象处理软件 PhoXo v6.0 的注册算法分析 + 注册机源代码一款感觉还不错的图象处理软件,分析了下,简单写出来。
软件在未注册的状态下,每次启动时会弹出一个NAG提示对话框;先打开注册窗口,输入注册名:aCaFeeL,输入注册码:12345678,点击OK按钮,程序提示下次启动时检查。
故确定软件用的是重启验证的方式,将PhoXo.exe文件拖入OD中后,下断点: bp MessageBoxExA,按F9键运行程序,此时程序被中断下来:
>>>>>>
77D5055C >/$8BFF mov edi, edi ; 被断在了这里
77D5055E|.55 push ebp
77D5055F|.8BEC mov ebp, esp
77D50561|.6A FF push -1
77D50563|.FF75 18 push dword ptr
77D50566|.FF75 14 push dword ptr
77D50569|.FF75 10 push dword ptr
77D5056C|.FF75 0C push dword ptr
77D5056F|.FF75 08 push dword ptr
77D50572|.E8 4D5A0100 call USER32.MessageBoxTimeoutA
77D50577|.5D pop ebp
77D50578\.C2 1400 retn 14
>>>>>>
再按ALT+F9建后,弹出NAG对话框,点击‘OK’按钮后,便回到了PhoXo的领空:
>>>>>>
0055B883|> \53 push ebx ; /Style
0055B884|.57 push edi ; |Title
0055B885|.FF75 08 push dword ptr ; |Text
0055B888|.FF75 F4 push dword ptr ; |hOwner
0055B88B|.FF15 B4E55700 call dword ptr [<&USER32.Messag>; \MessageBoxA
0055B891|.85F6 test esi, esi ; 回到了这里!
0055B893|.8BF8 mov edi, eax
0055B895|.74 05 je short PhoXo.0055B89C
0055B897|.8B45 F8 mov eax, dword ptr
0055B89A|.8906 mov dword ptr , eax
0055B89C|>837D FC 00 cmp dword ptr , 0
0055B8A0 74 0B je short PhoXo.0055B8AD
0055B8A2|.6A 01 push 1 ; /Enable = TRUE
0055B8A4|.FF75 FC push dword ptr ; |hWnd
0055B8A7|.FF15 C0E75700 call dword ptr [<&USER32.Enable>; \EnableWindow
0055B8AD|>8B4D F0 mov ecx, dword ptr
0055B8B0|.6A 01 push 1
0055B8B2|.E8 F4FEFFFF call PhoXo.0055B7AB
0055B8B7|.8BC7 mov eax, edi
0055B8B9|.5F pop edi
0055B8BA|.5E pop esi
0055B8BB|.5B pop ebx
0055B8BC|.C9 leave
0055B8BD\.C2 0C00 retn 0C
>>>>>>
F8键走完上面这个子call后,在继续分析,便来到了这里:
>>>>>>
0040B001 .51 push ecx
0040B002 .52 push edx
0040B003 .C68424 58010000 18 mov byte ptr , 18
0040B00B .E8 D0510200 call PhoXo.004301E0
0040B010 .8B4424 2C mov eax, dword ptr ;注册码 -> eax
0040B014 .83C4 08 add esp, 8
0040B017 .85C0 test eax, eax
0040B019 .75 05 jnz short PhoXo.0040B020
0040B01B .B8 D0F35700 mov eax, PhoXo.0057F3D0
0040B020 >8B4C24 28 mov ecx, dword ptr ;注册码长度 -> ecx
0040B024 .51 push ecx
0040B025 .50 push eax
0040B026 .E8 D54F0200 call PhoXo.00430000 ;注册算法,F7键进入分析:
0040B02B .83C4 08 add esp, 8
0040B02E .8D4C24 20 lea ecx, dword ptr
0040B032 .8AD8 mov bl, al
0040B034 .C68424 50010000 17 mov byte ptr , 17
0040B03C .6A 01 push 1
0040B03E .E8 AD5D0000 call PhoXo.00410DF0
0040B043 .6A 01 push 1
0040B045 .8D4C24 34 lea ecx, dword ptr
0040B049 .C68424 54010000 13 mov byte ptr , 13
0040B051 .E8 9A5D0000 call PhoXo.00410DF0
0040B056 .84DB test bl, bl ;bl = 0 ?
0040B058 75 0E jnz short PhoXo.0040B068 ;关键跳,bl<>0,一跳便OK了
0040B05A .6A FF push -1
0040B05C .6A 00 push 0
0040B05E .68 81270000 push 2781
0040B063 .E8 90081500 call PhoXo.0055B8F8 ;弹出NAG对话框
0040B068 >8D4C24 40 lea ecx, dword ptr ;停留在了这里,向上分析▲
0040B06C .C68424 50010000 12 mov byte ptr , 12
0040B074 .E8 DEC31500 call PhoXo.00567457
0040B079 .8D9424 EC000000 lea edx, dword ptr
>>>>>>
毫无疑问,注册成功与否,便是看 0040B056 这里的bl是否为0了,不为0才注册成功,要分析算法,自然要进入 0040B026 地址的:
0040B026 .E8 D54F0200 call PhoXo.00430000
在这里F2键下断,用OD重新载入程序后,F9键运行,便断在了这里,按F7建进入该子程序后:
>>>>>>
00430000/$64:A1 00000000 mov eax, dword ptr fs: ;注册算法,开始:
00430006|.6A FF push -1
00430008|.68 601A5700 push PhoXo.00571A60
0043000D|.8B5424 0C mov edx, dword ptr ;注册码 -> edx
00430011|.50 push eax
00430012|.64:8925 00000000 mov dword ptr fs:, esp
00430019|.83EC 40 sub esp, 40
0043001C|.56 push esi
0043001D|.33F6 xor esi, esi ;esi 清零
0043001F|.3BD6 cmp edx, esi ;edx 与 esi 比较
00430021|.0F84 A1010000 je PhoXo.004301C8 ;注册码为空,则跳
00430027|.837C24 58 0B cmp dword ptr , 0B ;注册码长度与 $0B 比较
0043002C|.0F85 96010000 jnz PhoXo.004301C8 ;不等则跳走
00430032|.807A 05 2D cmp byte ptr , 2D ;注册码第6位的ASCII码与 $2D 比较
00430036|.0F85 8C010000 jnz PhoXo.004301C8 ;不同则跳走
0043003C|.53 push ebx
0043003D|.57 push edi
0043003E|.B9 08000000 mov ecx, 8 ;ecx := 8;
00430043|.33C0 xor eax, eax ;eax 清零
00430045|.8D7C24 2C lea edi, dword ptr
00430049|.F3:AB rep stos dword ptr es:
0043004B|.8B02 mov eax, dword ptr ;注册码1-4位 -> eax
0043004D 8B4A 04 mov ecx, dword ptr ;注册码5-8位 -> ecx
00430050|.894424 2C mov dword ptr , eax
00430054|.66:8B42 08 mov ax, word ptr ;注册码9,10位 -> ax
00430058|.894C24 30 mov dword ptr , ecx
0043005C|.8A4A 0A mov cl, byte ptr ;注册码11位 -> cl
0043005F|.66:894424 34 mov word ptr , ax
00430064|.884C24 36 mov byte ptr , cl
00430068|.33C0 xor eax, eax ;eax 清零
0043006A|>83F8 03 /cmp eax, 3 ;eax 与 $3 比较
0043006D|.75 13 |jnz short PhoXo.00430082 ;不相等,跳
0043006F|.8A5424 35 |mov dl, byte ptr ;注册码第10位 -> dl
00430073|.8A4C24 2F |mov cl, byte ptr ;注册码第4位 -> cl
00430077|.80EA 30 |sub dl, 30 ;dl := dl - $30;
0043007A|.02CA |add cl, dl ;cl := cl + dl;
0043007C|.884C24 2F |mov byte ptr , cl ;重新写回 注册码第4位
00430080|.EB 11 |jmp short PhoXo.00430093
00430082|>8A4C04 32 |mov cl, byte ptr ;注册码第7,8,9,11位依次 -> cl
00430086|.8A5C04 2C |mov bl, byte ptr ;注册码第1,2,3,5位依次 -> bl
0043008A|.2ACB |sub cl, bl ;cl := cl - bl;
0043008C|.80C1 30 |add cl, 30 ;cl := cl + $30;
0043008F|.884C04 2C |mov byte ptr , cl ;依次重新写回 注册码第1,2,3,5位
00430093|>40 |inc eax ;eax := eax + 1;
00430094|.83F8 05 |cmp eax, 5 ;eax 与 5 比较
00430097|.^ 7C D1 \jl short PhoXo.0043006A ;小于5,继续循环
00430099|.BF F4EB5C00 mov edi, PhoXo.005CEBF4 ;PhoXo -> edi
0043009E|.83C9 FF or ecx, FFFFFFFF
004300A1|.33C0 xor eax, eax ;eax 清零
004300A3|.8A5424 5C mov dl, byte ptr
004300A7|.F2:AE repne scas byte ptr es:
004300A9|.F7D1 not ecx ;取反
004300AB|.49 dec ecx ;ecx := ecx -1;
004300AC|.C64424 31 00 mov byte ptr , 0 ;新生成的字符串的6位 设置为0
004300B1|.51 push ecx
004300B2|.68 F4EB5C00 push PhoXo.005CEBF4 ;PhoXo
004300B7|.8D4C24 24 lea ecx, dword ptr ;'PhoXo' -> ecx
004300BB|.885424 24 mov byte ptr , dl
004300BF|.897424 28 mov dword ptr , esi
004300C3|.897424 2C mov dword ptr , esi
004300C7|.897424 30 mov dword ptr , esi
004300CB|.E8 F00BFEFF call PhoXo.00410CC0
004300D0|.8A4424 5C mov al, byte ptr
004300D4|.8D7C24 2C lea edi, dword ptr ;取新生成的字符串的前5位 -> edi
004300D8|.884424 0C mov byte ptr , al
004300DC|.83C9 FF or ecx, FFFFFFFF
004300DF|.33C0 xor eax, eax ;eax 清零
004300E1|.897424 54 mov dword ptr , esi
004300E5|.F2:AE repne scas byte ptr es:
004300E7|.F7D1 not ecx ;取反
004300E9|.49 dec ecx ;ecx := ecx -1;
004300EA|.897424 10 mov dword ptr , esi
004300EE|.51 push ecx
004300EF|.8D4C24 30 lea ecx, dword ptr ;取新生成的字符串的前5位 -> ecx
004300F3|.51 push ecx
004300F4|.8D4C24 14 lea ecx, dword ptr
004300F8|.897424 1C mov dword ptr , esi
004300FC|.897424 20 mov dword ptr , esi
00430100|.E8 BB0BFEFF call PhoXo.00410CC0
00430105|.8B4424 20 mov eax, dword ptr ;'PhoXo' -> eax
00430109|.3BC6 cmp eax, esi ;比较是否为空
0043010B|.75 05 jnz short PhoXo.00430112 ;不为空字符串,跳
0043010D|.B8 D0F35700 mov eax, PhoXo.0057F3D0
00430112|>8B5424 14 mov edx, dword ptr
00430116|.8B5C24 24 mov ebx, dword ptr
0043011A|.3BD3 cmp edx, ebx
0043011C|.8BCA mov ecx, edx
0043011E|.72 02 jb short PhoXo.00430122
00430120|.8BCB mov ecx, ebx
00430122|>55 push ebp
00430123|.8B6C24 14 mov ebp, dword ptr ;取新生成的字符串的前5位 -> ebp
00430127|.8BF8 mov edi, eax ;'PhoXo' -> edi
00430129|.8BF5 mov esi, ebp ;取新生成的字符串的前5位 -> esi
0043012B|.33C0 xor eax, eax
0043012D|.F3:A6 repe cmps byte ptr es:, by>;取新生成的字符串的前5位 = 'PhoXo' ??
0043012F 74 05 je short PhoXo.00430136 ;相等,则成功,跳!
00430131|.1BC0 sbb eax, eax
00430133|.83D8 FF sbb eax, -1
00430136|>33F6 xor esi, esi
>>>>>>
通过上面的分析,我们知道了其注册算法的方式为:
读入注册名和注册码,注册码的长度应该为11位,且第6位必须为‘-’字符;
即是:
将:【注册码第 7位的ASCII值 - 注册码第1位的ASCII值 + $30】的结果 重新写回 注册码的第1位;
将:【注册码第 8位的ASCII值 - 注册码第2位的ASCII值 + $30】的结果 重新写回 注册码的第2位;
将:【注册码第 9位的ASCII值 - 注册码第3位的ASCII值 + $30】的结果 重新写回 注册码的第3位;
将:【注册码第10位的ASCII值 + 注册码第4位的ASCII值 - $30】的结果 重新写回 注册码的第4位;
将:【注册码第11位的ASCII值 - 注册码第5位的ASCII值 + $30】的结果 重新写回 注册码的第5位;
然后这个新生成的11位长度的字符串,取该新字符串的前5位(即上面运算的5个结果),与字符串 PhoXo 比较,只要两者相等,便注册成功了!
比如,输入假注册码:12345-789AB 后,经过上面的运算,便得到了 666E=-789AB 这个新字符串,取这个新字符串的前5位:666E=,然后与字符串PhoXo比较,看是否相同,相同,便注册成功了!
其注册算法转换成用 Delphi + KOL/MCK 写的代码即是如下形式:(已写成为一个string函数格式,方便你的调用和修改,嘿嘿 :)
function PhoXo_sn(codechk: string): string; //PhoXo v6.0 软件的算法函数
var
i, bl, cl, dl : integer;
begin
for i:=1 to 5 do //还原 PhoXo v6.0 软件本身的算法
begin
if (i=4)
then begin
dl := ord(codechk);//注册码第10位
cl := ord(codechk); //注册码第 4位
dl := dl - $30;
cl := cl + dl;
codechk := chr(cl);
end
else begin
cl := ord(codechk);//注册码第7,8,9,11位依次
bl := ord(codechk); //注册码第1,2,3, 5位依次
cl := cl - bl;
cl := cl + $30;
codechk := chr(cl);
end;
end;
Result := codechk;
end;
而根据上面的算法,也就可以写出一个可用的注册机了;
用 Delphi + KOL/MCK 写的代码即是如下形式:(已写成为一个string函数格式,方便你的调用和修改,嘿嘿 :)
function PhoXo_keygen(RegName : string): string;//PhoXo v6.0 注册机算法
var
i : integer;
begin
if RegName = ''
then begin
showmessage('InPut Your Name, First!');
exit;
end
else Regname := 'PhoXo-' +
chr(ord($61 + random(26)))+
chr(ord($61 + random(26)))+
chr(ord($61 + random(26)))+
chr(ord($41 + random(26)))+
chr(ord($61 + random(26)));
for i:=1 to 5 do
begin
case i of //注册码第7,8,9,10,11位依次和字符串PhoXo运算
1: Regname := chr($30 + ord(Regname) - ord('P'));
2: Regname := chr($30 + ord(Regname) - ord('h'));
3: Regname := chr($30 + ord(Regname) - ord('o'));
4: Regname := chr($30 - ord(Regname) + ord('X'));
5: Regname := chr($30 + ord(Regname) - ord('o'));
end;
end;
Result := Regname;
end;
上面的注册机算法在多台机器上使用不同注册名通过验证,但没有时间再优化它了,应该不存在bug的问题;
软件输入的注册信息保存在 register.ini 文件中,其格式为: 注册名长度 00 00 00 注册名 注册码长度 00 00 00 注册码
放上几组可用的Key:
注册名:aCaFeeL
注册码:QB(6)-qzgRh 或者
J6222-jnqVq 或者
MA814-mywWs 或者
L=9=9-luxKx 或者
T-546-tetTu 或者
R+246-rcqTu 或者
焎症-!注册 或者
搼z忖-成功!
好的,就到这里结束吧!分析难免有不当之处,还望大家给我指出来! 抢先顶贴 , 保存一下该可以学到很多东西的, 嗯 原帖由 lgjxj 于 2007-11-10 18:31 发表 https://www.chinapyg.com/images/common/back.gif
抢先顶贴 , 保存一下该可以学到很多东西的, 嗯
KAN大哥,不许过分谦虚哈~ 学习逆向工程ing... 好东西,谢谢楼主 可以学到很多东西的 好东西!!!!继续吧
页:
[1]