Optimize code

This commit is contained in:
方块君 2022-05-14 18:04:21 +08:00
parent 650e7542ed
commit 8f753de854
10 changed files with 1514 additions and 669 deletions

View File

@ -1,6 +1,8 @@
plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'kotlin-android' id 'kotlin-android'
id 'top.niunaijun.blackobfuscator'
id 'icu.nullptr.stringfuck'
} }
android { android {
@ -8,7 +10,7 @@ android {
defaultConfig { defaultConfig {
applicationId "xfk233.genshinproxy" applicationId "xfk233.genshinproxy"
minSdk 27 minSdk 28
targetSdk 32 targetSdk 32
versionCode 5 versionCode 5
versionName "1.5" versionName "1.5"
@ -16,8 +18,9 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', 'proguard-log.pro'
} }
} }
compileOptions { compileOptions {
@ -29,10 +32,23 @@ android {
} }
} }
BlackObfuscator {
enabled true
depth 3
obfClass = ["xfk233.genshinproxy"]
}
stringFuck {
setKey "xfk2333"
obfuscationList ["xfk233.genshinproxy"]
workOnDebug true
}
dependencies { dependencies {
//API //API
compileOnly 'de.robv.android.xposed:api:82' compileOnly 'de.robv.android.xposed:api:82'
//Api //Api
compileOnly 'de.robv.android.xposed:api:82:sources' compileOnly 'de.robv.android.xposed:api:82:sources'
implementation 'com.github.kyuubiran:EzXHelper:0.9.2' implementation 'com.github.kyuubiran:EzXHelper:0.9.2'
implementation 'icu.nullptr.stringfuck:library:0.1.4'
} }

692
app/genshinproxy-dic.txt Normal file
View File

@ -0,0 +1,692 @@
倒卖的丢你老母个嗨
倒卖的丢你老母个臭嗨
倒卖的你个逆子早晚懒趴掉下来
倒卖的你妈有逼吗
倒卖的你老母个烂ham
倒卖的你这个逆子
倒卖的你逆你妈的臭烂逼
倒卖的信不信骨灰都给你扬咯
倒卖的去你妈个臭逼
倒卖的去你妈的
倒卖的去你妈的烂逼
倒卖的含家产
倒卖的夭寿鬼
倒卖的憨憨
倒卖的扬你妈的骨灰
倒卖的操你妈的臭头鸡仔
林北一拳打爆你妈的狗头
林北一拳打爆你妈的脑袋
林北一拳打穿你妈的血逼
倒卖的瓜娃子
还逆向
逆向
逆向你妈个逼
逆向你妈的死人头
逆向工程师
倒卖的食屎啦
倒卖的骨灰都给你妈扬咯
倒卖的骨灰都给你扬咯
倒卖的扑街仔
富强
民主
文明
和谐
自由
平等
公正
法制
爱国
敬业
诚信
友善
ʻ
ʼ
ʽ
ʾ
ʿ
ˆ
ˈ
ˉ
ˊ
ˋ
ˎ
ˏ
ˑ
י
ـ
ٴ
゙゙
ᐧᐧ
ᴵᴵ
ʻʻ
ʽʽ
ʼʼ
ʿʿ
ʾʾ
ــ
ˆˆ
ˉˉ
ˈˈ
ˋˋ
ˊˊ
ˏˏ
ˎˎ
ˑˑ
ᵔᵔ
יי
ᵎᵎ
ᵢᵢ
ⁱⁱ
ﹳﹳ
ٴٴ
ﹶﹶ
ʻʼ
ʻʽ
ʻʾ
ʻʿ
ʻˆ
ʻˈ
ʻˉ
ʻˊ
ʻˋ
ʻˎ
ʻˏ
ʻˑ
ʻי
ʻـ
ʻٴ
ʻᐧ
ʻᴵ
ʻᵎ
ʻᵔ
ʻᵢ
ʻⁱ
ʻﹳ
ʻﹶ
ʻ゙
ʼʻ
ʼʽ
ʼʾ
ʼʿ
ʼˆ
ʼˈ
ʼˉ
ʼˊ
ʼˋ
ʼˎ
ʼˏ
ʼˑ
ʼי
ʼـ
ʼٴ
ʼᐧ
ʼᴵ
ʼᵎ
ʼᵔ
ʼᵢ
ʼⁱ
ʼﹳ
ʼﹶ
ʼ゙
ʽʻ
ʽʼ
ʽʾ
ʽʿ
ʽˆ
ʽˈ
ʽˉ
ʽˊ
ʽˋ
ʽˎ
ʽˏ
ʽˑ
ʽי
ʽـ
ʽٴ
ʽᐧ
ʽᴵ
ʽᵎ
ʽᵔ
ʽᵢ
ʽⁱ
ʽﹳ
ʽﹶ
ʽ゙
ʾʻ
ʾʼ
ʾʽ
ʾʿ
ʾˆ
ʾˈ
ʾˉ
ʾˊ
ʾˋ
ʾˎ
ʾˏ
ʾˑ
ʾי
ʾـ
ʾٴ
ʾᐧ
ʾᴵ
ʾᵎ
ʾᵔ
ʾᵢ
ʾⁱ
ʾﹳ
ʾﹶ
ʾ゙
ʿʻ
ʿʼ
ʿʽ
ʿʾ
ʿˆ
ʿˈ
ʿˉ
ʿˊ
ʿˋ
ʿˎ
ʿˏ
ʿˑ
ʿי
ʿـ
ʿٴ
ʿᐧ
ʿᴵ
ʿᵎ
ʿᵔ
ʿᵢ
ʿⁱ
ʿﹳ
ʿﹶ
ʿ゙
ˆʻ
ˆʼ
ˆʽ
ˆʾ
ˆʿ
ˆˈ
ˆˉ
ˆˊ
ˆˋ
ˆˎ
ˆˏ
ˆˑ
ˆי
ˆـ
ˆٴ
ˆᐧ
ˆᴵ
ˆᵎ
ˆᵔ
ˆᵢ
ˆⁱ
ˆﹳ
ˆﹶ
ˆ゙
ˈʻ
ˈʼ
ˈʽ
ˈʾ
ˈʿ
ˈˆ
ˈˉ
ˈˊ
ˈˋ
ˈˎ
ˈˏ
ˈˑ
ˈי
ˈـ
ˈٴ
ˈᐧ
ˈᴵ
ˈᵎ
ˈᵔ
ˈᵢ
ˈⁱ
ˈﹳ
ˈﹶ
ˈ゙
ˉʻ
ˉʼ
ˉʽ
ˉʾ
ˉʿ
ˉˆ
ˉˈ
ˉˊ
ˉˋ
ˉˎ
ˉˏ
ˉˑ
ˉי
ˉـ
ˉٴ
ˉᐧ
ˉᴵ
ˉᵎ
ˉᵔ
ˉᵢ
ˉⁱ
ˉﹳ
ˉﹶ
ˉ゙
ˊʻ
ˊʼ
ˊʽ
ˊʾ
ˊʿ
ˊˆ
ˊˈ
ˊˉ
ˊˋ
ˊˎ
ˊˏ
ˊˑ
ˊי
ˊـ
ˊٴ
ˊᐧ
ˊᴵ
ˊᵎ
ˊᵔ
ˊᵢ
ˊⁱ
ˊﹳ
ˊﹶ
ˊ゙
ˋʻ
ˋʼ
ˋʽ
ˋʾ
ˋʿ
ˋˆ
ˋˈ
ˋˉ
ˋˊ
ˋˎ
ˋˏ
ˋˑ
ˋי
ˋـ
ˋٴ
ˋᐧ
ˋᴵ
ˋᵎ
ˋᵔ
ˋᵢ
ˋⁱ
ˋﹳ
ˋﹶ
ˋ゙
ˎʻ
ˎʼ
ˎʽ
ˎʾ
ˎʿ
ˎˆ
ˎˈ
ˎˉ
ˎˊ
ˎˋ
ˎˏ
ˎˑ
ˎי
ˎـ
ˎٴ
ˎᐧ
ˎᴵ
ˎᵎ
ˎᵔ
ˎᵢ
ˎⁱ
ˎﹳ
ˎﹶ
ˎ゙
ˏʻ
ˏʼ
ˏʽ
ˏʾ
ˏʿ
ˏˆ
ˏˈ
ˏˉ
ˏˊ
ˏˋ
ˏˎ
ˏˑ
ˏי
ˏـ
ˏٴ
ˏᐧ
ˏᴵ
ˏᵎ
ˏᵔ
ˏᵢ
ˏⁱ
ˏﹳ
ˏﹶ
ˏ゙
ˑʻ
ˑʼ
ˑʽ
ˑʾ
ˑʿ
ˑˆ
ˑˈ
ˑˉ
ˑˊ
ˑˋ
ˑˎ
ˑˏ
ˑי
ˑـ
ˑٴ
ˑᐧ
ˑᴵ
ˑᵎ
ˑᵔ
ˑᵢ
ˑⁱ
ˑﹳ
ˑﹶ
ˑ゙
יʻ
יʼ
יʽ
יʾ
יʿ
יˆ
יˈ
יˉ
יˊ
יˋ
יˎ
יˏ
יˑ
יـ
יٴ
יᐧ
יᴵ
יᵎ
יᵔ
יᵢ
יⁱ
יﹳ
יﹶ
י゙
ـʻ
ـʼ
ـʽ
ـʾ
ـʿ
ـˆ
ـˈ
ـˉ
ـˊ
ـˋ
ـˎ
ـˏ
ـˑ
ـי
ـٴ
ـᐧ
ـᴵ
ـᵎ
ـᵔ
ـᵢ
ـⁱ
ـﹳ
ـﹶ
ـ゙
ٴʻ
ٴʼ
ٴʽ
ٴʾ
ٴʿ
ٴˆ
ٴˈ
ٴˉ
ٴˊ
ٴˋ
ٴˎ
ٴˏ
ٴˑ
ٴי
ٴـ
ٴᐧ
ٴᴵ
ٴᵎ
ٴᵔ
ٴᵢ
ٴⁱ
ٴﹳ
ٴﹶ
ٴ゙
ᐧʻ
ᐧʼ
ᐧʽ
ᐧʾ
ᐧʿ
ᐧˆ
ᐧˈ
ᐧˉ
ᐧˊ
ᐧˋ
ᐧˎ
ᐧˏ
ᐧˑ
ᐧי
ᐧـ
ᐧٴ
ᐧᴵ
ᐧᵎ
ᐧᵔ
ᐧᵢ
ᐧⁱ
ᐧﹳ
ᐧﹶ
ᐧ゙
ᴵʻ
ᴵʼ
ᴵʽ
ᴵʾ
ᴵʿ
ᴵˆ
ᴵˈ
ᴵˉ
ᴵˊ
ᴵˋ
ᴵˎ
ᴵˏ
ᴵˑ
ᴵי
ᴵـ
ᴵٴ
ᴵᐧ
ᴵᵎ
ᴵᵔ
ᴵᵢ
ᴵⁱ
ᴵﹳ
ᴵﹶ
ᴵ゙
ᵎʻ
ᵎʼ
ᵎʽ
ᵎʾ
ᵎʿ
ᵎˆ
ᵎˈ
ᵎˉ
ᵎˊ
ᵎˋ
ᵎˎ
ᵎˏ
ᵎˑ
ᵎי
ᵎـ
ᵎٴ
ᵎᐧ
ᵎᴵ
ᵎᵔ
ᵎᵢ
ᵎⁱ
ᵎﹳ
ᵎﹶ
ᵎ゙
ᵔʻ
ᵔʼ
ᵔʽ
ᵔʾ
ᵔʿ
ᵔˆ
ᵔˈ
ᵔˉ
ᵔˊ
ᵔˋ
ᵔˎ
ᵔˏ
ᵔˑ
ᵔי
ᵔـ
ᵔٴ
ᵔᐧ
ᵔᴵ
ᵔᵎ
ᵔᵢ
ᵔⁱ
ᵔﹳ
ᵔﹶ
ᵔ゙
ᵢʻ
ᵢʼ
ᵢʽ
ᵢʾ
ᵢʿ
ᵢˆ
ᵢˈ
ᵢˉ
ᵢˊ
ᵢˋ
ᵢˎ
ᵢˏ
ᵢˑ
ᵢי
ᵢـ
ᵢٴ
ᵢᐧ
ᵢᴵ
ᵢᵎ
ᵢᵔ
ᵢⁱ
ᵢﹳ
ᵢﹶ
ᵢ゙
ⁱʻ
ⁱʼ
ⁱʽ
ⁱʾ
ⁱʿ
ⁱˆ
ⁱˈ
ⁱˉ
ⁱˊ
ⁱˋ
ⁱˎ
ⁱˏ
ⁱˑ
ⁱי
ⁱـ
ⁱٴ
ⁱᐧ
ⁱᴵ
ⁱᵎ
ⁱᵔ
ⁱᵢ
ⁱﹳ
ⁱﹶ
ⁱ゙
ﹳʻ
ﹳʼ
ﹳʽ
ﹳʾ
ﹳʿ
ﹳˆ
ﹳˈ
ﹳˉ
ﹳˊ
ﹳˋ
ﹳˎ
ﹳˏ
ﹳˑ
ﹳי
ﹳـ
ﹳٴ
ﹳᐧ
ﹳᴵ
ﹳᵎ
ﹳᵔ
ﹳᵢ
ﹳⁱ
ﹳﹶ
ﹳ゙
ﹶʻ
ﹶʼ
ﹶʽ
ﹶʾ
ﹶʿ
ﹶˆ
ﹶˈ
ﹶˉ
ﹶˊ
ﹶˋ
ﹶˎ
ﹶˏ
ﹶˑ
ﹶי
ﹶـ
ﹶٴ
ﹶᐧ
ﹶᴵ
ﹶᵎ
ﹶᵔ
ﹶᵢ
ﹶⁱ
ﹶﹳ
ﹶ゙
゙ʻ
゙ʼ
゙ʽ
゙ʾ
゙ʿ
゙ˆ
゙ˈ
゙ˉ
゙ˊ
゙ˋ
゙ˎ
゙ˏ
゙ˑ
゙י
゙ـ
゙ٴ
゙ᐧ
゙ᴵ
゙ᵎ
゙ᵔ
゙ᵢ
゙ⁱ
゙ﹳ
゙ﹶ

