BUUCTF--刮开有奖

匿名 (未验证) 提交于 2019-12-02 23:59:01

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

 

1.准备

获取信息

  1. 32位文件

 

2.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 }

 

3. 代码分析

3.1 字符串解析

通过第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; }

输出

 

3.2 字符串加密

分析第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+158j .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函数。

 

3.3 加密方式

进入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+C0r .rdata:00407831 aBcdefghijklmno db 'BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',0

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

 

3.4 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

 

3.get flag!

flag{UJWP1jMp}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!