refactor: modify dexkit backend
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -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
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -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#
|
||||||
|
|||||||
@@ -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})
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
}
|
//}
|
||||||
|
|||||||
14
libs/dexkit/CMakeLists.txt
Normal file
14
libs/dexkit/CMakeLists.txt
Normal 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
1
libs/dexkit/DexKit
Submodule
Submodule libs/dexkit/DexKit added at 36fded3630
41
libs/dexkit/build.gradle.kts
Normal file
41
libs/dexkit/build.gradle.kts
Normal 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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
289
libs/dexkit/native-bridge.cpp
Normal file
289
libs/dexkit/native-bridge.cpp
Normal 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]));
|
||||||
|
}
|
||||||
@@ -27,5 +27,6 @@ include(
|
|||||||
":app",
|
":app",
|
||||||
":libs:stub",
|
":libs:stub",
|
||||||
":libs:ksp",
|
":libs:ksp",
|
||||||
":libs:mmkv"
|
":libs:mmkv",
|
||||||
|
":libs:dexkit",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user