Smash The Stack: IO Level 5 Walkthrough

Level 5 of the Smash The Stack IO wargame presents a classic stack-based buffer overflow scenario. Executing the binary simply echoes the supplied command-line argument: level5@io:/levels$ ./level05 test test Analyzing the Source Code The source file level05.c shows an unbounded strcpy into a fixed 128-byte stack buffer: #include <stdio.h> #include <string.h> int main(int argc, char **argv) { char buf[128]; if (argc < 2) return 1; strcpy(buf, argv[1]); printf("%s\n", buf); return 0; } Because strcpy() copies until it hits a null byte without checking the destination bounds of buf[128], an argument exceeding 128 bytes overwrites adjacent stack data, including the saved base pointer (EBP) and return address (EIP). ...

December 3, 2014 · 2 min · 344 words · Ahmad Mahfouz

Smash The Stack: IO Level 4 Walkthrough

In Level 4 of the Smash The Stack IO wargame, executing the binary prints a static welcome message regardless of input arguments: level4@io:/levels$ ./level04 Welcome level5 level4@io:/levels$ ./level04 $(python -c "print 'A' * 1024") Welcome level5 Analyzing the Source Code Inspecting level04.c: #include <stdio.h> #include <stdlib.h> int main() { char username[1024]; FILE* f = popen("whoami", "r"); fgets(username, sizeof(username), f); printf("Welcome %s", username); return 0; } Vulnerability Analysis: Insecure PATH Resolution Notice the popen call: FILE* f = popen("whoami", "r"); The author called whoami as a bare command name rather than specifying an absolute binary path (such as /usr/bin/whoami). When popen() spawns /bin/sh -c whoami, the shell searches for the whoami executable in the directories listed in the current user’s PATH environment variable from left to right. ...

December 3, 2014 · 1 min · 206 words · Ahmad Mahfouz

Underc0de 3 Boot2Root Walkthrough: LFI, Python Cron Command Injection, and SUID Binary Exploitation

Underc0de 3 is a vulnerable Boot2Root virtual machine designed for penetration testing practice. The attack chain spans web reconnaissance, encoded Local File Inclusion (LFI), credential discovery, cronjob command injection, and final privilege escalation via an SUID buffer overflow. Phase 1: Network Reconnaissance and Port Scanning Identify the target VM using netdiscover or arp-scan: Target IP: 192.168.1.112 Run a full Nmap service scan: nmap -sS -sV -p- -T4 192.168.1.112 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.0p1 Debian 4+deb7u2 25/tcp open smtp Postfix smtpd 80/tcp open http Apache httpd 2.2.22 (Debian) Phase 2: Web Reconnaissance & Base64-Encoded LFI Directory enumeration using dirb reveals an /ascii/ folder and /index.html. Inspecting the HTML source reveals a hidden comment: ...

December 3, 2014 · 3 min · 485 words · Ahmad Mahfouz

Smash The Stack: IO Level 3 Walkthrough

In Level 3 of the Smash The Stack IO wargame, passing a large argument quickly causes a segmentation fault: level3@io:/levels$ ./level03 $(python -c "print 'A' * 1000") Segmentation fault Analyzing the Source Code The source file level03.c is provided in /levels: #include <stdio.h> #include <string.h> #include <unistd.h> void good() { puts("Win."); execl("/bin/sh", "sh", NULL); } void bad() { printf("I'm so sorry, you're at %p and you want to be at %p\n", bad, good); } int main(int argc, char **argv, char **envp) { void (*functionpointer)(void) = bad; char buffer[50]; if (argc != 2 || strlen(argv[1]) < 4) return 0; memcpy(buffer, argv[1], strlen(argv[1])); memset(buffer, 0, strlen(argv[1]) - 4); printf("This is exciting we're going to %p\n", functionpointer); functionpointer(); return 0; } Vulnerability Analysis Target Function: good() spawns a privileged shell via execl("/bin/sh", ...). Buffer and Function Pointer: main() allocates a 50-byte buffer (char buffer[50]) and initializes a function pointer pointing to bad(). Unbounded Copy: memcpy(buffer, argv[1], strlen(argv[1])) copies the entire input into buffer without checking against its 50-byte bound. Partial Clear: memset(buffer, 0, strlen(argv[1]) - 4) zeroes out buffer up to strlen(argv[1]) - 4. The last 4 bytes of our input remain untouched in memory. Execution: The program invokes functionpointer(). If we overflow buffer such that the trailing 4 bytes align precisely over functionpointer, we redirect execution to good(). Finding Addresses and Offset in GDB Disassemble and locate the address of good(): ...

