169 lines
6.1 KiB
Kotlin
169 lines
6.1 KiB
Kotlin
@file:Suppress("DEPRECATION")
|
|
|
|
package me.iacn.biliroaming.hook
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.net.http.SslError
|
|
import android.webkit.SslErrorHandler
|
|
import android.webkit.WebView
|
|
import me.iacn.biliroaming.utils.*
|
|
import org.apache.http.conn.scheme.HostNameResolver
|
|
import org.apache.http.conn.ssl.SSLSocketFactory
|
|
import java.net.Socket
|
|
import java.security.KeyStore
|
|
import java.security.SecureRandom
|
|
import java.security.cert.X509Certificate
|
|
import javax.net.ssl.*
|
|
|
|
class SSLHook(classLoader: ClassLoader) : BaseHook(classLoader) {
|
|
override fun startHook() {
|
|
Log.d("startHook: Ssl")
|
|
|
|
val emptyTrustManagers = arrayOf(object : X509TrustManager {
|
|
@SuppressLint("TrustAllX509TrustManager")
|
|
override fun checkClientTrusted(chain: Array<out X509Certificate>, authType: String) {
|
|
}
|
|
|
|
@SuppressLint("TrustAllX509TrustManager")
|
|
override fun checkServerTrusted(chain: Array<out X509Certificate>, authType: String) {
|
|
}
|
|
|
|
override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
|
|
|
|
@Suppress("unused", "UNUSED_PARAMETER")
|
|
fun checkServerTrusted(
|
|
chain: Array<X509Certificate>,
|
|
authType: String,
|
|
host: String
|
|
): List<X509Certificate> = emptyList()
|
|
})
|
|
|
|
"javax.net.ssl.TrustManagerFactory".hookBeforeMethod(
|
|
mClassLoader,
|
|
"getTrustManagers"
|
|
) { param ->
|
|
param.result = emptyTrustManagers
|
|
}
|
|
|
|
"javax.net.ssl.SSLContext".hookBeforeMethod(
|
|
mClassLoader,
|
|
"init",
|
|
"javax.net.ssl.KeyManager[]",
|
|
"javax.net.ssl.TrustManager[]",
|
|
SecureRandom::class.java
|
|
) { param ->
|
|
param.args[0] = null
|
|
param.args[1] = emptyTrustManagers
|
|
param.args[2] = null
|
|
}
|
|
|
|
"javax.net.ssl.HttpsURLConnection".hookBeforeMethod(
|
|
mClassLoader,
|
|
"setSSLSocketFactory",
|
|
javax.net.ssl.SSLSocketFactory::class.java
|
|
) { param ->
|
|
param.args[0] = "javax.net.ssl.SSLSocketFactory".findClass(mClassLoader).new()
|
|
}
|
|
|
|
"org.apache.http.conn.scheme.SchemeRegistry".findClassOrNull(mClassLoader)
|
|
?.hookBeforeMethod("register", "org.apache.http.conn.scheme.Scheme") { param ->
|
|
if (param.args[0].callMethodAs<String>("getName") == "https") {
|
|
param.args[0] = param.args[0].javaClass.new(
|
|
"https",
|
|
SSLSocketFactory.getSocketFactory(),
|
|
443
|
|
)
|
|
}
|
|
}
|
|
|
|
"org.apache.http.conn.ssl.HttpsURLConnection".findClassOrNull(mClassLoader)?.run {
|
|
hookBeforeMethod("setDefaultHostnameVerifier", HostnameVerifier::class.java) { param ->
|
|
param.args[0] = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
|
|
}
|
|
|
|
hookBeforeMethod("setHostnameVerifier", HostnameVerifier::class.java) { param ->
|
|
param.args[0] = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
|
|
}
|
|
|
|
}
|
|
"org.apache.http.conn.ssl.SSLSocketFactory".hookBeforeMethod(
|
|
mClassLoader,
|
|
"getSocketFactory"
|
|
) { param ->
|
|
param.result = SSLSocketFactory::class.java.new()
|
|
}
|
|
|
|
"org.apache.http.conn.ssl.SSLSocketFactory".findClassOrNull(mClassLoader)
|
|
?.hookAfterConstructor(
|
|
String::class.java,
|
|
KeyStore::class.java,
|
|
String::class.java,
|
|
KeyStore::class.java,
|
|
SecureRandom::class.java,
|
|
HostNameResolver::class.java
|
|
) { param ->
|
|
val algorithm = param.args[0] as? String
|
|
val keystore = param.args[1] as? KeyStore
|
|
val keystorePassword = param.args[2] as? String
|
|
val random = param.args[4] as? SecureRandom
|
|
|
|
@Suppress("UNCHECKED_CAST") val trustManagers =
|
|
emptyTrustManagers as Array<TrustManager>
|
|
|
|
val keyManagers = keystore?.let {
|
|
SSLSocketFactory::class.java.callStaticMethodAs<Array<KeyManager>>(
|
|
"createKeyManagers",
|
|
keystore,
|
|
keystorePassword
|
|
)
|
|
}
|
|
|
|
|
|
param.thisObject.setObjectField("sslcontext", SSLContext.getInstance(algorithm))
|
|
param.thisObject.getObjectField("sslcontext")
|
|
?.callMethod("init", keyManagers, trustManagers, random)
|
|
param.thisObject.setObjectField(
|
|
"socketfactory",
|
|
param.thisObject.getObjectField("sslcontext")?.callMethod("getSocketFactory")
|
|
)
|
|
}
|
|
|
|
"org.apache.http.conn.ssl.SSLSocketFactory".hookAfterMethod(
|
|
mClassLoader,
|
|
"isSecure",
|
|
Socket::class.java
|
|
) { param ->
|
|
param.result = true
|
|
}
|
|
|
|
"okhttp3.CertificatePinner".findClassOrNull(mClassLoader)?.run {
|
|
(runCatchingOrNull { getDeclaredMethod("findMatchingPins", String::class.java) }
|
|
?: declaredMethods.firstOrNull { it.parameterTypes.size == 1 && it.parameterTypes[0] == String::class.java && it.returnType == List::class.java })?.hookBeforeMethod { param ->
|
|
param.args[0] = ""
|
|
}
|
|
}
|
|
|
|
"android.webkit.WebViewClient".findClassOrNull(mClassLoader)?.run {
|
|
replaceMethod(
|
|
"onReceivedSslError",
|
|
WebView::class.java,
|
|
SslErrorHandler::class.java,
|
|
SslError::class.java
|
|
) { param ->
|
|
(param.args[1] as SslErrorHandler).proceed()
|
|
null
|
|
}
|
|
replaceMethod(
|
|
"onReceivedError",
|
|
WebView::class.java,
|
|
Int::class.javaPrimitiveType,
|
|
String::class.java,
|
|
String::class.java
|
|
) {
|
|
null
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|