Use reflection instead of parcel magic to get around networkName check

This commit is contained in:
Mygod
2021-05-27 12:22:47 -04:00
parent ea076d9602
commit b6bdf8cfb7
3 changed files with 20 additions and 41 deletions

View File

@@ -167,6 +167,7 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (since API 26) `Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V,unsupported` * (since API 26) `Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V,unsupported`
* (prior to API 26) `Landroid/net/wifi/WifiManager;->setWifiApEnabled(Landroid/net/wifi/WifiConfiguration;Z)Z` * (prior to API 26) `Landroid/net/wifi/WifiManager;->setWifiApEnabled(Landroid/net/wifi/WifiConfiguration;Z)Z`
* `Landroid/net/wifi/p2p/WifiP2pConfig$Builder;->MAC_ANY_ADDRESS:Landroid/net/MacAddress;,blocked` * `Landroid/net/wifi/p2p/WifiP2pConfig$Builder;->MAC_ANY_ADDRESS:Landroid/net/MacAddress;,blocked`
* (since API 29) `Landroid/net/wifi/p2p/WifiP2pConfig$Builder;->mNetworkName:Ljava/lang/String;,blocked`
* `Landroid/net/wifi/p2p/WifiP2pManager;->startWps(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/WpsInfo;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V,max-target-r` * `Landroid/net/wifi/p2p/WifiP2pManager;->startWps(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/WpsInfo;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V,max-target-r`
* (since API 28, prior to API 30) `Landroid/provider/Settings$Global;->SOFT_AP_TIMEOUT_ENABLED:Ljava/lang/String;,lo-prio,max-target-o` * (since API 28, prior to API 30) `Landroid/provider/Settings$Global;->SOFT_AP_TIMEOUT_ENABLED:Ljava/lang/String;,lo-prio,max-target-o`
* (prior to API 30) `Lcom/android/internal/R$array;->config_tether_bluetooth_regexs:I,max-target-q` * (prior to API 30) `Lcom/android/internal/R$array;->config_tether_bluetooth_regexs:I,max-target-q`
@@ -300,10 +301,7 @@ Nonexported system resources:
* (since API 30) `@com.android.networkstack.tethering:array/config_tether_wigig_regexs` * (since API 30) `@com.android.networkstack.tethering:array/config_tether_wigig_regexs`
* (since API 30) `@com.android.wifi.resources:integer/config_wifiFrameworkSoftApShutDownTimeoutMilliseconds` * (since API 30) `@com.android.wifi.resources:integer/config_wifiFrameworkSoftApShutDownTimeoutMilliseconds`
Other: Other: Activity `com.android.settings/.Settings$TetherSettingsActivity` is assumed to be exported.
* (since API 29) `android.net.wifi.p2p.WifiP2pConfig` needs to be parcelized in a very specific order, except for possible extra fields at the end. (used only for safe mode)
* Activity `com.android.settings/.Settings$TetherSettingsActivity` is assumed to be exported.
For `ip rule` priorities, `RULE_PRIORITY_SECURE_VPN` and `RULE_PRIORITY_TETHERING` is assumed to be 12000 and 18000 respectively; For `ip rule` priorities, `RULE_PRIORITY_SECURE_VPN` and `RULE_PRIORITY_TETHERING` is assumed to be 12000 and 18000 respectively;
(prior to API 24) `RULE_PRIORITY_DEFAULT_NETWORK` is assumed to be 22000 (or at least > 18000). (prior to API 24) `RULE_PRIORITY_DEFAULT_NETWORK` is assumed to be 22000 (or at least > 18000).

View File

