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

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

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