40
app/proguard-log.pro Normal file
View File

@ -0,0 +1,40 @@
##########################################################################################################
# 作者Sollyu
# 日期2020-11-02
# 内容发布版本移除日志kotlin编译时带的而外信息增强反调试难度
# 使用proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', 'proguard-log.pro'
##########################################################################################################
##########################################################################################################
# 删除安卓日志
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** w(...);
public static *** e(...);
}
##########################################################################################################
# 删除Kotlin编译时可能生成显示变量的方法
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
public static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String);
public static void checkFieldIsNotNull(java.lang.Object, java.lang.String);
public static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
public static void checkNotNull(java.lang.Object);
public static void checkNotNull(java.lang.Object, java.lang.String);
public static void checkNotNullExpressionValue(java.lang.Object, java.lang.String);
public static void checkNotNullParameter(java.lang.Object, java.lang.String);
public static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
public static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String);
public static void throwUninitializedPropertyAccessException(java.lang.String);
}
##########################################################################################################
# 会暴露变量名称
-assumenosideeffects class java.util.Objects {
public static java.lang.Object requireNonNull(java.lang.Object, java.lang.String);
}
-assumenosideeffects class de.robv.android.xposed.XposedBridge {
public synchronized static void log(...);
}

View File

@ -19,3 +19,26 @@
# If you keep the line number information, uncomment this to # If you keep the line number information, uncomment this to
# hide the original source file name. # hide the original source file name.
#-renamesourcefileattribute SourceFile #-renamesourcefileattribute SourceFile
-keep class * implements de.robv.android.xposed.IXposedHookLoadPackage {
public void *(de.robv.android.xposed.callbacks.XC_LoadPackage$LoadPackageParam);
}
-keep class * implements de.robv.android.xposed.IXposedHookInitPackageResources {
public void *(de.robv.android.xposed.callbacks.XC_InitPackageResources$InitPackageResourcesParam);
}
-keep class * implements de.robv.android.xposed.IXposedHookZygoteInit {
public void *(de.robv.android.xposed.IXposedHookZygoteInit$StartupParam);
}
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
public static void check*(...);
public static void throw*(...);
}
-obfuscationdictionary genshinproxy-dic.txt
-classobfuscationdictionary genshinproxy-dic.txt
-packageobfuscationdictionary genshinproxy-dic.txt
-repackageclasses "xfk233.genshinproxy"

View File

