本文仅供技术交流使用,相关信息已做模糊处理,请勿用于非法用途。

国庆出游7天,途中有2-3天手机会无信号,只能使用运输公司提供的WiFi。而根据公开的价格这个东西非常的坑,每个设备大概需要1000多块RMB。虽然相比路费不算多,但是作为搞安全的,能白嫖自然是最好的咯~

出发前准备

“巧妇难为无米之炊”,没有设备的支持在手机都没信号的地方也很难进行攻击,下面先梳理下我们需要达成的目标和需求。

首要目标:最理想的情况自然是通过漏洞找到出网路径,从而实现白嫖上网。考虑到便捷性,现场情况大概率是传统的公共WiFi模式上网,也即有一个无需认证的WiFi,设备连接上之后通过网关web页面进行进一步的认证。根据经验大概有下面几个攻击方式:

  • 无限试用攻击:如果提供了试用功能,因为没有手机信号大概率不会通过短信认证,而是根据MAC地址进行区分。可以考虑伪造MAC地址达到无限试用的目的。
  • 白名单流量伪造:公司想赚钱肯定需要让用户能够在无网环境下付款,如果采用电子支付方式必然存在白名单流量(如支付宝)。根据过滤方式,可以考虑伪造Host等方法伪装成白名单流量。
  • 传统防火墙绕过:认证网络也可以看作是一个在传统防火墙后的内网网段,因此各种传统绕过姿势也是适用的。

备选目标:当然也有可能防火墙非常牛逼,没有任何漏洞(笑),而且需要现金或信用卡现场支付开网,这样白嫖的想法就基本破灭了,不过还是能通过扩展二级网络的方式实现只付1台设备的钱让多台设备上网。

设备需求:无论是哪个目标,在手机上实现都是比较困难的(尤其是同行的人均是iOS的情况下,听说安卓机可以支持STA/AP苹果罪大恶极)。因此需要一个可定制化的设备进行,这个设备需要:

  • 小型化:因为活动范围比较大,需要带着设备走,从而保证可以连接到破解后的二级WiFi。要求大概是可以放到小挎包或口袋里。
  • 低能耗:同样因为需要移动,必须可以支持充电宝或电池供电,而且续航至少不间断运转10小时。
  • 可编程:因为要支持各种各样可能的破解方式,需要支持自定义程序运行,最好是类Linux或各种单片机系统。

听上去这个设备需求好像重新定义了手机,不过考虑到目前安卓机的root难度和我小白的安卓姿势水平,就不基于安卓献丑了哈哈~

方案1-树莓派(or 夸克?)

第一个想到的当然是之前退休的树莓派3B+了,配上充电宝24小时续航不成问题,而且是纯血Linux,开发非常方便,遇到奇怪的WiFi验证问题也可以有桌面环境能解决,唯一需要考虑的是双频WiFi的问题。因为根据之前的测试,3B+的信号并不算优秀。虽然理论上支持STA/AP模式,网速和信号可能也很头疼。因此最好就是买一个usb网卡插上去,外置网卡连认证WiFi,内置网卡开AP。于是乎狗东上买了下面这货:

WiFi6外置网卡

而这也是一切问题的开端,具体原因这里先按下不表,等下面的章节自然会揭晓。而第二个选择则是稚晖君的夸克电脑

Quark开发板

2*3cm尺寸让人非常心动,上tb一看价格400块,相比树莓派也只有尺寸优势了,打扰了。

我们先康康怎么进行基础的配置吧。

树莓派配置

刷系统不多说了,现在树莓派官方有提供刷机工具,一键完成ssh等配置,相比几年前降低了很多要求,重点看怎么把我们的网卡和AP配上。

首先买这个网卡就是看到有提供Linux驱动,然而很可惜,6.x版本以上的内核因为API修改并不能正常编译安装,官网驱动也好久没更新了(怎么有种上当的感觉……事实证明也确实上当了)。没办法只能自行解包修改,还好deb安装包内提供了源码,改吧改吧总算是跑起来了。修改后的驱动开源在Github,有需要可以自取:https://github.com/MXWXZ/aic8800d80fdrvpackage

重启后就能看到网卡的灯亮了,用 nmcli 也能看到识别成 wlan1 了,接下来我们将理论上信号更好的外置网卡连接wifi,树莓派自带的开启热点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看设备状态
sudo nmcli d status
# 自带网卡启用热点
sudo nmcli d wifi hotspot ssid *** password *** ifname wlan0
# 查看热点uuid
sudo nmcli connection show
# 查看热点配置
sudo nmcli connection show <uuid0>
# 配置自动连接
sudo nmcli connection modify <uuid0> connection.autoconnect yes connection.autoconnect-priority 999
# 外置网卡连接wifi
sudo nmcli d wifi connect "***" ifname wlan1
# 配置自动连接
sudo nmcli connection show
sudo nmcli connection modify <uuid1> connection.autoconnect yes connection.autoconnect-priority 999

最后装个 tigervnc 以方便在图形界面解决可能存在的认证奇怪问题就搞定了。

方案2-xiao

