首页
社区
课程
招聘
[看雪CTF.TSRC 2018 团队赛][分析] 第二题 半加器
发表于: 2018-12-3 23:30 2801

[看雪CTF.TSRC 2018 团队赛][分析] 第二题 半加器

2018-12-3 23:30
2801

题目给出了一个 32 位控制台 Windows 应用程序 Exam.exe:

看起来没有什么保护,它是一个 MSVC 2017 编译的 C/C++ 程序。

运行一下:

看起来就是一个经典的输入 flag,输出对错的挑战。

简单用 IDA Pro 分析一下,顺着 MSVCRT 的初始化逻辑脑补一下,可以找到 main 在 0x4A19B0 处。
逻辑大致如下:

仅仅检查了长度是否大于等于10,小于30,以及 0-based index 下 [7] 处是否是 'A'。
若不是的话则报错,这很奇怪,因为按照规则,若答案正确的话应该输出明确的正确提示。
尝试输入满足以上条件的串 0123456A89,程序确实没有任何输出。

显然,程序中存在一些隐藏的检查 flag 的逻辑。观察可以发现程序没有写文件和外部环境的行为,因此可以排除规则中所允许的“重启验证”,flag 应该就在本次执行中被验证了。考虑到输入的来源就这么两处,只要死咬着输入(和被变换过的输入)不放,肯定能找到处理 flag 的地方。

在下一个教科书般的内存读取断点之前,让我们先试试查找到 g_inputg_p_buf 的交叉引用,结果发现在 mainMangleInput 以外另有两个函数 0x495810 (命名为 InitBuffer) 和 0x49DC80 (命名为ValidateFlag)引用到了 g_input

这两个函数的逻辑也很简单:

看起来,这里才是真正的检查 flag 的地方,注意到与之比较的标准答案来自于函数参数,寻找交叉引用得到该参数:

至此,已经可以计算出输入惹:

提交即可。可以看出来多出来的那个判断 [7] 的地方是为了对付规则中的 “flag只能包含字母和数字”。

然而,题目里的谜团还没有彻底解开,这个检查 flag 的函数到底是在哪里调用的呢?
继续追踪交叉引用,可以找到是在 0x4957B0 这个函数里调用 atexit() 注册成退出时执行的函数的。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//