• 标 题:空档接龙助手2.01注册码分析。 (6千字)
  • 作 者:hoto
  • 时 间:2003-1-13 10:07:39
  • 链 接:http://bbs.pediy.com

记得学习破解时,第一次成功看到注册码而注册成功的就是这个软件,现在出了2.01版,CrackABC给我这最新版本之后,就再次对他进行了一次分析,这一次就分析一下它的注册码的生成过程吧。


0040640F  MOV ECX,ESI
00406411  CALL FREECELL.0044143E
00406416  MOV DWORD PTR SS:[ESP+F4],EAX
0040641D  LEA ECX,DWORD PTR SS:[ESP+14]
00406421  CALL FREECELL.00431955  <---------进入“注册”窗口
00406426  CMP EAX,1      <-------有没有点击“确定”按钮,1为确定
00406429  JNZ FREECELL.004064F0
0040642F  MOV AL,BYTE PTR DS:[ESI+C1]
00406435  TEST AL,AL
00406437  JNZ FREECELL.004064F0
0040643D  LEA ECX,DWORD PTR SS:[ESP+EC]
00406444  PUSH ECX
00406445  LEA ECX,DWORD PTR SS:[ESP+10]
00406449  CALL FREECELL.0043550A
0040644E  MOV EDI,DWORD PTR SS:[ESP+F4]
00406455  PUSH ECX
00406456  LEA EDX,DWORD PTR SS:[ESP+10]
0040645A  MOV ECX,ESP
0040645C  MOV DWORD PTR SS:[ESP+14],ESP
00406460  PUSH EDX
00406461  MOV BYTE PTR SS:[ESP+108],2
00406469  CALL FREECELL.0043550A
0040646E  PUSH EBP <--------EBP中为系统信息码的十六进制值,但是注册码生成过程中没有用到它。
0040646F  CALL FREECELL.00405DB0 <---------此CALL为计算注册码的地方。跟入可分析注册码生成过程。
00406474  ADD ESP,8
00406477  CMP EAX,EDI <------------比较,EAX为真注册码,EDI为输入的注册码(输入值的十六进制)
00406479  JNZ SHORT FREECELL.004064DF <----------不相等,则跳过。相等时,写入注册表,同时显示注册成功对话框。
0040647B  PUSH 0                                                ; /Arg3 = 00000000
0040647D  PUSH 0                                                ; |Arg2 = 00000000
0040647F  PUSH FREECELL.0045428C                ; |Arg1 = 0045428C
00406484  CALL FREECELL.0043849A                  ; \FREECELL.0043849A
00406489  MOV EAX,DWORD PTR SS:[ESP+C]
0040648D  MOV ECX,ESI
0040648F  PUSH EAX                                            ; /Arg3
00406490  PUSH FREECELL.004541B0              ; |Arg2 = 004541B0 ASCII "UserName"
00406495  PUSH FREECELL.00454158                ; |Arg1 = 00454158 ASCII "Options"
0040649A  CALL FREECELL.00438648                  ; \FREECELL.00438648
0040649F  PUSH EDI                                            ; /Arg3
004064A0  PUSH FREECELL.004541BC              ; |Arg2 = 004541BC ASCII "RegisterCode"
004064A5  PUSH FREECELL.00454158              ; |Arg1 = 00454158 ASCII "Options"
004064AA  MOV ECX,ESI                                      ; |
004064AC  CALL FREECELL.004385D3                ; \FREECELL.004385D3
004064B1  MOV BYTE PTR DS:[ESI+C1],1
004064B8  CALL FREECELL.00435B86
004064BD  TEST EAX,EAX
004064BF  JE SHORT FREECELL.004064CA
004064C1  MOV EDX,DWORD PTR DS:[EAX]
004064C3  MOV ECX,EAX
004064C5  CALL DWORD PTR DS:[EDX+74]
004064C8  JMP SHORT FREECELL.004064CC
004064CA  XOR EAX,EAX
004064CC  MOV EAX,DWORD PTR DS:[EAX+1C]
004064CF  PUSH 105                            ; /Redraw = RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW
004064D4  PUSH 0                              ; |hUpdateRgn = NULL
004064D6  PUSH 0                              ; |pRect = NULL
004064D8  PUSH EAX                            ; |hWnd
004064D9  CALL DWORD PTR DS:[<&USER32.RedrawWi>; \RedrawWindow  重新显示整个窗口,窗口中将显示“本软件注册为: ...”等字样。



-----------------------进入注册码生成过程的CALL中------------------------

00405DB8  MOV ECX,DWORD PTR DS:[EAX-8]
00405DBB  MOV ESI,0D431 <---------初始化  ESI
00405DC0  TEST ECX,ECX  <---------比较用户名是否为空,ECX中为用户名字串长度。
00405DC2  JLE SHORT FREECELL.00405DF8
00405DC4  /  MOVSX EAX,BYTE PTR DS:[EDI+EAX] <--------取出用户名中的一位到EAX
00405DC8  |  XOR EAX,14142135  <-----对其进行一次异或
00405DCD  |  PUSH EAX                <-----将EAX压栈
00405DCE  |  CALL FREECELL.004108E4         
00405DD3  |  ADD ESP,4
00405DD6  |  CALL FREECELL.004108F1    <-------经过此CALL 后,EAX已经经过了一次变化
-------------------------------------------------------------------
变化的等效代码如下:
MOV    ECX,EAX
IMUL  ECX,ECX,343FD
ADD    ECX,269EC3
MOV    EAX,ECX
SHR    EAX,10
ADD    EAX,7FFF
-------------------------------------------------------------------
00405DDB  |  MOV ECX,ESI       
00405DDD  |  SHR ECX,10
00405DE0  |  SHL ESI,10
00405DE3  |  OR ECX,ESI
00405DE5  |  ADD EAX,ECX
00405DE7  |  XOR EAX,27181828 
00405DEC  |  INC EDI
00405DED  |  MOV ESI,EAX          <-------变化后,放入ESI中。
00405DEF  |  MOV EAX,DWORD PTR SS:[ESP+10]
00405DF3  |  CMP EDI,DWORD PTR DS:[EAX-8]
00405DF6  \  JL SHORT FREECELL.00405DC4  <----用户字串结束时,结束循环。
00405DF8  PUSH 75BCD15
00405DFD  CALL FREECELL.004108E4
00405E02  ADD ESP,4
00405E05  MOV EDI,64 <--------初始化循环次数为100次

00405E0A  /CALL FREECELL.004108F1<------此CALL内有一个变化过程
----------------------------------------------------------------
变换的等效代码为:
MOV  ECX ,[地址1]
IMUL  ECX,ECX,343FD
ADD    ECX,1269EC3
MOV  [地址1],ECX
MOV  EAX,ECX
SHR  EAX,10
AND  EAX,7FFF
----------------------------------------------------------------
00405E0F  |MOV EDX,ESI
00405E11  |SHR EDX,10
00405E14  |SHL ESI,10
00405E17  |OR EDX,ESI
00405E19  |ADD EAX,EDX
00405E1B  |XOR EAX,17320508
00405E20  |DEC EDI
00405E21  |MOV ESI,EAX <-----------经过变化后,再放入ESI
00405E23  \JNZ SHORT FREECELL.00405E0A <-------循环次数达100次后,结束循环。
00405E25  LEA ECX,DWORD PTR SS:[ESP+10]
00405E29  CALL FREECELL.00435795
00405E2E  MOV EAX,ESI  <----------将结果放入EAX后返回
00405E30  POP EDI
00405E31  POP ESI
00405E32  RETN

--------------------------------TC20的算法实现--------------------------------
main()
{
    char name[256];
    int nlen;
    int i;
    unsigned long temp1,temp2,temp3;
    unsigned long result;
    printf("输入注册用户名:");
    scanf("%s",name);
    nlen = strlen(name);
    result = 0xd431;
    for(i=0;i<nlen;i++)
    {
        temp1 = name[i];
        temp1 = temp1 ^ 0x14142135;
        temp1 = temp1 * 0x343fd;
        temp1 += 0x269ec3;
        temp1 = temp1 >> 0x10;
        temp1 = temp1 & 0x7fff;

        temp2 = result;
        temp2 = temp2 >> 0x10;
        result = result << 0x10;
        temp2 = temp2 | result;
        temp1 += temp2;
        temp1 = temp1 ^ 0x27181828;

        result = temp1;
    }

    temp1 = 123456789;
    for(i=0;i<100;i++)
    {
        temp1 *= 0x343fd;
        temp1+= 0x269ec3;

        temp2 = temp1;
        temp2 = temp2 >> 0x10;
        temp2 = temp2 & 0x7fff;

        temp3 = result;
        temp3 = temp3 >> 0x10;
        result = result << 0x10;
        temp3 = temp3 | result;

        temp3 += temp2;
        temp3 = temp3 ^ 0x17320508;
        result = temp3;

    }
        printf("注册码: %lu\r\n",result);
        getch();
}
--------------------------------------------------------------------------