逆向攻防世界CTF系列27-200simple-check-100

巨难受的一题,gdb环境配了半天

32位无壳

image-20241111204514578

这里要check,先跟进下面的interesting_function看看

image-20241111204605642

putchar,这里就是输出,那我们只需要动调将check_key那修改为正确就行

image-20241111204712189

下断点

image-20241111204747074

右上角右键modify成1

image-20241111204856485

但是输出乱码。

查阅资料后可以用gbd动调

环境配了半天

如果是2024-11-11左右安装gbd如果出现报错,可以参考[Kali 2024 逆向调试 GDB 13.2 安装插件 Peda 不兼容报错解决方案_kali安装gdb-CSDN博客](https://blog.csdn.net/qq_51886509/article/details/141227182?ops_request_misc=%7B%22request%5Fid%22%3A%22984C9D72-904C-4F18-B580-8A359D6C46D7%22%2C%22scm%22%3A%2220140713.130102334.pc%5Fall.%22%7D&request_id=984C9D72-904C-4F18-B580-8A359D6C46D7&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~times_rank-2-141227182-null-null.142^v100^pc_search_result_base4&utm_term=no module named six gdb&spm=1018.2226.3001.4187)

开始

gbd

file task9_x86_64_46d01fe312d35ecf69c4ff8ab8ace75d080891dc

设置断点在main函数入口处

b main

开始运行

r

到这里继续单步执行,一直到test eax,eax那

n

查看eax寄存器值

i r eax

修改eax寄存器值

set $eax=1

image-20241111205118089

修改就行

直接运行至程序结束

c

flag:

flag_is_you_know_cracking!!!

到这,其实还有解法,那就是纯静态分析,来自攻防世界的wp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unsigned int *__cdecl interesting_function(int *a1)
{
unsigned int *result; // eax
unsigned int v2; // [esp+1Ch] [ebp-1Ch] BYREF
unsigned int *v3; // [esp+20h] [ebp-18h]
int *v4; // [esp+24h] [ebp-14h]
int j; // [esp+28h] [ebp-10h]
int i; // [esp+2Ch] [ebp-Ch]

result = (unsigned int *)a1;
v4 = a1;
for ( i = 0; i <= 6; ++i )
{
v2 = v4[i] ^ 0xDEADBEEF;
result = &v2;
v3 = &v2;
for ( j = 3; j >= 0; --j )
result = (unsigned int *)putchar((char)(*((_BYTE *)v3 + j) ^ flag_data[4 * i + j]));
}
return result;
}

这里无非是对flag做处理,enc来自flag_data,都可以获取,要点耐心还是可以解密的

我们不用管check_key,它的作用只是验证,我们目的是输出flag

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
#include <stdio.h>

unsigned char flag_data[] = {
220, 23, 191, 91, 212, 10, 210, 27, 125, 218,
167, 149, 181, 50, 16, 246, 28, 101, 83, 83,
103, 186, 234, 110, 120, 34, 114, 211 };
char v7[] = {
84, -56, 126, -29, 100, -57, 22, -102, -51, 17,
101, 50, 45, -29, -45, 67, -110, -87, -99, -46,
-26, 109, 44, -45, -74, -67, -2, 106 };

unsigned int v2;
unsigned char* v3;

int main() {
for (int i = 0; i <= 6; ++i) {
v2 = ((v7[4 * i] & 0x000000FF) + ((v7[4 * i + 1] & 0x000000FF) << 8)
+ ((v7[4 * i + 2] & 0x000000FF) << 16) + ((v7[4 * i + 3] & 0x000000FF) <<
24)) ^ 0xDEADBEEF;
v3 = (unsigned char*)&v2;
for (int j = 3; j >= 0; --j) printf("%c", *(v3 + j) ^ flag_data[4 * i + j]);
}
printf("\n");
for (int i = 0; i <= 6; ++i) {
printf("%c", v7[4 * i + 3] ^ 0xDE ^ flag_data[4 * i + 3]);
printf("%c", v7[4 * i + 2] ^ 0xAD ^ flag_data[4 * i + 2]);
printf("%c", v7[4 * i + 1] ^ 0xBE ^ flag_data[4 * i + 1]);
printf("%c", v7[4 * i] ^ 0xEF ^ flag_data[4 * i]);
}
}

解释一下两种解法,第一种是直接模仿源码,第二种其实也是一样不过进一步理解了

第一种先进行处理,原文中的v4[i]其实是4个字节,从循环i<=6也可以猜到,是四个四个处理的

那么第二层循环只是挨个输出而已

第二种方法其实就是直接进行处理,因为是小端字节序,低位在低地址

所以我们看到的v7其实是小端序,我们要给它还原成我们熟知的顺序

for (int j = 3; j >= 0; –j) printf(“%c”, *(v3 + j) ^ flag_data[4 * i + j]);这个其实做的也是逆序

image-20241111211020181