CryptoCat Pwn Challenges

This is all that I have learnt using CryptoCat YouTube course. Below are the things I have learnt from each challenge. Challenges can be found here.
1️⃣ Intro Challenge
While this challenge was complete introduction about the tools and buffer overflow, we can still learn how to approach an executable.
📌 vuln is a file that we are inspecting in this challenge.
Basic Info - (file)
1 | # Get information about an executable |
Above command tells us that file is 32-bit executable, dynamically linked and not stripped.
Dynamically linked means that executable does not contain all the code it needs to run. Instead, it relies on external shared libraries (e.g., .dll
in Windows or .so
in Linux).
A “not stripped” executable means we can reverse the program and see the function names, variables etc.
Check Security Settings - (checksec)
1 | # check binary security settings |
Above command is used to check security settings applied on the binary.
PWNDBG
Pwndbg is a Python module which is loaded directly into GDB, making the process of debugging and reverse-engineering more user-friendly.
1 | # Load file using `file` command in GDB |
With info functions
command, we can see the user-defined function names and other libc functions as well such as gets
and puts
.

Here are some useful pwndbg commands:
Command | Info |
---|---|
disassemble main |
Disassemble function |
break main |
Set break-point on function |
info stack |
Get info about stack |
x $eax |
Get register value |
n |
Go onto next instruction (when hitting a break-point) |
c |
Continue the program |
delete breakpoints |
Delete all breakpoints |
run |
Run program |
2️⃣ Overwriting Stack Variables Challenge
📌 login is the file that we are inspecting in this challenge.
Run the binary and if you supply enough characters in the input, it will give Segmentation fault error. That’s because gets
function does not check the defined buffer size of the variable (causing buffer overflow).
First, buffer size of password
variable is filled up and then authorized
variable memory is overwritten which is why we see random number in the output.
Ghidra
If we lookup the binary in Ghidra, there we can see the de-compiled code and even the correct password.
Learnings From Solution
We can modify value of authorized
variable to 1
from GDB. First we check flow of program in Ghidra and decide to change variable value when it’s being checked in if statement (if authorized == 0
).
- Set a breakpoint at the adress of
cmp
instruction in GDB →break *0x0804921e
- Run the program (
run
) and when breakpoint hits, get the memory address from pointer using commandx $ebp - 0xc
as that’s what the0
is being compared to (dword ptr [ebp - 0xc], 0
). - Set the value of that address (
0xffffcbec
) to 1 →set *0xffffcbec=1
- Verify the change →
x $ebp - 0xc
3️⃣ Overwriting Stack Variables Challenge
We can solve this challenge using the same method like in previous challenge but we should not because in CTFs, binary sits on remote server and we connect to it using netcat. Therefore, we use different approach.
Since gets
function is in use, we can get past the allocated buffer and overwrite the variable that holds the value which is being checked with 0xdeadbeef
(we know we are overwriting the value because it’s being printed in the response).
Our input variable is assigned size of 32 bytes (1 char = 1 byte), and whatever we supply after 32 characters are overwriting the value that’s being checked against 0xdeadbeef
, therefore we overwrite it by supplying 32 characters then our payload.
4️⃣ Ret2Win Challenge
This challenge asks us to overwrite return address to access hidden hacked()
function. This is possible because scanf()
takes standard input and stores it in the buffer (and user input can exceed 16 bytes).
We can use gdb
to find hacked()
function’s address.

To know how many characters are required to overwrite return address, we use cyclic 100
command in GDB that lets us generate random characters and find the offset that crashes the program.
Run the program (run
) in GDB and paste the characters generated by cyclic
. Program will crash and debugging information will be shown.
💡EIP is a register in x86 architectures (32bit). It holds the “Extended Instruction Pointer“ for the stack. In other words, it tells the computer where to go next to execute the next command and controls the flow of a program.
Scroll up to see Invalid address error and EIP pointing at 4 bytes from our payload string.

Enter cyclic -l haaa
to find the offset, which comes out to be 28
.
We use python2
to craft a payload that fills up the 28 bytes. The buffer[16]
variable is assigned buffer of 16 bytes, then extra bytes to cover padding and some other stuff such as saved frame pointer, then our payload to overwrite return address.
0x8049182
is the address of hacked()
function which we want to access. Therefore, we will write it like this after 28 bytes: \x82\x91\x04\x08
. We wrote the address in reverse because it’s an LSB executable.
Generate payload using the below command:
1 | python2 -c 'print("A"*28 + "\x82\x91\x04\x08")' > payload |
⚠️ Output has to be saved in a file because \x82\x91..
characters are not printable.
Run the program by supplying payload file as input and we have successfully solved the challenge.

Learning From Solution
If we have access to executable, cyclic
command can be used to generate characters and cyclic -l [chars]
to find the right offset.
Overwriting address should be done using hex characters via python2
to avoid errors.
In progress…