阿虚
Hello World!
Hello World!
亦步亦趋

0x0 环境

——————–

环境:

系统:Windows 10

工具:IDA 7.X

——————–

0x1 跑起来

       这个CM和前面几个不一样,打开UI还会放音乐,就像是玩小霸王(红白机)那种游戏带的背景音乐。听起来还是蛮带感的。

       输入密码后弹出错误提示“Nope, thats not it!”

http://www.xuwu.org/wp-content/uploads/2020/02/ybyq1.png

0x2 IDA分析

       只有一处引用字符串可以很快定位到关键函数

http://www.xuwu.org/wp-content/uploads/2020/02/ybyq2-1024x243.png

       函数从流程图来看挺大的F5以下看下函数大致流程。

INT_PTR __stdcall DialogFunc(HWND hWnd, UINT a2, WPARAM a3, LPARAM a4)
{ 
  switch ( a2 )
  {
    case 0x110u:
	  .....
      break;
    case 0x111u:
      ......
          lstrcpyA(String1, String2);
          GetDlgItemTextA(hWnd, 100, byte_406949, 512);
          if ( lstrcmpA(byte_406949, String1) )
            MessageBoxA(hWnd, aNopeThatsNotIt, Caption, 0x10u);
          else
            MessageBoxA(hWnd, aYepThatsTheRig, aGoodBoy, 0x40u);
        ...... 
      break;
    case 0x10u:  
      break;
  }
  return 0;
}

       能看出直接定位是在DLG的窗口消息回调当中,作者并没有做什么隐藏和加壳。

0x3 分析解码逻辑

