We covered a scenario of a binary vulnerable to buffer overflow vulnerability. The binary has NX and PIE protections enabled so we opened the binary with Ghidra debugger and built the exploitation methodology based on calculating the offsets of the input variable and another variable that controls an entry to an if statement that prints the flag. The objective was to control the value of that binary and let the execution flow enter the if statement. This was part of HackTheBox Jeeves Intro to Binary Exploitation Track.

Initial Analysis and Code Exploration

I began my analysis of the downloaded executable by checking its file type, confirming it was a 64-bit executable. I then used the command checksec file Jeeps to inspect its security protections, specifically looking for buffer overflow mitigations. Following this, I opened the binary in Ghidra, a reverse engineering tool, to delve into its code.

In Ghidra, I focused on the main function. I identified a variable, Local 48, as the one responsible for accepting user input—the program prompts the user for their name, which gets stored here. Crucially, I noticed an if statement that depended on another integer variable, local_underscore_C. If local_underscore_C held a specific hexadecimal value (0x6161616161616161), the code inside the if statement would execute. This code was designed to open a file named flag.txt, read its content, and presumably print the flag. The challenge was that I could only directly control Local 48, making it seem impossible to enter the if statement through normal input since local_underscore_C appeared to be a separate variable.

  • Query successful

Try again without apps

I’ve summarized the video about the “Jeeps” Hack The Box challenge in detail, using a conversational tone and the pronoun “I,” as you requested. I’ve also extracted the technical commands shown on the terminal.


Hack The Box: “Jeeps” Challenge Walkthrough 💻

I started by introducing the “Jeeps” challenge from Hack The Box’s “Intro to Binary Exploitation” track. The core objective of this challenge is to understand and apply buffer overflow techniques. I explained that the first step is to start the challenge instance, which provides an IP address and port for connection. You can also download the challenge files, including an executable that needs to be exploited.


Initial Analysis and Code Exploration 🕵️‍♂️

I began my analysis of the downloaded executable by checking its file type, confirming it was a 64-bit executable. I then used the command checksec file Jeeps to inspect its security protections, specifically looking for buffer overflow mitigations. Following this, I opened the binary in Ghidra, a reverse engineering tool, to delve into its code.

In Ghidra, I focused on the main function. I identified a variable, Local 48, as the one responsible for accepting user input—the program prompts the user for their name, which gets stored here. Crucially, I noticed an if statement that depended on another integer variable, local_underscore_C. If local_underscore_C held a specific hexadecimal value (0x6161616161616161), the code inside the if statement would execute. This code was designed to open a file named flag.txt, read its content, and presumably print the flag. The challenge was that I could only directly control Local 48, making it seem impossible to enter the if statement through normal input since local_underscore_C appeared to be a separate variable.


Finding the Buffer Overflow Offset

My goal was to overwrite local_underscore_C by providing an input to Local 48 that was long enough to spill over into local_underscore_C‘s memory location. In Ghidra, I examined the memory offsets of these variables:

  • local_underscore_C was at offset 0xc (hexadecimal).
  • Local 48 (user input) was at offset 0x48 (hexadecimal).

I calculated the difference to find the required offset:

  • 0x48 (hex) = 72 (decimal)
  • 0xc (hex) = 12 (decimal)
  • Distance = 72 – 12 = 60 bytes. This meant I needed 60 bytes of input to reach and begin overwriting local_underscore_C.

Confirming the Offset with GDB

To confirm my findings from Ghidra, I used GDB (GNU Debugger). I started GDB with the executable using a command similar to gdb ./Jeeps. I set a breakpoint right after the gets function (which handles user input) in the main function using the command:

  • breakpoint *main+53

Then, I ran the program with a short input using run (or r). By examining the stack in GDB, I was able to reconfirm that the distance between the user input’s location and the target variable (local_underscore_C) was indeed 60 bytes.

Crafting the Exploit Script with Pwntools

I then wrote a Python script to automate the exploit using the pwntools library. I started by importing it: from pwn import *.

The script’s logic was as follows:

  1. It connected to the remote instance using netcat functionality provided by pwntools, specifying the target IP and port.
  2. I constructed the payload:
    • First, I filled the buffer with 60 ‘A’ characters to reach the local_underscore_C variable. The code for this was payload = 'A' * 60.
    • Next, I needed to append the target hexadecimal value (0x6161616161616161) that local_underscore_C needed to hold. I used the p64() function from pwntools to pack this hex value into bytes: byte_payload = p64(0x6161616161616161).
    • Since the input expected was a string, I decoded this byte payload into a string using ISO-8859-1 encoding: byte_payload.decode('ISO-8859-1').
    • The final payload was the concatenation of the 60 ‘A’s and the decoded hexadecimal value.
  3. The script then sent this crafted payload to the server using target.sendline(final_payload).
  4. Finally, it received and printed the output until it found a closing curly brace }, which I expected to be the end of the flag: print(target.recvuntil(b'}')).

I used the nano exploit.py command to create and edit the script.

Running the Exploit and Getting the Flag

To execute the exploit, I simply ran the Python script using:

  • python3 exploit.py (or python exploit.py)

The script successfully connected, sent the crafted input, overwrote local_underscore_C with the desired value, triggered the if condition, and the server responded with the flag! I then submitted the flag to Hack The Box.

In essence, this video demonstrated how a simple buffer overflow works. By providing more input than a program expects for a particular variable, the excess data “overflows” into adjacent memory locations. In this specific case, I precisely controlled this overflow to overwrite a different variable with a specific value, which then unlocked a part of the code that printed the flag. Tools like Ghidra (for static analysis) and GDB (for dynamic analysis) were indispensable for understanding the binary’s behavior and calculating the exact offset needed for the overflow. Pwntools then provided the means to automate sending this specially crafted input to the remote server.

Video Walkthrough

About the Author

Mastermind Study Notes is a group of talented authors and writers who are experienced and well-versed across different fields. The group is led by, Motasem Hamdan, who is a Cybersecurity content creator and YouTuber.

View Articles