鱼C论坛

 找回密码
 立即注册
查看: 2906|回复: 0

010editor算法分析

[复制链接]
发表于 2018-1-26 21:08:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 溯__ 于 2018-1-26 21:11 编辑

1.定位到注册算法入口
跟着序号①②③④看:
00DD57DE   .  PUSH 0x9
00DD57E0   .  CALL 010Edito.0040A82B
00DD57E5   .  MOV ECX,DWORD PTR DS:[0x2E70F20]
00DD57EB   .  MOV EBX,EAX //ebx接收函数0040A82B的返回值
00DD57ED   .  PUSH 0x4389
00DD57F2   .  PUSH 0x9
00DD57F4   .  CALL 010Edito.00409CA0// ④所以此时查看函数00409CA0,这个函数内部jmp到013BE220
00DD57F9   .  MOV ECX,DWORD PTR DS:[0x2E70F20]
00DD57FF   .  MOV EDI,EAX  //edi接收函数00409CA0返回值③
00DD5801   .  CMP EBX,0xE7
00DD5807   .  JE 010Edito.00DD5900 //ebx是函数0040A82B的返回值,默认情况是0xE7 ,所以此处会跳转
00DD580D   .  CMP DWORD PTR DS:[ECX+0x2C],0x0
00DD5811   .  JE 010Edito.00DD5900
..........................................
00DD5900   >  CMP EDI,0xDB    // 比较edi和0xDB的值②
00DD5906      JNZ 010Edito.00DD5A38  // 此处不能跳转,EDI = 0xDB,edi是函数00409CA0的返回值..........................................其间无长跳转
00DD599F   .  CALL DWORD PTR DS:[<&Qt5Core.??YQS>;  Qt5Core.?append@QString@@QAEAAV1@PBD@Z
00DD59A5   >  PUSH 010Edito.0231D3A4             ;  ASCII " Thank you for purchasing 010 Editor!"①
00DD59AA   .  LEA ECX,DWORD PTR SS:[EBP-0x1C]
00DD59AD   .  CALL DWORD PTR DS:[<&Qt5Core.??YQS>;  Qt5Core.?append@QString@@QAEAAV1@PBD@Z

接下来:

定位到013BE220,发现返回0xDB的在Case 2D of switch 013BE243,所以需要函数0040A82B返回0x2D,
查看函数0040A82B,这个函数内部jmp到013BD900,接着查看地址013BD900处
地址013BD900也就是注册验证的核心地方了,可以在里面直接返回0x2D爆破,当然这里分析一下其算法

013BE220      PUSH EBP
013BE221      MOV EBP,ESP
013BE223      PUSH ESI
013BE224      MOV ESI,ECX
013BE226      CMP DWORD PTR DS:[ESI+0x2C],0x0
013BE22A  |.  JE SHORT 010Edito.013BE236
013BE22C  |.  MOV EAX,0x113
013BE231  |.  POP ESI
013BE232  |.  POP EBP
013BE233  |.  RETN 0x8
013BE236  |>  PUSH EDI
013BE237  |.  PUSH [ARG.2]
013BE23A  |.  MOV EDI,[ARG.1]
013BE23D  |.  PUSH EDI
013BE23E  |.  CALL 010Edito.0040A82B
013BE243  |.  CMP EAX,0x2D                       ;  Switch (cases 2D..E7)
.....................................
013BE2EF  |>  POP EDI                            ;  Case 2D of switch 013BE243
013BE2F0  |.  MOV EAX,0xDB
013BE2F5  |.  POP ESI
013BE2F6  |.  POP EBP
013BE2F7  \.  RETN 0x8

这里先写明013BD900(也就是函数0040A82B)的参数情况
参数一:0x9
参数二: 0x4389
2.“处理用户名函数”之前对注册号的判断
函数中在013BD99D之前是获取注册码和一些检测工作
013BD96D MOV ECX,EDI
013BD96F PUSH EAX                                                     ;  局部变量地址
013BD970 CALL 010Edito.00409B74                                       ;  获取注册码

下面是注册码和局部变量的对应关系
注册码KEY[]
12 34  56 78  87 65  43  21  00  11
0  1  2  3   4  5   6   7   8   9

                0019CFF8  90 FA 01 6C E0 4E 2C 03 01 00 00 00 12 34 56 78
                0019D008  87 65 43 21 00 11 6D 6B 08 06 86 05 C6 4C 89 6B
                0019D018  00 00 00 00 6C D0 19 00 89 5A 88 01 FF FF FF FF
ebp->        0019D028  78 D0 19 00                                    

ebp-0x24  KEY[0]
ebp-0x23  KEY[1]
ebp-0x22  KEY[2]
ebp-0x21  KEY[3]
ebp-0x20  KEY[4]
ebp-0x1F  KEY[5]
ebp-0x1E  KEY[6]
ebp-0x1D  KEY[7]
ebp-0x1C  KEY[8]
ebp-0x1B  KEY[9]

接着会判断KEY[3]:
KEY[3] == 0x9C
013BD99D   MOV BL,BYTE PTR SS:[EBP-0x21]             ;BL = KEY[3]
013BD9A0   MOV BH,BYTE PTR SS:[EBP-0x1F]                ;BH = KEY[5]       
013BD9A3   CMP BL,0x9C                                ;判断KEY[3] 是否为0x9C
013BD9A6   JNZ SHORT 010Edito.013BDA18
013BD9A8   MOV AL,BYTE PTR SS:[EBP-0x24]              ;情况1:KEY[3] = 9C
013BD9AB   XOR AL,BYTE PTR SS:[EBP-0x1E]                  ;al = KEY[0] xor KEY[6]
013BD9AE   MOV BYTE PTR SS:[EBP-0x18],AL                ;BYTE ptr [EBP-0x18] = KEY[0] xor KEY[6]
013BD9B1   MOV AL,BYTE PTR SS:[EBP-0x23]
013BD9B4   XOR AL,BYTE PTR SS:[EBP-0x1D]                ; al = KEY[1] xor KEY[7]
013BD9B7   PUSH DWORD PTR SS:[EBP-0x18]                        ; push KEY[0] xor KEY[6]  作为0040764E的参数
013BD9BA   MOVZX ECX,AL
013BD9BD   MOV EAX,0x100                                               
013BD9C2   IMUL CX,AX                                                        ; cx = (KEY[1] xor KEY[7])*0x100
013BD9C6   MOV AL,BYTE PTR SS:[EBP-0x22]                ; al = KEY[2]
013BD9C9   XOR AL,BH                                                        ; al = KEY[2] xor KEY[5]
013BD9CB   MOVZX EAX,AL  
013BD9CE   ADD CX,AX                                                           ; cx = ((KEY[1] xor KEY[7])*0x100) + (KEY[2] xor KEY[5])
013BD9D1   MOVZX ESI,CX                                                        ; esi = ((KEY[1] xor KEY[7])*0x100) + (KEY[2] xor KEY[5])

013BD9D4   CALL 010Edito.0040764E               

                013BCDF0  />  PUSH EBP                                                        ((((KEY[0] xor KEY[6]) xor 0x18) + 0x3D)xor 0xA7)
                013BCDF1  |.  MOV EBP,ESP
                013BCDF3  |.  MOV EAX,[ARG.1]     ;arg1 = KEY[0] xor KEY[6]
                013BCDF6  |.  XOR AL,0x18
                013BCDF8  |.  ADD AL,0x3D
                013BCDFA  |.  XOR AL,0xA7
                013BCDFC  |.  POP EBP
                013BCDFD  \.  RETN

               
013BD9D9   .  0FB6C0                 MOVZX EAX,AL                                                ;eax = ((((KEY[0] xor KEY[6]) xor 0x18) + 0x3D)xor 0xA7)
013BD9DC   .  56                     PUSH ESI                                                        ;esi = ((KEY[1] xor KEY[7])*0x100) + (KEY[2] xor KEY[5])
013BD9DD   .  8947 1C                MOV DWORD PTR DS:[EDI+0x1C],EAX   
013BD9E0   .  E8 EDA904FF            CALL 010Edito.004083D2

                013BCD60  />  PUSH EBP
                013BCD61  |.  MOV EBP,ESP
                013BCD63  |.  MOV EAX,[ARG.1]
                013BCD66  |.  MOV ECX,0xB    ecx = 0xB
                013BCD6B  |.  XOR EAX,0x7892
                013BCD70  |.  ADD EAX,0x4D30
                013BCD75  |.  XOR EAX,0x3421  eax=((((KEY[1] xor KEY[7])*0x100) + (KEY[2] xor KEY[5])) xor 0x7892)+0x4d30) xor 0x3421
                013BCD7A  |.  MOVZX EAX,AX
                013BCD7D  |.  CDQ
                013BCD7E  |.  IDIV ECX      
                013BCD80  |.  TEST EDX,EDX  ecx/eax的余数
                013BCD82  |.  JE SHORT 010Edito.013BCD86 如果余数不为0,就跳出,否则清零eax
                013BCD84  |.  XOR EAX,EAX
                013BCD86  |>  POP EBP
                013BCD87  \.  RETN

013BD9E5     MOV ECX,DWORD PTR DS:[EDI+0x1C]    ;ECX = ((((KEY[0] xor KEY[6]) xor 0x18) + 0x3D)xor 0xA7)
013BD9E8     ADD ESP,0x8
013BD9EB     MOVZX EAX,AX ; EAX= ((((KEY[1] xor KEY[7])*0x100) + (KEY[2] xor KEY[5])) xor 0x7892)+0x4d30) xor 0x3421
013BD9EE     MOV DWORD PTR DS:[EDI+0x20],EAX
013BD9F1     TEST ECX,ECX                                ;如果ecx = 0,就结束
013BD9F3     JE 010Edito.013BDBB5
013BD9F9     TEST EAX,EAX                                ;如果eax = 0,就结束
013BD9FB     JE 010Edito.013BDBB5
013BDA01     CMP EAX,0x3E8                                ;如果eax > 0x3E8,就结束
013BDA06     JA 010Edito.013BDBB5   
013BDA0C     CMP ECX,0x2      ;如果小于 CF = 1 否则为0
013BDA0F     SBB ESI,ESI    ; -CF
013BDA11     AND ESI,ECX
013BDA13     JMP 010Edito.013BDACB

