只需要5个
一般步骤是
[DllImport("wpcap.dll")] private static extern int pcap_findalldevs(ref IntPtr devicelist, StringBuilder errbuf); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] private struct pcap_if { public IntPtr next; public string name; public string description; public IntPtr addresses; public uint flags; }
pcap_findalldevs找到所有的网络接口
自己找到正确的那个
然后
[DllImport("wpcap.dll")] private static extern void pcap_freealldevs(IntPtr devicelist);
调用这种非托管的dll,包括winapi,弄完一样几乎都要相应的free一下,也几乎都有一个相应的free方法,这是c#不太习惯的
为什么要用pcap_findalldevs?虽然用System.Net.NetworkInformation命名空间里面的玩意可以多快好省的搞到一切信息吧,但是却不能保证winpcap可以打开这个设备啊,用winpcap的函数就相当于测试一下工作是否正常。
然后通过pcap_findalldevs找到相应的网络接口后
要pcap_if结构中的name
然后open
[DllImport("wpcap.dll")] private static extern IntPtr pcap_open(string source, int snaplen,int flags, int read_timeout, IntPtr auth, StringBuilder errbuf);
这个source就是上面那个name
打开后
[DllImport("wpcap.dll")] private static extern int pcap_sendpacket(IntPtr p, byte[] buff, int size);
pcap_sendpacket,这里发送的是以太网的数据包
其实以太网数据包和ip数据包相比,仅仅是在ip数据包前面多了14个字节
这里可能是个误区,好像以太网数据包在mac前面还有点东西,最后还有crc校验,但是对于用winpcap的pcap_sendpacket来说就等于ip包前多了14个字节而已
前6个是目标mac地址,接下来6个是本机网卡的mac地址,最后2个是协议类型,ip协议就是08 00
目标mac如何获得?
其实你用sniffer工具看一下就知道,就是网关的mac
比如我的机器是通过路由器上网的(路由器进行的PPPoE拨号)
那么发送时的以太网数据格式为
路由器mac(6字节)+网卡mac(6字节)+协议2字节+协议内容
这是我用ie连接时捕获的结果,返回的比如syn+ack就是网卡mac在前和路由mac在后仅此而已
自己构造好发出去就行了
于是就可以突破windows对于rawsocket的限制进行syn扫描或者攻击什么的了,只要能装winpcap的windows系统都可以。
最后
[DllImport("wpcap.dll")] private static extern void pcap_close(IntPtr p);
===========
补充一句,winpcap是不管矫正你的数据包的,像ip头的checksum你得算对了才能发出去呢。而rawsocket,系统会帮你矫正checksum的,不信你可以试试,用rawsocket即使不计算checksum把那俩字节全用0,系统照样给你算出checksum发出去,比如说我用rawsocket发出去了syn也收到了syn+ack,但是用winpcap发出去结果就收不到,我就奇怪了同样一个程序啊,结果用sniffer工具一看,用winpcap的ip checksum不对,我就更奇怪了,同样一个程序生成的Ip包,怎么checksum会不一样呢?折腾了半天发现,原来用rawsocket发送的ip包的checksum也是错误的,但是却被系统自己给改成了正确的,合着之前一直算错了,但rawsocket每次都给矫正发出去了,而winpcap是不给矫正的,算错了就发不出去,于是改对了checksum后,用winpcap发送syn也就可以正常接收到syn+ack了。