RE—攻防世界—流浪者

看文件图标就知道这和MFC有关,没有加壳和反调试混淆。

MFC

微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是微软公司提供的一个类库(class libraries),以C++类的形式封装了[Windows API](https://baike.baidu.com/item/Windows API/6088382),并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。

其实MFC就是一个对C++语言的封装,用来减小开发人员工作量。

分析

那到手是一个exe文件,试运行一下,就是一个输入密码的题,MFC编写的程序比单纯的控制台程序更难分析。

image-20220405201407424

由于不知道exe的入口函数是什么,我们可以去找到判断密码正确与否的函数,最简单的办法便是字符串的交叉引用。Shift+F12可以查看程序的字符串。

image-20220405201844677

其中pass!在我们输入的时候没有出现。

image-20220405201957872

交叉引用后反编译查看源代码

image-20220405202046464

发现是程序通过会出现的界面。

于是跳转到call了该函数的函数那里:

image-20220405202150060

可以发现该函数对传入的数字加上4*v4然后在一个aAbcdef这个数组里面找到对应的值并赋值给str1,最后比较字符串“KanXueCTF2019JustForhappy”和str1。

所以我们需要找到传入的al是什么,继续交叉引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
int __thiscall sub_401890(CWnd *this)
{
CWnd *DlgItem; // eax
int v2; // eax
struct CString *v4; // [esp-4h] [ebp-C4h]
int v5[26]; // [esp+4Ch] [ebp-74h] BYREF
int i; // [esp+B4h] [ebp-Ch]
char *Str; // [esp+B8h] [ebp-8h]
CWnd *v8; // [esp+BCh] [ebp-4h]

v8 = this;
v4 = (CWnd *)((char *)this + 100);
DlgItem = CWnd::GetDlgItem(this, 1002);
CWnd::GetWindowTextA(DlgItem, v4);
v2 = sub_401A30((char *)v8 + 100);
Str = CString::GetBuffer((CWnd *)((char *)v8 + 100), v2);
if ( !strlen(Str) )
return CWnd::MessageBoxA(v8, aPass, 0, 0); // 如果没有任何输入,输出
for ( i = 0; Str[i]; ++i )
{
if ( Str[i] > '9' || Str[i] < '0' ) // 不是数字
{
if ( Str[i] > 'z' || Str[i] < 'a' ) // 不是小写字母
{
if ( Str[i] > 'Z' || Str[i] < 'A' ) // 不是大写字母
sub_4017B0();
else
v5[i] = Str[i] - 29; // 是大写值字母减29
}
else
{
v5[i] = Str[i] - 87; // 是小写字母减87
}
}
else
{
v5[i] = Str[i] - 48; // 是数字减48
}
}
return sub_4017F0((int)v5);
}

于是便可以对上面的程序来反解出flag;

逆算法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
KanXue = "KanXueCTF2019JustForhappy"
abcdef = "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ"
SomeDwordArray = []
Key = ""

for i in range(len(KanXue)):
SomeDwordArray.append(abcdef.find(KanXue[i]))

print("SomeDwordArray =", SomeDwordArray)

for dw in SomeDwordArray:
if dw <= 9 and dw >= 0:
Key += chr(dw + ord('0'))
elif dw + ord('W') >= ord('a') and dw + ord('W') <= ord('z'):
Key += chr(dw + ord('W'))
else:
Key += chr(dw + 0x1D)

print(Key)

解出来的key加上flag{}。