資源共享吧|易語言論壇|逆向破解教程|輔助開發(fā)教程|網(wǎng)絡(luò)安全教程|m.rigasin.com|我的開發(fā)技術(shù)隨記

標(biāo)題: http動(dòng)態(tài)注入(鏈路劫持) [打印本頁]

作者: show0p    時(shí)間: 2018-10-10 22:00
標(biāo)題: http動(dòng)態(tài)注入(鏈路劫持)
http動(dòng)態(tài)注入(鏈路劫持)
前置聲明
git:https://github.com/Erriy/data_pirate
email:[EMAIL="erriy@msn.com"]erriy@msn.com[/EMAIL]
攻擊靶機(jī)效果圖


已實(shí)現(xiàn)的與沒實(shí)現(xiàn)的
已實(shí)現(xiàn)

arp攻擊
三環(huán)路由功能
偽裝服務(wù)器與客戶端

沒實(shí)現(xiàn)

代碼殘缺,并不一定可運(yùn)行,僅在本機(jī)測試通過
雖采用c寫所有核心邏輯,但并未進(jìn)行移植測試
http流報(bào)首長度修正
chunked 編碼插入
gzip壓縮的數(shù)據(jù)緩存解壓后再進(jìn)行插入
tcp/ip首部校驗(yàn),判斷是否為壞包

說點(diǎn)沒用的,沒興趣可直接跳過
    (自認(rèn)為)代碼寫完了,狗啃的一樣,屎一樣的代碼,而且沒做內(nèi)存回收操作。就像魔術(shù)一樣,你知道了原理,就沒有什么樂趣可言了。代碼拖了很久拖到最后已經(jīng)不想寫了,但是之前興趣高昂的時(shí)候已經(jīng)到處扯了,吹過的牛b猶如潑出去的屎,想收回來可以,但是太臟了,所以到現(xiàn)在雖然寫的不是很完美,但基本功能均已實(shí)現(xiàn),所以我將它畫上句號。我哥問我說寫完了有成就感么?我說沒有,只有一種解脫感。興起時(shí),框架重寫都很有奔頭,興頭過了,敲鍵盤猶如搬磚,雖然代碼不多,但是人的懶惰是無止境的,幾個(gè)字母都不想敲。

    筆者無聊的時(shí)候想了一個(gè)軟件,基于云合作的一種軟件,其中各項(xiàng)功能其實(shí)很多軟件都有了,但是有些軟件總是很讓人反感,就想自己寫一個(gè)。電腦在兩臺以上的時(shí)候,互相間的傳輸很是麻煩,最初只是想寫一個(gè)跨平臺共享剪貼板的后臺服務(wù),然后用腦圖軟件一點(diǎn)一點(diǎn)的增加功能,最終感覺算是一個(gè)“個(gè)人云”的分布式服務(wù)了,這個(gè)時(shí)候就產(chǎn)生了一個(gè)問題,網(wǎng)絡(luò)編程我并不熟,那么就有必要去搞一搞了。(Ps:這個(gè)代碼可能下一步會搞,但是不知道會搞多久了,也不知道興趣能堅(jiān)持多久,做的感覺差不多時(shí)開源大家有興趣可以去玩玩,當(dāng)然現(xiàn)在八字還沒一撇)

    一說網(wǎng)絡(luò),首先想起的就是socket,但是當(dāng)初學(xué)習(xí)socket的時(shí)候,感覺很痛苦,各種參數(shù)什么的,到底是干什么的呢?特別是udp和tcp,到底有啥區(qū)別呢?底下的東西并不清楚,就會導(dǎo)致用起來的時(shí)候不是隨心應(yīng)手,出了問題也不好解決。其次是考慮到傳輸安全的問題,明文傳輸?shù)降资侨绾尾话踩模繛槭裁炊家f加密傳輸呢?那么再次考慮一下,加密傳輸這個(gè)加密通道怎么打通呢?如果開始時(shí)溝通一個(gè)密碼,那么這個(gè)密碼本身不也是明文傳輸?shù)拿矗磕敲醇用艿囊饬x不就沒了么?然后一點(diǎn)點(diǎn)的看到非對稱加密相關(guān)的東西,然后想了種方法,通過服務(wù)端保存私鑰,客戶端連接服務(wù)端獲取公鑰,認(rèn)證無誤后建立連接,客戶端通過生成隨機(jī)密碼(高強(qiáng)度)通過公鑰加密發(fā)送到服務(wù)端,然后服務(wù)端確認(rèn)開啟這條高強(qiáng)度對稱加密通道。自己感覺很是開心,好像發(fā)現(xiàn)了什么新大陸一樣,然后漸漸的了解的多了忽然發(fā)現(xiàn),原來這跟https的原理雷同,證書認(rèn)證的基本原理。好了,扯遠(yuǎn)了。反正就是網(wǎng)絡(luò)編程很不熟,就搞了《tcp/ip協(xié)議》第一卷看了下,也沒看完,就看了9章左右,感覺差不多理解了,就開始寫測試代碼吧。

    第一版測試代碼是基于linux內(nèi)核的netfilter框架寫的,大約用了兩百多行代碼,實(shí)現(xiàn)了tcp payload替換,將其中比較簡短的一些js直接替換為我的js代碼,直接alert彈窗。忘了說了,由于本身不屬于靶機(jī)的物理上層設(shè)備,就用arpspoof進(jìn)行arp劫持來讓自己變成中間人。當(dāng)時(shí)寫的比較簡陋,而且對tcp還是處于一種比較朦朧的狀態(tài),測試雖然成功,但是效果并不好,雖然注入成功,但是破壞了網(wǎng)頁本身的流程,不能正常加載。

    第二版測試代碼其實(shí)跟第一版很相近,但是代碼更多了些,將每個(gè)包的狀態(tài)都進(jìn)行了解析,基本屬于測試學(xué)習(xí)tcp協(xié)議本身的東西吧,測試效果并沒有改變。

    第三版改動(dòng)很大,由于一直處于內(nèi)核層操作,所以有很多很不方便的地方,而且效率問題影響很大,就想到有沒有什么辦法能讓我在ring3很穩(wěn)定的去搞這些東西呢?還有就是能不能windows端下,osx下,android下,甚至越獄的ios下都能進(jìn)行鏈路劫持呢?答案是有的,最簡單的方式就是原始套接字監(jiān)聽。下面就是整體邏輯的一些梳理了,進(jìn)入正題!
本版測試代碼邏輯
本版測試平臺

系統(tǒng) : osx 10.11.3
編譯器 :Apple LLVM version 7.0.2 (clang-700.1.81)
lib庫需求 :lpcap, lnet, lpthread, lz
(PS : 不能用vmware虛擬機(jī)測試,虛擬機(jī)的虛擬路由發(fā)包與常規(guī)網(wǎng)絡(luò)數(shù)據(jù)傳輸方式不同,懷疑為了效率考慮vmware虛擬路由邏輯底層直接進(jìn)行內(nèi)存拷貝操作然后經(jīng)由vmnet驅(qū)動(dòng)解析,但中間人攻擊后的數(shù)據(jù)(非本機(jī)IP數(shù)據(jù)包)并未解析,抓ip包異常之大(不確定,僅猜想,未深入測試))

以太網(wǎng)&arp&ip&tcp&http簡介(非標(biāo)準(zhǔn)化簡介)
    注意:本部分簡介只為本測試需要的功能進(jìn)行解釋,介紹并不完整,如想深入了解,請自行學(xué)習(xí)協(xié)議
    互聯(lián)網(wǎng)數(shù)據(jù)傳輸本質(zhì)上就是進(jìn)程通訊,只是這個(gè)通訊的速度相對于其它的進(jìn)程通訊更慢些,丟包率可能更高些。tcp/ip協(xié)議棧本身就像多級火箭一樣,一級一級的火箭推送只為護(hù)送有效載荷(payload)到達(dá)目標(biāo)。數(shù)據(jù)排放均為網(wǎng)絡(luò)字序。
