NativeLoader

现在,可以在HMA做了隐藏的情况下正确加载库文件

借鉴过来的,貌似会导致亿点问题

感觉isEmu也会翻车呢  ┭┮﹏┭┮
This commit is contained in:
HanaHime 2024-02-29 11:29:26 +08:00
parent 60fdfd9071
commit 1f620bcc06
3 changed files with 96 additions and 3 deletions

View File

@ -69,6 +69,8 @@ dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation("cn.hutool:hutool-core:5.8.0.M1")
DEPENDENCY_ANDROIDX.forEach { DEPENDENCY_ANDROIDX.forEach {
implementation(it) implementation(it)
} }

View File

@ -1,11 +1,19 @@
package moe.fuqiuluo.shamrock.xposed.loader package moe.fuqiuluo.shamrock.xposed.loader
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import cn.hutool.core.io.FileUtil
import cn.hutool.core.io.IoUtil
import com.tencent.mmkv.MMKV
import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedBridge
import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.xposed.XposedEntry import moe.fuqiuluo.shamrock.xposed.XposedEntry
import moe.fuqiuluo.shamrock.xposed.loader.tmpnativehelper.moduleClassLoader
import mqq.app.MobileQQ import mqq.app.MobileQQ
import java.io.BufferedInputStream
import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
internal object NativeLoader { internal object NativeLoader {
@ -17,6 +25,31 @@ internal object NativeLoader {
return externalLibPath.resolve("libffmpegkit.so").exists() return externalLibPath.resolve("libffmpegkit.so").exists()
} }
private val isEmu: Boolean
get() {
if (Build.SUPPORTED_ABIS.any { it.contains("x86") }) {
XposedBridge.log("[Shamrock] 通过SUPPORTED_ABIS检测到 Android x86")
return true
}
return try {
val clazz = Class.forName("dalvik.system.VMRuntime")
val method = clazz.getDeclaredMethod("getRuntime")
val runtime = method.invoke(null)
val field = clazz.getDeclaredField("vmInstructionSet")
field.isAccessible = true
val instructionSet = field.get(runtime) as String
instructionSet.contains("x86")
XposedBridge.log("[Shamrock] 反射检测到 Android x86")
} catch (e: Exception) {
XposedBridge.log("[Shamrock] $e")
false
}
}
private fun getLibFilePath(name: String): String {
return if (isEmu) "lib/x86_64/lib${name}.so" else "lib/arm64-v8a/lib$name.so"
}
/** /**
* 使目标进程可以使用来自模块的库 * 使目标进程可以使用来自模块的库
*/ */
@ -24,7 +57,8 @@ internal object NativeLoader {
fun load(name: String) { fun load(name: String) {
try { try {
if (name == "shamrock" || name == "clover") { if (name == "shamrock" || name == "clover") {
val context = MobileQQ.getContext()
/* val context = MobileQQ.getContext()
val packageManager = context.packageManager val packageManager = context.packageManager
val applicationInfo = packageManager.getApplicationInfo("moe.fuqiuluo.shamrock.hided", 0) val applicationInfo = packageManager.getApplicationInfo("moe.fuqiuluo.shamrock.hided", 0)
val file = File(applicationInfo.nativeLibraryDir) val file = File(applicationInfo.nativeLibraryDir)
@ -34,7 +68,10 @@ internal object NativeLoader {
LogCenter.log("LoadLibrary(name = $name) failed, file not exists.", level = Level.ERROR) LogCenter.log("LoadLibrary(name = $name) failed, file not exists.", level = Level.ERROR)
return return
} }
}.absolutePath) }.absolutePath)*/
onload(name, getCtx())
} else { } else {
val sourceFile = externalLibPath.resolve("lib$name.so") val sourceFile = externalLibPath.resolve("lib$name.so")
val soFile = MobileQQ.getContext().filesDir.parentFile!!.resolve("txlib").resolve("lib$name.so") val soFile = MobileQQ.getContext().filesDir.parentFile!!.resolve("txlib").resolve("lib$name.so")
@ -54,4 +91,52 @@ internal object NativeLoader {
XposedBridge.log(e) XposedBridge.log(e)
} }
} }
}
fun getCtx() = MobileQQ.getContext()
@SuppressLint("UnsafeDynamicallyLoadedCode")
fun onload(name: String, context: Context) {
val soDir = File(context.filesDir, "SM_LIBS")
if (soDir.isFile) {
soDir.delete()
}
if (!soDir.exists()) {
soDir.mkdirs()
}
val soPath = NativeLoader.getLibFilePath(name)
val soFile = File(soDir, name)
val libStream =
BufferedInputStream(moduleClassLoader.getResourceAsStream(soPath))
val tmpSoFile = File(soDir, "$name.tmp")
try {
FileUtil.writeFromStream(libStream, tmpSoFile)
if (!soFile.exists()) {
LogCenter.log("SO文件 ${name} 不存在,正在尝试加载", Level.INFO)
tmpSoFile.renameTo(soFile)
} else {
val oldStream = FileUtil.getInputStream(soFile)
val newStream = FileUtil.getInputStream(tmpSoFile)
if (!IoUtil.contentEquals(oldStream, newStream)) {
LogCenter.log("SO文件版本不一致正在重新加载", Level.INFO)
soFile.delete()
tmpSoFile.renameTo(soFile)
}
}
try {
System.load(soFile.absolutePath)
LogCenter.log("加载SO文件成功 -> ${soFile.path}", Level.INFO)
} catch (e: Throwable) {
LogCenter.log(e.toString(), Level.WARN)
throw e
}
} catch (e: Exception) {
LogCenter.log(e.toString(), Level.WARN)
throw e
} finally {
if (tmpSoFile.exists()) {
tmpSoFile.delete()
}
}
}
}

View File

@ -0,0 +1,6 @@
@file:JvmName("ModuleInfo")
package moe.fuqiuluo.shamrock.xposed.loader.tmpnativehelper
import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader
val moduleClassLoader: ClassLoader = LuoClassloader::class.java.classLoader!!