I've hidden the flag very carefully, you'll never manage to find it! Please note that the goal is to find the flag, and not to obtain a shell.
We are provided with a 32-bit ELF binary. So, for this challenge, it's not about obtaining a shell, as the challenge description states; our task is going to be finding the flag hidden inside the binary.
Now, let's analyze the binary in Binary Ninja
In the main function, the program registers a signal handler for SIGALRM
and uses mmap
to create a random address where it copies the flag. Then, it creates another mmap
for user input, reads 60 bytes, and calls it.
Let's step through this in GDB:
I set a breakpoint at the mmap
function to reach the main function where the magic happens
After stepping through, we find that the dummy flag is copied to the stack
Now, our task is clear. The flag is somewhere in the stack, and we need to prepare a shellcode to print it to stdout. After some research, I decided to use an "EGG Hunter."
An EGG Hunter is a shellcode technique where the process's memory is searched for a specific marker (the "egg") to locate a secondary payload or shellcode.
In our case, we need to search for the flag's signature and print the flag to stdout.
First, let's prepare a pwntools
template to write our payload. For debugging, I'll save the payload as a file to run it in GDB
This simple shellcode tests if our payload works by pushing 0x1337
to the stack and popping it into the eax
register.
As seen in GDB, our shellcode is about to be called
The small assembly code executes successfully
Great, as we can see from the instruction above, the small assembly code that we've written is gonna be executed.
Okay, our two lines of assembly code have been executed, and as you can see at the top, the $eax
register has the value of 0x1337
. Now, let's write our payload.
Before writing our payload, let's figure out what we need to do. Since we are using the Egg hunter
technique, we need an 8-bytes long signature, which for this challenge, we're going to use HTB{
. Additionally, since we'll be searching the VAS (Virtual Address Space), we need to check if we have permission to access a memory section while searching.
To check the permission, we can use the syscall access()
. This syscall allows us to check if we can access a specific memory address; if not, it will set our al
register to 0xf2
(EFAULT).
After we have located our flag, we need a way to print the value to stdout. To do that, we can use the syscall write()
.
Now let's write our egg hunter shellcode:
Okay, here is the assembly shellcode. I've written a comment on the shellcode describing what it's doing. At a high level, it sets the egg (HTB{
) to the edi
register, then sets VAS memory start for us to search our flag on edx
. On the test_next
label, it increments edx
register and checks if we can access
that memory section using the access
syscall.
Then we compare our 4 bytes of egg to a memory section that we can access. It will go through the memory section until we find our flag. Finally, we use our write
syscall to print the flag to stdout.
Let's test it out using GDB:
Our shellcode started to execute
Awesome! The flag is found, and it's set on the $ecx
register from the screenshot above. Now, let's test our payload using only the binary, without GDB
Great, it seems to work fine. Now, let's modify our code so that our payload will send the shellcode to the remote instance
Here is the full code. When given the HTB instance, it will send the shellcode and check if we can get the flag or not.
Awesome! The shellcode worked against the remote instance.
Reference:
https://www.hick.org/code/skape/papers/egghunt-shellcode.pdf