以太網(wǎng)協(xié)議(IEEE802.3)簡介
1
2
3
4
5
6
7
8
9
struct _ethhdr
{
    unsigned char   h_dest[6];      // [00][01][02][03][04][05] target mac
    unsigned char   h_source[6];    // [06][07][08][09][10][11] source mac
#define _ETH_P_IP                       (0x0800)
#define _ETH_P_ARP                      (0x0806)
    unsigned short  h_proto;        // [12][13]
    // payload...
};


    包的傳輸以以太網(wǎng)地址(mac)為目標(biāo)發(fā)送,以太網(wǎng)頭部包含發(fā)送端mac地址,目標(biāo)端mac地址和攜帶數(shù)據(jù)的協(xié)議。內(nèi)網(wǎng)數(shù)據(jù)交換依照目標(biāo)mac地址來發(fā)送數(shù)據(jù)。mac地址并非無意義的一串字符,前三個(gè)字節(jié)代表廠商,通過mac地址掃描即可大致確定目標(biāo)設(shè)備是什么,當(dāng)一個(gè)目標(biāo)的mac地址為魅族旗下的,很大的可能是魅族手機(jī),而如果是技嘉的,則很大可能是pc(包含筆記本)。下載mac網(wǎng)卡廠商列表(http://standards-oui.ieee.org/oui.txt)自己做下簡單的搜索就行了,不贅述。順便推薦下讀者,沒事把自己的mac都改了吧。
arp協(xié)議簡介
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct _arphdr
{
    unsigned short  ar_hrd;   // [00][01]   format of hardware address
    unsigned short  ar_pro;   // [02][03]   format of protocol address
    unsigned char   ar_hln;   // [04]       length of hardware address
    unsigned char   ar_pln;   // [05]       length of protocol address
#define _ARP_REPLY                      (0x0002)
#define _ARP_REQUEST                    (0x0001)
    unsigned short  ar_op;    // [06][07]   ARP opcode (command)
    // use char[] against package
    unsigned char   ar_sha[6];// [08][09][10][11][12][13] sender hardware mac
    unsigned char   ar_sip[4];// [14][15][16][17]         sender IP address
    unsigned char   ar_tha[6];// [18][19][20][21][22][23] target hardware mac
    unsigned char   ar_tip[4];// [24][25][26][27]         target IP address
};


    地址解析協(xié)議,即ARP(Address Resolution Protocol),通過ip獲取mac地址的協(xié)議,主機(jī)發(fā)送信息時(shí)將包含目標(biāo)IP地址的ARP請求廣播到網(wǎng)絡(luò)上的所有主機(jī),并接收返回消息,以此確定目標(biāo)的物理地址;收到返回消息后將該IP地址和物理地址存入本機(jī)ARP緩存中并保留一定時(shí)間,下次請求時(shí)直接查詢ARP緩存以節(jié)約資源。
    本測試通過持續(xù)發(fā)送arp應(yīng)答包污染靶機(jī)與路由器,使其發(fā)送的ip包的下一跳是本機(jī),實(shí)現(xiàn)中間人流量劫持(中間人的一種簡單實(shí)現(xiàn)方式,實(shí)際流經(jīng)的任何一個(gè)路由交換設(shè)備都是中間人)。
ip協(xié)議簡介
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct _iphdr
{
#if defined(__LITTLE_ENDIAN_BITFIELD)
    unsigned char   ihl:4,version:4;    // [00] Internet Header Length(ihl)
#elif defined(__BIG_ENDIAN_BITFIELD)    // 4bit ip header max length = 0xf*4 = 60 bytes
    unsigned char   version:4,ihl:4;    // [00]
#else
    #error "check __LITTLE_ENDIAN_BITFIELD / __BIG_ENDIAN_BITFIELD"
#endif
    unsigned char   tos;                // [01]
    unsigned short  tot_len;            // [02][03] ipheader and payload len
    unsigned short  id;                 // [04][05] packet number
    unsigned short  frag_off;           // [06][07]
    unsigned char   ttl;                // [08]     time to live
#define _IPPROTO_TCP                    (0x06)
    unsigned char   protocol;           // [09]
    unsigned short  check;              // [10][11]
    unsigned int    saddr;              // [12][13][14][15] src ip
    unsigned int    daddr;              // [16][17][18][19] dst ip
    // The options start here.             [20]~[59]
    // payload...
};


    IP的責(zé)任就是把數(shù)據(jù)從源傳送到目的地。它不負(fù)責(zé)保證傳送可靠性,流控制,包順序和其它對于主機(jī)到主機(jī)協(xié)議來說很普通的服務(wù)。ihl字段表示ip頭部長度所占長度/4,一般為5,也就是ip頭部一般為20字節(jié),但并不所有都這樣,有興趣著可以去讀協(xié)議或者rfc文檔。tot_len字段表示本報(bào)文首部加運(yùn)載的數(shù)據(jù)總長度,通過此字段(字序轉(zhuǎn)換)-ihl*4得出的值是payload部分大小。check字段為校驗(yàn)碼,只校驗(yàn)ip首部是否正確。
    之前看過幾篇文章通過檢查id和ttl來判斷是否遭遇鏈路劫持,確實(shí)能看出來,但是如果攻擊者足夠心細(xì)的話,是很難檢測的。id字段代表發(fā)送端ip報(bào)文計(jì)數(shù)器,每發(fā)送一個(gè)ip報(bào)文都自加,有些粗心者在鏈路劫持時(shí)發(fā)送的id都是一樣的,或者隨機(jī)亂序的,很容易被發(fā)現(xiàn)。至于ttl,某種意義上時(shí)經(jīng)過的路由數(shù)的記錄,不同系統(tǒng)的初始值并不相同,亦可自行設(shè)置,每經(jīng)過一個(gè)路由ttl自減一,如有粗心大意者劫持某個(gè)ip時(shí),然后ttl初始為64,反推即可大致確定攻擊者位置(也可能經(jīng)過攻擊者篡改,無法確定定位到的是否是真的攻擊者)。
    路由通過目標(biāo)ip地址進(jìn)行轉(zhuǎn)發(fā),若下一跳并不是目標(biāo),則選路至最可能是目標(biāo)的下一路由,此時(shí)我們可以推測,如果當(dāng)前路由裝作已到達(dá)目標(biāo)然后發(fā)送回應(yīng),會發(fā)生什么?內(nèi)網(wǎng)測試hook 99.99.99.99 ip地址成功,通過攻擊機(jī)偽造tcp和http響應(yīng),攻擊靶機(jī)成功(如下圖所示,本版測試代碼已刪除,歷史版本中有)。

tcp協(xié)議簡介
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct _tcphdr
{
    unsigned short  source;     // [00][01]         source port
    unsigned short  dest;       // [02][03]         target port
    unsigned int    seq;        // [04][05][06][07] send sequence
    unsigned int    ack_seq;    // [08][09][10][11] ack sequence
#if defined(__LITTLE_ENDIAN_BITFIELD)
    unsigned short  res1:4,doff:4,fin:1,syn:1,rst:1,psh:1,ack:1,urg:1,ece:1,cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
    unsigned short  doff:4,res1:4,cwr:1,ece:1,urg:1,ack:1,psh:1,rst:1,syn:1,fin:1;
#else
    #error  "check __LITTLE_ENDIAN_BITFIELD / __BIG_ENDIAN_BITFIELD"
#endif                          // [12][13]         doff tcp hdr len
    unsigned short  window;     // [14][15]
    unsigned short  check;      // [16][17]
    unsigned short  urg_ptr;    // [18][19]
    // The options start here.     [20]~[59] mss,wsopt,sack-premitted,sack,tspot ...
    // payload...
};


    TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。(如出錯(cuò)歡迎糾正)我個(gè)人曾想過一個(gè)問題,tcp協(xié)議中涉及到各種各樣的算法,那么最重要的是什么呢?是tcp的超時(shí)重傳容錯(cuò)機(jī)制。tcp中涉及的慢啟動(dòng)算法什么的,并非tcp本質(zhì),而是一種完善,錦上添花,有必要去學(xué)習(xí),好處很多,但此文并不關(guān)注。
    source和dest字段是端口記錄,我曾經(jīng)非常不理解端口這個(gè)東西,看到這就很清晰了,端口號就是一個(gè)數(shù)字,這個(gè)數(shù)字與ip共同標(biāo)識一個(gè)tcp數(shù)據(jù)流,通過系統(tǒng)查表可知這個(gè)流是屬于哪個(gè)應(yīng)用的。寫到這想起曾經(jīng)學(xué)習(xí)socket時(shí)比較迷惑我的一個(gè)問題,NAT轉(zhuǎn)發(fā)導(dǎo)致的內(nèi)網(wǎng)不可穿透的問題,如不了解的可以自行想一下,實(shí)在想不出來再自行查資料,此處不贅述。(大牛請自行忽略)
    seq字段和ack_seq字段曾經(jīng)迷惑過我一段時(shí)間,sequence是順序的意思,seq標(biāo)示著發(fā)出去的包的序號,接收端可通過序號進(jìn)行重組,每發(fā)送多大數(shù)據(jù),下一個(gè)seq就是本seq+當(dāng)前包發(fā)送的payload數(shù)據(jù)大小,通過seq-初始seq可知已發(fā)送數(shù)據(jù)大。╯yn,fin包例外,本身占一位)。ack_seq代表本端已接收到的數(shù)據(jù),目標(biāo)端下一個(gè)seq應(yīng)該為多少。更形象一點(diǎn)來說,seq與ack_seq實(shí)際上維護(hù)了兩個(gè)內(nèi)存空間,本端發(fā)送的初始seq和當(dāng)前seq代表本端已發(fā)送的內(nèi)存空間數(shù)據(jù),對端發(fā)送的初始seq和本端發(fā)出去的ack_seq代表著本端已接收到對端的數(shù)據(jù)多少(包含syn,fin包)。
    doff代表tcp頭部所占32位空間大小,doff*4為本tcp首部所占內(nèi)存大小,由于doff最大為0xf,則tcp首部最大為0xf*4=60bytes。其他標(biāo)志位本文只關(guān)注syn,ack,fin,rst。三次握手經(jīng)常聽到,但是也沒有去怎么深入了解過。啊,首先還是說下ack吧,Acknowledgement,確認(rèn)字符,此位段代表ack_seq字段有效,確認(rèn)已接收到某部分?jǐn)?shù)據(jù)。然后來說三次握手:

    連接已建立了,那么這是就會想到,如果連接沒建立起來呢?syn-flood攻擊的原理你就理解了。不贅述,有興趣自行了解。
    鏈接建立后開始傳輸數(shù)據(jù),由于考慮到效率問題,不可能只發(fā)送一個(gè)包等待確認(rèn)之后才會繼續(xù)發(fā)送下一個(gè)包,這時(shí)引入滑動(dòng)窗口的概念,window字段,選項(xiàng)頭中的sack,sack-premitted,wsopt,mss字段。
    syn包時(shí)選項(xiàng)頭部包含了很多,由于window字段為short類型,能表示的最大值為65535,但緩沖區(qū)大小可能遠(yuǎn)大于此值,特wsopt選項(xiàng)部分表示窗口大小的倍數(shù),wsopt的值代表window右移的位數(shù),也就是擴(kuò)大了2的wsopt次方倍。例如window=1024,wsopt=14(取值0~14),則代表本端滑動(dòng)窗口為1024<<14。發(fā)送端無需接受確認(rèn)即可發(fā)送當(dāng)前滑動(dòng)窗口大小的數(shù)據(jù),窗口起始地址為當(dāng)前以被確認(rèn)(ack)的數(shù)據(jù)。一同發(fā)送這么多數(shù)據(jù)是有很大隱患的,此時(shí)引入sack機(jī)制,syn時(shí)sack-premitted表示當(dāng)前端是否支持sack功能,雙方均支持才產(chǎn)生實(shí)際作用。sack提供選擇性確認(rèn)技術(shù),即你說了那么多,但是我中間丟/壞了幾個(gè)包,你把中間那幾個(gè)包發(fā)給我,后邊的一段范圍內(nèi)的我都收到了,對端就會重新發(fā)那幾個(gè)包。window的值是不確定的,可能由于本地的緩存變小而不斷減小,當(dāng)接收端window為0時(shí)發(fā)送端等待。(關(guān)于選項(xiàng)包括sack的部分,自行了解,不贅述)。
    tcp好像差不多了,剩下的就是關(guān)閉tcp連接了。由于此連接是雙工的,所以關(guān)閉時(shí)兩端都要發(fā)送fin,當(dāng)然也是可以單向fin的,表示本端不再繼續(xù)發(fā)送數(shù)據(jù)了。四次揮手不贅述,有興趣自行查閱。
    最開始說tcp時(shí)想的遠(yuǎn)一點(diǎn)的讀者就能想到一個(gè)猥瑣的想法了,端口這個(gè)東西只是個(gè)數(shù)字,那么這個(gè)數(shù)字不是也能做一些文章么?一個(gè)木馬與遠(yuǎn)控端溝通時(shí)打通的tcp通道,經(jīng)常容易被端口檢測工具檢測到。那么我們就要做端口隱藏,深入到系統(tǒng)更深層次的hook,那么我們能不能更簡單一點(diǎn)的采用[I]端口寄生[/I]技術(shù)呢?不在本地再次開端口,而是采用本地已有應(yīng)用已經(jīng)打開的端口去發(fā)送我們的數(shù)據(jù)呢?通過原始套接字抓包監(jiān)聽是否為我們所要的包,如果你自身不監(jiān)聽的話,網(wǎng)絡(luò)驅(qū)動(dòng)會認(rèn)為此包無效自動(dòng)丟棄。我們通過自己設(shè)置的seq規(guī)則,或者說直接在ip選項(xiàng)部分或tcp選項(xiàng)部分加入自己的標(biāo)識,那么這個(gè)流的提取不成問題。問題在于會不會干擾正常流的接收。此方法我并未測試,但感覺非常大的可能性是可行的,即便tcp不行,我們也可以采用udp打穿內(nèi)網(wǎng)限制,像qq一系列的基本上很多電腦都有,udp端口偽造很簡單,而像服務(wù)器之類的,端口偽造就更簡單了,肯定是有固定端口開放的,不然就不叫服務(wù)器了。
    tcp的非正式介紹告一段落。
    忘了說一個(gè)rst,非正常關(guān)閉,唉,懶得介紹了,自己查吧,強(qiáng)制關(guān)閉,相信大家在fq的時(shí)候了解過這種東西。(感覺自己好不負(fù)責(zé)啊。。。)
