📄 u_capture.pas
字号:
(*
* One Way Network Sniffer (OWNS)
* Copyright (C) 2001-2002 OWNS
*
* http://owns.sourceforge.net/
* http://www.owns.st
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)
(*
* $Id: u_capture.pas,v 1.8 2001/10/01 20:20:37 owns Exp $
* Main class for capturing from an ethernet interface
*
*
* FCapture := TCapture.create;
* FLibpCapSniffer := TLibpCapSniffer.create;
* FLibpCapSniffer.AdapterIndex := 1;
* FLibpCapSniffer.mode := Live;
* FCapture.Sniffer := FLibpCapSniffer;
* FCapture.startCapture;
*
* => Many options can be changed with filter property
* => You can get statistics about current capture with Statistics property
*
* files are created in files subdirectory
*
* 2 threads are created in addition to main thread
* - a thread that will capture packets (created when TSniffer.create is called)
* - a thread that will create files (TEndConnection.Thread)
*)
unit u_capture;
interface
uses classes,SysUtils,
u_statistics, u_Filter,u_ConnectionsTCP,
u_Packet, u_EthernetFrame, u_TCPPacket,
u_Sniffer, u_Debug;
type
ECaptureException = class(Exception);
TEndCaptureEvent = procedure of object;
TEndConnectionThread = class;
TCapture = class
private
FSniffer : TSniffer;
FConnectionsTCP : TConnectionsTCP;
FEndConnectionThread : TEndConnectionThread;
FSaveNonTCP : Boolean;
FFileStreamNonTCP : TFileStream;
FTimeOutTCP : Cardinal;
FEndCapture : TEndCaptureEvent;
function getStatistics : TStatistics;
function getFilter : TFilter;
procedure OnPacket(p_packet : Pointer; p_RecvBytes: Word; p_Tick : Cardinal);
procedure setSniffer(p_Sniffer : TSniffer);
procedure EndSniffing;
procedure EndConnectionThreadTerminated(Sender: TObject);
public
constructor Create; virtual;
destructor destroy; override;
procedure startCapture;
procedure stopCapture;
property Statistics : TStatistics read getStatistics;
property Filter : TFilter read getFilter;
property SaveNonTCP : boolean read FSaveNonTCP write FSaveNonTCP;
property TimeOutTCP : Cardinal read FTimeOutTCP write FTimeOutTCP;
property Sniffer : TSniffer read FSniffer write setSniffer;
property OnEndCapture : TEndCaptureEvent read FEndCapture write FEndCapture;
end;
// this thread will call verifyTimeOut
TEndConnectionThread = class(TThread)
private
FCapture : TCapture;
FCanBeTerminated : Boolean;
public
constructor Create(p_Capture : TCapture); virtual;
procedure Execute; override;
property CanBeTerminated : Boolean read FCanBeTerminated;
end;
implementation
// do not try to change FSniffer priority. This does not yield to good results
// keep priority to tpIdle for EndConnection too
constructor TCapture.Create;
begin
FSaveNonTCP := false;
FTimeOutTCP := 10000; // number of ms of inactivity after which we consider the connection as closed
FSNiffer := nil;
FEndCapture := nil;
end;
destructor TCapture.destroy;
begin
if (FSniffer <> nil) then
begin
if FSniffer.Snooping then
stopCapture;
end;
inherited;
end;
// Set the sniffer that we want to use
// see : u_ObserverSniffer, u_LibpcapSniffer, u_SehSniffer
procedure TCapture.setSniffer(p_Sniffer : TSniffer);
begin
FSniffer := p_Sniffer;
FSniffer.OnPacket := onPacket;
FSniffer.OnEndSniffing := EndSniffing;
end;
// this function is called when an ethernet packet is received
procedure TCapture.OnPacket(p_packet : Pointer; p_RecvBytes: Word; p_Tick : Cardinal);
var
l_Packet : TEthernetFrame;
l_PacketTCP : TTCPPacket;
begin
l_Packet := getPacket(p_packet);
g_Statistics.packetReceived(l_packet,p_RecvBytes);
if (l_Packet is TTCPPacket) then
begin
l_PacketTCP := l_Packet As TTCPPacket;
FConnectionsTCP.addTCPPacket(l_PacketTCP,p_Tick);
end else
if SaveNonTCP then
FFileStreamNonTCP.write(p_packet^,p_RecvBytes);
l_Packet.free;
end;
// start capture
procedure TCapture.startCapture;
var
l_ErrStr : String;
begin
If SaveNonTCP then
FFileStreamNonTCP := TFileStream.create('NonTCP.bin',fmCreate);
g_Statistics.StartStatistiques;
FConnectionsTCP := TConnectionsTCP.create;
FConnectionsTCP.timeOut := FTimeOutTCP;
// create thread that will free TCP connection
FEndConnectionThread := TEndConnectionThread.create(self);
FEndConnectionThread.OnTerminate := EndConnectionThreadTerminated;
FEndConnectionThread.FreeOnTerminate := true;
{$IFDEF MSWINDOWS}
FEndConnectionThread.Priority := tpIdle;
{$ENDIF}
{$IFDEF LINUX}
// FEndConnectionThread.Priority := -1;
{$ENDIF}
FEndConnectionThread.resume;
if (not FSniffer.Activate(l_ErrStr)) then
begin
// an error occured !
FEndCOnnectionThread.Terminate;
// FConnectionsTCP.free;
// if SaveNonTCP then
// FFileStreamNonTCP.free;
raise ECaptureException.create(l_ErrStr);
end;
end;
// stop capture
procedure TCapture.stopCapture;
var
l_ErrStr : String;
begin
if (not FSniffer.Deactivate(l_ErrStr)) then
raise ECaptureException.create(l_ErrStr);
end;
// this function is called when sniffing terminated. This can be because we
// called stopCapture or for any other reason (EOF, exception ...)
procedure TCapture.EndSniffing;
begin
// FEndConnectionThread takes time before executing Execute Method. This is
// because of the lower priority of this thread.
// But we must make sure that verifyTimeOut is executed at least once
while (FEndConnectionThread.CanBeTerminated = false) do begin end;
FEndConnectionThread.terminate;
end;
// this function is called when EndCOnnectionThread terminates
procedure TCapture.EndConnectionThreadTerminated(Sender: TObject);
begin
FConnectionsTCP.free;
if SaveNonTCP then
FFileStreamNonTCP.free;
if assigned(FEndCapture) then FEndCapture;
end;
// Properties
////////////////////////////////////////////////////////////////////////////////
// g_Statistics is a singleton that gives many informations (number of packets received etc ...)
function TCapture.getStatistics : TStatistics;
begin
result := g_Statistics;
end;
// g_Filter is a singleton. You can use it to filter what you want to save etc ...
function TCapture.getFilter : TFilter;
begin
result := g_Filter;
end;
////////////////////////////////////////////////////////////////////////////////
//
// TEndConnectionThread
//
////////////////////////////////////////////////////////////////////////////////
constructor TEndConnectionThread.Create(p_Capture : TCapture);
begin
inherited Create(True);
FCapture := p_Capture;
FCanBeTerminated := false;
end;
// All connections that are not being accessed since 10 seconds are considered as
// closed (and are saved on disk in "files" subdirectory if they pass the filter).
procedure TEndConnectionThread.Execute;
var
l_VerifyOneMoreTime : Boolean;
begin
// when terminated is set to true, we execute verifyTimeOut one more time
l_VerifyOneMoreTime := false;
FCanBeTerminated := True;
while ((not Terminated) or (l_VerifyOneMoreTime)) do
begin
try
FCapture.FConnectionsTCP.verifyTimeOut;
if Terminated then
l_VerifyOneMoreTime := not l_VerifyOneMoreTime;
except
on e: Exception do
begin
g_Debug.debug('(TEndConnectionThread)'+e.Message+' proc:'+g_CurrentProc,'TEndConnectionThread.Execute');
end;
end;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -