010 Editor v8.0.1_x32分析以及注册机制作

环境以及工具

Window7_x32

010 Editor v8.0.1_x32

OD

VS2017

第一步 找到判断注册结果的关键跳转和关键函数

使用OD打开010editor,进入到注册界面,先尝试输入随意的ID和Key,获取弹出的提示信息字符串

尝试在OD中搜索如下字符 “Invalid name or password.”,搜索结果如下

发现存在大量提示信息,我们在其中找到注册成功的提示信息,(上图红框:感谢购买010editor),双击查看反汇编窗口,见下图。

往上查看判断注册成功的关键跳转

我们发现地址为00DD5926处跳转JNZ 010Edito.00DD5A58应该为关键跳转,下方可以找到输出字符串”Password accepted. This ….”, 而其跳转地址处汇编代码为输出”Password accepted….”

(010editor使用QT界面库编写 ,我们可以猜测出push字符串随后的函数应为输出字符串)

回到关键跳转00DD5926处,判断密码为正确的条件为EDI = 0xDB,而EDI的值是EAX给的,而EAX为函数010Edito.00409C9B的返回值,这个函数可能为验证Key的关键函数,而我们动态调试发现有跳转直接跳转到cmp edi,0xdb。

同样为函数010Edito.00409C9B,现在可以认为这是关键函数,此时EDI的值为0x177,为了验证此跳转为关键跳转,我们把EDI的值修改为0xDB。

之后F9运行

验证成功!接下来我们进入函数分析。

第二步 分析关键函数1(返回DB为注册成功)

函数010Edito.00409C9B,参数情况为:

arg1 = 0x9 ;

arg2 = 0x4389;

从下往上看,找到需要的0xDB,而跳转条件是eax = 0x2D, 为函数010Edito.0040A826的返回值。

第三步 分析关键函数2(返回2D为注册成功)

进入函数,该函数作用为将key取出,放在在局部变量数组中,数组起始地址为ebx-24

key[0 ]   = [ebx-24]=0x12
key[1 ]   = [ebx-23]=0x34
key[2 ]   = [ebx-22]=0x56
key[3 ]   = [ebx-21]=0x78
key[4 ]   = [ebx-20]=0x90
key[5 ]   = [ebx-1F]=0x12
key[6 ]   = [ebx-1E]=0x34
key[7 ]   = [ebx-1D]=0x56
key[8 ]   = [ebx-1C]=0x78
key[9 ]   = [ebx-1B]=0x90

密钥数组对应如上,该处汇编代码如下,当KEY[3] == 0x9C时

013BDC5D   .  8A5D DF       MOV BL,BYTE PTR SS:[EBP-0x21]    ;  key[3]
013BDC60   .  8A7D E1       MOV BH,BYTE PTR SS:[EBP-0x1F]    ;  key[5]
013BDC63   .  80FB 9C       CMP BL,0x9C                      ;  是否等于0x9c
013BDC66   .  75 70         JNZ SHORT 010Edito.013BDCD8      ;  跳转到是否等于FC
013BDC68   .  8A45 DC       MOV AL,BYTE PTR SS:[EBP-0x24]    ;  key[0]
013BDC6B   .  3245 E2       XOR AL,BYTE PTR SS:[EBP-0x1E]    ;  key[0]^key[6]
013BDC6E   .  8845 E8       MOV BYTE PTR SS:[EBP-0x18],AL ;
013BDC71   .  8A45 DD       MOV AL,BYTE PTR SS:[EBP-0x23] ;  key[1]
013BDC74   .  3245 E3       XOR AL,BYTE PTR SS:[EBP-0x1D] ;  key[1]^key[7]
013BDC77   .  FF75 E8       PUSH DWORD PTR SS:[EBP-0x18]
013BDC7A   .  0FB6C8        MOVZX ECX,AL
013BDC7D   .  B8 00010000   MOV EAX,0x100
013BDC82   .  66:0FAFC8     IMUL CX,AX                      ;  (key[1]^key[7])*0x100
013BDC86   .  8A45 DE       MOV AL,BYTE PTR SS:[EBP-0x22]    ;  key[2]
013BDC89   .  32C7          XOR AL,BH                   ;  key[2]^key[5]
013BDC8B   .  0FB6C0        MOVZX EAX,AL
013BDC8E   .  66:03C8       ADD CX,AX                                             
;cx = (key[1]^key[7])*0x100 + key[2]^key[5]
013BDC91   .  0FB7F1        MOVZX ESI,CX
013BDC94   .  E8 AB9904FF   CALL 010Edito.00407644                    
  013BD0B0  /> \55            PUSH EBP
  013BD0B1  |.  8BEC          MOV EBP,ESP
  013BD0B3  |.  8B45 08       MOV EAX,[ARG.1] 
  ;  eax = key[0]^key[6] 
  013BD0B6  |.  34 18         XOR AL,0x18     
  ;  al = key[0]^key[6]^0x18 
  013BD0B8  |.  04 3D         ADD AL,0x3D     
  ;  al = key[0]^key[6]^0x18 + 0x3D
  013BD0BA  |.  34 A7         XOR AL,0xA7     
  ;  al =(key[0]^key[6]^0x18+0x3D)^0xA7
  013BD0BC  |.  5D            POP EBP                          
  013BD0BD  \.  C3            RETN