http協(xié)議簡介
    超文本傳輸協(xié)議(英文:HyperText Transfer Protocol,縮寫:HTTP)是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議。設(shè)計(jì)HTTP最初的目的是為了提供一種發(fā)布和接收HTML頁面的方法。通過HTTP或者HTTPS協(xié)議請求的資源由統(tǒng)一資源標(biāo)識符(Uniform Resource Identifiers,URI)來標(biāo)識。
    http依賴于tcp,https依賴于ssl/tls,https不贅述,加密的,這個(gè)模塊日不了,也是可做攻擊的,比如我了解過的https降級攻擊和證書偽造攻擊,有興趣可自行了解。
    http request(請求)本文只介紹兩個(gè)個(gè):GET,POST。
    首先說我不是專門搞web的,所以這兩個(gè)介紹可能比較呆板,而且可能有錯(cuò)誤導(dǎo)向,歡迎指正。
    // 以下一段可能產(chǎn)生誤導(dǎo),勿偏信
    GET請求一般常用于跟服務(wù)器索要相應(yīng)的資源。POST一般用于提交什么表單什么的。這種方法是服務(wù)器的約定,我也可以自己寫個(gè)http服務(wù)器就特例化非要玩點(diǎn)不一樣的,我就POST不這么干,我GET也不這個(gè)意思,甚至我非要用gets來代替,倒是也行,但并不統(tǒng)一化(你還得自己在寫個(gè)瀏覽器,加載頁面時(shí)的所有uri你都用POST去加載)。
    Cookie,cookie劫持這個(gè)挺多人說的,原來我也不了解,由于網(wǎng)絡(luò)本身無法確定對方真的是誰,而每次都要輸入密碼還會讓人很不爽,所以http協(xié)議支持設(shè)置cookie存于本地,用于標(biāo)識身份,相當(dāng)于一個(gè)臨時(shí)身份證。這個(gè)cookie被劫持了,即便不知道用戶名密碼,一樣可以登錄上去。
    GET / HTTP/1.1\r\n 請求成三段,GET 為方法,/為uri資源標(biāo)識符, HTTP/1.1代表http協(xié)議1.1版。uri中常見的有這種形式的 /?type=xxxx&mode=xxx,?前的為請求資源標(biāo)識,后面的是參數(shù),各參數(shù)用&連接在一起。比如sql注入中常見的在標(biāo)題欄輸入的測試 /?id=xxxx and 1=2,看反饋是否與正常不同。
    Host字段,由于當(dāng)前訪問的ip可能存在多個(gè)域名,那么單純GET中的uri就不足以確定請求的資源是什么了,Host字段也給我們個(gè)方便,直接與uri拼接即可分析出當(dāng)前靶機(jī)訪問的頁面。
    If-Modified-Since 和If-None-Match ,這兩個(gè)字段可能導(dǎo)致服務(wù)器端并不會重新發(fā)送回請求的數(shù)據(jù)。字面理解第一個(gè)標(biāo)簽,如果修改了,表示本地已經(jīng)緩存了這個(gè)資源,如果服務(wù)器端的這個(gè)資源沒改變,則不用重發(fā),直接發(fā)回304,那么這個(gè)資源就不用重新再發(fā)一遍了,減少了網(wǎng)絡(luò)傳輸壓力,但是我們也哭了,因?yàn)檫@樣的話我們就沒有辦法修改了。第二個(gè)自行去看吧。(汗。。。)
    Accept-Encoding,表示我們接受什么樣的數(shù)據(jù)傳回,是否支持壓縮數(shù)據(jù),本測試代碼比較懶,不想徹底寫一遍tcp協(xié)議了,就設(shè)置了none,返回的數(shù)據(jù)很可能就不會是壓縮的了(有些流氓他不管你是不是none,反正我就返回壓縮的,你打我。浚,這樣我們就能直接插入我們想要的代碼了。如果是壓縮的,也是能搞的,尾部我會介紹一些其他的方案,本測試代碼方案并不完美,也并不簡單,更不高效,本測試代碼只是為了更深入了解協(xié)議棧所做的一些妥協(xié),其實(shí)不這么做也能把事情搞了。
    http response部分,主要是看Transfer-Encoding: chunked字段、Content-Length字段和Content-Encoding字段,返回值自然不用說了哈。
    Transfer-Encoding: chunked字段和Content-Length字段對應(yīng)關(guān)系,只有其一生效,如果一起會發(fā)生什么,我不知道,你自己試下吧。chunked編碼是一種不確定長度的傳輸方式,也就是說我并不知道我要傳輸多少數(shù)據(jù)。Content-Length就定長了。Content-Length本身表示整個(gè)報(bào)文首部后面的數(shù)據(jù)長度,接收端依次標(biāo)簽確定是否接受完了。chunked可以用一種現(xiàn)象很好的感覺出來,比如瀏覽器下載的時(shí)候,經(jīng)常碰到不知道文件多大,不知道什么時(shí)候能下載完的情況,這就可能是chunked編碼導(dǎo)致的(不確定,應(yīng)該是,沒去抓包看過)。chunked編碼的好處在于其不定長的數(shù)據(jù)傳輸方式,比如我的頁面是動(dòng)態(tài)生成的,那你就一定要等我生成完畢才能發(fā)么?這個(gè)等待時(shí)間雖然很少,但是網(wǎng)絡(luò)延遲有時(shí)已經(jīng)很高了,我們盡可能的讓客戶端少等待一點(diǎn)。于是我生成出來多少就發(fā)送多少。也可能是壓縮,為了壓縮傳輸如果定長的話我就一定要等待壓縮完畢才能去發(fā)送。chunked編碼很簡單,16進(jìn)制可打印字符標(biāo)記當(dāng)前chunked段的長度,然后\r\n,隨后跟這么長的數(shù)據(jù),然后下一chunked。以為0字段的chunked表示結(jié)束。
    這時(shí)我們應(yīng)該已經(jīng)很清晰了,如果我想動(dòng)態(tài)的插入代碼,那么我需要修正Content-Length或者chunked標(biāo)識長度的字段(本測試代碼并沒有做修正。。。懶得做分析了。。。好一種破罐子破摔的感覺。。。)。
    好了,一時(shí)就想到這么多。
代碼邏輯簡介
    將攻擊機(jī)為靶機(jī)與服務(wù)器的中間人(本測試通過arp簡單實(shí)現(xiàn),雙向arp欺騙),整個(gè)劫持過程的輸入采取類似嗅探器的原理,由于數(shù)據(jù)本身流經(jīng)本機(jī),所以并不用開啟網(wǎng)卡混雜模式(開了混雜其實(shí)也沒用,現(xiàn)在的路由設(shè)備發(fā)包并不廣播,也就是說其他mac地址的數(shù)據(jù)并不會嗅探到),但由于各個(gè)系統(tǒng)開啟路由轉(zhuǎn)發(fā)方式并不相同,所以本劫持的輸出部分為發(fā)出以太網(wǎng)數(shù)據(jù)包,劫持模塊中包含ip地址判斷,非發(fā)往本機(jī)的數(shù)據(jù)包通過發(fā)原始包形式轉(zhuǎn)發(fā)到下一跳。簡而言之,用嗅探和原始包發(fā)送做了個(gè)用戶層的路由功能。
    路由之前判斷,若tcp流目標(biāo)端口或原始端口為80,則認(rèn)定為http數(shù)據(jù)流,開始http劫持模塊。
    http劫持包含兩部分,一是是否需要劫持的判斷,二是已劫持的流的維持和后期校正。這中間就有個(gè)需求,需要將數(shù)據(jù)分流,本代碼采取hash表的形式分流,以原地址和目標(biāo)地址抑或、原端口和目標(biāo)端口抑或直接過再次求checksum為hash索引,為了效率以及代碼簡單性考慮(單線程延遲很高,未做效率優(yōu)化,判斷異常啰嗦),每個(gè)流對象都使用stalker開啟新線程追蹤(若考慮并行,可采取線程池輪流處理單個(gè)流對象)。
    stalker中封裝線程部分,通過回調(diào)函數(shù)來進(jìn)行實(shí)際的邏輯處理,由于tcp流的全雙工性質(zhì),設(shè)置中間過濾層(類似水壩),單向劫持發(fā)送偽造應(yīng)答,一定條件后開閘泄洪,發(fā)送經(jīng)本機(jī)修改后的偽造請求/應(yīng)答給目標(biāo)機(jī)器。
架構(gòu)簡圖

模塊理順
main(thread)
    主線程主做模塊初始化引導(dǎo)功能,平臺相關(guān)性很大,除去啟動(dòng)核心邏輯外,無太多實(shí)際功能。
sender
    sender模塊主做原始包發(fā)送,本測試代碼采用libnet進(jìn)行發(fā)送,不支持的平臺可直接采取原始套接字發(fā)送。
net_state
    net_state主做保存網(wǎng)絡(luò)狀態(tài)的事宜,由主線程初始化,設(shè)置本地網(wǎng)絡(luò)狀態(tài),提供其它各線程網(wǎng)絡(luò)狀態(tài)或目標(biāo)地址查詢功能
queue
    此模塊主要做多線程通信之用,只做了最簡單的雙進(jìn)程單向通訊,生產(chǎn)者消費(fèi)者模式,一個(gè)寫線程一個(gè)讀線程,算是單工模式吧。中途有一次自己模擬ipc進(jìn)程通訊機(jī)制寫了個(gè)itc線程通訊模塊,通過雙向queue來進(jìn)行全雙工溝通,但由于使用起來過于繁瑣,就扔了。
packet_info
    解析數(shù)據(jù)包模塊,類似linux netfilter框架中的sk_buff對象,但并未進(jìn)行優(yōu)化,由于為測試代碼,并不知道自己可能用到多少功能,所以獲取每個(gè)信息的時(shí)候都是重新運(yùn)算的。做效率優(yōu)化可以直接做成構(gòu)造函數(shù)中解析,然后直接讀成員變量就好了,效率能高很多。
tcp_stream
    此模塊主要做分流操作,分流原理上文已說,通過hash表分流(未做回收操作,懶得做了)
cheater(thread)
    通過主線程初始化,初始化后工作于另一線程,提供調(diào)用著接口,接口通過queue與線程溝通,線程循環(huán)主要做arp欺騙架起中間人工作。
hunter(thread)
    通過主線程初始化,本模塊采用libpcap抓包庫實(shí)現(xiàn),可能有些平臺并不支持,android下可采用原始套接字抓包嗅探,已在sony z1 compact(已root)測試成功,采用原始套接字嗅探(要求root),采用linux下的arm-none-linux-gnueabi-gcc工具鏈編譯arm原生程序,通過終端模擬器還有adb調(diào)用均測試成功(亦可采用ndk編譯,通過java層調(diào)用,先申請su權(quán)限)。本模塊主做抓包功能,做router的輸入。
stalker(every different thread)
    stalker采用并發(fā)編程(非并行),是用pthread庫,windows下需要自行添加pthread庫,或重寫此部分功能(代碼垃圾的很,移植這破代碼太不值了,看看然后自己寫吧)。由于pthread本身并不支持線程休眠功能,所以采用互斥鎖實(shí)現(xiàn)睡眠與喚醒,通過queue實(shí)現(xiàn)caller與stalker異步溝通,stalker隊(duì)列循環(huán)中若無消息則自行睡眠,caller推送消息時(shí)自動(dòng)喚醒stalker,主要功能實(shí)現(xiàn)處于stalker callback中。
其它方式的一些小思路
arp攻擊思路

    如上面的情況所示
    0代表正常的tcp流

    至于其它的中間人攻擊方式類似dhcp,dns什么的,請自行了解,不再贅述。當(dāng)然,你要本身就是個(gè)網(wǎng)關(guān),這些事情就不用考慮了,但了解下還是必要的。
我設(shè)想過的一種自認(rèn)更好的架構(gòu)和實(shí)現(xiàn)方式
    前面說過本測試代碼本身是為了學(xué)習(xí)tcp協(xié)議而寫的,并非為了真正使用,再說一句廢話就是,這個(gè)東西不僅僅可做壞事,比如動(dòng)態(tài)掛馬什么的,更可以做流量控制和訪問限制,況且如果不曾了解攻擊方式,那么我們自然也無法去防范這些事情,所以我認(rèn)為無論你是否對此感興趣,都有必要學(xué)習(xí)一下。扯遠(yuǎn)了,回來繼續(xù)。
    我曾設(shè)想過一種架構(gòu),算是一邊學(xué)習(xí)一邊產(chǎn)生出來的想法。說出來見笑了。
    寫這個(gè)模塊中途我去了解過一些chrome的架構(gòu)設(shè)計(jì)模式介紹,它的這種進(jìn)程消息傳遞機(jī)制當(dāng)時(shí)給了我很大的震撼,雖然這種東西很常見,但是之前卻很少注意到它。當(dāng)時(shí)我在寫分tcp分流模塊,然后就徹底改了一下分流部分,添加了雙線程讀/寫隊(duì)列,將處理與分發(fā)完全異步。當(dāng)時(shí)的一句話很震撼,大意是一個(gè)好的架構(gòu)可以讓開發(fā)更簡單,使用起來可以更肆無忌憚。唉?好像扯遠(yuǎn)了。回來。
    所有的模塊,用面向?qū)ο蟮乃枷雭砜,所有的東西都要有兩種東西,數(shù)據(jù)和方法。方法的本質(zhì)是處理數(shù)據(jù),我們在方法上再次分類,分為外部處理方法和內(nèi)部處理方法。內(nèi)部處理可以直接理解為引擎,外部處理方法可以理解為溝通。溝通再次分類就可能有兩種,輸入與輸出。分到這里,我們所有的東西都可能需要用的東西就出來了,可能有數(shù)據(jù),可能有內(nèi)部處理方法,可能有輸入,可能有輸出。從函數(shù)到內(nèi)存處理到計(jì)算機(jī)本質(zhì),甚至各種工具(比如車的引擎,輸入油,通過引擎內(nèi)部“函數(shù)”處理,輸出動(dòng)能和熱能以及尾氣),以及人的本身,都這么幾種方法。扯遠(yuǎn)了,倒是感覺越來越理解Object類了。我們的每個(gè)模塊都可以設(shè)置成object類型,提供輸入輸出與內(nèi)部處理,將內(nèi)部完全封裝,通過一種自定義的通訊模式,噢,不,通訊模式本身也封裝成這種類型,組成一個(gè)擁有以下幾個(gè)具象功能的類:

