- UID
- 3526
注册时间2005-10-6
阅读权限40
最后登录1970-1-1
独步武林
该用户从未签到
|
一款图象处理软件 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 [ebp+18]
77D50566 |. FF75 14 push dword ptr [ebp+14]
77D50569 |. FF75 10 push dword ptr [ebp+10]
77D5056C |. FF75 0C push dword ptr [ebp+C]
77D5056F |. FF75 08 push dword ptr [ebp+8]
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 [ebp+8] ; |Text
0055B888 |. FF75 F4 push dword ptr [ebp-C] ; |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 [ebp-8]
0055B89A |. 8906 mov dword ptr [esi], eax
0055B89C |> 837D FC 00 cmp dword ptr [ebp-4], 0
0055B8A0 74 0B je short PhoXo.0055B8AD
0055B8A2 |. 6A 01 push 1 ; /Enable = TRUE
0055B8A4 |. FF75 FC push dword ptr [ebp-4] ; |hWnd
0055B8A7 |. FF15 C0E75700 call dword ptr [<&USER32.Enable>; \EnableWindow
0055B8AD |> 8B4D F0 mov ecx, dword ptr [ebp-10]
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 [esp+158], 18
0040B00B . E8 D0510200 call PhoXo.004301E0
0040B010 . 8B4424 2C mov eax, dword ptr [esp+2C] ; 注册码 -> 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 [esp+28] ; 注册码长度 -> 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 [esp+20]
0040B032 . 8AD8 mov bl, al
0040B034 . C68424 50010000 17 mov byte ptr [esp+150], 17
0040B03C . 6A 01 push 1
0040B03E . E8 AD5D0000 call PhoXo.00410DF0
0040B043 . 6A 01 push 1
0040B045 . 8D4C24 34 lea ecx, dword ptr [esp+34]
0040B049 . C68424 54010000 13 mov byte ptr [esp+154], 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 [esp+40] ; 停留在了这里,向上分析▲
0040B06C . C68424 50010000 12 mov byte ptr [esp+150], 12
0040B074 . E8 DEC31500 call PhoXo.00567457
0040B079 . 8D9424 EC000000 lea edx, dword ptr [esp+EC]
>>>>>>
毫无疑问,注册成功与否,便是看 0040B056 这里的bl是否为0了,不为0才注册成功,要分析算法,自然要进入 0040B026 地址的:
0040B026 . E8 D54F0200 call PhoXo.00430000
在这里F2键下断,用OD重新载入程序后,F9键运行,便断在了这里,按F7建进入该子程序后:
>>>>>>
00430000 /$ 64:A1 00000000 mov eax, dword ptr fs:[0] ; 注册算法,开始:
00430006 |. 6A FF push -1
00430008 |. 68 601A5700 push PhoXo.00571A60
0043000D |. 8B5424 0C mov edx, dword ptr [esp+C] ; 注册码 -> edx
00430011 |. 50 push eax
00430012 |. 64:8925 00000000 mov dword ptr fs:[0], 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 [esp+58], 0B ; 注册码长度与 $0B 比较
0043002C |. 0F85 96010000 jnz PhoXo.004301C8 ; 不等则跳走
00430032 |. 807A 05 2D cmp byte ptr [edx+5], 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 [esp+2C]
00430049 |. F3:AB rep stos dword ptr es:[edi]
0043004B |. 8B02 mov eax, dword ptr [edx] ; 注册码1-4位 -> eax
0043004D 8B4A 04 mov ecx, dword ptr [edx+4] ; 注册码5-8位 -> ecx
00430050 |. 894424 2C mov dword ptr [esp+2C], eax
00430054 |. 66:8B42 08 mov ax, word ptr [edx+8] ; 注册码9,10位 -> ax
00430058 |. 894C24 30 mov dword ptr [esp+30], ecx
0043005C |. 8A4A 0A mov cl, byte ptr [edx+A] ; 注册码11位 -> cl
0043005F |. 66:894424 34 mov word ptr [esp+34], ax
00430064 |. 884C24 36 mov byte ptr [esp+36], 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 [esp+35] ; 注册码第10位 -> dl
00430073 |. 8A4C24 2F |mov cl, byte ptr [esp+2F] ; 注册码第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 [esp+2F], cl ; 重新写回 注册码第4位
00430080 |. EB 11 |jmp short PhoXo.00430093
00430082 |> 8A4C04 32 |mov cl, byte ptr [esp+eax+32] ; 注册码第7,8,9,11位依次 -> cl
00430086 |. 8A5C04 2C |mov bl, byte ptr [esp+eax+2C] ; 注册码第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 [esp+eax+2C], 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 [esp+5C]
004300A7 |. F2:AE repne scas byte ptr es:[edi]
004300A9 |. F7D1 not ecx ; 取反
004300AB |. 49 dec ecx ; ecx := ecx -1;
004300AC |. C64424 31 00 mov byte ptr [esp+31], 0 ; 新生成的字符串的6位 设置为0
004300B1 |. 51 push ecx
004300B2 |. 68 F4EB5C00 push PhoXo.005CEBF4 ; PhoXo
004300B7 |. 8D4C24 24 lea ecx, dword ptr [esp+24] ; 'PhoXo' -> ecx
004300BB |. 885424 24 mov byte ptr [esp+24], dl
004300BF |. 897424 28 mov dword ptr [esp+28], esi
004300C3 |. 897424 2C mov dword ptr [esp+2C], esi
004300C7 |. 897424 30 mov dword ptr [esp+30], esi
004300CB |. E8 F00BFEFF call PhoXo.00410CC0
004300D0 |. 8A4424 5C mov al, byte ptr [esp+5C]
004300D4 |. 8D7C24 2C lea edi, dword ptr [esp+2C] ; 取新生成的字符串的前5位 -> edi
004300D8 |. 884424 0C mov byte ptr [esp+C], al
004300DC |. 83C9 FF or ecx, FFFFFFFF
004300DF |. 33C0 xor eax, eax ; eax 清零
004300E1 |. 897424 54 mov dword ptr [esp+54], esi
004300E5 |. F2:AE repne scas byte ptr es:[edi]
004300E7 |. F7D1 not ecx ; 取反
004300E9 |. 49 dec ecx ; ecx := ecx -1;
004300EA |. 897424 10 mov dword ptr [esp+10], esi
004300EE |. 51 push ecx
004300EF |. 8D4C24 30 lea ecx, dword ptr [esp+30] ; 取新生成的字符串的前5位 -> ecx
004300F3 |. 51 push ecx
004300F4 |. 8D4C24 14 lea ecx, dword ptr [esp+14]
004300F8 |. 897424 1C mov dword ptr [esp+1C], esi
004300FC |. 897424 20 mov dword ptr [esp+20], esi
00430100 |. E8 BB0BFEFF call PhoXo.00410CC0
00430105 |. 8B4424 20 mov eax, dword ptr [esp+20] ; '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 [esp+14]
00430116 |. 8B5C24 24 mov ebx, dword ptr [esp+24]
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 [esp+14] ; 取新生成的字符串的前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:[edi], 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[i + 6]);//注册码第10位
cl := ord(codechk); //注册码第 4位
dl := dl - $30;
cl := cl + dl;
codechk := chr(cl);
end
else begin
cl := ord(codechk[i + 6]);//注册码第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[i+6]) - ord('P'));
2: Regname := chr($30 + ord(Regname[i+6]) - ord('h'));
3: Regname := chr($30 + ord(Regname[i+6]) - ord('o'));
4: Regname := chr($30 - ord(Regname[i+6]) + ord('X'));
5: Regname := chr($30 + ord(Regname[i+6]) - 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忖-成功!
好的,就到这里结束吧!分析难免有不当之处,还望大家给我指出来! |
|