当前位置: 首页 > news >正文

使用sharppcap抓数据包

首先用到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;
}
}

 

转载于:https://www.cnblogs.com/wudingfeng/archive/2010/12/25/1916931.html

相关文章:

  • SOA
  • Mac OS 10.6.5上如何默认启动mysq服务
  • fedora linux 下安装pwntcha[验证码开源]
  • 初识 统一建模语言(UML)
  • OllyDBG 1.10汉化第二版
  • Eclipse Android配置
  • asp.net与Discuz-UCenter整合(3):UCenter与应用同步
  • css中的相对定位和绝对定位
  • cvs svnmanager
  • TMS3705 射频识别技术软硬件系统研制 - 安防,免费资源,弱电技术,安防技术,智能化,金辉,金辉安防同盟,安全防范,电子技术,监控技术,摄像机...
  • vs2010 aspx页面创建控件时出错 未将对象引用设置到对象的实例 解决方法
  • IBM超级电脑Watson人机大赛首轮领先
  • 创意空间
  • Python的print 格式化输出
  • Linux netstat 命令详解
  • Android Studio:GIT提交项目到远程仓库
  • dva中组件的懒加载
  • Intervention/image 图片处理扩展包的安装和使用
  • Java读取Properties文件的六种方法
  • js算法-归并排序(merge_sort)
  • Markdown 语法简单说明
  • React 快速上手 - 07 前端路由 react-router
  • 笨办法学C 练习34:动态数组
  • 从零开始学习部署
  • 基于HAProxy的高性能缓存服务器nuster
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 手机端车牌号码键盘的vue组件
  • 思考 CSS 架构
  • 优化 Vue 项目编译文件大小
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • PostgreSQL之连接数修改
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • ​520就是要宠粉,你的心头书我买单
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ​什么是bug?bug的源头在哪里?
  • "无招胜有招"nbsp;史上最全的互…
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (06)金属布线——为半导体注入生命的连接
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (C语言)字符分类函数
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (三)docker:Dockerfile构建容器运行jar包
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • ***利用Ms05002溢出找“肉鸡
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .NET开源项目介绍及资源推荐:数据持久层
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)
  • .NET框架
  • [C++]:for循环for(int num : nums)
  • [C++进阶篇]STL中vector的使用
  • [Flex][问题笔记]TextArea滚动条问题
  • [Intel Edison开发板] 05、Edison开发基于MRAA实现IO控制,特别是UART通信