今天无聊在手机上翻了一下开发者选项,无意中发现测试功能里面有一个叫WiFi嗅探
的功能。听到Wifi
嗅探的功能我的第一反应就是曾经使用抓包的方式可以破解WEP
加密。或者是抓取公开wifi的网络流量。
大部分关于嗅探的教程都是需要购买特定型号的无线网卡的,但一加手机的开发者选项里面居然有这个功能,这么好玩的功能当然是要试试看了。
输出文件是pacp
格式,复制到电脑上可以用Wireshark
打开看到802.11
数据包
既然一加是高通Soc,那其他的高通Soc手机能否使用这个功能?这个功能如何使用命令启动?这便是这篇文章的目的
从这个应用开始 既然这是从一个测试APP找到的,那么自然从这个app入手了。使用adb
找到当前activity
,然后将该程序的apk
复制到电脑使用jadx
打开
打开后,一眼就找到了一个叫做WifiSniffer
的类
然后找到了下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private void setSnifferEnabled (boolean z) { if (z) { Log.i("WifiSniffer" , "Start sniffing." ); Toast.makeText(getApplicationContext(), getString(2131690071 ), 0 ).show(); Utils.setSystemProperty("vendor.wlan.sniffer.file" , "airport_" + getCurrentTime() + ".pcap" ); Utils.transact("OEM_WIFI_SNIFFLOG_START" ); Handler handler = this .mHandler; handler.sendMessage(handler.obtainMessage(0 , 10 , 1 )); return ; } Log.i("WifiSniffer" , "Stop sniffing." ); Toast.makeText(getApplicationContext(), getString(2131690075 ), 0 ).show(); Utils.transact("OEM_WIFI_SNIFFLOG_STOP" ); Handler handler2 = this .mHandler; handler2.sendMessage(handler2.obtainMessage(0 , 10 , 0 )); }
继续查找Utils.transact
的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static synchronized String transact (String str) { synchronized (Utils.class) { if (!connect()) { Log.e("OpLogkit Utils" , "connection failed" ); return "-1" ; } if (!writeCommand(str)) { Log.e("OpLogkit Utils" , "write command failed? reconnect!" ); if (!connect() || !writeCommand(str)) { return "-1" ; } } Log.i("OpLogkit Utils" , "send: '" + str + "'" ); return "1" ; } }
继续查找writeCommand
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 public static boolean writeCommand (String str) { byte [] bytes = str.getBytes(); int length = bytes.length; byte [] bArr = new byte [1024 ]; if (length >= 1 && length <= bArr.length) { bArr[0 ] = (byte ) (length & 255 ); bArr[1 ] = (byte ) ((length >> 8 ) & 255 ); try { mSocketOut.write(bArr, 0 , 2 ); mSocketOut.write(bytes, 0 , length); mSocketOut.flush(); return true ; } catch (IOException e) { Log.e("OpLogkit Utils" , "write socket error" ); disconnect(); e.printStackTrace(); } } return false ; } public static boolean connect () { if (mSocket != null ) { return true ; } Log.i("OpLogkit Utils" , "socket connecting..." ); try { mSocket = new LocalSocket(); mSocket.connect(new LocalSocketAddress("oemlogkit" , LocalSocketAddress.Namespace.RESERVED)); mSocket.setSoTimeout(120000 ); mSocketIn = mSocket.getInputStream(); mSocketOut = mSocket.getOutputStream(); return true ; } catch (IOException e) { disconnect(); e.printStackTrace(); return false ; } }
看起来关键的逻辑并不在这个apk
里,这个apk干了下面几件事情
设置了几个prop
,prop
可以简单认为是系统配置
向一个本地的UnixSocket
发送了一些信息
到native 很显然,大部分逻辑应该都在oemlogkit
这个UnixSocket
对应的程序里。通过查找文档,找到了这个文件的路径是/dev/socket/oemlogkit
。但是这没啥用。
到处找找吧,使用ps -A | grep oem
可以找到一个叫做oemlogkit
的进程
1 2 3 4 5 6 127|OnePlus7Pro:/dev/socket $ ps -A | grep oem root 412 2 0 0 0 0 I [oem_key_dump] root 1032 1 12366952 1336 0 0 S oemlogkit system 6103 812 16067252 110532 0 0 S com.oem.oemlogkit root 26341 1032 0 0 0 0 Z [oemlogkit] system 27653 812 15906224 52108 0 0 S com.oem.logkitsdservice
使用 which oemlogkit
可以找到该进程的文件路径
1 2 OnePlus7Pro:/dev/socket $ which oemlogkit /system_ext/bin/oemlogkit
使用adb将这个文件拉到电脑上,发现这是一个elf
二进制文件,使用ida
载入,然后找到了下面的代码
这些代码最主要部分还是修改了几个prop
,同时也从prop
里获取信息
其中最重要的是vendor.wlan.sniffer.enabled
;同时也可以看到抓包使用的程序是熟悉的tcpdump
。
进入prop 修改一个prop
就能启动监听模式,起初我以为这是内核的事情,在GitHub的一加内核代码仓库里搜索了半天没有任何结果。
使用adb shell setprop vendor.wlan.sniffer.enabled 1
得到了一个权限错误
1 2 Failed to set property 'vendor.wlan.sniffer.enabled' to '1'. See dmesg for error reason.
可以使用dmesg
查看原因?然而使用的时候提示权限不足。。。这时候想起来开发人员工具内可以抓取内核日志,于是抓取日志找到了下面的信息
1 2 3 4 5 6 7 8 9 10 11 12 08-09 18:31:12.849 0 0 I [20210809_18:31:12.844281]@7 init: processing action (vendor.wlan.sniffer.enabled=1) from (/vendor/etc/init/hw/init.oem.rc:785) 08-09 18:31:12.849 0 0 I [20210809_18:31:12.844911]@7 init: starting service 'launch_sniffer'... 08-09 18:31:12.945 0 0 I [20210809_18:31:12.945092]@4 [sh][0xc5673c92c51][18: 31:12.945089] wlan: [20078:I:HDD] __hdd_driver_mode_change: 15669: Driver mode changing to 4 ...... 08-09 18:31:25.854 0 0 I [20210809_18:31:25.853580]@6 init: processing action (vendor.wlan.sniffer.enabled=0) from (/vendor/etc/init/hw/init.oem.rc:789) 08-09 18:31:25.863 0 0 I [20210809_18:31:25.858894]@7 init: starting service 'terminate_sniffer'... 08-09 18:31:25.884 0 0 I [20210809_18:31:25.881416]@5 init: processing action (vendor.wlan.sniffer.dump=1) from (/system_ext/etc/init/wifi-events.rc:75)
这下就应该去/vendor/etc/init/hw/init.oem.rc
找信息了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 service launch_sniffer /vendor/bin/sh /vendor/bin/launch_sniffer.sh ${vendor.wlan.sniffer.iface} ${vendor.wlan.sniffer.channel} ${vendor.wlan.sniffer.bandwidth} class main user root group root disabled oneshot service terminate_sniffer /vendor/bin/sh /vendor/bin/terminate_sniffer.sh class main user root group root disabled oneshot #endif
找到了两个脚本。但是我的设备没有root。
启动脚本 最后找了朋友得到了这两个文件的内容
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 # !/vendor/bin/sh # launch_sniffer.sh iface=$(getprop vendor.wlan.sniffer.iface) channel=$(getprop vendor.wlan.sniffer.channel) bandwidth=$(getprop vendor.wlan.sniffer.bandwidth) vendor_dir=$(getprop vendor.wlan.sniffer.vendor_dir) file=$(getprop vendor.wlan.sniffer.file) setprop vendor.wlan.sniffer.pid 0 mkdir -p $vendor_dir if [ ! $(echo $vendor_dir | grep "/$") ] then vendor_dir=$vendor_dir/ fi vendor_path=$vendor_dir$file if [[ $(lsmod | grep "^wlan") == "" ]] then insmod /vendor/lib/modules/qca_cld3_wlan.ko sleep 1 fi ifconfig $iface down sleep 3 echo 4 > /sys/module/wlan/parameters/con_mode ifconfig $iface up if [ $bandwidth -eq "80" ] then iwpriv $iface setMonChan $channel 2 else bandwidth=HT$bandwidth iw dev $iface set channel $channel $bandwidth fi tcpdump -i $iface -w $vendor_path & setprop vendor.wlan.sniffer.pid $!
1 2 3 4 5 6 7 8 9 10 11 12 13 # !/vendor/bin/sh # terminate_sniffer.sh iface=$(getprop vendor.wlan.sniffer.iface) pid=$(getprop vendor.wlan.sniffer.pid) kill -s SIGINT $pid setprop vendor.wlan.sniffer.pid 0 ifconfig $iface down sleep 3 echo 0 > /sys/module/wlan/parameters/con_mode ifconfig $iface up
可以所有的逻辑都很明显了
总结一下就是下面的代码。很显然这个功能应该是高通设备都能用的,只是需要iwpriv
和tcpdump
两个程序。这两个程序不知道其他设备是否自带
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 开启 ifconfig wlan0 down sleep 3 echo 4 > /sys/module/wlan/parameters/con_mode ifconfig wlan0 up iwpriv wlan0 setMonChan 频道 2 tcpdump -i wlan0 -w 路径 # 关闭 ifconfig wlan0 down sleep 3 echo 0 > /sys/module/wlan/parameters/con_mode ifconfig wlan0 up
后续 既然是通用的,可以写个小软件来快速使用这个功能。但是我root过的手机放学校了没带回家(雾),那就开学再见吧