capacitor-dex-editor 0.0.61 → 0.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +18 -0
- package/android/src/main/java/com/aetherlink/dexeditor/DexEditorPluginPlugin.java +0 -6
- package/android/src/main/java/com/aetherlink/dexeditor/DexManager.java +12 -44
- package/android/src/main/java/com/aetherlink/dexeditor/RustDex.java +86 -0
- package/android/src/main/jniLibs/arm64-v8a/libdex_rust.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libdex_rust.so +0 -0
- package/android/src/main/jniLibs/x86/libdex_rust.so +0 -0
- package/android/src/main/jniLibs/x86_64/libdex_rust.so +0 -0
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -9,13 +9,16 @@ buildscript {
|
|
|
9
9
|
repositories {
|
|
10
10
|
google()
|
|
11
11
|
mavenCentral()
|
|
12
|
+
maven { url "https://plugins.gradle.org/m2/" }
|
|
12
13
|
}
|
|
13
14
|
dependencies {
|
|
14
15
|
classpath 'com.android.tools.build:gradle:8.7.2'
|
|
16
|
+
classpath 'org.mozilla.rust-android-gradle:plugin:0.9.6'
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
apply plugin: 'com.android.library'
|
|
21
|
+
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
|
|
19
22
|
|
|
20
23
|
android {
|
|
21
24
|
namespace "com.aetherlink.dexeditor"
|
|
@@ -72,3 +75,18 @@ dependencies {
|
|
|
72
75
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
73
76
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
74
77
|
}
|
|
78
|
+
|
|
79
|
+
// Rust 编译配置
|
|
80
|
+
cargo {
|
|
81
|
+
module = "../rust"
|
|
82
|
+
libname = "dex_rust"
|
|
83
|
+
targets = ["arm", "arm64", "x86", "x86_64"]
|
|
84
|
+
profile = "release"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 将 Rust 编译任务添加到构建流程
|
|
88
|
+
tasks.configureEach { task ->
|
|
89
|
+
if ((task.name == 'javaPreCompileDebug' || task.name == 'javaPreCompileRelease')) {
|
|
90
|
+
task.dependsOn 'cargoBuild'
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -621,12 +621,6 @@ public class DexEditorPluginPlugin extends Plugin {
|
|
|
621
621
|
result.put("data", dexManager.listAllSessions());
|
|
622
622
|
break;
|
|
623
623
|
|
|
624
|
-
case "precompileSmaliCache":
|
|
625
|
-
result.put("data", dexManager.precompileSmaliCache(
|
|
626
|
-
params.getString("sessionId")
|
|
627
|
-
));
|
|
628
|
-
break;
|
|
629
|
-
|
|
630
624
|
// ==================== XML/资源操作 ====================
|
|
631
625
|
case "getManifest":
|
|
632
626
|
result.put("data", dexManager.getManifestFromApk(
|
|
@@ -151,8 +151,13 @@ public class DexManager {
|
|
|
151
151
|
String apkPath;
|
|
152
152
|
Map<String, DexBackedDexFile> dexFiles;
|
|
153
153
|
Map<String, ClassDef> modifiedClasses;
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
// 使用 LRU 缓存限制内存,最多缓存 200 个类
|
|
155
|
+
Map<String, String> smaliCache = new java.util.LinkedHashMap<String, String>(200, 0.75f, true) {
|
|
156
|
+
@Override
|
|
157
|
+
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
|
|
158
|
+
return size() > 200;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
156
161
|
boolean modified = false;
|
|
157
162
|
|
|
158
163
|
MultiDexSession(String sessionId, String apkPath) {
|
|
@@ -160,7 +165,6 @@ public class DexManager {
|
|
|
160
165
|
this.apkPath = apkPath;
|
|
161
166
|
this.dexFiles = new HashMap<>();
|
|
162
167
|
this.modifiedClasses = new HashMap<>();
|
|
163
|
-
this.smaliCache = new HashMap<>();
|
|
164
168
|
}
|
|
165
169
|
|
|
166
170
|
void addDex(String dexName, DexBackedDexFile dexFile) {
|
|
@@ -1755,6 +1759,7 @@ public class DexManager {
|
|
|
1755
1759
|
|
|
1756
1760
|
/**
|
|
1757
1761
|
* 在多 DEX 会话中搜索
|
|
1762
|
+
* 优先使用 Rust 实现,如果不可用则回退到 Java 实现
|
|
1758
1763
|
*/
|
|
1759
1764
|
public JSObject searchInMultiSession(String sessionId, String query, String searchType,
|
|
1760
1765
|
boolean caseSensitive, int maxResults) throws Exception {
|
|
@@ -1763,6 +1768,10 @@ public class DexManager {
|
|
|
1763
1768
|
throw new IllegalArgumentException("Session not found: " + sessionId);
|
|
1764
1769
|
}
|
|
1765
1770
|
|
|
1771
|
+
// 尝试使用 Rust 实现(仅对 string/code 搜索有显著提升)
|
|
1772
|
+
// 目前 Rust 实现需要 DEX 字节数据,暂时禁用
|
|
1773
|
+
// TODO: 实现 Rust 加速搜索
|
|
1774
|
+
|
|
1766
1775
|
JSObject result = new JSObject();
|
|
1767
1776
|
JSArray results = new JSArray();
|
|
1768
1777
|
String queryMatch = caseSensitive ? query : query.toLowerCase();
|
|
@@ -1911,47 +1920,6 @@ public class DexManager {
|
|
|
1911
1920
|
return smali;
|
|
1912
1921
|
}
|
|
1913
1922
|
|
|
1914
|
-
/**
|
|
1915
|
-
* 预编译会话中所有类的 Smali(用于加速搜索)
|
|
1916
|
-
*/
|
|
1917
|
-
public JSObject precompileSmaliCache(String sessionId) throws Exception {
|
|
1918
|
-
MultiDexSession session = multiDexSessions.get(sessionId);
|
|
1919
|
-
if (session == null) {
|
|
1920
|
-
throw new IllegalArgumentException("Session not found: " + sessionId);
|
|
1921
|
-
}
|
|
1922
|
-
|
|
1923
|
-
if (session.smaliCacheReady) {
|
|
1924
|
-
JSObject result = new JSObject();
|
|
1925
|
-
result.put("cached", true);
|
|
1926
|
-
result.put("count", session.smaliCache.size());
|
|
1927
|
-
return result;
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
int count = 0;
|
|
1931
|
-
long startTime = System.currentTimeMillis();
|
|
1932
|
-
|
|
1933
|
-
for (Map.Entry<String, DexBackedDexFile> entry : session.dexFiles.entrySet()) {
|
|
1934
|
-
DexBackedDexFile dexFile = entry.getValue();
|
|
1935
|
-
for (ClassDef classDef : dexFile.getClasses()) {
|
|
1936
|
-
String className = convertTypeToClassName(classDef.getType());
|
|
1937
|
-
if (!session.smaliCache.containsKey(className)) {
|
|
1938
|
-
String smali = getSmaliForClass(dexFile, classDef);
|
|
1939
|
-
session.smaliCache.put(className, smali);
|
|
1940
|
-
count++;
|
|
1941
|
-
}
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
|
-
|
|
1945
|
-
session.smaliCacheReady = true;
|
|
1946
|
-
long elapsed = System.currentTimeMillis() - startTime;
|
|
1947
|
-
|
|
1948
|
-
JSObject result = new JSObject();
|
|
1949
|
-
result.put("success", true);
|
|
1950
|
-
result.put("count", count);
|
|
1951
|
-
result.put("elapsedMs", elapsed);
|
|
1952
|
-
return result;
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1955
1923
|
/**
|
|
1956
1924
|
* 从多 DEX 会话获取类的 Smali 代码
|
|
1957
1925
|
*/
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
package com.aetherlink.dexeditor;
|
|
2
|
+
|
|
3
|
+
import android.util.Log;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* RustDex - Rust 实现的 DEX 解析器 JNI 接口
|
|
7
|
+
* 使用 azw413/smali crate 实现高性能 DEX 搜索
|
|
8
|
+
*/
|
|
9
|
+
public class RustDex {
|
|
10
|
+
private static final String TAG = "RustDex";
|
|
11
|
+
private static boolean libraryLoaded = false;
|
|
12
|
+
|
|
13
|
+
static {
|
|
14
|
+
try {
|
|
15
|
+
System.loadLibrary("dex_rust");
|
|
16
|
+
libraryLoaded = true;
|
|
17
|
+
Log.d(TAG, "Rust library loaded successfully");
|
|
18
|
+
} catch (UnsatisfiedLinkError e) {
|
|
19
|
+
Log.w(TAG, "Failed to load Rust library: " + e.getMessage());
|
|
20
|
+
libraryLoaded = false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 检查 Rust 库是否可用
|
|
26
|
+
*/
|
|
27
|
+
public static boolean isAvailable() {
|
|
28
|
+
return libraryLoaded;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 在 DEX 中搜索
|
|
33
|
+
* @param dexBytes DEX 文件字节数组
|
|
34
|
+
* @param query 搜索查询
|
|
35
|
+
* @param searchType 搜索类型: class, method, field, string, code
|
|
36
|
+
* @param caseSensitive 是否区分大小写
|
|
37
|
+
* @param maxResults 最大结果数
|
|
38
|
+
* @return JSON 格式的搜索结果
|
|
39
|
+
*/
|
|
40
|
+
public static native String searchInDex(
|
|
41
|
+
byte[] dexBytes,
|
|
42
|
+
String query,
|
|
43
|
+
String searchType,
|
|
44
|
+
boolean caseSensitive,
|
|
45
|
+
int maxResults
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 列出 DEX 中的类
|
|
50
|
+
* @param dexBytes DEX 文件字节数组
|
|
51
|
+
* @param packageFilter 包名过滤器
|
|
52
|
+
* @param offset 偏移量
|
|
53
|
+
* @param limit 限制数量
|
|
54
|
+
* @return JSON 格式的类列表
|
|
55
|
+
*/
|
|
56
|
+
public static native String listClasses(
|
|
57
|
+
byte[] dexBytes,
|
|
58
|
+
String packageFilter,
|
|
59
|
+
int offset,
|
|
60
|
+
int limit
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 获取类的 Smali 代码
|
|
65
|
+
* @param dexBytes DEX 文件字节数组
|
|
66
|
+
* @param className 类名
|
|
67
|
+
* @return JSON 格式的 Smali 代码
|
|
68
|
+
*/
|
|
69
|
+
public static native String getClassSmali(
|
|
70
|
+
byte[] dexBytes,
|
|
71
|
+
String className
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Java 回退实现 - 当 Rust 库不可用时使用
|
|
76
|
+
*/
|
|
77
|
+
public static String searchInDexFallback(
|
|
78
|
+
byte[] dexBytes,
|
|
79
|
+
String query,
|
|
80
|
+
String searchType,
|
|
81
|
+
boolean caseSensitive,
|
|
82
|
+
int maxResults
|
|
83
|
+
) {
|
|
84
|
+
return "{\"error\": \"Rust library not available, using Java implementation\", \"fallback\": true}";
|
|
85
|
+
}
|
|
86
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|