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

 找回密碼
 注冊成為正式會員
查看: 2484|回復(fù): 1
打印 上一主題 下一主題

[網(wǎng)絡(luò)安全/滲透測試] http動態(tài)注入(鏈路劫持)

[復(fù)制鏈接]

715

主題

1223

帖子

1

精華

終身高級VIP會員

Rank: 7Rank: 7Rank: 7

資源幣
11472
積分
4971
貢獻
0
在線時間
2065 小時
注冊時間
2015-4-20
最后登錄
2024-7-9

終身VIP會員

跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2018-10-10 22:00:10 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
http動態(tài)注入(鏈路劫持)
前置聲明

  • [I]本測試代碼僅供安全測試以及網(wǎng)絡(luò)協(xié)議學(xué)習(xí)之用,由本代碼所造成的一切后果,本人概不負責(zé)[/I]
  • 本代碼初始為簡單學(xué)習(xí)tcp協(xié)議之用,實現(xiàn)劫持功能并非最簡單方式
  • 代碼寫作到后期已經(jīng)如同搬磚,興趣索然,由于筆者精力以及知識有限,而且項目學(xué)習(xí)之中略有感悟,此份代碼架構(gòu)并不優(yōu)美,結(jié)束時會簡單描述下我想要達成的那種自我感覺更優(yōu)美的框架結(jié)構(gòu)
  • 本文盡可能的口述化的描述一些問題,可能很多地方并不會使用一些專業(yè)化術(shù)語,也有可能描述略有偏差,歡迎指出,如果深入學(xué)習(xí)推薦讀者去學(xué)習(xí)《tcp/ip協(xié)議》三卷
  • 最后一點,我說什么東西都挺墨跡的,讀的時候別著急哈
git:https://github.com/Erriy/data_pirate
email:[EMAIL="erriy@msn.com"]erriy@msn.com[/EMAIL]
攻擊靶機效果圖


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

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

沒實現(xiàn)

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

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

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

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

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

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

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

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