.text:00401163 loc_401163:                             ; CODE XREF: DialogFunc+95↑j
.text:00401163                 lea     edx, g_name
.text:00401169                 push    edx             ; lpString
.text:0040116A                 call    lstrlenA
.text:0040116F                 mov     ebp, eax        ; name_length;
.text:00401171                 mov     ecx, 5
.text:00401176                 xor     esi, esi        ; index;
.text:00401178                 xor     eax, eax        ; j = 0; 
.text:0040117A do_while:                               ; CODE XREF: DialogFunc+E5↓j
.text:0040117A                 mov     cl, [esi+edx]   ; cl = g_name_buf[i];
.text:0040117D                 mov     bl, cl
.text:0040117F                 xor     bl, (g_key1+1)[eax]
.text:00401185                 inc     eax
.text:00401186                 cmp     eax, 5
.text:00401189                 mov     [edx+esi], bl   ; g_name_buf[i] ^= g_key1[i];
.text:0040118C                 mov     g_key1[eax], cl ; g_key1[j] = cl;
.text:00401192                 jnz     short loc_401196 ; if (j == 5)
.text:00401194                 xor     eax, eax        ;     j = 0; 
.text:00401196 loc_401196:                             ; CODE XREF: DialogFunc+DE↑j
.text:00401196                 inc     esi
.text:00401197                 cmp     esi, ebp        ; index < name_length;
.text:00401199                 jb      short do_while  ;
.text:00401199                                         ; ;
.text:0040119B                 xor     edi, edi        ; edi = j;
.text:0040119D                 xor     ecx, ecx        ; ecx = index;
.text:0040119F                 test    ebp, ebp        ; ebp = name_length;
.text:004011A1                 jbe     short do_while_2_end ; for () 
.text:004011A3 do_while_2:                             ; CODE XREF: DialogFunc+113↓j
.text:004011A3                 mov     bl, (g_key1+6)[edi]
.text:004011A9                 mov     esi, ebp        ; ebp = name_length;
.text:004011AB                 sub     esi, ecx
.text:004011AD                 dec     esi             ; t = name_length - index - 1;
.text:004011AE                 mov     al, [edx+esi]   ; tt = g_name_buf[t];
.text:004011B1                 xor     bl, al
.text:004011B3                 inc     edi             ; j++;
.text:004011B4                 mov     [edx+esi], bl   ; g_name_buf[t] ^= g_key1[5 + j];
.text:004011B7                 mov     (g_key1+5)[edi], al ; g_key[4 + j] = tt; 
.text:004011BD                 cmp     edi, 5
.text:004011C0                 jnz     short loc_4011C4 ; if (j == 5)
.text:004011C2                 xor     edi, edi        ;     j = 0; 
.text:004011C4 loc_4011C4:                             ; CODE XREF: DialogFunc+10C↑j
.text:004011C4                 inc     ecx             ; index++;
.text:004011C5                 cmp     ecx, ebp        ; index < name_length;
.text:004011C7                 jb      short do_while_2 
.text:004011C9 do_while_2_end:                         ; CODE XREF: DialogFunc+ED↑j
.text:004011C9                 xor     esi, esi        ; esi = j;
.text:004011CB                 xor     edi, edi        ; edi = index;
.text:004011CD                 test    ebp, ebp        ; ebp = name_length;
.text:004011CF                 jbe     short do_while3_end ; edi = j; 
.text:004011D1 do_while3:                              ; CODE XREF: DialogFunc+13C↓j
.text:004011D1                 mov     al, [edx+edi]   ; t1 = g_name_buf[index];
.text:004011D4                 mov     cl, (g_key1+0Bh)[esi]
.text:004011DA                 xor     cl, al          ; t = t1 ^ g_key2[1 + j];
.text:004011DC                 inc     esi             ; j++;
.text:004011DD                 mov     [edx+edi], cl   ; g_name_buf[index] = t;
.text:004011E0                 mov     (g_key1+0Ah)[esi], al ; g_key2[j] = t1;
.text:004011E6                 cmp     esi, 5
.text:004011E9                 jnz     short loc_4011ED ; if (j == 5)
.text:004011EB                 xor     esi, esi        ;     j = 0; 
.text:004011ED loc_4011ED:                             ; CODE XREF: DialogFunc+135↑j
.text:004011ED                 inc     edi             ; index++;
.text:004011EE                 cmp     edi, ebp        ; index < name_length;
.text:004011F0                 jb      short do_while3 ; t1 = g_name_buf[index]; 
.text:004011F2 do_while3_end:                          ; CODE XREF: DialogFunc+11B↑j
.text:004011F2                 xor     edi, edi        ; edi = j;
.text:004011F4                 xor     ecx, ecx        ; ecx = index;
.text:004011F6                 test    ebp, ebp        ; ebp = name_length;
.text:004011F8                 jbe     short do_while4_end 
.text:004011FA do_while4:                              ; CODE XREF: DialogFunc+16A↓j
.text:004011FA                 mov     bl, (g_key1+10h)[edi] ; t = g_key2[6 + j];
.text:00401200                 mov     esi, ebp
.text:00401202                 sub     esi, ecx
.text:00401204                 dec     esi             ; t1 = name_length - index - 1;
.text:00401205                 mov     al, [edx+esi]   ; t2 = g_name_buf[t1];
.text:00401208                 xor     bl, al
.text:0040120A                 inc     edi             ; j++;
.text:0040120B                 mov     [edx+esi], bl   ; g_name_buf[t1] = t ^ t2;
.text:0040120E                 mov     (g_key1+0Fh)[edi], al ; g_key2[5 + j ] = t2;
.text:00401214                 cmp     edi, 5
.text:00401217                 jnz     short loc_40121B ; if (j == 5)
.text:00401219                 xor     edi, edi        ;      j = 0; 
.text:0040121B loc_40121B:                             ; CODE XREF: DialogFunc+163↑j
.text:0040121B                 inc     ecx             ; index++;
.text:0040121C                 cmp     ecx, ebp
.text:0040121E                 jb      short do_while4 ; t = g_key2[6 + j]; 
.text:00401220 do_while4_end:                          ; CODE XREF: DialogFunc+144↑j
.text:00401220                 lea     edi, g_undef1
.text:00401226                 xor     eax, eax        ; eax = index;
.text:00401228                 test    ebp, ebp
.text:0040122A                 mov     dword ptr g_undef1, 0
.text:00401234                 jbe     short do_while5_end
.text:00401236
.text:00401236 do_while5:                              ; CODE XREF: DialogFunc+197↓j
.text:00401236                 mov     ecx, eax
.text:00401238                 and     ecx, 3
.text:0040123B                 mov     bl, [edi+ecx]   ; t = g_undef1[index &amp; 3];
.text:0040123E                 lea     esi, [edi+ecx]
.text:00401241                 mov     cl, [edx+eax]   ; t1 = g_name_buf[index + index]
.text:00401244                 add     bl, cl
.text:00401246                 inc     eax             ; index++;
.text:00401247                 cmp     eax, ebp
.text:00401249                 mov     [esi], bl       ; g_undef1[index &amp; 3] = t + t1;
.text:0040124B                 jb      short do_while5 
.text:0040124D do_while5_end:                          ; CODE XREF: DialogFunc+180↑j
.text:0040124D                 pop     ebp
.text:0040124E                 mov     ecx, 0Ah
.text:00401253                 mov     eax, dword ptr g_undef1
.text:00401258                 xor     ebx, ebx 
.text:0040125A do_while6:                              ; CODE XREF: DialogFunc+1B6↓j
.text:0040125A                 xor     edx, edx
.text:0040125C                 div     ecx
.text:0040125E                 add     dl, 30h ; '0'
.text:00401261                 mov     (g_string+1)[ebx], dl ; String1[index] = (DWORD)g_undef1 / 10 + 0x30
.text:00401267                 inc     ebx             ; index++;
.text:00401268                 test    eax, eax
.text:0040126A                 jnz     short do_while6 ;          ; ;
.text:0040126C                 push    (offset g_string+1) ; lpString
.text:00401271                 call    lstrlenA
.text:00401276                 xor     ebx, ebx 
.text:00401278 do_while7:                              ; CODE XREF: DialogFunc+1D2↓j
.text:00401278                 mov     cl, g_string[eax]
.text:0040127E                 mov     String2[ebx], cl
.text:00401284                 inc     ebx
.text:00401285                 dec     eax
.text:00401286                 jnz     short do_while7 ;    ; ;
.text:00401288                 push    offset String2  ; lpString2
.text:0040128D                 push    (offset g_string+1) ; lpString1
.text:00401292                 call    lstrcpyA        ;       ; ;
.text:00401297                 push    200h            ; cchMax
.text:0040129C                 push    offset password ; lpString
.text:004012A1                 push    64h ; 'd'       ; nIDDlgItem
.text:004012A3                 push    [ebp+hWnd]      ; hDlg
.text:004012A6                 call    GetDlgItemTextA ;             ; ;
.text:004012AB                 push    (offset g_string+1) ; lpString2
.text:004012B0                 push    offset password ; lpString1
.text:004012B5                 call    lstrcmpA
.text:004012BA                 or      eax, eax
.text:004012BC                 jnz     short check_err ;        ; ;
.text:004012BE                 push    40h ; '@'       ; uType
.text:004012C0                 push    offset aGoodBoy ; "Good boy..."
.text:004012C5                 push    offset aYepThatsTheRig ; "Yep, thats the right code!\n\rGo write "...
.text:004012CA                 push    [ebp+hWnd]      ; hWnd
.text:004012CD                 call    MessageBoxA
.text:004012D2                 jmp     short fun_end

       算法有点长,但是还原后实际上并没有多少。KEY完全是由name计算出来的。里面多少还是有点坑。比如说在使用lstrlenA()计算name的长度时,在函数内部会将char*的buf指针+1。但是我在vs2019使用lstrlenA()字符串buf指针并不会+1。又再者里面有用到一个全局的g_key开始在IDA分析时我是当做2个keybuf来进行编写代码的,但是调试后发现就算定义两个相邻的数组在实际内存中中间或多或少会有多个’0x0’来间隔。也有可能是被IDA自动分析给误导了。

