在c#用raw socket进行sniff嗅探(一)

raw socket 三部曲:

socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);

socket.Bind(new IPEndPoint(IPAddress.Parse(IP), 0));

同步下:rcv_size = socket.Receive(buffer);

异步下:socket.Begin***

实现过程不难,难点是捕获后对数据报的分析,过滤的工作。

ps:网络层ip数据报格式如下:ip header+××header(如TCP header) + Data

今天存在问题如下:嗅觉不灵敏,不知道是设置不对还是raw socket效果本身就是这样,等待考究……

今天研究到此结束,待续……

附代码:

RawSocket.cs

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Net;
using  System.Net.Sockets;
using  System.Runtime.InteropServices;

namespace  RawSocket
{
        /// <summary>
        /// @author segment
        /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    
public struct IpHeader
    
{
        [FieldOffset(
0)]
        
public byte ip_verlen; // IP version and IP Header length
        [FieldOffset(1)]
        
public byte ip_tos; // Type of service
        [FieldOffset(2)]
        
public ushort ip_totallength; // total length of the packet
        [FieldOffset(4)]
        
public ushort ip_id; // unique identifier
        [FieldOffset(6)]
        
public ushort ip_offset; // flags and offset
        [FieldOffset(8)]
        
public byte ip_ttl; // Time To Live
        [FieldOffset(9)]
        
public byte ip_protocol; // protocol (TCP, UDP etc)
        [FieldOffset(10)]
        
public ushort ip_checksum; //IP Header checksum
        [FieldOffset(12)]
        
public uint ip_srcaddr; //Source address
        [FieldOffset(16)]
        
public uint ip_destaddr;//Destination Address
    }


    
class RawSocket
    
{
        Socket socket;
        String IP 
= "218.20.242.189";
        
private String StandardIP(uint ip)
        
{
            
byte[] b_ip = new byte[4];
            b_ip[
0= (byte)(ip & 0x000000ff);
            b_ip[
1= (byte)((ip & 0x0000ff00>> 8);
            b_ip[
2= (byte)((ip & 0x00ff0000)>>16);
            b_ip[
3= (byte)((ip & 0xff000000)>>24);
            
return b_ip[0].ToString() + "." + b_ip[1].ToString() + "." + b_ip[2].ToString() + "." + b_ip[3].ToString();
        }

        
unsafe private void ParseReceive(byte[]buffer,int size)
        
{
            
if (buffer == nullreturn;
            
fixed (byte*pbuffer = buffer)
            
{
                IpHeader
* ip_header = (IpHeader*)pbuffer;
                
int protocol = ip_header->ip_protocol;
                
uint ip_srcaddr = ip_header->ip_srcaddr, ip_destaddr = ip_header->ip_destaddr, header_len = 0;
                
string out_string = "";
                
short src_port = 0, dst_port = 0;
                IPAddress tmp_ip;
                
string from_ip="", to_ip="";
                from_ip 
= ip_header->ip_srcaddr.ToString();
                
switch (protocol)
                
{
                    
case 1: out_string = "ICMP:"break;
                    
case 2: out_string = "IGMP:"break;
                    
case 6:
                        out_string 
= "TCP:";
                        
break;
                    
case 17: out_string = "UDP:";
                        
break;
                    
default: out_string = "UNKNOWN"break;
                }

//                System.Console.WriteLine(out_string + "from ip:" + IPAddress.Parse(from_ip).ToString() + " to ip:" + IPAddress.Parse(to_ip).ToString());
                System.Console.WriteLine(out_string + "src:" + StandardIP(ip_srcaddr) + "dest:" + StandardIP(ip_destaddr));
            }

            
        }

        
public void ShutDown()
        
{
            
if(socket != null)
            
{
                
try
                
{
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close();
                }

                
catch(Exception)
                
{
                    System.Console.WriteLine(
"关闭socket错误!");
                }


            }

        }

        
public void Run()
        
{
            System.Console.WriteLine(
"Raw Socket running...");
            socket 
= new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
            
byte[] buffer = new byte[4096];
            
int rcv_size = 0;
            
// socket.Blocking = false;
            socket.Bind(new IPEndPoint(IPAddress.Parse(IP), 0));
            
while (true)
            
{
                System.Console.WriteLine(
"开始新一次循环");
                
try
                
{
                    
//socket.BeginReceive(buffer, 0, 10, SocketFlags.None, Callback, null);
                    rcv_size = socket.Receive(buffer);
                    ParseReceive(buffer, rcv_size);
                }

                
catch (Exception e)
                
{
                    System.Console.WriteLine(
"异常:" + e.Message);
                    
return;
                }

                
//System.Threading.Thread.Sleep(500);
                
//System.Console.WriteLine("接收到:" + rcv_size.ToString());
            }

        }

        
~RawSocket()
        
{
            ShutDown();
        }

    }

}

 

使用方法:

 

public   static   void  Main(String[] args)
        
{
            RawSocket socket 
= new RawSocket();
            socket.Run();

        }
—————————————————————— Hearen's SimpleSniffer —————————————————————— 一、功能简介: .针对同一局域网中的所有主机进行监听并返回处理优化后的数据供研究使用; .在数据表中显示了所有当前侦听到的数据包包括源IP、源端口、目的IP、目的端口、数据包协议类型、数据包捕获时间及数据包简略信息(仅应用层数据); .可以针对某一特定IP地址(源或目的),某特定端口(源或目的)以及特定类型数据包进行侦听 -- 捕获前过滤; .当数据过多时可以随时点击‘清理’对当前的数据表进行清空 -- 不过捕获的数据是不会被清除的,仅清除列表中显示的数据; .双击‘清理’时清空所有嗅探到的数据 -- 不仅仅是列表中显示的数据; .选择列表中的数据时,数据详细信息会显示在下方的面板中; 此时可以通过选择特定字符串来查看在其左侧的十六进制表示以供研究之用; .左下角会显示当前在该局域网中捕获到的数据包个数及总大小(该大小包含IP协议及其建立在该协议以上协议的头部)-- 数据单位会自动进行切换当数据大小达到2G时将重置清零; .在获取数据包后可以针对某一IP,PORT,IP:PORT或IP/PORT及协议进行筛选,同时可以查阅当前所有捕获的数据包(如果没有设置捕获前过滤,否则只能查阅过滤后的数据)。 二、使用说明:本应用的使用环境为Windows 7、Windows 8及Windows 8.1。 在使用过程中需要获得管理员权限 - 捕获数据包需要访问底层数据,需要获得最高权限才可以正常运行该应用; 三、作者留言 该应用的开发环境为VS2013,所用语言为C#,界面设计属于WinForm(比较老式的界面风格,推荐使用WPF)。因本人水平有限,在该应用中不免存在很多漏洞和不足;如果你有更多更好的想法或者发现该小应用中的bug还望批评指正。
—————————————————————— Hearen's SimpleSniffer —————————————————————— 一、功能简介: 1.针对同一局域网中的所有主机进行监听并返回处理优化后的数据供研究使用; 2.在数据表中显示了所有当前侦听到的数据包包括源IP、源端口、目的IP、目的端口、数据包协议类型、数据包捕获时间及数据包简略信息(仅应用层数据); 3.可以针对某一特定IP地址(源或目的),某特定端口(源或目的)以及特定类型数据包进行侦听 -- 捕获前过滤; 4.当数据过多时可以随时点击‘清理’对当前的数据表进行清空 -- 不过捕获的数据是不会被清除的,仅清除列表中显示的数据; 5.双击‘清理’时清空所有嗅探到的数据 -- 不仅仅是列表中显示的数据; 6.选择列表中的数据时,数据详细信息会显示在下方的面板中; 此时可以通过选择特定字符串来查看在其左侧的十六进制表示以供研究之用; 7.左下角会显示当前在该局域网中捕获到的数据包个数及总大小(该大小包含IP协议及其建立在该协议以上协议的头部)-- 数据单位会自动进行切换当数据大小达到2G时将重置清零; 8.在获取数据包后可以针对某一IP,PORT,IP:PORT或IP/PORT及协议进行筛选,同时可以查阅当前所有捕获的数据包(如果没有设置捕获前过滤,否则只能查阅过滤后的数据)。 二、使用说明:本应用的使用环境为Windows 7、Windows 8及Windows 8.1。 在使用过程中需要获得管理员权限 - 捕获数据包需要访问底层数据,需要获得最高权限才可以正常运行该应用; 三、作者留言 该应用的开发环境为VS2013,所用语言为C#,界面设计属于WinForm(比较老式的界面风格,推荐使用WPF)。因本人水平有限,在该应用中不免存在很多漏洞和不足;如果你有更多更好的想法或者发现该小应用中的bug还望批评指正。 ||联系方式:LHearen@126.com|| 四、免责声明 本系统仅用于学习交流之用,本人不承担该应用的技术及版权问题,且不对该应用负法律责任。
一、功能简介: 1.针对同一局域网中的所有主机进行监听并返回处理优化后的数据供用户研究使用; 2.在数据表中显示了所有当前侦听到的数据包包括源IP、源端口、目的IP、目的端口、数据包协议类型、数据包捕获时间及数据包简略信息(仅应用层数据); 3.可以对某种特定类型协议的数据进行针对性监听; 4.可以针对某一特定源IP地址进行侦听; 5.当数据过多时可以随时点击‘清理’对当前的数据表进行清空 - 不过捕获的数据是不会被清除的,仅清除列表中的数据; 6.在数据显示区域可以通过选择特定字符串以此查看在其左侧的十六进制表示以供研究之用; 7.在应用左下角显示当前应用在该局域网中捕获到的数据包个数及总大小(该大小包含IP协议及其建立在该协议以上协议的头部)- 当数据大小达到2G时将重置清零; 8.在获取数据包后可以针对某一IP或IP:PORT或IP/PORT及协议进行筛选,同时可以查阅当前所有的捕获的数据包(如果没有设置捕获前过滤,否则只能查阅过滤后的数据)。 二、安装环境说明:本应用的安装环境为Windows 7、Windows 8及Windows 8.1。 三、安装过程说明 1.在安装过程中需要获得管理员权限 - 捕获数据包需要访问底层数据,需要获得最高权限才可以正常运行该应用; 2.在安装结束时,用户可以选择此时启动应用还是结束安装流程;当选择此时启动时系统会再次提醒用户允许应用获取管理员权限-原因同上。 四、作者留言 该应用的开发环境为VS2013,所用语言为C#,界面设计属于WinForm(比较老式的界面风格,推荐使用WPF),在后期程序发布打包使用的是InstallShield Limited Edition(如果需要长期打包窗体应用发布最好购买正版,可以获得更多个性化的功能)。因本人水平有限,在该应用中不免存在很多漏洞和不足;如果你有更多更好的想法或者发现该小应用中的bug还望批评指正。 ||联系方式:LHearen@gmail.com|| 五、免责声明 本系统仅用于学习交流之用,本人不承担该应用的技术及版权问题,且不对该应用负法律责任。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值