進(jìn)程/線程/模塊溝通類
抓包類
發(fā)包類
處理類
輸出類(輸出到文件、ui刷新等等)
線程/進(jìn)程/模塊類

    通過主模塊啟動(dòng)抓包類模塊,通過抓包類模塊啟動(dòng)處理類模塊,處理類模塊處理完成后調(diào)起輸出類,輸出自行決定是否dump,是否調(diào)用發(fā)包類發(fā)出去,是否發(fā)送到主模塊進(jìn)行ui刷新。所有模塊都繼承于溝通類和線程/進(jìn)程/模塊類。每個(gè)模塊都可能是一個(gè)線程或者一個(gè)單獨(dú)的進(jìn)程,或者其它的不同的語言寫的操作的模塊,遵循一些協(xié)議。
    再具象化到這個(gè)真實(shí)的程序,以下所有均為異步操作,通過消息機(jī)制傳遞。我們可以將嗅探和發(fā)包還有輸出寫成服務(wù),自我定義一系列消息結(jié)構(gòu)體來傳輸消息。我們可以在寫一個(gè)arpspoof(本來就有這個(gè)程序),自己去調(diào)用我們自己寫的發(fā)包服務(wù)來進(jìn)行arp污染操作。我們在寫一個(gè)路由模塊,通過嗅探服務(wù)接收到的數(shù)據(jù)進(jìn)行處理判斷,發(fā)送至輸出類,輸出通過消息類型判斷是否是需要dump的,是否是需要發(fā)出去。(PS:我不知道printf本身是不是多線程無鎖的,如果printf本身就是有鎖的,那么我的測試代碼中不止發(fā)包時(shí)有鎖,logout時(shí)本身就是一種互斥行為,但如果把所有的消息都彈出到異步輸出類中統(tǒng)一處理,即可效率最大化,再ps:消息傳遞本身可能會有損耗,這就要看情況進(jìn)行優(yōu)化了)。
    還有一個(gè)就是更實(shí)際一點(diǎn)的代碼優(yōu)化了,測試代碼本身就要在中間做filter做大壩攔截緩存的,但是由于懶惰問題我并沒有進(jìn)行緩存處理。這種情況下,其實(shí)我們主要搞一個(gè)fakeserver就好了,維持與靶機(jī)的溝通,做一個(gè)虛假的中間緩存服務(wù)器。然后另一方面把dump出來的請求通過socket直接正常與服務(wù)器溝通,把接收的數(shù)據(jù)通過我們的fakeserver發(fā)回客戶端。不畫圖了,就這樣吧。
