2024 网鼎杯玄武组Reverse1 题解

查看 10|回复 0
作者:金野喵君   
比赛结束后一小时才做出来这道题,很遗憾。
首先将题目main文件拖入IDA中分析,分析main函数逻辑,该程序具有插入字符串(最多19个字符,最多进行15次插入)和搜索(也是最多进行15次)两个功能。


image.png (55 KB, 下载次数: 0)
下载附件
2024-11-5 00:21 上传

main函数中最先调用preprocessing函数,将本地的"flag.txt"文件读入到内存中,地址0x0064040处存储的就是flag,所以我们需要想办法读到这个内存地址。


image.png (13.06 KB, 下载次数: 0)
下载附件
2024-11-5 00:21 上传

接着分析负责插入功能的insert函数,发现插入用户输入的字符串的过程实质是构造一棵二叉树,且要求左子节点的值比右子节点的值大。


image.png (35.63 KB, 下载次数: 0)
下载附件
2024-11-5 00:20 上传



image.png (39.84 KB, 下载次数: 0)
下载附件
2024-11-5 00:06 上传

分析search函数,发现是遍历二叉树的过程。


image.png (20.74 KB, 下载次数: 0)
下载附件
2024-11-5 00:22 上传

我们可以发现search后,程序会puts打印找到的字符串。


image.png (18.38 KB, 下载次数: 0)
下载附件
2024-11-5 00:21 上传

全局变量a在内存中的地址为0x4040。当v6 = 0x4000时,&a + 24 * v6 等于0x0064040,也就是flag处。要想v6为0x4000需要输入一组数据,要求数值逐渐减小,并且小于0x6D7564206D612069,只有这样insert函数中的变量a1才会以2为底的指数增长,直到达到0x2000。我们可以将问题转化为,需要构造一棵只有左孩子节点的二叉树。
只要输入13次数据,就可以让0x2000处的节点填进数据,这样就可以和0x4000处的flag连到一起(作为左孩子节点)。
insert函数中,利用进程id和系统时间来生成随机数,并在用户每次插入字符串使用随机数进行&操作,这会导致可能随机发生树节点发生换位。这里挺阴间的,你及时知道正确的插入数据的序列,也需要一定的运气才能获得flag(每次输入时都不发生换位)。为了方便验证序列是正确的,我将a1>1的判断跳转修改为jmp,直接跳过换位操作。


image.png (17.83 KB, 下载次数: 0)
下载附件
2024-11-5 00:24 上传



image.png (37.85 KB, 下载次数: 0)
下载附件
2024-11-5 00:23 上传

在本地运行修改后的main文件,说明一下这里测试的如“00000008aaaaaaaaaaa”在调试时,手动修改为“\x00\x00\x00\x00\x00\x00\x00\x5F
[color=]aaaaaaaaaaa
”(因为无法输入不可打印的ascii字符),完成13轮输入后,查询“wd”,成功获取到flag。


image.png (121.54 KB, 下载次数: 0)
下载附件
2024-11-5 00:22 上传



image.png (64.33 KB, 下载次数: 0)
下载附件
2024-11-5 00:23 上传

贴一下解题脚本


image.png (63.16 KB, 下载次数: 0)
下载附件
2024-11-5 00:10 上传

下载次数, 宋体

您需要登录后才可以回帖 登录 | 立即注册

返回顶部