吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1167|回复: 18
收起左侧

[CTF] 2024 网鼎杯玄武组Reverse1 题解

[复制链接]
金野喵君 发表于 2024-11-5 00:06
本帖最后由 金野喵君 于 2024-11-6 14:27 编辑

比赛结束后一小时才做出来这道题,很遗憾。
首先将题目main文件拖入IDA中分析,分析main函数逻辑,该程序具有插入字符串(最多19个字符,最多进行15次插入)和搜索(也是最多进行15次)两个功能。
image.png
main函数中最先调用preprocessing函数,将本地的"flag.txt"文件读入到内存中,地址0x0064040处存储的就是flag,所以我们需要想办法读到这个内存地址。
image.png
接着分析负责插入功能的insert函数,发现插入用户输入的字符串的过程实质是构造一棵二叉树,且要求左子节点的值比右子节点的值大。

image.png
image.png
分析search函数,发现是遍历二叉树的过程。
image.png
我们可以发现search后,程序会puts打印找到的字符串。
image.png
全局变量a在内存中的地址为0x4040。当v6 = 0x4000时,&a + 24 * v6 等于0x0064040,也就是flag处。要想v6为0x4000需要输入一组数据,要求数值逐渐减小,并且小于0x6D7564206D612069,只有这样insert函数中的变量a1才会以2为底的指数增长,直到达到0x2000。我们可以将问题转化为,需要构造一棵只有左孩子节点的二叉树。
只要输入13次数据,就可以让0x2000处的节点填进数据,这样就可以和0x4000处的flag连到一起(作为左孩子节点)。
insert函数中,利用进程id和系统时间来生成随机数,并在用户每次插入字符串使用随机数进行&操作,这会导致可能随机发生树节点发生换位。这里挺阴间的,你即使知道正确的插入数据的序列,也需要一定的运气才能获得flag(每次输入时随机数计算都不触发换位的前提下,13轮输入,说实在得是欧皇才能快速成功)。
为了方便验证序列是正确的,我将a1>1的判断跳转修改为jmp,直接跳过换位操作。patch这部分代码只是避开运气的部分(强行欧皇),不影响程序的整体逻辑。
image.png
image.png
在本地运行修改后的main文件,说明一下这里测试的如“00000008aaaaaaaaaaa”在调试时,手动修改为“\x00\x00\x00\x00\x00\x00\x00\x5Faaaaaaaaaaa”(因为无法输入不可打印的ascii字符),完成13轮输入后,查询“wd”,成功获取到flag。
image.png
image.png
贴一下解题脚本

image.png
main.rar (4.41 KB, 下载次数: 7)





免费评分

参与人数 2威望 +1 吾爱币 +21 热心值 +2 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
HillBoom + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

jindaxia 发表于 2024-11-8 15:50
本帖最后由 jindaxia 于 2024-11-12 17:09 编辑

还有一种可能,因为环境是在容器内运行的,所以 pid固定为1,srand(pid*time)  那么随机数种子就固定在了当前启动时间,
在seed固定的情况下,当前时间戳,单位是秒,可以预测每一位产生的随机数, 另外程序给了一个就算插入到右节点,还能纠正的机会,即发生交换(最后一个异或,会交换左右节点)
所以与其赌命让13次生成的随机数都比前一次小(几乎不可能),不如根据随机数的值(是否会交换),选择插入的值是要比前一次大,还是前一次小
所以为了预留足够的间距容纳 比前一次大,又比前前一次小的数,两次插入的数组必须有足够长的间距,

node结构体
[Asm] 纯文本查看 复制代码
struct  AAA
{
  char str_data[16];
  __int64 random_num;
};
image.png

免费评分

参与人数 1吾爱币 +10 热心值 +1 收起 理由
Hmily + 10 + 1 用心讨论,共获提升!

查看全部评分

l5808 发表于 2024-11-6 08:21
十一七 发表于 2024-11-6 10:29
有没有可能,赛时打的是远程,你直接 patch 二进制没啥用
 楼主| 金野喵君 发表于 2024-11-6 11:19
十一七 发表于 2024-11-6 10:29
有没有可能,赛时打的是远程,你直接 patch 二进制没啥用

patch只是为了手动测试一遍过,不patch的话要看运气,需要13次输入都不触发交换。需要一直循环跑脚本去试,如果是倒霉蛋不配得到flag。
曟AI 发表于 2024-11-6 11:27
学习学历
jindaxia 发表于 2024-11-8 15:44
金野喵君 发表于 2024-11-6 11:19
patch只是为了手动测试一遍过,不patch的话要看运气,需要13次输入都不触发交换。需要一直循环跑脚本去试 ...

打成功的概率是多少? 13次都在左边?
Susenliu 发表于 2024-11-8 15:57

感谢楼主分享
 楼主| 金野喵君 发表于 2024-11-11 11:13
本帖最后由 金野喵君 于 2024-11-11 11:28 编辑
jindaxia 发表于 2024-11-8 15:50
还有一种可能,因为环境是在容器内运行的,所以 pid固定为1,srand(pid*time)  那么随机数种子就固定在了当 ...

太强了。确实,如果pid为1,可以依据容器的启动时间来预测随机数。如果平台给出的容器启动时间和该进程时间不一致(没有精确到秒一致),只需要枚举误差内的时间去试出真正的大小顺序就行了。只能说这题太恶心了,不容易想到。
 楼主| 金野喵君 发表于 2024-11-11 11:21
jindaxia 发表于 2024-11-8 15:44
打成功的概率是多少? 13次都在左边?

是的,13次子节点的随机数都比根节点的随机数大,概率还蛮小的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-22 19:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表