June 10, 2026
How I Recovered a Password from a Linux Binary Using Ghidra
Introduction
revs3k
4 min read
Introduction
This challenge was part of a beginner-friendly CTF hosted by HACKVERSE in collaboration with EC-Council. Reverse engineering was completely new to me at the time, so I decided to treat this challenge as a learning opportunity rather than focusing solely on solving it.
In this article, I'll walk through the challenge, explain my thought process, and show how I eventually recovered the correct password.
The challenge description was as follows:
Binary Reverse Engineering is the art of taking apart compiled programs to understand how they work, uncovering their secrets without access to source code. In this challenge, you're given mysterious binary files that seem to be checking for a specific input. Your task is to:
1. Analyze the binaries to understand their validation logic
2. Figure out what input will make the programs reveal their flag
**Question 2**
What is the correct password for binary1? (The answer is case-sensitive)
**Important Security Notice**
This challenge may include components that may be flagged by antivirus software due to their legitimate but potentially dual-use nature. While our code contains no malicious elements, we recommend the following security precautions:
- Run this challenge in an isolated virtual machine
- Disconnect the virtual machine from network access
- Use a dedicated testing environment if possible
These measures will ensure optimal security while completing the challenge.
_Solving this challenge will unlock Question 3_Binary Reverse Engineering is the art of taking apart compiled programs to understand how they work, uncovering their secrets without access to source code. In this challenge, you're given mysterious binary files that seem to be checking for a specific input. Your task is to:
1. Analyze the binaries to understand their validation logic
2. Figure out what input will make the programs reveal their flag
**Question 2**
What is the correct password for binary1? (The answer is case-sensitive)
**Important Security Notice**
This challenge may include components that may be flagged by antivirus software due to their legitimate but potentially dual-use nature. While our code contains no malicious elements, we recommend the following security precautions:
- Run this challenge in an isolated virtual machine
- Disconnect the virtual machine from network access
- Use a dedicated testing environment if possible
These measures will ensure optimal security while completing the challenge.
_Solving this challenge will unlock Question 3_When I first read the words Reverse Engineering, my initial reaction was to skip the challenge altogether. However, I quickly realized that this could be a great opportunity to learn something new and get a practical introduction to reverse engineering.
So I downloaded the binary and started exploring.
Since I had no prior experience with reverse engineering, the first thing I wanted to know was: what type of file am I dealing with?
~/Downloads$ file binary1
binary1: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=a50a059c555c706ff2e6003e173b763bda2879a9, for GNU/Linux 3.2.0, not stripped~/Downloads$ file binary1
binary1: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=a50a059c555c706ff2e6003e173b763bda2879a9, for GNU/Linux 3.2.0, not strippedThe output tells us that the file is an ELF (Executable and Linkable Format) binary for Linux.
A quick safety note before proceeding: whenever you're analyzing unknown binaries, it's a good practice to use a virtual machine or isolated environment. Although this challenge binary was harmless, treating unknown executables cautiously is always recommended.
After making the file executable using:
chmod +x binary1chmod +x binary1I ran it and was immediately prompted for a password — which aligned perfectly with the challenge description. Our goal was clear: understand how the program validates input and recover the correct password.
Checking Binary Protections
Before diving deeper, I wanted to understand what security protections were enabled in the binary.
For that, I used the checksec utility:
~/Downloads$ checksec --file=./binary1
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH 47 Symbols No 0 2 ./binary1~/Downloads$ checksec --file=./binary1
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH 47 Symbols No 0 2 ./binary1At this point, I had reached the limits of what I knew, so I spent some time researching these protections and used ChatGPT to better understand the output.
Here's a simplified summary:
For this challenge, the most interesting observation was that the binary was not stripped, meaning many function names were still available and easier to identify.
Loading the Binary in Ghidra
Now it was time to use one of the most popular reverse engineering tools available: Ghidra, developed by the NSA.
Installation is straightforward on most Linux distributions:
sudo apt install ghidrasudo apt install ghidraAfter launching Ghidra, follow these steps.
When Ghidra starts:
- Select Non-Shared Project
- Choose a project name (for example,
binary1_analysis) - Select a location to save the project
Import the Binary
Inside the project window:
- Navigate to File → Import File
- Select
binary1 - Ghidra will automatically recognize it as a 64-bit ELF binary
- Click through the prompts
Open in CodeBrowser
- Double-click the imported binary
- When prompted, choose Yes to analyze it
- Leave the default analysis settings enabled
- Click Analyze
Explore the Interface
The three most important sections for this challenge are:
- Symbol Tree — Lists available functions and symbols
- Listing Window — Displays assembly instructions
- Decompiler Window — Shows a C-like representation of the code
If you're new to Ghidra, I highly recommend watching a beginner introduction video before proceeding.
Once the analysis completed, these three panels became the primary focus of my investigation.
Rather than diving deeply into assembly, I decided to look for clues based on the strings displayed when running the binary.
The prompts:
- "Enter password"
- "Incorrect password"
must exist somewhere inside the program, and tracing them could lead us to the validation logic.
By examining the main() function, I noticed a call to another function named verify_password.
Even without reading the implementation, the function name itself was a strong hint.
To inspect it, simply double-click verify_password in either the Symbol Tree or the decompiler view.
Understanding the Password Verification Logic
Inside the verify_password() function, three things immediately stood out:
local_38 = 0x673a257671212f28;
local_30 = 0x3131122d140d2d2d;local_38 = 0x673a257671212f28;
local_30 = 0x3131122d140d2d2d;along with a loop that processed user input.
The variables local_38 and local_30 each contain 8 bytes of data.
Together they store:
8 bytes + 8 bytes = 16 bytes8 bytes + 8 bytes = 16 bytesThese values appeared to be the secret data used during validation.
Looking more closely at the loop revealed the actual logic:
- Two 8-byte constants store 16 secret bytes.
- Every character of the user's input is XOR'ed with
0x42. - The transformed result is compared against those secret bytes.
- If every byte matches, the password is accepted.
Once this became clear, recovering the password was simply a matter of reversing the operation.
Extracting the Secret Bytes
Looking at the assembly representation, the values are stored as:
local_38 = 28 2f 21 71 76 25 3a 67
local_30 = 2d 2d 0d 14 2d 12 31 31local_38 = 28 2f 21 71 76 25 3a 67
local_30 = 2d 2d 0d 14 2d 12 31 31Combining them gives us the full 16-byte sequence:
28 2f 21 71 76 25 3a 67 2d 2d 0d 14 2d 12 31 3128 2f 21 71 76 25 3a 67 2d 2d 0d 14 2d 12 31 31Since the binary XORs the user input with 0x42, we can reverse the operation by XORing these bytes with 0x42 as well.
A quick Python script does the job:
python3 - <<'EOF'
data = [
0x28,0x2f,0x21,0x71,
0x76,0x25,0x3a,0x67,
0x2d,0x2d,0x0d,0x14,
0x2d,0x12,0x31,0x31
]
print(''.join(chr(b ^ 0x42) for b in data))
EOFpython3 - <<'EOF'
data = [
0x28,0x2f,0x21,0x71,
0x76,0x25,0x3a,0x67,
0x2d,0x2d,0x0d,0x14,
0x2d,0x12,0x31,0x31
]
print(''.join(chr(b ^ 0x42) for b in data))
EOFRunning the script reveals the original password hidden inside the binary.