首页
社区
课程
招聘
[旧帖] 破解010editor 2.0版(算法+注册机) 0.00雪花
2012-2-9 18:19 5293

[旧帖] 破解010editor 2.0版(算法+注册机) 0.00雪花

2012-2-9 18:19
5293
这是个老软件了,05年的,010Editor v2.0,程序没加壳,也没反调试,用Borland C++写的,下面开始。
载入OD以后,通过查找字符串可以找到注册相关的字符串,然后可以定位到注册部分的代码。
0046C3D1  |> \66:C745 B0 38>mov word ptr ss:[ebp-50],38       ;  上面是对注册名的完整性之类的验证,跳到这里算法才开始;
0046C3D7  |.  8D45 E4       lea eax,[local.7]
0046C3DA  |.  E8 B552F9FF   call 010Edito.00401694                   ;  SEH
0046C3DF  |.  8BD0          mov edx,eax
0046C3E1  |.  FF45 BC       inc [local.17]                           ;  堆栈 ss:[0012F48C]=00000001
0046C3E4  |.  8B4D 9C       mov ecx,[local.25]                       ;  ECX = 00CDC834
0046C3E7  |.  8B81 EC020000 mov eax,dword ptr ds:[ecx+2EC]           ;  EAX = 00CDB044
0046C3ED  |.  E8 0AD90D00   call 010Edito.00549CFC                   ;  SEH?
0046C3F2  |.  8D55 E4       lea edx,[local.7]                        ;  EDX指向注册名
0046C3F5  |.  52            push edx                                 ;  注册名入栈
0046C3F6  |.  FF35 A8275A00 push dword ptr ds:[5A27A8]               ;  0入栈
0046C3FC  |.  E8 AF020000   call 010Edito.0046C6B0                   ;  参数虽然是注册名,但是不用跟,这里不是关键
0046C401  |.  83C4 08       add esp,8
0046C404  |.  FF4D BC       dec [local.17]
0046C407  |.  8D45 E4       lea eax,[local.7]
0046C40A  |.  BA 02000000   mov edx,2
0046C40F  |.  E8 40381300   call 010Edito.0059FC54
0046C414  |.  66:C745 B0 44>mov word ptr ss:[ebp-50],44
0046C41A  |.  8D45 E0       lea eax,[local.8]
0046C41D  |.  E8 7252F9FF   call 010Edito.00401694
0046C422  |.  8BD0          mov edx,eax
0046C424  |.  FF45 BC       inc [local.17]
0046C427  |.  8B4D 9C       mov ecx,[local.25]
0046C42A  |.  8B81 F4020000 mov eax,dword ptr ds:[ecx+2F4]
0046C430  |.  E8 D3290B00   call 010Edito.0051EE08                   ;  出现假码
0046C435  |.  8D55 E0       lea edx,[local.8]
0046C438  |.  52            push edx                                 ;  假码入栈
0046C439  |.  FF35 A8275A00 push dword ptr ds:[5A27A8]               ;  0入栈
0046C43F  |.  E8 80020000   call 010Edito.0046C6C4	            ; 这里也不是关键
0046C444  |.  83C4 08       add esp,8
0046C447  |.  FF4D BC       dec [local.17]
0046C44A  |.  8D45 E0       lea eax,[local.8]
0046C44D  |.  BA 02000000   mov edx,2
0046C452  |.  E8 FD371300   call 010Edito.0059FC54                   ;  出现假码
0046C457  |.  6A 01         push 1
0046C459  |.  FF35 A8275A00 push dword ptr ds:[5A27A8]               ;  xiaomi入栈
0046C45F  |.  E8 ACE3FFFF   call 010Edito.0046A810
0046C464  |.  83C4 08       add esp,8
0046C467  |.  8945 94       mov [local.27],eax
0046C46A  |.  6A 01         push 1
0046C46C  |.  FF35 A8275A00 push dword ptr ds:[5A27A8]
0046C472  |.  E8 25E3FFFF   call 010Edito.0046A79C                   ;  关键call,跟进,看下面这个call调用完eax必须为0DB
0046C477  |.  83C4 08       add esp,8
0046C47A  |.  8945 90       mov [local.28],eax
0046C47D  |.  817D 90 DB000>cmp [local.28],0DB
0046C484  |.  75 35         jnz short 010Edito.0046C4BB              ;  eax的值与0DB比较,不相等就跳了
0046C486  |.  66:C745 B0 50>mov word ptr ss:[ebp-50],50
0046C48C  |.  BA 7D845C00   mov edx,010Edito.005C847D                ;  注册码正确. 谢谢你购买 010 Editor!


0046A79C  /$  55            push ebp
0046A79D  |.  8BEC          mov ebp,esp
0046A79F  |.  FF75 0C       push [arg.2]                             ;  1入栈
0046A7A2  |.  FF75 08       push [arg.1]                             ;  注册名入栈
0046A7A5  |.  E8 66000000   call 010Edito.0046A810                   ;  算法call,跟进,看下面这个call调用完eax必须为2D
0046A7AA  |.  83C4 08       add esp,8
0046A7AD  |.  83E8 2D       sub eax,2D                               ;  eax=2D注册才能成功; Switch (cases 2D..E7)
0046A7B0  |.  74 0E         je short 010Edito.0046A7C0
0046A7B2  |.  83E8 21       sub eax,21
0046A7B5  |.  74 17         je short 010Edito.0046A7CE
0046A7B7  |.  2D 99000000   sub eax,99
0046A7BC  |.  74 09         je short 010Edito.0046A7C7
0046A7BE  |.  EB 15         jmp short 010Edito.0046A7D5
0046A7C0  |>  B8 DB000000   mov eax,0DB                              ;  switch要跳转到这里注册才会成功; Case 2D of switch 