结果:DWORD PTR DS:[EDI+0x1C] = ((((KEY[0] xor KEY[6]) xor 0x18) + 0x3D)xor 0xA7)
DWORD PTR DS:[EDI+0x20] = (((((KEY[1] xor KEY[7])*0x100) + (KEY[2] xor KEY[5])) xor 0x7892)+0x4d30) xor 0x3421)/0xB
对应的C代码
case 0x9C:
        {
                DWORD EAX = (((((KEY[ 1 ] ^ KEY[ 7 ]) * 0x100) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421;
                DWORD ECX = (((KEY[ 0 ] ^ KEY[ 6 ]) ^ 0x18) + 0x3D) ^ 0xA7;
                if (EAX % 0xB != 0)
                {
                        EAX = 0;//error
                }
                if (EAX == 0 || EAX > 0x3E8)
                {
                        return;//error
                }
                if(ECX == 0)
                {
                        return;//error
                }
                if (ECX < 0x2)
                {
                        // ECX == 1,ESI=1
                        ESI = ECX;
                }
                else
                {
                        ESI = 0;
                }
                // 这里ECX如果大于0x2 ESI=0否则=ECX=1,至于ECX的值是多少,在后面可以看到
                EDI0x20 = EAX/0xB;
                break;

        }
KEY[3] == 0xFC
013BDA18   >  80FB FC                CMP BL,0xFC        //如果KEY[3] != 0x9C
013BDA1B   .  75 1F                  JNZ SHORT 010Edito.013BDA3C        //如果KEY[3] == 0xFC
013BDA1D   .  C747 1C FF000000       MOV DWORD PTR DS:[EDI+0x1C],0xFF   ;  Case FC of switch 013BD9A3
013BDA24   .  BE FF000000            MOV ESI,0xFF
013BDA29   .  C747 20 01000000       MOV DWORD PTR DS:[EDI+0x20],0x1
013BDA30   .  C747 30 01000000       MOV DWORD PTR DS:[EDI+0x30],0x1
013BDA37   .  E9 8F000000            JMP 010Edito.013BDACB

结果:DWORD PTR DS:[EDI+0x1C] = 0xFF
DWORD PTR DS:[EDI+0x20] = 0x1
// 后面判断,如果是0xFC,是不会返回0x2D,这里就略去
KEY[3] == 0xAC
013BDA3C   >  CMP BL,0xAC         //如果KEY[3] != 0xFC   
013BDA3F   .  JNZ 010Edito.013BDBB5               
013BDA45   .  MOV AL,BYTE PTR SS:[EBP-0x23]      ;  KEY[3] = 0xAC

013BDA48   .  XOR AL,BYTE PTR SS:[EBP-0x1D]      ;al = KEY[1] xor KEY[7]
013BDA4B   .  MOVZX ECX,AL ;ecx =  KEY[1] xor KEY[7]
013BDA4E   .  MOV EAX,0x100
013BDA53   .  IMUL CX,AX                                  ;ecx = (KEY[1] xor KEY[7])*0x100
013BDA57   .  MOV AL,BYTE PTR SS:[EBP-0x22] ;al = KEY[2]
013BDA5A   .  XOR AL,BH ; al = KEY[2] xor KEY[5]
013BDA5C   .  MOV DWORD PTR DS:[EDI+0x1C],0x2
013BDA63   .  MOVZX EAX,AL
013BDA66   .  ADD CX,AX ;cx = (KEY[1] xor KEY[7]) << 2)+(KEY[2] xor KEY[5])
013BDA69   .  MOVZX EAX,CX  ;eax = (KEY[1] xor KEY[7]) << 2)+(KEY[2] xor KEY[5])
013BDA6C   .  PUSH EAX
013BDA6D   .  CALL 010Edito.004083D2

                013BCD60  />PUSH EBP
                013BCD61  |.MOV EBP,ESP
                013BCD63  |.MOV EAX,[ARG.1];eax = (KEY[1] xor KEY[7]) << 2)+(KEY[2] xor KEY[5])
                013BCD66  |.MOV ECX,0xB    ecx = 0xB
                013BCD6B  |.XOR EAX,0x7892
                013BCD70  |.ADD EAX,0x4D30
                013BCD75  |.XOR EAX,0x3421  eax= ((((KEY[1] xor KEY[7])<<2) + (KEY[2] xor KEY[5])) xor 0x7892)+0x4d30) xor 0x3421
                013BCD7A  |.MOVZX EAX,AX
                013BCD7D  |.CDQ
                013BCD7E  |.IDIV ECX      eax = (((((KEY[1] xor KEY[7])*0x100) + (KEY[2] xor KEY[5])) xor 0x7892)+0x4d30) xor 0x3421)/0xB
                013BCD80  |.TEST EDX,EDX  eax/ecx的余数
                013BCD82  |.JE SHORT 010Edito.013BCD86 如果余数不为0,就跳出,否则清零eax
                013BCD84  |.XOR EAX,EAX
                013BCD86  |>POP EBP
                013BCD87  \.RETN



013BDA72   .MOVZX EAX,AX
013BDA75   .ADD ESP,0x4
013BDA78   .MOV DWORD PTR DS:[EDI+0x20],EAX   
013BDA7B   .TEST EAX,EAX  
013BDA7D   .JE 010Edito.013BDBB5  ;等于0就返回
013BDA83   .CMP EAX,0x3E8 ;eax= ((((KEY[1] xor KEY[7])<<2) + (KEY[2] xor KEY[5])) xor 0x7892)+0x4d30) xor 0x3421
013BDA88   .JA 010Edito.013BDBB5  ;大于0x3E8就返回

013BDA8E   MOVZX EDX,BYTE PTR SS:[EBP-0x1B] ;edx = KEY[9]
013BDA92   MOVZX ECX,BYTE PTR SS:[EBP-0x20] ;ecx = KEY[4]
013BDA96   MOVZX EAX,BH  ;EAX = KEY[5]
013BDA99   XOR EDX,EAX  ;edx = KEY[9] xor KEY[5]

013BDA9B   MOVZX EAX,BYTE PTR SS:[EBP-0x1C]   ;eax = KEY[8]
013BDA9F   XOR ECX,EAX  ecx = KEY[4] xor KEY[8]
013BDAA1   SHL EDX,0x8  ; edx = (KEY[9] xor KEY[5]) << 8

