更新
项目地址
概述
前文通过分析Android 9源码,定位到Hook点,然后使用Xposed Hook,实现了Wifi热点IP的固定。
系统升级到Android 11后,发现源码有变化,插件不起作用了。于是再来操作一波。
Hook点
安卓10
android.net.ip.IpServer的getRandomWifiIPv4Address函数。
1 | private String getRandomWifiIPv4Address() |
安卓11
android.net.ip.IpServer的requestIpv4Address函数。
1 | private LinkAddress requestIpv4Address(s) { |
由于该函数还被用于其他方式的网络共享及更换前缀,所以需要判断网络类型(mInterfaceType == TETHERING_WIFI)和调用者(遍历堆栈查找configureIPv4),最后进行替换。
安卓10
源码分析
通过前文可知,设置热点IP的流程如下:
在configureIPv4函数中,首先调用getRandomWifiIPv4Address生成字符串形式的IP,然后转换为LinkAddress,最后调用ifcg.setLinkAddress设置IP地址。(其中ifcg类型为InterfaceConfiguration)
在源码中搜索setLinkAddress,可以发现有以下几处引用
其中/frameworks/base/services/net/java/android/net/ip/IpServer.java调用者为configureIPv4函数(官方文档:IP 服务重构路径)
查看源码IpServer.java#404,发现并无太大变化(增加了configureDhcp,已更新 DHCP 服务器),仍使用getRandomWifiIPv4Address生成随机IP地址:
1 | InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString); |
查找getRandomWifiIPv4Address的交叉引用,发现还是只有这一处。因此,修改Hook类名为android.net.ip.IpServer即可适配安卓10
Hook点
android.net.ip.IpServer的getRandomWifiIPv4Address函数,返回固定字符串即可。
1 | private String getRandomWifiIPv4Address() |
安卓11
源码分析
搜索setLinkAddress,仍然只有几处引用
相比于安卓10,IpServer.java和WifiP2pServiceImpl.java的引用消失了,变成了NetdWrapper.java的fromStableParcel和setInterfaceLinkAddress函数(官方文档:模块边界)
查找fromStableParcel的交叉引用,发现NetdWrapper.java和NetworkManagementService.java的getInterfaceConfig函数有调用。
查看源码,发现只有一行代码区别
1 | NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL); |
两者都是调用mNetdService.interfaceGetCfg(iface)获取配置。
查找setInterfaceLinkAddress的交叉引用,发现并没有函数调用它
于是搜索configureIPv4,发现只有一处引用,仍位于android.net.ip.IpServer类中
(由/frameworks/base/services/net/java/android/net/ip/IpServer.java移动到了/frameworks/base/packages/Tethering/src/android/net/ip/IpServer.java)
分析该函数(源代码IpServer.java#596),发现有:
1 | if (enabled) { |
而mIpv4Address是在configureIPv4函数开头设置的:
1 | if (enabled) { |
查看requestIpv4Address函数:
1 | private LinkAddress requestIpv4Address() { |
首先判断是否设置了静态IP,如果mStaticIpv4ServerAddr不为空则直接使用(由maybeConfigureStaticIp设置)。
然后判断是否为蓝牙,是则使用BLUETOOTH_IFACE_ADDR(192.168.44.1/24)。
其他情况调用mPrivateAddressCoordinator.requestDownstreamAddress(this)
后者位于frameworks/base/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
1 | public LinkAddress requestDownstreamAddress(final IpServer ipServer) { |
调用getRandomSubAddr生成子网地址,然后判断是否存在与上下游冲突。
查找requestIpv4Address交叉引用,发现还会被handleNewPrefixRequest调用,向上追溯找到onNewPrefixRequest(DHCP服务器通知前缀改变时触发)
1 | // request from DHCP server that it wants to have a new prefix |
Hook点
android.net.ip.IpServer的requestIpv4Address函数。
1 | private LinkAddress requestIpv4Address() |
由于该函数还被用于其他方式的网络共享及更换前缀,所以需要判断网络类型(mInterfaceType == TETHERING_WIFI)和调用者(遍历堆栈查找configureIPv4),最后进行替换。
PS:测试发现Android 11设置IP的包名不再是android,而是com.android.networkstack.tethering.inprocess
Hook代码
见GitHub:MainHook.java
参考
How can I permanently assign a static IP address to Wi-Fi clients? (Lineage OS 17.1 Android 10)