книги хакеры / Защита_от_взлома_сокеты,_эксплойты,_shell_код_Фостер_Дж_
.pdf
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
|
C |
|
E |
|
|
|
|
|
|
|
C |
|
E |
|
|
|
||||||
|
|
X |
|
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
||||||
|
- |
|
|
|
|
|
d |
|
|
|
- |
|
|
|
|
|
d |
|
||||||
|
F |
|
|
|
|
|
|
|
i |
|
|
|
F |
|
|
|
|
|
|
|
i |
|
||
|
|
|
|
|
|
|
|
t |
|
|
|
|
|
|
|
|
|
|
t |
|
||||
P |
D |
|
|
|
|
|
|
|
|
o |
|
P |
D |
|
|
|
|
|
|
|
|
o |
||
|
|
|
|
NOW! |
r |
|
|
|
|
|
NOW! |
r |
||||||||||||
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
|
BUY |
|
|
||||||||
|
|
|
|
to |
|
|
716 Глава 14. Создание инструмента для проверки уязвимости Web приложения |
|
|
|
|
to |
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
m |
|
w |
|
|
|
|
|
|
|
|
|
m |
||
w Click |
|
|
|
|
|
|
o |
|
w Click |
|
|
|
|
|
|
o |
||||||||
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
||
|
. |
|
|
|
|
|
|
.c |
|
|
|
. |
|
|
|
|
|
|
.c |
|
||||
|
|
p |
df |
|
|
|
|
e |
|
|
|
|
p |
df |
|
|
|
|
e |
|
||||
|
|
|
|
|
g |
|
|
|
|
|
|
|
|
|
g |
|
|
|
||||||
|
|
|
|
|
n |
|
|
|
|
|
|
|
|
|
|
n |
|
|
|
|
||||
|
|
|
|
-xcha |
|
|
|
|
|
В строках 86–196 определена функция doreq(). Она отвечает за установление-x cha |
|
|
|
|
|
соединения и передачу запроса со строкой атаки. В строках 98–156 происходит создание сокета и работа с ним. Подробнее о сокетах см. главу 3, а сейчас достаточно знать, что на stdout выводится сообщение, если при работе с сокетом произошла ошибка. Кроме того, в этом случае функция возвращает false.
После того как соединение установлено и тест проведен, полученный ответ анализируется на предмет наличия уязвимости. В строках 161–191 мы проверяем, получен ли ответ «200 OK» или указанный в сигнатуре атаки.
В строках 198–278 определена функция check(). Она смотрит, есть ли в пути, заданном в сигнатуре, указание на то, что нужно просматривать каталоги административных или CGI-программ. Если нет, то заданный путь без изменения добавляется к запросу, передаваемому doreq().
В строках 221–227 проверяется, есть ли в заданном пути подстрока @CGIDIRS. Если есть, поднимается флажок iscgi, и тогда в строках 239–275 тест выполняется для каждого из каталогов, перечисленных в массиве CGIDIRS, или пока не будет получен положительный результат. Аналогично обрабатывается подстрока @ADMINDIRS, åñëè @CGIDIRS отсутствует.
В строках 280–283 определена функция resolve(). Она определяет IP-адрес, соответствующий указанному в командной строке имени хоста. Если поиск завершился успешно, то функция возвращает true, а в параметр addr записывается найденный IP-адрес.
В строках 305–317 определена функция usage(). Она вызывается, если в командной строке задано недостаточное число аргументов, и просто печатает справку о порядке запуска.
В строке 320 начинается функция main(). Именно в ней реализована общая логика программы.
В строках 332 и 333 обнуляется структура WSADATA, а затем вызывается функция WSAStartup(), которая загружает и инициализирует библиотеку ws2.dll. Если инициализация завершилась с ошибкой, печатается сообщение и программа завершается с кодом 1.
В строках 339–370 обрабатываются переданные программе аргументы. В строке 340 проверяется их число. Если аргументов недостаточно, печатается справка о порядке вызова. В строке 346 имя хоста преобразуется в IP-адрес. В строке 353 обрабатывается номер порта; если он не задан, по умолчанию предполагается порт 80. Аналогично обрабатываются параметры, определяющие степень подробности вывода и размер буфера. Перед тем как продолжить, программа печатает параметры, с которыми будет работать.
В строке 373 внутренние структуры заполняются информацией, прочитанной из файла DB_FILENAME (по умолчанию scan_database.db).
В строках 380–395 в цикле для каждой описанной в базе уязвимости вызывается функция check(), которая проверяет ее наличие на целевой машине.
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
|
C |
|
E |
|
|
|
|
|
|
C |
|
E |
|
|
|
||||||
|
|
X |
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
||||||
|
- |
|
|
|
|
|
d |
|
|
- |
|
|
|
|
|
d |
|
||||||
|
F |
|
|
|
|
|
|
|
t |
|
|
F |
|
|
|
|
|
|
|
t |
|
||
|
D |
|
|
|
|
|
|
|
|
i |
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
|
|
|
|
|
|
|
|
|
r |
||||
P |
|
|
|
|
|
NOW! |
o |
P |
|
|
|
|
|
NOW! |
o |
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
BUY |
|
|
||||||||
|
|
|
|
to |
|
|
|
|
|
|
Углубленный анализ 717 |
|
to |
|
|
|
|
|
|
||||
w Click |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
m |
w Click |
|
|
|
|
|
|
|
m |
|||||||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
||
|
w |
|
|
|
|
|
|
|
|
o |
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
g |
.c |
|
|
. |
|
|
|
|
g |
.c |
|
||||||
|
|
p |
|
|
|
|
|
|
|
|
|
p |
|
-x cha |
|
|
|
||||||
|
|
|
|
-xchÅñëèa |
check() вернула true и поднят флажок output, то вызывается функция |
|
|
e |
|
||||||||||||||
|
|
|
df |
|
|
n |
e |
|
|
|
|
df |
|
|
n |
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isvuln(), которая печатает информацию об уязвимости. Кроме того, вызывается функция twiddle(), печатающая сообщение о том, как далеко программа продвинулась.
Âстроке 397 программа извещает пользователя о завершении сканирования.
Âстроке 399 вызывается функция WSACleanup(), которая освобождает ресурсы, после чего программа выходит с кодом 0.
Разбор базы данных
Чтобы успешно разрабатывать хакерские программы, нужно хорошо понимать, какие действия необходимы для выполнения сканирования. В частности, в такой программе обязательно должны быть средства для разбора данных о сигнатурах уязвимостей. Мы реализовали такой механизм в классах
VulnDB è VulnDBEntry.
Класс VulnDB читает файл, удаляет лишние пробелы в начале и конце строки, пропускает строки, содержащие только комментарий, а оставшиеся передает для обработки классу VulnDBEntry.
1 |
/* |
|
2 |
* VulnDB.cpp |
|
3 |
* |
|
4 |
* |
|
5 |
* |
|
6 |
*/ |
|
7 |
|
|
8 |
#include <windows.h> |
|
9 |
#include <stdio.h> |
|
10 |
#include "VulnDB.h" |
|
11 |
|
|
12 |
#define VULNDB_BUF_SIZE |
0x0400 |
13 |
#define VULNDB_COMMENT |
'#' |
14 |
|
|
15/*
16* strtrim()
17*
18*
19*/
20static
21char *strtrim(char *sin, char *sout)
22{
23int len = 0;
24int idxl = 0;
25int idxt = 0;
26
27 len = strlen(sin);
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
|
C |
|
E |
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||||
|
|
X |
|
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
|||||
|
- |
|
|
|
|
d |
|
|
|
- |
|
|
|
|
|
d |
|
||||||
|
F |
|
|
|
|
|
|
t |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
||
|
D |
|
|
|
|
|
|
|
i |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
|
|
|
|
|
|
|
|
|
|
r |
||||
P |
|
|
|
|
|
NOW! |
o |
|
P |
|
|
|
|
|
NOW! |
o |
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
|
BUY |
|
|
|||||||
|
|
|
|
to |
|
|
|
|
|
Углубленный анализ |
719 |
|
to |
|
|
|
|
|
|
||||
w Click |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
m |
|
w Click |
|
|
|
|
|
|
|
m |
|||||||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
||
|
w |
|
|
|
|
|
|
|
o |
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
g |
.c |
|
|
|
. |
|
|
|
|
g |
.c |
|
|||||
|
|
p |
|
|
|
|
|
|
|
|
|
|
p |
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
e |
|
|
|
|
|
df-x chan |
e |
|
||||||||
|
|
|
df-xchan77 */ |
|
|
|
|
|
|
|
|
78 |
VulnDB::VulnDB() |
79 |
{ |
80 |
} |
81 |
|
82/*
83* ~VulnDB()
84*
85*
86*/
87VulnDB::~VulnDB()
88{
89VulnDBEntry *vde = NULL;
90 |
int |
idx = 0; |
91 |
|
|
92for(idx=0; idx < m_vec.size(); ++idx)
93{
94 |
vde |
= m_vec[idx]; |
95delete vde;
96m_vec[idx] = NULL;
97}
98
99m_vec.clear();
100}
101
102/*
103* Init()
104*
105*
106*/
107bool VulnDB::Init(string filename)
108{
109VulnDBEntry *vdbe = NULL;
110 |
FILE |
*fptr = NULL; |
111 |
char |
tmp[VULNDB_BUF_SIZE]; |
112 |
char |
buf[VULNDB_BUF_SIZE]; |
113 |
bool |
ret = 0; |
114 |
|
|
115fptr = fopen(filename.c_str(), "r");
116if(fptr == NULL)
117{
118return(false);
119}
120
121// для каждой строке в файле, кроме комментариев:
122// разобрать
123// сохранить в списке узлов
124// сохранить в списке
125