下面这个call才是真正的算法子程序,这里需要注意一下,分析的时候应该是从后面往前分析,因为我们前面已经分析出eax必须为2D,注册才能成功,所以先找关键字2D,果然在这里有一句0046AA57   >  B8 2D000000   mov eax,2D。所以以此为突破口可以分析出前面的跳转哪些必须跳,哪些不能跳,把这些跳转都先注释一下,后面就好分析了。
0046A810   $  55            push ebp
0046A811   .  8BEC          mov ebp,esp
0046A813   .  83C4 C0       add esp,-40
0046A816   .  B8 747D5C00   mov eax,010Edito.005C7D74
0046A81B   .  E8 3C651200   call 010Edito.00590D5C
0046A820   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A823   .  83C0 04       add eax,4
0046A826   .  E8 35561300   call 010Edito.0059FE60
0046A82B   .  84C0          test al,al                               ;  al必须为0
0046A82D   .  75 0F         jnz short 010Edito.0046A83E              ;  不能跳
0046A82F   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A832   .  83C0 08       add eax,8                                ;  eax指向假码
0046A835   .  E8 26561300   call 010Edito.0059FE60
0046A83A   .  84C0          test al,al                               ;  al必须为0
0046A83C   .  74 14         je short 010Edito.0046A852               ;  必须跳
0046A83E   >  B8 93000000   mov eax,93
0046A843   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046A846   .  64:8915 00000>mov dword ptr fs:[0],edx
0046A84D   .  E9 89020000   jmp 010Edito.0046AADB
0046A852   >  8D4D C4       lea ecx,dword ptr ss:[ebp-3C]
0046A855   .  51            push ecx
0046A856   .  FF75 08       push dword ptr ss:[ebp+8]
0046A859   .  E8 8A0A0000   call 010Edito.0046B2E8                   ;  对注册码格式作检查
0046A85E   .  83C4 08       add esp,8
0046A861   .  33C0          xor eax,eax
0046A863   .  8945 D4       mov dword ptr ss:[ebp-2C],eax            ;  局部变量0012FE28 = 0
0046A866   >  66:C745 E8 08>mov word ptr ss:[ebp-18],8               ;  局部变量0012FE3C = 8
0046A86C   .  8B55 D4       mov edx,dword ptr ss:[ebp-2C]            ;  edx = 0
0046A86F   .  8B1495 D47B5C>mov edx,dword ptr ds:[edx*4+5C7BD4]      ;  999
0046A876   .  8D45 FC       lea eax,dword ptr ss:[ebp-4]
0046A879   .  E8 EA511300   call 010Edito.0059FA68                   ;  貌似无用
0046A87E   .  FF45 F4       inc dword ptr ss:[ebp-C]                 ;  局部变量0012FE48 ++
0046A881   .  8D55 FC       lea edx,dword ptr ss:[ebp-4]
0046A884   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A887   .  83C0 04       add eax,4
0046A88A   .  E8 A9541300   call 010Edito.0059FD38
0046A88F   .  50            push eax
0046A890   .  FF4D F4       dec dword ptr ss:[ebp-C]
0046A893   .  8D45 FC       lea eax,dword ptr ss:[ebp-4]
0046A896   .  BA 02000000   mov edx,2
0046A89B   .  E8 B4531300   call 010Edito.0059FC54
0046A8A0   .  59            pop ecx
0046A8A1   .  84C9          test cl,cl                               ;  cl必须为0
0046A8A3   .  74 14         je short 010Edito.0046A8B9               ;  这里必须跳才能注册成功
0046A8A5   .  B8 E7000000   mov eax,0E7
0046A8AA   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046A8AD   .  64:8915 00000>mov dword ptr fs:[0],edx
0046A8B4   .  E9 22020000   jmp 010Edito.0046AADB
0046A8B9   >  FF45 D4       inc dword ptr ss:[ebp-2C]
0046A8BC   .  837D D4 01    cmp dword ptr ss:[ebp-2C],1
0046A8C0   .^ 7C A4         jl short 010Edito.0046A866               ;  其实真正的算法从这里才开始
0046A8C2   .  807D C7 9C    cmp byte ptr ss:[ebp-39],9C              ;  假码的7,8位与9C比较
0046A8C6   .  0F85 83000000 jnz 010Edito.0046A94F                    ;  不相等就跳;这里不能跳
0046A8CC   .  8A4D C4       mov cl,byte ptr ss:[ebp-3C]              ;  假码的1,2位放到cl
0046A8CF   .  324D CA       xor cl,byte ptr ss:[ebp-36]              ;  假码的1,2位与假码的13,14位异或
0046A8D2   .  884D C3       mov byte ptr ss:[ebp-3D],cl              ;  异或的结果局部变量0012FE17
0046A8D5   .  8A45 C5       mov al,byte ptr ss:[ebp-3B]              ;  假码的3,4位放到al
0046A8D8   .  3245 CB       xor al,byte ptr ss:[ebp-35]              ;  假码的3,4位与假码的15,16位异或
0046A8DB   .  33D2          xor edx,edx                              ;  异或的结果放到dh
0046A8DD   .  8AD0          mov dl,al
0046A8DF   .  C1E2 08       shl edx,8
0046A8E2   .  8A4D C6       mov cl,byte ptr ss:[ebp-3A]              ;  假码的5,6位放到cl
0046A8E5   .  324D C9       xor cl,byte ptr ss:[ebp-37]              ;  假码的5,6位与假码的11,12位异或
0046A8E8   .  33C0          xor eax,eax                              ;  异或的结果放到al
0046A8EA   .  8AC1          mov al,cl
0046A8EC   .  66:03D0       add dx,ax                                ;  3,4位和5,6位的结果放到了dx,3,4位在dh,5,6位在dl
0046A8EF   .  66:8955 C0    mov word ptr ss:[ebp-40],dx              ;  上面这个结果放到0012FE14
0046A8F3   .  8A55 C3       mov dl,byte ptr ss:[ebp-3D]
0046A8F6   .  52            push edx
0046A8F7   .  E8 26130000   call 010Edito.0046BC22                   ;  第三个参数是从这算的;关于这个参数见下面说明
0046A8FC   .  59            pop ecx                                  ;  al保存了从1,2位假码算来的结果
0046A8FD   .  33C9          xor ecx,ecx
0046A8FF   .  8AC8          mov cl,al
0046A901   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A904   .  8948 18       mov dword ptr ds:[eax+18],ecx            ;  1,2位的结果放到00C96D54
0046A907   .  66:8B55 C0    mov dx,word ptr ss:[ebp-40]              ;  3,4,5,6位的异或结果放到dx
0046A90B   .  52            push edx
0046A90C   .  E8 27130000   call 010Edito.0046BC38                   ;  第四个参数是在这里算的
0046A911   .  59            pop ecx
0046A912   .  0FB7C8        movzx ecx,ax
0046A915   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A918   .  8948 1C       mov dword ptr ds:[eax+1C],ecx
0046A91B   .  8B55 08       mov edx,dword ptr ss:[ebp+8]
0046A91E   .  837A 18 00    cmp dword ptr ds:[edx+18],0				; 第三个参数不能为0
0046A922   .  74 15         je short 010Edito.0046A939               ;  不能跳
0046A924   .  8B4D 08       mov ecx,dword ptr ss:[ebp+8]
0046A927   .  8379 1C 00    cmp dword ptr ds:[ecx+1C],0
0046A92B   .  74 0C         je short 010Edito.0046A939               ;  不能跳
0046A92D   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A930   .  8178 1C E8030>cmp dword ptr ds:[eax+1C],3E8            ;  第四个参数必须是3E8才行
0046A937   .  76 46         jbe short 010Edito.0046A97F              ;  必须跳
不好意思啊各位观众,这里我要剧透一下,不然可能会看版不懂,怎么冒出了个“第三个参数”?这其实是下面有一个函数,它根据注册名
和两个参数计算后8位注册码(注册码共16位),而这两个参数就是这个函数的第三、四个参数,其中一个参数是根据1、2位注册码与13
、14位注册码异或后,在做一系列计算来的,这个一系列计算就在上面算第三个参数的call里面。另一个参数是根据3,4,5,6位注册码与11
、12位,15、16位注册码做一系列计算来的。
这里有点麻烦了,感觉像个环,套住了,我要算后8位的注册码,必须知道第三个参数和第四个参数,从上面可以看到第四个参数必须是3E8,
但是第三个参数不确定(只知道不能为0)。而第三个参数又是1、2位注册码与15、16位注册码经过一系列运算来的,好像谁都是谁的前提,
无解。其实不是的,答案是超简单的,结论是第三个参数是可以随便定的!比如我把第三个参数确定为F2(我后面的注册机就是这么定的,
其实可以取00-FF之间任意数),那么第三、四个参数确定了,再配合注册名,后8位的注册码就算出来了,那1、2位的注册码也就算出来了。
第三、四个参数的call就不在这里贴了,跟进去看看很简单的。
这里接着上面的代码看吧
0046A939   >  B8 E7000000   mov eax,0E7
0046A93E   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046A941   .  64:8915 00000>mov dword ptr fs:[0],edx
0046A948   .  E9 8E010000   jmp 010Edito.0046AADB
0046A94D   .  EB 30         jmp short 010Edito.0046A97F
0046A94F   >  807D C7 FC    cmp byte ptr ss:[ebp-39],0FC             ;  假码的78位与0FC比较不相等就跳
0046A953   .  75 16         jnz short 010Edito.0046A96B              ;  不能跳
这里又要解释一下,上面分析说了根据eax为2D分析出的跳转哪些该跳,哪些不该跳。其实这些跳转不是一条线路的,分了两条线路,上面这
个78位与0FC比较就是其中一条支线,经过我的分析,这条支线是行不通的,所以程序不应该跳到这小段代码。
0046A955   .  8B4D 08       mov ecx,dword ptr ss:[ebp+8]
0046A958   .  C741 18 FF000>mov dword ptr ds:[ecx+18],0FF
0046A95F   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A962   .  C740 1C 01000>mov dword ptr ds:[eax+1C],1
0046A969   .  EB 14         jmp short 010Edito.0046A97F
0046A96B   >  B8 E7000000   mov eax,0E7
0046A970   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046A973   .  64:8915 00000>mov dword ptr fs:[0],edx
0046A97A   .  E9 5C010000   jmp 010Edito.0046AADB
0046A97F   >  8B4D 08       mov ecx,dword ptr ss:[ebp+8]
0046A982   .  FF71 1C       push dword ptr ds:[ecx+1C]               ;  第四个参数,由假码的5,6,7,8算来,结果必须是xxxx03E8
0046A985   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A988   .  FF70 18       push dword ptr ds:[eax+18]               ;  第三个参数,由假码的1,2位算来,我算的时候是F2
0046A98B   .  807D C7 9C    cmp byte ptr ss:[ebp-39],9C
0046A98F   .  0F94C2        sete dl
0046A992   .  83E2 01       and edx,1
0046A995   .  52            push edx                                 ;  第二个参数,索引开始号
0046A996   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046A999   .  83C0 04       add eax,4
0046A99C   .  E8 2F74F9FF   call 010Edito.00401DD0                   ;  把注册名取到eax;这个函数的参数只有一个eax
0046A9A1   .  50            push eax                                 ;  第一个参数,注册名
0046A9A2   .  E8 D90F0000   call 010Edito.0046B980                   ;  根据注册名算结果;关键call,跟进!
0046A9A7   .  83C4 10       add esp,10
0046A9AA   .  8945 D0       mov dword ptr ss:[ebp-30],eax            ;  al必须与[ebp-38]相等
0046A9AD   .  8A55 D0       mov dl,byte ptr ss:[ebp-30]
0046A9B0   .  80E2 FF       and dl,0FF
0046A9B3   .  3A55 C8       cmp dl,byte ptr ss:[ebp-38]              ;  根据注册名算得的结果与注册码的9,10位比较;
0046A9B6   .  74 14         je short 010Edito.0046A9CC               ;  必须跳
0046A9B8   .  B8 E7000000   mov eax,0E7
0046A9BD   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046A9C0   .  64:8915 00000>mov dword ptr fs:[0],edx
0046A9C7   .  E9 0F010000   jmp 010Edito.0046AADB
0046A9CC   >  8B4D D0       mov ecx,dword ptr ss:[ebp-30]
0046A9CF   .  C1E9 08       shr ecx,8
0046A9D2   .  80E1 FF       and cl,0FF
0046A9D5   .  3A4D C9       cmp cl,byte ptr ss:[ebp-37]              ;  与注册码的11,12位比较
0046A9D8   .  74 14         je short 010Edito.0046A9EE               ;  必须跳
0046A9DA   .  B8 E7000000   mov eax,0E7
0046A9DF   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046A9E2   .  64:8915 00000>mov dword ptr fs:[0],edx
0046A9E9   .  E9 ED000000   jmp 010Edito.0046AADB
0046A9EE   >  8B4D D0       mov ecx,dword ptr ss:[ebp-30]
0046A9F1   .  C1E9 10       shr ecx,10
0046A9F4   .  80E1 FF       and cl,0FF
0046A9F7   .  3A4D CA       cmp cl,byte ptr ss:[ebp-36]              ;  与注册码的13,14位比较
0046A9FA   .  74 14         je short 010Edito.0046AA10               ;  必须跳
0046A9FC   .  B8 E7000000   mov eax,0E7
0046AA01   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046AA04   .  64:8915 00000>mov dword ptr fs:[0],edx
0046AA0B   .  E9 CB000000   jmp 010Edito.0046AADB
0046AA10   >  8B4D D0       mov ecx,dword ptr ss:[ebp-30]
0046AA13   .  C1E9 18       shr ecx,18
0046AA16   .  80E1 FF       and cl,0FF
0046AA19   .  3A4D CB       cmp cl,byte ptr ss:[ebp-35]              ;  与注册码的15,16位比较
0046AA1C   .  74 14         je short 010Edito.0046AA32               ;  必须跳
0046AA1E   .  B8 E7000000   mov eax,0E7
0046AA23   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046AA26   .  64:8915 00000>mov dword ptr fs:[0],edx
0046AA2D   .  E9 A9000000   jmp 010Edito.0046AADB
0046AA32   >  807D C7 9C    cmp byte ptr ss:[ebp-39],9C              ;  注册码7,8位与9C比较?
0046AA36   .  75 30         jnz short 010Edito.0046AA68              ;  不能跳
0046AA38   .  8B4D 0C       mov ecx,dword ptr ss:[ebp+C]
0046AA3B   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
0046AA3E   .  3B48 18       cmp ecx,dword ptr ds:[eax+18]
0046AA41   .  76 14         jbe short 010Edito.0046AA57              ;  必须跳
0046AA43   .  B8 4E000000   mov eax,4E
0046AA48   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046AA4B   .  64:8915 00000>mov dword ptr fs:[0],edx
0046AA52   .  E9 84000000   jmp 010Edito.0046AADB
0046AA57   >  B8 2D000000   mov eax,2D                               ;  跳到这里注册就成功了
0046AA5C   .  8B55 D8       mov edx,dword ptr ss:[ebp-28]
0046AA5F   .  64:8915 00000>mov dword ptr fs:[0],edx
0046AA66   .  EB 73         jmp short 010Edito.0046AADB


----------------------0046A9A2   .  E8 D90F0000   call 010Edito.0046B980 ;根据注册名算结果--------------
0046B994  |.  59            pop ecx
0046B995  |.  8945 F0       mov [local.4],eax                        ;  注册名长度
0046B998  |.  33D2          xor edx,edx
0046B99A  |.  8955 F4       mov [local.3],edx
0046B99D  |.  8B4D F4       mov ecx,[local.3]
0046B9A0  |.  3B4D F0       cmp ecx,[local.4]                        ;  注册名大于0?
0046B9A3  |.  0F8D 3B010000 jge 010Edito.0046BAE4
0046B9A9  |>  8B45 08       /mov eax,[arg.1]
0046B9AC  |.  8B55 F4       |mov edx,[local.3]
0046B9AF  |.  0FBE0C10      |movsx ecx,byte ptr ds:[eax+edx]         ;  取注册名的第edx位
0046B9B3  |.  51            |push ecx
0046B9B4  |.  E8 7FBB1200   |call 010Edito.00597538                  ;  按位处理注册名,这里不跟进了,里面好像是用表处理的
0046B9B9  |.  59            |pop ecx
0046B9BA  |.  8945 F8       |mov [local.2],eax
0046B9BD  |.  837D 0C 00    |cmp [arg.2],0
0046B9C1  |.  0F84 86000000 |je 010Edito.0046BA4D
0046B9C7  |.  8B45 F8       |mov eax,[local.2]
0046B9CA  |.  8B1485 2C805C>|mov edx,dword ptr ds:[eax*4+5C802C]	; 这里好像也是在查表,我注册机是按查表写的。
0046B9D1  |.  0355 FC       |add edx,[local.1]
0046B9D4  |.  8B4D F8       |mov ecx,[local.2]
0046B9D7  |.  83C1 0D       |add ecx,0D
0046B9DA  |.  81E1 FF000000 |and ecx,0FF
0046B9E0  |.  33148D 2C805C>|xor edx,dword ptr ds:[ecx*4+5C802C]
0046B9E7  |.  8B45 F8       |mov eax,[local.2]
0046B9EA  |.  83C0 2F       |add eax,2F
0046B9ED  |.  25 FF000000   |and eax,0FF
0046B9F2  |.  0FAF1485 2C80>|imul edx,dword ptr ds:[eax*4+5C802C]
0046B9FA  |.  6B4D F4 13    |imul ecx,[local.3],13
0046B9FE  |.  81E1 FF000000 |and ecx,0FF
0046BA04  |.  03148D 2C805C>|add edx,dword ptr ds:[ecx*4+5C802C]
0046BA0B  |.  8B45 F4       |mov eax,[local.3]
0046BA0E  |.  8D04C0        |lea eax,dword ptr ds:[eax+eax*8]
0046BA11  |.  8B4D 10       |mov ecx,[arg.3]
0046BA14  |.  8BD9          |mov ebx,ecx
0046BA16  |.  C1E1 04       |shl ecx,4
0046BA19  |.  03CB          |add ecx,ebx
0046BA1B  |.  03C1          |add eax,ecx
0046BA1D  |.  25 FF000000   |and eax,0FF
0046BA22  |.  031485 2C805C>|add edx,dword ptr ds:[eax*4+5C802C]
0046BA29  |.  6B45 F4 0D    |imul eax,[local.3],0D
0046BA2D  |.  8B4D 14       |mov ecx,[arg.4]
0046BA30  |.  8BD9          |mov ebx,ecx
0046BA32  |.  C1E1 04       |shl ecx,4
0046BA35  |.  2BCB          |sub ecx,ebx
0046BA37  |.  03C1          |add eax,ecx
0046BA39  |.  25 FF000000   |and eax,0FF
0046BA3E  |.  031485 2C805C>|add edx,dword ptr ds:[eax*4+5C802C]
0046BA45  |.  8955 FC       |mov [local.1],edx
0046BA48  |.  E9 88000000   |jmp 010Edito.0046BAD5
0046BA4D  |>  8B45 F8       |mov eax,[local.2]
0046BA50  |.  8B1485 2C805C>|mov edx,dword ptr ds:[eax*4+5C802C]
0046BA57  |.  0355 FC       |add edx,[local.1]
0046BA5A  |.  8B4D F8       |mov ecx,[local.2]
0046BA5D  |.  83C1 3F       |add ecx,3F
0046BA60  |.  81E1 FF000000 |and ecx,0FF
0046BA66  |.  33148D 2C805C>|xor edx,dword ptr ds:[ecx*4+5C802C]
0046BA6D  |.  8B45 F8       |mov eax,[local.2]
0046BA70  |.  83C0 17       |add eax,17
0046BA73  |.  25 FF000000   |and eax,0FF
0046BA78  |.  0FAF1485 2C80>|imul edx,dword ptr ds:[eax*4+5C802C]
0046BA80  |.  8B4D F4       |mov ecx,[local.3]
0046BA83  |.  8BC1          |mov eax,ecx
0046BA85  |.  C1E1 03       |shl ecx,3
0046BA88  |.  2BC8          |sub ecx,eax
0046BA8A  |.  81E1 FF000000 |and ecx,0FF
0046BA90  |.  03148D 2C805C>|add edx,dword ptr ds:[ecx*4+5C802C]
0046BA97  |.  8B4D F4       |mov ecx,[local.3]
0046BA9A  |.  8D0CC9        |lea ecx,dword ptr ds:[ecx+ecx*8]
0046BA9D  |.  8B45 10       |mov eax,[arg.3]
0046BAA0  |.  8BD8          |mov ebx,eax
0046BAA2  |.  C1E0 04       |shl eax,4
0046BAA5  |.  03C3          |add eax,ebx
0046BAA7  |.  03C8          |add ecx,eax
0046BAA9  |.  81E1 FF000000 |and ecx,0FF
0046BAAF  |.  03148D 2C805C>|add edx,dword ptr ds:[ecx*4+5C802C]
0046BAB6  |.  6B45 F4 0D    |imul eax,[local.3],0D
0046BABA  |.  8B4D 14       |mov ecx,[arg.4]
0046BABD  |.  8BD9          |mov ebx,ecx
0046BABF  |.  C1E1 04       |shl ecx,4
0046BAC2  |.  2BCB          |sub ecx,ebx
0046BAC4  |.  03C1          |add eax,ecx
0046BAC6  |.  25 FF000000   |and eax,0FF
0046BACB  |.  031485 2C805C>|add edx,dword ptr ds:[eax*4+5C802C]
0046BAD2  |.  8955 FC       |mov [local.1],edx
0046BAD5  |>  FF45 F4       |inc [local.3]
0046BAD8  |.  8B45 F4       |mov eax,[local.3]
0046BADB  |.  3B45 F0       |cmp eax,[local.4]
0046BADE  |.^ 0F8C C5FEFFFF \jl 010Edito.0046B9A9
0046BAE4  |>  8B45 FC       mov eax,[local.1]
0046BAE7  |.  5B            pop ebx
0046BAE8  |.  8BE5          mov esp,ebp
0046BAEA  |.  5D            pop ebp
0046BAEB  \.  C3            retn