013BDC99   .  0FB6C0        MOVZX EAX,AL
013BDC9C   .  56            PUSH ESI          
;  esi = (key[1]^key[7])*0x100 + key[2]^key[5]
013BDC9D   .  8947 1C       MOV DWORD PTR DS:[EDI+0x1C],EAX
013BDCA0   .  E8 23A704FF   CALL 010Edito.004083C8
  013BD020  /> \55            PUSH EBP
  013BD021  |.  8BEC          MOV EBP,ESP
  013BD023  |.  8B45 08       MOV EAX,[ARG.1]     
  ;eax=(key[1]^key[7])*100+key[2]^key[5]
  013BD026  |.  B9 0B000000   MOV ECX,0xB         
  ; ecx = 0xB
  013BD02B  |.  35 92780000   XOR EAX,0x7892      
  ;eax=((key[1]^key[7])*0x100+key[2]^key[5])^0x7892
  013BD030  |.  05 304D0000   ADD EAX,0x4D30
  ;eax=((key[1]^key[7])*0x100+key[2]^key[5])^0x7892 + 0x4D30
  013BD035  |.  35 21340000   XOR EAX,0x3421
  ;eax=(((key[1]^key[7])*0x100+key[2]^key[5])^0x7892 + 0x4D30)^0x3421
  013BD03A  |.  0FB7C0        MOVZX EAX,AX
  013BD03D  |.  99            CDQ
  013BD03E  |.  F7F9          IDIV ECX        
  ;eax=(((key[1]^key[7])*0x100+key[2]^key[5])^0x7892 + 0x4D30)^0x3421/0xB
  013BD040  |.  85D2          TEST EDX,EDX    ;eax/ecx的余数是否为0
  013BD042  |.  74 02         JE SHORT 010Edito.013BD046  ;如果余数不为0,清零eax
  013BD044  |.  33C0          XOR EAX,EAX
  013BD046  |>  5D            POP EBP                                
  013BD047  \.  C3            RETN

013BDCA5   .  8B4F 1C       MOV ECX,DWORD PTR DS:[EDI+0x1C]
; ecx = (key[0]^key[6]^0x18+0x3D)^0xA7
013BDCA8   .  83C4 08       ADD ESP,0x8       
013BDCAB   .  0FB7C0        MOVZX EAX,AX
;eax=(((key[1]^key[7])*100+key[2]^key[5])^0x7892 + 0x4D30)^0x3421
013BDCAE   .  8947 20       MOV DWORD PTR DS:[EDI+0x20],EAX
;[EDI+0x20] =(((key[1]^key[7])*100+key[2]^key[5])^0x7892 + 0x4D30)^0x3421/0xB
013BDCB1   .  85C9          TEST ECX,ECX  
013BDCB3   .  0F84 BC010000 JE 010Edito.013BDE75  ;ecx = 0 则eax=E7返回,验证失败
013BDCB9   .  85C0          TEST EAX,EAX
013BDCBB   .  0F84 B4010000 JE 010Edito.013BDE75  ;eax = 0 则eax=E7返回,验证失败
013BDCC1   .  3D E8030000   CMP EAX,0x3E8
013BDCC6   .  0F87 A9010000 JA 010Edito.013BDE75  ;eax > 0x3E8 则eax=E7返回,验证失败
013BDCCC   .  83F9 02       CMP ECX,0x2               ;ecx小于等于1时,借位cf=1,否则cf=0
013BDCCF   .  1BF6          SBB ESI,ESI               ; esi=esi-esi-CF=-cf
013BDCD1   .  23F1          AND ESI,ECX               ;esi = esi & ecx    
013BDCD3   .  E9 B3000000   JMP 010Edito.013BDD8B ;0xAC分支也跳转到这里013BDD8B

当KEY[3] == 0x9C时,等换成C为

case 0x9C:
{
    [EDI+0x1C] = (key[0]^key[6]^0x18+0x3D)^0xA7;  //最后一步验证用到
    [EDI+0x20] =(((key[1]^key[7])*0x100+key[2]^key[5])^0x7892 + 0x4D30)^0x3421;
    eax=(((key[1]^key[7])*0x100+key[2]^key[5])^0x7892 + 0x4D30)^0x3421;
    ecx = (key[0]^key[6]^0x18+0x3D)^0xA7;
    cf = 0;
    if(eax % 0xB != 0)
    {
        eax = 0;
    } 
    if(ecx == 0 || eax == 0 || eax  > 0x3E8)
    {
          //验证失败
        return;
    }
    else 
    {

      eax=(((key[1]^key[7])*0x100+key[2]^key[5])^0x7892 + 0x4D30)^0x3421/0xB;
         [EDI+0x20] = eax;
        if(ecx <= 1)
        {
            cf = 1;
        }
        esi = (0 - cf) & ecx; //cf=0 则 esi=0;
    }
    break;
}

当KEY[3] == 0xFC时,所有跳转最终都不返回我们需要的0x2D ,跳过。

当KEY[3] == 0xAC时

