“百度杯”CTF比赛 十一月场--CrackMe01

测试文件:https://static2.ichunqiu.com/icq/resources/fileupload/CTF/BSRC/BSRC-11-3/CrackMe01_97D2BF0DBD2EC13065E7104F24CAAED9.zip

1.准备

获取信息

  • 32位文件

2.IDA打开

熟悉Windows API的话,一般组成的就是MessageBox,ShowWindow...这里测试错误答案时,没有窗口提示,也就排除了MessageBox,而且要处理消息事件的话,直接查找默认消息处理DefWindowProc。

在import里面搜索DefWindowProc

点击进入之后,Ctrl+X查找用到的地方

一个一个进入,F5分析就行。(实际上就是第一个)

找到这么一段代码

 1 LRESULT __stdcall sub_4027F0(int a1, UINT Msg, WPARAM wParam, LPARAM lParam)
 2 {
 3   UINT v4; // eax
 4   LPARAM v5; // edx
 5   __int16 v6; // bx
 6   void *v7; // edi
 7   HDC v9; // esi
 8   unsigned int v10; // ecx
 9   __int16 v11; // ax
10   unsigned int v12; // eax
11   int v13; // edi
12   int v14; // eax
13   struct tagRECT v15; // [esp+18h] [ebp-68h]
14   struct tagRECT Rect; // [esp+28h] [ebp-58h]
15   struct tagPAINTSTRUCT Paint; // [esp+38h] [ebp-48h]
16 
17   v4 = Msg;
18   v5 = lParam;
19   v6 = 0;
20   v7 = (void *)wParam;
21   if ( Msg > 0xF )
22   {
23     if ( Msg != 4097 )
24       return DefWindowProcW((HWND)a1, v4, (WPARAM)v7, v5);
25     v10 = 0;
26     do
27     {
28       v11 = *(_WORD *)(wParam + 2 * v10++);
29       v6 += v11;
30     }
31     while ( v10 <= lParam );
32     v12 = 0;
33     do
34     {
35       *(const WCHAR *)((char *)&chText + v12) ^= v6;
36       v12 += 2;
37     }
38     while ( v12 < 0x2C );
39     GetWindowRect((HWND)a1, &v15);
40     v13 = (v15.left - v15.right + GetSystemMetrics(16)) / 2;
41     v14 = GetSystemMetrics(17);
42     SetWindowPos((HWND)a1, HWND_MESSAGE|0x2, v13, (v15.top - v15.bottom + v14) / 2, -1, -1, 5u);
43     SetWindowPos((HWND)a1, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 3u);
44     if ( (v6 & 0xF00) == 0x400 && (v6 & 0xF0) == 0xB0u && (v6 & 6) == 6 )
45     {
46       ShowWindow((HWND)a1, 5);
47       UpdateWindow((HWND)a1);
48     }
49     v7 = (void *)wParam;
50 LABEL_18:
51     if ( v7 )
52       free(v7);
53     v5 = lParam;
54     v4 = Msg;
55     return DefWindowProcW((HWND)a1, v4, (WPARAM)v7, v5);
56   }
57   switch ( Msg )
58   {
59     case 0xFu:
60       v9 = BeginPaint((HWND)a1, &Paint);
61       GetClientRect((HWND)a1, &Rect);
62       DrawTextW(v9, &chText, -1, &Rect, 0x25u);
63       EndPaint((HWND)a1, &Paint);
64       goto LABEL_18;
65     case 1u:
66       return 0;
67     case 2u:
68       PostQuitMessage(0);
69       return 0;
70   }
71   return DefWindowProcW((HWND)a1, v4, (WPARAM)v7, v5);
72 }

3.代码分析

去除掉代码中对窗口消息,创建,我们需要的代码就是

    do
    {
      *(const WCHAR *)((char *)&chText + v12) ^= v6;
      v12 += 2;
    }
    while ( v12 < 0x2C );

这里实际上就是对chText的前0x2c个进行了异或处理,代码中两个字节为一组,总共22组。

chText

F0 04 DA 04 D7 04 D1 04  8C 04 FF 04 F5 04 FE 04 
E3 04 F8 04 E7 04 FF 04  E3 04 E9 04 F0 04 F3 04 
85 04 80 04 84 04 F2 04  F4 04 F3 04

因此chText为

chText[]={0x4F0, 0x4DA, 0x4D7, 0x4D1, 0x48C, 0x4FF, 0x4F5, 0x4FE,  0x4E3, 0x4F8, 0x4E7, 0x4FF, 0x4E3,  0x4E9, 0x4F0, 0x4F3, 0x485, 0x480, 0x484, 0x4F2, 0x4F4, 0x4F3}

v6的值我们可以通过第44行代码

if ( (v6 & 0xF00) == 0x400 && (v6 & 0xF0) == 0xB0u && (v6 & 6) == 6 )
{
  ShowWindow((HWND)a1, 5);
  UpdateWindow((HWND)a1);
}

得到v6=0x4b6

4.脚本获取

chText = [0x4F0, 0x4DA, 0x4D7, 0x4D1, 0x48C, 0x4FF, 0x4F5, 0x4FE, 0x4E3, 0x4F8, 0x4E7, 0x4FF, 0x4E3, 0x4E9, 0x4F0,
          0x4F3, 0x485, 0x480, 0x484, 0x4F2, 0x4F4, 0x4F3]
flag = ''

for i in range(22):
    chText[i] ^= 0x4b6
    flag += chr(chText[i])

print(flag)

5.get flag!

Flag:ICHUNQIU_FE362DBE

原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11704483.html