----------------------0046A9A2   .  E8 D90F0000   call 010Edito.0046B980 ;根据注册名算结果--------------
关于这一段算法的分析我没做过多注释,分析的时候我直接写在记事本里面了,因为要根据这段写注册机。
这段用到了四个局部变量,分别如下:
local.1存放后8位注册码临时结果(初始化为0);
local.2(当前字母ascii码);
local.3(当前字母的索引号);
local.4(注册名长度);

取出的字母ascii码为索引在5c802c表里查表,取出表中数字(一个整型)与local.1(初始化位0)相加得tmp1;

local.2加0D,结果与0FF做AND操作得tmp2,将tmp2为索引取表的结果与tmp1相异或放tmp1;

取当前字母ascii码,加上2F,结果与0FF做AND操作得tmp3,将tmp3为索引取表的结果与tmp1相乘(有符号乘)放tmp1;

当前字母索引×13(16进制)的结果与0FF做AND操作得tmp4,将tmp4为索引取表的结果与tmp1相加放tmp1;

当前字母索引×9得tmp5,取第三个参数左移4位与第三个参数相加再与tmp5相加,结果与0FF做AND操作放tmp5,将tmp5为索引取表的结果与tmp1相加放tmp1;

当前字母索引×0D得tmp6,取03E8左移4位减去03E8放tmp7,tmp6 += tmp7,and tmp7,0FF,将tmp7为索引取表的结果与tmp1相加放tmp1;

