2 Commits

Author SHA1 Message Date
38cf806b40 Shamrock: review
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-29 22:40:36 +08:00
82269bb171 NativeLoader
应该是这样关?
猫脑过载.png
2024-02-29 20:43:18 +08:00
2 changed files with 27 additions and 44 deletions

View File

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

View File

@ -3,17 +3,12 @@ package moe.fuqiuluo.shamrock.xposed.loader
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 moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.xposed.XposedEntry
import moe.fuqiuluo.shamrock.xposed.loader.tmpnativehelper.moduleClassLoader
import mqq.app.MobileQQ
import java.io.BufferedInputStream
import java.io.ByteArrayOutputStream
import oicq.wlogin_sdk.tools.MD5
import java.io.File
internal object NativeLoader {
@ -40,7 +35,8 @@ internal object NativeLoader {
val instructionSet = field.get(runtime) as String
if ( instructionSet.contains("x86") ) {
XposedBridge.log("[Shamrock] 反射检测到 Android x86")
true } else { false }
true
} else false
} catch (e: Exception) {
XposedBridge.log("[Shamrock] $e")
false
@ -58,21 +54,7 @@ internal object NativeLoader {
fun load(name: String) {
try {
if (name == "shamrock" || name == "clover") {
/* val context = MobileQQ.getContext()
val packageManager = context.packageManager
val applicationInfo = packageManager.getApplicationInfo("moe.fuqiuluo.shamrock.hided", 0)
val file = File(applicationInfo.nativeLibraryDir)
LogCenter.log("LoadLibrary(name = $name)")
System.load(file.resolve("lib$name.so").also {
if (!it.exists()) {
LogCenter.log("LoadLibrary(name = $name) failed, file not exists.", level = Level.ERROR)
return
}
}.absolutePath)*/
onload(name, getCtx())
onLoadByCopiedLibrary(name, getCtx())
} else {
val sourceFile = externalLibPath.resolve("lib$name.so")
val soFile = MobileQQ.getContext().filesDir.parentFile!!.resolve("txlib").resolve("lib$name.so")
@ -93,10 +75,10 @@ internal object NativeLoader {
}
}
fun getCtx() = MobileQQ.getContext()
private inline fun getCtx() = MobileQQ.getContext()
@SuppressLint("UnsafeDynamicallyLoadedCode")
fun onload(name: String, context: Context) {
private fun onLoadByCopiedLibrary(name: String, context: Context) {
val soDir = File(context.filesDir, "SM_LIBS")
if (soDir.isFile) {
soDir.delete()
@ -104,23 +86,31 @@ internal object NativeLoader {
if (!soDir.exists()) {
soDir.mkdirs()
}
val soPath = NativeLoader.getLibFilePath(name)
val soPath = 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)
fun reloadSo(tmp: File? = null) {
LogCenter.log("SO文件大小不一致或不存在正在重新加载", Level.INFO)
soFile.delete()
tmpSoFile.renameTo(soFile)
if (tmp == null) moduleClassLoader.getResourceAsStream(soPath).use { origin ->
soFile.outputStream().use { origin.copyTo(it) }
} else tmp.renameTo(soFile)
}
try {
if (!soFile.exists()) {
reloadSo()
} else {
val tmpSoFile = soFile.resolve("$name.tmp").also { file ->
if (file.exists()) file.delete()
file.outputStream().use {
moduleClassLoader.getResourceAsStream(soPath).use { origin ->
origin.copyTo(it)
}
}
}
if (soFile.length() != tmpSoFile.length() || MD5.getFileMD5(soFile).let {
it != MD5.getFileMD5(tmpSoFile)
}) {
reloadSo(tmpSoFile)
}
}
try {
@ -133,11 +123,6 @@ internal object NativeLoader {
} catch (e: Exception) {
LogCenter.log(e.toString(), Level.WARN)
throw e
} finally {
if (tmpSoFile.exists()) {
tmpSoFile.delete()
}
}
}
}