Текущий архив: 2007.04.01;
Скачать: CL | DM;
Вниз
Определение IP пользователя пытающегося подключиться ко мне Найти похожие ветки
← →
cleverman (2006-10-18 17:03) [0]Итак, уважаемые мастера, помогите советом.
Суть такая.
На моей машине есть серверная часть некоей проги удаленного управления (Real VNC). Каким образом я программно могу определить IP подключающихся к этому серверу пользователей, использующих клиентскую часть. Порт подключения известен.
← →
Ketmar © (2006-10-18 17:23) [1]снифер. искать у Rouse_(c).
← →
cleverman (2006-10-19 09:02) [2]Хм... Сниффер - это понятно. Это первое, что пришло мне в голову. Но тут проблемка немного другая. Мне нужно зашить немалую обработку события подключения, если IP подключающегося соответствует определенному списку IP. Поэтому я имел ввиду определение IP средствами Delphi, а не посторонними снифферами.
← →
Ketmar © (2006-10-19 09:07) [3]слазим с бронепоезда. идём на сайт Rouse_(c). качаем снифер. о, чудо -- он на Delphi написан, оказывается!
зыж ты бы сначала, всё же, ходил на сайты, а потом говорил "не подходит!" ага?
← →
Rouse_ © (2006-10-19 09:53) [4]Можно конечно и сниффером, перебрать открытые хэндлы гнезд в системе, отфильтровать из них те, которые принадлежат процессу Real VNC и из них вытащить RemoteHost, но на написание демки сейчас нет времени, поэтому самое простое конечно же сделать так:
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Unit Name : Unit1
// * Purpose : Демо получения ТСР статистики
// * Author : Александр (Rouse_) Багель
// * Version : 1.02
// ****************************************************************************
//
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;
← →
Rouse_ © (2006-10-19 09:53) [5]
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 | %15s: | %11s | %-12s",
["Host", "Port", "Remote Host", "Remote Port", "State"]));
Memo1.Lines.Add("=============================================================== =========");
// и начинаем выводить данные по ТСР
for I := 0 to TCPTable^.dwNumEntries - 1 do
Memo1.Lines.Add(Format("%15s: | %5d | %15s: | %11d | %s",
[inet_ntoa(in_addr(TCPTable^.Table[I].dwLocalAddr)),
htons(TCPTable^.Table[I].dwLocalPort),
inet_ntoa(in_addr(TCPTable^.Table[I].dwRemoteAddr)),
htons(TCPTable^.Table[I].dwRemotePort),
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;
← →
Rouse_ © (2006-10-19 09:54) [6]
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 | %15s: | %11s | %-12s | %20s | (%s)",
["Host", "Port", "Remote Host", "Remote Port", "State", "Process name", "ID"]));
Memo1.Lines.Add(
"=============================================================================== ============================");
// начинаем выводить информацию
for I := 0 to TCPExTable^.dwNumEntries - 1 do
Memo1.Lines.Add(Format("%15s: | %5d | %15s: | %11d | %-12s | %20s | (%d)",
[inet_ntoa(in_addr(TCPExTable^.Table[I].dwLocalAddr)),
htons(TCPExTable^.Table[I].dwLocalPort),
inet_ntoa(in_addr(TCPExTable^.Table[I].dwRemoteAddr)),
htons(TCPExTable^.Table[I].dwRemotePort),
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.
← →
Rouse_ © (2006-10-19 09:55) [7]ЗЫ: это чуть чуть расширенный вариант вот этого примера: http://rouse.drkb.ru/files/tcpstat.zip
← →
cleverman (2006-10-19 10:41) [8]to Ketmar ©
to Rouse_©
Премного благодарен за помощь. :)
Я как раз уже демонтировал по кусочкам выложенный на сайте сниффер (спасибо to Rouse_© за предоставленный код) и преобразовал его в нужный вариант. Не люблю лентяйничать за чужой счет, но все равно спасибо.
З.Ы. в сниффере, кстати идет утечка памяти :) Где, еще не нашел, но визуально утечка налицо
← →
Rouse_ © (2006-10-19 10:57) [9]Визуально это не утечка, а просто растет буффер TMemo - туда же текст выводиться :) Очисти TMemo и память вернется к нормальному состоянию :)
← →
cleverman (2006-10-19 11:05) [10]Я уже сообразил :) Как только добавил последнюю строчку
procedure TSnifferThread.ShowPacket;
begin
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;
Application.ProcessMessages;
end;
Страницы: 1 вся ветка
Текущий архив: 2007.04.01;
Скачать: CL | DM;
Память: 0.52 MB
Время: 0.052 c