local.1 = tmp1;

迭代完注册名就OK了。

呵呵。这对着汇编码写的算法描述就好像我翻译英文一样呀,见笑了,大家凑合着看下吧。

关于对注册名的处理,那个call我没有完全搞定,经过试验,注册名是英文的话它会将它转为大写,这个过程好像不需要用到表,但是它确实是用到了表,不知道源码怎么写的。我的注册机也照样用的表,表是直接从内存窗口里面抠出来的。  注册名可以包含符号、字母和数字,但是汉字算出来的注册码还是不对,我没再搞了,大家有兴趣就试试吧。

注册机是用C写的控制台版的。
// crackCode.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "string.h"

void code2string( char* scode, int bcode, int fcode );
void halfcode2string( char* scode, int code );

int matrix[256] = {
	969622712, 594890599,1593930257,1052452058,
	890701766,1677293387, 394424968, 266815521,
	1532978959,1211194088,2019260265, 729421127,
	953225874,1117854514, 892543556,2000911200,
	514538256,1400963072, 486675118,1862498216,
	1136668818, 758909582,1653935295, 821063674,
	888606944, 687085563, 890056597,1513495898,
	365692427, 184357836, 677395407, 863045227,
	818746596, 391985767,1842768403, 758385145,
	1478392706,1985112985,1552765320, 746944881,
	368385984,1758203153,1240817244, 660489060,
	756944316,1290697955, 844453952, 288239112,
	1769473626,1922176006, 826636519, 391520695,
	1081548223,1069693142,1244729994, 766313326,
	1101031894, 624951698,14501479,1794907983,
	1460682958,1660839647,1104890686, 897721119,
	1442187162, 480708164, 454443986,1064446153,
	1595150448,1041527979,1145775470,1399869657,
	255985995, 802693350,2005610078,1897360642,
	2146073193,1538606632, 431647857, 964049561,
	395138253,19164808, 856904574, 730737943,
	708645054,1506870658, 933323739, 819349658,
	1780571206, 236747382, 533160167,2042104933,
	670325172,2040165158,1354372994, 705785180,
	1669754395,1066536508,1426207888,1437950089,
	741941201, 796931522,1694313338,1290302874,
	1367672048,2039808424,1062939821, 954597728,
	1668694488, 859122242,1369582617, 140269649,
	53024683, 729221831, 816609203, 736893191,
	55706320, 262747091,1629838835, 581764799,
	1488480625,1607077349,1879925846,1453945819,
	1521965565, 856558562,1530662365,1230847072,
	1404918182,1281256849,1238970765, 272453753,
	1640907491,2127893021, 350314733, 556617458,
	654390256,1648581270, 531062411,1862873022,
	1241517385,1471028336, 5121143,1444839026,
	1183580211,1573659650,2018540230,1487873223,
	234237236, 898254600,1023090193, 728843548,
	2007454357,1451820833, 267351539, 302982385,
	26807015, 865879122, 664886158, 195503981,
	1625037691,1330347906,1742434311,1330272217,
	1645368040, 542321916,1782121222, 411042851,
	435386250,1176704752,1454246199,1136813916,
	1707755005, 224415730, 201138891, 989750331,
	1006010278,1147286905, 406860280, 840388503,
	1282017578,1605698145,23396724, 862145265,
	1898780916,1855549801,1571519230,2083204840,
	1859876276,1602449334,1009413590, 690816450,
	86131931, 345661263,1565025600, 857544170,
	1329948960,1211787679, 994381573, 991984748,
	1956475134,1098146294,1655714289, 659576699,
	689116467,1485584392, 451884118, 255590636,
	2108114754,1266252396,1589326471,2019907768,
	15552498,1651075358, 614606175,1656823678,
	797605325,1681594366,2005080248, 624648446,
	884695971,1526931791,1595240948, 439447199,
	2060396292, 680093752, 409028215, 469068267,
	195583689,1791650630, 507724330,1364025102,
	1094582668, 813049577,32316922,1240756058,
	1176200235,2104494066, 325396055,1796606917,
	1709197385, 525495836,1510101430, 735526761,
	767523533,1374043776,1559389967, 567085571,
	1560216161, 867042846,1001796703,1568754293,
	628841972, 173812827, 379868455, 384973125
};

short int nameMatrix[256] = {
	32, 32, 32, 32, 32, 32, 32, 32,
	32, 40, 40, 40, 40, 40, 32, 32,
	32, 32, 32, 32, 32, 32, 32, 32,
	32, 32, 32, 32, 32, 32, 32, 32,
	72, 16, 16, 16, 16, 16, 16, 16,
	16, 16, 16, 16, 16, 16, 16, 16,
	132,132,132,132,132,132,132,132,
	132,132, 16, 16, 16, 16, 16, 16,
	16,385,385,385,385,385,385,257,
	257,257,257,257,257,257,257,257,
	257,257,257,257,257,257,257,257,
	257,257,257, 16, 16, 16, 16, 16,
	16,386,386,386,386,386,386,258,
	258,258,258,258,258,258,258,258,
	258,258,258,258,258,258,258,258,
	258,258,258, 16, 16, 16, 16, 32
	,
};

int _tmain(int argc, _TCHAR* argv[])
{
	char sname[20];
	scanf("%s", sname);

	int bcode = 0;	//注册码的后8位
	int fcode = 0;	//注册码的前8位

	unsigned int i,k;
	for ( i = 0; i < strlen(sname); i++ ) 
	{
		k = (unsigned int)sname[i];
		if ( (nameMatrix[k] & 0x2) )
			sname[i] -= 0x20;
	}

	for ( i = 0; i < strlen(sname); i++ ) 
	{
		k = (unsigned int)sname[i];	//	取当前字母ascii码
		
		int itmp1 = matrix[k] + bcode;
		unsigned int uitmp2 = (k+0x0D) & 0xFF;
		itmp1 ^= matrix[uitmp2];	//	异或

		uitmp2 = (k+0x2F) & 0xFF;
		itmp1 *= matrix[uitmp2];

		uitmp2 = (i*0x13) & 0xFF;
		itmp1 += matrix[uitmp2];

		uitmp2 = ( (0xF2<<4) + 0xF2 + (i*9) ) & 0xFF;
		itmp1 += matrix[uitmp2];

		uitmp2 = ( (0x03E8<<4) - 0x03E8 + (i*0x0D) ) & 0xFF;
		itmp1 += matrix[uitmp2];

		bcode = itmp1;						// code 包含了后8位的注册码
	}

	printf("%X\n", bcode);

	fcode = (bcode>>16) & 0xFF;				// 注册码的1,2位等于第13,14位
	fcode |= 0x9C000000;					// 注册码的7,8位是9C,固定不能改

	//3,4位的注册码等于注册码的15,16位与0xA9异或
	fcode |= ( (bcode & 0xFF000000) ^ 0xA9000000 ) >> 16;
	
	//5,6位的注册码等于注册码的11,12位与0x3B异或
	fcode |= ( (bcode & 0x0000FF00) ^ 0x00003B00 ) << 8;

	printf("%X\n", fcode);

	//将code转换成注册码字符串
	char scode[20];
	code2string( scode, bcode, fcode );
	printf("%s\n", scode);

	return 0;
}

