Форум: "Сети";
Текущий архив: 2005.06.06;
Скачать: [xml.tar.bz2];
ВнизСниффер Найти похожие ветки
← →
JaoDa (2005-02-04 14:54) [0]У кого-нибудь есть сорсы сниффера под Win XP или пример работы с
библиотекой Winpcap переложенный на Delphi?
зы: у меня есть под 98-ую, которые работают с packed32.dll, но в XP они, увы, не пахают :/
← →
Rouse_ © (2005-02-07 12:03) [1]Вот тебе без всяких packed32.dll, но для W2000 и выше:
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Unit Name : uMain
// * Purpose : Демонстрационный пример сниффера.
// * Author : Александр (Rouse_) Багель
// * Version : 1.00
// ****************************************************************************
//
// Особая благодарность TrefptYc и группе Машина Времени,
// за оказанную моральную поддержку, в процессе написания данного примера :)
//
unit uMain;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WinSock;
const
MAX_PACKET_SIZE = $10000; // 2^16
SIO_RCVALL = $98000001;
IP_HDRINCL = 16;
WSA_VER = $202;
MAX_ADAPTER_NAME_LENGTH = 256;
MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
MAX_ADAPTER_ADDRESS_LENGTH = 8;
IPHelper = "iphlpapi.dll";
resourcestring
LOG_STR_0 = "==============================================================================" + sLineBreak;
LOG_STR_1 = "Packet ID: %-5d TTL: %d" + sLineBreak;
LOG_STR_2 = "Packet size: %-5d bytes type: %s" + sLineBreak;
LOG_STR_3 = "Source IP : %15s: %d" + sLineBreak;
LOG_STR_4 = "Destination IP : %15s: %d" + sLineBreak;
LOG_STR_5 = "------------------------------ Packet dump -----------------------------------" + sLineBreak;
type
USHORT = WORD;
ULONG = DWORD;
time_t = Longint;
// ip заголовок
TIPHeader = packed record
iph_verlen: UCHAR; // версия и длина заголовка
iph_tos: UCHAR; // тип сервиса
iph_length: USHORT; // длина всего пакета
iph_id: USHORT; // Идентификация
iph_offset: USHORT; // флаги и смещения
iph_ttl: UCHAR; // время жизни пакета
iph_protocol: UCHAR; // протокол
iph_xsum: USHORT; // контрольная сумма
iph_src: ULONG; // IP-адрес отправителя
iph_dest: ULONG; // IP-адрес назначения
end;
PIPHeader = ^TIPHeader;
// tcp заголовок
TTCPHeader = packed record
sourcePort: USHORT; // порт отправителя
destinationPort: USHORT; // порт назначения
sequenceNumber: ULONG; // номер последовательности
acknowledgeNumber: ULONG; // номер подтверждения
dataoffset: UCHAR; // смещение на область данных
flags: UCHAR; // флаги
windows: USHORT; // размер окна
checksum: USHORT; // контрольная сумма
urgentPointer: USHORT; // срочность
end;
PTCPHeader = ^TTCPHeader;
// udp заголовок
TUDPHeader = packed record
sourcePort: USHORT; // порт отправителя
destinationPort: USHORT; // порт назначения
len: USHORT; // длина пакета
checksum: USHORT; // контрольная сумма
end;
PUDPHeader = ^TUDPHeader;
// Структуры для выполнения GetAdaptersInfo
PIP_MASK_STRING = ^IP_MASK_STRING;
IP_ADDRESS_STRING = record
S: array [0..15] of Char;
end;
IP_MASK_STRING = IP_ADDRESS_STRING;
PIP_ADDR_STRING = ^IP_ADDR_STRING;
IP_ADDR_STRING = record
Next: PIP_ADDR_STRING;
IpAddress: IP_ADDRESS_STRING;
IpMask: IP_MASK_STRING;
Context: DWORD;
end;
PIP_ADAPTER_INFO = ^IP_ADAPTER_INFO;
IP_ADAPTER_INFO = record
Next: PIP_ADAPTER_INFO;
ComboIndex: DWORD;
AdapterName: array [0..MAX_ADAPTER_NAME_LENGTH + 3] of Char;
Description: array [0..MAX_ADAPTER_DESCRIPTION_LENGTH + 3] of Char;
AddressLength: UINT;
Address: array [0..MAX_ADAPTER_ADDRESS_LENGTH - 1] of BYTE;
Index: DWORD;
Type_: UINT;
DhcpEnabled: UINT;
CurrentIpAddress: PIP_ADDR_STRING;
IpAddressList: IP_ADDR_STRING;
GatewayList: IP_ADDR_STRING;
DhcpServer: IP_ADDR_STRING;
HaveWins: BOOL;
PrimaryWinsServer: IP_ADDR_STRING;
SecondaryWinsServer: IP_ADDR_STRING;
LeaseObtained: time_t;
LeaseExpires: time_t;
end;
// Поток сниффера
TSnifferThread = class(TThread)
private
WSA: TWSAData;
hSocket: TSocket;
Addr_in: sockaddr_in;
Packet: array[0..MAX_PACKET_SIZE - 1] of Byte;
LogData: String;
procedure ShowPacket;
protected
function InitSocket: Boolean; virtual;
procedure DeInitSocket(const ExitCode: Integer); virtual;
procedure Execute; override;
procedure ParcePacket(const PacketSize: Word); virtual;
public
Host: String;
end;
TfrmMain = class(TForm)
btnStartStop: TButton;
memReport: TMemo;
cbInterfaces: TComboBox;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure btnStartStopClick(Sender: TObject);
private
TotalPacketCount: Integer;
FSnifferThread: TSnifferThread;
procedure ReadLanInterfaces;
end;
// При помощи данной функции мы определим наличие сетевых интерфейсов
// на локальном компьютере и информацию о них
function GetAdaptersInfo(pAdapterInfo: PIP_ADAPTER_INFO;
var pOutBufLen: ULONG): DWORD; stdcall; external IPHelper;
const
// Размеры используемых структур
IPHeaderSize = SizeOf(TIPHeader);
TCPHeaderSize = SizeOf(TTCPHeader);
UDPHeaderSize = SizeOf(TUDPHeader);
var
frmMain: TfrmMain;
implementation
← →
Rouse_ © (2005-02-07 12:06) [2]
{$R *.dfm}
{ TSnifferThread }
// Инициализация слушающего сокета
function TSnifferThread.InitSocket: Boolean;
var
PromiscuousMode, HeaderInclude: Integer;
begin
// инициализируем WinSock
Result := WSAStartup(WSA_VER, WSA) = NOERROR;
if not Result then
begin
LogData := "Ошибка: " + SysErrorMessage(WSAGetLastError);
Synchronize(ShowPacket);
Exit;
end;
// создаем сокет
hSocket := socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if hSocket = INVALID_SOCKET then
begin
DeInitSocket(WSAGetLastError);
Exit;
end;
FillChar(Addr_in, SizeOf(sockaddr_in), 0);
Addr_in.sin_family:= AF_INET;
// указываем за каким интерфейсом будем следить
Addr_in.sin_addr.s_addr := inet_addr(PChar(Host));
// связываем сокет с локальным адресом
if bind(hSocket, Addr_in, SizeOf(sockaddr_in)) <> 0 then
begin
DeInitSocket(WSAGetLastError);
Exit;
end;
// Переключаем интерфейс на прием всех пакетов проходящих через интерфейс - promiscuous mode.
PromiscuousMode := 1;
if ioctlsocket(hSocket, SIO_RCVALL, PromiscuousMode) <> 0 then
begin
DeInitSocket(WSAGetLastError);
Exit;
end;
Result := True;
end;
// Завершение работы сокета
procedure TSnifferThread.DeInitSocket(const ExitCode: Integer);
begin
// Если была ошибка - выводим ее
if ExitCode <> 0 then
begin
LogData := "Ошибка: " + SysErrorMessage(ExitCode);
Synchronize(ShowPacket);
end;
// Закрываем сокет
if hSocket <> INVALID_SOCKET then closesocket(hSocket);
// Деинициализируем WinSock
WSACleanup;
end;
// Рабочая процедура потока сниффера
procedure TSnifferThread.Execute;
var
PacketSize: Integer;
begin
// Производим инициализацию
if InitSocket then
try
// Крутим поток до упора
while not Terminated do
begin
// Ждем получения пакета (блокирующий режим)
PacketSize := recv(hSocket, Packet, MAX_PACKET_SIZE, 0);
// Если есть данные - производим их разбор
if PacketSize > SizeOf(TIPHeader) then ParcePacket(PacketSize);
end;
finally
// В конце освобождаем занятые ресурсы
DeInitSocket(NO_ERROR);
end;
end;
// Процедура разборки пакета
procedure TSnifferThread.ParcePacket(const PacketSize: Word);
var
IPHeader: TIPHeader;
TCPHeader: TTCPHeader;
UDPHeader: TUDPHeader;
SrcPort, DestPort: Word;
I, A, Octets, PartOctets: Integer;
PacketType, DumpData: String;
Addr: TInAddr;
begin
Inc(frmMain.TotalPacketCount);
// Читаем из буфера IP заголовок
Move(Packet[0], IPHeader, IPHeaderSize);
// Пишем время жизни пакета
LogData := LOG_STR_0 +
Format(LOG_STR_1, [frmMain.TotalPacketCount, IPHeader.iph_ttl]);
// определяем тип протокола
case IPHeader.iph_protocol of
IPPROTO_TCP: // TCP
begin
PacketType := "TCP";
// Читаем ТСР заголовок
Move(Packet[IPHeaderSize], TCPHeader, TCPHeaderSize);
// Смотрим порт отправителя и получателя
SrcPort := TCPHeader.sourcePort;
DestPort := TCPHeader.destinationPort;
end;
IPPROTO_UDP: // UDP
begin
PacketType := "UDP";
// Чтаем UDP заголовок
Move(Packet[IPHeaderSize], UDPHeader, UDPHeaderSize);
// Смотрим порт отправителя и получателя
SrcPort := UDPHeader.sourcePort;
DestPort := UDPHeader.destinationPort;
end;
else
PacketType := "Unsupported (0x" + IntToHex(IPHeader.iph_protocol, 2) + ")";
end;
// Пишем размер пакета
LogData := LogData + Format(LOG_STR_2, [PacketSize, PacketType]);
// Пишем IP адрес отправителя с портом
Addr.S_addr := IPHeader.iph_src;
LogData := LogData + Format(LOG_STR_3, [inet_ntoa(Addr), SrcPort]);
// Пишем IP адрес получателя с портом
Addr.S_addr := IPHeader.iph_dest;
LogData := LogData + Format(LOG_STR_4, [inet_ntoa(Addr), DestPort]) + LOG_STR_5;
// Выводим содержимое пакета на экран (парсинг комментировать не буду, там все просто)
// получается что-то вроде этого:
//
// ------------------------------ Packet dump -----------------------------------
// 000000 45 00 00 4E D8 91 00 00 | 80 11 DB 3B C0 A8 02 82 E..N.......;....
// 000010 C0 A8 02 FF 00 89 00 89 | 00 3A AC 6A 83 BD 01 10 .........:.j....
// 000020 00 01 00 00 00 00 00 00 | 20 45 43 46 46 45 49 44 ........ ECFFEID
// 000030 44 43 41 43 41 43 41 43 | 41 43 41 43 41 43 41 43 DCACACACACACACAC
// 000040 41 43 41 43 41 43 41 43 | 41 00 00 20 00 01 ACACACACA.. ..
I := 0;
Octets := 0;
PartOctets := 0;
while I < PacketSize do
begin
case PartOctets of
0: LogData := LogData + Format("%.6d ", [Octets]);
9: LogData := LogData + "| ";
18:
begin
Inc(Octets, 10);
PartOctets := -1;
LogData := LogData + " " + DumpData + sLineBreak;
DumpData := "";
end;
else
begin
LogData := LogData + Format("%s ", [IntToHex(Packet[I], 2)]);
if Packet[I] in [$19..$7F] then
DumpData := DumpData + Chr(Packet[I])
else
DumpData := DumpData + ".";
Inc(I);
end;
end;
Inc(PartOctets);
end;
if PartOctets <> 0 then
begin
PartOctets := (16 - Length(DumpData)) * 3;
if PartOctets >= 24 then Inc(PartOctets, 2);
Inc(PartOctets, 4);
LogData := LogData + StringOfChar(" ", PartOctets) +
DumpData + sLineBreak + sLineBreak
end
else
LogData := LogData + sLineBreak + sLineBreak;
// Выводим все что напарсерили в Memo
Synchronize(ShowPacket);
end;
procedure TSnifferThread.ShowPacket;
begin
frmMain.memReport.Text :=
frmMain.memReport.Text + sLineBreak + LogData;
end;
← →
Rouse_ © (2005-02-07 12:07) [3]
{ TfrmMain }
procedure TfrmMain.FormCreate(Sender: TObject);
begin
TotalPacketCount := 0;
ReadLanInterfaces;
end;
// Читаем все IP адреса со всех присутствующих
// в системе сетевых интерфейсов
procedure TfrmMain.ReadLanInterfaces;
var
InterfaceInfo,
TmpPointer: PIP_ADAPTER_INFO;
IP: PIP_ADDR_STRING;
Len: ULONG;
begin
// Смотрим сколько памяти нам требуется?
if GetAdaptersInfo(nil, Len) = ERROR_BUFFER_OVERFLOW then
begin
// Берем нужное кол-во
GetMem(InterfaceInfo, Len);
try
// выполнение функции
if GetAdaptersInfo(InterfaceInfo, Len) = ERROR_SUCCESS then
begin
// Перечисляем все сетевые интерфейсы
TmpPointer := InterfaceInfo;
repeat
// перечисляем все IP адреса каждого интерфейса
IP := @TmpPointer.IpAddressList;
repeat
cbInterfaces.Items.Add(Format("%s - [%s]",
[IP^.IpAddress.S, TmpPointer.Description]));
IP := IP.Next;
until IP = nil;
TmpPointer := TmpPointer.Next;
until TmpPointer = nil;
end;
finally
// Освобождаем занятую память
FreeMem(InterfaceInfo);
end;
end;
// Смотрим - можем ли мы продолжать работу программы?
if cbInterfaces.Items.Count = 0 then
begin
memReport.Text := "Сетевые интерфейсы не обнаружены." + sLineBreak +
"Продолжение работы программы не возможно.";
btnStartStop.Enabled := False;
Exit;
end
else
cbInterfaces.ItemIndex := 0;
end;
// Запуск остановка потока
procedure TfrmMain.btnStartStopClick(Sender: TObject);
begin
if FSnifferThread <> nil then
begin
FSnifferThread.Terminate;
FSnifferThread := nil;
btnStartStop.Caption := "Start";
end
else
begin
FSnifferThread := TSnifferThread.Create(True);
FSnifferThread.Host := Copy(cbInterfaces.Text, 1, Pos(" ", cbInterfaces.Text));
FSnifferThread.FreeOnTerminate := True;
FSnifferThread.Resume;
btnStartStop.Caption := "Stop";
end;
end;
end.
← →
Verg © (2005-02-07 20:58) [4]Первое, что бросилось в глаза:
> const
> // Размеры используемых структур
> IPHeaderSize : DWORD = SizeOf(TIPHeader);
> TCPHeaderSize = SizeOf(TTCPHeader);
> UDPHeaderSize = SizeOf(TUDPHeader);
> Inc(frmMain.TotalPacketCount);
> // Читаем из буфера IP заголовок
> Move(Packet[0], IPHeader, SizeOf(TIPHeader)); // Допустим, нам не нужны опции
> IPHeaderSize := (IPHeader.iph_verlen and $F) shl 2;
> // Пишем время жизни пакета
> LogData := LOG_STR_0 +
> Format(LOG_STR_1, [frmMain.TotalPacketCount, IPHeader.iph_ttl]);
> // определяем тип протокола
...................
← →
JaoDa (2005-02-07 21:46) [5]ваауууу и всё работает. крассотищщща!!! :))))))))) пасиб большое! :)))))))
зы: имя автора ядра обязуюсь сохранить! :)
← →
Rouse_ © (2005-02-07 22:48) [6]> Verg © (07.02.05 20:58) [4]
О, кстати, Андрей, ты не мог бы завтра выйти в асю? Я хотел с тобой именно по данному примеру проконсультироваться, да все никак тебя не застать... :(
С Ethernet заголовком небольшая проблема...
Зыранее сенькс.
← →
InGo (2005-02-15 10:56) [7]Подскажите, а можно ли по какому-нибудь критерию в заголовке убить пакет, чтоб он дальше не прошел?
← →
Verg © (2005-02-15 17:30) [8]
> 7] InGo (15.02.05 10:56)
> Подскажите, а можно ли по какому-нибудь критерию в заголовке
> убить пакет, чтоб он дальше не прошел?
Что значит убить? Он (пакет) уже пришел, понимаешь? Его уже получили. Если SOCK_RAW его получил, то и все остальные его получили. Постфакт...
Если посреди комнаты кто-то крикнул, и ты этот крик услышал, то как ты можешь заставить других "забыть", про услышанный им тоже, тот же самый крик?
Снифер - это снифер, он НЕ посредник. Информация (пакеты) проходит не ЧЕРЕЗ него, а И ЕМУ ТОЖЕ.
← →
atruhinov (2005-02-17 02:13) [9]Помогите пожайлуста!!!
Здесь уже приводился пример сниффера, я разобрался, но
прочитать Ethernet заголовок не получается.
type
PEthernetHdr = ^TEthernetHdr;
TEthernetHdr = packed record
ether_dhost: TEtherAddr;
ether_shost: TEtherAddr;
ether_type: word;
end;
var
etherheader:PEthernetHdr;
begin
iRet := recv(RawSocket, buf, sizeof(buf), 0);
.
.
.
etherheader:=PEthernetHdr(@buf);
.
.
.
Выводиться блок IP но Ethernet ни в какую.
Если кто-то сталкивался с этой проблемой - помогите!!!
← →
Rouse_ © (2005-02-25 21:51) [10]> Ethernet
Это пример сниффера сетевого уровня а не канального...
← →
Tor-3000 (2005-02-26 12:40) [11]Rouse_
посмотри
http://forum.sources.ru/index.php?s=&showtopic=79575&hl=пакет
← →
Тореро (2005-03-13 17:56) [12]Rouse_ можешь помочь мне, ламеру неразумному, плз ? Вот смотри. я поставил несколько фильтров, и теперь получаю сетевые пакеты только с сообщениями IRC. как мне их расшифровать и привести к нормальному тексту ? а то выдаёт чёрт знает что...
← →
Тореро (2005-03-18 07:10) [13]Всё, не надо. теперь ужо другая проблема. оно не перехватывает пакеты других подсетей. с помощью чего можно реально перехватить пакеты, проходящие в других подсетях ?
← →
Максим (2005-03-21 14:39) [14]Rouse_, Поздравляю !
Отличный код !
← →
Максим (2005-03-21 14:46) [15]Rouse_, подскажите пож-ста, как ограничить пакеты только с одним портом и одним адресом ?
← →
Максим (2005-03-21 15:17) [16]Rouse_, Хотел Вас поправить.
Порт храниться в пакете двумя байтами, в обратном порядке, поэтому надо что то вроде:
SrcPort := Lo(TCPHeader.sourcePort)*$100+Hi(TCPHeader.sourcePort);
DestPort := Lo(TCPHeader.destinationPort)*$100+Hi(TCPHeader.destinationPort);
вставить в процедуру ParcePacket
← →
thaddy (2005-03-21 20:40) [17]Winpcap example (in KOL delphi, bit API same):
http://members.chello.nl/t.koning8/kolsniffer.zip
← →
Verg © (2005-03-21 21:52) [18]
> Максим (21.03.05 15:17) [16]
ntohs/ntohl
← →
Alex Konshin © (2005-03-22 04:00) [19]Тореро (18.03.05 07:10) [13]
Подсеть в том же сегменте локалки? Если нет - то и не будет: эти пакеты вполне могут не пропускаться маршрутизатором.
← →
Максим (2005-03-22 07:49) [20]Verg, как скажешь.
Уважаемый All, подскажите пож-ста, как добиться того, чтобы приходили только пакеты с портом 9999 (dest или src) и одним адресом, скажем 10.0.222.222 ?
← →
Rouse_ © (2005-03-22 09:54) [21]> Уважаемый All, подскажите пож-ста, как добиться того, чтобы приходили только пакеты с портом 9999 (dest или src) и одним адресом, скажем 10.0.222.222 ?
Так а какая разница какие приходят - ты отображай только те которые соответствуют введенным тобой условиям...
← →
Максим (2005-03-22 14:09) [22]Rouse_, так и сделал. Думал можно некий фильтр задать при создании сокета. Оказывается, все проще.
Еще такой вопрос, мне нужно писать в БД когда приходит пакет с содержанием "$$$ logged on" (все остальное игнорить). Как думаете существенно ли где это делать ? В ShowPacket(...) или может в ParcePacket(...) ?
← →
Rouse_ © (2005-03-22 15:46) [23]Разницы никакой...
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2005.06.06;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.019 c