代碼總結(jié)
    說到這里基本上邏輯已經(jīng)理清了,代碼本身就不說了,我的代碼本身很垃圾,有興趣的倒是可以大致看那么一眼,我總覺得主要是思路理清了比代碼看得明白更重要。希望讀到這里的你沒感覺失望,如果能幫助到你,實(shí)在是一件值得快樂的幸事。
防止鏈路劫持安全建議
    我曾笑著跟朋友開玩笑說,了解了越多的網(wǎng)絡(luò),就越發(fā)現(xiàn)安全是那么脆弱。有很多人并不注意安全,或者說有很多人都只注重軟件安全卻忽略了其他的比如網(wǎng)絡(luò)安全。我之前玩過一個(gè)android軟件,打開大致看了下加了360的殼,然后懶得分析,直接用我的ring3路由內(nèi)網(wǎng)arp攻擊后抓包,全是明文的,而且還非常簡單的表單,不到兩分鐘就直接破了。這是個(gè)小的“福利”軟件,個(gè)人作坊做的,我真的很想提醒他被爆菊了。
開發(fā)篇

平時(shí)使用篇

    好了,就這些,感覺以上都是廢話,其實(shí)我說完了我本身都不會這么做,我已經(jīng)破罐子破摔了,希望沒有人盯上我。。。
總結(jié)(最后那么一點(diǎn)點(diǎn)廢話)
    勿以善小而不為,勿以惡小而為之。好壞之評定非常困難,希望大家都有自己認(rèn)為更好的價(jià)值觀。我們每個(gè)人都做過不少壞事,但不能因?yàn)樽约鹤鲞^壞事就覺得虱子多了不嫌癢了,我本身并不是什么好人,不能說什么太高尚的話。我希望大家能在做什么之前想起我最近經(jīng)常想的一個(gè)問題:為什么現(xiàn)實(shí)社會中你不會去偷別人東西而虛擬網(wǎng)絡(luò)中就會想做這樣的事情呢?是現(xiàn)實(shí)社會中的懲罰來得更直接,給你的恐懼驅(qū)使你不去做么?那么也許在網(wǎng)絡(luò)上才真正能體現(xiàn)一個(gè)人的本性吧。
    謝謝你的耐心閱讀,希望有幫到你。


作者: drobox    時(shí)間: 2018-10-11 17:50
我把所有文字看完了···




歡迎光臨 資源共享吧|易語言論壇|逆向破解教程|輔助開發(fā)教程|網(wǎng)絡(luò)安全教程|m.rigasin.com|我的開發(fā)技術(shù)隨記 (http://m.rigasin.com/) Powered by Discuz! X3.4