逛tb找设备时发现了好玩的东西,一个叫 xiao 的超mini开发版: https://wiki.seeedstudio.com/cn/xiao_esp32s3_getting_started/

xiao开发板

不愧叫xiao,整机尺寸达到了20x17.5mm,集成了typec,wifi、蓝牙、摄像头、麦克风,休眠功耗低至14μA。最最重要的是,最高级的Sense版狗东售价也才70几块钱,配上Wi-Fi天线也不超过100,哪个理工科学生能拒绝这种诱惑?

到货后观察了一番,没有外壳放包里可能会损坏,3D打印个壳子时间比较长,家里翻了翻找了个牙刷头的盒子开两个洞用作充电线和wifi天线(理论上来说用那种小药盒应该才是最佳选项,可惜翻了半天找到最小的就这个了)。

自制外壳

原本还有块3.7V的无人机电池,不过貌似好久没用了也不知道寿命咋样,就不折腾了还是用充电宝吧。

xiao软件配置

官方文档对于Arduino的说明比较详细,虽然也支持RTOS等其他开发方式,不过没有具体的教程。

开始我想的是用Zephyr RTOS系统自己写一个,看了看教程还挺好搞的。然而不知道是驱动代码的问题还是API没调对,STA/AP模式的DHCP一直无法分配地址,搞了几个小时解决不了弃疗了……最后还是用的Arduino,参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <WiFi.h>

#define AP_SSID "whosyourdaddy"
#define AP_PASS "12345678"

#define STA_SSID "***"
#define STA_PASS "12345678"

IPAddress ap_ip(192, 168, 77, 1);
IPAddress ap_mask(255, 255, 255, 0);
IPAddress ap_leaseStart(192, 168, 77, 11);
IPAddress ap_dns(114, 114, 114, 114);

int state = 0;

void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
pinMode(LED_BUILTIN, OUTPUT);

Serial.println("Program started");
digitalWrite(LED_BUILTIN, LOW);

Network.onEvent(onEvent);
WiFi.AP.begin();
WiFi.AP.config(ap_ip, ap_ip, ap_mask, ap_leaseStart, ap_dns);
WiFi.AP.create(AP_SSID, AP_PASS);
if (!WiFi.AP.waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) {
Serial.println("Failed to start AP");
return;
}
WiFi.begin(STA_SSID, STA_PASS);
}

void loop() {
delay(2000);
if (state == (1 << 2) - 1) {
digitalWrite(LED_BUILTIN, HIGH);
}
}

void onEvent(arduino_event_id_t event, arduino_event_info_t info) {
switch (event) {
case ARDUINO_EVENT_WIFI_STA_START:
Serial.println("STA Started");
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
Serial.println("STA Connected");
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.println("STA Got IP");
Serial.println(WiFi.STA);
WiFi.AP.enableNAPT(true);
state |= 1 << 1;
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
Serial.println("STA Lost IP");
WiFi.AP.enableNAPT(false);
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
Serial.println("STA Disconnected");
WiFi.AP.enableNAPT(false);
break;
case ARDUINO_EVENT_WIFI_STA_STOP:
Serial.println("STA Stopped");
break;
case ARDUINO_EVENT_WIFI_AP_START:
Serial.println("AP Started");
Serial.println(WiFi.AP);
state |= 1;
break;
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
Serial.println("AP STA Connected");
break;
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
Serial.println("AP STA Disconnected");
break;
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
Serial.print("AP STA IP Assigned: ");
Serial.println(IPAddress(info.wifi_ap_staipassigned.ip.addr));
break;
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED:
Serial.println("AP Probe Request Received");
break;
case ARDUINO_EVENT_WIFI_AP_STOP:
Serial.println("AP Stopped");
break;
default:
break;
}
}

实战

万事具备,趁手机还有信号抓紧时间破解。先简单看下网络环境,现场用的确实是传统公共wifi+二次认证的形式,但是付费采用的是信用卡预扣款,也没有免费试用的选项。不过简单扫扫就蚌埠住了,ping居然是通的,nc也可以通,不过三次握手后的数据会被过滤。到这里其实已经明确了,防火墙规则只是过滤TCP或UDP的Payload段,有一万种方法可以绕……

这边就不用那么麻烦了,利用Pingtunnel就能开一个socks5 -> ICMP的代理,然后笔记本就能配上socks代理出网了。至于手机上网懒得再写Arduino了,直接用树莓派开上socks代理,然后手机转发流量到树莓派的IP上就搞定了。

然而,这个时候就遇到了之前提到的国产外置网卡的巨坑了,对Linux支持差就不说了,修完的驱动貌似还存在未知bug,作为STA模式连接几分钟后就panic把内核搞炸了。没办法只能将其与内置网卡换一下,作为AP模式才能勉强能跑。但也存在未知bug,连接时间一长就只允许1台设备接入AP了,只能强制重启……不得不说TP-Link的东西无论是路由器还是啥,总有点毛病都有心理阴影了。

后记

虽然硬件有点小问题,但是多重启几次还是能用的(雾),最主要的是白嫖到了WiFi,还是很爽的。更妙的是找到了新玩具xiao,学习了一番RTOS开发,后面想出新玩法再说。