На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Rouse_, jack128, Krid
  
    > Получение TCP/UDP статистики , Информация по открытым портам и процессам открывших порт
      ExpandedWrap disabled
        ////////////////////////////////////////////////////////////////////////////////
        //
        //  ****************************************************************************
        //  * Unit Name : Unit1
        //  * Purpose   : Демо получения ТСР статистики
        //  * Author    : Александр (Rouse_) Багель
        //  * Version   : 1.03
        //  ****************************************************************************
        //
         
        unit Unit1;
         
        interface
         
        uses
          Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
          Dialogs, StdCtrls, Winsock;
         
        // так как в примере используются недокументированные функции присутствующие
        // только в ХР и выше - то часть кода сделал через директивы компилятора
        // (лень было делать динамическую загрузку)
        // Если они вам нужны раскоментируйте директиву USES_NATIVE_API
         
        {.$DEFINE USES_NATIVE_API}
         
        const
          TH32CS_SNAPPROCESS  = $00000002;
         
          // Константы состояний порта
          MIB_TCP_STATE_CLOSED     = 1;
          MIB_TCP_STATE_LISTEN     = 2;
          MIB_TCP_STATE_SYN_SENT   = 3;
          MIB_TCP_STATE_SYN_RCVD   = 4;
          MIB_TCP_STATE_ESTAB      = 5;
          MIB_TCP_STATE_FIN_WAIT1  = 6;
          MIB_TCP_STATE_FIN_WAIT2  = 7;
          MIB_TCP_STATE_CLOSE_WAIT = 8;
          MIB_TCP_STATE_CLOSING    = 9;
          MIB_TCP_STATE_LAST_ACK   = 10;
          MIB_TCP_STATE_TIME_WAIT  = 11;
          MIB_TCP_STATE_DELETE_TCB = 12;
         
        type
          TForm1 = class(TForm)
            Memo1: TMemo;
            Button1: TButton;
            Button2: TButton;
            procedure Button1Click(Sender: TObject);
            procedure Button2Click(Sender: TObject);
            function PortStateToStr(const State: DWORD): String;
          end;
         
          // Стандартная структура для получения ТСР статистики
          PTMibTCPRow = ^TMibTCPRow;
          TMibTCPRow = packed record
            dwState: DWORD;
            dwLocalAddr: DWORD;
            dwLocalPort: DWORD;
            dwRemoteAddr: DWORD;
            dwRemotePort: DWORD;
          end;
         
          // В данную структуру будет передаваться результат GetTcpTable
          PTMibTCPTable = ^TMibTCPTable;
          TMibTCPTable = packed record
            dwNumEntries: DWORD;
            Table: array[0..0] of TMibTCPRow;
          end;
         
          // Стандартная структура для получения UDP статистики
          PTMibUdpRow = ^TMibUdpRow;
          TMibUdpRow = packed record
            dwLocalAddr: DWORD;
            dwLocalPort: DWORD;
          end;
         
          // В данную структуру будет передаваться результат GetUDPTable
          PTMibUdpTable = ^TMibUdpTable;
          TMibUdpTable = packed record
            dwNumEntries: DWORD;
            table: array [0..0] of TMibUdpRow;
          end;
         
         
          {$IFDEF USES_NATIVE_API}
            // Расширенные варианты данных структур
         
            PTMibTCPExRow = ^TMibTCPExRow;
            TMibTCPExRow = packed record
              dwState: DWORD;
              dwLocalAddr: DWORD;
              dwLocalPort: DWORD;
              dwRemoteAddr: DWORD;
              dwRemotePort: DWORD;
              dwProcessID: DWORD;
            end;
         
            PTMibTCPExTable = ^TMibTCPExTable;
            TMibTCPExTable = packed record
              dwNumEntries: DWORD;
              Table: array[0..0] of TMibTCPExRow;
            end;
         
            PTMibUdpExRow = ^TMibUdpExRow;
            TMibUdpExRow = packed record
              dwLocalAddr: DWORD;
              dwLocalPort: DWORD;
              dwProcessID: DWORD;
            end;
         
            PTMibUdpExTable = ^TMibUdpExTable;
            TMibUdpExTable = packed record
              dwNumEntries: DWORD;
              table: array [0..0] of TMibUdpExRow;
            end;
         
            // Структура для получения списка текущий процессов и их параметров
            TProcessEntry32 = packed record
              dwSize: DWORD;
              cntUsage: DWORD;
              th32ProcessID: DWORD;
              th32DefaultHeapID: DWORD;
              th32ModuleID: DWORD;
              cntThreads: DWORD;
              th32ParentProcessID: DWORD;
              pcPriClassBase: Longint;
              dwFlags: DWORD;
              szExeFile: array [0..MAX_PATH - 1] of WideChar;
            end;
         
          {$ENDIF}
         
          function GetTcpTable(pTCPTable: PTMibTCPTable; var pDWSize: DWORD;
            bOrder: BOOL): DWORD; stdcall; external 'IPHLPAPI.DLL';
         
          function GetUdpTable(pUDPTable: PTMibUDPTable; var pDWSize: DWORD;
            bOrder: BOOL): DWORD; stdcall; external 'IPHLPAPI.DLL';
         
          {$IFDEF USES_NATIVE_API}
         
            function AllocateAndGetTcpExTableFromStack(pTCPExTable: PTMibTCPExTable;
              bOrder: BOOL; heap: THandle; zero: DWORD; flags: DWORD): DWORD; stdcall;
              external 'IPHLPAPI.DLL';
         
            function AllocateAndGetUdpExTableFromStack(pUDPExTable: PTMibUDPExTable;
              bOrder: BOOL; heap: THandle; zero: DWORD; flags: DWORD): DWORD; stdcall;
              external 'IPHLPAPI.DLL';
         
            function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): THandle;
              stdcall; external 'KERNEL32.DLL';
         
            function Process32First(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL;
              stdcall; external 'KERNEL32.DLL' name 'Process32FirstW';
         
            function Process32Next(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL;
              stdcall; external 'KERNEL32.DLL' name 'Process32NextW';
         
          {$ENDIF}
         
        var
          Form1: TForm1;
         
        implementation
         
        {$R *.dfm}
         
        // Получение TCP/UDP статистики при помощи стандартных методов
        procedure TForm1.Button1Click(Sender: TObject);
        var
          Size: DWORD;
          TCPTable: PTMibTCPTable;
          UDPTable: PTMibUdpTable;
          I: DWORD;
        begin
          // для успешного получения стстаистики первоначально необходимо определиться
          // сколько памяти потребует данная операция
          // для этого делаем так:
          // Вделяем память под TCP таблицу (под один элемент)
          GetMem(TCPTable, SizeOf(TMibTCPTable));
          try
            // Показываем что памяти у нас не выделено
            Size := 0;
            // Выполняем функцию и после этого переменная Size
            // будет содержать кол-во необходимой памяти
            if GetTcpTable(TCPTable, Size, True) <> ERROR_INSUFFICIENT_BUFFER then Exit;
          finally
            // освобождаем память занятую под один элемент
            FreeMem(TCPTable);
          end;
          // Теперь выделяем уже требуемое кол-во памяти
          GetMem(TCPTable, Size);
          try
            // Выполняем функцию
            if GetTcpTable(TCPTable, Size, True) = NO_ERROR then
            begin
              Memo1.Lines.Add('');
              Memo1.Lines.Add('Standart TCP Stats');
              Memo1.Lines.Add(Format('%15s: | %5s %-12s', ['Host', 'Port', 'State']));
              Memo1.Lines.Add('==================================================');
            // и насинаем выводить данные по ТСР
            for I := 0 to TCPTable^.dwNumEntries - 1 do
              Memo1.Lines.Add(Format('%15s: | %5d %s', [inet_ntoa(in_addr(TCPTable^.Table[I].dwLocalAddr)),
                htons(TCPTable^.Table[I].dwLocalPort), PortStateToStr(TCPTable^.Table[I].dwState)]));
            end;
          finally
            // Не забываем освободить память
            FreeMem(TCPTable);
          end;
         
          // По аналогии поступаем и с UDP статистикой
          GetMem(UDPTable, SizeOf(TMibUDPTable));
          try
            Size := 0;
            if GetUdpTable(UDPTable, Size, True) <> ERROR_INSUFFICIENT_BUFFER then Exit;
          finally
            FreeMem(UDPTable);
          end;
          GetMem(UDPTable, Size);
          try
            if GetUdpTable(UDPTable, Size, True) = NO_ERROR then
            begin
              Memo1.Lines.Add('');
              Memo1.Lines.Add('Standart UDP Stats');
              Memo1.Lines.Add(Format('%15s: | %5s', ['Host', 'Port']));
              Memo1.Lines.Add('======================================');
            for I := 0 to UDPTable^.dwNumEntries - 1 do
              Memo1.Lines.Add(Format('%15s: | %5d', [inet_ntoa(in_addr(UDPTable^.Table[I].dwLocalAddr)),
                htons(UDPTable^.Table[I].dwLocalPort)]));
            end;
          finally
            FreeMem(UDPTable);
          end;
        end;
         
        {$IFNDEF USES_NATIVE_API}
        procedure TForm1.Button2Click(Sender: TObject);
        begin
          Memo1.Lines.Add('');
          Memo1.Lines.Add('USES_NATIVE_API are disabled.');
        end;
         
        {$ELSE}
         
        // Получение TCP/UDP статистики при помощи недокументрированных методов
        // Работает только на ХР или Win 2003
        procedure TForm1.Button2Click(Sender: TObject);
         
          // данная функция ищет процесс с th32ProcessID совпадающий с ProcessId
          // и возвращает его имя
          function ProcessPIDToName(const hProcessSnap: THandle; ProcessId: DWORD): String;
          var
            processEntry: TProcessEntry32;
          begin
            // Подготовительные действия
            Result := '';
            FillChar(processEntry, SizeOf(TProcessEntry32), #0);
            processEntry.dwSize := SizeOf(TProcessEntry32);
            // Прыгаем на первый процесс в списке
            if not Process32First(hProcessSnap, processEntry) then Exit;
            repeat
              // Сравнение
              if processEntry.th32ProcessID = ProcessId then
              begin
                // Если нашли нужный процесс - выводим результат и выходим
                Result := String(processEntry.szExeFile);
                Exit;
              end;
            // ищем пока не кончатся процессы
            until not Process32Next(hProcessSnap, processEntry);
          end;
         
        var
          TCPExTable: PTMibTCPExTable;
          UDPExTable: PTMibUdpExTable;
          I: DWORD;
          hProcessSnap: THandle;
        begin
          // для определения каким процессом открыт тот или иной порт
          // получаем список процессов
          hProcessSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
          if (hProcessSnap = INVALID_HANDLE_VALUE) then
          begin
            Memo1.Lines.Add('');
            Memo1.Lines.Add('CreateToolhelp32Snapshot failed');
            Exit;
          end;
          try
            // Выполняем вот такую вот функцию
            // она не документтрованна, но как видно из названия - она сама выделяет необходимую для работы
            // память и нам остается только прочитать результат по завершении ее выполнения
            if AllocateAndGetTcpExTableFromStack(@TCPExTable, False, GetProcessHeap, 2, 2) = NO_ERROR then
            try
              Memo1.Lines.Add('');
              Memo1.Lines.Add('Extended TCP Stats');
              Memo1.Lines.Add(Format('%15s: | %5s | %-12s | %20s | (%s)', ['Host', 'Port', 'State', 'Process name', 'ID']));
              Memo1.Lines.Add('==========================================================================');
              // начинаем выводить информацию
              for I := 0 to TCPExTable^.dwNumEntries - 1 do
                Memo1.Lines.Add(Format('%15s: | %5d | %-12s | %20s | (%d)',
                  [inet_ntoa(in_addr(TCPExTable^.Table[I].dwLocalAddr)),
                  htons(TCPExTable^.Table[I].dwLocalPort),
                  PortStateToStr(TCPExTable^.Table[I].dwState),
                  // Вот здесь у нас происходит сопоставление процесса открытому порту
                  ProcessPIDToName(hProcessSnap, TCPExTable^.Table[I].dwProcessID),
                  TCPExTable^.Table[I].dwProcessID]));
            finally
              // Не забываем освободить память занятую функцией
              GlobalFreePtr(TCPExTable);
            end;
         
            // По аналогии поступаем и с UDP статистикой
            if AllocateAndGetUdpExTableFromStack(@UDPExTable, False, GetProcessHeap, 2, 2) = NO_ERROR then
            try
              Memo1.Lines.Add('');
              Memo1.Lines.Add('Extended UDP Stats');
              Memo1.Lines.Add(Format('%15s: | %5s | %20s | (%s)', ['Host', 'Port', 'Process name', 'ID']));
              Memo1.Lines.Add('==============================================================');
              // начинаем выводить информацию
              for I := 0 to UDPExTable^.dwNumEntries - 1 do
                Memo1.Lines.Add(Format('%15s: | %5d | %20s | (%d)',
                  [inet_ntoa(in_addr(UDPExTable^.Table[I].dwLocalAddr)),
                  htons(UDPExTable^.Table[I].dwLocalPort),
                  ProcessPIDToName(hProcessSnap, UDPExTable^.Table[I].dwProcessID),
                  UDPExTable^.Table[I].dwProcessID]));
            finally
              GlobalFreePtr(UDPExTable);
            end;
          finally
            // Закрываем хэндл полученый от CreateToolhelp32Snapshot
            CloseHandle(hProcessSnap);
          end;
        end;
         
        {$ENDIF}
         
        // Функция преобразует состояние порта в строковый эквивалент
        function TForm1.PortStateToStr(const State: DWORD): String;
        begin
          case State of
            MIB_TCP_STATE_CLOSED: Result := 'CLOSED';
            MIB_TCP_STATE_LISTEN: Result := 'LISTEN';
            MIB_TCP_STATE_SYN_SENT: Result := 'SYN SENT';
            MIB_TCP_STATE_SYN_RCVD: Result := 'SYN RECEIVED';
            MIB_TCP_STATE_ESTAB: Result := 'ESTABLISHED';
            MIB_TCP_STATE_FIN_WAIT1: Result := 'FIN WAIT 1';
            MIB_TCP_STATE_FIN_WAIT2: Result := 'FIN WAIT 2';
            MIB_TCP_STATE_CLOSE_WAIT: Result := 'CLOSE WAIT';
            MIB_TCP_STATE_CLOSING: Result := 'CLOSING';
            MIB_TCP_STATE_LAST_ACK: Result := 'LAST ACK';
            MIB_TCP_STATE_TIME_WAIT: Result := 'TIME WAIT';
            MIB_TCP_STATE_DELETE_TCB: Result := 'DELETE TCB';
          else
            Result := 'UNKNOWN';
          end;
        end;
         
         
        end.


      Проект также доступен по адресу: http://rouse.drkb.ru/network.php#tcpstat
      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
      0 пользователей:


      Рейтинг@Mail.ru
      [ Script execution time: 0,0275 ]   [ 16 queries used ]   [ Generated: 3.05.24, 14:11 GMT ]