@ -0,0 +1,713 @@
package xfk233.genshinproxy
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.ClipboardManager
import android.content.Context
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.XModuleResources
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RoundRectShape
import android.os.Build
import android.text.Editable
import android.text.InputType
import android.text.TextWatcher
import android.util.Base64
import android.util.TypedValue
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.webkit.SslErrorHandler
import android.widget.*
import com.github.kyuubiran.ezxhelper.init.EzXHelperInit
import com.github.kyuubiran.ezxhelper.utils.*
import de.robv.android.xposed.IXposedHookZygoteInit
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.callbacks.XC_LoadPackage
import icu.nullptr.stringfuck.StringFuck
import org.json.JSONObject
import xfk233.genshinproxy.Utils.dp2px
import xfk233.genshinproxy.Utils.isInit
import java.io.BufferedReader
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.regex.Pattern
import javax.net.ssl.*
import kotlin.system.exitProcess
class Hook {
private val regex = Pattern.compile("http(s|)://.*?\\.(hoyoverse|mihoyo|yuanshen|mob)\\.com")
private lateinit var server: String
private var forceUrl = false
private lateinit var modulePath: String
private lateinit var moduleRes: XModuleResources
private lateinit var windowManager: WindowManager
private var proxyList = false
private lateinit var sp: SharedPreferences
private val proxyListRegex = arrayListOf(
"api-os-takumi.mihoyo.com",
"hk4e-api-os-static.mihoyo.com",
"hk4e-sdk-os.mihoyo.com",
"dispatchosglobal.yuanshen.com",
"osusadispatch.yuanshen.com",
"account.mihoyo.com",
"log-upload-os.mihoyo.com",
"dispatchcntest.yuanshen.com",
"devlog-upload.mihoyo.com",
"webstatic.mihoyo.com",
"log-upload.mihoyo.com",
"hk4e-sdk.mihoyo.com",
"api-beta-sdk.mihoyo.com",
"api-beta-sdk-os.mihoyo.com",
"cnbeta01dispatch.yuanshen.com",
"dispatchcnglobal.yuanshen.com",
"cnbeta02dispatch.yuanshen.com",
"sdk-os-static.mihoyo.com",
"webstatic-sea.mihoyo.com",
"webstatic-sea.hoyoverse.com",
"hk4e-sdk-os-static.hoyoverse.com",
"sdk-os-static.hoyoverse.com",
"api-account-os.hoyoverse.com",
"hk4e-sdk-os.hoyoverse.com",
"overseauspider.yuanshen.com",
"gameapi-account.mihoyo.com",
"minor-api.mihoyo.com",
"public-data-api.mihoyo.com",
"uspider.yuanshen.com",
"sdk-static.mihoyo.com",
"minor-api-os.hoyoverse.com",
"log-upload-os.hoyoverse.com"
)
private val activityList: ArrayList<Activity> = arrayListOf()
private var activity: Activity
get() {
for (mActivity in activityList) {
if (mActivity.isFinishing) {
activityList.remove(mActivity)
} else {
return mActivity
}
}
throw Throwable("Activity not found.")
}
set(value) {
activityList.add(value)
}
private fun getDefaultSSLSocketFactory(): SSLSocketFactory {
return SSLContext.getInstance("TLS").apply {
init(arrayOf<KeyManager>(), arrayOf<TrustManager>(DefaultTrustManager()), SecureRandom())
}.socketFactory
}
private fun getDefaultHostnameVerifier(): HostnameVerifier {
return DefaultHostnameVerifier()
}
class DefaultHostnameVerifier : HostnameVerifier {
@SuppressLint("BadHostnameVerifier")
override fun verify(p0: String?, p1: SSLSession?): Boolean {
return true
}
}
@SuppressLint("CustomX509TrustManager")
private class DefaultTrustManager : X509TrustManager {
@SuppressLint("TrustAllX509TrustManager")
override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) {
}
@SuppressLint("TrustAllX509TrustManager")
override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
}
fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) {
StringFuck.init()
modulePath = startupParam.modulePath
moduleRes = XModuleResources.createInstance(modulePath, null)
TrustMeAlready().initZygote()
}
private var startForceUrl = false
private var startProxyList = false
private lateinit var dialog: LinearLayout
@SuppressLint("WrongConstant", "ClickableViewAccessibility")
fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
if (lpparam.packageName != "com.miHoYo.GenshinImpact") return
EzXHelperInit.initHandleLoadPackage(lpparam)
findMethod("com.combosdk.openapi.ComboApplication") { name == "attachBaseContext" }.hookBefore {
val context = it.args[0] as Context
Utils.check(context, modulePath)
sp = context.getSharedPreferences("serverConfig", 0)
forceUrl = sp.getBoolean("forceUrl", false)
startForceUrl = forceUrl
server = sp.getString("serverip", "") ?: ""
proxyList = sp.getBoolean("ProxyList", false)
startProxyList = proxyList
if (sp.getBoolean("KeepSSL", false)) sslHook()
}
hook()
findMethod(Activity::class.java, true) { name == "onCreate" }.hookBefore { param ->
activity = param.thisObject as Activity
}
findMethod("com.miHoYo.GetMobileInfo.MainActivity") { name == "onCreate" }.hookBefore { param ->
activity = param.thisObject as Activity
showDialog()
activity.windowManager.addView(LinearLayout(activity).apply {
dialog = this
visibility = View.GONE
background = ShapeDrawable().apply {
shape = RoundRectShape(floatArrayOf(18f, 18f, 18f, 18f, 18f, 18f, 18f, 18f), null, null)
paint.color = Color.parseColor("#FFEFEDF5")
}
addView(TextView(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also {
it.gravity = Gravity.CENTER_VERTICAL
}
gravity = Gravity.CENTER
text = String(Base64.decode("5pys5qih5Z2X5piv5YWN6LS55bm25byA5rqQ55qELCDlpoLmnpzkvaDmmK/otK3kubDnmoTmraTmqKHlnZfmiJbova/ku7bjgIJcbumCo+S5iOS9oOiiq+mql+S6hu+8jOivt+mAgOasvivlt67or4TvvIFcblRoaXMgbW9kdWxlIGlzIGZyZWUgYW5kIG9wZW4gc291cmNlLCBpZiB5b3UgcHVyY2hhc2VkIHRoaXMgbW9kdWxlIG9yIHNvZnR3YXJlLlxuVGhlbiB5b3UgaGF2ZSBiZWVuIGNoZWF0ZWQsIHBsZWFzZSByZWZ1bmQh", Base64.DEFAULT)).replace("\\n", "\n")
})
}, WindowManager.LayoutParams(dp2px(activity, 200f), dp2px(activity, 150f), WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT).apply {
gravity = Gravity.CENTER_VERTICAL
x = 0
y = 0
})
}
}
private fun showDialog() {
AlertDialog.Builder(activity).apply {
setCancelable(false)
setTitle(moduleRes.getString(R.string.SelectServer))
setMessage(moduleRes.getString(R.string.Tips))
setNegativeButton(moduleRes.getString(R.string.Settings)) { _, _ ->
AlertDialog.Builder(activity).apply {
setMessage(moduleRes.getString(R.string.Tips2))
setCancelable(false)
setView(ScrollView(context).apply {
setPadding(25, 0, 25, 0)
addView(LinearLayout(activity).apply {
orientation = LinearLayout.VERTICAL
addView(EditText(activity).apply {
hint = "http(s)://server.com:1234"
val str = sp.getString("serverip", "") ?: ""
setText(str.toCharArray(), 0, str.length)
addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence, p1: Int, p2: Int, p3: Int) {}
@SuppressLint("CommitPrefEdits")
override fun afterTextChanged(p0: Editable) {
sp.edit().run {
putString("serverip", p0.toString())
apply()
}
}
})
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.ForcedMode)
isChecked = sp.getBoolean("forceUrl", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("forceUrl", b)
apply()
}
forceUrl = b
}
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.ProxyList)
isChecked = sp.getBoolean("ProxyList", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("ProxyList", b)
apply()
}
proxyList = b
}
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.HookConfig)
isChecked = sp.getBoolean("HookConfig", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("HookConfig", b)
apply()
}
proxyList = b
}
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.EnableTools)
isChecked = sp.getBoolean("EnableTools", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("EnableTools", b)
apply()
}
proxyList = b
}
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.KeepSSL)
isChecked = sp.getBoolean("KeepSSL", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("KeepSSL", b)
apply()
}
}
})
})
})
setPositiveButton(moduleRes.getString(R.string.Back)) { _, _ ->
showDialog()
}
setNeutralButton(moduleRes.getString(R.string.ExitGames)) { _, _ ->
exitProcess(0)
}
}.show()
}
setPositiveButton(moduleRes.getString(R.string.CustomServer)) { _, _ ->
val ip = sp.getString("serverip", "") ?: ""
if (ip == "") {
Toast.makeText(activity, moduleRes.getString(R.string.ServerAddressError), Toast.LENGTH_LONG).show()
activity.finish()
} else {
server = ip
forceUrl = true
if (sp.getBoolean("EnableTools", false)) gmTool()
Thread {
runOnMainThread {
dialog.visibility = View.VISIBLE
}
Thread.sleep(10 * 1000)
runOnMainThread {
dialog.visibility = View.GONE
activity.windowManager.removeView(dialog)
}
}.start()
}
}
setNeutralButton(moduleRes.getString(R.string.OfficialServer)) { _, _ ->
forceUrl = false
server = ""
if (startForceUrl || startProxyList) {
Toast.makeText(activity, moduleRes.getString(R.string.JoinServerError), Toast.LENGTH_LONG).show()
showDialog()
}
}
}.show()
}
inner class MoveOnTouchListener : View.OnTouchListener {
private var originalXPos = 0
private var originalYPos = 0
private var offsetX = 0f
private var offsetY = 0f
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
val x = event.rawX
val y = event.rawY
val location = IntArray(2)
v.getLocationOnScreen(location)
originalXPos = location[0]
originalYPos = location[1]
offsetX = x - originalXPos
offsetY = y - originalYPos
}
MotionEvent.ACTION_MOVE -> {
val onScreen = IntArray(2)
v.getLocationOnScreen(onScreen)
val x = event.rawX
val y = event.rawY
val params: WindowManager.LayoutParams = v.layoutParams as WindowManager.LayoutParams
val newX = (x - offsetX).toInt()
val newY = (y - offsetY).toInt()
if (newX == originalXPos && newY == originalYPos) {
return false
}
params.x = newX
params.y = newY
windowManager.updateViewLayout(v, params)
}
}
return false
}
}
private lateinit var imageView: ImageView
private lateinit var mainView: ScrollView
private fun gmTool() {
if (this::mainView.isInitialized) return
if (this::imageView.isInitialized) return
if (isInit) return
isInit = true
mainView = ScrollView(activity).apply {
visibility = View.GONE
addView(LinearLayout(activity).apply {
orientation = LinearLayout.VERTICAL
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
setBackgroundColor(Color.parseColor("#5F000000"))
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
setBackgroundColor(Color.parseColor("#8F000000"))
addView(TextView(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
setTextColor(Color.BLUE)
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
text = moduleRes.getString(R.string.Tools)
})
addView(TextView(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also {
it.setMargins(0, 0, 5, 0)
}
setTextColor(Color.BLUE)
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
text = "X"
setOnClickListener {
mainView.visibility = View.GONE
imageView.visibility = View.VISIBLE
}
})
})
addView(LinearLayout(activity).apply {
orientation = LinearLayout.VERTICAL
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
var userEdit: EditText
var passEdit: EditText
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(TextView(activity).apply {
setTextColor(Color.BLUE)
text = moduleRes.getString(R.string.CheckServerStatus)
setOnClickListener {
Thread {
try {
XposedBridge.log("$server/authentication/type")
URL("$server/authentication/type").apply {
val conn = if (server.startsWith("https")) {
(openConnection() as HttpsURLConnection).apply {
sslSocketFactory = getDefaultSSLSocketFactory()
hostnameVerifier = getDefaultHostnameVerifier()
}
} else {
openConnection() as HttpURLConnection
}
conn.requestMethod = "GET"
conn.readTimeout = 8000
conn.connectTimeout = 8000
val reader = BufferedReader(InputStreamReader(conn.inputStream))
if (conn.responseCode == 200) {
val response = StringBuilder()
var line = ""
while (reader.readLine()?.also { line = it } != null) {
response.append(line)
}
runOnMainThread {
text = if (response.toString() == "me.exzork.gcauth.handler.GCAuthAuthenticationHandler") moduleRes.getString(R.string.ServerStatus) + "GcAuth" else moduleRes.getString(R.string.ServerStatus) + "GcAuth" + moduleRes.getString(R.string.NotInstall)
}
} else {
runOnMainThread {
text = moduleRes.getString(R.string.ServerStatus) + moduleRes.getString(R.string.GetServerStatusError)
}
}
}
} catch (e: Throwable) {
runOnMainThread {
text = moduleRes.getString(R.string.ServerStatus) + moduleRes.getString(R.string.GetServerStatusError) + e
}
}
}.start()
}
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.InputSwitch)
setOnCheckedChangeListener { _, b ->
if (b) {
val params = mainView.layoutParams as WindowManager.LayoutParams
params.flags = params.flags and (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE.inv())
windowManager.updateViewLayout(mainView, params)
} else {
val params = mainView.layoutParams as WindowManager.LayoutParams
params.flags = params.flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
windowManager.updateViewLayout(mainView, params)
}
}
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(TextView(activity).apply {
setTextColor(Color.BLUE)
text = moduleRes.getString(R.string.User)
})
addView(EditText(activity).apply {
userEdit = this
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
val user = sp.getString("user", "") ?: ""
setText(user.toCharArray(), 0, user.length)
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(TextView(activity).apply {
setTextColor(Color.BLUE)
text = moduleRes.getString(R.string.Password)
})
addView(EditText(activity).apply {
passEdit = this
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
val user = sp.getString("pass", "") ?: ""
setText(user.toCharArray(), 0, user.length)
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(Button(activity).apply {
text = moduleRes.getString(R.string.Login)
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
setOnClickListener {
Thread {
try {
URL("$server/authentication/type").apply {
val conn = if (server.startsWith("https")) {
(openConnection() as HttpsURLConnection).apply {
sslSocketFactory = getDefaultSSLSocketFactory()
hostnameVerifier = getDefaultHostnameVerifier()
}
} else {
openConnection() as HttpURLConnection
}
conn.requestMethod = "POST"
conn.readTimeout = 8000
conn.connectTimeout = 8000
conn.doOutput = true
conn.doInput = true
conn.useCaches = false
conn.outputStream.apply {
write("{\"username\":\"${userEdit.text}\",\"password\":\"${passEdit.text}\"}".toByteArray())
flush()
}
if (conn.responseCode == 200) {
val input = conn.inputStream
val message = ByteArrayOutputStream()
var len: Int
val buffer = ByteArray(1024)
while (input.read(buffer).also { len = it } != -1) {
message.write(buffer, 0, len)
}
input.close()
message.close()
val json = JSONObject(String(message.toByteArray()))
if (json.optBoolean("success", false)) {
val token = json.optString("jwt", "")
runOnMainThread {
Toast.makeText(activity, "${moduleRes.getString(R.string.LoginSuccess)}\n${token}", Toast.LENGTH_LONG).show()
@Suppress("DEPRECATION")
(activity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).text = token
sp.edit().run {
putString("user", userEdit.text.toString())
putString("pass", passEdit.text.toString())
apply()
}
}
} else {
runOnMainThread {
Toast.makeText(activity, moduleRes.getString(R.string.LoginFailed) + json.optString("message", ""), Toast.LENGTH_LONG).show()
}
}
}
}
} catch (e: Throwable) {
runOnMainThread {
Toast.makeText(activity, moduleRes.getString(R.string.LoginError) + e, Toast.LENGTH_LONG).show()
}
}
}.start()
}
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(Button(activity).apply {
text = "Open WebView"
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
setOnClickListener {
val webview = loadClass("com.miHoYo.sdk.webview.MiHoYoWebview")
webview.invokeStaticMethod("init", args(activity, "test_webview"), argTypes(Activity::class.java, String::class.java))
webview.invokeStaticMethod("show", args("test_webview"), argTypes(String::class.java))
webview.invokeStaticMethod("load", args("test_webview", "https://www.fkj233.cn/gourl/"), argTypes(String::class.java, String::class.java))
}
})
})
})
})
}
windowManager = activity.windowManager
windowManager.addView(mainView, WindowManager.LayoutParams(dp2px(activity, 200f), WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT).apply {
gravity = Gravity.START or Gravity.TOP
x = 0
y = 0
})
val layoutParams = WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT).apply {
gravity = Gravity.START or Gravity.TOP
x = 0
y = 0
}
imageView = ImageView(activity).apply {
@Suppress("DEPRECATION")
background = moduleRes.getDrawable(R.drawable.ic_android_black_24dp).also { it.alpha = 50 }
this.layoutParams = layoutParams
setOnTouchListener(MoveOnTouchListener())
setOnClickListener {
mainView.visibility = View.VISIBLE
it.visibility = View.GONE
}
}
windowManager.addView(imageView, layoutParams)
}
private fun sslHook() {
// OkHttp3 Hook
findMethodOrNull("com.combosdk.lib.third.okhttp3.OkHttpClient\$Builder") { name == "build" }?.hookBefore {
it.thisObject.invokeMethod("sslSocketFactory", args(getDefaultSSLSocketFactory()), argTypes(SSLSocketFactory::class.java))
it.thisObject.invokeMethod("hostnameVerifier", args(getDefaultHostnameVerifier()), argTypes(HostnameVerifier::class.java))
}
findMethodOrNull("okhttp3.OkHttpClient\$Builder") { name == "build" }?.hookBefore {
it.thisObject.invokeMethod("sslSocketFactory", args(getDefaultSSLSocketFactory(), DefaultTrustManager()), argTypes(SSLSocketFactory::class.java, X509TrustManager::class.java))
it.thisObject.invokeMethod("hostnameVerifier", args(getDefaultHostnameVerifier()), argTypes(HostnameVerifier::class.java))
}
// WebView Hook
arrayListOf(
"android.webkit.WebViewClient",
"cn.sharesdk.framework.g",
"com.facebook.internal.WebDialog\$DialogWebViewClient",
"com.geetest.sdk.dialog.views.GtWebView\$c",
"com.miHoYo.sdk.webview.common.view.ContentWebView\$6"
).forEach {
findMethodOrNull(it) { name == "onReceivedSslError" && parameterTypes[1] == SslErrorHandler::class.java }?.hookBefore { param ->
(param.args[1] as SslErrorHandler).proceed()
}
}
// Android HttpsURLConnection Hook
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "getDefaultSSLSocketFactory" }?.hookBefore {
it.result = getDefaultSSLSocketFactory()
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "setSSLSocketFactory" }?.hookBefore {
it.result = null
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "setDefaultSSLSocketFactory" }?.hookBefore {
it.result = null
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "setHostnameVerifier" }?.hookBefore {
it.result = null
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "setDefaultHostnameVerifier" }?.hookBefore {
it.result = null
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "getDefaultHostnameVerifier" }?.hookBefore {
it.result = getDefaultHostnameVerifier()
}
}
private fun hook() {
findMethod("com.miHoYo.sdk.webview.MiHoYoWebview") { name == "load" && parameterTypes[0] == String::class.java && parameterTypes[1] == String::class.java }.hookBefore {
replaceUrl(it, 1)
}
findAllMethods("android.webkit.WebView") { name == "loadUrl" }.hookBefore {
replaceUrl(it, 0)
}
findAllMethods("android.webkit.WebView") { name == "postUrl" }.hookBefore {
replaceUrl(it, 0)
}
findMethod("okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
findMethod("com.combosdk.lib.third.okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
findMethod("com.google.gson.Gson") { name == "fromJson" && parameterTypes[0] == String::class.java && parameterTypes[1] == java.lang.reflect.Type::class.java }.hookBefore {
replaceUrl(it, 0)
}
findConstructor("java.net.URL") { parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
findMethod("com.combosdk.lib.third.okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
findMethod("okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
}
private fun replaceUrl(method: XC_MethodHook.MethodHookParam, args: Int) {
if (!forceUrl && !proxyList) return
if (!this::server.isInitialized) return
if (server == "") return
if (method.args[args].toString() == "") return
XposedBridge.log("old: " + method.args[args].toString())
if (!sp.getBoolean("HookConfig", false) && method.args[args].toString().startsWith("[{\"area\":")) return
if (proxyList) {
for (list in proxyListRegex) {
for (head in arrayListOf("http://", "https://")) {
method.args[args] = method.args[args].toString().replace(head + list, server)
}
}
} else {
val m = regex.matcher(method.args[args].toString())
if (m.find()) {
method.args[args] = m.replaceAll(server)
}
}
XposedBridge.log("new: " + method.args[args].toString())
}
}

View File

@ -1,673 +1,19 @@
package xfk233.genshinproxy package xfk233.genshinproxy
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.ClipboardManager
import android.content.Context
import android.content.SharedPreferences
import android.content.res.XModuleResources
import android.graphics.Color
import android.graphics.PixelFormat
import android.text.Editable
import android.text.InputType
import android.text.TextWatcher
import android.util.TypedValue
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.webkit.SslErrorHandler
import android.widget.*
import com.github.kyuubiran.ezxhelper.init.EzXHelperInit
import com.github.kyuubiran.ezxhelper.utils.*
import de.robv.android.xposed.IXposedHookLoadPackage import de.robv.android.xposed.IXposedHookLoadPackage
import de.robv.android.xposed.IXposedHookZygoteInit import de.robv.android.xposed.IXposedHookZygoteInit
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.callbacks.XC_LoadPackage import de.robv.android.xposed.callbacks.XC_LoadPackage
import org.json.JSONObject
import xfk233.genshinproxy.Utils.dp2px
import xfk233.genshinproxy.Utils.isInit
import java.io.BufferedReader
import java.io.ByteArrayOutputStream
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.regex.Pattern
import javax.net.ssl.*
import kotlin.system.exitProcess
class MainHook : IXposedHookLoadPackage, IXposedHookZygoteInit { class MainHook : IXposedHookLoadPackage, IXposedHookZygoteInit {
private val regex = Pattern.compile("http(s|)://.*?\\.(hoyoverse|mihoyo|yuanshen|mob)\\.com") private val hook = Hook()
private lateinit var server: String
private var forceUrl = false
private lateinit var modulePath: String
private lateinit var moduleRes: XModuleResources
private lateinit var windowManager: WindowManager
private var proxyList = false
private lateinit var sp: SharedPreferences
private val proxyListRegex = arrayListOf(
"api-os-takumi.mihoyo.com",
"hk4e-api-os-static.mihoyo.com",
"hk4e-sdk-os.mihoyo.com",
"dispatchosglobal.yuanshen.com",
"osusadispatch.yuanshen.com",
"account.mihoyo.com",
"log-upload-os.mihoyo.com",
"dispatchcntest.yuanshen.com",
"devlog-upload.mihoyo.com",
"webstatic.mihoyo.com",
"log-upload.mihoyo.com",
"hk4e-sdk.mihoyo.com",
"api-beta-sdk.mihoyo.com",
"api-beta-sdk-os.mihoyo.com",
"cnbeta01dispatch.yuanshen.com",
"dispatchcnglobal.yuanshen.com",
"cnbeta02dispatch.yuanshen.com",
"sdk-os-static.mihoyo.com",
"webstatic-sea.mihoyo.com",
"webstatic-sea.hoyoverse.com",
"hk4e-sdk-os-static.hoyoverse.com",
"sdk-os-static.hoyoverse.com",
"api-account-os.hoyoverse.com",
"hk4e-sdk-os.hoyoverse.com",
"overseauspider.yuanshen.com",
"gameapi-account.mihoyo.com",
"minor-api.mihoyo.com",
"public-data-api.mihoyo.com",
"uspider.yuanshen.com",
"sdk-static.mihoyo.com",
"minor-api-os.hoyoverse.com",
"log-upload-os.hoyoverse.com"
)
private val activityList: ArrayList<Activity> = arrayListOf() override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
private var activity: Activity hook.handleLoadPackage(lpparam)
get() {
for (mActivity in activityList) {
if (mActivity.isFinishing) {
activityList.remove(mActivity)
} else {
return mActivity
}
}
throw Throwable("Activity not found.")
}
set(value) {
activityList.add(value)
}
private fun getDefaultSSLSocketFactory(): SSLSocketFactory {
return SSLContext.getInstance("TLS").apply {
init(arrayOf<KeyManager>(), arrayOf<TrustManager>(DefaultTrustManager()), SecureRandom())
}.socketFactory
}
private fun getDefaultHostnameVerifier(): HostnameVerifier {
return DefaultHostnameVerifier()
}
class DefaultHostnameVerifier : HostnameVerifier {
@SuppressLint("BadHostnameVerifier")
override fun verify(p0: String?, p1: SSLSession?): Boolean {
return true
}
}
@SuppressLint("CustomX509TrustManager")
private class DefaultTrustManager : X509TrustManager {
@SuppressLint("TrustAllX509TrustManager")
override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) {
}
@SuppressLint("TrustAllX509TrustManager")
override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
} }
override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) { override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) {
modulePath = startupParam.modulePath hook.initZygote(startupParam)
moduleRes = XModuleResources.createInstance(modulePath, null)
TrustMeAlready().initZygote(startupParam)
} }
private var startForceUrl = false
private var startProxyList = false
@SuppressLint("WrongConstant", "ClickableViewAccessibility")
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
if (lpparam.packageName != "com.miHoYo.GenshinImpact") return
EzXHelperInit.initHandleLoadPackage(lpparam)
findMethod("com.combosdk.openapi.ComboApplication") { name == "attachBaseContext" }.hookBefore {
val context = it.args[0] as Context
sp = context.getSharedPreferences("serverConfig", 0)
forceUrl = sp.getBoolean("forceUrl", false)
startForceUrl = forceUrl
server = sp.getString("serverip", "") ?: ""
proxyList = sp.getBoolean("ProxyList", false)
startProxyList = proxyList
if (sp.getBoolean("KeepSSL", false)) sslHook()
}
hook()
findMethod(Activity::class.java, true) { name == "onCreate" }.hookBefore { param ->
activity = param.thisObject as Activity
}
findMethod("com.miHoYo.GetMobileInfo.MainActivity") { name == "onCreate" }.hookBefore { param ->
activity = param.thisObject as Activity
showDialog()
}
}
private fun showDialog() {
AlertDialog.Builder(activity).apply {
setCancelable(false)
setTitle(moduleRes.getString(R.string.SelectServer))
setMessage(moduleRes.getString(R.string.Tips))
setNegativeButton(moduleRes.getString(R.string.Settings)) { _, _ ->
AlertDialog.Builder(activity).apply {
setMessage(moduleRes.getString(R.string.Tips2))
setCancelable(false)
setView(ScrollView(context).apply {
setPadding(25, 0, 25, 0)
addView(LinearLayout(activity).apply {
orientation = LinearLayout.VERTICAL
addView(EditText(activity).apply {
hint = "http(s)://server.com:1234"
val str = sp.getString("serverip", "") ?: ""
setText(str.toCharArray(), 0, str.length)
addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence, p1: Int, p2: Int, p3: Int) {}
@SuppressLint("CommitPrefEdits")
override fun afterTextChanged(p0: Editable) {
sp.edit().run {
putString("serverip", p0.toString())
apply()
}
}
})
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.ForcedMode)
isChecked = sp.getBoolean("forceUrl", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("forceUrl", b)
apply()
}
forceUrl = b
}
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.ProxyList)
isChecked = sp.getBoolean("ProxyList", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("ProxyList", b)
apply()
}
proxyList = b
}
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.HookConfig)
isChecked = sp.getBoolean("HookConfig", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("HookConfig", b)
apply()
}
proxyList = b
}
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.EnableTools)
isChecked = sp.getBoolean("EnableTools", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("EnableTools", b)
apply()
}
proxyList = b
}
})
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.KeepSSL)
isChecked = sp.getBoolean("KeepSSL", false)
setOnCheckedChangeListener { _, b ->
sp.edit().run {
putBoolean("KeepSSL", b)
apply()
}
}
})
})
})
setPositiveButton(moduleRes.getString(R.string.Back)) { _, _ ->
showDialog()
}
setNeutralButton(moduleRes.getString(R.string.ExitGames)) { _, _ ->
exitProcess(0)
}
}.show()
}
setPositiveButton(moduleRes.getString(R.string.CustomServer)) { _, _ ->
val ip = sp.getString("serverip", "") ?: ""
if (ip == "") {
Toast.makeText(activity, moduleRes.getString(R.string.ServerAddressError), Toast.LENGTH_LONG).show()
activity.finish()
} else {
server = ip
forceUrl = true
if (sp.getBoolean("EnableTools", false)) gmTool()
}
}
setNeutralButton(moduleRes.getString(R.string.OfficialServer)) { _, _ ->
forceUrl = false
server = ""
if (startForceUrl || startProxyList) {
Toast.makeText(activity, moduleRes.getString(R.string.JoinServerError), Toast.LENGTH_LONG).show()
showDialog()
}
}
}.show()
}
inner class MoveOnTouchListener : View.OnTouchListener {
private var originalXPos = 0
private var originalYPos = 0
private var offsetX = 0f
private var offsetY = 0f
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
val x = event.rawX
val y = event.rawY
val location = IntArray(2)
v.getLocationOnScreen(location)
originalXPos = location[0]
originalYPos = location[1]
offsetX = x - originalXPos
offsetY = y - originalYPos
}
MotionEvent.ACTION_MOVE -> {
val onScreen = IntArray(2)
v.getLocationOnScreen(onScreen)
val x = event.rawX
val y = event.rawY
val params: WindowManager.LayoutParams = v.layoutParams as WindowManager.LayoutParams
val newX = (x - offsetX).toInt()
val newY = (y - offsetY).toInt()
if (newX == originalXPos && newY == originalYPos) {
return false
}
params.x = newX
params.y = newY
windowManager.updateViewLayout(v, params)
}
}
return false
}
}
private lateinit var imageView: ImageView
private lateinit var mainView: ScrollView
private fun gmTool() {
if (this::mainView.isInitialized) return
if (this::imageView.isInitialized) return
if (isInit) return
isInit = true
mainView = ScrollView(activity).apply {
visibility = View.GONE
addView(LinearLayout(activity).apply {
orientation = LinearLayout.VERTICAL
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
setBackgroundColor(Color.parseColor("#5F000000"))
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
setBackgroundColor(Color.parseColor("#8F000000"))
addView(TextView(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
setTextColor(Color.BLUE)
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
text = moduleRes.getString(R.string.Tools)
})
addView(TextView(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also {
it.setMargins(0, 0, 5, 0)
}
setTextColor(Color.BLUE)
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
text = "X"
setOnClickListener {
mainView.visibility = View.GONE
imageView.visibility = View.VISIBLE
}
})
})
addView(LinearLayout(activity).apply {
orientation = LinearLayout.VERTICAL
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
var userEdit: EditText
var passEdit: EditText
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(TextView(activity).apply {
setTextColor(Color.BLUE)
text = moduleRes.getString(R.string.CheckServerStatus)
setOnClickListener {
Thread() {
try {
XposedBridge.log("$server/authentication/type")
URL("$server/authentication/type").apply {
val conn = if (server.startsWith("https")) {
(openConnection() as HttpsURLConnection).apply {
sslSocketFactory = getDefaultSSLSocketFactory()
hostnameVerifier = getDefaultHostnameVerifier()
}
} else {
openConnection() as HttpURLConnection
}
conn.requestMethod = "GET"
conn.readTimeout = 8000
conn.connectTimeout = 8000
val reader = BufferedReader(InputStreamReader(conn.inputStream))
if (conn.responseCode == 200) {
val response = StringBuilder()
var line = ""
while (reader.readLine()?.also { line = it } != null) {
response.append(line)
}
runOnMainThread {
text = if (response.toString() == "me.exzork.gcauth.handler.GCAuthAuthenticationHandler") moduleRes.getString(R.string.ServerStatus) + "GcAuth" else moduleRes.getString(R.string.ServerStatus) + "GcAuth" + moduleRes.getString(R.string.NotInstall)
}
} else {
runOnMainThread {
text = moduleRes.getString(R.string.ServerStatus) + moduleRes.getString(R.string.GetServerStatusError)
}
}
}
} catch (e: Throwable) {
runOnMainThread {
text = moduleRes.getString(R.string.ServerStatus) + moduleRes.getString(R.string.GetServerStatusError) + e
}
}
}.start()
}
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(Switch(activity).apply {
text = moduleRes.getString(R.string.InputSwitch)
setOnCheckedChangeListener { _, b ->
if (b) {
val params = mainView.layoutParams as WindowManager.LayoutParams
params.flags = params.flags and (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE.inv())
windowManager.updateViewLayout(mainView, params)
} else {
val params = mainView.layoutParams as WindowManager.LayoutParams
params.flags = params.flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
windowManager.updateViewLayout(mainView, params)
}
}
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(TextView(activity).apply {
setTextColor(Color.BLUE)
text = moduleRes.getString(R.string.User)
})
addView(EditText(activity).apply {
userEdit = this
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
val user = sp.getString("user", "") ?: ""
setText(user.toCharArray(), 0, user.length)
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(TextView(activity).apply {
setTextColor(Color.BLUE)
text = moduleRes.getString(R.string.Password)
})
addView(EditText(activity).apply {
passEdit = this
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
val user = sp.getString("pass", "") ?: ""
setText(user.toCharArray(), 0, user.length)
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(Button(activity).apply {
text = moduleRes.getString(R.string.Login)
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
setOnClickListener {
Thread() {
try {
URL("$server/authentication/type").apply {
val conn = if (server.startsWith("https")) {
(openConnection() as HttpsURLConnection).apply {
sslSocketFactory = getDefaultSSLSocketFactory()
hostnameVerifier = getDefaultHostnameVerifier()
}
} else {
openConnection() as HttpURLConnection
}
conn.requestMethod = "POST"
conn.readTimeout = 8000
conn.connectTimeout = 8000
conn.doOutput = true
conn.doInput = true
conn.useCaches = false
conn.outputStream.apply {
write("{\"username\":\"${userEdit.text}\",\"password\":\"${passEdit.text}\"}".toByteArray())
flush()
}
if (conn.responseCode == 200) {
val input = conn.inputStream
val message = ByteArrayOutputStream()
var len: Int
val buffer = ByteArray(1024)
while (input.read(buffer).also { len = it } != -1) {
message.write(buffer, 0, len)
}
input.close()
message.close()
val json = JSONObject(String(message.toByteArray()))
if (json.optBoolean("success", false)) {
val token = json.optString("jwt", "")
runOnMainThread {
Toast.makeText(activity, "${moduleRes.getString(R.string.LoginSuccess)}\n${token}", Toast.LENGTH_LONG).show()
(activity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).text = token
sp.edit().run {
putString("user", userEdit.text.toString())
putString("pass", passEdit.text.toString())
apply()
}
}
} else {
runOnMainThread {
Toast.makeText(activity, moduleRes.getString(R.string.LoginFailed) + json.optString("message", ""), Toast.LENGTH_LONG).show()
}
}
}
}
} catch (e: Throwable) {
runOnMainThread {
Toast.makeText(activity, moduleRes.getString(R.string.LoginError) + e, Toast.LENGTH_LONG).show()
}
}
}.start()
}
})
})
addView(LinearLayout(activity).apply {
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
addView(Button(activity).apply {
text = "Open WebView"
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
setOnClickListener {
val webview = loadClass("com.miHoYo.sdk.webview.MiHoYoWebview")
webview.invokeStaticMethod("init", args(activity, "test_webview"), argTypes(Activity::class.java, String::class.java))
webview.invokeStaticMethod("show", args("test_webview"), argTypes(String::class.java))
webview.invokeStaticMethod("load", args("test_webview", "https://www.fkj233.cn/gourl/"), argTypes(String::class.java, String::class.java))
}
})
})
})
})
}
windowManager = activity.windowManager
windowManager.addView(mainView, WindowManager.LayoutParams(dp2px(activity, 200f), WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT).apply {
gravity = Gravity.START or Gravity.TOP
x = 0
y = 0
})
val layoutParams = WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT).apply {
gravity = Gravity.START or Gravity.TOP
x = 0
y = 0
}
imageView = ImageView(activity).apply {
@Suppress("DEPRECATION")
background = moduleRes.getDrawable(R.drawable.ic_android_black_24dp).also { it.alpha = 50 }
this.layoutParams = layoutParams
setOnTouchListener(MoveOnTouchListener())
setOnClickListener {
mainView.visibility = View.VISIBLE
it.visibility = View.GONE
}
}
windowManager.addView(imageView, layoutParams)
}
private fun sslHook() {
// OkHttp3 Hook
findMethodOrNull("com.combosdk.lib.third.okhttp3.OkHttpClient\$Builder") { name == "build" }?.hookBefore {
it.thisObject.invokeMethod("sslSocketFactory", args(getDefaultSSLSocketFactory()), argTypes(SSLSocketFactory::class.java))
it.thisObject.invokeMethod("hostnameVerifier", args(getDefaultHostnameVerifier()), argTypes(HostnameVerifier::class.java))
}
findMethodOrNull("okhttp3.OkHttpClient\$Builder") { name == "build" }?.hookBefore {
it.thisObject.invokeMethod("sslSocketFactory", args(getDefaultSSLSocketFactory(), DefaultTrustManager()), argTypes(SSLSocketFactory::class.java, X509TrustManager::class.java))
it.thisObject.invokeMethod("hostnameVerifier", args(getDefaultHostnameVerifier()), argTypes(HostnameVerifier::class.java))
}
// WebView Hook
arrayListOf(
"android.webkit.WebViewClient",
"cn.sharesdk.framework.g",
"com.facebook.internal.WebDialog\$DialogWebViewClient",
"com.geetest.sdk.dialog.views.GtWebView\$c",
"com.miHoYo.sdk.webview.common.view.ContentWebView\$6"
).forEach {
findMethodOrNull(it) { name == "onReceivedSslError" && parameterTypes[1] == SslErrorHandler::class.java }?.hookBefore { param ->
(param.args[1] as SslErrorHandler).proceed()
}
}
// Android HttpsURLConnection Hook
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "getDefaultSSLSocketFactory" }?.hookBefore {
it.result = getDefaultSSLSocketFactory()
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "setSSLSocketFactory" }?.hookBefore {
it.result = null
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "setDefaultSSLSocketFactory" }?.hookBefore {
it.result = null
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "setHostnameVerifier" }?.hookBefore {
it.result = null
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "setDefaultHostnameVerifier" }?.hookBefore {
it.result = null
}
findMethodOrNull("javax.net.ssl.HttpsURLConnection") { name == "getDefaultHostnameVerifier" }?.hookBefore {
it.result = getDefaultHostnameVerifier()
}
}
private fun hook() {
findMethod("com.miHoYo.sdk.webview.MiHoYoWebview") { name == "load" && parameterTypes[0] == String::class.java && parameterTypes[1] == String::class.java }.hookBefore {
replaceUrl(it, 1)
}
findAllMethods("android.webkit.WebView") { name == "loadUrl" }.hookBefore {
replaceUrl(it, 0)
}
findAllMethods("android.webkit.WebView") { name == "postUrl" }.hookBefore {
replaceUrl(it, 0)
}
findMethod("okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
findMethod("com.combosdk.lib.third.okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
findMethod("com.google.gson.Gson") { name == "fromJson" && parameterTypes[0] == String::class.java && parameterTypes[1] == java.lang.reflect.Type::class.java }.hookBefore {
replaceUrl(it, 0)
}
findConstructor("java.net.URL") { parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
findMethod("com.combosdk.lib.third.okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
findMethod("okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore {
replaceUrl(it, 0)
}
}
private fun replaceUrl(method: XC_MethodHook.MethodHookParam, args: Int) {
if (!forceUrl && !proxyList) return
if (!this::server.isInitialized) return
if (server == "") return
if (BuildConfig.DEBUG) XposedBridge.log("old: " + method.args[args].toString())
if (!sp.getBoolean("HookConfig", false) && method.args[args].toString().startsWith("[{\"area\":")) return
if (proxyList) {
for (list in proxyListRegex) {
for (head in arrayListOf("http://", "https://")) {
method.args[args] = method.args[args].toString().replace(head + list, server)
}
}
} else {
val m = regex.matcher(method.args[args].toString())
if (m.find()) {
method.args[args] = m.replaceAll(server)
}
}
if (BuildConfig.DEBUG) XposedBridge.log("new: " + method.args[args].toString())
}
} }

View File

@ -15,15 +15,14 @@ import de.robv.android.xposed.XposedBridge;
import static de.robv.android.xposed.XposedHelpers.*; import static de.robv.android.xposed.XposedHelpers.*;
public class TrustMeAlready implements IXposedHookZygoteInit { public class TrustMeAlready {
private static final String SSL_CLASS_NAME = "com.android.org.conscrypt.TrustManagerImpl"; private static final String SSL_CLASS_NAME = "com.android.org.conscrypt.TrustManagerImpl";
private static final String SSL_METHOD_NAME = "checkTrustedRecursive"; private static final String SSL_METHOD_NAME = "checkTrustedRecursive";
private static final Class<?> SSL_RETURN_TYPE = List.class; private static final Class<?> SSL_RETURN_TYPE = List.class;
private static final Class<?> SSL_RETURN_PARAM_TYPE = X509Certificate.class; private static final Class<?> SSL_RETURN_PARAM_TYPE = X509Certificate.class;
@Override public void initZygote() {
public void initZygote(StartupParam startupParam) throws Throwable {
XposedBridge.log("TrustMeAlready loading..."); XposedBridge.log("TrustMeAlready loading...");
int hookedMethods = 0; int hookedMethods = 0;

View File

@ -1,6 +1,10 @@
package xfk233.genshinproxy package xfk233.genshinproxy
import android.content.Context import android.content.Context
import android.content.pm.PackageManager
import android.util.Base64
import android.widget.Toast
import kotlin.system.exitProcess
object Utils { object Utils {
var isInit = false var isInit = false
@ -9,4 +13,14 @@ object Utils {
val scale: Float = context.resources.displayMetrics.density val scale: Float = context.resources.displayMetrics.density
return (dpValue * scale + 0.5f).toInt() return (dpValue * scale + 0.5f).toInt()
} }
inline fun check(context: Context, modulePath: String) {
context.packageManager.getPackageArchiveInfo(modulePath, PackageManager.GET_SIGNING_CERTIFICATES).apply {
this ?: exitProcess(0)
if (signingInfo.apkContentsSigners[0].toCharsString() !in arrayOf(String(Base64.decode("MzA4MjAyZTQzMDgyMDFjYzAyMDEwMTMwMGQwNjA5MmE4NjQ4ODZmNzBkMDEwMTA1MDUwMDMwMzczMTE2MzAxNDA2MDM1NTA0MDMwYzBkNDE2ZTY0NzI2ZjY5NjQyMDQ0NjU2Mjc1NjczMTEwMzAwZTA2MDM1NTA0MGEwYzA3NDE2ZTY0NzI2ZjY5NjQzMTBiMzAwOTA2MDM1NTA0MDYxMzAyNTU1MzMwMjAxNzBkMzIzMjMwMzEzMDM4MzEzMzMxMzEzMjMwNWExODBmMzIzMDM1MzIzMDMxMzAzMTMxMzMzMTMxMzIzMDVhMzAzNzMxMTYzMDE0MDYwMzU1MDQwMzBjMGQ0MTZlNjQ3MjZmNjk2NDIwNDQ2NTYyNzU2NzMxMTAzMDBlMDYwMzU1MDQwYTBjMDc0MTZlNjQ3MjZmNjk2NDMxMGIzMDA5MDYwMzU1MDQwNjEzMDI1NTUzMzA4MjAxMjIzMDBkMDYwOTJhODY0ODg2ZjcwZDAxMDEwMTA1MDAwMzgyMDEwZjAwMzA4MjAxMGEwMjgyMDEwMTAwYTJjNmYyZGEzMTY4NmZhNzMwNTYyODE5NDYyOTFlYWE1M2U1ZTgzYmZkZTliNDgyMGMzNWNiY2ZlN2I2NGNlODhiYWViYjE5ZWNjMjM2YzI2MzczMWE1Mzg4NzJlZTU1MzQxNGYyOTY3ODAyM2JlNGIyYTlkY2QyMzkyMTUzNDY3OGEyOWEwOTkzNTljNDk1YzIwNjgxZjMzYTJmMzU5ZTEzNGY0OGM1N2I5Y2MzOTU0YjZlNzllYjMxMzM5MWMxYjZmYjgwYzM3ZjIyOGZmMjgyOTQxZjRkYTgwNDUwZDYwYzc3ZGRmOGFjYmNiYzA2OTY2MTVlNjRiMjA1YjYyMWRjMTcyMzMzZTBkZTQzOWYyMmI4YTE4M2MzYWMyMWFjZGEyNDcwODI0MjM5MDVkYTRjMjIzM2I2YzY4ODEyMGJjNDdkMWRiMGYwYTlhMGQzZjA3MTI4ZDAwNjE4NzE3OWRjOWY4OWE2YWRjZTY2YjkzNzgwZGQ5YmZlYzE2MjFjMWVjYzYwMzY0YzkzMGM0MDNhY2UyMjEzOTM2ZjQ1ZThlZWI0YjRmZmIxZWJkZDU5NjYxZjU4NmFjZWVmMGUzOWM1YWVkYzI3NDc1M2Q4ZTU3ZjJhZmJlOGRkMGVhYjJmMDA3N2NjOTQyNDc3MGY5ODdlMmQzYmExOTRhZjNlNjMwMjAzMDEwMDAxMzAwZDA2MDkyYTg2NDg4NmY3MGQwMTAxMDUwNTAwMDM4MjAxMDEwMDEzMzA2NjNmMWZjNjhiNjFmZTYwY2JiOWQ4NGZkNWViMjU0ZjliMDUxZmYzODY1ZTUxZjZiMjkzOTFlOGNiNWE4OGUyNjhmNmI5NTI3MTQ3YTIzZTM3YTg2N2JhYWFjMDczNjhjZjA1Mzg0MTI3MWJiOTFlNTE0M2FiMDIzY2ExZmZiY2RhOWYyMmQ2Y2NjZjI2YjQ4MjVkMTEyM2RiZmJkMDI4ZjFlOGViMDc4ZDEyYzkwMGQ3OWEyZmNmYTJiMTliZWY1YzU1ZmNlOTcwMGQ3Yjc1OWRhNThlN2U0OGQwOTJmMTRhZGFkODFjZGE4YTljYjM3NDY5NjFmNzk0NzY5NWU3ZjU3ZWE3Njk3MWUwOTNhMmI5NjdiMzJjZTY1OTE4ZTcxOWYyOWJhMDUxOGI2ZTdhMWFlYzAxZGY4ZDU0YjZiNzU5YmVmNTRkYjYxMjAxMjE3NTcyNmUxOTNmNmVkNTgyZjViYTA2MjMxYzQ5NDM5NmY5NDE3ODgwNWExNWIzM2RhZTg5ZmNiYjc4OTRhMzY0NzdlNjA3YWRmOWU2MGU1NzdjMDBiYzc4ZGQ5OTYyODY2MWU4NmNlZmQwZmQ1ZmRmMzc0Y2NkMjNmZmQwYzBkOTlkNzY1NTMzOGJmZGNjYTE4MTE5ZWYwOTI5ZWJmZTU1NTdmNTEyYTFiOTE4", Base64.DEFAULT)), String(Base64.decode("MzA4MjAyOTAzMDgyMDE3ODAyMDEwMTMwMGQwNjA5MmE4NjQ4ODZmNzBkMDEwMTA1MDUwMDMwMGUzMTBjMzAwYTA2MDM1NTA0MDMwYzAzNzg2NjZiMzAxZTE3MGQzMjMyMzAzNTMxMzEzMDMzMzEzOTMyMzU1YTE3MGQzNDM3MzAzNTMwMzUzMDMzMzEzOTMyMzU1YTMwMGUzMTBjMzAwYTA2MDM1NTA0MDMwYzAzNzg2NjZiMzA4MjAxMjIzMDBkMDYwOTJhODY0ODg2ZjcwZDAxMDEwMTA1MDAwMzgyMDEwZjAwMzA4MjAxMGEwMjgyMDEwMTAwODFmODY5MDljOTQ0YTIzMTNjMmQwZDNkNWM0NjhmN2FkYjk0M2IxMmZiZjUwMmEyNzgwNTQwZDgxODVhOTlmN2Y2NjJlMDA3ZjgwODExZDNiNWFlNzUxNGVkMjYyZDI5ZTMyMzFjYjNmMGFkNTAxZTFiZmEyNWMyOWE2OWE2ZjQ4YTQ1NWVlM2E4NzM5MDcyYzJmMzFkZWU5ZjA0ZTZlZDY1YTVlMDMwODEyYmI5NzE5OTczZTc3OTFmZTQ4MTk3ZWU4OWQ5NjVlMTE4MGRkOTNhZTcyM2EyNzIyNzg4MDgzZWU5MGIwMzNhMzA0MDBkNTI1NWUzMWZmZDJiNDI5MDhhZjE3NTc5M2UyZDk0ZjViODI0ZDY3OTBiZjVmNWQ2MDFlMTg3ODk1MWFlMGY5YmQ5OTJhMjc5MmIyMDcwYzIyYmRkNmNlNmY1ZWU5MmFhYzVmMDEzZjJiYzM2ZjIxMDllYzE1YzE3N2RlYzQwMmNhNmNkNjczZmU5NDUyN2E1OTNiOWE1NTM2ZmNkMjIyNTJmMDFkNmRlZWJmODk2M2U3NDBhMDZiYTNjZjVjM2U2MDRhODRhNjQxYWY1MzhkNjAxZDQ2NjVhNGJlMmJlMWRmYTAxZDc1Y2QyOTZiZjc2YzIwYWM2NTY4MTEyYzQ2NGRjY2Q4MDFlODJhZmM3NmQwMjAzMDEwMDAxMzAwZDA2MDkyYTg2NDg4NmY3MGQwMTAxMDUwNTAwMDM4MjAxMDEwMDUwN2Y1OWNiZDZkNmNmYWQ0OWIxOTZjZDAxY2UyYjA2NTk0ZGZmOTU3OWIyYTkwMWUxODk3YjdkNGMwNWRjYmM4ZWJjYmNhZjA2ZjNlMzViMWI5NTM0MDg2OGE5MTFiOTQ5NzBkYTYyNTE2YmYwN2Q0MmE4NDk1YjNmZDc5NThkNjc4MDMzMmJmYzA2NjM4NTQ5NWM1YmI0NDNmNDE2MzQ5MjdiZTFkMmJkYjMyYzU1ZmRkZmI0NTQ1MDE5OGUzZWU4OWE2MmM3NGI3NzIyYTk0ZjE3ZDZhMmVjZTI5YTI3MmQ1NTU3MmY1OGQ3MmZhNmU0ZDJjNjc3MmFjMTYxMDU4ZjBiZTQ5NWEzNGVmMzZmZjU2NTQ1YWIwMDM0YmJiYjgwY2QwNmY4NzZhNWUzOGExYjc0ZmEyYTYyNGIyNjA1MjUyZjI2NzMwZTAwNWE3YjkwN2ZkZTQ4NzkyZmRhODc5ZDdhMDI3NzY3ZWQyZWI5NzI5MjNkMjJlOGJhZTc5Mjg0OTFlODk5MWFiZDRhNmY1YmM3NmYzZWI3NTM2YmVjNzYzYjcwNmQzNmUwMjkwNDVmN2UyODkxOWU5MmZjN2M0NTk5YWIwOTU5MGQ5ZDM2YjU0MjE4NjZjYTk5MWRhN2E4NDRjOGZhYjZmZmQwOWM1ZDIyMTc5ZjhjODY0Y2Yz", Base64.DEFAULT)))) {
Toast.makeText(context, String(Base64.decode("UGxlYXNlIGRvIG5vdCBtb2RpZnkgdGhpcyBtb2R1bGUhISEgLyDor7fkuI3opoHkv67mlLnmraTmqKHlnZfvvIHvvIHvvIE=", Base64.DEFAULT)), Toast.LENGTH_LONG).show()
exitProcess(0)
}
}
}
} }

View File

@ -3,11 +3,13 @@ buildscript {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
maven { url 'https://jitpack.io' }
} }
dependencies { dependencies {
classpath "com.android.tools.build:gradle:7.0.4" classpath "com.android.tools.build:gradle:7.2.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"
classpath "com.github.CodingGay:BlackObfuscator-ASPlugin:3.7"
classpath "icu.nullptr.stringfuck:gradle-plugin:0.1.4"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }

View File

@ -1,6 +1,6 @@
#Fri Apr 29 17:30:47 CST 2022 #Sat May 14 18:02:35 CST 2022
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME