[ACTF新生赛2020]easyre

UPX壳, 先脱壳image-20220123231753142

这次采用堆栈平衡法(esp定律法)来寻找popad, 从而找到程序的真正的入口. 也可以采用直接找popad的方法, UPX一般可以这么干, 见 [BUUCTF]新年快乐

程序的入口点是一个pushad, F8让它执行, 改变esp, 对esp下硬件断点

image-20220123232551388

然后让程序跑起来, 被硬件断点断下, 可以看到刚好断在popad之后.

一般对于UPX来说popad之后的第一个jmp就是跳到程序真正的入口点, 这里是0x401280

image-20220123232745208

然后用Scylla插件脱壳, 用法见 [BUUCTF]新年快乐

脱壳完了拖进IDA, F5查看伪代码

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
_BYTE v4[12]; // [esp+12h] [ebp-2Eh] BYREF
_DWORD v5[3]; // [esp+1Eh] [ebp-22h]
_BYTE v6[5]; // [esp+2Ah] [ebp-16h] BYREF
int v7; // [esp+2Fh] [ebp-11h]
int v8; // [esp+33h] [ebp-Dh]
int v9; // [esp+37h] [ebp-9h]
char v10; // [esp+3Bh] [ebp-5h]
int i; // [esp+3Ch] [ebp-4h]

sub_401A10();
qmemcpy(v4, "*F'\"N,\"(I?+@", sizeof(v4));
printf("Please input:");
scanf("%s", v6); //利用scanf()的溢出去修改v7~v10
if ( v6[0] != 'A' || v6[1] != 'C' || v6[2] != 'T' || v6[3] != 'F' || v6[4] != '{' || v10 != '}' )
//判断输入格式符不符合ACTF{...}
return 0;
v5[0] = v7;
v5[1] = v8;
v5[2] = v9;
for ( i = 0; i <= 11; ++i )
{
if ( v4[i] != byte_402000[*((char *)v5 + i) - 1] )
//逐个字节对比, 可以通过在码表中逐位穷举来逆推出v5的每一个字节
return 0;
}
printf("You are correct!");
return 0;
}

取得v5的代码如下

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
#include <cstdio>

using namespace std;

int main()
{
char v4[] = "*F'\"N,\"(I?+@";
char v5[16] = { 0 };
unsigned char byte_402000[] =
{
126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
116, 115, 114, 113, 112, 111, 110, 109, 108, 107,
106, 105, 104, 103, 102, 101, 100, 99, 98, 97,
96, 95, 94, 93, 92, 91, 90, 89, 88, 87,
86, 85, 84, 83, 82, 81, 80, 79, 78, 77,
76, 75, 74, 73, 72, 71, 70, 69, 68, 67,
66, 65, 64, 63, 62, 61, 60, 59, 58, 57,
56, 55, 54, 53, 52, 51, 50, 49, 48, 47,
46, 45, 44, 43, 42, 41, 40, 39, 38, 37,
36, 35, 32, 33, 34, 0
};
for (int i = 0; i <= 11; ++i)
for (int j = 0; j < sizeof(byte_402000); j++)
//设v5[i]-1=j, 穷举出j的值
if (v4[i] == byte_402000[j])
v5[i] = j + 1;
printf("%s", v5);
}
//U9X_1S_W6@T?

我们就得出ACTF{U9X_1S_W6@T?}, 验证一下

image-20220124004429711

没问题, 所以flag就是flag{U9X_1S_W6@T?}