【软件名称】QQ密码键盘记录器
【下载地址】自己找
【应用平台】Win9x/NT/2000/XP
【软件大小】未知
【软件限制】Nag
【破解声明】看到论坛有人问这个软件,最近也想学一下算法,所以就有了此文。从未写过破文,各位大侠见笑了!只是对技术感兴趣,无其它目的。如果有人利用此文做出注册机做坏事,与本人没有任何关系!失误之处敬请诸位大侠赐教!
【破解工具】od,ida
【软件简介】记录QQ密码!
========================================================================================
【分析过程】

1.查壳,无壳,vc编写;
2.od载入,运行老罗的字符参考插件,很容易找到关键处!
输入假码"1234567890ABCDEF"

代码:
00402440 <>/$  6A FF      push -1                         ;  sub_402440 00402442   |.  68 8832410>push <QQPwd.loc_413288>         ;  SE 句柄安装 00402447   |.  64:A1 0000>mov eax,dword ptr fs:[0] 0040244D   |.  50         push eax 0040244E   |.  64:8925 00>mov dword ptr fs:[0],esp 00402455   |.  83EC 18    sub esp,18 00402458   |.  53         push ebx 00402459   |.  8B4C24 2C  mov ecx,dword ptr ss:[esp+2C]   ;  假码->ecx 0040245D   |.  33C0       xor eax,eax 0040245F   |.  894424 05  mov dword ptr ss:[esp+5],eax 00402463   |.  33DB       xor ebx,ebx 00402465   |.  66:894424 >mov word ptr ss:[esp+9],ax 0040246A   |.  895C24 24  mov dword ptr ss:[esp+24],ebx 0040246E   |.  884424 0B  mov byte ptr ss:[esp+B],al 00402472   |.  8B41 F8    mov eax,dword ptr ds:[ecx-8]    ;  假码长度->eax 00402475   |.  83F8 10    cmp eax,10 00402478   |.  885C24 04  mov byte ptr ss:[esp+4],bl 0040247C   |.  0F8C C0000>jl <QQPwd.loc_402542>           ;  假码长度<16则跳 00402482   |.  56         push esi 00402483   |.  68 0401000>push 104 00402488   |.  8D4C24 34  lea ecx,dword ptr ss:[esp+34]   ;  假码->ecx 0040248C   |.  E8 DFC5000>call <QQPwd.sub_40EA70>         ;  假码->eax 00402491   |.  8B10       mov edx,dword ptr ds:[eax]      ;  假码第1个4位->edx 00402493   |.  33F6       xor esi,esi 00402495   |.  895424 10  mov dword ptr ss:[esp+10],edx   ;  假码第1个4位->[12efa4] 00402499   |.  8B48 04    mov ecx,dword ptr ds:[eax+4]    ;  假码第2个4位->ecx 0040249C   |.  894C24 14  mov dword ptr ss:[esp+14],ecx   ;  假码第2个4位->[12efa8] 004024A0   |.  8B50 08    mov edx,dword ptr ds:[eax+8]    ;  假码第3个4位->edx 004024A3   |.  895424 18  mov dword ptr ss:[esp+18],edx   ;  假码第3个4位->[12efac] 004024A7   |.  8B40 0C    mov eax,dword ptr ds:[eax+C]    ;  假码最后4位->eax 004024AA   |.  894424 1C  mov dword ptr ss:[esp+1C],eax   ;  假码最后4位->[12efb0] 004024AE <>|>  8A4C34 10  /mov cl,byte ptr ss:[esp+esi+10>;  -|取每位注册码,如果是数字,取其ascii码值与30之差,如果是字母A-F则取其ascii值与37之差,其余则取FF 004024B2   |.  51         |push ecx                       ;   | 004024B3   |.  E8 68FFFFF>|call <QQPwd.sub_402420>        ;   |追进此call可知,注册码每位只能取0-9及A-F 004024B8   |.  83C4 04    |add esp,4                      ;   |-->此循环的实际作用:将假码每位补0,如2->02 004024BB   |.  884434 10  |mov byte ptr ss:[esp+esi+10],a>;   |差值->[12efa4] 004024BF   |.  46         |inc esi                        ;   |计数 004024C0   |.  83FE 10    |cmp esi,10                     ;   | 004024C3   |.^ 7C E9      \jl short <QQPwd.loc_4024AE>    ;  _|是否循环完 004024C5   |.  33C0       xor eax,eax 004024C7   |.  8D4C24 10  lea ecx,dword ptr ss:[esp+10]   ;  保存上面循环变换后的值地址(堆栈12efa4)->ecx 004024CB   |.  5E         pop esi 004024CC <>|>  8A51 01    /mov dl,byte ptr ds:[ecx+1]     ;  依次取假码的偶数位(2,4,6,8,10,12,14,16)位经上面循环变换后的结果,记为OU 004024CF   |.  8A19       |mov bl,byte ptr ds:[ecx]       ;  依次取假码的奇数位(1,3,5,7,9,11,13,15)经上面循环变换后的结果,记为QI 004024D1   |.  C0E2 04    |shl dl,4                       ;  shl OU,4(实际就是反转ascii,如:02->20) 004024D4   |.  02D3       |add dl,bl                      ;  (shl OU,4)+QI,每次结果记为A(i) 004024D6   |.  83C1 02    |add ecx,2                      ;  移到下2个 004024D9   |.  885404 04  |mov byte ptr ss:[esp+eax+4],dl ;  A(i)->[12ef9c] 004024DD   |.  40         |inc eax                        ;  计数 004024DE   |.  83F8 08    |cmp eax,8 004024E1   |.^ 7C E9      \jl short <QQPwd.loc_4024CC>    ;  是否循环完 004024E3   |.  8A4424 07  mov al,byte ptr ss:[esp+7]      ;  A(4)[12ef9f]->al 004024E7   |.  8A5C24 04  mov bl,byte ptr ss:[esp+4]      ;  A(1)[12ef9c]->bl 004024EB   |.  8A4C24 0B  mov cl,byte ptr ss:[esp+B]      ;  A(8)[12efa3]->cl 004024EF   |.  8A5424 05  mov dl,byte ptr ss:[esp+5]      ;  A(2)[12ef9d]->dl 004024F3   |.  32C3       xor al,bl                       ;  xor A(4),A(1),结果记为B1 004024F5   |.  8A5C24 06  mov bl,byte ptr ss:[esp+6]      ;  A(3)->bl 004024F9   |.  32CA       xor cl,dl                       ;  xor A(8),A(2),结果记为B2 004024FB   |.  8A5424 09  mov dl,byte ptr ss:[esp+9]      ;  A(6)->dl 004024FF   |.  32D3       xor dl,bl                       ;  xor A(6),A(3),结果记为B3 00402501   |.  8A5C24 08  mov bl,byte ptr ss:[esp+8]      ;  A(5)->bl 00402505   |.  325C24 0A  xor bl,byte ptr ss:[esp+A]      ;  xor A(7),A(5),结果记为B4 00402509   |.  3C 55      cmp al,55 0040250B   |.  75 35      jnz short <QQPwd.loc_402542>    ;  B1 !=55则跳 0040250D   |.  80F9 6E    cmp cl,6E 00402510   |.  75 30      jnz short <QQPwd.loc_402542>    ;  B2 !=6E则跳 00402512   |.  80FA 4E    cmp dl,4E 00402515   |.  75 2B      jnz short <QQPwd.loc_402542>    ;  B3 !=4E则跳 00402517   |.  80FB 19    cmp bl,19 0040251A   |.  75 26      jnz short <QQPwd.loc_402542>    ;  B4 !=19则跳 0040251C   |.  8D4C24 2C  lea ecx,dword ptr ss:[esp+2C]   ;  4024ae处循环变换后值保存地址->ecx 00402520   |.  C74424 24 >mov dword ptr ss:[esp+24],-1 00402528   |.  E8 5FC3000>call <QQPwd.sub_40E88C> 0040252D   |.  B8 0100000>mov eax,1 00402532   |.  5B         pop ebx 00402533   |.  8B4C24 18  mov ecx,dword ptr ss:[esp+18] 00402537   |.  64:890D 00>mov dword ptr fs:[0],ecx 0040253E   |.  83C4 24    add esp,24 00402541   |.  C3         retn




综合上面的,思考观察一下可得出:

A(1)=假码1,2位反转
A(2)=假码3,4位反转
A(3)=假码5,6位反转
A(4)=假码7,8位反转
A(5)=假码9,10位反转
A(6)=假码11,12位反转
A(7)=假码13,14位反转
A(8)=假码15,16位反转
========================================================================================

【分析总结】
1.注册码长度为16
2.注册码每位只能是数字0-9,和字母A-F(大写)
3.运算关系:
xor A(4),A(1)=55
xor A(8),A(2)=6E
xor A(6),A(3)=4E
xor A(7),A(5)=19
4.注册码求逆:
随机生成4个10进制2位数,作为A(1),A(2),A(3),A(5)的值,因为由A xor B=C可得出A=B xor C,所以就可以反算出A(4),A(6),A(7),A(8)了,再将A(1)-A(8)转为16进制字符,反转后再按顺序连接即是注册码。

用delphi表述如下:

代码:
procedure TForm1.btnGenSnClick(Sender: TObject); var A1,A2,A3,A4,A5,A6,A7,A8:integer; S1,S2,S3,S4,S5,S6,S7,S8,sn:string; begin edtsn.Text:=''; A1:=GetNum; //随机产生 A4:=A1 xor 85; S1:=reverse(OcttoHex(A1)); //转为16进制字符,再反转 S4:=reverse(OcttoHex(A4)); A2:=GetNum; A8:=A2 xor 110; S2:=reverse(OcttoHex(A2)); S8:=reverse(OcttoHex(A8)); A3:=GetNum; A6:=A3 xor 78; S3:=reverse(OcttoHex(A3)); S6:=reverse(OcttoHex(A6)); A5:=GetNum; A7:=A5 xor 25; S5:=reverse(OcttoHex(A5)); S7:=reverse(OcttoHex(A7)); sn:=s1+s2+s3+s4+s5+s6+s7+s8; //连接 edtsn.text:=sn; end;


========================================================================================
                                                   2005-10-12