以太網(wǎng)&arp&ip&tcp&http簡介(非標準化簡介)
    注意:本部分簡介只為本測試需要的功能進行解釋,介紹并不完整,如想深入了解,請自行學(xué)習(xí)協(xié)議
    互聯(lián)網(wǎng)數(shù)據(jù)傳輸本質(zhì)上就是進程通訊,只是這個通訊的速度相對于其它的進程通訊更慢些,丟包率可能更高些。tcp/ip協(xié)議棧本身就像多級火箭一樣,一級一級的火箭推送只為護送有效載荷(payload)到達目標。數(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)為目標發(fā)送,以太網(wǎng)頭部包含發(fā)送端mac地址,目標端mac地址和攜帶數(shù)據(jù)的協(xié)議。內(nèi)網(wǎng)數(shù)據(jù)交換依照目標mac地址來發(fā)送數(shù)據(jù)。mac地址并非無意義的一串字符,前三個字節(jié)代表廠商,通過mac地址掃描即可大致確定目標設(shè)備是什么,當(dāng)一個目標的mac地址為魅族旗下的,很大的可能是魅族手機,而如果是技嘉的,則很大可能是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é)議,主機發(fā)送信息時將包含目標IP地址的ARP請求廣播到網(wǎng)絡(luò)上的所有主機,并接收返回消息,以此確定目標的物理地址;收到返回消息后將該IP地址和物理地址存入本機ARP緩存中并保留一定時間,下次請求時直接查詢ARP緩存以節(jié)約資源。
    本測試通過持續(xù)發(fā)送arp應(yīng)答包污染靶機與路由器,使其發(fā)送的ip包的下一跳是本機,實現(xiàn)中間人流量劫持(中間人的一種簡單實現(xiàn)方式,實際流經(jīng)的任何一個路由交換設(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ù)從源傳送到目的地。它不負責(zé)保證傳送可靠性,流控制,包順序和其它對于主機到主機協(xié)議來說很普通的服務(wù)。ihl字段表示ip頭部長度所占長度/4,一般為5,也就是ip頭部一般為20字節(jié),但并不所有都這樣,有興趣著可以去讀協(xié)議或者rfc文檔。tot_len字段表示本報文首部加運載的數(shù)據(jù)總長度,通過此字段(字序轉(zhuǎn)換)-ihl*4得出的值是payload部分大小。check字段為校驗碼,只校驗ip首部是否正確。
    之前看過幾篇文章通過檢查id和ttl來判斷是否遭遇鏈路劫持,確實能看出來,但是如果攻擊者足夠心細的話,是很難檢測的。id字段代表發(fā)送端ip報文計數(shù)器,每發(fā)送一個ip報文都自加,有些粗心者在鏈路劫持時發(fā)送的id都是一樣的,或者隨機亂序的,很容易被發(fā)現(xiàn)。至于ttl,某種意義上時經(jīng)過的路由數(shù)的記錄,不同系統(tǒng)的初始值并不相同,亦可自行設(shè)置,每經(jīng)過一個路由ttl自減一,如有粗心大意者劫持某個ip時,然后ttl初始為64,反推即可大致確定攻擊者位置(也可能經(jīng)過攻擊者篡改,無法確定定位到的是否是真的攻擊者)。
    路由通過目標ip地址進行轉(zhuǎn)發(fā),若下一跳并不是目標,則選路至最可能是目標的下一路由,此時我們可以推測,如果當(dāng)前路由裝作已到達目標然后發(fā)送回應(yīng),會發(fā)生什么?內(nèi)網(wǎng)測試hook 99.99.99.99 ip地址成功,通過攻擊機偽造tcp和http響應(yīng),攻擊靶機成功(如下圖所示,本版測試代碼已刪除,歷史版本中有)。

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

  • client通過發(fā)送syn(synchronous 同步)包給server,由于此時并未接收到server發(fā)來的數(shù)據(jù),所以ack未設(shè)置,ack_seq無效。當(dāng)前發(fā)送的seq為本地發(fā)送的初始序列號,可理解為隨機生成(深入研究還有點規(guī)律,此文忽略),攜帶一些附加選項(同步用附加選項一會細說)
  • server接收到client發(fā)送的syn包后,發(fā)送自己的syn包給client,由于client已經(jīng)傳輸了數(shù)據(jù),所以server要告訴client本地已經(jīng)收到了,ack字段設(shè)置,ack_seq=client發(fā)送的seq+1(再次強調(diào)網(wǎng)絡(luò)字序問題),表示我們已經(jīng)收到ack_seq-client.seq = 1數(shù)據(jù)(并非syn包攜帶數(shù)據(jù)為1字節(jié)),順便生成了當(dāng)前tcp流的初始seq,攜帶一些同步用附加選項(tcp全雙工)
  • client收到server的syn&ack包之后,同樣發(fā)送個ack給server確認已收到,此時tcp連接已建立。

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

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

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

  • 是目前測試代碼中的方式,我們通過雙向欺騙,告訴客戶端我們是服務(wù)器/路由器,告訴服務(wù)器/路由器我們是客戶端。然后流經(jīng)過我們之后才會傳到對方。
  • 是一種dns污染模式,我們單向欺騙服務(wù)端/路由器說我們是客戶端,所有去往客戶端的流量都被劫持,此時我們做單向路由,把正常的數(shù)據(jù)都繼續(xù)轉(zhuǎn)發(fā)給客戶端。然后到dns解析時我們直接將dns應(yīng)答結(jié)果替換成我們的ip地址,這時這個鏈接就是一個偽造的服務(wù)端連接了。中間人通道成功架起。
  • proxy代理模式,或者說NAT轉(zhuǎn)發(fā)模式,這種模式下我們只欺騙客戶端說我們是路由器/服務(wù)器,客戶端的所有流量都在我們的掌控之下,此時我們即是靶機的上層設(shè)備了,可以直接模擬路由進行NAT轉(zhuǎn)發(fā)操作,也可直接提取鏈接,然后開啟一個服務(wù)去正常訪問服務(wù)器,然后將返回結(jié)果再次重新返回給靶機,中途自然你想做什么就做什么了。

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

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

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

  • 通訊一定要加密!最好使用比如openssl這種方式,當(dāng)然你有精力并且技術(shù)足夠完全可以自己寫,即便不是也最好把關(guān)鍵的地方加密
  • 登錄相關(guān)一定不要明文傳輸,最好存儲散列摘要,最好自己外面再添加一些別的獨有的信息,防止直接從別的社工褲拖散列登陸
  • 收到的數(shù)據(jù)要校驗!自己在自己的數(shù)據(jù)中插校驗散列值,防止被盯上了,一段時間一換方式,不要采用大眾都使用的方式

平時使用篇

  • 密碼一定要不同,即便有很多相同的,也要把重要的幾個密碼單獨設(shè)置
  • 不要為了某些原因就去使用不可信的代理服務(wù)器,即便使用,記得用隱私模式,不要做登陸相關(guān)的操作,防止中間代理服務(wù)器嗅探
  • 使用強力防火墻,有些殺毒軟件很有意思,默認不開防火墻
  • 公共wifi安全性很低,盡可能不要做任何有關(guān)個人重要事情的操作。
  • 自家wifi定期檢查,最好設(shè)置mac白名單,關(guān)wps/qss功能,使用高強度密碼,包含各種符號,16位以上
  • 不要使用不可信任的瀏覽器插件
  • 定期清理緩存,防止緩存投毒

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

回復(fù)

使用道具 舉報

3

主題

326

帖子

0

精華

終身高級VIP會員

蒙古國海軍總司令

Rank: 7Rank: 7Rank: 7

資源幣
785
積分
736
貢獻
0
在線時間
152 小時
注冊時間
2017-9-22
最后登錄
2022-10-21

終身VIP會員

沙發(fā)
發(fā)表于 2018-10-11 17:50:02 | 只看該作者
我把所有文字看完了···
回復(fù) 支持 反對

使用道具 舉報

 點擊右側(cè)快捷回復(fù)  

本版積分規(guī)則

小黑屋|資源共享吧 ( 瓊ICP備2023000410號-1 )

GMT+8, 2025-4-18 16:47 , Processed in 0.057325 second(s), 14 queries , MemCached On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回復(fù) 返回頂部 返回列表