|
| ||||||||||||
| ||||||||||||
|
2005 г.
Создание сниффера на PERL под Windows, используя модуль Win32::NetPacketПрограммы и модули, необходимые для этого, следующие.
Основные методы Win32::NetPacket. new$nic = Win32:: NetPacket- >new ([option = > value]); Этот метод открывает network interface card (nic – сетевой адаптер), создает объект Win32::NetPacket для этого адаптера и возвращает ссылку на этот объект. При возникновении ошибки возвращает неопределенное значение (undef), сообщение хранится в переменной $@. Опции передаются в хеш, используя ключи и значения парами. Возможные опции:
SetUserBuffer$nic->SetUserBuffer($Buffer, $size); $Buffer - буфер, определяемый пользователем, который будет содержать захваченные данные и $size - его размер. Этот метод ничего не возвращает. SetHwFilter$success = $nic->SetHwFilter(CONSTANT); Устанавливает аппаратный фильтр на входящие пакеты. Если операция была выполнена успешно метод возвращает истинное значение. Константы, которые определяют фильтры:
NDIS_PACKET_TYPE_DIRECTED
NDIS_PACKET_TYPE_MULTICAST
NDIS_PACKET_TYPE_ALL_MULTICAST
NDIS_PACKET_TYPE_BROADCAST
NDIS_PACKET_TYPE_SOURCE_ROUTING
NDIS_PACKET_TYPE_PROMISCUOUS
NDIS_PACKET_TYPE_SMT
NDIS_PACKET_TYPE_ALL_LOCAL
NDIS_PACKET_TYPE_MAC_FRAME
NDIS_PACKET_TYPE_FUNCTIONAL
NDIS_PACKET_TYPE_ALL_FUNCTIONAL
NDIS_PACKET_TYPE_GROUP
SetReadTimeout$success = $nic->SetReadTimeout($timeout); Этот метод устанавливает значение времени ожидания (таймаут) чтения, связанного с $nic адаптером. $timeout содержит время в миллисекундах, после которых ReceivePacket() возвратит значение (даже, если драйвером не было захвачено ни одного пакета). Установка таймаута в 0 - отмена таймаута, то есть ReceivePacket() никогда не возвратит данные, если не придет хотя бы один пакет. Таймаут равный -1 заставляет метод ReceivePacket() возвращать значение немедленно. Этот метод также работает, если адаптер работает в статистическом режиме, и может использоваться, чтобы установить интервал времени между двумя статистическими сообщениями. SetMinToCopy$success = $nic->SetMinToCopy($nbytes) Этот метод может использоваться, чтобы определить минимальное количество данных в буфере, которое заставит драйвер реализовать чтение (т.е. метод ReceivePacket() ). $nbytes определяет это значение в байтах. Этот метод реализован только в Windows NT/2000/XP. Драйвер для Windows 95/98/ME не поддерживает эту возможность, поэтому этот вызов осуществлен под эти системы только для совместимости. ReceivePacket$BytesReceived = $nic->ReceivePacket(); Этот метод выполняет захват множества пакетов. Возвращает длину части буфера, содержащую достоверные данные. Число пакетов, полученных этим методом переменно. Это зависит от количества пакетов, фактически сохраненных в буфере драйвера, от размера этих пакетов и от размера буфера, связанного с $nic. Можно установить таймаут на запросы чтения с помощью метода SetReadTimeout(). В этом случае метод возвратит значение, даже если пакеты не были захвачены, если время ожидания, установленное этим методом истекло. Формат, используемый драйвером, чтобы послать пакеты приложению следующий:
Пакет #1 - > --------- ----- bpf_hdr структура ------
| Bpf_hdr | --- > | tv_sec l = int |
--------- | tv_usec l = int |
| Данные | | bh_caplen I = unsigned int |
--------- | bh_datalen I = unsigned int |
| Выравнивание | | bh_hdrlen S = unsigned short|
Пакет #2 - > --------- ------------------------------
| Bpf_hdr |
---------
| Данные |
---------
| Выравнивание |
---------
... И т.д
Каждый пакет имеет заголовок, находящийся в структуре bpf_hdr, которая определяет ее длину и вмещает ее временной штамп (timestamp). Поле выравнивание используется для выравнивания данных в буфере по границе слова. Структура Bpf_hdr имеет следующие поля:
Например, можно получить значения первого заголовка буфера пользователя $buffer: ($tv_sec, $tv_usec, $caplen, $datalen, $hdrlen)=unpack ‘llIIS’, $buffer; и затем извлечь первый пакет из этого буфера: my $packet = substr $buffer, 0, $datalen; GetStats($packets_received, $packets_lost) = $nic->GetStats(); В контексте списка возвращает число пакетов, которые были получены адаптером, начиная с того времени, с которого он был открыт и количество пакетов, полученных адаптером. Пакет отбрасывается, когда пользовательское приложение не готово получить его или буфер, связанный с адаптером полон. GetInfo($name, $description, $type, $speed, $ip, $mask) = $nic->GetInfo(); В контексте списка возвращает: название, описание, тип, скорость в битах в секунду, IP адрес и сетевую маску $nic адаптера. Используя вышеперечисленные методы, можно написать такую программу.
use Win32::NetPacket qw/:ndis/;
use constant SizeOfInt => 4;
my $nic = Win32::NetPacket->new(
driver_buffer_size => 512*1024,
read_timeout => 0,
min_to_copy => 8*1024,
) or die $@;
$nic->SetHwFilter(NDIS_PACKET_TYPE_PROMISCUOUS);
my $Buff;
$nic->SetUserBuffer($Buff, 128*1024);
my $BytesReceived = $nic->ReceivePacket();
my $offset = 0;
while($offset < $BytesReceived) {
my ($tv_sec, $tv_usec, $caplen, $datalen, $hdrlen)=unpack 'llIIS', substr $Buff, $offset;
printf "\nPacket length, captured portion: %ld, %ld\n", $datalen, $caplen;
$offset += $hdrlen;
my $data = substr $Buff, $offset, $datalen; # извлекаем датаграмму
my $i;
print map { ++$i % 16 ? "$_ " : "$_\n" } @mas=unpack( 'H2' x length( $data ), $data ),
length( $data ) % 16 ? "\n" : '';
$offset = (($offset+$caplen)+(SizeOfInt-1)) & ~(SizeOfInt-1);
}
Что делать с массивом @mas, содержащим байты датаграммы, каждый решит по своему, будь то хакер или программист. |
|
CITForum © 1997–2025