![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Снифер HTTP-запросов [D7, WinXP]
Дмитрий_05 © (2005-11-22 09:23:00)Привет всем. Подскажите пожалуйста как мне выделить HTTP-трафик из TCP-трафика? т.е. мне нужно чтобы моя программа видела по каким сайтам лазиет пользователь, причем любым браузером. В этом примере я определяю только IP-адреса пакетов, но т.к. если зайти на какуюнибудь страничку сайта, пакетов около 150 и больше приходит... как бы мне сделать, чтобы было просто написано, например "forum.vingrad.ru" один раз. Делаю я так:
uses WinSock;
...
type
USHORT = WORD;
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;
TTCPHeader = packed record
sourcePort: USHORT; // порт отправителя
destinationPort: USHORT; // порт назначения
sequenceNumber: ULONG; // номер последовательности
acknowledgeNumber: ULONG; // номер подтверждения
dataoffset: UCHAR; // смещение на область данных
flags: UCHAR; // флаги
windows: USHORT; // размер окна
checksum: USHORT; // контрольная сумма
urgentPointer: USHORT; // срочность
end;
PTCPHeader = ^TTCPHeader;
TSnifferThread = class(TThread)
private
WSA: TWSAData;
hSocket: TSocket;
Addr_in: sockaddr_in;
Packet: array [0..$10000 - 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;
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Label1: TLabel;
XPManifest1: TXPManifest;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
TotalPacketCount: Integer;
FSnifferThread: TSnifferThread;
public
{ Public declarations }
end;
const
// Размеры используемых структур
IPHeaderSize = SizeOf(TIPHeader);
TCPHeaderSize = SizeOf(TTCPHeader);
var
Form1: TForm1;
implementation
{$R *.dfm}
// узнаем текущий IP
function GetLocalIP: string;
var
WSAData: TWSAData;
Host: PHostEnt;
Buf: array [0..127] of Char;
begin
Result := '';
if WSAStartup($101, WSAData) = 0 then
begin
if GetHostName(@Buf, 128) = 0 then
begin
Host := GetHostByName(@Buf);
if Host <> nil then
Result := iNet_ntoa(PInAddr(Host^.h_addr_list^)^);
end;
WSACleanup;
end;
end;
{TSnifferThread}
function TSnifferThread.InitSocket: Boolean;
var
PromiscuousMode: Integer;
begin
// инициализируем WinSock
Result := WSAStartup($202, 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, $98000001, 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, $10000, 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;
SrcPort, DestPort: Word;
I, Octets, PartOctets: Integer;
PacketType, DumpData, ExtendedInfo: String;
Addr, A, B: TInAddr;
begin
Move(Packet[0], IPHeader, IPHeaderSize);
SrcPort := 0;
DestPort := 0;
ExtendedInfo := '';
// определяем тип протокола
if IPHeader.iph_protocol = IPPROTO_TCP then
begin
PacketType := 'TCP';
// Читаем ТСР заголовок
Move(Packet[IPHeaderSize], TCPHeader, TCPHeaderSize);
// Смотрим порт отправителя и получателя
SrcPort := TCPHeader.sourcePort;
DestPort := TCPHeader.destinationPort;
// Пишем IP адрес отправителя с портом
Addr.S_addr := IPHeader.iph_src;
LogData := inet_ntoa(Addr);
// Выводим все что напарсерили в Memo
Synchronize(ShowPacket);
end;
end;
procedure TSnifferThread.ShowPacket;
begin
Form1.Memo1.Lines.BeginUpdate;
Form1.Memo1.Text := Form1.Memo1.Text + FormatDateTime('c', Now) + ' | ' + LogData + sLineBreak;
SendMessage(Form1.Memo1.Handle, WM_VSCROLL, SB_BOTTOM, 0);
Form1.Memo1.Lines.EndUpdate;
end;
{TForm1}
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text := GetLocalIP;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if FSnifferThread <> nil then
begin
FSnifferThread.Terminate;
FSnifferThread := nil;
Button1.Caption := '>>> Start >>>';
end
else
begin
FSnifferThread := TSnifferThread.Create(True);
FSnifferThread.Host := Edit1.Text;
FSnifferThread.FreeOnTerminate := True;
FSnifferThread.Resume;
Button1.Caption := '*** Stop ***';
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if FSnifferThread <> nil then
begin
FSnifferThread.Terminate;
FSnifferThread := nil;
end;
end;
FloodaK (2006-03-03 12:53:00) [1]<center> FloodaK<center>
FloodaK (2006-02-27 08:20:00) [2]<h1>FloodaK</h1>
<xml>
umbra (2005-11-24 18:05:00) [3]на том же сайте, откуда ее скачал есть ссылка - http://www.winpcap.org/install/default.htm.
Дмитрий_05 (2005-11-24 17:40:00) [4]umbra, она библиотеку wpcap.dll требует... что это за библиотека?
umbra (2005-11-23 12:41:00) [5]HTTP-сниффер с исходниками
http://www.arsware.org/cms/showpage.php?cid=101&PHPSESSID=77fa03bd7b6139b01280fe6adab1bbe4
Slym (2005-11-23 11:38:00) [6]WinPcap - например
seeker (2005-11-23 11:31:00) [7]
> а как мне тогда этот GET ловить?
>
-Свой проксисервер.
-hook.
Дмитрий_05 (2005-11-23 11:19:00) [8]а как мне тогда этот GET ловить?
Slym (2005-11-23 11:09:00) [9]Если не ошибаюсь... так снифить можно только входящий трафик... а исходящий (GET -в нем) нет.
Дмитрий_05 (2005-11-23 10:48:00) [10]проанализировал я содержимое пакетов... почему-то я html-теги видно... а вот слова "GET" в пакетах что-то нету...(((
Digitman (2005-11-22 11:26:00) [11]
> если зайти на какуюнибудь страничку сайта, пакетов около
> 150 и больше приходит
TCP - протокол транспортного уровня, ему безразлично что передавать .. по TCP-соединению передается просто некий поток данных ..
получая в сниффере этот поток (фрагмент за фрагментом) ты анализируешь его содержимое на предмет соответствия получаемых в потоке данных формату , предусмотренному протоколом http (см., например, здесь http://book.itep.ru/4/45/http4561.htm) ... если данные соответствуют формату HTTP GET-запроса, то из заголовка запроса выделяется искомый URL.