Shellcode
Shellcode - anglojęzyczny zlepek słów shell (powłoka) oraz code (kod) oznaczający prosty, niskopoziomowy program prezentowany najczęściej w postaci kodu maszynowego, odpowiedzialny za wywołanie powłoki systemowej. Często wykorzystywany w ostatniej fazie wykorzystywania wielu błędów zabezpieczeń przez exploity.
Dostarczany jest on zwykle wraz z innymi danymi wejściowymi użytkownika (zazwyczaj poprzedza go obszar instrukcji NOP, zaś za nim znajduje się przybliżony adres shellcodu w pamięci). Na skutek wykorzystania luki w atakowanej aplikacji, procesor rozpoczyna wykonywanie shellcode, pozwalając na uzyskanie nieautoryzowanego dostępu do systemu komputerowego lub eskalację uprawnień.
Przykładowy shellcode, zapisany zgodnie z notacją języka C, zamieszczony jest poniżej:
char shellcode[]= "\x31\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\x31\xc9" /* xorl %ecx,%ecx */ "\xb0\x46" /* movl %al,$0x46 */ "\xcd\x80" /* int $0x80 */ "\x50" /* pushl %eax */ "\x68""/ash" /* pushl $0x6873612f */ "\x68""/bin" /* pushl $0x6e69622f */ "\x89\xe3" /* movl %esp,%ebx */ "\x50" /* pushl %eax */ "\x53" /* pushl %ebx */ "\x89\xe1" /* movl %ecx,%esp */ "\xb0\x0b" /* movb %al,$0x0b */ "\xcd\x80" /* int $0x80 */ ;
W niektórych przypadkach, ze względu na ograniczenia parametrów wejściowych, które może przyjąć program, autorzy shellcode zmuszeni są do wykorzystywania nietypowych konstrukcji - np. unikania jakichkolwiek instrukcji i parametrów zawierających bajt o wartości 0x00, który w C odczytywany jest jako znacznik końca ciągu tekstowego; albo korzystania tylko z instrukcji, których reprezentacja zamknie się w zbiorze znaków drukowalnych ASCII; albo do ograniczenia kodu do bardzo niewielkich wymiarów.
Shellcode dla Windows
W shellcode dla systemów Windows najbardziej stabilną opcją uzyskania dostępu do API wydaje się przeszukiwanie struktury _PEB.
typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID Reserved4[3]; PVOID AtlThunkSListPtr; PVOID Reserved5; ULONG Reserved6; PVOID Reserved7; ULONG Reserved8; ULONG AtlThunkSListPtr32; PVOID Reserved9[45]; BYTE Reserved10[96]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved11[128]; PVOID Reserved12[1]; ULONG SessionId; } PEB, *PPEB;
Dostęp do struktury w języku Asembler można uzyskać instrukcją:
mov rax, gs:[30h] ;RAX = PEB structure
Innym sposobem na korzystanie z API systemu Windows może być np. użycie instrukcji SYSCALL. Rozwiązanie to jednak nie jest stabilne, gdyż wartości (numery) wywołań mogą się zmieniać wraz z wersjami systemu operacyjnego.
Bibliografia
- Dawid Farbaniec Kod powłoki dla Windows x86-64 (x64).