013BDCFC   > \80FB AC       CMP BL,0xAC
013BDCFF   .  0F85 70010000 JNZ 010Edito.013BDE75
013BDD05   .  8A45 DD       MOV AL,BYTE PTR SS:[EBP-0x23]                                ; al = key[1]
013BDD08   .  3245 E3       XOR AL,BYTE PTR SS:[EBP-0x1D]                                ; al = key[1]^key[7]
013BDD0B   .  0FB6C8        MOVZX ECX,AL                                           ; ecx = key[1]^key[7]
013BDD0E   .  B8 00010000   MOV EAX,0x100
013BDD13   .  66:0FAFC8     IMUL CX,AX                                                ; cx = (key[1]^key[7]) * 0x100
013BDD17   .  8A45 DE       MOV AL,BYTE PTR SS:[EBP-0x22]                           ;  al = key[2]
013BDD1A   .  32C7          XOR AL,BH                                             ; al = key[2]^key[5]
013BDD1C   .  C747 1C 02000>MOV DWORD PTR DS:[EDI+0x1C],0x2                             ;[edi+0x1C] = 0x2
013BDD23   .  0FB6C0        MOVZX EAX,AL                                          ; eax = key[2]^key[5]
013BDD26   .  66:03C8       ADD CX,AX                                             ; cx = (key[1]^key[7]) * 0x100 + key[2]^key[5]
013BDD29   .  0FB7C1        MOVZX EAX,CX                                          ; eax = (key[1]^key[7]) * 0x100 + key[2]^key[5]
013BDD2C   .  50            PUSH EAX
013BDD2D   .  E8 96A604FF   CALL 010Edito.004083C8
  013BD020  /> \55            PUSH EBP
  013BD021  |.  8BEC          MOV EBP,ESP
  013BD023  |.  8B45 08       MOV EAX,[ARG.1]                                     
  013BD026  |.  B9 0B000000   MOV ECX,0xB
  013BD02B  |.  35 92780000   XOR EAX,0x7892                                      ;       eax = ((key[1]^key[7]) * 0x100 + key[2]^key[5])^0x7892
  013BD030  |.  05 304D0000   ADD EAX,0x4D30                                      ;       eax = ((key[1]^key[7]) * 0x100 + key[2]^key[5])^0x7892 + 0x4D30
  013BD035  |.  35 21340000   XOR EAX,0x3421                                      ;       eax = (((key[1]^key[7]) * 0x100 + key[2]^key[5])^0x7892 + 0x4D30)^0x3421
  013BD03A  |.  0FB7C0        MOVZX EAX,AX
  013BD03D  |.  99            CDQ
  013BD03E  |.  F7F9          IDIV ECX                                            ;       eax = ((((key[1]^key[7]) * 0x100 + key[2]^key[5])^0x7892 + 0x4D30)^0x3421)/0xB
  013BD040  |.  85D2          TEST EDX,EDX                                        ;        余数edx != 0 则,eax=0
  013BD042  |.  74 02         JE SHORT 010Edito.013BD046
  013BD044  |.  33C0          XOR EAX,EAX
  013BD046  |>  5D            POP EBP                                                  
  013BD047  \.  C3            RETN

013BDD32   .  0FB7C0        MOVZX EAX,AX
013BDD35   .  83C4 04       ADD ESP,0x4
013BDD38   .  8947 20       MOV DWORD PTR DS:[EDI+0x20],EAX
013BDD3B   .  85C0          TEST EAX,EAX                                          ;  检测上面的函数返回结果eax是否为0
013BDD3D   .  0F84 32010000 JE 010Edito.013BDE75;eax=0跳转到返回0xE7,验证失败
013BDD43   .  3D E8030000   CMP EAX,0x3E8
013BDD48   .  0F87 27010000 JA 010Edito.013BDE75;eax大于0x3E8跳转到返回0xE7,验证失败
013BDD4E   .  0FB655 E5     MOVZX EDX,BYTE PTR SS:[EBP-0x1B]                        ; edx = key[9]
013BDD52   .  0FB64D E0     MOVZX ECX,BYTE PTR SS:[EBP-0x20]                        ; ecx = key[4]
013BDD56   .  0FB6C7        MOVZX EAX,BH                                          ; eax = key[5]
013BDD59   .  33D0          XOR EDX,EAX                                               ; edx = key[9]^key[5]
013BDD5B   .  0FB645 E4     MOVZX EAX,BYTE PTR SS:[EBP-0x1C]                        ; eax = key[8]                    
013BDD5F   .  33C8          XOR ECX,EAX                                               ; ecx = key[4]^key[8]
013BDD61   .  C1E2 08       SHL EDX,0x8
013BDD64   .  0FB645 E2     MOVZX EAX,BYTE PTR SS:[EBP-0x1E]                        ; eax = key[6]
013BDD68   .  03D1          ADD EDX,ECX                                               ; edx = ((key[9]^key[5])<<8) +  key[4]^key[8]
013BDD6A   .  0FB64D DC     MOVZX ECX,BYTE PTR SS:[EBP-0x24]                        ; ecx = key[0]
013BDD6E   .  C1E2 08       SHL EDX,0x8                                               ; edx = (((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8
013BDD71   .  33C8          XOR ECX,EAX                                               ; ecx = key[0]^key[6]
013BDD73   .  03D1          ADD EDX,ECX                                               ; edx = ((((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8) + key[0]^key[6]
013BDD75   .  68 278C5B00   PUSH 010Edito.005B8C27                                       ;  CCCCCCCC
013BDD7A   .  52            PUSH EDX
013BDD7B   .  E8 0BCA04FF   CALL 010Edito.0040A78B
  013BCF90  /> \55            PUSH EBP
  013BCF91  |.  8BEC          MOV EBP,ESP
  013BCF93  |.  8B4D 08       MOV ECX,[ARG.1]                                     ;     ecx = ((((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8) + key[0]^key[6]
  013BCF96  |.  B8 F1F0F0F0   MOV EAX,0xF0F0F0F1
  013BCF9B  |.  334D 0C       XOR ECX,[ARG.2]                                     ;     ecx = (((((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8) + key[0]^key[6])                   ^ 0x005B8C27   
  013BCF9E  |.  81F1 78C02200 XOR ECX,0x22C078                                    ;     ecx = ((((((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8) + key[0]^key[6])                  ^ 0x005B8C27)  ^  0x22C078
  013BCFA4  |.  81E9 75C10200 SUB ECX,0x2C175                                     ;     ecx = ((((((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8) + key[0]^key[6])                  ^ 0x005B8C27)  ^  0x22C078 - 0x2C175
  013BCFAA  |.  81F1 6731E5FF XOR ECX,0xFFE53167                                  ;     ecx = (((((((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8) + key[0]^key[6])                  ^ 0x005B8C27) ^  0x22C078 - 0x2C175) ^ 0xFFE53167
  013BCFB0  |.  81E1 FFFFFF00 AND ECX,0xFFFFFF                                    ;     ecx = ((((((((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8) + key[0]^key[6])                  ^ 0x005B8C27)    ^  0x22C078 - 0x2C175) ^ 0xFFE53167) & 0xFFFFFF
  013BCFB6  |.  F7E1          MUL ECX                                             ;      eax = 0xF0F0F0F1 * ecx    结果高32位放在edx。 低32位放在eax
  013BCFB8  |.  C1EA 04       SHR EDX,0x4
  013BCFBB  |.  8BC2          MOV EAX,EDX
  013BCFBD  |.  C1E0 04       SHL EAX,0x4
  013BCFC0  |.  03C2          ADD EAX,EDX
  013BCFC2  |.  2BC8          SUB ECX,EAX     ;结果为0 则 zf=1
  013BCFC4  |.  B8 00000000   MOV EAX,0x0
  013BCFC9  |.  0F44C2        CMOVE EAX,EDX   ;当zf = 1时移动 
  013BCFCC  |.  5D            POP EBP        
  013BCFCD  \.  C3            RETN


013BDD80   .  83C4 08       ADD ESP,0x8
013BDD83   .  8945 F0       MOV DWORD PTR SS:[EBP-0x10],EAX
013BDD86   .  8947 34       MOV DWORD PTR DS:[EDI+0x34],EAX
013BDD89   .  8BF0          MOV ESI,EAX
013BDD8B   > \8D45 EC       LEA EAX,DWORD PTR SS:[EBP-0x14];0x9C分支也跳转到这里

转换成C代码

case 0xAC:
{
    eax = ((((key[1]^key[7]) * 0x100 + key[2]^key[5])^0x7892 + 0x4D30)^0x3421);
    ecx = ((((((((key[9]^key[5]) << 8) +  key[4]^key[8]) << 8) + key[0]^key[6])                  ^ 0x005B8C27)    ^  0x22C078 - 0x2C175) ^ 0xFFE53167) & 0xFFFFFF;
    if(eax % 0xB != 0)
    {
        eax = 0;
        return ;  //跳转返回0x7E分支,验证失败
    }
    eax = ((((key[1]^key[7]) * 0x100 + key[2]^key[5])^0x7892 + 0x4D30)^0x3421)/0xB;
    eax = 0xF0F0F0F1 * ecx;   // 结果高32位放在edx。 低32位放在eax
    edx = edx >> 4;
    eax = edx;
    eax = eax << 4;
    eax = eax + edx;
    ecx = ecx - eax;
    eax = 0;
    if(ecx==0)
    {
        eax = edx; 
    }  
    [ebp-0x10] = eax;     //最后一步验证用到
    [edi+0x34] = eax;
    esi = eax;
    break;
}

分支0x9C、0xAC都将运行到此处

013BDD8B   > \8D45 EC       LEA EAX,DWORD PTR SS:[EBP-0x14]
013BDD8E   .  50            PUSH EAX
013BDD8F   .  8D4F 04       LEA ECX,DWORD PTR DS:[EDI+0x4]
013BDD92   .  FF15 782BE702 CALL DWORD PTR DS:[<&Qt5Core.?toUtf8@QString@@QBE?AVQByteArr>;  Qt5Core.?toUtf8@QString@@QBE?AVQByteArray@@XZ

不知道这段是干嘛,我们继续单步,到如上图所示,函数[<&Qt5Core.?data@QByteArray@@QAE>] 返回了用户名字符串,然后传入函数010Edito.00402E50,其再返回 一串类似哈希值的值,那么这个函数的作用应该为处理函数名称,进入分析。

第四步 分析用户名处理函数

根据mov esp, 0x10可知,用户名处理函数共有四个参数

参数1:用户名

参数2:当BL=0XFC时为1,否则为0,根据前面的分析可知,BL为Key[3]

参数3:esi,经上一个函数处理得到

参数4:[edi+0x20],经上一个函数处理得到

013BD120  /> \55            PUSH EBP
013BD121  |.  8BEC          MOV EBP,ESP
013BD123  |.  83EC 10       SUB ESP,0x10
013BD126  |.  8B55 08       MOV EDX,[ARG.1]
;edx = 用户名pName
013BD129  |.  33C9          XOR ECX,ECX
;ecx = 0
013BD12B  |.  56            PUSH ESI
;备份esi
013BD12C  |.  8BF2          MOV ESI,EDX
;esi = 用户名pName
013BD12E  |.  894D FC       MOV [LOCAL.1],ECX
;[LOCAL.1] = 0
013BD131  |.  57            PUSH EDI
;备份EDI
013BD132  |.  8D7E 01       LEA EDI,DWORD PTR DS:[ESI+0x1]
;edi = 用户名地址 + 1,后面被esi减去求得长度
013BD135  |>  8A06          /MOV AL,BYTE PTR DS:[ESI]
;al = pName[0]
013BD137  |.  46            |INC ESI
;pName++
013BD138  |.  84C0          |TEST AL,AL
013BD13A  |.^ 75 F9         \JNZ SHORT 010Edito.013BD135
;判断是否到达字符串结尾
013BD13C  |.  2BF7          SUB ESI,EDI
;求得长度,ESI指向为用户名字符串结尾的'\0'
013BD13E  |.  33FF          XOR EDI,EDI
013BD140  |.  85F6          TEST ESI,ESI
013BD142  |.  0F8E F0000000 JLE 010Edito.013BD238
;检查长度是否不为0
013BD148  |.  53            PUSH EBX
013BD149  |.  8B5D 14       MOV EBX,[ARG.4]
;ebx = [ARG.4] = 传入的[edi+0x20]
013BD14C  |.  894D F0       MOV [LOCAL.4],ECX ;置零
013BD14F  |.  894D F4       MOV [LOCAL.3],ECX ;置零
013BD152  |.  8B4D 10       MOV ECX,[ARG.3]
;ecx = [ARG.3] = 传入的esi
013BD155  |.  C1E3 04       SHL EBX,0x4
013BD158  |.  2B5D 14       SUB EBX,[ARG.4]
;ebx = ([ARG.4] *16) - [ARG.4]
013BD15B  |.  C1E1 04       SHL ECX,0x4
013BD15E  |.  034D 10       ADD ECX,[ARG.3]
;ecx = ([ARG.3]  *16) + [ARG.3]
013BD161  |.  894D F8       MOV [LOCAL.2],ECX
;[LOCAL.2] = ([ARG.3] << 4) + [ARG.3]
013BD164  |>  0FB60417      /MOVZX EAX,BYTE PTR DS:[EDI+EDX]
013BD168  |.  50            |PUSH EAX                                                    ; /c = B6
013BD169  |.  FF15 9422E702 |CALL DWORD PTR DS:[<&MSVCR120.toupper>]                     ; \toupper  小写字母转换为大写字母
013BD16F  |.  8BD0          |MOV EDX,EAX
;返回值复制给edx,大写字符
013BD171  |.  83C4 04       |ADD ESP,0x4
013BD174  |.  8B0C95 4841E6>|MOV ECX,DWORD PTR DS:[EDX*4+0x2E64148]
;将大写字母作为索引从数组0x2E64148中取内容
;为了方便,把数组0x2E64148称为nArray,故这里ecx = nArray[edx]
013BD17B  |.  034D FC       |ADD ECX,[LOCAL.1]
;ecx =nArray[大写字符] + [LOCAL.1] ,[LOCAL.1]最初为0
013BD17E  |.  837D 0C 00    |CMP [ARG.2],0x0
;判断是哪种类型的注册
013BD182  |.  74 4A         |JE SHORT 010Edito.013BD1CE


;注册类型1---------------------------------------------------------
013BD184  |.  8D42 0D       |LEA EAX,DWORD PTR DS:[EDX+0xD]   
013BD187  |.  25 FF000000   |AND EAX,0xFF
;eax = [大写字符+0xD] & 0xFF,这个值为数组下标,与0xFF可能说明数组最大个数为0xFF,即256013BD18C  |.  330C85 4841E6>|XOR ECX,DWORD PTR DS:[EAX*4+0x2E64148]
;ecx = (nArray[大写字符] + [LOCAL.1]) ^ nArray[eax]
013BD193  |.  8D42 2F       |LEA EAX,DWORD PTR DS:[EDX+0x2F]
;eax = [大写字符+0x2F]
013BD196  |.  25 FF000000   |AND EAX,0xFF
;eax = eax & 0xFF
013BD19B  |.  0FAF0C85 4841>|IMUL ECX,DWORD PTR DS:[EAX*4+0x2E64148]
;ecx = ecx*nArray[eax]
013BD1A3  |.  8B45 F8       |MOV EAX,[LOCAL.2]                                           ;  010Edito.01885E59
;eax = [LOCAL.2] = ([ARG.3] << 4) + [ARG.3]
013BD1A6  |.  0FB6C0        |MOVZX EAX,AL
;eax &= 0xFF
013BD1A9  |.  030C85 4841E6>|ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
;ecx = ecx + nArray[eax]
013BD1B0  |.  0FB6C3        |MOVZX EAX,BL
;eax = ebx = ([ARG.4] << 4) - [ARG.4]
013BD1B3  |.  030C85 4841E6>|ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
;ecx = ecx + nArray[eax]
013BD1BA  |.  8B45 F4       |MOV EAX,[LOCAL.3]
;eax = [LOCAL.3]
013BD1BD  |.  0FB6C0        |MOVZX EAX,AL
013BD1C0  |.  030C85 4841E6>|ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
;ecx = ecx + nArray[eax]
013BD1C7  |.  8BC1          |MOV EAX,ECX
;eax = ecx
013BD1C9  |.  8945 FC       |MOV [LOCAL.1],EAX
;[LOCAL.1] = eax
013BD1CC  |.  EB 48         |JMP SHORT 010Edito.013BD216


;注册类型0----------------------------------------------------------
013BD1CE  |>  8D42 3F       |LEA EAX,DWORD PTR DS:[EDX+0x3F];这里不同
013BD1D1  |.  25 FF000000   |AND EAX,0xFF
013BD1D6  |.  330C85 4841E6>|XOR ECX,DWORD PTR DS:[EAX*4+0x2E64148]
013BD1DD  |.  8D42 17       |LEA EAX,DWORD PTR DS:[EDX+0x17];这里不同
013BD1E0  |.  25 FF000000   |AND EAX,0xFF
013BD1E5  |.  0FAF0C85 4841>|IMUL ECX,DWORD PTR DS:[EAX*4+0x2E64148]
013BD1ED  |.  8B45 F8       |MOV EAX,[LOCAL.2]                                           ;  010Edito.01885E59
013BD1F0  |.  0FB6C0        |MOVZX EAX,AL
013BD1F3  |.  030C85 4841E6>|ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
013BD1FA  |.  0FB6C3        |MOVZX EAX,BL
013BD1FD  |.  030C85 4841E6>|ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
013BD204  |.  8B45 F0       |MOV EAX,[LOCAL.4]
;eax = [LOCAL.4], 另一种注册类型这里为 [LOCAL.3]
013BD207  |.  0FB6C0        |MOVZX EAX,AL
013BD20A  |.  030C85 4841E6>|ADD ECX,DWORD PTR DS:[EAX*4+0x2E64148]
013BD211  |.  8BC1          |MOV EAX,ECX
013BD213  |.  894D FC       |MOV [LOCAL.1],ECX



;共通线----------------------------------------------------------------
013BD216  |>  8345 F4 13    |ADD [LOCAL.3],0x13
;[LOCAL.3] += 0x13
013BD21A  |.  47            |INC EDI
013BD21B  |.  8345 F8 09    |ADD [LOCAL.2],0x9
;[LOCAL.2] += 0x9
013BD21F  |.  83C3 0D       |ADD EBX,0xD
;EBX += 0xD
013BD222  |.  8345 F0 07    |ADD [LOCAL.4],0x7
;[LOCAL.4] += 0x7
013BD226  |.  8B55 08       |MOV EDX,[ARG.1]
; EDX = [ARG.1] = 用户名
013BD229  |.  3BFE          |CMP EDI,ESI
;ESI指向为用户名字符串结尾的0, 判断EDI是否也到结尾,没有则继续循环计算
013BD22B  |.^ 0F8C 33FFFFFF \JL 010Edito.013BD164
013BD231  |.  5B            POP EBX                                                      ;  05661E08
013BD232  |.  5F            POP EDI                                                      ;  05661E08
013BD233  |.  5E            POP ESI                                                      ;  05661E08
013BD234  |.  8BE5          MOV ESP,EBP
013BD236  |.  5D            POP EBP                                                      ;  05661E08
013BD237  |.  C3            RETN

 ;用户名长度为0------------------------------------------------------
013BD238  |>  5F            POP EDI                                                      ;  05661E08
013BD239  |.  8BC1          MOV EAX,ECX
013BD23B  |.  5E            POP ESI                                                      ;  05661E08
013BD23C  |.  8BE5          MOV ESP,EBP
013BD23E  |.  5D            POP EBP                                                      ;  05661E08
013BD23F  \.  C3            RETN

转换成C语言

arg_1 = pName;
arg_2;
arg_3 = ESI;
arg_4 = [edi+0x20];

DWORD LOCAL_1 = 0;
DWORD LOCAL_2 = (arg_3 * 16) + arg_3
DWORD LOCAL_3 = 0;
DWORD LOCAL_4 = 0;

ebx =(arg_4 * 16) - arg_4;
char nArray[256]=
{
39CB44B8, 23754F67,   5F017211,   3EBB24DA,   351707C6,   63F9774B,   17827288,   0FE74821,   5B5F670F,   48315AE8,   785B7769,   2B7A1547,   38D11292,   42A11B32,   35332244,   77437B60,   1EAB3B10,   53810000,   1D0212AE,   6F0377A8,   43C03092,   2D3C0A8E,   62950CBF,   30F06FFA,   34F710E0,   28F417FB,   350D2F95,   5A361D5A,   15CC060B,   0AFD13CC,   28603BCF,   3371066B,   30CD14E4,   175D3A67,   6DD66A13,   2D3409F9,   581E7B82,   76526B99,   5C8D5188,   2C857971,   15F51FC0,   68CC0D11,   49F55E5C,   275E4364,   2D1E0DBC,   4CEE7CE3,   32555840,   112E2E08,   6978065A,   72921406,   314578E7,   175621B7,   40771DBF,   3FC238D6,   4A31128A,   2DAD036E,   41A069D6,   25400192,   00DD4667,   6AFC1F4F,   571040CE,   62FE66DF,   41DB4B3E,   3582231F,   55F6079A,   1CA70644,   1B1643D2,   3F7228C9,   5F141070,   3E1474AB,   444B256E,   537050D9,   0F42094B,   2FD820E6,   778B2E5E,   71176D02,   7FEA7A69,   5BB54628,   19BA6C71,   39763A99,   178D54CD,   01246E88,   3313537E,   2B8E2D17,   2A3D10BE,   59D10582,   37A163DB,   30D6489A,   6A215C46,   0E1C7A76,   1FC760E7,   79B80C65,   27F459B4,   799A7326,   50BA1782,   2A116D5C,   63866E1B,   3F920E3C,   55023490,   55B56089,   2C391FD1,   2F8035C2,   64FD2B7A,   4CE8759A,   518504F0,   799501A8,   3F5B2CAD,   38E60160,   637641D8,   33352A42,   51A22C19,   085C5851,   032917AB,   2B770AC7,   30AC77B3,   2BEC1907,   035202D0,   0FA933D3,   61255DF3,   22AD06BF,   58B86971,   5FCA0DE5,   700D6456,   56A973DB,   5AB759FD,   330E0BE2,   5B3C0DDD,   495D3C60,   53BD59A6,   4C5E6D91,   49D9318D,   103D5079,   61CE42E3,   7ED5121D,   14E160ED,   212D4EF2,   270133F0,   62435A96,   1FA75E8B,   6F092FBE,   4A000D49,   57AE1C70,   004E2477,   561E7E72,   468C0033,   5DCC2402,   78507AC6,   58AF24C7,   0DF62D34,   358A4708,   3CFB1E11,   2B71451C,   77A75295,   56890721,   0FEF75F3,   120F24F1,   01990AE7,   339C4452,   27A15B8E,   0BA7276D,   60DC1B7B,   4F4B7F82,   67DB7007,   4F4A57D9,   621252E8,   20532CFC,   6A390306,   18800423,   19F3778A,   462316F0,   56AE0937,   43C2675C,   65CA45FD,   0D604FF2,   0BFD22CB,   3AFE643B,   3BF67FA6,   44623579,   184031F8,   32174F97,   4C6A092A,   5FB50261,   01650174,   33634AF1,   712D18F4,   6E997169,   5DAB7AFE,   7C2B2EE8,   6EDB75B4,   5F836FB6,   3C2A6DD6,   292D05C2,   052244DB,   149A5F4F,   5D486540,   331D15EA,   4F456920,   483A699F,   3B450F05,   3B207C6C,   749D70FE,   417461F6,   62B031F1,   2750577B,   29131533,   588C3808,   1AEF3456,   0F3C00EC,   7DA74742,   4B797A6C,   5EBB3287,   786558B8,   00ED4FF2,   6269691E,   24A2255F,   62C11F7E,   2F8A7DCD,   643B17FE,   778318B8,   253B60FE,   34BB63A3,   5B03214F,   5F1571F4,   1A316E9F,   7ACF2704,   28896838,   18614677,   1BF569EB,   0BA85EC9,   6ACA6B46,   1E43422A,   514D5F0E,   413E018C,   307626E9,   01ED1DFA,   49F46F5A,   461B642B,   7D7007F2,   13652657,   6B160BC5,   65E04849,   1F526E1C,   5A0251B6,   2BD73F69,   2DBF7ACD,   51E63E80,   5CF2670F,   21CD0A03,   5CFF0261,   33AE061E,   3BB6345F,   5D814A75,   257B5DF4,   0A5C2C5B,   16A45527,   16F23945
};

while(nNameLen)
{
  pName[i]
  char cName = toupper(pName);    //小写转大写

  //注册类型1
  if(key[3] != 0xFC)
  {
      LOCAL_1 = (nArray[cName]+LOCAL_1);
      LOCAL_1 ^= nArray[(cName+0xD)];
      LOCAL_1 *= nArray[(cName+0x2F)];

      LOCAL_1 += nArray[LOCAL_2];
      LOCAL_1 += nArray[ebx];
      LOCAL_1 += nArray[LOCAL_3];
  }
  //注册类型0,没有用到
  else if(key[3] == 0xFC)
  {
      LOCAL_1 = (nArray[cName]+LOCAL_1);
      LOCAL_1 ^= nArray[(cName+0x3F)];
      LOCAL_1 *= nArray[(cName+0x17)];

      LOCAL_1 += nArray[LOCAL_2];
      LOCAL_1 += nArray[ebx];
      LOCAL_1 += nArray[LOCAL_4];
  }
  LOCAL_3 += 0x13;
  nNameLen--;
  LOCAL_2 += 0x9;
  ebx += 0xD 
  LOCAL_4 += 0x7;
  i++;
}
return LOCAL_1;

函数返回结果如上图。

第五步 处理计算结果

由上图分析可知,接下来将处理用户名函数的返回值多次右移比较,根据结果分发返回值,最终跳转到我们需要的返回值0x2D。代码如下

013BDDB6   .  E8 955004FF   CALL 010Edito.00402E50             ;  处理用户名的函数
013BDDBB   .  8BD0          MOV EDX,EAX
013BDDBD   .  83C4 10       ADD ESP,0x10                      ;  意味着上面函数有四个参数
013BDDC0   .  3855 E0       CMP BYTE PTR SS:[EBP-0x20],DL     ;  比较key[4],返回值低8013BDDC3   .  0F85 81000000 JNZ 010Edito.013BDE4A             ;  跳转到返回0xE7,失败
013BDDC9   .  8BCA          MOV ECX,EDX
013BDDCB   .  C1E9 08       SHR ECX,0x8                       ;  右移0x8
013BDDCE   .  3AF9          CMP BH,CL                         ;  key[5],cl
013BDDD0   .  75 78         JNZ SHORT 010Edito.013BDE4A       ;  跳转到返回0xE7,失败
013BDDD2   .  8BCA          MOV ECX,EDX
013BDDD4   .  C1E9 10       SHR ECX,0x10                      ;  右移10013BDDD7   .  384D E2       CMP BYTE PTR SS:[EBP-0x1E],CL     ;  key[6]
013BDDDA   .  75 6E         JNZ SHORT 010Edito.013BDE4A       ;  跳转到返回0xE7,失败
013BDDDC   .  C1E8 18       SHR EAX,0x18                      ;  右移0x18
013BDDDF   .  3845 E3       CMP BYTE PTR SS:[EBP-0x1D],AL     ;  key[7]
013BDDE2   .  75 66         JNZ SHORT 010Edito.013BDE4A       ;  跳转到返回0xE7,失败
013BDDE4   .  80FB 9C       CMP BL,0x9C                       ;  Switch (cases 9C..FC)
013BDDE7   .  75 0F         JNZ SHORT 010Edito.013BDDF8
013BDDE9   .  8B45 08       MOV EAX,DWORD PTR SS:[EBP+0x8]    ;  Case 9C of switch 013BDDE4
013BDDEC   .  3B47 1C       CMP EAX,DWORD PTR DS:[EDI+0x1C]       ; 小于等于
013BDDEF   .  76 52         JBE SHORT 010Edito.013BDE43       ;  跳转到返回0x2D,验证正确
013BDDF1   .  BE 4E000000   MOV ESI,0x4E
013BDDF6   .  EB 57         JMP SHORT 010Edito.013BDE4F        ;  返回返回4E,验证失败
013BDDF8   >  80FB FC       CMP BL,0xFC
013BDDFB   .  75 2E         JNZ SHORT 010Edito.013BDE2B        ;  FC分支得不到正确结果,跳过
013BDE2B   >  80FB AC       CMP BL,0xAC
013BDE2E   .  75 1A         JNZ SHORT 010Edito.013BDE4A
013BDE30   .  8B45 F0       MOV EAX,DWORD PTR SS:[EBP-0x10]   ;  Case AC of switch 013BDDE4
013BDE33   .  85C0          TEST EAX,EAX
013BDE35   .  74 13         JE SHORT 010Edito.013BDE4A        ;  跳转到验证错误
013BDE37   .  3945 0C       CMP DWORD PTR SS:[EBP+0xC],EAX
013BDE3A   .  76 07         JBE SHORT 010Edito.013BDE43       ;  跳转到返回0x2D,验证正确
013BDE3C   .  BE 4E000000   MOV ESI,0x4E
013BDE41   .  EB 0C         JMP SHORT 010Edito.013BDE4F
013BDE43   >  BE 2D000000   MOV ESI,0x2D                  ;  验证正确,返回0x2D!!!!
013BDE48   .  EB 05         JMP SHORT 010Edito.013BDE4F
013BDE4A   >  BE E7000000   MOV ESI,0xE7                      ;  Default case of switch 013BDDE4
013BDE4F   >  8D4D EC       LEA ECX,DWORD PTR SS:[EBP-0x14]
013BDE52   .  C745 FC FFFFF>MOV DWORD PTR SS:[EBP-0x4],-0x1
013BDE59   .  FF15 7C24E702 CALL DWORD PTR DS:[<&Qt5Core.??1Q>;  Qt5Core.??1QByteArray@@QAE@XZ
013BDE5F   .  8BC6          MOV EAX,ESI
013BDE61   .  8B4D F4       MOV ECX,DWORD PTR SS:[EBP-0xC]
013BDE64   .  64:890D 00000>MOV DWORD PTR FS:[0],ECX
013BDE6B   .  59            POP ECX                           ;  0584FD48
013BDE6C   .  5F            POP EDI                           ;  0584FD48
013BDE6D   .  5E            POP ESI                           ;  0584FD48
013BDE6E   .  5B            POP EBX                           ;  0584FD48
013BDE6F   .  8BE5          MOV ESP,EBP
013BDE71   .  5D            POP EBP                           ;  0584FD48
013BDE72   .  C2 0800       RETN 0x8

上述代码中,将返回值低八位和key[ n ]进行比较,每次比较完后右移八位,再次比较新数值的低八位。总共比较4次,正好将32位返回值全部比对完。

在第三步分析0x9C分支中已经得到 [EDI+0x1C] = ecx = (key[0]^key[6]^0x18+0x3D)^0xA7,

局部变量 [ EBP+0x8 ] = 9。

局部变量[ EBP - 0x10] 为第三步中分析AC分支返回eax得到,

 eax = ((((key[1]^key[7]) * 0x100 + key[2]^key[5])^0x7892 + 0x4D30)^0x3421)/0xB;

局部变量 [ EBP+0xC ] = 4389。

转换为C代码为

//将返回值看成为一个数组,nArray[4]
if((nArray[0]==key[4]) &&
   (nArray[1]==key[5]) &&
   (nArray[2]==key[6]) &&
   (nArray[3]==key[7]))
   {
   if(key[3]==0x9C)
   {
            //[EDI+0x1C] = (key[0]^key[6]^0x18+0x3D)^0xA7;
   if(9 <= (key[0]^key[6]^0x18+0x3D)^0xA7))
   {
   return 0x2D;   //验证成功
   }
   return 0x4E;   //验证失败
   }
   else if(key[3]==0xFC)
   {
    return 0xE7;  //验证失败
   }
   else if(key[3]=0xAC)
   {
   if([ebp - 10] >= 4389) 
   {
   return 0x2D;   //验证成功
   }
   return 0x4E;   //验证失败
   }
   }

第六步 编写注册机

猜你喜欢

转载自blog.csdn.net/yusakul/article/details/81203564
今日推荐