December 1, 2014 · 2 min · 352 words · Ahmad Mahfouz

Smash The Stack: IO Level 2 Walkthrough

In Level 2 of the Smash The Stack IO wargame, source code is provided directly in level02.c: level2@io:/levels$ cat level02.c #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> void catcher(int a) { setresuid(geteuid(), geteuid(), geteuid()); printf("WIN!\n"); system("/bin/sh"); exit(0); } int main(int argc, char **argv) { puts("source code is available in level02.c\n"); if (argc != 3 || !atoi(argv[2])) return 1; signal(SIGFPE, catcher); return abs(atoi(argv[1])) / atoi(argv[2]); } Analyzing the Code The Target (catcher): The catcher function sets the real, effective, and saved UID to the effective UID (geteuid()) and drops into /bin/sh. This triggers when the program receives a SIGFPE signal. Input Validation: The check if (argc != 3 || !atoi(argv[2])) ensures two arguments are passed and argv[2] does not evaluate to 0. This explicitly prevents standard division-by-zero errors. The Division: The function returns abs(atoi(argv[1])) / atoi(argv[2]). Understanding SIGFPE and Two’s Complement Overflow In C on 32-bit x86 systems, a signed 32-bit integer ranges from -2,147,483,648 (INT_MIN / 0x80000000) to +2,147,483,647 (INT_MAX / 0x7FFFFFFF). ...

December 1, 2014 · 2 min · 261 words · Ahmad Mahfouz

Smash The Stack: IO Level 1 Walkthrough

In this challenge on the Smash The Stack IO wargame, the binaries are located under /levels. Let’s inspect the target binary for Level 1: level1@io:/levels$ ls -alh level01 -r-sr-x--- 1 level2 level1 1.2K Jan 13 2014 level01 Notice the permissions: -r-sr-x--- with the SUID bit set for level2. Executing this binary successfully will spawn a process with level2 privileges. Initial Execution Running the program prompts for a passcode: level1@io:/levels$ ./level01 Enter the 3 digit passcode to enter: 838 Providing an arbitrary number exits silently with no output. ...

December 1, 2014 · 2 min · 287 words · Ahmad Mahfouz

Forwarding Client Real IPs from Nginx Reverse Proxy to Apache

A common high-performance web architecture deploys Nginx on the public frontend (port 80/443) to handle TLS termination, static asset caching, and request routing, reverse-proxying dynamic requests to an Apache backend (e.g., listening on port 8080 or localhost). However, without explicit header forwarding, Apache logs will show all incoming requests originating from 127.0.0.1 (the reverse proxy IP) rather than the client’s actual public IP. This disrupts geolocation, fraud detection, rate-limiting, and security audit trails. ...

November 30, 2014 · 2 min · 297 words · Ahmad Mahfouz

Encrypting and Decrypting Files with GnuPG (GPG)

GnuPG (GPG) is a complete implementation of the OpenPGP standard (RFC 4880). It allows you to encrypt data either symmetrically (using a shared passphrase) or asymmetrically (using public/private key pairs). When you need to protect sensitive documents (such as financial records, credentials, or backups) before sending them over email or untrusted channels, symmetric GPG encryption provides strong, zero-infrastructure security. Symmetric Encryption with a Passphrase To encrypt a file symmetrically using a password: ...

November 24, 2014 · 1 min · 212 words · Ahmad Mahfouz

Automation: Creating UTF-8 MySQL Databases and Users via Python

When provisioning new web applications or services, setting up clean UTF-8 databases and isolating access permissions to dedicated application users is a routine administrative task. Using the proper character set (utf8mb4 in modern MySQL, or utf8 in legacy environments) prevents multi-byte character encoding errors and collation mismatches. The Standard SQL Provisioning Queries The standard sequence to create an application database with UTF-8 support and grant least-privilege permissions to a dedicated user is: ...

November 24, 2014 · 2 min · 357 words · Ahmad Mahfouz

Resetting MySQL and MariaDB Root Passwords

Locked out of MySQL with ERROR 1045 (28000): Access denied for user 'root'@'localhost'? When root credentials are lost or desynchronized, you cannot change the password while the daemon enforces standard privileges. You must restart the database daemon in a bypass mode, update the authentication tables, and restart the service normally. Here are two reliable methods to recover access. Method 1: Using --skip-grant-tables This method starts the daemon without reading the grant tables, allowing local root login without a password. ...

November 24, 2014 · 2 min · 234 words · Ahmad Mahfouz