013BDAA4   MOVZX EAX,BYTE PTR SS:[EBP-0x1E]  ;eax = KEY[6]
013BDAA8   ADD EDX,ECX ; EDX = ((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8])
013BDAAA   MOVZX ECX,BYTE PTR SS:[EBP-0x24] ;ECX = KEY[0]
013BDAAE   SHL EDX,0x8   ; EDX = (((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8]))<<0x8
013BDAB1   XOR ECX,EAX   ; ECX = KEY[0] xor KEY[6];
013BDAB3   ADD EDX,ECX   ; EDX = ((((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8]))<<0x8)+(KEY[0] xor KEY[6])
013BDAB5   PUSH 010Edito.005B8C27  
013BDABA   PUSH EDX ;
013BDABB   CALL 010Edito.0040A790

        013BCCD0   PUSH EBP
        013BCCD1   MOV EBP,ESP
        013BCCD3   MOV ECX,[ARG.1] ; ;ECX = ((((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8]))<<0x8)+(KEY[0] xor KEY[6])
        013BCCD6   MOV EAX,0xF0F0F0F1 ;eax = 0xF0F0F0F1
        013BCCDB   XOR ECX,[ARG.2] ;ecx = (((((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8]))<<0x8)+(KEY[0] xor KEY[6]))xor 005B8C27
        013BCCDE   XOR ECX,0x22C078;ecx = ((((((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8]))<<8) + (KEY[6]  xor KEY[0]))xor 005B8C27) xor 0x22c078
        013BCCE4   SUB ECX,0x2C175 ;ecx = (((((((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8]))<<8) + (KEY[6]  xor KEY[0]))xor 005B8C27) xor 0x22c078) - 0x2C175
        013BCCEA   XOR ECX,0xFFE53167;
        013BCCF0   AND ECX,0xFFFFFF;ecx=(((((((((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8]))<<8) + (KEY[6]  xor KEY[0]))xor 005B8C27) xor 0x22c078) - 0x2C175) xor 0xFFE53167) and 0xFFFFFF   // ECX<0xFFFFFF
       
        013BCCF6   MUL ECX ; EDX:EAX = 0xF0F0F0F1*ecx  edx*0x100000000+eax = 0xF0F0F0F1*ecx ;EDX = ECX
        013BCCF8   SHR EDX,0x4 ;   
        013BCCFB   MOV EAX,EDX;     
        013BCCFD   SHL EAX,0x4;                                            
        013BCD00   ADD EAX,EDX;                  
       
        013BCD02   SUB ECX,EAX ;

        013BCD04   MOV EAX,0x0 ;eax = 0
        013BCD09   CMOVE EAX,EDX  ;zf = 1时移动

        013BCD0C   POP EBP
        013BCD0D   RETN


013BDAC0   .  83C4 08                ADD ESP,0x8
013BDAC3   .  8945 F0                MOV DWORD PTR SS:[EBP-0x10],EAX
013BDAC6   .  8947 34                MOV DWORD PTR DS:[EDI+0x34],EAX
013BDAC9   .  8BF0                   MOV ESI,EAX

