-
- 前置知识
- 正文
-
- 一、UPX脱壳
- 二、IDA静态分析
-
- 1、main函数反编译,代码审计
- [2、追踪 check() 函数链](#2、追踪 check() 函数链)
- [三、根据 check() 函数链调用链,编写有效 Flag](#三、根据 check() 函数链调用链,编写有效 Flag)
前置知识
正文
一、UPX脱壳
查过了,无壳。
二、IDA静态分析
1、main函数反编译,代码审计
IDA 进入后,左侧 Functions Window (函数窗口)可以看到所有函数。找到 main 函数并双击,然后按 F5 键反编译。

代码如下:
c
int __fastcall main(int argc, const char **argv, const char **envp)
{
_BYTE v4[48]; // 存储用户输入的 flag
// 打印 ASCII 艺术字(忽略)
puts(" _ _ _ _ _____ _____ _____ ");
// ...(省略 banner)
while ( 1 )
{
puts("Input the flag");
__isoc99_scanf("%s", v4); // 读取用户输入
if ( (unsigned int)check(v4) == 1 ) // 调用 check() 验证
break;
puts("0ops, your flag seems fake.");
rewind(__bss_start);
}
puts("Your flag is correct, go and submit it!");
return 0;
}
逻辑很简单 :用户输入一个字符串 → 调用 check() 验证 → 正确则输出成功信息,错误则继续循环。
关键问题 :check() 函数到底检查了什么条件?
2、追踪 check() 函数链
check() 只有一行代码:
c
__int64 __fastcall check(__int64 a1)
{
return iven_is_handsome(a1); // 调用 iven_is_handsome
}

而 iven_is_handsome 里面又调用了 iven_is_c0ol,iven_is_c0ol 调用了 iven_1s_educated...... 实际上,这些函数形成了一条调用链:
check()
→ iven_is_handsome()
→ iven_is_c0ol()
→ iven_1s_educated()
→ iven_1s_brave()
→ iven_1s_great()
→ iven_and_grace()
→ finally_fun()
从后往前,逐一反编译每个函数,esc键往前退回,可以得到如下的位置→字符映射表:
finally_fun(最后一环):
c
return a1[1] == 99 && a1[25] == 64 && a1[27] == 101;
// 索引1 = 'c' 索引25 = '@' 索引27 = 'e'
可以用随波逐流工具验证一下a1的值:

也可以用 Python 的 chr() 函数转换。
iven_and_grace:
c
return a1[4] == 50 && a1[17] == 114 && a1[29] == 102 && a1[24] == 95 && finally_fun(a1);
// 索引4 = '2' 索引17 = 'r' 索引29 = 'f' 索引24 = '_'
iven_1s_great:
c
return a1[2] == 116 && a1[9] == 99 && a1[32] == 125 && a1[19] == 118 && a1[5] == 48 && a1[14] == 110 && iven_and_grace(a1);
// 索引2 = 't' 索引9 = 'c' 索引32 = '}' 索引19 = 'v' 索引5 = '0' 索引14 = 'n'
iven_1s_brave:
c
return a1[15] == 100 && a1[8] == 123 && a1[18] == 51 && a1[28] == 95 && a1[21] == 114 && iven_1s_great(a1);
// 索引15 = 'd' 索引8 = '{' 索引18 = '3' 索引28 = '_' 索引21 = 'r'
iven_1s_educated:
c
return a1[0] == 119 && a1[6] == 50 && a1[22] == 115 && a1[31] == 110 && a1[12] == 95 && iven_1s_brave(a1);
// 索引0 = 'w' 索引6 = '2' 索引22 = 's' 索引31 = 'n' 索引12 = '_'
iven_is_c0ol:
c
return a1[7] == 48 && a1[16] == 95 && a1[11] == 112 && a1[23] == 101 && a1[30] == 117 && iven_1s_educated(a1);
// 索引7 = '0' 索引16 = '_' 索引11 = 'p' 索引23 = 'e' 索引30 = 'u'
iven_is_handsome:
c
return a1[10] == 112 && a1[13] == 64 && a1[3] == 102 && a1[26] == 114 && a1[20] == 101 && iven_is_c0ol(a1);
// 索引10 = 'p' 索引13 = '@' 索引3 = 'f' 索引26 = 'r' 索引20 = 'e'
每个函数都做同一件事:检查输入字符串的某些位置是否等于特定字符。
三、根据 check() 函数链调用链,编写有效 Flag
用AI 编写脚本:
python
flag = [''] * 33
# finally_fun
flag[1] = chr(99) # 'c'
flag[25] = chr(64) # '@'
flag[27] = chr(101) # 'e'
# iven_and_grace
flag[4] = chr(50) # '2'
flag[17] = chr(114) # 'r'
flag[29] = chr(102) # 'f'
flag[24] = chr(95) # '_'
# iven_1s_great
flag[2] = chr(116) # 't'
flag[9] = chr(99) # 'c'
flag[32] = chr(125) # '}'
flag[19] = chr(118) # 'v'
flag[5] = chr(48) # '0'
flag[14] = chr(110) # 'n'
# iven_1s_brave
flag[15] = chr(100) # 'd'
flag[8] = chr(123) # '{'
flag[18] = chr(51) # '3'
flag[28] = chr(95) # '_'
flag[21] = chr(114) # 'r'
# iven_1s_educated
flag[0] = chr(119) # 'w'
flag[6] = chr(50) # '2'
flag[22] = chr(115) # 's'
flag[31] = chr(110) # 'n'
flag[12] = chr(95) # '_'
# iven_is_c0ol
flag[7] = chr(48) # '0'
flag[16] = chr(95) # '_'
flag[11] = chr(112) # 'p'
flag[23] = chr(101) # 'e'
flag[30] = chr(117) # 'u'
# iven_is_handsome
flag[10] = chr(112) # 'p'
flag[13] = chr(64) # '@'
flag[3] = chr(102) # 'f'
flag[26] = chr(114) # 'r'
flag[20] = chr(101) # 'e'
print(''.join(flag))
