Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  03:04[Войти] | [Зарегистрироваться]
Ответ на вопрос № 58624

18-01-2008 13:43
Привет Всем обитателям!!! Подскажите, есть сниффер (код представлен ниже), как мне сделать так, что бы он выводил не только информацию о пакете, но и само сообщение... И куда этот код вставить в прогу..


unit uMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, WinSock, ComCtrls;

const
  MAX_PACKET_SIZE = $10000; // 2^16
  SIO_RCVALL = $98000001;
  WSA_VER = $202;
  MAX_ADAPTER_NAME_LENGTH        = 256;
  MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
  MAX_ADAPTER_ADDRESS_LENGTH    = 8;
  IPHelper = 'iphlpapi.dll';

  // Тип ICMP пакета
  ICMP_ECHO            = 8// Запрос
  ICMP_ECHOREPLY        = 0// Ответ

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 = 'ARP Type: %s, operation: %s' + sLineBreak;
  LOG_STR_6 = 'ICMP Type: %s' + sLineBreak;
  LOG_STR_7 = '------------------------------ Packet dump -----------------------------------' + sLineBreak;

type
  USHORT = WORD;
  ULONG = DWORD;
  time_t = Longint;

  // ip заголовок
  // Более подробно в RFC 791
  // http://rtfm.vn.ua/inet/prot/rfc791r.html
  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 заголовок
  // Более подробно в RFC 793
  // http://rtfm.vn.ua/inet/prot/rfc793r.html
  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 заголовок
  // Более подробно в RFC 768
  // http://rtfm.vn.ua/inet/prot/rfc768r.html
  TUDPHeader = packed record
    sourcePort:      USHORT;  // порт отправителя
    destinationPort:  USHORT;  // порт назначения
    len:              USHORT;  // длина пакета
    checksum:        USHORT;  // контрольная сумма
  end;
  PUDPHeader = ^TUDPHeader;

  // ICMP заголовок
  // Более подробно в RFC 792
  // http://rtfm.vn.ua/inet/prot/rfc792r.html
  TICMPHeader = packed record
  IcmpType      : BYTE;      // Тип пакета
  IcmpCode      : BYTE;      // Код пакета
  IcmpChecksum  : WORD;
  IcmpId        : WORD;
  IcmpSeq      : WORD;
  IcmpTimestamp : DWORD;
  end;
  PICMPHeader = ^TICMPHeader;


  // Структуры для выполнения GetAdaptersInfo
  IP_ADDRESS_STRING = record
    S: array [0..15] of Char;
  end;
  IP_MASK_STRING = IP_ADDRESS_STRING;
  PIP_MASK_STRING = ^IP_MASK_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;
    cbInterfaces: TComboBox;
    Label1: TLabel;
    RichEdit1: TRichEdit;
    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);
  ICMPHeaderSize = SizeOf(TICMPHeader);
  TCPHeaderSize = SizeOf(TTCPHeader);
  UDPHeaderSize = SizeOf(TUDPHeader);

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

{ TSnifferThread }

// Инициализация слушающего сокета
function TSnifferThread.InitSocket: Boolean;
var
  PromiscuousMode: 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;
  ICMPHeader: TICMPHeader;
  TCPHeader: TTCPHeader;
  UDPHeader: TUDPHeader;
  SrcPort, DestPort: Word;
  I, Octets, PartOctets: Integer;
  PacketType, DumpData, ExtendedInfo: String;
  Addr, A, B: TInAddr;
begin
  Inc(frmMain.TotalPacketCount);
  // Читаем из буфера IP заголовок
  Move(Packet[0], IPHeader, IPHeaderSize);
  // Пишем время жизни пакета
  LogData := LOG_STR_0 +
    Format(LOG_STR_1, [frmMain.TotalPacketCount, IPHeader.iph_ttl]);
  SrcPort := 0;
  DestPort := 0;
  ExtendedInfo := '';
  // определяем тип протокола
  case IPHeader.iph_protocol of
    IPPROTO_ICMP: // ICMP
    begin
      PacketType := 'ICMP';
              // Читаем ICMP заголовок
      Move(Packet[IPHeaderSize], ICMPHeader, ICMPHeaderSize);
              // Смотрим тип пакета
      case ICMPHeader.IcmpCode of
        ICMP_ECHO: ExtendedInfo := Format(LOG_STR_6, ['Echo']);
        ICMP_ECHOREPLY: ExtendedInfo := Format(LOG_STR_6, ['Echo reply']);
      else
        ExtendedInfo := Format(LOG_STR_6, ['Unknown']);
      end;
    end;
    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]);
  if ExtendedInfo <> '' then
    LogData := LogData + ExtendedInfo;

  // Пишем 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_7;

  // Выводим содержимое пакета на экран (парсинг комментировать не буду, там все просто)
  // получается что-то вроде этого:
  //
  // ------------------------------ 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.RichEdit1.Lines.BeginUpdate;
