Шаблоны приложений ZMap

Перейти к содержанию полного руководства пользователя ZMap на русском языке.

[su_accordion]
[su_spoiler title=»Содержание статьи»]
Баннер захвата
Модуль Forge Socket
Создание зондов и выходных модулей

[/su_spoiler]
[/su_accordion]

Шаблоны приложений

ZMap предназначен для работы с большим количеством хостов, он находит те, которые отвечают положительно. Тем не менее, мы понимаем, что многие пользователи желают выполнить обработку на уровне приложений. Например, пользователи, которые выполняют сканирование TCP SYN на порту 80, хотят выполнить простой запрос, а те, кто сканирует порт 443, могут быть заинтересованы в применении соединения TLS Handshake.

Баннер захвата

Мы включили образец приложения, баннер захвата, который позволяет пользователям получать сообщения от исследования TCP-серверов. Баннер захвата подключается к серверам, необязательно посылает сообщение, и выводит первое сообщение, полученное от сервера. Этот инструмент может быть использован для извлечения баннеров, например, HTTP ответов на конкретные команды, подсказки логина и пароля или строки SSH сервера.

Этот пример находит 1000 серверов на 80 порту и отправляет простой запрос каждому, сохраняя их базовые ответы на http-banners.out

$ zmap -p 80 -N 1000 -B 10M -o - | ./banner-grab-tcp -p 80 -c 500 -d ./http-req > out

Чтобы получить больше деталей, используйте banner-grab, смотрите информационный файл на examples/banner-grab.

Важно!

ZMap и баннер захвата могут оказать существенное влияние на производительность и точность друг друга, если выполняются одновременно (как в приведенном выше примере). Убедитесь в том, что ZMap не подавляет соединения баннера захвата, иначе последний будет отставать от чтения стандартных потоков, призывая ZMap блокировать их. Мы рекомендуем использовать более низкую скорость сканирования с ZMap и увеличивать конкурентность tcp баннера захвата до 3000. Обратите внимание, что больше 1000 одновременных соединений требуют использования ulimit –SHn и ulimit -HHn 100000.

Эти параметры, конечно, будут зависеть от производительности вашего сервера и скорости; мы рекомендуем разработчикам экспериментировать с небольшими образцами перед запуском большого сканирования.

Модуль Forge Socket

Мы также включили форму баннера захвата, Forge Socket, которая повторно использует SYN-ACK запросы от сервера для соединения с баннером. В banner-grab-tcp ZMap отправляет SYN на каждый сервер и исследует ответы сервера с помощью SYN+ACK.

Ядро ZMap получает их и отправляет RST, так как активных соединений с этим пакетом нет. Программа баннера захвата должна затем создать новое TCP соединение для того же сервера для извлечения данных из него.

В forge-socket используется модуль ядра с таким же именем, благодаря чему создается связь с произвольными параметрами TCP. Это позволяет подавлять RST пакет ядра, вместо того, чтобы создать сокет, который будет повторно использовать параметры SYN + ACK для отправки и получения данных.

Чтобы использовать Forge Socket, вам понадобится модуль ядра из github. Вам необходимо исплльзовать git [email protected]:ewust/forge_socket.git в директории ZMap, после чего перейти в каталог сокета и запустить forge-socket. Источник модуля ядра insmod forge_socket.ko.

Не забудьте также, что ядро не должно отправлять RST пакеты. Самый простой способ, чтобы отключить систему RST пакетов, использовать iptables -A OUTPUT -p tcp -m tcp --tcp-flgas RST,RST RST,RST -j DROP, также можно добавить дополнительно --dport X, чтобы ограничить сканируемый порт. Чтобы отменить это после завершения сканирования, необходимо запустить ptables -D OUTPUT -p tcp -m tcp --tcp-flags RST,RST RST,RST -j DROP.

Теперь вы можете создать пример программы forge-socket ZMap. Чтобы его запустить, нужно использовать extended_file выходного модуля ZMap:

$ zmap -p 80 -N 1000 -B 10M -O extended_file -o - | \
    ./forge-socket -c 500 -d ./http-req > ./http-banners.out

Больше информации читайте в examples/forge-socket.

Создание зондов и выходных модулей

ZMap может поддерживать различные типы сканирования с помощью исследовательских модулей и давать дополнительные виды результатов с помощью модулей вывода. Зарегистрированные зонды и модули вывода могут быть перечислены через интерфейс командной строки:

—list-probe-modules  – список установленных зондов;

—list-output-modules  – список установленных выходных модулей.

Выходные модули

Выход ZMap и пост-обработка может быть расширена за счет внедрения и регистрации выходных модулей. Выходные модули получают ответ для каждого принятого пакета. В то время как стандартные модули обеспечивают простой выход, эти модули способны выполнять дополнительную пост-обработку (например, отслеживание дубликатов или вывод чисел в терминах AS вместо IP-адреса).

Выходные модули создаются путем добавления новой структуры output_module и ее регистрации на output_modules.c:

typedef struct output_module {
	const            char *name;      // how is output module referenced in the CLI
	unsigned         update_interval; // how often is update called in seconds
	output_init_cb   init;            // called at scanner initialization
	output_update_cb start;           // called at the beginning of scanner
	output_update_cb update;          // called every update_interval seconds
	output_update_cb close;           // called at scanner termination
	output_packet_cb process_ip;      // called when a response is received
	const            char *helptext;  // Printed when --list-output-modules is called
} output_module_t;

Выходной модуль должен иметь имя, которое указывается в командной строке и обеспечивает success_ip а также other_ip ответ.

Процесс обратного вызова активируется для каждого ответного пакета, который принимается и передается через выходной фильтр с помощью текущего зонда. Ответ может быть успешным или нет (например, это может быть TCP RST). Эти обратные вызовы должны определить функции, которые соответствуют output_packet_cb.

int (*output_packet_cb) (
	ipaddr_n_t saddr,               // IP address of scanned host in network-order
	ipaddr_n_t daddr,               // destination IP address in network-order
	const      char* response_type, // send-module classification of packet
	int        is_repeat,           // {0: first response from host, 1: subsequent responses}
	int        in_cooldown,         // {0: not in cooldown state, 1: scanner in cooldown state}
	const      u_char* packet,      // pointer to struct iphdr of IP packet
	size_t     packet_len           // length of packet in bytes
);

Выходной модуль также может регистрировать обратные вызовы, которые будут выполняться при инициализации сканера (такие задачи, как открытие выходного файла), начинать сканирование (например, запись блокируемых адресов), обновлять метаданные во время сканирования или закрывать все открытые описания файлов. Обратные вызовы предоставляются с полным доступом к конфигурации сканирования и имеют следующий вид, который определяется в output_modules.h.

int (*output_update_cb)(struct state_conf*, struct state_send*, struct state_recv*);

Пример доступен по ссылке src/output_modules/module_csv.c

Зонды

Пакеты создаются с помощью зондов, благодаря которым возможно удаленное создание пакетов и классификация ответов. ZMap поставляется с двумя модулями сканирования по умолчанию: tcp_synscan и icmp_echoscan. По умолчанию ZMap использует tcp_synscan, который посылает TCP SYN пакеты и классифицирует ответы от каждого хоста как открытые (SYN+ACK) или закрытые (RST).

ZMap также позволяет разработчикам создавать свои собственные исследовательские модули для сканирования с ZMap, используя следующие API.

Каждый тип сканирования осуществляется путем разработки и регистрации необходимых ответов через структуру send_module_t:

typedef struct probe_module {
	const char               *name;             // how scan is invoked on command-line
	size_t                   packet_length;     // how long is probe packet (must be static size)
	const char               *pcap_filter;      // PCAP filter for collecting responses
	size_t                   pcap_snaplen;      // maximum number of bytes for libpcap to capture
	uint8_t                  port_args;         // set to 1 if ZMap requires a --target-port be
	                                            // specified by the user
	probe_global_init_cb     global_initialize; // called once at scanner initialization
	probe_thread_init_cb     thread_initialize; // called once for each thread packet buffer
	probe_make_packet_cb     make_packet;       // called once per host to update packet
	probe_validate_packet_cb validate_packet;   // called once per received packet,
	                                            // return 0 if packet is invalid,
	                                            // non-zero otherwise.
	probe_print_packet_cb    print_packet;      // called per packet if in dry-run mode
	probe_classify_packet_cb process_packet;    // called by receiver to classify response
	probe_close_cb           close;             // called at scanner termination
	fielddef_t               *fields            // Definitions of the fields specific to this module
	int                      numfields          // Number of fields
} probe_module_t;

При инициализации сканера global_initialize вызывается один раз и может быть использован для выполнения любой необходимой конфигурации. Тем не менее, global_initialize не имеет доступа к буферу пакета. Вместо этого thread_initialize вызывается при инициализации каждого запроса и обеспечивает доступ к буферу, который будет использоваться для создания зондов.

Этот обратный вызов должен быть использован для построения пакета хоста таким образом, чтобы только определенные значения (например, хост назначения и контрольная сумма) обновлялись для каждого хоста. Например, заголовок Ethernet не будет меняться между заголовками и, следовательно, может быть определен заранее, чтобы уменьшить расход времени в процессе сканирования.

Make_packet обратного вызова вызывается для каждого хоста, который сканируется, чтобы обновлять конкретные значения хоста. Исследовательский модуль отвечает за размещение большей части проверяемой строки таким образом, что, когда действительный ответ возвращается сервером, зонд может проверить, есть ли он.

Например, для TCP SYN сканирования tcp_synscan зонд может использовать исходный TCP-порт и порядковый номер для хранения строки проверки. Пакеты (SYN + ACKs) будут содержать ожидаемые значения (в пункте назначения) и номер подтверждения.

int make_packet(
	void *packetbuf,                          // packet buffer
	ipaddr_n_t src_ip,                        // source IP in network-order
	ipaddr_n_t    dst_ip, // destination IP in network-order
	uint32_t *validation,                     // validation string to place in probe
	int probe_num                             // if sending multiple probes per host,
	                                          // this will be which probe number for this
	                                          // host we are currently sending
);

Модули сканирования должны также определить pcap_filter, validate_packet, и process_packet. Только пакеты, которые соответствуют PCAP фильтру, будут рассмотрены сканером. Например, в случае TCP SYN сканирования, мы хотим исследовать TCP SYN / ACK или TCP RST-пакеты и будем использовать фильтр, аналогичный tcp && tcp[13] & 4 != 0 || tcp[13] == 18.

Функция validate_packet будет вызываться для каждого пакета, который соответствует этому PCAP фильтру. Если проверка возвращает ненулевое значение, то функция process_packet будет заполнять филдсет с использованием полей, определенных в данных пакета. Например, следующий код обрабатывает пакет для TCP SynScan зонда:

void synscan_process_packet(const u_char *packet, uint32_t len, fieldset_t *fs)
{
	struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)];
	struct tcphdr *tcp = (struct tcphdr*)((char *)ip_hdr
	+ (sizeof(struct iphdr)));
	fs_add_uint64(fs, "sport", (uint64_t) ntohs(tcp->source));
	fs_add_uint64(fs, "dport", (uint64_t) ntohs(tcp->dest));
	fs_add_uint64(fs, "seqnum", (uint64_t) ntohl(tcp->seq));
	fs_add_uint64(fs, "acknum", (uint64_t) ntohl(tcp->ack_seq));
	fs_add_uint64(fs, "window", (uint64_t) ntohs(tcp->window));
	if (tcp->rst) { // RST packet
	fs_add_string(fs, "classification", (char*) "rst", 0);
	fs_add_uint64(fs, "success", 0);
	} else { // SYNACK packet
	fs_add_string(fs, "classification", (char*) "synack", 0);
	fs_add_uint64(fs, "success", 1);
        }
}

Перейти к содержанию полного руководства пользователя ZMap на русском языке.

Перевод: Виктория Верстлер

Источник: https://zmap.io/documentation.html

Оставьте комментарий