0x4 C语言源码

// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <stdlib.h>
#include <windows.h>
 
BYTE g_key1[22] = { 0x00, 0xAA, 0x89, 0x0C4, 0x0FE, 0x46, 0x78, 0x0F0, 0x0D0, 0x3
,0x0E7, 0x0F7, 0x0FD, 0x0F4, 0x0E7, 0x0B9, 0x0B5, 0x1B, 0x0C9, 0x50, 0x73, 0x0 };

bool check(char* user, char* password)
{
    int user_length = lstrlenA(user);
    if (user_length < 3)
    {
        return false;
    }

    user = user + 1;
    char g_old_name[256] = { 0x0 };
    for (int i = 0, j = 0; i < user_length; i++)
    {
        char t = user[i];
        char tt = t ^ g_key1[j+1];
        j++;
        user[i] = tt;
        g_key1[j] = t;
        if (j == 5)
        {
            j = 0;
        }
    }

    for (int i = 0, j = 0; i < user_length; i++)
    {
        char t = g_key1[6 + j];
        char tt = user[user_length - i - 1];
        char ttt = user[user_length - i - 1];
        user[user_length - i - 1] = tt ^ t;
        j++;
        g_key1[5 + j] = ttt;

        if (j == 5)
        {
            j = 0;
        }
    }

    for (int i = 0, j = 0; i < user_length; i++)
    {
        char t = user[i];
        char tt = g_key1[j + 0xB];
        char ttt = tt ^ t;
        j++;
        user[i] = ttt;
        g_key1[0xA + j] = t;
        if (j == 5)
        {
            j = 0;
        }
    }

    for (int i = 0, j = 0; i < user_length; i++)
    {
        char t = g_key1[j + 0x10];
        char tt = user[user_length - i - 1];
        char ttt = t ^ tt;
        j++;
        user[user_length - i - 1] = ttt;
        g_key1[j + 0xF] = tt;
        if (j == 5)
        {
            j = 0;
        }
    }

    BYTE g_undef1[4] = { 0x0 };
    for (int i = 0; i < user_length; i++)
    {
        int j = i &amp; 3;
        char t = g_undef1[j];
        char tt = user[i] + t;
        g_undef1[j] = tt;
    }


    char String1[512] = { 0x0 };
    int i = 0;
    int s = 0;
    int y = 0;
    do 
    {
        int p = *(int*)g_undef1;
        s = p / 10;
        y = p % 10;
        *(int*)g_undef1 = s;
        String1[i+1] = (y + 0x30); 
        i++;
    } while (s != 0);

    int s1 = strlen(String1 + 1);
    char String2[512] = { 0x0 };
    i = 0;
    for (s1; s1 != 0; s1--)
    {
        String2[i++] = String1[s1];
    }

    strcpy(String1 + 1, String2);

    if (strcmp(String1 + 1, password) != 0)
    {
        return false;
    }

    return true;
}
  
int main()
{
    char name[256] = "CTFHUB";
    //char password[256] = { 0x0 };
    char password[256] = "111111111111";

    //reg(name, password);

    if (check(name, password))
    {
        std::cout << "ok \n";
    }

    return 0;
}

阿虚

文章作者

发表评论

textsms
account_circle
email

Hello World!

亦步亦趋
0x0 环境 -------------------- 环境: 系统:Windows 10 工具:IDA 7.X -------------------- 0x1 跑起来        这个CM和前面几个不一样,打开UI还会放音乐,就像…
扫描二维码继续阅读
2020-02-26