refactor: modify dexkit backend

This commit is contained in:
teble
2022-09-26 19:48:19 +08:00
parent dd6d993321
commit feb058c728
14 changed files with 721 additions and 360 deletions

3
.gitmodules vendored
View File

@@ -4,3 +4,6 @@
[submodule "libs/stub/qq-stub"] [submodule "libs/stub/qq-stub"]
path = libs/stub/qq-stub path = libs/stub/qq-stub
url = https://github.com/LuckyPray/qq-stub url = https://github.com/LuckyPray/qq-stub
[submodule "libs/dexkit/DexKit"]
path = libs/dexkit/DexKit
url = git@github.com:LuckyPray/DexKit.git

View File

@@ -178,6 +178,7 @@ android {
dependencies { dependencies {
compileOnly(projects.libs.stub) compileOnly(projects.libs.stub)
implementation(projects.libs.mmkv) implementation(projects.libs.mmkv)
implementation(projects.libs.dexkit)
ksp(projects.libs.ksp) ksp(projects.libs.ksp)
// androidx // androidx
implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.core:core-ktx:1.9.0")
@@ -205,7 +206,6 @@ dependencies {
implementation("com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}") implementation("com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0")
implementation("com.github.LuckyPray:DexKit-Android:1.2.2")
implementation("com.github.livefront.sealed-enum:runtime:0.5.0") implementation("com.github.livefront.sealed-enum:runtime:0.5.0")
ksp("com.github.livefront.sealed-enum:ksp:0.5.0") ksp("com.github.livefront.sealed-enum:ksp:0.5.0")
} }
@@ -223,6 +223,12 @@ val openQQ = tasks.register<Exec>("openQQ") {
isIgnoreExitValue = true isIgnoreExitValue = true
} }
val restartQQ = tasks.register<Exec>("restartQQ") {
group = "qauxv"
commandLine(adb, "shell", "am", "start", "$(pm resolve-activity --components com.tencent.mobileqq)")
isIgnoreExitValue = true
}
tasks.register<Exec>("openTroubleShooting") { tasks.register<Exec>("openTroubleShooting") {
group = "qauxv" group = "qauxv"
commandLine( commandLine(
@@ -255,8 +261,8 @@ androidComponents.onVariants { variant ->
task("install${variantCapped}AndRestartQQ") { task("install${variantCapped}AndRestartQQ") {
group = "qauxv" group = "qauxv"
dependsOn(":app:install$variantCapped") dependsOn(":app:install$variantCapped")
openQQ.dependsOn(killQQ) restartQQ.dependsOn(killQQ)
finalizedBy(killQQ, openQQ) finalizedBy(killQQ, restartQQ)
} }
} }
@@ -300,7 +306,8 @@ tasks.register("checkGitSubmodule") {
doLast { doLast {
listOf( listOf(
"libs/mmkv/MMKV/Core", "libs/mmkv/MMKV/Core",
"libs/stub/qq-stub" "libs/stub/qq-stub",
"libs/dexkit/DexKit/Core",
).forEach { ).forEach {
val submoduleDir = File(projectDir, it.replace('/', File.separatorChar)) val submoduleDir = File(projectDir, it.replace('/', File.separatorChar))
if (!submoduleDir.exists()) { if (!submoduleDir.exists()) {

View File

@@ -309,12 +309,12 @@
license: Apache-2.0 license: Apache-2.0
licenseUrl: https://www.apache.org/licenses/LICENSE-2.0.txt licenseUrl: https://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/KyuubiRan/EzXHelper url: https://github.com/KyuubiRan/EzXHelper
- artifact: com.github.LuckyPray:DexKit-Android:+ - artifact: com.github.LuckyPray:DexKit:+
name: DexKit-Android name: DexKit
copyrightHolder: LuckyPray copyrightHolder: LuckyPray
licenseUrl: https://www.gnu.org/licenses/lgpl-3.0.html licenseUrl: https://www.gnu.org/licenses/lgpl-3.0.html
license: LGPL-3.0 license license: LGPL-3.0 license
url: https://github.com/LuckyPray/DexKit-Android url: https://github.com/LuckyPray/DexKit
- artifact: com.github.plattysoft:Leonids:+ - artifact: com.github.plattysoft:Leonids:+
name: Leonids name: Leonids
copyrightHolder: #COPYRIGHT_HOLDER# copyrightHolder: #COPYRIGHT_HOLDER#

View File

@@ -26,7 +26,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CLANG_C_EXTRA_OPT} -fPIC -Werror=return-ty
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-allow-shlib-undefined,--no-undefined") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-allow-shlib-undefined,--no-undefined")
add_subdirectory(../../../../libs/mmkv mmkv) add_subdirectory(../../../../libs/mmkv mmkv)
find_package(dexkit REQUIRED CONFIG) add_subdirectory(../../../../libs/dexkit dexkit)
add_library(qauxv SHARED add_library(qauxv SHARED
qauxv_core/Natives.cpp qauxv_core/Natives.cpp
@@ -34,7 +34,7 @@ add_library(qauxv SHARED
qauxv_core/NativeHookEntry.cc qauxv_core/NativeHookEntry.cc
qauxv_core/NativeMainHook.cc qauxv_core/NativeMainHook.cc
qauxv_core/shared_memory.cpp qauxv_core/shared_memory.cpp
qauxv_core/dexkit.cc) )
set_target_properties(qauxv PROPERTIES set_target_properties(qauxv PROPERTIES
CXX_EXTENSIONS OFF CXX_EXTENSIONS OFF
@@ -44,4 +44,4 @@ set_target_properties(qauxv PROPERTIES
target_compile_definitions(qauxv PRIVATE QAUXV_VERSION=\"${QAUXV_VERSION}\") target_compile_definitions(qauxv PRIVATE QAUXV_VERSION=\"${QAUXV_VERSION}\")
target_link_options(qauxv PRIVATE "-Wl,-e,__libqauxv_main") target_link_options(qauxv PRIVATE "-Wl,-e,__libqauxv_main")
target_link_libraries(qauxv mmkv c dl z ${ANDROID_LIBS} dexkit::dex_kit_static) target_link_libraries(qauxv mmkv dexkit c dl z ${ANDROID_LIBS})

View File

@@ -457,6 +457,10 @@ EXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
if (retCode < 0) { if (retCode < 0) {
return retCode; return retCode;
} }
retCode = DexKit_JNI_OnLoad(vm, reserved);
if (retCode < 0) {
return retCode;
}
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return -1; return -1;
} }

View File

@@ -22,6 +22,7 @@
package cc.ioctl.hook; package cc.ioctl.hook;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static io.luckypray.dexkit.descriptor.DexDescriptorUtil.getTypeSig;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -37,10 +38,11 @@ import io.github.qauxv.util.Initiator;
import io.github.qauxv.util.Log; import io.github.qauxv.util.Log;
import io.github.qauxv.util.dexkit.DexDeobfsProvider; import io.github.qauxv.util.dexkit.DexDeobfsProvider;
import io.github.qauxv.util.dexkit.DexKitFinder; import io.github.qauxv.util.dexkit.DexKitFinder;
import io.github.qauxv.util.dexkit.DexMethodDescriptor;
import io.github.qauxv.util.dexkit.impl.DexKitDeobfs; import io.github.qauxv.util.dexkit.impl.DexKitDeobfs;
import io.luckypray.dexkit.descriptor.member.DexMethodDescriptor;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -117,7 +119,7 @@ public class HideMiniAppPullEntry extends CommonSwitchFunctionHook implements De
if (clz == null) { if (clz == null) {
return false; return false;
} }
String conversationSig = DexMethodDescriptor.getTypeSig(clz); String conversationSig = getTypeSig(clz);
DexKitDeobfs dexKitDeobfs = (DexKitDeobfs) DexDeobfsProvider.INSTANCE.getCurrentBackend(); DexKitDeobfs dexKitDeobfs = (DexKitDeobfs) DexDeobfsProvider.INSTANCE.getCurrentBackend();
String[] strings = new String[]{ String[] strings = new String[]{
"initMiniAppEntryLayout.", "initMiniAppEntryLayout.",
@@ -130,18 +132,16 @@ public class HideMiniAppPullEntry extends CommonSwitchFunctionHook implements De
set.add(strings[i]); set.add(strings[i]);
map.put("Conversation_" + i, set); map.put("Conversation_" + i, set);
} }
Map<String, String[]> res = dexKitDeobfs.getDexKitHelper().batchFindMethodsUsedStrings(map, false, new int[0]); Map<String, List<DexMethodDescriptor>> res = dexKitDeobfs.getDexKitHelper().batchFindMethodsUsingStrings(map, false, new int[0]);
for (String[] methods: res.values()) { for (List<DexMethodDescriptor> methods: res.values()) {
for (String method : methods) { for (DexMethodDescriptor descriptor: methods) {
DexMethodDescriptor descriptor = new DexMethodDescriptor(method); if (descriptor.getDeclaringClassSig().equals(conversationSig)
if (descriptor.declaringClass.equals(conversationSig) && "()V".equals(descriptor.getMethodTypeSig())) {
&& "()V".equals(descriptor.signature)) {
Log.i("下拉 desc " + descriptor);
// save and return // save and return
ConfigManager cache = ConfigManager.getCache(); ConfigManager cache = ConfigManager.getCache();
cache.putInt("qn_hide_miniapp_v2_version_code", cache.putInt("qn_hide_miniapp_v2_version_code",
HostInfo.getVersionCode()); HostInfo.getVersionCode());
cache.putString("qn_hide_miniapp_v2_method_name", descriptor.name); cache.putString("qn_hide_miniapp_v2_method_name", descriptor.getName());
cache.save(); cache.save();
return true; return true;
} }

View File

@@ -40,17 +40,17 @@ import io.github.qauxv.util.dexkit.DexDeobfsProvider;
import io.github.qauxv.util.dexkit.DexKit; import io.github.qauxv.util.dexkit.DexKit;
import io.github.qauxv.util.dexkit.DexKitFinder; import io.github.qauxv.util.dexkit.DexKitFinder;
import io.github.qauxv.util.dexkit.DexKitTargetSealedEnum; import io.github.qauxv.util.dexkit.DexKitTargetSealedEnum;
import io.github.qauxv.util.dexkit.DexMethodDescriptor;
import io.github.qauxv.util.dexkit.NTextItemBuilder_setETText; import io.github.qauxv.util.dexkit.NTextItemBuilder_setETText;
import io.github.qauxv.util.dexkit.impl.DexKitDeobfs; import io.github.qauxv.util.dexkit.impl.DexKitDeobfs;
import io.luckypray.dexkit.DexKitBridge;
import io.luckypray.dexkit.descriptor.member.DexFieldDescriptor;
import io.luckypray.dexkit.descriptor.member.DexMethodDescriptor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import me.teble.DexKitHelper;
//强制使用默认字体 //强制使用默认字体
@FunctionHookEntry @FunctionHookEntry
@@ -116,34 +116,34 @@ public class DefaultFont extends CommonSwitchFunctionHook implements DexKitFinde
public boolean doFind() { public boolean doFind() {
// protected (BaseBubbleBuilder, TextItemBuilder).void ?(BaseBubbleBuilder.ViewHolder, ChatMessage) // protected (BaseBubbleBuilder, TextItemBuilder).void ?(BaseBubbleBuilder.ViewHolder, ChatMessage)
DexKitDeobfs dexKitDeobfs = (DexKitDeobfs) DexDeobfsProvider.INSTANCE.getCurrentBackend(); DexKitDeobfs dexKitDeobfs = (DexKitDeobfs) DexDeobfsProvider.INSTANCE.getCurrentBackend();
DexKitHelper helper = dexKitDeobfs.getDexKitHelper(); DexKitBridge dexKit = dexKitDeobfs.getDexKitHelper();
String[] resultMethods = helper.findMethodUsedField( Map<DexMethodDescriptor, List<DexFieldDescriptor>> resultMethods = dexKit.findMethodUsingField(
"", "",
"", "",
"", "",
"Landroid/widget/TextView;", "Landroid/widget/TextView;",
DexKitHelper.FLAG_GETTING, DexKitBridge.FLAG_GETTING,
Initiator._TextItemBuilder().getName(), Initiator._TextItemBuilder().getName(),
"", "",
"void", "void",
new String[]{"", Initiator._ChatMessage().getName()}, new String[]{"", Initiator._ChatMessage().getName()},
null null
); );
List<String> descs = Arrays.stream(resultMethods) List<DexMethodDescriptor> methods = resultMethods.keySet().stream()
.filter(s -> s.contains("BaseBubbleBuilder")) .filter(s -> s.getParameterTypesSig().contains("BaseBubbleBuilder"))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (descs.size() == 1) { if (methods.size() == 1) {
try { try {
DexMethodDescriptor descriptor = new DexMethodDescriptor(descs.get(0)); DexMethodDescriptor descriptor = methods.get(0);
descriptor.getMethodInstance(Initiator.getHostClassLoader()); descriptor.getMethod(Initiator.getHostClassLoader());
NTextItemBuilder_setETText.INSTANCE.setDescCache(descriptor.toString()); NTextItemBuilder_setETText.INSTANCE.setDescCache(descriptor.toString());
Log.d("save id: " + DexKitTargetSealedEnum.INSTANCE.nameOf(NTextItemBuilder_setETText.INSTANCE) + ",method: " + descs.get(0)); Log.d("save id: " + DexKitTargetSealedEnum.INSTANCE.nameOf(NTextItemBuilder_setETText.INSTANCE) + ",method: " + descriptor);
return true; return true;
} catch (NoSuchMethodException e) { } catch (Throwable e) {
Log.e(e); Log.e(e);
} }
} }
Map<String, String[]> resMap = helper.findMethodInvoking( Map<DexMethodDescriptor, List<DexMethodDescriptor>> resMap = dexKit.findMethodInvoking(
"", "",
"Lcom/tencent/mobileqq/activity/aio/item/TextItemBuilder;", "Lcom/tencent/mobileqq/activity/aio/item/TextItemBuilder;",
"", "",
@@ -155,20 +155,20 @@ public class DefaultFont extends CommonSwitchFunctionHook implements DexKitFinde
null, null,
null null
); );
Set<String> classSet = resMap.keySet().stream() Set<DexMethodDescriptor> methodSet = resMap.keySet().stream()
.filter(s -> s.contains("BaseBubbleBuilder")) .filter(s -> s.getParameterTypesSig().contains("BaseBubbleBuilder"))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
List<String> res = descs.stream() List<DexMethodDescriptor> res = methods.stream()
.filter(s -> !classSet.contains(s)) .filter(s -> !methodSet.contains(s))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (res.size() == 1) { if (res.size() == 1) {
try { try {
DexMethodDescriptor descriptor = new DexMethodDescriptor(descs.get(0)); DexMethodDescriptor descriptor = res.get(0);
descriptor.getMethodInstance(Initiator.getHostClassLoader()); descriptor.getMethod(Initiator.getHostClassLoader());
NTextItemBuilder_setETText.INSTANCE.setDescCache(descriptor.toString()); NTextItemBuilder_setETText.INSTANCE.setDescCache(descriptor.toString());
Log.d("save id: " + DexKitTargetSealedEnum.INSTANCE.nameOf(NTextItemBuilder_setETText.INSTANCE) + ",method: " + descs.get(0)); Log.d("save id: " + DexKitTargetSealedEnum.INSTANCE.nameOf(NTextItemBuilder_setETText.INSTANCE) + ",method: " + descriptor);
return true; return true;
} catch (NoSuchMethodException e) { } catch (Throwable e) {
Log.e(e); Log.e(e);
} }
} }

View File

@@ -31,19 +31,20 @@ import io.github.qauxv.util.dexkit.DexKitTarget
import io.github.qauxv.util.dexkit.DexMethodDescriptor import io.github.qauxv.util.dexkit.DexMethodDescriptor
import io.github.qauxv.util.dexkit.name import io.github.qauxv.util.dexkit.name
import io.github.qauxv.util.dexkit.valueOf import io.github.qauxv.util.dexkit.valueOf
import me.teble.DexKitHelper import io.luckypray.dexkit.DexKitBridge
import io.luckypray.dexkit.descriptor.member.DexMethodDescriptor as MethodDescriptor
import java.util.concurrent.locks.Lock import java.util.concurrent.locks.Lock
class DexKitDeobfs private constructor( class DexKitDeobfs private constructor(
private val mReadLock: Lock, private val mReadLock: Lock,
private var mDexKitHelper: DexKitHelper? private var mDexKitHelper: DexKitBridge?
) : DexDeobfsBackend { ) : DexDeobfsBackend {
override val id: String = ID override val id: String = ID
override val name: String = NAME override val name: String = NAME
override val isBatchFindMethodSupported: Boolean = true override val isBatchFindMethodSupported: Boolean = true
fun getDexKitHelper(): DexKitHelper { fun getDexKitHelper(): DexKitBridge {
return mDexKitHelper!! return mDexKitHelper!!
} }
@@ -68,8 +69,8 @@ class DexKitDeobfs private constructor(
} }
} }
val resultMap = helper.batchFindMethodsUsedStrings(deobfsMap, true) val resultMap = helper.batchFindMethodsUsingStrings(deobfsMap, true)
val resultMap2 = mutableMapOf<String, Set<String>>() val resultMap2 = mutableMapOf<String, Set<MethodDescriptor>>()
resultMap.forEach { resultMap.forEach {
val key = it.key.split("#").first() val key = it.key.split("#").first()
if (resultMap2.containsKey(key)) { if (resultMap2.containsKey(key)) {
@@ -81,9 +82,9 @@ class DexKitDeobfs private constructor(
resultMap2.forEach { (key, valueArr) -> resultMap2.forEach { (key, valueArr) ->
val target = DexKitTarget.valueOf(key) val target = DexKitTarget.valueOf(key)
val ret = target.verifyTargetMethod(valueArr.map { DexMethodDescriptor(it) }) val ret = target.verifyTargetMethod(valueArr.map { DexMethodDescriptor(it.descriptor) })
if (ret == null) { if (ret == null) {
valueArr.forEach(Log::i) valueArr.map { it.descriptor }.forEach(Log::i)
Log.e("${valueArr.size} candidates found for " + key + ", none satisfactory, save null.") Log.e("${valueArr.size} candidates found for " + key + ", none satisfactory, save null.")
target.descCache = DexKit.NO_SUCH_METHOD.toString() target.descCache = DexKit.NO_SUCH_METHOD.toString()
} else { } else {
@@ -109,9 +110,9 @@ class DexKitDeobfs private constructor(
val helper = mDexKitHelper!! val helper = mDexKitHelper!!
val keys = target.traitString val keys = target.traitString
val methods = keys.map { key -> val methods = keys.map { key ->
helper.findMethodUsedString(key, true) helper.findMethodUsingString(key, true)
}.flatMap { desc -> }.flatMap { desc ->
desc.map { DexMethodDescriptor(it) } desc.map { DexMethodDescriptor(it.descriptor) }
} }
if (methods.isNotEmpty()) { if (methods.isNotEmpty()) {
ret = target.verifyTargetMethod(methods) ret = target.verifyTargetMethod(methods)
@@ -151,15 +152,15 @@ class DexKitDeobfs private constructor(
} }
private val mSharedResourceImpl by lazy { private val mSharedResourceImpl by lazy {
object : SharedRefCountResourceImpl<DexKitHelper>() { object : SharedRefCountResourceImpl<DexKitBridge>() {
override fun openResourceInternal(): DexKitHelper { override fun openResourceInternal(): DexKitBridge {
Log.d("open resource: DexKit") Log.d("open resource: DexKit")
val dexClassLoader: ClassLoader = Initiator.getHostClassLoader().findDexClassLoader()!! val dexClassLoader: ClassLoader = Initiator.getHostClassLoader().findDexClassLoader()!!
return DexKitHelper(dexClassLoader) return DexKitBridge.create(dexClassLoader)!!
} }
override fun closeResourceInternal(res: DexKitHelper) { override fun closeResourceInternal(res: DexKitBridge) {
res.release() res.close()
Log.d("close resource: DexKit") Log.d("close resource: DexKit")
} }
} }

View File

@@ -1,303 +1,303 @@
/* ///*
* QAuxiliary - An Xposed module for QQ/TIM // * QAuxiliary - An Xposed module for QQ/TIM
* Copyright (C) 2019-2022 qwq233@qwq2333.top // * Copyright (C) 2019-2022 qwq233@qwq2333.top
* https://github.com/cinit/QAuxiliary // * https://github.com/cinit/QAuxiliary
* // *
* This software is non-free but opensource software: you can redistribute it // * This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License // * and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either // * as published by the Free Software Foundation; either
* version 3 of the License, or any later version and our eula as published // * version 3 of the License, or any later version and our eula as published
* by QAuxiliary contributors. // * by QAuxiliary contributors.
* // *
* This software is distributed in the hope that it will be useful, // * This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of // * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details. // * Affero General Public License for more details.
* // *
* You should have received a copy of the GNU Affero General Public License // * You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see // * and eula along with this software. If not, see
* <https://www.gnu.org/licenses/> // * <https://www.gnu.org/licenses/>
* <https://github.com/cinit/QAuxiliary/blob/master/LICENSE.md>. // * <https://github.com/cinit/QAuxiliary/blob/master/LICENSE.md>.
*/ // */
//
package me.teble //package me.teble
//
class DexKitHelper( //class DexKitHelper(
classLoader: ClassLoader // classLoader: ClassLoader
) { //) {
companion object { // companion object {
const val FLAG_GETTING = 1 // const val FLAG_GETTING = 1
const val FLAG_SETTING = 2 // const val FLAG_SETTING = 2
const val FLAG_USING = FLAG_GETTING or FLAG_SETTING // const val FLAG_USING = FLAG_GETTING or FLAG_SETTING
} // }
//
/** // /**
* 使用完成后切记记得调用 [release],否则内存不会释放 // * 使用完成后切记记得调用 [release],否则内存不会释放
*/ // */
private var token: Long = 0 // private var token: Long = 0
//
init { // init {
token = initDexKit(classLoader) // token = initDexKit(classLoader)
} // }
//
fun release() { // fun release() {
release(token) // release(token)
} // }
//
fun batchFindClassesUsedStrings( // fun batchFindClassesUsedStrings(
map: Map<String, Set<String>>, // map: Map<String, Set<String>>,
advancedMatch: Boolean = true, // advancedMatch: Boolean = true,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Map<String, Array<String>> { // ): Map<String, Array<String>> {
return batchFindClassesUsedStrings(token, map, advancedMatch, dexPriority) // return batchFindClassesUsedStrings(token, map, advancedMatch, dexPriority)
} // }
//
fun batchFindMethodsUsedStrings( // fun batchFindMethodsUsedStrings(
map: Map<String, Set<String>>, // map: Map<String, Set<String>>,
advancedMatch: Boolean = true, // advancedMatch: Boolean = true,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Map<String, Array<String>> { // ): Map<String, Array<String>> {
return batchFindMethodsUsedStrings(token, map, advancedMatch, dexPriority) // return batchFindMethodsUsedStrings(token, map, advancedMatch, dexPriority)
} // }
//
fun findMethodBeInvoked( // fun findMethodBeInvoked(
methodDescriptor: String, // methodDescriptor: String,
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>? = null, // methodParamTypes: Array<String>? = null,
callerMethodDeclareClass: String, // callerMethodDeclareClass: String,
callerMethodName: String, // callerMethodName: String,
callerMethodReturnType: String, // callerMethodReturnType: String,
callerMethodParamTypes: Array<String>? = null, // callerMethodParamTypes: Array<String>? = null,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Array<String> { // ): Array<String> {
return findMethodBeInvoked( // return findMethodBeInvoked(
token, // token,
methodDescriptor, // methodDescriptor,
methodDeclareClass, // methodDeclareClass,
methodName, // methodName,
methodReturnType, // methodReturnType,
methodParamTypes, // methodParamTypes,
callerMethodDeclareClass, // callerMethodDeclareClass,
callerMethodName, // callerMethodName,
callerMethodReturnType, // callerMethodReturnType,
callerMethodParamTypes, // callerMethodParamTypes,
dexPriority // dexPriority
) // )
} // }
//
fun findMethodInvoking( // fun findMethodInvoking(
methodDescriptor: String, // methodDescriptor: String,
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>? = null, // methodParamTypes: Array<String>? = null,
beCalledMethodDeclareClass: String, // beCalledMethodDeclareClass: String,
beCalledMethodName: String, // beCalledMethodName: String,
beCalledMethodReturnType: String, // beCalledMethodReturnType: String,
beCalledMethodParamTypes: Array<String>? = null, // beCalledMethodParamTypes: Array<String>? = null,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Map<String, Array<String>> { // ): Map<String, Array<String>> {
return findMethodInvoking( // return findMethodInvoking(
token, // token,
methodDescriptor, // methodDescriptor,
methodDeclareClass, // methodDeclareClass,
methodName, // methodName,
methodReturnType, // methodReturnType,
methodParamTypes, // methodParamTypes,
beCalledMethodDeclareClass, // beCalledMethodDeclareClass,
beCalledMethodName, // beCalledMethodName,
beCalledMethodReturnType, // beCalledMethodReturnType,
beCalledMethodParamTypes, // beCalledMethodParamTypes,
dexPriority // dexPriority
) // )
} // }
//
fun findMethodUsedField( // fun findMethodUsedField(
fieldDescriptor: String, // fieldDescriptor: String,
fieldDeclareClass: String, // fieldDeclareClass: String,
fieldName: String, // fieldName: String,
fieldType: String, // fieldType: String,
usedFlags: Int, // usedFlags: Int,
callerMethodDeclareClass: String, // callerMethodDeclareClass: String,
callerMethodName: String, // callerMethodName: String,
callerMethodReturnType: String, // callerMethodReturnType: String,
callerMethodParamTypes: Array<String>? = null, // callerMethodParamTypes: Array<String>? = null,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Array<String> { // ): Array<String> {
return findMethodUsedField( // return findMethodUsedField(
token, // token,
fieldDescriptor, // fieldDescriptor,
fieldDeclareClass, // fieldDeclareClass,
fieldName, // fieldName,
fieldType, // fieldType,
usedFlags, // usedFlags,
callerMethodDeclareClass, // callerMethodDeclareClass,
callerMethodName, // callerMethodName,
callerMethodReturnType, // callerMethodReturnType,
callerMethodParamTypes, // callerMethodParamTypes,
dexPriority // dexPriority
) // )
} // }
//
fun findMethodUsedString( // fun findMethodUsedString(
usedString: String, // usedString: String,
advancedMatch: Boolean = true, // advancedMatch: Boolean = true,
methodDeclareClass: String = "", // methodDeclareClass: String = "",
methodName: String = "", // methodName: String = "",
methodReturnType: String = "", // methodReturnType: String = "",
methodParamTypes: Array<String>? = null, // methodParamTypes: Array<String>? = null,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Array<String> { // ): Array<String> {
return findMethodUsedString( // return findMethodUsedString(
token, // token,
usedString, // usedString,
advancedMatch, // advancedMatch,
methodDeclareClass, // methodDeclareClass,
methodName, // methodName,
methodReturnType, // methodReturnType,
methodParamTypes, // methodParamTypes,
dexPriority // dexPriority
) // )
} // }
//
fun findMethod( // fun findMethod(
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>? = null, // methodParamTypes: Array<String>? = null,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Array<String> { // ): Array<String> {
return findMethod( // return findMethod(
token, // token,
methodDeclareClass, // methodDeclareClass,
methodName, // methodName,
methodReturnType, // methodReturnType,
methodParamTypes, // methodParamTypes,
dexPriority // dexPriority
) // )
} // }
//
fun findSubClasses( // fun findSubClasses(
parentClass: String, // parentClass: String,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Array<String> { // ): Array<String> {
return findSubClasses(token, parentClass, dexPriority) // return findSubClasses(token, parentClass, dexPriority)
} // }
//
fun findMethodOpPrefixSeq( // fun findMethodOpPrefixSeq(
opPrefixSeq: IntArray, // opPrefixSeq: IntArray,
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>? = null, // methodParamTypes: Array<String>? = null,
dexPriority: IntArray? = intArrayOf(), // dexPriority: IntArray? = intArrayOf(),
): Array<String> { // ): Array<String> {
return findMethodOpPrefixSeq( // return findMethodOpPrefixSeq(
token, // token,
opPrefixSeq, // opPrefixSeq,
methodDeclareClass, // methodDeclareClass,
methodName, // methodName,
methodReturnType, // methodReturnType,
methodParamTypes, // methodParamTypes,
dexPriority // dexPriority
) // )
} // }
//
private external fun initDexKit(classLoader: ClassLoader): Long // private external fun initDexKit(classLoader: ClassLoader): Long
//
private external fun release(token: Long) // private external fun release(token: Long)
//
private external fun batchFindClassesUsedStrings( // private external fun batchFindClassesUsedStrings(
token: Long, // token: Long,
map: Map<String, Set<String>>, // map: Map<String, Set<String>>,
advancedMatch: Boolean, // advancedMatch: Boolean,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Map<String, Array<String>> // ): Map<String, Array<String>>
//
private external fun batchFindMethodsUsedStrings( // private external fun batchFindMethodsUsedStrings(
token: Long, // token: Long,
map: Map<String, Set<String>>, // map: Map<String, Set<String>>,
advancedMatch: Boolean, // advancedMatch: Boolean,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Map<String, Array<String>> // ): Map<String, Array<String>>
//
private external fun findMethodBeInvoked( // private external fun findMethodBeInvoked(
token: Long, // token: Long,
methodDescriptor: String, // methodDescriptor: String,
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>?, // methodParamTypes: Array<String>?,
callerMethodDeclareClass: String, // callerMethodDeclareClass: String,
callerMethodName: String, // callerMethodName: String,
callerMethodReturnType: String, // callerMethodReturnType: String,
callerMethodParamTypes: Array<String>?, // callerMethodParamTypes: Array<String>?,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Array<String> // ): Array<String>
//
private external fun findMethodInvoking( // private external fun findMethodInvoking(
token: Long, // token: Long,
methodDescriptor: String, // methodDescriptor: String,
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>?, // methodParamTypes: Array<String>?,
beCalledMethodDeclareClass: String, // beCalledMethodDeclareClass: String,
beCalledMethodName: String, // beCalledMethodName: String,
beCalledMethodReturnType: String, // beCalledMethodReturnType: String,
beCalledMethodParamTypes: Array<String>?, // beCalledMethodParamTypes: Array<String>?,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Map<String, Array<String>> // ): Map<String, Array<String>>
//
private external fun findMethodUsedField( // private external fun findMethodUsedField(
token: Long, // token: Long,
fieldDescriptor: String, // fieldDescriptor: String,
fieldDeclareClass: String, // fieldDeclareClass: String,
fieldName: String, // fieldName: String,
fieldType: String, // fieldType: String,
beUsedFlags: Int, // beUsedFlags: Int,
callerMethodDeclareClass: String, // callerMethodDeclareClass: String,
callerMethodName: String, // callerMethodName: String,
callerMethodReturnType: String, // callerMethodReturnType: String,
callerMethodParamTypes: Array<String>?, // callerMethodParamTypes: Array<String>?,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Array<String> // ): Array<String>
//
private external fun findMethodUsedString( // private external fun findMethodUsedString(
token: Long, // token: Long,
usedString: String, // usedString: String,
advancedMatch: Boolean, // advancedMatch: Boolean,
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>?, // methodParamTypes: Array<String>?,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Array<String> // ): Array<String>
//
private external fun findMethod( // private external fun findMethod(
token: Long, // token: Long,
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>?, // methodParamTypes: Array<String>?,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Array<String> // ): Array<String>
//
private external fun findSubClasses( // private external fun findSubClasses(
token: Long, // token: Long,
parentClass: String, // parentClass: String,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Array<String> // ): Array<String>
//
private external fun findMethodOpPrefixSeq( // private external fun findMethodOpPrefixSeq(
token: Long, // token: Long,
opPrefixSeq: IntArray, // opPrefixSeq: IntArray,
methodDeclareClass: String, // methodDeclareClass: String,
methodName: String, // methodName: String,
methodReturnType: String, // methodReturnType: String,
methodParamTypes: Array<String>?, // methodParamTypes: Array<String>?,
dexPriority: IntArray?, // dexPriority: IntArray?,
): Array<String> // ): Array<String>
} //}

View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.4.1)
project(dexkit)
add_subdirectory(DexKit/Core Core)
add_library(${PROJECT_NAME} STATIC
native-bridge.cpp)
find_library(log-lib log)
target_link_libraries(${PROJECT_NAME}
dex_kit_static
z
${log-lib})

1
libs/dexkit/DexKit Submodule

Submodule libs/dexkit/DexKit added at 36fded3630

View File

@@ -0,0 +1,41 @@
/*
* QAuxiliary - An Xposed module for QQ/TIM
* Copyright (C) 2019-2022 qwq233@qwq2333.top
* https://github.com/cinit/QAuxiliary
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version and our eula as published
* by QAuxiliary contributors.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
* <https://github.com/cinit/QAuxiliary/blob/master/LICENSE.md>.
*/
@file:Suppress("UnstableApiUsage")
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
}
android {
compileSdk = 32
sourceSets {
val main by getting
main.apply {
manifest.srcFile("DexKit/Android/dexkit/src/main/AndroidManifest.xml")
java.setSrcDirs(listOf("DexKit/Android/dexkit/src/main/java"))
res.setSrcDirs(listOf("DexKit/Android/dexkit/src/main/res"))
}
}
}

View File

@@ -0,0 +1,289 @@
#include <jni.h>
#include <android/log.h>
#include <dex_kit.h>
#include "dex_kit_jni_helper.h"
#define TAG "DexKit"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, TAG ,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG ,__VA_ARGS__)
static jclass dex_kit_class = nullptr;
static jfieldID token_field = nullptr;
static JavaVM *g_currentJVM = nullptr;
static int registerNativeMethods(JNIEnv *env, jclass cls);
extern "C" JNIEXPORT JNICALL jint DexKit_JNI_OnLoad(JavaVM *vm, void *reserved) {
g_currentJVM = vm;
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
dex_kit_class = env->FindClass("io/luckypray/dexkit/DexKitBridge");
int ret = registerNativeMethods(env, dex_kit_class);
if (ret != 0) {
return -3;
}
return JNI_VERSION_1_6;
}
namespace DexKit {
#define DEXKIT_JNI extern "C" JNIEXPORT JNICALL
DEXKIT_JNI jlong
nativeInitDexKit(JNIEnv *env, jclass clazz,
jstring apk_path) {
if (!apk_path) {
return 0;
}
const char *cStr = env->GetStringUTFChars(apk_path, nullptr);
LOGI("apkPath -> %s", cStr);
std::string filePathStr(cStr);
auto dexkit = new dexkit::DexKit(filePathStr);
env->ReleaseStringUTFChars(apk_path, cStr);
return (jlong) dexkit;
}
DEXKIT_JNI void
nativeSetThreadNum(JNIEnv *env, jclass clazz,
jlong native_ptr, jint thread_num) {
if (!native_ptr) {
return;
}
SetThreadNum(env, native_ptr, thread_num);
}
DEXKIT_JNI jint
nativeGetDexNum(JNIEnv *env, jclass clazz,
jlong native_ptr) {
if (!native_ptr) {
return 0;
}
return GetDexNum(env, native_ptr);
}
DEXKIT_JNI void
nativeRelease(JNIEnv *env, jclass clazz,
jlong native_ptr) {
if (!native_ptr) {
return;
}
ReleaseDexKitInstance(env, native_ptr);
}
DEXKIT_JNI jobject
nativeBatchFindClassesUsingStrings(JNIEnv *env,
jclass clazz,
jlong native_ptr,
jobject map,
jboolean advanced_match,
jintArray dex_priority) {
if (!native_ptr) {
return CMap2JMap(env, std::map<std::string, std::vector<std::string>>());
}
return BatchFindClassesUsingStrings(env, native_ptr, map, advanced_match, dex_priority);
}
DEXKIT_JNI jobject
nativeBatchFindMethodsUsingStrings(JNIEnv *env,
jclass clazz,
jlong native_ptr,
jobject map,
jboolean advanced_match,
jintArray dex_priority) {
if (!native_ptr) {
return CMap2JMap(env, std::map<std::string, std::vector<std::string>>());
}
return BatchFindMethodsUsingStrings(env, native_ptr, map, advanced_match, dex_priority);
}
DEXKIT_JNI jobjectArray
nativeFindMethodCaller(JNIEnv *env, jclass clazz,
jlong native_ptr,
jstring method_descriptor,
jstring method_declare_class,
jstring method_declare_name,
jstring method_return_type,
jobjectArray method_param_types,
jstring caller_method_declare_class,
jstring caller_method_declare_name,
jstring caller_method_return_type,
jobjectArray caller_method_param_types,
jintArray dex_priority) {
if (!native_ptr) {
return StrVec2JStrArr(env, std::vector<std::string>());
}
return FindMethodCaller(env, native_ptr, method_descriptor, method_declare_class,
method_declare_name, method_return_type, method_param_types,
caller_method_declare_class, caller_method_declare_name,
caller_method_return_type, caller_method_param_types,
dex_priority);
}
DEXKIT_JNI jobject
nativeFindMethodInvoking(JNIEnv *env, jclass clazz,
jlong native_ptr,
jstring method_descriptor,
jstring method_declare_class,
jstring method_declare_name,
jstring method_return_type,
jobjectArray method_param_types,
jstring be_called_method_declare_class,
jstring be_called_method_declare_name,
jstring be_called_method_return_type,
jobjectArray be_called_method_param_types,
jintArray dex_priority) {
if (!native_ptr) {
return CMap2JMap(env, std::map<std::string, std::vector<std::string>>());
}
return FindMethodInvoking(env, native_ptr, method_descriptor, method_declare_class,
method_declare_name, method_return_type, method_param_types,
be_called_method_declare_class, be_called_method_declare_name,
be_called_method_return_type, be_called_method_param_types,
dex_priority);
}
DEXKIT_JNI jobject
nativeFindMethodUsingField(JNIEnv *env, jclass clazz,
jlong native_ptr,
jstring field_descriptor,
jstring field_declare_class,
jstring field_name,
jstring field_type,
jint used_flags,
jstring caller_method_declare_class,
jstring caller_method_name,
jstring caller_method_return_type,
jobjectArray caller_method_param_types,
jintArray dex_priority) {
if (!native_ptr) {
return StrVec2JStrArr(env, std::vector<std::string>());
}
return FindMethodUsingField(env, native_ptr, field_descriptor, field_declare_class,
field_name,
field_type, used_flags, caller_method_declare_class,
caller_method_name, caller_method_return_type,
caller_method_param_types, dex_priority);
}
DEXKIT_JNI jobjectArray
nativeFindMethodUsingString(JNIEnv *env, jclass clazz,
jlong native_ptr,
jstring used_string,
jboolean advanced_match,
jstring method_declare_class,
jstring method_name,
jstring method_return_type,
jobjectArray method_param_types,
jintArray dex_priority) {
if (!native_ptr) {
return StrVec2JStrArr(env, std::vector<std::string>());
}
return FindMethodUsingString(env, native_ptr, used_string, advanced_match,
method_declare_class,
method_name, method_return_type, method_param_types,
dex_priority);
}
DEXKIT_JNI jobjectArray
nativeFindMethod(JNIEnv *env, jclass clazz,
jlong native_ptr,
jstring method_declare_class,
jstring method_name,
jstring method_return_type,
jobjectArray method_param_types,
jintArray dex_priority) {
if (!native_ptr) {
return StrVec2JStrArr(env, std::vector<std::string>());
}
return FindMethod(env, native_ptr, method_declare_class, method_name, method_return_type,
method_param_types, dex_priority);
}
DEXKIT_JNI jobjectArray
nativeFindSubClasses(JNIEnv *env, jclass clazz,
jlong native_ptr,
jstring parent_class,
jintArray dex_priority) {
if (!native_ptr) {
return StrVec2JStrArr(env, std::vector<std::string>());
}
return FindSubClasses(env, native_ptr, parent_class, dex_priority);
}
DEXKIT_JNI jobjectArray
nativeFindMethodOpPrefixSeq(JNIEnv *env, jclass clazz,
jlong native_ptr,
jintArray op_prefix_seq,
jstring method_declare_class,
jstring method_name,
jstring method_return_type,
jobjectArray method_param_types,
jintArray dex_priority) {
if (!native_ptr) {
return StrVec2JStrArr(env, std::vector<std::string>());
}
return FindMethodOpPrefixSeq(env, native_ptr, op_prefix_seq, method_declare_class,
method_name,
method_return_type, method_param_types, dex_priority);
}
DEXKIT_JNI jobjectArray
nativeFindMethodUsingOpCodeSeq(JNIEnv *env, jclass clazz,
jlong native_ptr,
jintArray op_code_seq,
jstring method_declare_class,
jstring method_name,
jstring method_return_type,
jobjectArray method_param_types,
jintArray dex_priority) {
if (!native_ptr) {
return StrVec2JStrArr(env, std::vector<std::string>());
}
return FindMethodUsingOpCodeSeq(env, native_ptr, op_code_seq, method_declare_class, method_name,
method_return_type, method_param_types, dex_priority);
}
DEXKIT_JNI jobject
nativeGetMethodOpCodeSeq(JNIEnv *env, jclass clazz,
jlong native_ptr,
jstring method_descriptor,
jstring method_declare_class,
jstring method_name,
jstring method_return_type,
jobjectArray method_param_types,
jintArray dex_priority) {
if (!native_ptr) {
return EmptyJMap(env);
}
return GetMethodOpCodeSeq(env, native_ptr, method_descriptor, method_declare_class, method_name,
method_return_type, method_param_types, dex_priority);
}
} // namespace
static JNINativeMethod g_methods[]{
{"nativeInitDexKit", "(Ljava/lang/String;)J", (void *) DexKit::nativeInitDexKit},
{"nativeSetThreadNum", "(JI)V", (void *) DexKit::nativeSetThreadNum},
{"nativeGetDexNum", "(J)I", (void *) DexKit::nativeGetDexNum},
{"nativeRelease", "(J)V", (void *) DexKit::nativeRelease},
{"nativeBatchFindClassesUsingStrings", "(JLjava/util/Map;Z[I)Ljava/util/Map;", (void *) DexKit::nativeBatchFindClassesUsingStrings},
{"nativeBatchFindMethodsUsingStrings", "(JLjava/util/Map;Z[I)Ljava/util/Map;", (void *) DexKit::nativeBatchFindMethodsUsingStrings},
{"nativeFindMethodCaller", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[I)[Ljava/lang/String;", (void *) DexKit::nativeFindMethodCaller},
{"nativeFindMethodInvoking", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[I)Ljava/util/Map;", (void *) DexKit::nativeFindMethodInvoking},
{"nativeFindMethodUsingField", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[I)Ljava/util/Map;", (void *) DexKit::nativeFindMethodUsingField},
{"nativeFindMethodUsingString", "(JLjava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[I)[Ljava/lang/String;", (void *) DexKit::nativeFindMethodUsingString},
{"nativeFindMethod", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[I)[Ljava/lang/String;", (void *) DexKit::nativeFindMethod},
{"nativeFindSubClasses", "(JLjava/lang/String;[I)[Ljava/lang/String;", (void *) DexKit::nativeFindSubClasses},
{"nativeFindMethodOpPrefixSeq", "(J[ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[I)[Ljava/lang/String;", (void *) DexKit::nativeFindMethodOpPrefixSeq},
{"nativeFindMethodUsingOpCodeSeq", "(J[ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[I)[Ljava/lang/String;", (void *) DexKit::nativeFindMethodUsingOpCodeSeq},
{"nativeGetMethodOpCodeSeq", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[I)Ljava/util/Map;", (void *) DexKit::nativeGetMethodOpCodeSeq},
};
static int registerNativeMethods(JNIEnv *env, jclass cls) {
return env->RegisterNatives(cls, g_methods, sizeof(g_methods) / sizeof(g_methods[0]));
}

View File

@@ -27,5 +27,6 @@ include(
":app", ":app",
":libs:stub", ":libs:stub",
":libs:ksp", ":libs:ksp",
":libs:mmkv" ":libs:mmkv",
":libs:dexkit",
) )