• BUUCTF--刮开有奖


    文件链接:https://buuoj.cn/files/abe6e2152471e1e1cbd9e5c0cae95d29/8f80610b-8701-4c7f-ad60-63861a558a5b.exe?token=eyJ0ZWFtX2lkIjpudWxsLCJ1c2VyX2lkIjoxOTAzLCJmaWxlX2lkIjoyMDd9.XXT5Dg.7mQMViMZzaEYSVj_dfXyRr4aPKQ

    准备

    获取信息

    1. 32位文件

    IDA打开

    进入主函数WinMain

    int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
      DialogBoxParamA(hInstance, (LPCSTR)0x67, 0, DialogFunc, 0);
      return 0;
    }

    找到关键的函数DialogFunc,并反编译为C代码

     1 BOOL __userpurge DialogFunc@<eax>(int a1@<edi>, int a2@<esi>, HWND hDlg, UINT a4, WPARAM a5, LPARAM a6)
     2 {
     3   const char *v6; // esi
     4   const char *v7; // edi
     5   int v9; // [esp+4h] [ebp-20030h]
     6   int v10; // [esp+8h] [ebp-2002Ch]
     7   int v11; // [esp+Ch] [ebp-20028h]
     8   int v12; // [esp+10h] [ebp-20024h]
     9   int v13; // [esp+14h] [ebp-20020h]
    10   int v14; // [esp+18h] [ebp-2001Ch]
    11   int v15; // [esp+1Ch] [ebp-20018h]
    12   int v16; // [esp+20h] [ebp-20014h]
    13   int v17; // [esp+24h] [ebp-20010h]
    14   int v18; // [esp+28h] [ebp-2000Ch]
    15   int v19; // [esp+2Ch] [ebp-20008h]
    16   CHAR String; // [esp+30h] [ebp-20004h]
    17   char v21; // [esp+31h] [ebp-20003h]
    18   char v22; // [esp+32h] [ebp-20002h]
    19   char v23; // [esp+33h] [ebp-20001h]
    20   char v24; // [esp+34h] [ebp-20000h]
    21   char v25; // [esp+10030h] [ebp-10004h]
    22   char v26; // [esp+10031h] [ebp-10003h]
    23   char v27; // [esp+10032h] [ebp-10002h]
    24   int v28; // [esp+20028h] [ebp-Ch]
    25   int v29; // [esp+2002Ch] [ebp-8h]
    26 
    27   __alloca_probe();
    28   if ( a4 == 272 )
    29     return 1;
    30   v29 = a2;
    31   v28 = a1;
    32   if ( a4 != 273 )
    33     return 0;
    34   if ( (_WORD)a5 == 1001 )
    35   {
    36     memset(&String, 0, 0xFFFFu);
    37     GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
    38     if ( strlen(&String) == 8 )
    39     {
    40       v9 = 90;
    41       v10 = 74;
    42       v11 = 83;
    43       v12 = 69;
    44       v13 = 67;
    45       v14 = 97;
    46       v15 = 78;
    47       v16 = 72;
    48       v17 = 51;
    49       v18 = 110;
    50       v19 = 103;
    51       sub_4010F0(&v9, 0, 10);
    52       memset(&v25, 0, 0xFFFFu);
    53       v6 = (const char *)sub_401000(&v25, strlen(&v25));
    54       memset(&v25, 0, 0xFFFFu);
    55       v26 = v23;
    56       v25 = v22;
    57       v27 = v24;
    58       v7 = (const char *)sub_401000(&v25, strlen(&v25));
    59       if ( String == v9 + 34
    60         && v21 == v13
    61         && 4 * v22 - 141 == 3 * v11
    62         && v23 / 4 == 2 * (v16 / 9)
    63         && !strcmp(v6, "ak1w")
    64         && !strcmp(v7, "V1Ax") )
    65       {
    66         MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
    67       }
    68     }
    69     return 0;
    70   }
    71   if ( (_WORD)a5 != 1 && (_WORD)a5 != 2 )
    72     return 0;
    73   EndDialog(hDlg, (unsigned __int16)a5);
    74   return 1;
    75 }

    代码分析

    字符串解析

    通过第37行代码GetDlgItemTextA,我们知道了String是我们输入的flag。

    通过第38行代码我们知道flag的长度应该是8

    第51行函数sub_4010F0在对v9~v19进行某种操作,进入sub_4010F0函数,将函数转换为C语言代码,再将v9~v19代入

    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    
    using namespace std;
    
    int __cdecl sub_4010F0(char *a1, int a2, int a3)
    {
        int result; // eax
        int i; // esi
        int v5; // ecx
        int v6; // edx
    
        result = a3;
        for (i = a2; i <= a3; a2 = i)
        {
            v5 = i;
            v6 = a1[i];
            if (a2 < result && i < result)
            {
                do
                {
                    if (v6 >a1[result])
                    {
                        if (i >= result)
                            break;
                        ++i;
                        a1[v5] = a1[result];
                        if (i >= result)
                            break;
                        while (a1[i] <= v6)
                        {
                            if (++i >= result)
                                goto LABEL_13;
                        }
                        if (i >= result)
                            break;
                        v5 = i;
                        a1[result] = a1[i];
                    }
                    --result;
                } while (i < result);
            }
        LABEL_13:
            a1[result] = v6;
            sub_4010F0(a1, a2, i - 1);
            result = a3;
            ++i;
        }
        return result;
    }
    
    char str[20] = { 90,74,83,69,67,97,78,72,51,110,103 };
    
    int main()
    {
        cout << str << endl;
    
        sub_4010F0(str, 0, 10);
    
        for (int i = 0; i < 11; ++i) {
            cout << str[i];
        }
        return 0;
    }

    输出

    字符串加密

    分析第52行代码~58行代码。我们转到汇编代码处

    .text:004012B0                 push    0FFFFh          ; size_t
    .text:004012B5                 lea     edx, [ebp+var_10004]
    .text:004012BB                 push    0               ; int
    .text:004012BD                 push    edx             ; void *
    .text:004012BE                 call    _memset
    .text:004012C3                 mov     al, [ebp+var_1FFFF]
    .text:004012C9                 mov     dl, [ebp+var_1FFFD]
    .text:004012CF                 mov     cl, [ebp+var_1FFFE]
    .text:004012D5                 mov     [ebp+var_10004], al
    .text:004012DB                 lea     eax, [ebp+var_10004]
    .text:004012E1                 mov     [ebp+var_10002], dl
    .text:004012E7                 add     esp, 18h
    .text:004012EA                 mov     [ebp+var_10003], cl
    .text:004012F0                 lea     edx, [eax+1]
    .text:004012F3
    .text:004012F3 loc_4012F3:                             ; CODE XREF: DialogFunc+158↓j
    .text:004012F3                 mov     cl, [eax]
    .text:004012F5                 inc     eax
    .text:004012F6                 test    cl, cl
    .text:004012F8                 jnz     short loc_4012F3
    .text:004012FA                 sub     eax, edx
    .text:004012FC                 push    eax
    .text:004012FD                 lea     eax, [ebp+var_10004]
    .text:00401303                 push    eax
    .text:00401304                 call    sub_401000
    .text:00401309                 push    0FFFFh          ; size_t
    .text:0040130E                 lea     ecx, [ebp+var_10004]
    .text:00401314                 push    0               ; int
    .text:00401316                 push    ecx             ; void *
    .text:00401317                 mov     esi, eax
    .text:00401319                 call    _memset
    .text:0040131E                 mov     al, [ebp+var_20001]
    .text:00401324                 mov     dl, [ebp+var_20002]
    .text:0040132A                 mov     cl, [ebp+var_20000]
    .text:00401330                 mov     [ebp+var_10003], al
    .text:00401336                 lea     eax, [ebp+var_10004]
    .text:0040133C                 mov     [ebp+var_10004], dl
    .text:00401342                 add     esp, 14h
    .text:00401345                 mov     [ebp+var_10002], cl
    .text:0040134B                 lea     edx, [eax+1]
    .text:0040134E                 mov     edi, edi

    看加粗加红处(下面是对应字符串的信息)

    -00020004 String          db ?
    -00020003 var_20003       db ?
    -00020002 var_20002       db ?
    -00020001 var_20001       db ?
    -00020000 var_20000       db ?
    -0001FFFF var_1FFFF       db ?
    -0001FFFE var_1FFFE       db ?
    -0001FFFD var_1FFFD       db ?

    我们可以知道,v6使用sub_4010F0函数后的字符串的6,7,8位,调用sub_401000函数,v7使用sub_4010F0函数后的字符串的3,4,5位,调用sub_401000函数。

    加密方式

    进入sub_401000

     1 _BYTE *__cdecl sub_401000(int a1, int a2)
     2 {
     3   int v2; // eax
     4   int v3; // esi
     5   size_t v4; // ebx
     6   _BYTE *v5; // eax
     7   _BYTE *v6; // edi
     8   int v7; // eax
     9   _BYTE *v8; // ebx
    10   int v9; // edi
    11   signed int v10; // edx
    12   int v11; // edi
    13   signed int v12; // eax
    14   signed int v13; // esi
    15   _BYTE *result; // eax
    16   _BYTE *v15; // [esp+Ch] [ebp-10h]
    17   _BYTE *v16; // [esp+10h] [ebp-Ch]
    18   int v17; // [esp+14h] [ebp-8h]
    19   int v18; // [esp+18h] [ebp-4h]
    20 
    21   v2 = a2 / 3;
    22   v3 = 0;
    23   if ( a2 % 3 > 0 )
    24     ++v2;
    25   v4 = 4 * v2 + 1;
    26   v5 = malloc(v4);
    27   v6 = v5;
    28   v15 = v5;
    29   if ( !v5 )
    30     exit(0);
    31   memset(v5, 0, v4);
    32   v7 = a2;
    33   v8 = v6;
    34   v16 = v6;
    35   if ( a2 > 0 )
    36   {
    37     while ( 1 )
    38     {
    39       v9 = 0;
    40       v10 = 0;
    41       v18 = 0;
    42       do
    43       {
    44         if ( v3 >= v7 )
    45           break;
    46         ++v10;
    47         v9 = *(unsigned __int8 *)(v3++ + a1) | (v9 << 8);
    48       }
    49       while ( v10 < 3 );
    50       v11 = v9 << 8 * (3 - v10);
    51       v12 = 0;
    52       v17 = v3;
    53       v13 = 18;
    54       do
    55       {
    56         if ( v10 >= v12 )
    57         {
    58           *((_BYTE *)&v18 + v12) = (v11 >> v13) & 0x3F;
    59           v8 = v16;
    60         }
    61         else
    62         {
    63           *((_BYTE *)&v18 + v12) = 64;
    64         }
    65         *v8++ = byte_407830[*((char *)&v18 + v12)];
    66         v13 -= 6;
    67         ++v12;
    68         v16 = v8;
    69       }
    70       while ( v13 > -6 );
    71       v3 = v17;
    72       if ( v17 >= a2 )
    73         break;
    74       v7 = a2;
    75     }
    76     v6 = v15;
    77   }
    78   result = v6;
    79   *v8 = 0;
    80   return result;
    81 }

    进入第65行byte_407830

    .rdata:00407830 ; char byte_407830[]
    .rdata:00407830 byte_407830     db 41h                  ; DATA XREF: sub_401000+C0↑r
    .rdata:00407831 aBcdefghijklmno db 'BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',0

    我们可以猜测这个函数应该是base64加密。

    flag分析

          if ( String == v9 + 34                    // sub_4010F0函数后的第一位等于51+34=85-->'U'
            && v21 == v13                           // 第2位,等于v13,即sub_4010F0函数返回值的第5位值-->'J'
            && 4 * v22 - 141 == 3 * v11
            && v23 / 4 == 2 * (v16 / 9)
            && !strcmp(v6, "ak1w")                  // 第6,7,8行代码base64之后,需要等于"ak1w"
            && !strcmp(                             // 第3,4,5行代码,加密之后等于V1Ax
                  v7,
                  "V1Ax") )
          {
            MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
          }

    将v6,v7解密之后得到WP1jMp,再结合第1,2位得到flag

    get flag!

    flag{UJWP1jMp}

  • 相关阅读:
    c# 图像转化成灰度图
    文件操作 流
    GBK UTF8 GB2312 流
    助力奥巴马,拯救大气层
    ASP.NET 缓存技术
    GridView 和 ViewState 来实现条件查寻
    把日期按指定格式输出
    创业灵感淘宝网
    文件_上传_下载
    java23种设计模式与追MM
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11488817.html
Copyright © 2020-2023  润新知