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

OverTheWire Utumno Level 0 → 1 tutorial!!

Login

Use the starting credentials for Utumno to play utumno0. SSH runs on port 2227 and the initial user/password is utumno0 / utumno0 (official info). :contentReference[oaicite:0]{index=0}

ssh utumno0@utumno.labs.overthewire.org -p 2227
# password: utumno0

The game data lives in /utumno/, so jump there first. ([overthewire.org][1])

cd /utumno

Task

Binary: /utumno/utumno0

  • Executing it prints only a short message like Read me! :P.
  • The file is executable but not readable, so you can’t inspect it with gdb, objdump, or strings.
  • Goal: extract the password for utumno1.

We will hook libc output using LD_PRELOAD to intercept puts()/printf() and then peek at interesting pointers/strings inside the process. This technique is a common public solution for this level. ([BreakInSecurity][2])


Source Code

There is no source provided for utumno0 (and it is not readable). We’ll write a tiny preload shim to override puts() so we can inspect memory at runtime:

// preload.c — override puts() to inspect the program at runtime
#include <stdio.h>

// build: gcc -m32 -fPIC -shared -o preload.so preload.c
int puts(const char *s){
    // Step 1: prove the hook runs
    // printf("hooked puts: %s\n", s);

    // Step 2: print words from the stack to harvest candidate addresses
    // printf("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n");

    // Step 3: once you find promising addresses (e.g., 0x08048xxx),
    // print them as C-strings (adjust to what you discover):
    // printf("%s\n", (char*)0x08048402);
    // printf("%s\n", (char*)0x080484a5);
    // printf("%s\n", (char*)0x08048490);

    return 0; // keep original output suppressed; we only need the dump
}

Why this works: LD_PRELOAD forces the dynamic linker to load our shared object first and prefer our puts() over libc’s, letting us instrument the program without read permissions. ([BreakInSecurity][2])


Exploitation Steps

1) Confirm behavior & permissions

./utumno0
# Read me! :P

file ./utumno0
# executable, regular file, no read permission

(These observations are widely noted in public write-ups.) ([BreakInSecurity][2])


2) Build the hook

mkdir -p /tmp/u0 && cd /tmp/u0
nano preload.c         # paste the code above
gcc -m32 -fPIC -shared -o preload.so preload.c

3) Spray the stack to harvest addresses

# temporarily enable the "%08x..." line in puts(), then:
LD_PRELOAD=./preload.so /utumno/utumno0
# you'll see several 32-bit values; look for ones like 0x08048xxx

Those are likely .text/.rodata addresses. We’ll try to interpret a few of them as strings. ([BreakInSecurity][2])


4) Print candidate strings

Replace the %08x spray with printf("%s\n", (char*)ADDR) calls for the addresses you found (three examples often seen in public runs are 0x08048402, 0x080484a5, 0x08048490). Then run:

LD_PRELOAD=./preload.so /utumno/utumno0

Typical output contains the original message and a line with the password, e.g.:

Read me! :P
password: aathaeyiew

This approach (and the example password string) appears in reputable public solutions. ([BreakInSecurity][2])


5) Profit

Use the discovered password to log in as the next user:

ssh utumno1@utumno.labs.overthewire.org -p 2227
# password: aathaeyiew

Note: passwords for each level are stored at /etc/utumno_pass/utumnoX on the box. ([BreakInSecurity][2])


Password

From my run / common public solutions:

aathaeyiew

(If your dump shows a different value, use yours—addresses can vary.) ([BreakInSecurity][2])


Quick One-liner

cd /tmp && mkdir u0 && cd u0 && cat > preload.c <<'EOF'
#include <stdio.h>
int puts(const char *s){
  printf("%s\n",(char*)0x08048402);
  printf("%s\n",(char*)0x080484a5);
  printf("%s\n",(char*)0x08048490);
  return 0;
}
EOF
gcc -m32 -fPIC -shared -o preload.so preload.c && LD_PRELOAD=./preload.so /utumno/utumno0

Adjust the three addresses to whatever you harvested from your %08x stack spray. The technique is documented in public write-ups. ([BreakInSecurity][2])


Troubleshooting

  • LD_PRELOAD seems ignored → Ensure you launch exactly like LD_PRELOAD=./preload.so /utumno/utumno0 (absolute or relative path to the target). ([BreakInSecurity][2])
  • No readable tool output → That’s the point: the binary isn’t readable. Use the hook to dump pointers/strings at runtime. ([BreakInSecurity][2])
  • Different addresses → Normal. First spray %08x to collect candidates, then print them as %s.
  • Where’s the game data? → It’s under /utumno/. SSH is at utumno.labs.overthewire.org:2227, initial creds utumno0/utumno0. ([overthewire.org][1])

Congrats 🎉 You just used LD_PRELOAD function hooking to extract a secret from a non-readable binary. On to Level 1 → 2!


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