线程守护的题目

ctf_game wp

师傅给的任务,
这儿题目考察的是线程守护,
前面一个hgame week4 secret的题目为父子进程发送信号, 可以同时看看,

链接: https://pan.baidu.com/s/1NC6sjsELWTGHNCuWUflhqg 密码: csdr

分析函数

最开始看到.bak的后缀,然后以为是个啥备份文件,然后拿来以后犹豫了下, 用file指令查看了下,是个elf, 还是64位,

在这里插入图片描述

然后直接运行一下,一开始一个简单的介绍, 进去大概就是个抓娃娃机, 然后发现随机的动, 而且跳得地方看起来也没啥规律, 移动过去抓住, 然后等级高了以后发现动的几率增大了, 到后面还经常抓住了以后滑落下来,

那大概有个底, ida看一下, 文件还是比较大, 看起来不是很一般的题目,静态分析,再动调几次基本可以确定main函数和其中的调用的几个函数:

main函数

main函数前面是输出那段提示信息,然后进入这个大循环, 就是这个游戏的运行了, 显示不断循环获取输入,然后根据这些字符决定运行的函数,

但是这里注意到有一个v是在提示中并没有出现的,后面的提示说debug模式,也就因此命名了下函数,运行输入v,发现总是显示不再debug模式。

然后后面是一次运行后的收尾部分。

首先是读取一下用户的生命值, 然后判定是否是生命值为0游戏结束了,

然后下面吧一个数据增大了,之后由这个数据和我们的等级决定是否进入某个函数,这个位置得动调一下, 确定这个函数:

然后会发现每次运行到这个函数的时候F的位置才会变化,这个函数将f位置随机变化,是rand_fun,然后前面的数据, 决定了是否进入这个函数为rand_data, 其他两个函数左右移动函数确定下来里面的F的位置F_position和爪子位置position两个量, 就还是比较简单的看明白,

cat函数


主要这个cat函数看起来比较复杂, 调试会看到其实左右的两个循环并不需要去管,我们看下真正判定是否抓住的位置只在中间的位置;


主要的三个判定都在这个位置, 然后我们可以将jnzjz互换,

但是这个cat函数会出现掉落的情况,所以里面的判定, 中间那个判定的位置是时好时坏,

得到flag1

这个时候可以直接全nop掉,然后保存到源文件,直接去运行,直接s五次就可以拿到前一半flag,

但在这个想法之前,我尝试直接修改了usr_level, 但是随即程序结束,然后提示有数据被修改了,所以nop掉以后直接s下去才行:

这里是第一半flag, 然后前面的数字不知道啥意思,下面提示是关于线程的,说在一个竞争中得到剩下的一半flag

线程

其实在分析时 就看到了许多奇怪的函数了结构的出现:

首先是提示中也出现的ThreadSanitizer, 就是在多线程中为了保证数据访问时不会混乱,c++设置的工具,也是程序中随处可见的:

还有这个锁的结构就引起了我一点怀疑,这个是在多线程中读写数据为了保持数据不会在线程之间混乱, 进行原子操作设置的锁结构。

而提示也说到在一个race, 想到了data race

data race

而这时候也是察觉到了多线程这个要素,但是比较无从下手,程序运行后输出提示,查询单线程, 进入游戏后,有五个线程:

这时候也是有点盲目了,还有个v的debug模式没使用过,应该会有一些问题,


在main函数时就是debug_data在判定是否进入debug函数

然后在debug函数内部也是一直在判定debug_data

然后其中的add_life()level_up()就是字面意思,直接加血和等级,但是里面也判断一首debug_data,而debug_on()就是直接复制debug_data = 1

这里注意一点,前面的读写数据都是在pthread_mutex_lockpthread_mutex_unlock之间,但是这个debug_on()

却是这样的, 这个地方就是存在一个data race

然后就尝试调到这里,中间的确遇到一些艰难,里面的每次都要检测debug_data是需要都patch掉,

然后调的时候有时候会进行报错,说是data race, 大致如下:

然后下一次再次调试过去的时候发现给回显了一个flag地址:

但是我们没有断到这个位置,下次运行的时候地址已经没有了, 应该找到这个函数的位置, 下端,然后在这个提示的时候过去查看flag。

线程守护

查找字符串,找到了这个don't modify me的位置, 一共在三个函数中,其中一个为检测debug_data 数据的:

而且三个函数都在这个函数中被调用,

可以看到是产生新线程, 然后这三个线程从这三个函数开始运行, 三个函数差不太多,就是在一个while()里面, 如果数据改变啥的, 就会break出来,

这是个多线程守护数据,

然后在去找下, 得到了这个:

一堆的这个ThreadSanitizer, 其中比较引起注意的是这一句,然后找到这个函数, 下断, 调试的时候直接完成游戏,level=5 的时候就会运行到这里,这就是我们的: ‘find a race for the left flag’。

还有这仨位置:

头两个是关于第一次输出的flag, 第三个是我们的报错的时候出现的字符串,找到他们对应函数下断,

调试得到flag

注意当level为1的时候会进入报错,当level为2就可以看到他告诉说flag的位置,但是如果去的晚的话就是:

然后动调到修改debug_data的位置,运行的时候会被拦截下来,
然后跟着动调, 慢慢的会出现那个指示flag的位置的地方,

然后在显示"flag at xxx"的时候过去, 就看到了另外一半flag:

合并起来就是我们的整个的flag

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值