比如QQ通过端口1234正在接受文件,那么如何用第三方软件同时去监控这个1234端口的数据流量情况呢?
楼主现在在调研实现方法。。。
------解决思路----------------------
api hook或者写底层驱动
------解决思路----------------------
c#可以写底层驱动?
------解决思路----------------------
C# 在windows 上什么都可以干
------解决思路----------------------
hook winapi 就可以实现监控.
------解决思路----------------------
原始套接字,参考fastCSharp的demo.rawSocketListener
using System;
using fastCSharp;
namespace fastCSharp.demo.rawSocketListener
{
class Program
{
/// <summary>
/// 原始套接字监听
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Console.WriteLine("Press ip and enter ");
string ip = Console.ReadLine();
if (ip.length() == 0) Console.WriteLine(ip = "192.168.1.100");
try
{
using (fastCSharp.net.rawSocketListener rawSocket = new fastCSharp.net.rawSocketListener(getPacket, System.Net.IPAddress.Parse(ip)))
{
if (rawSocket.IsDisposed)
{
if (rawSocket.LastException != null) Console.WriteLine(rawSocket.LastException.ToString());
Console.WriteLine("套接字监听失败,可能需要管理员权限运行。");
}
else
{
Console.WriteLine("Press quit to exit.");
while (Console.ReadLine() != "quit") ;
return;
}
}
}
catch (Exception error)
{
Console.WriteLine(error.ToString());
}
Console.ReadKey();
}
/// <summary>
/// 数据包处理
/// </summary>
/// <param name="data">数据包</param>
private static void getPacket(subArray<byte> data)
{
fastCSharp.net.packet.ip ip4 = new fastCSharp.net.packet.ip(data);
if (ip4.IsPacket)
{
switch (ip4.Protocol)
{
case fastCSharp.net.packet.ip.protocol.Icmp:
fastCSharp.net.packet.icmp icmp = new fastCSharp.net.packet.icmp(ip4.Packet);
if (icmp.IsPacket)
{
Console.WriteLine(ip4.Source.toHex8() + " -> " + ip4.Destination.toHex8() + " " + ip4.Protocol.ToString() + " " + icmp.Type.ToString() + " " + icmp.Code.ToString());
}
else Console.WriteLine("Unknown");
break;
case fastCSharp.net.packet.ip.protocol.Igmp:
fastCSharp.net.packet.igmp igmp = new fastCSharp.net.packet.igmp(ip4.Packet);
if (igmp.IsPacket)
{
Console.WriteLine(ip4.Source.toHex8() + " -> " + ip4.Destination.toHex8() + " " + ip4.Protocol.ToString());
}
else Console.WriteLine("Unknown");
break;
case fastCSharp.net.packet.ip.protocol.Tcp:
fastCSharp.net.packet.tcp tcp = new fastCSharp.net.packet.tcp(ip4.Packet);
if (tcp.IsPacket)
{
Console.WriteLine(ip4.Source.toHex8() + ":" + ((ushort)tcp.SourcePort).toHex() + " -> " + ip4.Destination.toHex8() + ":" + ((ushort)tcp.DestinationPort).toHex() + " " + ip4.Protocol.ToString());
}
else Console.WriteLine("Unknown");
break;
case fastCSharp.net.packet.ip.protocol.Udp:
fastCSharp.net.packet.udp udp = new fastCSharp.net.packet.udp(ip4.Packet);
if (udp.IsPacket)
{
Console.WriteLine(ip4.Source.toHex8() + ":" + ((ushort)udp.SourcePort).toHex() + " -> " + ip4.Destination.toHex8() + ":" + ((ushort)udp.DestinationPort).toHex() + " " + ip4.Protocol.ToString());
}
else Console.WriteLine("Unknown");
break;
default:
Console.WriteLine(ip4.Source.toHex8() + " -> " + ip4.Destination.toHex8() + " " + ip4.Protocol.ToString());
break;
}
}
else Console.WriteLine("Unknown");
byte[] buffer = data.Array;
fastCSharp.net.rawSocketListener.Free(ref buffer);
}
}
}
------解决思路----------------------
这个不需要hook api(而且C#托管dll去做底层的钩子不太现实)
但是.Net socket提供了IO控制,你需要地作IP层监听
this.listener.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
this.listener.Bind(ipPoint);
var output = new byte[4];
this.listener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, output);
public partial class FrmSynPortData
{
private Socket listener;
//private IList<ArraySegment<byte>> buffer = new List<ArraySegment<byte>>();
private byte[] buffer = new byte[65536]; //缓冲
private int transfered = 0; //传输的字节数
public FrmSynPortData()
{
InitializeComponent();
this.timerDetect.Interval = 100;
this.listener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
this.FormClosing += (obj, e) =>
{
this.timerDetect.Stop();
this.timerDetect.Dispose();
this.listener.Shutdown(SocketShutdown.Both);
this.listener.Close();
};
}
private void FrmPortData_Load(object sender, EventArgs e)
{
var ipPoint = new IPEndPoint(Helper.MachineIP, int.Parse(Input.Trim()));
this.listener.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
this.listener.Bind(ipPoint);
var output = new byte[4];
this.listener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, output);
//if (BitConverter.ToInt32(output, 0) != 0)
if (output[0] + output[1] + output[2] + output[3] != 0)
MessageBox.Show("Failed to listen port via IOControl mode!");
else
{
this.listener.Blocking = false;
//this.listener.Listen(20480);
//MaxConnections = 2147483647
this.timerDetect.Start();
}
}
private void timerDetect_Tick(object sender, EventArgs e)
{
if (this.listener.Available > 0)
{
var msg = SysnAnalyzePacket(this.listener);
if(msg != null) this.rtbMessage.Text += msg;
}
}
void acptCallback(IAsyncResult iAsyResult)
{
var asyResult = this.listener.BeginAccept(rcvCallback, this.listener);
var socket = ((Socket)iAsyResult.AsyncState).EndAccept(out buffer, out transfered, iAsyResult);
AddMessage("[{0}] Accepted {1} bytes data from {2}\r\nMessage: {3}",
DateTime.Now.ToString("HH:mm:ss.fff"),
transfered,
socket.RemoteEndPoint,
Encoding.ASCII.GetString(buffer, 0, transfered));
}
void rcvCallback(IAsyncResult iAsyResult)
{
var listener = (Socket)iAsyResult.AsyncState;
listener.BeginReceive(buffer, 0, buffer.Length, SocketFlags.Peek, rcvCallback, listener);
//超过1000条时清空
if (this.rtbMessage.TextLength > 5000) this.rtbMessage.Clear();
SocketError error;
var rcvLength = listener.EndReceive(iAsyResult, out error);
AddMessage("收到数据: {0}字节!", rcvLength);
if (error != default(SocketError))
{
this.rtbMessage.Text += "===========接收出错:" + error.ToString();
}
AddMessage("[{0}] Recieved Message: {1}", DateTime.Now.ToString("HH:mm:ss.fff"), Encoding.ASCII.GetString(buffer, 0, rcvLength));
}
void AddMessage(string format, params object[] args)
{
this.rtbMessage.Text += string.Format(format, args);
}
/// <summary>
/// 同步方式解析TCP数据包
/// </summary>
/// <param name="listener"></param>
public static string SysnAnalyzePacket(Socket listener)
{
var buffer = new byte[4096];
int transfered = listener.Receive(buffer);
TCPPacket packet = new TCPPacket(ref buffer);
//string Data = System.Text.RegularExpressions.Regex.Replace(System.Text.Encoding.ASCII.GetString(ip.TCP.PacketData), @"[^a-zA-Z_0-9\.\@\- ]", "");
if (packet.ProtocolType != ProtocolType.Tcp
------解决思路----------------------
!packet.SourceAddress.Equals(MachineIP) && !packet.DestinationAddress.Equals(MachineIP))
{
return null;
}
if (packet.Error != null)
return string.Format("\r\nError: {0} \r\nStack Trace: {1}", packet.Error.Message, packet.Error.StackTrace);
else
return string.Format("\r\n{0}:{1} --> {2}:{3} Message: {4}",
packet.SourceAddress,
packet.SourcePort,
packet.DestinationAddress,
packet.DestinationPort,
Encoding.ASCII.GetString(packet.PacketData)
);
}
}
还有个TCPPacket类太长就不贴了,网上有,不过有点小问题
上面的例子拿网络抓取工具对照过,没有问题