Przejdź do zawartości

Shellcode

Z Wikipedii, wolnej encyklopedii
To jest stara wersja tej strony, edytowana przez Ivâa01 (dyskusja | edycje) o 16:58, 25 maj 2022. Może się ona znacząco różnić od aktualnej wersji.

Shellcodeangloję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