Уязвимость переполнения буфера - PullRequest
0 голосов
/ 01 апреля 2020

Я пробираюсь через лабораторию, чтобы продемонстрировать использование буфера через поток. У меня это работает, но есть одна область, которую я не совсем понимаю, и я надеюсь, что кто-то может объяснить мне.

Это код с эксплойтом:

/* Vunlerable program: stack.c */
/* You can get this program from the lab’s website */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
  char buffer[24];
  /* The following statement has a buffer overflow problem */
  strcpy(buffer, str); ➀
  return 1;
}
int main(int argc, char **argv)
{
  char str[517];
  FILE *badfile;
  badfile = fopen("badfile", "r");
  fread(str, sizeof(char), 517, badfile);
  bof(str);
  printf("Returned Properly\n");
  return 1;
}

One Шагом лаборатории является определение размера памяти, выделенной для буфера [24]. Для этого я запустил gdb для функции bof и вижу, что память, выделенная в моей системе, равна 0x20, что составляет 32 бита.

Если я изменю размер буфера, я могу запустить gdb и найти слот памяти выделен. Но могу ли я сказать, сколько памяти будет выделено для буфера [24] без GDB? Если я перехожу в буфер [8], должен ли я сразу узнать, что представляет собой блок памяти в 32-битной системе, или он меняется в системе? И если я должен знать, может кто-нибудь объяснить, как.

1 Ответ

1 голос
/ 01 апреля 2020

Это зависит от целевой платформы, флагов компилятора и компиляции.

Например, G CC 7.2 x86 в режиме отладки (-O0) выравнивает кадры стека на 16-байтовой границе и выделяет указатель кадра (ebp).

Пример: ( ссылка Godbolt )

bof(char*):
        push    ebp                   ; -4
        mov     ebp, esp           
        sub     esp, 40               ; -40
        sub     esp, 8                ; -8
        push    DWORD PTR [ebp+8]     ; -4
        lea     eax, [ebp-32]         ; 32 bytes to top of stack frame
        push    eax                   ; -4
        call    strcpy                ; stack is aligned to 16 bytes (-64)
        add     esp, 16
        mov     eax, 1
        leave
        ret

При оптимизации (-O2) указатель кадра опускается, но стек выровнен по 16 байтам ( ссылка Годболт ):

bof(char*):
        sub     esp, 52               ; -52
        push    DWORD PTR [esp+56]    ; -4
        lea     eax, [esp+20]         ; 36 bytes to top of stack frame
        push    eax                   ; -4
        call    strcpy                ; stack is aligned to 16 bytes (-64)
        mov     eax, 1
        add     esp, 60
        ret

с принудительным выравниванием стека 4 байта (-O2 -mpreferred-stack-boundary=2) ( ссылка Годболт ):

bof(char*):
        sub     esp, 24               ; -24
        push    DWORD PTR [esp+28]    ; -4
        lea     eax, [esp+4]          ; 24 bytes to top of stack frame
        push    eax                   ; -4
        call    strcpy
        mov     eax, 1
        add     esp, 32
        ret

С включенной защитой стека (-O2 -fstack-protector-all) ( godbolt link ):

bof(char*):
        sub     esp, 52                      ; -52
        mov     eax, DWORD PTR gs:20
        mov     DWORD PTR [esp+36], eax      ; stack check value at -16 (-52+36)
        xor     eax, eax
        push    DWORD PTR [esp+56]           ; -4
        lea     eax, [esp+16]                ; 40 bytes to top of stack frame, leaving exactly 24 bytes to check value
        push    eax
        call    strcpy
        add     esp, 16
        mov     edx, DWORD PTR [esp+28]
        xor     edx, DWORD PTR gs:20
        jne     .L5
        mov     eax, 1
        add     esp, 44
        ret
.L5:
        call    __stack_chk_fail

Другие компиляторы могут иметь совершенно разные результаты.

В реальной жизни переполнение буфера используется в режиме сборки путем анализа инструкций и подсчета байтов до адреса возврата функции, поэтому не имеет значения, каким был исходный код или как он был скомпилирован (эта информация часто в любом случае недоступна) .

...