frmMain.RichEdit1.Text:=frmMain.RichEdit1.Text+sLineBreak+LogData;
SendMessage(frmMain.RichEdit1.Handle, WM_VSCROLL, SB_BOTTOM, 0);
frmMain.RichEdit1.Lines.EndUpdate;
{  frmMain.memReport.Lines.BeginUpdate;
  frmMain.memReport.Text :=
    frmMain.memReport.Text + sLineBreak + LogData;
  SendMessage(frmMain.memReport.Handle, WM_VSCROLL, SB_BOTTOM, 0);
  frmMain.memReport.Lines.EndUpdate;  }

end;

{ 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
    RichEdit1.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.

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

20-11-2009 06:30 | Комментарий к предыдущим ответам
если все таки еще актуально - 45 00 - стандартная часть заголовка IP пакета - означает IPv4

05-01-2009 06:27


{$APPTYPE CONSOLE}
{$R ico.res}
uses WinSock, Windows, SysUtils;
const
  MAX_PACKET_SIZE = $10000; // 2^16
  SIO_RCVALL = $98000001;
  WSA_VER = $202;
  MAX_ADAPTER_NAME_LENGTH        = 256;
  MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
  MAX_ADAPTER_ADDRESS_LENGTH    = 8;
  // Тип ICMP пакета
  ICMP_ECHO            = 8// Запрос
  ICMP_ECHOREPLY        = 0// Ответ
  LOG_STR_0 = '=============================================================================='#13#10;
  LOG_STR_1 = 'Packet ID: %-5d TTL: %d'#13#10;
  LOG_STR_2 = 'Packet size: %-5d bytes type: %s'#13#10;
  LOG_STR_3 = 'Source IP      : %15s: %d'#13#10;
  LOG_STR_4 = 'Destination IP : %15s: %d'#13#10;
  LOG_STR_5 = 'ARP Type: %s, operation: %s'#13#10;
  LOG_STR_6 = 'ICMP Type: %s'#13#10;
  LOG_STR_7 = '------------------------------ Packet dump -----------------------------------'#13#10;

type
  USHORT = WORD;
  ULONG = DWORD;
  time_t = longInt;


  // ip заголовок
  // Более подробно в RFC 791
  // http://rtfm.vn.ua/inet/prot/rfc791r.html
  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 заголовок
  // Более подробно в RFC 793
  // http://rtfm.vn.ua/inet/prot/rfc793r.html
  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 заголовок
  // Более подробно в RFC 768
  // http://rtfm.vn.ua/inet/prot/rfc768r.html
  TUDPHeader = packed record
    sourcePort:      USHORT;  // порт отправителя
    destinationPort:  USHORT;  // порт назначения
    len:              USHORT;  // длина пакета
    checksum:        USHORT;  // контрольная сумма
  end;
  PUDPHeader = ^TUDPHeader;


  // ICMP заголовок
  // Более подробно в RFC 792
  // http://rtfm.vn.ua/inet/prot/rfc792r.html
  TICMPHeader = packed record
  IcmpType      : BYTE;      // Тип пакета
  IcmpCode      : BYTE;      // Код пакета
  IcmpChecksum  : WORD;
  IcmpId        : WORD;
  IcmpSeq      : WORD;
  IcmpTimestamp : DWORD;
  end;
  PICMPHeader = ^TICMPHeader;


  // Структуры для выполнения GetAdaptersInfo
  IP_ADDRESS_STRING = record
    s : array [0..15] of char;
  end;
  IP_MASK_STRING = IP_ADDRESS_STRING;
  PIP_MASK_STRING = ^IP_MASK_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;                 

const
  // Размеры используемых структур
  IPHeaderSize = SizeOf(TIPHeader);
  ICMPHeaderSize = SizeOf(TICMPHeader);
  TCPHeaderSize = SizeOf(TTCPHeader);
  UDPHeaderSize = SizeOf(TUDPHeader);


//////////////////////////// 
var
  WSA: TWSAData;
  hSocket: TSocket;
  Addr_in: sockaddr_in;
  Packet: array[0..MAX_PACKET_SIZE - 1] of byte;
  TotalPacketCount: integer;
  PacketSize: integer;
  host: string;


procedure ShowPacket(s:string);
begin
  writeln('--------------------------');
  writeln(s);
end;


// При помощи данной функции мы определим наличие сетевых интерфейсов
// на локальном компьютере и информацию о них
function GetAdaptersInfo(pAdapterInfo: PIP_ADAPTER_INFO;
        var pOutBufLen: ULONG): DWORD; stdcall; external 'iphlpapi.dll';

// Читаем все IP адреса со всех присутствующих
// в системе сетевых интерфейсов
function ReadLanInterfaces : integer;
var
  InterfaceInfo, TmpPointer: PIP_ADAPTER_INFO;
  IP: PIP_ADDR_STRING;
  len: ULONG;
  n : integer;
begin
  n:=0;
  // Смотрим сколько памяти нам требуется?
  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
            ShowPacket(IP^.IpAddress.S+' - ['+TmpPointer.Description+']');
            IP := IP.Next;
                               inc(n);
          until IP = nil;
          TmpPointer := TmpPointer.Next;
        until TmpPointer = nil;
      end;
    finally
      // Освобождаем занятую память
      FreeMem(InterfaceInfo);
    end;
  end;
  ReadLanInterfaces := n;
end;


procedure DeInitSocket(const ExitCode : integer);
begin  // Завершение работы сокета
  // Если была ошибка - выводим ее
  if ExitCode <> 0 then ShowPacket('Ошибка: ' + SysErrorMessage(ExitCode));
  // Закрываем сокет
  if hSocket <> INVALID_SOCKET then closesocket(hSocket);
  // Деинициализируем WinSock
  WSACleanup;
end;


function InitSocket : boolean;
var  // Инициализация слушающего сокета
  PromiscuousMode : integer;
begin
  // инициализируем WinSock
  Result := WSAStartup(WSA_VER, WSA) = NOERROR;
  if not Result then
  begin
           ShowPacket('Ошибка: ' + SysErrorMessage(WSAGetLastError));
    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;


function ParcePacket(const PacketSize : word) : string;
var  // Процедура разборки пакета
  IPHeader: TIPHeader;
  ICMPHeader: TICMPHeader;
  TCPHeader: TTCPHeader;
  UDPHeader: TUDPHeader;
  SrcPort, DestPort: Word;
  i, Octets, PartOctets: Integer;
  PacketType, DumpData, ExtendedInfo,s : string;
  Addr: TInAddr;
begin
  inc(TotalPacketCount);
  // Читаем из буфера IP заголовок
  move(Packet[0], IPHeader, IPHeaderSize);
  // Пишем время жизни пакета
  s := LOG_STR_0 + Format(LOG_STR_1, [TotalPacketCount, IPHeader.iph_ttl]);
  SrcPort := 0;
  DestPort := 0;
  ExtendedInfo := '';
  // определяем тип протокола
  case IPHeader.iph_protocol of
    IPPROTO_ICMP: // ICMP
    begin
      PacketType := 'ICMP';
              // Читаем ICMP заголовок
      Move(Packet[IPHeaderSize], ICMPHeader, ICMPHeaderSize);
              // Смотрим тип пакета
      case ICMPHeader.IcmpCode of
        ICMP_ECHO: ExtendedInfo := Format(LOG_STR_6, ['Echo']);
        ICMP_ECHOREPLY: ExtendedInfo := Format(LOG_STR_6, ['Echo reply']);
      else
        ExtendedInfo := Format(LOG_STR_6, ['Unknown']);
      end;
    end;
    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;
  // Пишем размер пакета
  s := s + Format(LOG_STR_2, [PacketSize, PacketType]);
  if ExtendedInfo <> '' then s := s + ExtendedInfo;
           
  SrcPort := htons(SrcPort);
  DestPort := htons(DestPort);

  // Пишем IP адрес отправителя с портом
  Addr.S_addr := IPHeader.iph_src;
  s := s + Format(LOG_STR_3, [inet_ntoa(Addr), SrcPort]);
  // Пишем IP адрес получателя с портом
  Addr.S_addr := IPHeader.iph_dest;
  s := s + Format(LOG_STR_4, [inet_ntoa(Addr), DestPort]) + LOG_STR_7;

  // Выводим содержимое пакета на экран (парсинг комментировать не буду, там все просто)
  // получается что-то вроде этого:
  //
  // ------------------------------ 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: s := s + Format('%.6d ', [Octets]);
      9: s := s + '| ';
      18:
      begin
        inc(Octets, 10);
        PartOctets := -1;
        s := s + '    ' + DumpData + sLineBreak;
        DumpData := '';
      end;
    else
      begin
        s := s + 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);
    s := s + StringOfChar(' ', PartOctets) + DumpData +#13#10#13#10;
  end
    else s := s +#13#10#13#10;
  ParcePacket:=s;
end;


begin
  TotalPacketCount := 0;
  writeln('HOST-list:');
  if ReadLanInterfaces>0 then    // Смотрим - можем ли мы продолжать работу программы?
  begin
    write('input ip host:');
    readln(host);
    if InitSocket then
    begin
      repeat
        // Ждем получения пакета (блокирующий режим)
        PacketSize := recv(hSocket, Packet, MAX_PACKET_SIZE, 0);
        // Если есть данные - производим их разбор
        if PacketSize > SizeOf(TIPHeader) then ShowPacket(ParcePacket(PacketSize));
      until false; 
      DeInitSocket(NO_ERROR);
    end;
  end
  else writeln('Сетевые интерфейсы не обнаружены.'#13#10'Продолжение работы программы не возможно.');
end.


21-07-2008 01:37
Ну что, товарищи знатоки, никто не проявил пока интереса?

17-07-2008 05:02
В продолжение к этому вопросу.
тоже работаю над кодом этого сниффера, ну и ессна возникли несколько вопросов. Один из них вот:
при просмотре пакетов, оказывается, что все они начинаются с "45"
-----1----------
Packet ID: 299  TTL: 127
Packet size: 162  bytes type: TCP
Source IP      :      ххх: 8979
Destination IP :  ххх: 20499
------------------------------ Packet dump -----------------------------------
000000 45 00 00 A2 FE 23 40 00 | 7F 06 D7 04 5B 00 00 0A    E....#@....[...
000010 C0 A8 0A 7B 13 23 13 50 | 43 01 52 89 E9 E1 58 4D    ...{.#.PC.R...XM
-----1----------
ну или вот:
-----2----------
Packet ID: 300  TTL: 128
Packet size: 66    bytes type: TCP
Source IP      :  ххх: 20499
Destination IP :      ххх: 8979
------------------------------ Packet dump -----------------------------------
000000 45 00 00 42 13 49 40 00 | 80 06 C1 3F C0 A8 0A 7B    E..B.I@....?...{
000010 5B 00 00 0A 13 50 13 23 | E9 E1 58 4D 43 01 53 03    [....P.#..XMC.S.
-----2----------

если использовать снифф товарища саурона, то он выдает все немного не так:
-----3------
Packet ID: 44      Packet size: 31   
Source IP      :  ххх: 22273
Destination IP :  ххх: 1206
------------------------------------------------------------------------------
000000 1F 00 BC 45 5E 8E 65 08 | 18 9E 23 7A F6 F4 55 60    ..E^.e...#z..U`
000010 C6 BE FC B1 3E 3F 9E 9B | 8F 0A B7 37 09 F6 A8        ....>?.....7...
-----3------

снимки сделаны не в одно и то же время(приведены для примера), но подробные исследования одновременных снимков показали, что и порты ЭТОТ снифф показывает неверно...

вот и возник вопрос, а правильно ли парсит пакеты этот снифф? правильно ли записаны структуры в нем? не устарел ли процесс разборки пакетов? перефразирую: что я делаю не так? ))

с нетерпением жду...

19-01-2008 13:53
Это авторский код
//  *************************************************
//  * Project  : SnifferDemo
//  * Author    : Александр (Rouse_) Багель
//  *************************************************

Проще было взят от сюда
http://rouse.drkb.ru/files/sniffer.zip

19-01-2008 08:05
1)Создать новый проект для виндовс
2)Изменить свойство Name формы с form1 на frmMain
3)Сохранить  в файл uMain.pas
4)Добавить на форму компоненты:
  TButton со свойством Name = btnStartStop
  TComboBox  со свойством NamecbInterfaces
  TLabel со свойством NameLabel1
  TRichEdit со свойством NameRichEdit1
5) Создать события формы и контролов:
    FormCreate
    btnStartStopClick
6) Сохранить
7) Скопировать ваш код из вопроса поверх всего вашего модуля uMain
8) Скомпилировать и вуаля все работает!

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Раз дощечка, два дощечка будет лесенка. Раз словечко, два словечко, будет ЧТО?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования