Читаем Защита от хакеров корпоративных сетей полностью

–write.c–

int main

{

write(1,»EXAMPLE\n»,10);

}

–write.c–

Сохраним исходный текст в файле write.c, откомпилируем его компилятором GCC и выполним.

bash$ gcc write.c -o example —static

bash$ ./example

EXAMPLE

bash$

Все достаточно просто. Для того чтобы окончательно понять работу программы, воспользуемся утилитой gdb. У утилиты gdb больше возможностей, чем читатель может себе представить. Если он знает их все, то ему нужно сменить хобби. Для изучения примера достаточно основных возможностей утилиты gdb. Для начала откроем пример программы:

bash$ gdb ./example

GNU gdb 5.1

Copyright 2001 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public

License, and you are welcome to change it and/or distribute

copies of it under certain conditions.

Type “show copying” to see the conditions.

There is absolutely no warranty for GDB. Type “show

warranty” for details.

This GDB was configured as “i686-pc-linux-gnu”...

(gdb)

Может оказаться, что версия утилиты gdb читателя отличается от используемой в книге. Но это не имеет большого значения. Без всякого сомнения, используемые возможности утилиты gdb реализованы в версии утилиты читателя. Введем в ответ на приглашение утилиты команду disassemble main и исследуем выполняемый код программы в функции main, обратив особое внимание на участок кода, который вызывает функцию write. Команда disassemble выводит код функции на языке ассемблера используемого компьютера. Для нашего примера это Intel x86.

(gdb) disas main

Dump of assembler code for function main:

0x80481e0

: push %EBP

0x80481e1 : mov %ESP,%EBP

0x80481e3 : sub $0x8,%ESP

0x80481e6 : sub $0x4,%ESP

0x80481e9 : push $0x9

0x80481eb : push $0x808e248

0x80481f0 : push $0x1

0x80481f2 : call 0x804cc60 <__libc_write>

0x80481f7 : add $0x10,%ESP

0x80481fa : leave

0x80481fb : ret

End of assembler dump.

(gdb)

Далее будет исследован выполняемый код функции write. Параметры функции write записываются в стек в обратном порядке. Сначала командой push $0x9 в стек проталкивается величина 0x9 (символ $0x указывает на представление утилитой gdb выводимых величин в шестнадцатеричном виде), где 9 – длина строки «EXAMPLE\n». Далее в стек командой push $0x808e248 проталкивается адрес строки «EXAMPLE\n». Для просмотра содержимого области по этому адресу достаточно в ответ на приглашение gdb ввести команду утилиты: x/s 0x808e248. Заключительный шаг перед вызовом функции write состоит в записи в стек дескриптора файла. В данном случае это 1 – дескриптор стандартного вывода. После перечисленных действий вызывается функция write.

0x80481e9 : push $0x9

0x80481eb : push $0x808e248

0x80481f0 : push $0x1

0x80481f2
: call 0x804cc60 <__libc_write>

Для просмотра кода функции write в ответ на приглашение утилиты введем команду disas__libc_write . Получим следующее.

(gdb) disas __libc_write

Dump of assembler code for function __libc_write:

0x804cc60 <__libc_write>: push %EBX

0x804cc61 <__libc_write+1>: mov 0x10(%ESP,1),%EDX

0x804cc65 <__libc_write+5>: mov 0xc(%ESP,1),%ECX

0x804cc69 <__libc_write+9>: mov 0x8(%ESP,1),%EBX

0x804cc6d <__libc_write+13>: mov $0x4,%EAX

0x804cc72 <__libc_write+18>: int $0x80

0x804cc74 <__libc_write+20>: pop %EBX

0x804cc75 <__libc_write+21>: cmp $0xfffff001,%EAX

0x804cc7a <__libc_write+26>: jae 0x8052bb0 <__syscall_error>

0x804cc80 <__libc_write+32>: ret

End of assembler dump.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже