软件名称:QQ聊天记录读取器
下载地址:http://www.ngnsss.com/
调试工具:OllyDBG
软件限制:软件运行1分钟后自动关闭,注册码重启验证
测试环境:WINXP SP2
看到lhynich发的贴http://bbs.pediy.com/showthread.php?s=&threadid=22817,我觉得对于新手,更应该鼓励,而不是耻笑,但是楼主确实太猖狂了点,是那些高手觉得这个软
件太简单了,所以没有去理你,但是每个人都有第一次,第一次将一个软件击败确实值得高兴,可以理解。我顺便也把这个算法简单分析了下,希望楼主有所进步.......
00402B60 . 6A FF PUSH -1 ; 此处F2下断
00402B62 . 68 08344200 PUSH QQ聊天记.00423408
00402B67 . 64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00402B6D . 50 PUSH EAX
00402B6E . 64:8925 00000>MOV DWORD PTR FS:[0],ESP
00402B75 . 83EC 08 SUB ESP,8
00402B78 . 56 PUSH ESI
00402B79 . 8BF1 MOV ESI,ECX
00402B7B . 6A 01 PUSH 1
00402B7D . E8 6C720100 CALL QQ聊天记.00419DEE
00402B82 . A1 FCE54200 MOV EAX,DWORD PTR DS:[42E5FC]
00402B87 . 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
00402B8B . 8D8E 1C010000 LEA ECX,DWORD PTR DS:[ESI+11C]
00402B91 . C74424 14 000>MOV DWORD PTR SS:[ESP+14],0
00402B99 . 51 PUSH ECX
00402B9A . 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8]
00402B9E . E8 0A870100 CALL QQ聊天记.0041B2AD
00402BA3 . 51 PUSH ECX
00402BA4 . 8D5424 08 LEA EDX,DWORD PTR SS:[ESP+8]
00402BA8 . 8BCC MOV ECX,ESP
00402BAA . 896424 0C MOV DWORD PTR SS:[ESP+C],ESP
00402BAE . 52 PUSH EDX
00402BAF . E8 79830100 CALL QQ聊天记.0041AF2D
00402BB4 . E8 77FEFFFF CALL QQ聊天记.00402A30 ; 算法CALL,F7跟入
00402BB9 . 83C4 04 ADD ESP,4
00402BBC . 85C0 TEST EAX,EAX ; CALL中返回的EAX的值是否为0
00402BBE . 6A 00 PUSH 0
00402BC0 . 68 A0E24200 PUSH QQ聊天记.0042E2A0
00402BC5 . 74 15 JE SHORT QQ聊天记.00402BDC ; 是0就跳到错误的地方
00402BC7 . 68 A8E24200 PUSH QQ聊天记.0042E2A8 ; 注册成功
00402BCC . 8BCE MOV ECX,ESI
00402BCE . E8 BF6A0100 CALL QQ聊天记.00419692
00402BD3 . 8BCE MOV ECX,ESI
00402BD5 . E8 DE990100 CALL QQ聊天记.0041C5B8
00402BDA . EB 0C JMP SHORT QQ聊天记.00402BE8
00402BDC > 68 94E24200 PUSH QQ聊天记.0042E294 ; 注册号无效
00402BE1 . 8BCE MOV ECX,ESI
00402BE3 . E8 AA6A0100 CALL QQ聊天记.00419692
================================================================================================
00402A30 /$ 6A FF PUSH -1
00402A32 |. 68 E8334200 PUSH QQ聊天记.004233E8
00402A37 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00402A3D |. 50 PUSH EAX
00402A3E |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP
00402A45 |. 83EC 18 SUB ESP,18
00402A48 |. 53 PUSH EBX
00402A49 |. 8B4C24 2C MOV ECX,DWORD PTR SS:[ESP+2C] ; 注册码放到ECX中
00402A4D |. 33C0 XOR EAX,EAX ; EAX清空,也可以说下面准备为EAX赋值
00402A4F |. 894424 05 MOV DWORD PTR SS:[ESP+5],EAX
00402A53 |. 33DB XOR EBX,EBX ; EBX清空
00402A55 |. 66:894424 09 MOV WORD PTR SS:[ESP+9],AX
00402A5A |. 895C24 24 MOV DWORD PTR SS:[ESP+24],EBX
00402A5E |. 884424 0B MOV BYTE PTR SS:[ESP+B],AL
00402A62 |. 8B41 F8 MOV EAX,DWORD PTR DS:[ECX-8] ; 取注册码长度,可以看到DS:[ECX-8]值为们输入注册码的长度,放入EAX
00402A65 |. 83F8 10 CMP EAX,10 ; 注册码的长度与16对比
00402A68 |. 885C24 04 MOV BYTE PTR SS:[ESP+4],BL
00402A6C |. 0F8C C0000000 JL QQ聊天记.00402B32 ; 如果小于16位就跳到错误的地方,可以算爆破点1
00402A72 |. 56 PUSH ESI
00402A73 |. 68 04010000 PUSH 104
00402A78 |. 8D4C24 34 LEA ECX,DWORD PTR SS:[ESP+34]
00402A7C |. E8 F68A0100 CALL QQ聊天记.0041B577 ; 取注册码
00402A81 |. 8B10 MOV EDX,DWORD PTR DS:[EAX] ; DS:[EAX]中放着注册码的第一位,也就是说将注册码第一位放入EDX
00402A83 |. 33F6 XOR ESI,ESI
00402A85 |. 895424 10 MOV DWORD PTR SS:[ESP+10],EDX ; 再放入ESP+10
00402A89 |. 8B48 04 MOV ECX,DWORD PTR DS:[EAX+4] ; 取注册码第5位置EAX
00402A8C |. 894C24 14 MOV DWORD PTR SS:[ESP+14],ECX ; 再放入ESP+14中
00402A90 |. 8B50 08 MOV EDX,DWORD PTR DS:[EAX+8] ; 取注册码第9位置EAX
00402A93 |. 895424 18 MOV DWORD PTR SS:[ESP+18],EDX ; 再放入ESP+18中
00402A97 |. 8B40 0C MOV EAX,DWORD PTR DS:[EAX+C] ; 取注册码第13位置EAX
00402A9A |. 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX ; 再放入ESP+1C中
00402A9E |> 8A4C34 10 /MOV CL,BYTE PTR SS:[ESP+ESI+10] ; 这里是循环的开始,逐个取注册码的十六进制码,放入CL中
00402AA2 |. 51 |PUSH ECX ; ECX中就是所取注册码的十六进制码
00402AA3 |. E8 68FFFFFF |CALL QQ聊天记.00402A10 ; 这个CALL是对注册码进行小小变形,跟进看看
00402AA8 |. 83C4 04 |ADD ESP,4
00402AAB |. 884434 10 |MOV BYTE PTR SS:[ESP+ESI+10],AL ; AL就是上面那个CALL中返回的注册码变形后的值
00402AAF |. 46 |INC ESI ; ESI=ESI+1,上面有个ESI清空的步骤,所以ESI的初始值为0
00402AB0 |. 83FE 10 |CMP ESI,10 ; ESI的累加值是否大于16
00402AB3 |.^ 7C E9 \JL SHORT QQ聊天记.00402A9E ; 小于的话就继续循环
00402AB5 |. 33C0 XOR EAX,EAX ; EAX清空
00402AB7 |. 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10] ; ESP+10从上面可以知道它放的是第一位注册码
00402ABB |. 5E POP ESI
00402ABC 8A51 01 MOV DL,BYTE PTR DS:[ECX+1] ; 这里又是个循环,[ECX+1]中放着注册码的第二位,也就是说依次取注册码的2、4、6...等位,放
入DL中
00402ABF |. 8A19 |MOV BL,BYTE PTR DS:[ECX] ; [ECX]中放着注册码的1、3、5、7...等位,放入BL中
00402AC1 |. C0E2 04 |SHL DL,4 ; 将DL中的值逻辑左移4位
00402AC4 |. 02D3 |ADD DL,BL ; DL=DL+BL,就是将右移后的结果加BL的值,重新放回DL
00402AC6 |. 83C1 02 |ADD ECX,2 ; ECX=ECX+2,ECX可以从上面找到它的值,它的初始值为注册码的第一位,每循环一次加2
00402AC9 |. 885404 04 |MOV BYTE PTR SS:[ESP+EAX+4],DL ; 最终的DL结果放入ESP+EAX+4,注意这里的EAX,EAX的初始值为0
00402ACD |. 40 |INC EAX ; 计算器,EAX=EAX+1,EAX的初始值为0,可以看到上面对EAX有个清空动作
00402ACE |. 83F8 08 |CMP EAX,8 ; 累计是否大于8
00402AD1 |.^ 7C E9 \JL SHORT QQ聊天记.00402ABC ; 小于则继续循环
00402AD3 |. 8A4424 07 MOV AL,BYTE PTR SS:[ESP+7] ; [ESP+7]的值放入AL,[ESP+7]指上面的[ESP+EAX+4]中的EAX=3时的值,也就是第4次循环计算后DL
的值
00402AD7 |. 8A5C24 04 MOV BL,BYTE PTR SS:[ESP+4] ; 第1次循环后DL的值
00402ADB |. 8A4C24 0B MOV CL,BYTE PTR SS:[ESP+B] ; 第8次循环后DL的值
00402ADF |. 8A5424 05 MOV DL,BYTE PTR SS:[ESP+5] ; 第2次循环后DL的值
00402AE3 |. 32C3 XOR AL,BL ; AL的值异或BL的值
00402AE5 |. 8A5C24 06 MOV BL,BYTE PTR SS:[ESP+6] ; 第3次循环后DL的值
00402AE9 |. 32CA XOR CL,DL ; CL的值异或DL的值
00402AEB |. 8A5424 09 MOV DL,BYTE PTR SS:[ESP+9] ; 第6次循环后DL的值
00402AEF |. 32D3 XOR DL,BL ; DL的值异或BL的值
00402AF1 |. 8A5C24 08 MOV BL,BYTE PTR SS:[ESP+8] ; 第5次循环后DL的值
00402AF5 |. 325C24 0A XOR BL,BYTE PTR SS:[ESP+A] ; 第7次循环后DL的值
00402AF9 |. 3C 38 CMP AL,38 ; AL是否为38H
00402AFB 75 35 JNZ SHORT QQ聊天记.00402B32 ; 不是就跳错,爆破2
00402AFD |. 80F9 6E CMP CL,6E ; CL是否为6E
00402B00 75 30 JNZ SHORT QQ聊天记.00402B32 ; 不是就跳错,爆破3
00402B02 |. 80FA 4E CMP DL,4E ; DL是否为4E
00402B05 75 2B JNZ SHORT QQ聊天记.00402B32 ; 不是就跳错,爆破4
00402B07 |. 80FB 1A CMP BL,1A ; BL是否为1A
00402B0A 75 26 JNZ SHORT QQ聊天记.00402B32 ; 不是就跳错,爆破5
00402B0C |. 8D4C24 2C LEA ECX,DWORD PTR SS:[ESP+2C] ; [ESP+2C的值放入ECX
00402B10 |. C74424 24 FFF>MOV DWORD PTR SS:[ESP+24],-1 ; ESP+24地址放入常数-1
00402B18 |. E8 9B860100 CALL QQ聊天记.0041B1B8
00402B1D |. B8 01000000 MOV EAX,1 ; EAX赋值1
00402B22 |. 5B POP EBX
00402B23 |. 8B4C24 18 MOV ECX,DWORD PTR SS:[ESP+18]
00402B27 |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX
00402B2E |. 83C4 24 ADD ESP,24
00402B31 |. C3 RETN
=======================================================================================================
这是跟进CALL 00402A10:
00402A10 /$ 8A4424 04 MOV AL,BYTE PTR SS:[ESP+4] ; 取该位注册码
00402A14 |. 3C 30 CMP AL,30 ; 是否大于0
00402A16 |. 7C 07 JL SHORT QQ聊天记.00402A1F
00402A18 |. 3C 39 CMP AL,39 ; 是否小于9,说明是判断是否为数字
00402A1A |. 7F 03 JG SHORT QQ聊天记.00402A1F
00402A1C |. 2C 30 SUB AL,30 ; 减30H后返回,就是注册码假如是数字就减30,这就是刚才说的变形
00402A1E |. C3 RETN
00402A1F |> 3C 41 CMP AL,41 ; 是否大于41H,既A
00402A21 |. 7C 07 JL SHORT QQ聊天记.00402A2A
00402A23 |. 3C 46 CMP AL,46 ; 是否小于46H,即F
00402A25 |. 7F 03 JG SHORT QQ聊天记.00402A2A
00402A27 |. 2C 37 SUB AL,37 ; 如果该注册码是A-F之间的就减37H
00402A29 |. C3 RETN
00402A2A |> \0C FF OR AL,0FF ; 除了数字和A-F外置FF,错误
00402A2C \. C3 RETN
=======================================================================================================================
总结:
注册码必须大于等于16位,先将注册码变形,碰到数字,将数字的十六进制值减30H,碰到字母,字母必须在大写的A-F之间,每位减37H后返回新码。
在新码中每取两位注册码的十六进制码分八组进行计算,计算规则都是将第二位逻辑左移4位后加第一位的值,这样得到四组结果,它们要符合以下规则:
第四组的计算结果异或第一组的结果必须为38
第二组的计算结果异或第八组的结果必须为6E
第六组的计算结果异或第三组的结果必须为4E
第五组的计算结果异或第七组的结果必须为1A
因为是异或和逻辑左移运算,所以我们可以逆推真正的注册码
提供一组可用的注册码:396F78BA899C2889,要爆破的话改文中提到的五处。
======================================================================
由于注册码只要求有效,不是根据用户名、机器码等换算而来的,所以没必要与算法结合写注册机,只要能达到显示注册码即可,可以偷懒了,放上一个DELPHI的搞笑源码:
procedure TForm1.Button1Click(Sender: TObject);
begin
If Length(edit1.text) = 0 Then
Begin
MessageBox(0, '留个大名吧!', '提示', MB_OK + MB_ICONWARNING);
Exit;
End;
MessageBox(0, '396F78BA899C2889', '这是可用的注册码!', MB_OK + MB_ICONWARNING);
end;
=====================================================================