结果:
DWORD PTR SS:[EBP-0x10] = EAX
DWORD PTR DS:[EDI+0x20] = (((((KEY[1] xor KEY[7])*0x100) + (KEY[2] xor KEY[5])) xor 0x7892)+0x4d30) xor 0x3421)/0xB
case 0xAC:
        {
                DWORD EAX = (((((KEY[ 1 ] ^ KEY[ 7 ]) * 0x100) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421;
                if(EAX % 0xB != 0)
                 {
                        EAX = 0;//error
                 }
                if(EAX == 0 || EAX > 0x3E8)
                {
                        return;//error
                }
                DWORD ECX = (((((((((KEY[ 9 ] ^ KEY[ 5 ]) << 8) + (KEY[ 4 ] ^ KEY[ 5 ])) << 8) + (KEY[ 6 ] ^ KEY[ 0 ])) ^ 0x05B8C27) ^ 0x22c078) - 0x2C175) ^ 0xFFE53167) & 0xFFFFFF;
                EAX = 0xF0F0F0F1;
                DWORD EDX = 0;
                伪代码:EDX:EAX = EAX*ECX;
                EDX = EDX >> 0x4;
                EAX = (EDX << 0x4) + EDX;
                ECX = ECX - EAX;
                if (ECX == 0)// ECX = EAX
                {
                        EAX = EDX;//right
                }
                else
                {
                        EAX = 0;//error
                }
                EDI0x20 = ((((((KEY[ 1 ] ^ KEY[ 7 ]) << 2) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421)/0xB;
                ESI = EAX;
                break;
        }



3.“处理用户名函数”
实际上面就是准备了ESI和EDI0x20 (DWORD PTR DS:[EDI+0x20])
“处理用户名函数”的参数为:
参数一:用户名字符串首地址
参数二:如果类型是0xFC就是0,否则是1,用于判断类型
参数三:上面获取的ESI   
参数四:上面获取的EDI0x20  

调用处
013BDACB   >  LEA EAX,DWORD PTR SS:[EBP-0x14]
013BDACE   .  PUSH EAX
013BDACF   .  LEA ECX,DWORD PTR DS:[EDI+0x4]
013BDAD2   CALL DWORD PTR DS:[<&Qt5Core.?toUt>;  013BDAD8   .  PUSH DWORD PTR DS:[EDI+0x20]   ;之前值已经获取((((KEY[1] xor KEY[7])<<2) + (KEY[2] xor KEY[5])) xor 0x7892)+0x4d30) xor 0x3421
013BDADB   .  XOR EAX,EAX ;
013BDADD   .  MOV DWORD PTR SS:[EBP-0x4],0x0  
013BDAE4   .  CMP BL,0xFC   
013BDAE7   .  LEA ECX,DWORD PTR SS:[EBP-0x14]
013BDAEA   .  PUSH ESI ;ESI
013BDAEB   .  SETNE AL ;如果BL != 0xFC, AL = 1
013BDAEE   .  PUSH EAX ;
013BDAEF   .  CALL DWORD PTR DS:[<&Qt5Core.?data>;  Qt5Core.?data@QByteArray@@QAEPADXZ// 这个函数没有参数,传出用户名
013BDAF5   .  PUSH EAX    ;传入的是用户名
013BDAF6   .  CALL 010Edito.00402E50   ;处理用户名
函数中
013BCE60  /> USH EBP
013BCE61  |. MOV EBP,ESP
013BCE63  |. SUB ESP,0x10
013BCE66  |. MOV EDX,[ARG.1]                           ;  EDX = 用户名
013BCE69  |. XOR ECX,ECX                                ;ECX = 0
013BCE6B  |. PUSH ESI        ;保存ESI
013BCE6C  |. MOV ESI,EDX     ;esi = 用户名
013BCE6E  |. MOV [LOCAL.1],ECX     ;[LOCAL.1] = 0
013BCE71  |. PUSH EDI ;保存EDI
013BCE72  |. LEA EDI,DWORD PTR DS:[ESI+0x1]   ;edi = 用户名地址+1,用于下面的判断
013BCE75  |> MOV AL,BYTE PTR DS:[ESI]   ;al=pStr[0]
013BCE77  |. INC ESI ;pStr = pStr+1
013BCE78  |. TEST AL,AL ;判断是否到达字符串结尾
013BCE7A  |.^JNZ SHORT 010Edito.013BCE75  
013BCE7C  |. SUB ESI,EDI   ;以上为获取字符串长度,<ESI = 用户名长度>

013BCE7E  |. XOR EDI,EDI        ; EDI = 0
013BCE80  |. TEST ESI,ESI   ;判断字符串是否为空
013BCE82  |. JLE 010Edito.013BCF78   ; 长度<=0就跳出
013BCE88  |. PUSH EBX  ; 保存EBX
013BCE89  |. MOV EBX,[ARG.4]  ;EBX = Arg_EDI0x20
013BCE8C  |. MOV [LOCAL.4],ECX                                           ;[LOCAL.4] = 0
013BCE8F  |. MOV [LOCAL.3],ECX                                           ;[LOCAL.3] = 0
013BCE92  |. MOV ECX,[ARG.3]; ECX = Arg_esi
013BCE95  |. SHL EBX,0x4  ;EBX = Arg_EDI0x20<<0x4
013BCE98  |. SUB EBX,[ARG.4];                               EBX = (Arg_EDI0x20<<0x4)-Arg_EDI0x20
013BCE9B  |. SHL ECX,0x4;ECX = Arg_esi << 0x4
013BCE9E  |. ADD ECX,[ARG.3];ECX = Arg_esi << 0x4 + Arg_esi
013BCEA1  |. MOV [LOCAL.2],ECX                             ; LOCAL.2 = Arg_esi << 0x4 + Arg_esi

013BCEA4  |> MOVZX EAX,BYTE PTR DS:[EDI+EDX]     ;EAX = 用户名[EDI]
013BCEA8  |. PUSH EAX                                 ; /c
013BCEA9  |. CALL DWORD PTR DS:[<&MSVCR120.toupper>]  ; // 将字符转化为大写字母
013BCEAF  |. MOV EDX,EAX   ;将转化后的放到 EDX = 大写字母char
013BCEB1  |. ADD ESP,0x4


013BCEB4  |. MOV ECX,DWORD PTR DS:[EDX*4+0x2E64148]  ;将大写字母作为索引从0x2E64148中取内容
013BCEBB  |. ADD ECX,[LOCAL.1]                ;ECX = [LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148]


013BCEBE  |. CMP [ARG.2],0x0             ;判断是哪种类型的注册
013BCEC2  |. JE SHORT 010Edito.013BCF0E     ;如果是0xFC类型就跳到下面一段处理
013BCEC4  |. LEA EAX,DWORD PTR DS:[EDX+0xD]   ;EAX = char+0xD
013BCEC7  |. AND EAX,0xFF  ; EAX  = (char+0xD) AND 0xFF;
013BCECC  |. XOR ECX,DWORD PTR DS:[EAX*4+0x2E64148]  
; ECX = ([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148] ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]

013BCED3  |.LEA EAX,DWORD PTR DS:[EDX+0x2F]   ; EAX = char+0x2F
013BCED6  |.AND EAX,0xFF   ;EAX = (char+0x2F) and 0xFF
013BCEDB  |.IMUL ECX,DWORD PTR DS:[EAX*4+0x2E64148]  
;ECX = (([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148] ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148]

013BCEE3  |.MOV EAX,[LOCAL.2]  ;EAX =[LOCAL.2]
013BCEE6  |.MOVZX EAX,AL; EAX =[LOCAL.2]&0xFF
013BCEE9  |.ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]  ;
ECX =
((([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148] ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:([LOCAL.2]*+0x2E64148)

013BCEF0  |.MOVZX EAX,BL   ;EAX = EBX
013BCEF3  |.ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
ECX =
((([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148] ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:([LOCAL.2]*+0x2E64148)
+DWORD PTR DS:[EBX*4+0x2E64148]

013BCEFA  |.MOV EAX,[LOCAL.3]   ;EAX = [LOCAL.3]
013BCEFD  |.MOVZX EAX,AL
013BCF00  |.ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
ECX =
((([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148] ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:([LOCAL.2]*+0x2E64148)
+DWORD PTR DS:[EBX*4+0x2E64148]
+ DWORD PTR DS:[[LOCAL.3]*4+0x2E64148]

013BCF07  |.  8BC1                   |MOV EAX,ECX
EAX =
((([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148] ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:([LOCAL.2]*+0x2E64148)
+DWORD PTR DS:[EBX*4+0x2E64148]
+ DWORD PTR DS:[[LOCAL.3]*4+0x2E64148]

013BCF09  |.  8945 FC                |MOV [LOCAL.1],EAX
[LOCAL.1] =
((([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148] ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:([LOCAL.2]*+0x2E64148)
+DWORD PTR DS:[EBX*4+0x2E64148]
+ DWORD PTR DS:[[LOCAL.3]*4+0x2E64148]

013BCF0C  |.  EB 48                  |JMP SHORT 010Edito.013BCF56

如果是0xFC类型就跳到这里  ECX = [LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148]
013BCF0E  |>  LEA EAX,DWORD PTR DS:[EDX+0x3F]  ;eax = char+0x3f
013BCF11  |.  AND EAX,0xFF ; eax = (char + 0x3f) and 0xff
013BCF16  |.  XOR ECX,DWORD PTR DS:[EAX*4+0x2E64148]       
;ecx =([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148]) xor(WORD PTR DS:[((char + 0x3f) and 0xff)*4+0x2E64148])
013BCF1D  |.  LEA EAX,DWORD PTR DS:[EDX+0x17]
013BCF20  |.  AND EAX,0xFF ;eax = (char +0x17) and 0xff
013BCF25  |.  IMUL ECX,DWORD PTR DS:[EAX*4+0x2E64148]
;ecx = (([LOCAL.1]+DWORD PTR DS:[char*4+0x2E64148]) xor(WORD PTR DS:[((char + 0x3f) and 0xff)*4+0x2E64148])) *(DWORD PTR DS:[((char +0x17) and 0xff)*4+0x2E64148])
013BCF2D  |.  MOV EAX,[LOCAL.2]
013BCF30  |.  MOVZX EAX,AL ;EAX = [LOCAL.2]
013BCF33  |.  ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148] ;

013BCF3A  |.  MOVZX EAX,BL ; EAX = ebx;
013BCF3D  |.  ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
013BCF44  |.  MOV EAX,[LOCAL.4]
013BCF47  |.  MOVZX EAX,AL ; eax = [LOCAL.4]
013BCF4A  |.  ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
013BCF51  |.  MOV EAX,ECX
013BCF53  |.  MOV [LOCAL.1],ECX


// 循环递增
013BCF56  |>  |ADD [LOCAL.3],0x13
013BCF5A  |.  |INC EDI
013BCF5B  |.  |ADD [LOCAL.2],0x9
013BCF5F  |.  |ADD EBX,0xD
013BCF62  |.  |ADD [LOCAL.4],0x7
013BCF66  |.  |MOV EDX,[ARG.1]    ;EDX = 用户名首地址
013BCF69  |.  |CMP EDI,ESI
013BCF6B  |.^ \JL 010Edito.013BCEA4  --->循环,
013BCF71  |.  POP EBX
013BCF72  |.  POP EDI
013BCF73  |.  POP ESI
013BCF74  |.  MOV ESP,EBP
013BCF76  |.  POP EBP
013BCF77  |.  RETN

// 长度小于0
013BCF78  |>  POP EDI
013BCF79  |.  MOV EAX,ECX
013BCF7B  |.  POP ESI
013BCF7C  |.  MOV ESP,EBP
013BCF7E  |.  POP EBP
013BCF7F  \.  RETN

很明显这里面涉及到一个整形数组
DWORD LOCAL3 = 0;
        DWORD LOCAL4 = 0;
        DWORD LOCAL2 = (ESI*17)&0xFF; // 用于设置注册天数
        DWORD LOCAL1 = 0;
        DWORD EBX = EDI0x20*15;   用于设置注册人数
        INT NameLength = strlen(Name);
        int i = 0;
        char EAX[ 4 ] = {0};
        DWORD  BUF[ 256 ] = { 0x39CB44B8, 0x23754F67, 0x5F017211, 0x3EBB24DA, 0x351707C6, 0x63F9774B, 0x17827288, 0x0FE74821, 0x5B5F670F, 0x48315AE8, 0x785B7769, 0x2B7A1547, 0x38D11292, 0x42A11B32, 0x35332244, 0x77437B60, 0x1EAB3B10, 0x53810000, 0x1D0212AE, 0x6F0377A8, 0x43C03092, 0x2D3C0A8E, 0x62950CBF, 0x30F06FFA, 0x34F710E0, 0x28F417FB, 0x350D2F95, 0x5A361D5A, 0x15CC060B, 0x0AFD13CC, 0x28603BCF, 0x3371066B, 0x30CD14E4, 0x175D3A67, 0x6DD66A13, 0x2D3409F9, 0x581E7B82, 0x76526B99, 0x5C8D5188, 0x2C857971, 0x15F51FC0, 0x68CC0D11, 0x49F55E5C, 0x275E4364, 0x2D1E0DBC, 0x4CEE7CE3, 0x32555840, 0x112E2E08, 0x6978065A, 0x72921406, 0x314578E7, 0x175621B7, 0x40771DBF, 0x3FC238D6, 0x4A31128A, 0x2DAD036E, 0x41A069D6, 0x25400192, 0x00DD4667, 0x6AFC1F4F, 0x571040CE, 0x62FE66DF, 0x41DB4B3E, 0x3582231F, 0x55F6079A, 0x1CA70644, 0x1B1643D2, 0x3F7228C9, 0x5F141070, 0x3E1474AB, 0x444B256E, 0x537050D9, 0x0F42094B, 0x2FD820E6, 0x778B2E5E, 0x71176D02, 0x7FEA7A69, 0x5BB54628, 0x19BA6C71, 0x39763A99, 0x178D54CD, 0x01246E88, 0x3313537E, 0x2B8E2D17, 0x2A3D10BE, 0x59D10582, 0x37A163DB, 0x30D6489A, 0x6A215C46, 0x0E1C7A76, 0x1FC760E7, 0x79B80C65, 0x27F459B4, 0x799A7326, 0x50BA1782, 0x2A116D5C, 0x63866E1B, 0x3F920E3C, 0x55023490, 0x55B56089, 0x2C391FD1, 0x2F8035C2, 0x64FD2B7A, 0x4CE8759A, 0x518504F0, 0x799501A8, 0x3F5B2CAD, 0x38E60160, 0x637641D8, 0x33352A42, 0x51A22C19, 0x085C5851, 0x032917AB, 0x2B770AC7, 0x30AC77B3, 0x2BEC1907, 0x035202D0, 0x0FA933D3, 0x61255DF3, 0x22AD06BF, 0x58B86971, 0x5FCA0DE5, 0x700D6456, 0x56A973DB, 0x5AB759FD, 0x330E0BE2, 0x5B3C0DDD, 0x495D3C60, 0x53BD59A6, 0x4C5E6D91, 0x49D9318D, 0x103D5079, 0x61CE42E3, 0x7ED5121D, 0x14E160ED, 0x212D4EF2, 0x270133F0, 0x62435A96, 0x1FA75E8B, 0x6F092FBE, 0x4A000D49, 0x57AE1C70, 0x004E2477, 0x561E7E72, 0x468C0033, 0x5DCC2402, 0x78507AC6, 0x58AF24C7, 0x0DF62D34, 0x358A4708, 0x3CFB1E11, 0x2B71451C, 0x77A75295, 0x56890721, 0x0FEF75F3, 0x120F24F1, 0x01990AE7, 0x339C4452, 0x27A15B8E, 0x0BA7276D, 0x60DC1B7B, 0x4F4B7F82, 0x67DB7007, 0x4F4A57D9, 0x621252E8, 0x20532CFC, 0x6A390306, 0x18800423, 0x19F3778A, 0x462316F0, 0x56AE0937, 0x43C2675C, 0x65CA45FD, 0x0D604FF2, 0x0BFD22CB, 0x3AFE643B, 0x3BF67FA6, 0x44623579, 0x184031F8, 0x32174F97, 0x4C6A092A, 0x5FB50261, 0x01650174, 0x33634AF1, 0x712D18F4, 0x6E997169, 0x5DAB7AFE, 0x7C2B2EE8, 0x6EDB75B4, 0x5F836FB6, 0x3C2A6DD6, 0x292D05C2, 0x052244DB, 0x149A5F4F, 0x5D486540, 0x331D15EA, 0x4F456920, 0x483A699F, 0x3B450F05, 0x3B207C6C, 0x749D70FE, 0x417461F6, 0x62B031F1, 0x2750577B, 0x29131533, 0x588C3808, 0x1AEF3456, 0x0F3C00EC, 0x7DA74742, 0x4B797A6C, 0x5EBB3287, 0x786558B8, 0x00ED4FF2, 0x6269691E, 0x24A2255F, 0x62C11F7E, 0x2F8A7DCD, 0x643B17FE, 0x778318B8, 0x253B60FE, 0x34BB63A3, 0x5B03214F, 0x5F1571F4, 0x1A316E9F, 0x7ACF2704, 0x28896838, 0x18614677, 0x1BF569EB, 0x0BA85EC9, 0x6ACA6B46, 0x1E43422A, 0x514D5F0E, 0x413E018C, 0x307626E9, 0x01ED1DFA, 0x49F46F5A, 0x461B642B, 0x7D7007F2, 0x13652657, 0x6B160BC5, 0x65E04849, 0x1F526E1C, 0x5A0251B6, 0x2BD73F69, 0x2DBF7ACD, 0x51E63E80, 0x5CF2670F, 0x21CD0A03, 0x5CFF0261, 0x33AE061E, 0x3BB6345F, 0x5D814A75, 0x257B5DF4, 0x0A5C2C5B, 0x16A45527, 0x16F23945 };
        while (NameLength)
        {
                char nameChar = toupper(Name[ i ]);
               
                if (KEY[3] != 0xFC)
                {
                        LOCAL1 =
                                (((LOCAL1 + BUF[ nameChar ]) ^ BUF[ (nameChar + 0xD)]) * BUF[ (nameChar + 0x2F)])
                                + BUF[ LOCAL2 ]
                                + BUF[ EBX ]
                                + BUF[ LOCAL3 ];
                }
                Else  //这一情况无用
                {
                        LOCAL1 =
                                (((LOCAL1 + BUF[ nameChar ]) ^ BUF[ (nameChar + 0x3F)]) * BUF[ (nameChar + 0x17)])
                                + BUF[ LOCAL2 ]
                                + BUF[ EBX ]
                                + BUF[ LOCAL4 ];
                }

                *(DWORD*)EAX = LOCAL1;

                EBX += 0xD;
                LOCAL3 += 0x13;
                LOCAL2 += 0x9;
                LOCAL4 += 0x7;
                i++;
                NameLength--;
        }

4.根据“处理用户名函数”返回值获得更多信息
在上面的函数返回之后,会对返回值进行判断,并且解开上面讲到的一些疑问
这里从结果0x2D往上找
这一段放到notepad中一高亮显示,首先就发现Case FC是跳不到正确处的,所以上面的关于FC的操作都可不用做

013BDAF6   .  CALL 010Edito.00402E50   ;处理用户名
013BDAFB   .  MOV EDX,EAX
013BDAFD   .  ADD ESP,0x10
013BDB00   .  CMP BYTE PTR SS:[EBP-0x20],DL ;KEY[4]和返回值比较
013BDB03   .  JNZ 010Edito.013BDB8A ;应该相等
013BDB09   .  MOV ECX,EDX
013BDB0B   .  SHR ECX,0x8
013BDB0E   .  CMP BH,CL  ;返回值>>0x8 和 KEY[5]比较
013BDB10   .  JNZ SHORT 010Edito.013BDB8A;应该相等
013BDB12   .  MOV ECX,EDX
013BDB14   .  SHR ECX,0x10
013BDB17   .  CMP BYTE PTR SS:[EBP-0x1E],CL;返回值>>0x10 和 KEY[6]比较
013BDB1A   .  JNZ SHORT 010Edito.013BDB8A;应该相等
013BDB1C   .  SHR EAX,0x18
013BDB1F   .  CMP BYTE PTR SS:[EBP-0x1D],AL;返回值>>0x18 和 KEY[7]比较
013BDB22   .  JNZ SHORT 010Edito.013BDB8A;应该相等

013BDB24   .  CMP BL,0x9C                        ;  Switch (cases 9C..FC)
013BDB27   .  JNZ SHORT 010Edito.013BDB38

013BDB29   .  MOV EAX,DWORD PTR SS:[EBP+0x8]     ;  Case 9C of switch 013BDB24
013BDB2C   .  CMP EAX,DWORD PTR DS:[EDI+0x1C]
013BDB2F   .  JBE SHORT 010Edito.013BDB83   // <= 跳到正确③


013BDB31   .  MOV ESI,0x4E
013BDB36   .  JMP SHORT 010Edito.013BDB8F
013BDB38   >  CMP BL,0xFC   ;
013BDB3B   .  JNZ SHORT 010Edito.013BDB6B
013BDB3D   .  MOVZX ECX,BYTE PTR SS:[EBP-0x22]   ;  Case FC of switch 013BDB24
013BDB41   .  MOVZX EAX,BYTE PTR SS:[EBP-0x23]
013BDB45   .  SHL ECX,0x8
013BDB48   .  ADD ECX,EAX
013BDB4A   .  MOVZX EAX,BYTE PTR SS:[EBP-0x24]
013BDB4E   .  SHL ECX,0x8
013BDB51   .  PUSH EDX
013BDB52   .  ADD ECX,EAX
013BDB54   .  PUSH ECX
013BDB55   .  CALL 010Edito.0040A790
013BDB5A   .  ADD ESP,0x8
013BDB5D   .  TEST EAX,EAX
013BDB5F   .  JE SHORT 010Edito.013BDB8A
013BDB61   .  MOV DWORD PTR DS:[EDI+0x18],EAX
013BDB64   .  MOV ESI,0x93
013BDB69   .  JMP SHORT 010Edito.013BDB8F
013BDB6B   >  CMP BL,0xAC
013BDB6E   .  JNZ SHORT 010Edito.013BDB8A


013BDB70   .  MOV EAX,DWORD PTR SS:[EBP-0x10]    ;  Case AC of switch 013BDB24
013BDB73   .  TEST EAX,EAX
013BDB75   .  JE SHORT 010Edito.013BDB8A
013BDB77   .  CMP DWORD PTR SS:[EBP+0xC],EAX
013BDB7A   .  JBE SHORT 010Edito.013BDB83   //<=跳到正确③
013BDB7C   .  MOV ESI,0x4E
013BDB81   .  JMP SHORT 010Edito.013BDB8F
013BDB83   >  MOV ESI,0x2D  // 正确答案②
013BDB88   .  JMP SHORT 010Edito.013BDB8F
013BDB8A   >  MOV ESI,0xE7                       ;  Default case of switch 013BDB24
013BDB8F   >  LEA ECX,DWORD PTR SS:[EBP-0x14]
013BDB92   .  MOV DWORD PTR SS:[EBP-0x4],-0x1
013BDB99   .  CALL DWORD PTR DS:[<&Qt5Core.??1QB>;  Qt5Core.??1QByteArray@@QAE@XZ
013BDB9F   .  MOV EAX,ESI  // 获得返回值①
013BDBA1   .  MOV ECX,DWORD PTR SS:[EBP-0xC]
013BDBA4   .  MOV DWORD PTR FS:[0],ECX
013BDBAB   .  POP ECX
013BDBAC   .  POP EDI
013BDBAD   .  POP ESI
013BDBAE   .  POP EBX
013BDBAF   .  MOV ESP,EBP
013BDBB1   .  POP EBP
013BDBB2   .  RETN 0x8               
对应c
if (EAX[0] == KEY[4] &&
                EAX[1] == KEY[5]&&
                EAX[2] == KEY[6]&&
                EAX[3] == KEY[7])
        {
                switch (KEY[3])
                {
                case 0x9c:
                        /*if ([ EBP + 0x8 ] <= [ EDI + 0x1C ])
                        {
                                RIGHT
                        }*/
                        break;
                case 0xfc:

                        break;
                case 0xac:
                        /*if ([ EBP - 0x10 ] >= [ EBP + 0xC ])
                        {
                                RIGHT
                        }*/
                        break;
                }

其次会发现在跳转之前有判断
case 0x9c:
/*if ([ EBP + 0x8 ] <= [ EDI + 0x1C ])   {
        RIGHT
}*/
在case 0xAC之后有判断
case 0xac:
/*if ([ EBP - 0x10 ] >= [ EBP + 0xC ]){
        RIGHT
}*/


对于0x9c(版本号授权)
[ EBP + 0x8 ] <= [ EDI + 0x1C ]这个条件表示:
[ EBP + 0x8 ]是注册验证函数参数1 ,值为 9(这个表示版本号), [ EDI + 0x1C ]根据前面可知是((((KEY[0] xor KEY[6]) xor 0x18) + 0x3D)xor 0xA7),
所以((((KEY[0] xor KEY[6]) xor 0x18) + 0x3D)xor 0xA7)>=9
结合上面的分析
DWORD ECX = (((KEY[ 0 ] ^ KEY[ 6 ]) ^ 0x18) + 0x3D) ^ 0xA7;
if (ECX < 0x2)
                {
                        // ECX == 1,ESI=1
                        ESI = ECX;
                }
                else
                {
                        ESI = 0;
                }

可以知道ESI = 0

void CkeygenDlg::OnBnClickedButton1()
{
        // TODO: 在此添加控件通知处理程序代码
       

        char szName[ 64 ] = { 0 };
        DWORD EDI0x20 = 1;// 0~1000,是0xB的倍数 // 表示人数
        DWORD EBX = EDI0x20*15;
        DWORD LOCAL3 = 0;
        DWORD LOCAL2 = 0; //LOCAL2 = ESI*17
        DWORD LOCAL1 = 0;
        INT NameLength;
        int i = 0;
        BYTE KEY[ 10 ] = { 0 };
        KEY[ 3 ] = 0x9C;
        BYTE EAX[ 4 ] = { 0 };
        DWORD  BUF[ 256 ] = { 0x39CB44B8, 0x23754F67, 0x5F017211, 0x3EBB24DA, 0x351707C6, 0x63F9774B, 0x17827288, 0x0FE74821, 0x5B5F670F, 0x48315AE8, 0x785B7769, 0x2B7A1547, 0x38D11292, 0x42A11B32, 0x35332244, 0x77437B60, 0x1EAB3B10, 0x53810000, 0x1D0212AE, 0x6F0377A8, 0x43C03092, 0x2D3C0A8E, 0x62950CBF, 0x30F06FFA, 0x34F710E0, 0x28F417FB, 0x350D2F95, 0x5A361D5A, 0x15CC060B, 0x0AFD13CC, 0x28603BCF, 0x3371066B, 0x30CD14E4, 0x175D3A67, 0x6DD66A13, 0x2D3409F9, 0x581E7B82, 0x76526B99, 0x5C8D5188, 0x2C857971, 0x15F51FC0, 0x68CC0D11, 0x49F55E5C, 0x275E4364, 0x2D1E0DBC, 0x4CEE7CE3, 0x32555840, 0x112E2E08, 0x6978065A, 0x72921406, 0x314578E7, 0x175621B7, 0x40771DBF, 0x3FC238D6, 0x4A31128A, 0x2DAD036E, 0x41A069D6, 0x25400192, 0x00DD4667, 0x6AFC1F4F, 0x571040CE, 0x62FE66DF, 0x41DB4B3E, 0x3582231F, 0x55F6079A, 0x1CA70644, 0x1B1643D2, 0x3F7228C9, 0x5F141070, 0x3E1474AB, 0x444B256E, 0x537050D9, 0x0F42094B, 0x2FD820E6, 0x778B2E5E, 0x71176D02, 0x7FEA7A69, 0x5BB54628, 0x19BA6C71, 0x39763A99, 0x178D54CD, 0x01246E88, 0x3313537E, 0x2B8E2D17, 0x2A3D10BE, 0x59D10582, 0x37A163DB, 0x30D6489A, 0x6A215C46, 0x0E1C7A76, 0x1FC760E7, 0x79B80C65, 0x27F459B4, 0x799A7326, 0x50BA1782, 0x2A116D5C, 0x63866E1B, 0x3F920E3C, 0x55023490, 0x55B56089, 0x2C391FD1, 0x2F8035C2, 0x64FD2B7A, 0x4CE8759A, 0x518504F0, 0x799501A8, 0x3F5B2CAD, 0x38E60160, 0x637641D8, 0x33352A42, 0x51A22C19, 0x085C5851, 0x032917AB, 0x2B770AC7, 0x30AC77B3, 0x2BEC1907, 0x035202D0, 0x0FA933D3, 0x61255DF3, 0x22AD06BF, 0x58B86971, 0x5FCA0DE5, 0x700D6456, 0x56A973DB, 0x5AB759FD, 0x330E0BE2, 0x5B3C0DDD, 0x495D3C60, 0x53BD59A6, 0x4C5E6D91, 0x49D9318D, 0x103D5079, 0x61CE42E3, 0x7ED5121D, 0x14E160ED, 0x212D4EF2, 0x270133F0, 0x62435A96, 0x1FA75E8B, 0x6F092FBE, 0x4A000D49, 0x57AE1C70, 0x004E2477, 0x561E7E72, 0x468C0033, 0x5DCC2402, 0x78507AC6, 0x58AF24C7, 0x0DF62D34, 0x358A4708, 0x3CFB1E11, 0x2B71451C, 0x77A75295, 0x56890721, 0x0FEF75F3, 0x120F24F1, 0x01990AE7, 0x339C4452, 0x27A15B8E, 0x0BA7276D, 0x60DC1B7B, 0x4F4B7F82, 0x67DB7007, 0x4F4A57D9, 0x621252E8, 0x20532CFC, 0x6A390306, 0x18800423, 0x19F3778A, 0x462316F0, 0x56AE0937, 0x43C2675C, 0x65CA45FD, 0x0D604FF2, 0x0BFD22CB, 0x3AFE643B, 0x3BF67FA6, 0x44623579, 0x184031F8, 0x32174F97, 0x4C6A092A, 0x5FB50261, 0x01650174, 0x33634AF1, 0x712D18F4, 0x6E997169, 0x5DAB7AFE, 0x7C2B2EE8, 0x6EDB75B4, 0x5F836FB6, 0x3C2A6DD6, 0x292D05C2, 0x052244DB, 0x149A5F4F, 0x5D486540, 0x331D15EA, 0x4F456920, 0x483A699F, 0x3B450F05, 0x3B207C6C, 0x749D70FE, 0x417461F6, 0x62B031F1, 0x2750577B, 0x29131533, 0x588C3808, 0x1AEF3456, 0x0F3C00EC, 0x7DA74742, 0x4B797A6C, 0x5EBB3287, 0x786558B8, 0x00ED4FF2, 0x6269691E, 0x24A2255F, 0x62C11F7E, 0x2F8A7DCD, 0x643B17FE, 0x778318B8, 0x253B60FE, 0x34BB63A3, 0x5B03214F, 0x5F1571F4, 0x1A316E9F, 0x7ACF2704, 0x28896838, 0x18614677, 0x1BF569EB, 0x0BA85EC9, 0x6ACA6B46, 0x1E43422A, 0x514D5F0E, 0x413E018C, 0x307626E9, 0x01ED1DFA, 0x49F46F5A, 0x461B642B, 0x7D7007F2, 0x13652657, 0x6B160BC5, 0x65E04849, 0x1F526E1C, 0x5A0251B6, 0x2BD73F69, 0x2DBF7ACD, 0x51E63E80, 0x5CF2670F, 0x21CD0A03, 0x5CFF0261, 0x33AE061E, 0x3BB6345F, 0x5D814A75, 0x257B5DF4, 0x0A5C2C5B, 0x16A45527, 0x16F23945 };
       
       
        UpdateData(TRUE);
        WideCharToMultiByte(CP_ACP , 0 ,
                                                m_user.GetBuffer() , -1 ,
                                                szName , 64 ,
                                                NULL , NULL);
       
       
        NameLength = strlen(szName);
       
        while(NameLength)
        {
                char nameChar = toupper(szName[ i ]);

                LOCAL1 =
                        (((LOCAL1 + BUF[ nameChar ]) ^ BUF[ (nameChar + 0xD) ]) * BUF[ (nameChar + 0x2F) ])
                        + BUF[ LOCAL2 ]
                        + BUF[ EBX ]
                        + BUF[ LOCAL3 ];
                 

                *(DWORD*)EAX = LOCAL1;

                EBX += 0xD;
                LOCAL3 += 0x13;
                LOCAL2 += 0x9;
                 
                i++;
                NameLength--;
        }

        KEY[ 4 ] = EAX[ 0 ];
        KEY[ 5 ] = EAX[ 1 ];
        KEY[ 6 ] = EAX[ 2 ];
        KEY[ 7 ] = EAX[ 3 ];

        //DWORD EAX = (((((KEY[ 1 ] ^ KEY[ 7 ]) * 0x100) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421 = EDI0x20;
        //DWORD ECX = (((KEY[ 0 ] ^ KEY[ 6 ]) ^ 0x18) + 0x3D) ^ 0xA7 = 版本号;版本号此时应大于9

        WORD tmp = ((EDI0x20*11) ^ 0x3421 - 0x4d30) ^ 0x7892;
        KEY[ 1 ] = (HIBYTE(tmp)) ^ KEY[ 7 ];
        KEY[ 2 ] = (LOBYTE(tmp)) ^ KEY[ 5 ];

        KEY[ 0 ] = (((10 ^ 0xa7) - 0x3d) ^ 0x18) ^ KEY[ 6 ];//这里取版本号10

        char reg[ 200 ] = { 0 };
        sprintf_s(reg , 200 , "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" , KEY[ 0 ] , KEY[ 1 ] , KEY[ 2 ] , KEY[ 3 ] , KEY[ 4 ] , KEY[ 5 ] , KEY[ 6 ] , KEY[ 7 ] , 0 , 0);
       
        m_reg = CString(reg);
       
        UpdateData(FALSE);
       

}
对于0xac(天数授权)
[ EBP - 0x10 ] >= [ EBP + 0xC ]这个条件表示
[ EBP + 0xc ]是注册验证函数参数2 ,值为 0x4389, [ EBP -0x10 ]根据前面的条件是,0xac注册最后的EAX,说明最后ecx == eax,eax被赋值为edx
就是这段

if (ECX == 0)// ECX = EAX
                {
                        EAX = EDX;//right
                }
                else
                {
                        EAX = 0;//error
                }
具体的需要结合上面的代码来看
由此可以算出 最后的eax的可能值,也是esi的可能值,

unsigned int num_ecx = 0xFFFFFF;
        unsigned int num_eax = 0;
        unsigned int num_edx = 0;
        while(1)
        {
                __asm {
                       
                        MOV ECX , num_ecx;
                        MOV EAX , 0XF0F0F0F1;
                        MUL ECX;
                        SHR EDX , 0x4 ;
                        MOV EAX , EDX;
                        SHL EAX , 0x4;
                        ADD EAX , EDX;
                        MOV num_eax , EAX;
                        MOV num_edx , EDX;
                }
                if (num_eax == num_ecx)
                {
                        printf("%x_%x\n", num_ecx, num_edx);
                }
                num_ecx--;
        }
从算出的结果取出一个(不要从最前面取,从中间取),用在注册机的0xAC情况中,用于表示天数
注意下面特别标注的地方

一些可用的值
ff7711_f0701
ff7700_f0700
ff76ef_f06ff
ff76de_f06fe
ff76cd_f06fd
ff76bc_f06fc
ff76ab_f06fb
ff769a_f06fa

void CkeygenDlg::OnBnClickedButton2()
{
        // TODO: 在此添加控件通知处理程序代码

        char szName[ 64 ] = { 0 };
        DWORD EDI0x20 = 1;// 0~1000,是0xB的倍数,表示人数
        DWORD EBX = EDI0x20*15;
        DWORD LOCAL3 = 0;       
        DWORD ESI = 0xf054c;// 这个就是算出的num_edx,与注册天数有关
        DWORD LOCAL2 = (17*ESI)&0xFF;//遍历出来的,ESI = EAX = EDX
        DWORD LOCAL1 = 0;
        INT NameLength;
        int i = 0;
        BYTE KEY[ 10 ] = { 0 };
        BYTE EAX[ 4 ] = { 0 };
        DWORD  BUF[ 256 ] = { 0x39CB44B8, 0x23754F67, 0x5F017211, 0x3EBB24DA, 0x351707C6, 0x63F9774B, 0x17827288, 0x0FE74821, 0x5B5F670F, 0x48315AE8, 0x785B7769, 0x2B7A1547, 0x38D11292, 0x42A11B32, 0x35332244, 0x77437B60, 0x1EAB3B10, 0x53810000, 0x1D0212AE, 0x6F0377A8, 0x43C03092, 0x2D3C0A8E, 0x62950CBF, 0x30F06FFA, 0x34F710E0, 0x28F417FB, 0x350D2F95, 0x5A361D5A, 0x15CC060B, 0x0AFD13CC, 0x28603BCF, 0x3371066B, 0x30CD14E4, 0x175D3A67, 0x6DD66A13, 0x2D3409F9, 0x581E7B82, 0x76526B99, 0x5C8D5188, 0x2C857971, 0x15F51FC0, 0x68CC0D11, 0x49F55E5C, 0x275E4364, 0x2D1E0DBC, 0x4CEE7CE3, 0x32555840, 0x112E2E08, 0x6978065A, 0x72921406, 0x314578E7, 0x175621B7, 0x40771DBF, 0x3FC238D6, 0x4A31128A, 0x2DAD036E, 0x41A069D6, 0x25400192, 0x00DD4667, 0x6AFC1F4F, 0x571040CE, 0x62FE66DF, 0x41DB4B3E, 0x3582231F, 0x55F6079A, 0x1CA70644, 0x1B1643D2, 0x3F7228C9, 0x5F141070, 0x3E1474AB, 0x444B256E, 0x537050D9, 0x0F42094B, 0x2FD820E6, 0x778B2E5E, 0x71176D02, 0x7FEA7A69, 0x5BB54628, 0x19BA6C71, 0x39763A99, 0x178D54CD, 0x01246E88, 0x3313537E, 0x2B8E2D17, 0x2A3D10BE, 0x59D10582, 0x37A163DB, 0x30D6489A, 0x6A215C46, 0x0E1C7A76, 0x1FC760E7, 0x79B80C65, 0x27F459B4, 0x799A7326, 0x50BA1782, 0x2A116D5C, 0x63866E1B, 0x3F920E3C, 0x55023490, 0x55B56089, 0x2C391FD1, 0x2F8035C2, 0x64FD2B7A, 0x4CE8759A, 0x518504F0, 0x799501A8, 0x3F5B2CAD, 0x38E60160, 0x637641D8, 0x33352A42, 0x51A22C19, 0x085C5851, 0x032917AB, 0x2B770AC7, 0x30AC77B3, 0x2BEC1907, 0x035202D0, 0x0FA933D3, 0x61255DF3, 0x22AD06BF, 0x58B86971, 0x5FCA0DE5, 0x700D6456, 0x56A973DB, 0x5AB759FD, 0x330E0BE2, 0x5B3C0DDD, 0x495D3C60, 0x53BD59A6, 0x4C5E6D91, 0x49D9318D, 0x103D5079, 0x61CE42E3, 0x7ED5121D, 0x14E160ED, 0x212D4EF2, 0x270133F0, 0x62435A96, 0x1FA75E8B, 0x6F092FBE, 0x4A000D49, 0x57AE1C70, 0x004E2477, 0x561E7E72, 0x468C0033, 0x5DCC2402, 0x78507AC6, 0x58AF24C7, 0x0DF62D34, 0x358A4708, 0x3CFB1E11, 0x2B71451C, 0x77A75295, 0x56890721, 0x0FEF75F3, 0x120F24F1, 0x01990AE7, 0x339C4452, 0x27A15B8E, 0x0BA7276D, 0x60DC1B7B, 0x4F4B7F82, 0x67DB7007, 0x4F4A57D9, 0x621252E8, 0x20532CFC, 0x6A390306, 0x18800423, 0x19F3778A, 0x462316F0, 0x56AE0937, 0x43C2675C, 0x65CA45FD, 0x0D604FF2, 0x0BFD22CB, 0x3AFE643B, 0x3BF67FA6, 0x44623579, 0x184031F8, 0x32174F97, 0x4C6A092A, 0x5FB50261, 0x01650174, 0x33634AF1, 0x712D18F4, 0x6E997169, 0x5DAB7AFE, 0x7C2B2EE8, 0x6EDB75B4, 0x5F836FB6, 0x3C2A6DD6, 0x292D05C2, 0x052244DB, 0x149A5F4F, 0x5D486540, 0x331D15EA, 0x4F456920, 0x483A699F, 0x3B450F05, 0x3B207C6C, 0x749D70FE, 0x417461F6, 0x62B031F1, 0x2750577B, 0x29131533, 0x588C3808, 0x1AEF3456, 0x0F3C00EC, 0x7DA74742, 0x4B797A6C, 0x5EBB3287, 0x786558B8, 0x00ED4FF2, 0x6269691E, 0x24A2255F, 0x62C11F7E, 0x2F8A7DCD, 0x643B17FE, 0x778318B8, 0x253B60FE, 0x34BB63A3, 0x5B03214F, 0x5F1571F4, 0x1A316E9F, 0x7ACF2704, 0x28896838, 0x18614677, 0x1BF569EB, 0x0BA85EC9, 0x6ACA6B46, 0x1E43422A, 0x514D5F0E, 0x413E018C, 0x307626E9, 0x01ED1DFA, 0x49F46F5A, 0x461B642B, 0x7D7007F2, 0x13652657, 0x6B160BC5, 0x65E04849, 0x1F526E1C, 0x5A0251B6, 0x2BD73F69, 0x2DBF7ACD, 0x51E63E80, 0x5CF2670F, 0x21CD0A03, 0x5CFF0261, 0x33AE061E, 0x3BB6345F, 0x5D814A75, 0x257B5DF4, 0x0A5C2C5B, 0x16A45527, 0x16F23945 };


        UpdateData(TRUE);
        WideCharToMultiByte(CP_ACP , 0 ,
                                                m_usersec.GetBuffer() , -1 ,
                                                szName , 64 ,
                                                NULL , NULL);
        NameLength = strlen(szName);
        while(NameLength)
        {
                char nameChar = toupper(szName[ i ]);

                LOCAL1 =
                        (((LOCAL1 + BUF[ nameChar ]) ^ BUF[ (nameChar + 0xD) ]) * BUF[ (nameChar + 0x2F) ])
                        + BUF[ LOCAL2 ]
                        + BUF[ EBX ]
                        + BUF[ LOCAL3 ];


                *(DWORD*)EAX = LOCAL1;

                EBX += 0xD;
                LOCAL3 += 0x13;
                LOCAL2 += 0x9;

                i++;
                NameLength--;
        }
        KEY[ 3 ] = 0xAC;
        KEY[ 4 ] = EAX[ 0 ];
        KEY[ 5 ] = EAX[ 1 ];
        KEY[ 6 ] = EAX[ 2 ];
        KEY[ 7 ] = EAX[ 3 ];

        //DWORD EAX = (((((KEY[ 1 ] ^ KEY[ 7 ]) * 0x100) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421 = EDI0x20;

        /*ecx=(((((((((KEY[9] xor KEY[5]) << 8)+(KEY[4] xor KEY[8]))<<8) + (KEY[6]  xor KEY[0]))xor 005B8C27) xor 0x22c078) - 0x2C175) xor 0xFFE53167) and 0xFFFFFF ;*/


        WORD tmp = ((EDI0x20*11) ^ 0x3421 - 0x4d30) ^ 0x7892;
        KEY[ 1 ] = (HIBYTE(tmp)) ^ KEY[ 7 ];
        KEY[ 2 ] = (LOBYTE(tmp)) ^ KEY[ 5 ];
       
        DWORD tmp2 = (((0xff5a0c ^ 0xFFE53167) + 0x2C175) ^ 0x22c078) ^ 0x05B8C27;// 这就是算出的e num_ecx
        KEY[ 0 ] = (tmp2 & 0xFF) ^ KEY[ 6 ];
        DWORD tmp3 = (tmp2 - (tmp2 & 0xFF)) >> 0x8;
        KEY[ 8 ] = (tmp3 & 0xFF) ^ KEY[ 4 ];
        KEY[ 9 ] = ((tmp3 - (tmp3 & 0xFF)) >> 0x8) ^ KEY[ 5 ];


        char reg[ 200 ] = { 0 };
        sprintf_s(reg , 200 , "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" , KEY[ 0 ] , KEY[ 1 ] , KEY[ 2 ] , KEY[ 3 ] , KEY[ 4 ] , KEY[ 5 ] , KEY[ 6 ] , KEY[ 7 ] , KEY[8] , KEY[9]);

        m_regsec = CString(reg);

        UpdateData(FALSE);

}

010editor算法分析与注册机编写.zip

40.4 KB, 下载次数: 1

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 14:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表