前言

题目来源于2025年LACTF的归档

IDA插件推荐:https://github.com/L4ys/LazyIDA

解题过程

题目其实还是比较简单的:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
int __fastcall main(int argc, const char **argv, const char **envp)
{
size_t v3; // 输入字符串长度
size_t v4; // 长度的一半
size_t v5; // 循环计数器
int v6; // strcmp 返回值

char v8[256]; // 重排后的字符串(“悖论化”结果)
char s[264]; // 用户输入的原始字符串

printf("What do you think the flag is? ");
fflush(stdout);

// 读取最多 256 个字符
fgets(s, 256, stdin);

// 找到换行符位置
v3 = strcspn(s, "\n");

// 把换行符替换为字符串结束符 '\0'
s[v3] = 0;

// ----------- 长度检查 -----------
if ( strlen(target) == v3 ) // 必须和 target 一样长(36)
{
v4 = v3 >> 1; // v4 = v3 / 2 = 18

// ----------- 关键“交织变换” -----------
if ( v3 > 1 )
{
v5 = 0; // i = 0

do
{
// v8 的偶数位来自输入前半部分
v8[2 * v5] = s[v5];

// v8 的奇数位来自输入后半部分
v8[2 * v5 + 1] = s[v4 + v5];

++v5;
}
while ( v5 < v4 ); // 循环 18 次
}

// 末尾补上字符串结束符
v8[v3] = 0;

printf("Paradoxified: %s\n", v8);

// ----------- 比较变换后的结果与 target -----------
v6 = strcmp(target, v8);

if ( v6 ) // 不相等
{
puts("You got the flag wrong >:(");
return 0;
}
else // 相等
{
puts("That's the flag! :D");
}
}
else // 长度不对
{
puts("Bad length >:(");
return 1;
}

return v6; // 返回 strcmp 结果
}

结果就是程序把输入拆成两半,然后一前一后交叉重排,要求重排后的结果等于 target

等价流程是:

1
2
3
4
5
输入 s = [前18字符][后18字符]

v8 = s[0], s[18], s[1], s[19], ..., s[17], s[35]

要求:v8 == target

要拿到 flag,只需要把这个交织过程倒过来

  • target 的偶数位 → flag 前半
  • target 的奇数位 → flag 后半

target值为

1
target = [0x6C, 0x5F, 0x61, 0x6C, 0x63, 0x6F, 0x74, 0x73, 0x66, 0x74, 0x7B, 0x5F, 0x74, 0x69, 0x68, 0x6E, 0x65, 0x5F, 0x5F, 0x69, 0x66, 0x6E, 0x6C, 0x66, 0x61, 0x69, 0x67, 0x6E, 0x5F, 0x69, 0x67, 0x74, 0x6F, 0x79, 0x74, 0x7D, 0x00]
1
2
3
4
5
6
7
8
9
10
11
12
13
target = [0x6C, 0x5F, 0x61, 0x6C, 0x63, 0x6F, 0x74, 0x73, 0x66, 0x74, 0x7B, 0x5F, 0x74, 0x69, 0x68, 0x6E, 0x65, 0x5F, 0x5F, 0x69, 0x66, 0x6E, 0x6C, 0x66, 0x61, 0x69, 0x67, 0x6E, 0x5F, 0x69, 0x67, 0x74, 0x6F, 0x79, 0x74, 0x7D, 0x00]

# 转成字符串
target = "".join(chr(b) for b in target_bytes)

# 反交织
first_half = target[::2]
second_half = target[1::2]

flag = first_half + second_half

print(flag)