void code2string( char* scode, int bcode, int fcode )
{
	halfcode2string( scode, fcode );
	halfcode2string( &scode[10], bcode );
	scode[19] = '\0'; 
}

void halfcode2string( char* scode, int code )
{
	int j = 0;
	for ( int i = 0; i < 4; i++ )
	{
		unsigned int tmpcode;
		tmpcode = code >> (i*8);

		char c = (char)(tmpcode>>4) & 0x0F;
		if ( c < 0x0A )	//	是数字
			c += 0x30;
		else			//	是字母
			c += 0x37;
		scode[j++] = c;

		c = (char)tmpcode & 0x0F;
		if ( c < 0x0A )	//	是数字
			c += 0x30;
		else			//	是字母
			c += 0x37;
		scode[j++] = c;

		if ( i == 1 || i == 3 )
			scode[j++] = '-';
	}
}

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

上传的附件:
收藏
点赞5
打赏
分享
最新回复 (47)
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
cntrump 13 2012-2-9 18:34
2
0
虽然软件非常老,支持共享精神。
雪    币: 96
活跃值: (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wkxq 2012-2-9 18:42
3
0
一如既往的支持!
雪    币: 153
活跃值: (29)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xiaocszn 2012-2-9 18:53
4
0
谢谢楼上两位帮顶!不知道这个够不够申请邀请码。
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
guohaogf 2012-2-9 18:57
5
0
现在简直是一头雾水
雪    币: 1252
活跃值: (510)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
zhujian 2 2012-2-9 19:05
6
0
不错,后排学习中。
雪    币: 72
活跃值: (60)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
后恋 2 2012-2-9 19:27
7
0
够了!好好学习的,就会发邀请码的
雪    币: 71
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mumaren 2012-2-9 20:20
8
0
不错啊

继续努力
雪    币: 12491
活跃值: (2952)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ytyay 2012-2-9 20:44
9
0
不错啊   支持一下
雪    币: 51
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
暗行 2012-2-10 00:59
10
0
好久没研究过这个了
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
贺一鸣 2012-2-10 09:03
11
0
路过,自己分析的么?
雪    币: 227
活跃值: (66)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
Naylon 2 2012-2-10 09:33
12
0
新人技术都碉堡了。。学习
邀请码肯定够,等版主吧
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
loongzyd 10 2012-2-10 10:20
13
0
感谢楼主的分享精神,大家一起努力吧。
雪    币: 19823
活跃值: (3100)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
atompure 2012-2-10 13:53
14
0
Oh, you are very good !
Salute !
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
petech 2012-2-10 14:10
15
0
LZ,讲解的很详细,你已经不能算菜鸟了,以后请多多帮助大伙
雪    币: 153
活跃值: (29)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xiaocszn 2012-2-10 14:39
16
0
谢谢各楼朋友的支持与鼓励!
雪    币: 153
活跃值: (29)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xiaocszn 2012-2-10 14:43
17
0
是的。这个其实又适合菜鸟,又不适合菜鸟。因为它没壳没反调试,直接根据字符串还能定位到注册的代码。不适合菜鸟是因为注册的算法有点多了,分析要花点时间。这个软件如果拿来爆破应该是很适合菜鸟的。
雪    币: 153
活跃值: (29)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xiaocszn 2012-2-10 14:49
18
0
哎,菜不菜只有自己知道呀!这个东西我搞了两天两通宵才搞出来,从算法开始到结束之间的每个call几乎都跟进去了,跟进去了还得看半天才知道这个call是不是有用。现在只能说是只入门了的菜鸟。
雪    币: 34
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
maladebazi 2012-2-10 16:26
19
0
顶起来 偷闲来顶贴啊 好教程啊
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hemingquan 2012-2-11 10:22
20
0
大家都 要加油了~~~~~
雪    币: 67
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lantianlan 2012-2-11 14:12
21
0
学习路过。。。
雪    币: 132
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无聊之人 2012-2-12 00:30
22
0
说到邀请码 上次不小心点了一下 100kxb 买了一个  ,到现在还没有用,谁要的话就送给谁了。就1个,先到先得~~~
雪    币: 29
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qqbwz 2012-2-12 15:09
23
0
楼主你这个软件哪里找的,我没看你文章,这是我第一次爆破软件(除了上次那个crackme)。想不到还有这样的方法爆破:找到成功注册信息后把前面的两个跳转改了就成功了(有一牛人说:要用od插件查找字符)。
雪    币: 153
活跃值: (29)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xiaocszn 2012-2-13 14:09
24
0
呵呵,这是我看天草破解全集 初级第18课看到的,他那里就是爆破的这个软件,我拿来逆向注册码发帖申请邀请码的。
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
面谱人 2012-2-13 15:26
25
0
软件虽老,但可以作学习用。。。。。
游客
登录 | 注册 方可回帖
返回