@@ -13,7 +13,6 @@ import android.os.Looper
import android.provider.Settings import android.provider.Settings
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.content.edit import androidx.core.content.edit
import be.mygod.librootkotlinx.useParcel
import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.net.MacAddressCompat import be.mygod.vpnhotspot.net.MacAddressCompat
import be.mygod.vpnhotspot.net.monitor.TetherTimeoutMonitor import be.mygod.vpnhotspot.net.monitor.TetherTimeoutMonitor
@@ -48,10 +47,6 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
private const val KEY_AUTO_SHUTDOWN = "service.repeater.autoShutdown" private const val KEY_AUTO_SHUTDOWN = "service.repeater.autoShutdown"
private const val KEY_SHUTDOWN_TIMEOUT = "service.repeater.shutdownTimeout" private const val KEY_SHUTDOWN_TIMEOUT = "service.repeater.shutdownTimeout"
private const val KEY_DEVICE_ADDRESS = "service.repeater.mac" private const val KEY_DEVICE_ADDRESS = "service.repeater.mac"
/**
* Placeholder for bypassing networkName check.
*/
private const val PLACEHOLDER_NETWORK_NAME = "DIRECT-00-VPNHotspot"
var persistentSupported = false var persistentSupported = false
@@ -65,6 +60,7 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
val safeModeConfigurable get() = Build.VERSION.SDK_INT >= 29 && hasP2pValidateName val safeModeConfigurable get() = Build.VERSION.SDK_INT >= 29 && hasP2pValidateName
val safeMode get() = Build.VERSION.SDK_INT >= 29 && val safeMode get() = Build.VERSION.SDK_INT >= 29 &&
(!hasP2pValidateName || app.pref.getBoolean(KEY_SAFE_MODE, true)) (!hasP2pValidateName || app.pref.getBoolean(KEY_SAFE_MODE, true))
private val mNetworkName by lazy { UnblockCentral.WifiP2pConfig_Builder_mNetworkName }
var networkName: String? var networkName: String?
get() = app.pref.getString(KEY_NETWORK_NAME, null) get() = app.pref.getString(KEY_NETWORK_NAME, null)
@@ -372,7 +368,12 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
p2pManager.createGroup(channel, listener) p2pManager.createGroup(channel, listener)
} else @TargetApi(29) { } else @TargetApi(29) {
p2pManager.createGroup(channel, WifiP2pConfig.Builder().apply { p2pManager.createGroup(channel, WifiP2pConfig.Builder().apply {
setNetworkName(PLACEHOLDER_NETWORK_NAME) try {
mNetworkName.set(this, networkName) // bypass networkName check
} catch (e: ReflectiveOperationException) {
Timber.w(e)
setNetworkName(networkName)
}
setPassphrase(passphrase) setPassphrase(passphrase)
when (val oc = operatingChannel) { when (val oc = operatingChannel) {
0 -> setGroupOperatingBand(when (val band = operatingBand) { 0 -> setGroupOperatingBand(when (val band = operatingBand) {
@@ -386,37 +387,9 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
} }
} }
setDeviceAddress(deviceAddress?.toPlatform()) setDeviceAddress(deviceAddress?.toPlatform())
}.build().run { }.build(), listener)
useParcel { p ->
p.writeParcelable(this, 0)
val end = p.dataPosition()
p.setDataPosition(0)
val creator = p.readString()
val deviceAddress = p.readString()
val wps = p.readParcelable<WpsInfo>(javaClass.classLoader)
val long = p.readLong()
check(p.readString() == PLACEHOLDER_NETWORK_NAME)
check(p.readString() == passphrase)
val extrasLength = end - p.dataPosition()
check(extrasLength and 3 == 0) // parcel should be padded
if (extrasLength != 4) app.logEvent("p2p_config_extras_unexpected_length") {
param("length", extrasLength.toLong())
}
val extras = (0 until extrasLength / 4).map { p.readInt() }
p.setDataPosition(0)
p.writeString(creator)
p.writeString(deviceAddress)
p.writeParcelable(wps, 0)
p.writeLong(long)
p.writeString(networkName)
p.writeString(passphrase)
extras.forEach(p::writeInt)
p.setDataPosition(0)
p.readParcelable(javaClass.classLoader)
}
}, listener)
} }
} catch (e: SecurityException) { } catch (e: RuntimeException) {
Timber.w(e) Timber.w(e)
startFailure(e.readableMessage) startFailure(e.readableMessage)
} }

View File

@@ -1,13 +1,16 @@
package be.mygod.vpnhotspot.util package be.mygod.vpnhotspot.util
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.net.wifi.p2p.WifiP2pConfig
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import timber.log.Timber import timber.log.Timber
/** /**
* The central object for accessing all the useful blocked APIs. Thanks Google! * The central object for accessing all the useful blocked APIs. Thanks Google!
*
* Lazy cannot be used directly as it will create inner classes.
*/ */
@SuppressLint("DiscouragedPrivateApi") @SuppressLint("BlockedPrivateApi", "DiscouragedPrivateApi")
@Suppress("FunctionName") @Suppress("FunctionName")
object UnblockCentral { object UnblockCentral {
/** /**
@@ -27,4 +30,9 @@ object UnblockCentral {
@RequiresApi(31) @RequiresApi(31)
fun getApInstanceIdentifier(clazz: Class<*>) = init.let { clazz.getDeclaredMethod("getApInstanceIdentifier") } fun getApInstanceIdentifier(clazz: Class<*>) = init.let { clazz.getDeclaredMethod("getApInstanceIdentifier") }
@get:RequiresApi(29)
val WifiP2pConfig_Builder_mNetworkName get() = init.let {
WifiP2pConfig.Builder::class.java.getDeclaredField("mNetworkName").apply { isAccessible = true }
}
} }