книги хакеры / журнал хакер / 091_Optimized
.pdf
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
|
||
P |
|
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
|
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
. |
|
|
|
|
|
.c |
|
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
|
||
|
|
|
|
-xcha |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
|
X |
|
|
|
|
|
|||
|
|
- |
|
|
|
|
|
d |
|
||
|
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
|
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
|||||
|
|
|
|
|
|
||||||
w |
|
|
|
|
|
|
|
|
|
||
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
|
-x cha |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
www.MilW0rm.com — хорошая копилка exploit'ов плюс сподручный инструментарий
завести обширную переписку — и можно быть в курсе дел, происходящих на всех континентах! Ведь силами одного человека отслеживать появление всех новых дыр просто нереально, разве что полностью посвятить свою жизнь уязвимостям.
Чем компилировать?
Чаще всего exploit'ы пишутся на Си/Си++, Perl, |
packet storm — немного exploit'ов, зато какой инструментарий! |
|
|
Python и PHP, реже — на всякой экзотике типа |
|
|
|
Ruby, причем тип языка указывается далеко не |
тельно. Но зачем?! |
в Linux и *BSD) и прочих системно-зависимых |
|
всегда, а о версии транслятора и ключах компи- |
Исключение составляют листинги, содер- |
фичей. Некоторые exploit'ы пишутся в расчете |
|
ляции остается только догадываться. Вот такая |
жащие в себе строку «This file is part of the |
наWindowsивместо«общепринятых»функций |
|
культурапрограммирования, скоторойнампри- |
Metasploit Framework» и являющиеся модулями |
типа fopen()/fclose() |
используют громоздкие |
ходится жить. |
Framework'а, без которого они, естественно, не |
API-вызовы CreateFile/CloseHandle. Откомпи- |
|
Ладно, Perl узнаетсяспервоговзглядапостроке |
запускаются. Присутствие такой строки необя- |
лировать такой exploit можно и под *nix'ом, но |
|
«#!/usr/bin/perl», идущейвпередилистинга. Если |
зательно, но сама структура модуля настолько |
для этого придется заменять API-вызовы на |
|
же ее нет — смотрим на следующее: |
характерна, что, увидев такую штуку один- |
соответствующие им Си-функции или syscall'ы. |
|
• присутствуют директивы в стиле «use IO:: |
единственный раз, будешь распознавать ее |
Самое неприятное состоит в том, что у Microsoft |
|
Socket;»; |
всегда. Например: milw0rm.com/exploits/1788. |
имеется свой собственный, особый взгляд на |
|
• точка с запятой ставится в конце каждой стро- |
С диалектами Си/Си++ все намного сложнее. |
интерфейс сокетов, и для переноса Windows- |
|
ки; |
Оченьчастослучаетсятак, чтопрограмму, напи- |
кода, работающего с сокетами, под *nix прихо- |
|
• тело функций и многострочечных циклов/опе- |
саннуюпододинкомпилятор, неудается(безпе- |
дится искать альтернативный *nix-exploit. Фор- |
|
раторов if заключено в фигурные скобки; |
ределок) откомпилировать ничем другим. Пос- |
мальным признаком форточной природы кода |
|
• отступ внутри тела роли не играет и часто от- |
ледняя версия компилятора далеко не всегда |
является наличие функции WSAStartup, кото- |
|
сутствует. |
оказывается самой лучшей. В особенности это |
рая в *nix-подобных системах и не ночевала. Но |
|
•многострочечныестроковыеконстантысоеди- |
касаетсяgcc,вядрокотороговноситсябольшое |
классическийСи —этотолькоцветочки.Самое |
|
няются через точку. |
количество изменений, зачастую не без ущерба |
страшное, как всегда, впереди. |
|
Выполнение всех этих условий свидетельствует |
для скорости и обратной совместимости. |
Приплюснутый Си — это настоящий кошмар. |
|
о том, что перед нами Perl. Язык Python внешне |
Первым делом необходимо определить: при- |
Компиляторы (и поставляемые вместе с ними |
|
похож на него, но содержит ряд принципиаль- |
плюснутыйэтоСииликлассический? Вотхарак- |
библиотеки) различаются просто колоссаль- |
|
ных отличий (и обычно предваряется строкой |
терные черты приплюснутого: |
но! Приходится иметь в своем распоряжении |
|
«#!/usr/bin/python», которой, впрочем, может и |
• объявление переменных по месту использова- |
целую артиллерию gcc различных версий, а в |
|
не быть): |
ния, а не в начале функции; |
рукавахдержатьвсякуюэкзотикутипаIntel C++, |
|
• присутствуют директивы в стиле «import |
• наличие таких ключевых слов, как «класс» и |
но и тогда будут встречаться программы, кото- |
|
socket», «import sys»; |
двух двоеточий «::»; |
рые упорно не хотят компилироваться! |
|
• точка с запятой в конце строки не ставится; |
• использование new для выделения памяти или |
Яркий тому пример |
— milw0rm.com/shell- |
• тело функций и многострочечных циклов опе- |
явное преобразование типа перед malloc() |
code/656 (прилагается к статье под именем |
|
раторов if не берется в скобки; |
• отсутствует printf, а весь ввод/вывод осущест- |
beta.cpp). Пропускаем его через gcc и полу- |
|
• отступ внутри тела функций, оператор if и цик- |
вляется операторами «<<» и «>>». |
чаем следующий список ошибок (не считая |
|
лов строго обязателен; |
Если хоть одно из этих условий выполняется, то |
варнингов): |
|
•многострочечныестроковыеконстантысоеди- |
программа явно написана на приплюснутом Си, |
|
|
няются, как в Си («<ENTER>»). |
в противном случае используется классичес- |
Список ошибок, выдаваемый компилятором gcc, при |
|
Выполнение всех этих условий — верный при- |
кий. Кстати говоря, Си/Си++ отличается от perl/ |
попытке трансляции файла beta.cpp |
|
знак Питона, который, как и Perl, портирован на |
python своими директивами «#include» и еще |
|
|
множество платформ и распространяется на |
тем, что символ «#» в нем никогда не использу- |
beta.cpp:34:21: windows.h: No such file or directory |
|
бесплатной основе. |
ется для оформления комментариев. |
beta.cpp: In function `int main(int, char**, char**)': |
|
Проблемы вызывает комплект поставки. Доста- |
В отличие от интерпретируемых языков, библи- |
beta.cpp:165: error: `stricmp' undeclared (first use this |
|
точночастохакерывыкладываютневесьexploit, |
отеки которых более или менее стандартизиро- |
function) |
|
а только его часть, и транслятор начинает ма- |
ваны, Си-компиляторывключаютвсебябольшое |
beta.cpp:185: error: `strnicmp' undeclared (first use this |
|
териться на отсутствующие включаемые фай- |
количество системно-зависимых библиотек, в |
function) |
|
лы/библиотеки. Такие exploit'ы следует сразу |
результатечегопрограммаможетвызыватьфун- |
beta.cpp:245: error: `isalnum' undeclared (first use this |
|
отправлять в топку, хотя при наличии большого |
кции, отсутствующие в нашем трансляторе, или |
function) |
|
количества свободного времени и некоторого |
использоватьспецифическиеособенностиконк- |
beta.cpp:250: error: `isprint' undeclared (first use this |
|
опыта работы с языком недостающие файлы |
ретнойверсииязыка.Впервуюочередь,этокаса- |
function) |
|
можно (теоретически) воссоздать и самостоя- |
ется сырых сокетов (по-разному реализованных |
beta.cpp:339: error: invalid conversion from `void*' to |
118 |
XÀÊÅÐ 07 /91/ 06 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
`char*'
beta.cpp:356: error: `O_BINARY' undeclared (first use this function)
beta.cpp:361: error: `lseek' undeclared (first use this function)
beta.cpp:377: error: invalid conversion from `void*' to `char*'
beta.cpp:384: error: `read' undeclared (first use this function)
beta.cpp:398: error: `close' undeclared (first use this Попытка компиляции файла beta.cpp и результат function)
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
Сошибкой34 всепонятно — программаусиленно косит под форточки, прихватив с собой файл <windows.h>, но тут же использует стандартные POSIX-вызовы: open() со странным флагом
O_BINARY, lseek(), read() и close(), которых ни в самом Windows, ни в одном из win32-компиля- торов никогда не существовало (см. ошибки
356, 361, 384 и 398). Убираем строку «#include <windows.h>», меняя ее на «#include <unistd. h>», и удаляем глупый флаг O_BINARY, поскольку по умолчанию файл уже является двоичным (узнать, какие заголовочные файлы соответствуют данной функции, можно из man'а, например, «man 2 open»). Чтобы избавиться от пре-
дупреждения «this file include <malloc.h> which is deprecated, use <stdlib.h> instead», удаляем и «#include <malloc.h>».
Ошибки 245 и 250 устраняются подключением их «родного» заголовочного файла, в котором они были объявлены «#include <ctype.h>» (см. «man isalnum»). А вот функций stricmp()
и strnicmp() в gcc действительно нет, однако они могут быть заменены на аналогичные им strcmp() и strncmp() даже без коррекции аргументов!
Ошибки 339 и 377 исправляются еще проще: достаточно взять строку «buffer = malloc(MAX_ BUFFER_SIZE)» и добавить явное преобразование типов, также называемое кастингом
«buffer = (char *)malloc(MAX_BUFFER_SIZE)».
Исправленныйвариантлежитвфайлеbeta-fixed. cpp и компилируется без всяких нареканий. Будем считать, что с идентификацией трансляторамыразобрались, иexploit откомпилировался нормально, но... это еще не конец, а только начало. Ведь программный листинг — это только оболочка, образно говоря, «тетива», а разящее острие — загадочный и таинственный shell-код, помещенный в строковый «иерогли-
фический» массив вроде «\x29\xc9\x83...\xe9\ xb0\xd9». Что делать, если он не работает или работает не так, как нам этого хочется?
Доработка напильником
Shell-код имеет сложную структуру и обычно состоит из нескольких частей. Например, exploit milw0rm.com/exploits/1075, приложен-
ный в файле 1075.с, использует целых 6 «иероглифических» массивов: dce_rpc_header1, tag_private, dce_rpc_header2, dce_rpc_header3, offsets, bind_shellcode. Первые пять — это слу-
жебные структуры, атакующие жертву, срывающие буферу крышу и передающие управление на bind_shellcode. Последний представляет
собой «чистый» shell-код, который может быть беспрепятственно заменен любым другим. На самом деле, тут все не так просто, и произвола хоть отбавляй. Как минимум, необходимо убедиться, что мы используем shell-код, совместимый с атакуемой системой, и точки входа у них совпадают. Часто (но не всегда) точка входа расположена в самом начале shell-кода, реже — в конце или в середине. Гораздо хуже, если exploit написан «пионером», и все блоки идут одним большим кусом, внутри которого присутствует и shell-код.
Чтобы определить положение дел, необходимо преобразовать «иероглифический» текст в двоичный файл и дизассемблировать его. Разыскивать соответствующий конвертор совершенно не обязательно. Проще переложить эту задачу на плечи компилятору Си, написав простенькую программку из нескольких строк.
Простейший конвертор для преобразования строковых констант в двоичный код
#include <stdio.h>
int main(void)
{
FILE *f;
if (f = fopen("shellcode", "wb")) fwrite(shellcode, sizeof(shellcode), 1, f);
exit(0);
}
Сам shell-код должен быть размещен в массиве, объявленном как «char shellcode[]» (см. прилагаемый файл hex2bin.c) и приведенным к синтаксису Си (то есть, если shell-код выдернут из perl'а, необходимо удалить точки в конце строковых констант). Компилируем наш импровизированный конвертор, запускаем его на выполнение — и тут же на диске образуется файл «shellcode», который можно загрузить в HTE, IDA Pro или любой другой дизассемблер повкусу, незабывая, конечно, переключитьего в 32-битный режим.
В данном случае мы получим следующий код:
Первые 16 байт shell-кода содержат осмысленный код расшифровщика
0000: |
29C9 |
sub ecx,ecx |
0002: |
83E9B0 |
sub ecx,-050 ;"P" |
0005: D9EE |
fldz |
0007: D97424F4 |
fstenv [esp][-000C] |
000B: 5B |
pop ebx |
000C: 81731319F50437 |
xor d,[ebx][00013], 03704F519 |
00000013: 83EBFC |
sub ebx,-004 ; "?" |
00000016: E2F4 |
loop 000C (1) |
Ага! Вполне типичный расшифровщик. Значит, точка входа в shell-код действительно находится в начале массива, и он может быть беспрепятственно заменен любым таким же. Если же вместо осмысленного кода нас встречает мусор, то нужно последовательно отступать на один байт до тех пор, пока мы не получим что-то удобоваримое.Естественно,дляэтогонеобходимознать ассемблер и хотя бы в общих чертах представлять себе устройство операционной системы.
Правильно спроектированный shell-код работает на всех версиях операционных систем, для которых он предназначен, однако в последнее времявсечащеичащеприходитсясталкиваться с «пионерством», которое привязано к фиксированным адресам и функционирует только под определенной сборкой Linux-ядра или заранее заданным сервис-паком, наложенным на
Windows.
*nix-подобные системы в этом плане менее изменчивы, и проблема «фиксированных адресов»здесьпрактическисведенананет.Обычно shell-код вызывает необходимые ему функции через системные вызовы, интерфейс с которыми обеспечивается прерыванием INT 80h или дальним вызовом по адресу 0007h:00000000h, что позволяет shell-коду функционировать под всей линейкой осей, для которых он предназначен. Тем не менее, определенные системные вызовы в различных версиях ядер реализованы неодинаково, что порождает проблемы совместимости. К счастью, базовый набор системных вызовов остается единым для всех осей, и грамотно спроектированный exploit поражает как Linux, так и BSD.
Заключение
Последние версии *nix'ов оснащены довольно мощными защитными механизмами: неисполняемым стеком, рандомизатором адресного пространства и т.д. Обычным exploit'ом такую штуку уже не пробить, а потому техника написания shell-кодов в ближайшем будущем обещает круто измениться, но прежде чем бросаться на неисполняемый стек, необходимо разобраться в существующих exploit'ах, что мы сейчас и попытались сделать. z
XÀÊÅÐ 07 /91/ 06 |
119 |