首先用到PacketDotNet,SharpPcap这两个DLL,工具Ethereal可以分析包内容
代码
class
Program
{
static bool showDetails = false ; // 查看详情的参数
private static bool BackgroundThreadStop = false ; // 线程停止标识
private static object QueueLock = new object (); // 线程锁变量
private static List < PacketDotNet.RawPacket > PacketQueue = new List < PacketDotNet.RawPacket > (); // 待处理数据包队列
static void Main( string [] args)
{
// 显示SharpPcap版本
string ver = SharpPcap.Version.VersionString;
Console.WriteLine( " SharpPcap {0} " , ver);
// 获取网络设备
var devices = LivePcapDeviceList.Instance;
if (devices.Count < 1 )
{
Console.WriteLine( " 找不到网络设备 " );
return ;
}
Console.WriteLine();
Console.WriteLine( " 以下是目前本计算机上的活动网络设备: " );
Console.WriteLine( " ---------------------------------------------------- " );
Console.WriteLine();
int i = 0 ;
foreach (LivePcapDevice dev in devices)
{
Console.WriteLine( " {0}) {1} {2} " , i, dev.Name, dev.Description);
i ++ ;
}
// 选择要监听的网络设备
Console.WriteLine();
Console.WriteLine( " --选择一个需要监听的网络设备-- " );
i = int .Parse(Console.ReadLine());
LivePcapDevice device = devices[i];
Console.Write( " -- 请选择操作:监听通讯[C/c],多线程监听通讯[T/t],监听统计[F/f],发送随机数据包[S/s]? " );
string resp = Console.ReadLine().ToUpper();
while ( ! (resp.StartsWith( " C " ) || resp.StartsWith( " F " ) || resp.StartsWith( " T " ) || resp.StartsWith( " S " )))
{
resp = Console.ReadLine().ToUpper();
}
try
{
if (resp.StartsWith( " C " ) || resp.StartsWith( " F " ) || resp.StartsWith( " T " ))
{
// 监听过滤条件
string filter = " ip and tcp " ;
// 连接设备
System.Threading.Thread backgroundThread = null ;
int readTimeoutMilliseconds = 1000 ;
if (resp.StartsWith( " F " ))
{
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
device.Filter = filter;
device.Mode = CaptureMode.Statistics; // 抓包统计
device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival); // 抓数据包回调事件
device.OnPcapStatistics += new StatisticsModeEventHandler(device_OnPcapStatistics); // 抓包统计回调事件
}
else if (resp.StartsWith( " C " ))
{
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
device.Filter = filter;
device.Mode = CaptureMode.Packets; // 抓包数据
showDetails = resp.EndsWith( " -A " ); // 当抓数据包时,检查是否要查看详情
device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival); // 抓数据包回调事件
}
else if (resp.StartsWith( " T " ))
{
backgroundThread = new System.Threading.Thread(BackgroundThread);
backgroundThread.Start();
device.Open();
device.Filter = filter;
device.Mode = CaptureMode.Packets; // 抓数据包
showDetails = resp.EndsWith( " -A " ); // 当抓数据包时,检查是否要查看详情
device.OnPacketArrival += new PacketArrivalEventHandler(device_OnThreadPacketArrival); // 抓数据包回调事件
}
Console.WriteLine();
Console.WriteLine( " -- 当前TCPdump过滤条件: \ " { 0 }\ "" , filter);
Console.WriteLine( " -- 正在监听设备 {0}, 按 '回车' 键以停止监听... " , device.Description);
// 开始监听
device.StartCapture();
// 停止监听
Console.ReadLine();
device.StopCapture();
Console.WriteLine( " -- 停止监听. " );
if (backgroundThread != null )
{
BackgroundThreadStop = true ;
backgroundThread.Join();
}
}
else if (resp.StartsWith( " S " ))
{
// 连接设备
device.Open();
// 生成随机数据包
byte [] bytes = GetRandomPacket();
try
{
// 发送数据
device.SendPacket(bytes);
SendQueue squeue = new SendQueue( 2000 );
Console.WriteLine( " -- 单个数据包发送成功. " );
for ( int j = 0 ; j < 10 ; j ++ )
{
if ( ! squeue.Add(bytes))
{
Console.WriteLine( " -- 警告: 队列大小不足以存放所有数据包,将只发送部分数据包. " );
break ;
}
}
device.SendQueue(squeue, SendQueueTransmitModes.Synchronized);
Console.WriteLine( " -- 数据包队列发送完毕. " );
}
catch (Exception e)
{
Console.WriteLine( " -- -- -- " + e.Message);
}
}
}
catch (Exception e)
{
Console.WriteLine( " -- -- -- " + e.Message);
}
finally
{
if (device.Opened)
{
// 断开设备连接
Console.WriteLine(device.Statistics().ToString());
device.Close();
Console.WriteLine( " --断开设备连接 " );
Console.Write( " 按 '回车' 键以退出... " );
Console.Read();
}
}
Console.Read();
}
/// <summary>
/// 抓包方法
/// </summary>
static void device_OnPacketArrival( object sender, CaptureEventArgs e)
{
PcapPorcessContext(e.Packet);
}
private static void PcapPorcessContext(PacketDotNet.RawPacket pPacket)
{
var time = pPacket.Timeval.Date;
var len = pPacket.Data.Length;
var layer = pPacket.LinkLayerType;
Console.WriteLine( " {0}:{1}:{2},{3} 长度={4} 第几层={5} " ,
time.Hour, time.Minute, time.Second, time.Millisecond, len, layer);
Console.WriteLine( " content is {0} " , Encoding.ASCII.GetString(pPacket.Data));
var packet = PacketDotNet.Packet.ParsePacket(pPacket); // Raw基础包对象
if (layer == PacketDotNet.LinkLayers.Ethernet) // 以太网包
{
var ethernetPacket = (PacketDotNet.EthernetPacket)packet;
System.Net.NetworkInformation.PhysicalAddress srcMac = ethernetPacket.SourceHwAddress;
System.Net.NetworkInformation.PhysicalAddress destMac = ethernetPacket.DestinationHwAddress;
Console.WriteLine( " MAC:{0} -> {1} " , srcMac, destMac);
if (showDetails)
Console.WriteLine( " 以太网包: " + ethernetPacket.ToColoredString( false ));
}
var ipPacket = PacketDotNet.IpPacket.GetEncapsulated(packet); // ip包
if (ipPacket != null )
{
System.Net.IPAddress srcIp = ipPacket.SourceAddress;
System.Net.IPAddress destIp = ipPacket.DestinationAddress;
Console.WriteLine( " IP: {0} -> {1} " , srcIp, destIp);
if (showDetails) Console.WriteLine( " IP packet: " + ipPacket.ToColoredString( false ));
var tcpPacket = PacketDotNet.TcpPacket.GetEncapsulated(packet); // TCP包
if (tcpPacket != null )
{
int srcPort = tcpPacket.SourcePort;
int destPort = tcpPacket.DestinationPort;
Console.WriteLine( " TCP Port: {0} -> {1} " , srcPort, destPort);
if (showDetails) Console.WriteLine( " TCP packet: " + tcpPacket.ToColoredString( false ));
}
var udpPacket = PacketDotNet.UdpPacket.GetEncapsulated(packet); // UDP包
if (udpPacket != null )
{
int srcPort = udpPacket.SourcePort;
int destPort = udpPacket.DestinationPort;
Console.WriteLine( " UDP Port: {0} -> {1} " , srcPort, destPort);
if (showDetails) Console.WriteLine( " UDP packet: " + udpPacket.ToColoredString( false ));
}
}
}
static ulong oldSec = 0 ;
static ulong oldUsec = 0 ;
/// <summary>
/// 抓包统计方法
/// </summary>
static void device_OnPcapStatistics( object sender, StatisticsModeEventArgs e)
{
// 计算统计心跳间隔
ulong delay = (e.Statistics.Timeval.Seconds - oldSec) * 1000000 - oldUsec + e.Statistics.Timeval.MicroSeconds;
// 获取 Bits per second
ulong bps = (( ulong )e.Statistics.RecievedBytes * 8 * 1000000 ) / delay;
/* ^ ^
| |
| |
| |
converts bytes in bits -- |
|
delay is expressed in microseconds --
*/
// 获取 Packets per second
ulong pps = (( ulong )e.Statistics.RecievedPackets * 1000000 ) / delay;
// 将时间戳装换为易读格式
var ts = e.Statistics.Timeval.Date.ToLongTimeString();
// 输出统计结果
Console.WriteLine( " {0}: bps={1}, pps={2} " , ts, bps, pps);
// 记录本次统计时间戳,以用于下次统计计算心跳间隔
oldSec = e.Statistics.Timeval.Seconds;
oldUsec = e.Statistics.Timeval.MicroSeconds;
}
/// <summary>
///
/// </summary>
private static DateTime LastStatisticsOutput = DateTime.Now;
private static TimeSpan LastStatisticsInterval = new TimeSpan( 0 , 0 , 2 );
static void device_OnThreadPacketArrival( object sender, CaptureEventArgs e)
{
// 输出设备通讯统计信息
var Now = DateTime.Now;
var interval = Now - LastStatisticsOutput;
if (interval > LastStatisticsInterval)
{
Console.WriteLine( " Device Statistics: " + ((LivePcapDevice)e.Device).Statistics());
LastStatisticsOutput = Now;
}
lock (QueueLock)
{
PacketQueue.Add(e.Packet); // 将捕获到的数据包加入处理队列
}
}
/// <summary>
/// 多线程处理数据包队列
/// </summary>
private static void BackgroundThread()
{
while ( ! BackgroundThreadStop)
{
bool shouldSleep = true ;
lock (QueueLock)
{
if (PacketQueue.Count != 0 )
{
shouldSleep = false ;
}
}
if (shouldSleep)
{
System.Threading.Thread.Sleep( 250 );
}
else // 处理队列
{
List < PacketDotNet.RawPacket > ourQueue; // 本线程待处理队列
lock (QueueLock)
{
ourQueue = PacketQueue;
PacketQueue = new List < PacketDotNet.RawPacket > ();
}
Console.WriteLine( " BackgroundThread: Local Queue Count is {0} " , ourQueue.Count);
foreach (var packet in ourQueue)
{
PcapPorcessContext(packet);
}
}
}
}
/// <summary>
/// 生成一个大小为200的随机数据包
/// </summary>
private static byte [] GetRandomPacket()
{
byte [] packet = new byte [ 200 ];
Random rand = new Random();
rand.NextBytes(packet);
return packet;
}
}
{
static bool showDetails = false ; // 查看详情的参数
private static bool BackgroundThreadStop = false ; // 线程停止标识
private static object QueueLock = new object (); // 线程锁变量
private static List < PacketDotNet.RawPacket > PacketQueue = new List < PacketDotNet.RawPacket > (); // 待处理数据包队列
static void Main( string [] args)
{
// 显示SharpPcap版本
string ver = SharpPcap.Version.VersionString;
Console.WriteLine( " SharpPcap {0} " , ver);
// 获取网络设备
var devices = LivePcapDeviceList.Instance;
if (devices.Count < 1 )
{
Console.WriteLine( " 找不到网络设备 " );
return ;
}
Console.WriteLine();
Console.WriteLine( " 以下是目前本计算机上的活动网络设备: " );
Console.WriteLine( " ---------------------------------------------------- " );
Console.WriteLine();
int i = 0 ;
foreach (LivePcapDevice dev in devices)
{
Console.WriteLine( " {0}) {1} {2} " , i, dev.Name, dev.Description);
i ++ ;
}
// 选择要监听的网络设备
Console.WriteLine();
Console.WriteLine( " --选择一个需要监听的网络设备-- " );
i = int .Parse(Console.ReadLine());
LivePcapDevice device = devices[i];
Console.Write( " -- 请选择操作:监听通讯[C/c],多线程监听通讯[T/t],监听统计[F/f],发送随机数据包[S/s]? " );
string resp = Console.ReadLine().ToUpper();
while ( ! (resp.StartsWith( " C " ) || resp.StartsWith( " F " ) || resp.StartsWith( " T " ) || resp.StartsWith( " S " )))
{
resp = Console.ReadLine().ToUpper();
}
try
{
if (resp.StartsWith( " C " ) || resp.StartsWith( " F " ) || resp.StartsWith( " T " ))
{
// 监听过滤条件
string filter = " ip and tcp " ;
// 连接设备
System.Threading.Thread backgroundThread = null ;
int readTimeoutMilliseconds = 1000 ;
if (resp.StartsWith( " F " ))
{
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
device.Filter = filter;
device.Mode = CaptureMode.Statistics; // 抓包统计
device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival); // 抓数据包回调事件
device.OnPcapStatistics += new StatisticsModeEventHandler(device_OnPcapStatistics); // 抓包统计回调事件
}
else if (resp.StartsWith( " C " ))
{
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
device.Filter = filter;
device.Mode = CaptureMode.Packets; // 抓包数据
showDetails = resp.EndsWith( " -A " ); // 当抓数据包时,检查是否要查看详情
device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival); // 抓数据包回调事件
}
else if (resp.StartsWith( " T " ))
{
backgroundThread = new System.Threading.Thread(BackgroundThread);
backgroundThread.Start();
device.Open();
device.Filter = filter;
device.Mode = CaptureMode.Packets; // 抓数据包
showDetails = resp.EndsWith( " -A " ); // 当抓数据包时,检查是否要查看详情
device.OnPacketArrival += new PacketArrivalEventHandler(device_OnThreadPacketArrival); // 抓数据包回调事件
}
Console.WriteLine();
Console.WriteLine( " -- 当前TCPdump过滤条件: \ " { 0 }\ "" , filter);
Console.WriteLine( " -- 正在监听设备 {0}, 按 '回车' 键以停止监听... " , device.Description);
// 开始监听
device.StartCapture();
// 停止监听
Console.ReadLine();
device.StopCapture();
Console.WriteLine( " -- 停止监听. " );
if (backgroundThread != null )
{
BackgroundThreadStop = true ;
backgroundThread.Join();
}
}
else if (resp.StartsWith( " S " ))
{
// 连接设备
device.Open();
// 生成随机数据包
byte [] bytes = GetRandomPacket();
try
{
// 发送数据
device.SendPacket(bytes);
SendQueue squeue = new SendQueue( 2000 );
Console.WriteLine( " -- 单个数据包发送成功. " );
for ( int j = 0 ; j < 10 ; j ++ )
{
if ( ! squeue.Add(bytes))
{
Console.WriteLine( " -- 警告: 队列大小不足以存放所有数据包,将只发送部分数据包. " );
break ;
}
}
device.SendQueue(squeue, SendQueueTransmitModes.Synchronized);
Console.WriteLine( " -- 数据包队列发送完毕. " );
}
catch (Exception e)
{
Console.WriteLine( " -- -- -- " + e.Message);
}
}
}
catch (Exception e)
{
Console.WriteLine( " -- -- -- " + e.Message);
}
finally
{
if (device.Opened)
{
// 断开设备连接
Console.WriteLine(device.Statistics().ToString());
device.Close();
Console.WriteLine( " --断开设备连接 " );
Console.Write( " 按 '回车' 键以退出... " );
Console.Read();
}
}
Console.Read();
}
/// <summary>
/// 抓包方法
/// </summary>
static void device_OnPacketArrival( object sender, CaptureEventArgs e)
{
PcapPorcessContext(e.Packet);
}
private static void PcapPorcessContext(PacketDotNet.RawPacket pPacket)
{
var time = pPacket.Timeval.Date;
var len = pPacket.Data.Length;
var layer = pPacket.LinkLayerType;
Console.WriteLine( " {0}:{1}:{2},{3} 长度={4} 第几层={5} " ,
time.Hour, time.Minute, time.Second, time.Millisecond, len, layer);
Console.WriteLine( " content is {0} " , Encoding.ASCII.GetString(pPacket.Data));
var packet = PacketDotNet.Packet.ParsePacket(pPacket); // Raw基础包对象
if (layer == PacketDotNet.LinkLayers.Ethernet) // 以太网包
{
var ethernetPacket = (PacketDotNet.EthernetPacket)packet;
System.Net.NetworkInformation.PhysicalAddress srcMac = ethernetPacket.SourceHwAddress;
System.Net.NetworkInformation.PhysicalAddress destMac = ethernetPacket.DestinationHwAddress;
Console.WriteLine( " MAC:{0} -> {1} " , srcMac, destMac);
if (showDetails)
Console.WriteLine( " 以太网包: " + ethernetPacket.ToColoredString( false ));
}
var ipPacket = PacketDotNet.IpPacket.GetEncapsulated(packet); // ip包
if (ipPacket != null )
{
System.Net.IPAddress srcIp = ipPacket.SourceAddress;
System.Net.IPAddress destIp = ipPacket.DestinationAddress;
Console.WriteLine( " IP: {0} -> {1} " , srcIp, destIp);
if (showDetails) Console.WriteLine( " IP packet: " + ipPacket.ToColoredString( false ));
var tcpPacket = PacketDotNet.TcpPacket.GetEncapsulated(packet); // TCP包
if (tcpPacket != null )
{
int srcPort = tcpPacket.SourcePort;
int destPort = tcpPacket.DestinationPort;
Console.WriteLine( " TCP Port: {0} -> {1} " , srcPort, destPort);
if (showDetails) Console.WriteLine( " TCP packet: " + tcpPacket.ToColoredString( false ));
}
var udpPacket = PacketDotNet.UdpPacket.GetEncapsulated(packet); // UDP包
if (udpPacket != null )
{
int srcPort = udpPacket.SourcePort;
int destPort = udpPacket.DestinationPort;
Console.WriteLine( " UDP Port: {0} -> {1} " , srcPort, destPort);
if (showDetails) Console.WriteLine( " UDP packet: " + udpPacket.ToColoredString( false ));
}
}
}
static ulong oldSec = 0 ;
static ulong oldUsec = 0 ;
/// <summary>
/// 抓包统计方法
/// </summary>
static void device_OnPcapStatistics( object sender, StatisticsModeEventArgs e)
{
// 计算统计心跳间隔
ulong delay = (e.Statistics.Timeval.Seconds - oldSec) * 1000000 - oldUsec + e.Statistics.Timeval.MicroSeconds;
// 获取 Bits per second
ulong bps = (( ulong )e.Statistics.RecievedBytes * 8 * 1000000 ) / delay;
/* ^ ^
| |
| |
| |
converts bytes in bits -- |
|
delay is expressed in microseconds --
*/
// 获取 Packets per second
ulong pps = (( ulong )e.Statistics.RecievedPackets * 1000000 ) / delay;
// 将时间戳装换为易读格式
var ts = e.Statistics.Timeval.Date.ToLongTimeString();
// 输出统计结果
Console.WriteLine( " {0}: bps={1}, pps={2} " , ts, bps, pps);
// 记录本次统计时间戳,以用于下次统计计算心跳间隔
oldSec = e.Statistics.Timeval.Seconds;
oldUsec = e.Statistics.Timeval.MicroSeconds;
}
/// <summary>
///
/// </summary>
private static DateTime LastStatisticsOutput = DateTime.Now;
private static TimeSpan LastStatisticsInterval = new TimeSpan( 0 , 0 , 2 );
static void device_OnThreadPacketArrival( object sender, CaptureEventArgs e)
{
// 输出设备通讯统计信息
var Now = DateTime.Now;
var interval = Now - LastStatisticsOutput;
if (interval > LastStatisticsInterval)
{
Console.WriteLine( " Device Statistics: " + ((LivePcapDevice)e.Device).Statistics());
LastStatisticsOutput = Now;
}
lock (QueueLock)
{
PacketQueue.Add(e.Packet); // 将捕获到的数据包加入处理队列
}
}
/// <summary>
/// 多线程处理数据包队列
/// </summary>
private static void BackgroundThread()
{
while ( ! BackgroundThreadStop)
{
bool shouldSleep = true ;
lock (QueueLock)
{
if (PacketQueue.Count != 0 )
{
shouldSleep = false ;
}
}
if (shouldSleep)
{
System.Threading.Thread.Sleep( 250 );
}
else // 处理队列
{
List < PacketDotNet.RawPacket > ourQueue; // 本线程待处理队列
lock (QueueLock)
{
ourQueue = PacketQueue;
PacketQueue = new List < PacketDotNet.RawPacket > ();
}
Console.WriteLine( " BackgroundThread: Local Queue Count is {0} " , ourQueue.Count);
foreach (var packet in ourQueue)
{
PcapPorcessContext(packet);
}
}
}
}
/// <summary>
/// 生成一个大小为200的随机数据包
/// </summary>
private static byte [] GetRandomPacket()
{
byte [] packet = new byte [ 200 ];
Random rand = new Random();
rand.NextBytes(packet);
return packet;
}
}