只需要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了。