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
, orstrings
. - 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 ourputs()
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 likeLD_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 atutumno.labs.overthewire.org:2227
, initial credsutumno0/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!! 💖☄️✨