capacitor-dex-editor 0.0.76 → 0.0.78
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
CHANGED
|
@@ -77,9 +77,9 @@ dependencies {
|
|
|
77
77
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
78
78
|
|
|
79
79
|
// dexlib2 & smali - DEX文件编辑核心库 (使用 api 暴露给主项目)
|
|
80
|
+
// baksmali 已移除 - 使用 C++ 实现
|
|
80
81
|
api 'com.android.tools.smali:smali-dexlib2:3.0.3'
|
|
81
82
|
api 'com.android.tools.smali:smali:3.0.3'
|
|
82
|
-
api 'com.android.tools.smali:smali-baksmali:3.0.3'
|
|
83
83
|
|
|
84
84
|
// Guava - dexlib2 依赖
|
|
85
85
|
api 'com.google.guava:guava:32.1.3-android'
|
|
@@ -27,10 +27,6 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableField;
|
|
|
27
27
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod;
|
|
28
28
|
import com.android.tools.smali.dexlib2.writer.io.FileDataStore;
|
|
29
29
|
import com.android.tools.smali.dexlib2.writer.pool.DexPool;
|
|
30
|
-
import com.android.tools.smali.baksmali.Baksmali;
|
|
31
|
-
import com.android.tools.smali.baksmali.BaksmaliOptions;
|
|
32
|
-
import com.android.tools.smali.baksmali.Adaptors.ClassDefinition;
|
|
33
|
-
import com.android.tools.smali.baksmali.formatter.BaksmaliWriter;
|
|
34
30
|
import com.android.tools.smali.smali.Smali;
|
|
35
31
|
import com.android.tools.smali.smali.SmaliOptions;
|
|
36
32
|
|
|
@@ -111,6 +107,7 @@ public class DexManager {
|
|
|
111
107
|
long lastModified;
|
|
112
108
|
Map<String, ClassDef> classDefMap; // type -> ClassDef
|
|
113
109
|
int dexVersion;
|
|
110
|
+
byte[] dexBytes; // DEX 原始字节用于 C++ 操作
|
|
114
111
|
|
|
115
112
|
ApkDexCache(String apkPath, String dexPath) {
|
|
116
113
|
this.apkPath = apkPath;
|
|
@@ -882,49 +879,12 @@ public class DexManager {
|
|
|
882
879
|
}
|
|
883
880
|
}
|
|
884
881
|
} catch (Exception e) {
|
|
885
|
-
Log.w(TAG, "C++ classToSmali failed
|
|
882
|
+
Log.w(TAG, "C++ classToSmali failed", e);
|
|
883
|
+
throw new Exception("C++ classToSmali failed: " + e.getMessage());
|
|
886
884
|
}
|
|
887
885
|
}
|
|
888
886
|
|
|
889
|
-
|
|
890
|
-
ClassDef classDef = findClass(session, className);
|
|
891
|
-
if (classDef == null) {
|
|
892
|
-
throw new IllegalArgumentException("Class not found: " + className);
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
StringWriter writer = new StringWriter();
|
|
896
|
-
BaksmaliOptions options = new BaksmaliOptions();
|
|
897
|
-
|
|
898
|
-
List<ClassDef> singleClass = new ArrayList<>();
|
|
899
|
-
singleClass.add(classDef);
|
|
900
|
-
ImmutableDexFile singleDex = new ImmutableDexFile(
|
|
901
|
-
session.originalDexFile.getOpcodes(),
|
|
902
|
-
singleClass
|
|
903
|
-
);
|
|
904
|
-
|
|
905
|
-
File tempDir = File.createTempFile("smali_", "_temp");
|
|
906
|
-
tempDir.delete();
|
|
907
|
-
tempDir.mkdirs();
|
|
908
|
-
|
|
909
|
-
try {
|
|
910
|
-
Baksmali.disassembleDexFile(singleDex, tempDir, 1, options);
|
|
911
|
-
|
|
912
|
-
String smaliPath = className.substring(1, className.length() - 1) + ".smali";
|
|
913
|
-
File smaliFile = new File(tempDir, smaliPath);
|
|
914
|
-
|
|
915
|
-
if (smaliFile.exists()) {
|
|
916
|
-
String smali = readFileContent(smaliFile);
|
|
917
|
-
JSObject result = new JSObject();
|
|
918
|
-
result.put("className", className);
|
|
919
|
-
result.put("smali", smali);
|
|
920
|
-
result.put("engine", "java");
|
|
921
|
-
return result;
|
|
922
|
-
} else {
|
|
923
|
-
throw new IOException("Failed to generate smali for: " + className);
|
|
924
|
-
}
|
|
925
|
-
} finally {
|
|
926
|
-
deleteRecursive(tempDir);
|
|
927
|
-
}
|
|
887
|
+
throw new UnsupportedOperationException("C++ library not available for classToSmali");
|
|
928
888
|
}
|
|
929
889
|
|
|
930
890
|
/**
|
|
@@ -938,17 +898,52 @@ public class DexManager {
|
|
|
938
898
|
}
|
|
939
899
|
|
|
940
900
|
/**
|
|
941
|
-
* 反汇编整个 DEX
|
|
901
|
+
* 反汇编整个 DEX 到目录(优先使用 C++ 实现)
|
|
942
902
|
*/
|
|
943
903
|
public void disassemble(String sessionId, String outputDir) throws Exception {
|
|
944
904
|
DexSession session = getSession(sessionId);
|
|
945
905
|
File outDir = new File(outputDir);
|
|
946
906
|
outDir.mkdirs();
|
|
947
907
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
908
|
+
// 优先使用 C++ 实现 - 逐个类反汇编
|
|
909
|
+
if (CppDex.isAvailable() && session.dexBytes != null) {
|
|
910
|
+
try {
|
|
911
|
+
// 获取所有类
|
|
912
|
+
String classesJson = CppDex.listClasses(session.dexBytes, "", 0, 10000);
|
|
913
|
+
if (classesJson != null && !classesJson.contains("\"error\"")) {
|
|
914
|
+
org.json.JSONObject result = new org.json.JSONObject(classesJson);
|
|
915
|
+
org.json.JSONArray classes = result.optJSONArray("classes");
|
|
916
|
+
if (classes != null) {
|
|
917
|
+
for (int i = 0; i < classes.length(); i++) {
|
|
918
|
+
String className = classes.getString(i);
|
|
919
|
+
try {
|
|
920
|
+
String smaliJson = CppDex.getClassSmali(session.dexBytes, className);
|
|
921
|
+
if (smaliJson != null && !smaliJson.contains("\"error\"")) {
|
|
922
|
+
org.json.JSONObject smaliResult = new org.json.JSONObject(smaliJson);
|
|
923
|
+
String smali = smaliResult.optString("smali", "");
|
|
924
|
+
if (!smali.isEmpty()) {
|
|
925
|
+
// 保存到文件
|
|
926
|
+
String filePath = className.substring(1, className.length() - 1) + ".smali";
|
|
927
|
+
File smaliFile = new File(outDir, filePath);
|
|
928
|
+
smaliFile.getParentFile().mkdirs();
|
|
929
|
+
writeFileContent(smaliFile, smali);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
} catch (Exception e) {
|
|
933
|
+
Log.w(TAG, "Failed to disassemble class: " + className, e);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
Log.d(TAG, "Disassembled to (C++): " + outputDir);
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
} catch (Exception e) {
|
|
941
|
+
Log.w(TAG, "C++ disassemble failed", e);
|
|
942
|
+
throw new Exception("C++ disassemble failed: " + e.getMessage());
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
throw new UnsupportedOperationException("C++ library not available for disassemble");
|
|
952
947
|
}
|
|
953
948
|
|
|
954
949
|
/**
|
|
@@ -1652,6 +1647,12 @@ public class DexManager {
|
|
|
1652
1647
|
return content.toString();
|
|
1653
1648
|
}
|
|
1654
1649
|
|
|
1650
|
+
private void writeFileContent(File file, String content) throws IOException {
|
|
1651
|
+
try (java.io.BufferedWriter writer = new java.io.BufferedWriter(new java.io.FileWriter(file))) {
|
|
1652
|
+
writer.write(content);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1655
1656
|
private byte[] readFileBytes(File file) throws IOException {
|
|
1656
1657
|
byte[] bytes = new byte[(int) file.length()];
|
|
1657
1658
|
try (FileInputStream fis = new FileInputStream(file)) {
|
|
@@ -2228,20 +2229,11 @@ public class DexManager {
|
|
|
2228
2229
|
}
|
|
2229
2230
|
|
|
2230
2231
|
/**
|
|
2231
|
-
* 获取类的 Smali
|
|
2232
|
+
* 获取类的 Smali 代码(内部方法)- 使用 C++ 实现
|
|
2232
2233
|
*/
|
|
2233
2234
|
private String getSmaliForClass(DexBackedDexFile dexFile, ClassDef classDef) {
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
ClassDefinition classDefinition = new ClassDefinition(options, classDef);
|
|
2237
|
-
java.io.StringWriter stringWriter = new java.io.StringWriter();
|
|
2238
|
-
BaksmaliWriter writer = new BaksmaliWriter(stringWriter, null);
|
|
2239
|
-
classDefinition.writeTo(writer);
|
|
2240
|
-
writer.close();
|
|
2241
|
-
return stringWriter.toString();
|
|
2242
|
-
} catch (Exception e) {
|
|
2243
|
-
return "";
|
|
2244
|
-
}
|
|
2235
|
+
// 此方法已弃用,使用 C++ 实现
|
|
2236
|
+
return "";
|
|
2245
2237
|
}
|
|
2246
2238
|
|
|
2247
2239
|
|
|
@@ -3071,6 +3063,9 @@ public class DexManager {
|
|
|
3071
3063
|
dexInputStream.close();
|
|
3072
3064
|
byte[] dexBytes = baos.toByteArray();
|
|
3073
3065
|
|
|
3066
|
+
// 保存 DEX 字节用于 C++ 操作
|
|
3067
|
+
cache.dexBytes = dexBytes;
|
|
3068
|
+
|
|
3074
3069
|
// 解析 DEX 文件并缓存所有 ClassDef
|
|
3075
3070
|
DexBackedDexFile dexFile = new DexBackedDexFile(Opcodes.getDefault(), dexBytes);
|
|
3076
3071
|
cache.dexVersion = 35; // 默认 DEX 版本
|
|
@@ -3102,7 +3097,7 @@ public class DexManager {
|
|
|
3102
3097
|
}
|
|
3103
3098
|
|
|
3104
3099
|
/**
|
|
3105
|
-
* 从 APK 中的 DEX 文件获取类的 Smali
|
|
3100
|
+
* 从 APK 中的 DEX 文件获取类的 Smali 代码(使用 C++ 实现)
|
|
3106
3101
|
*/
|
|
3107
3102
|
public JSObject getClassSmaliFromApk(String apkPath, String dexPath, String className) throws Exception {
|
|
3108
3103
|
JSObject result = new JSObject();
|
|
@@ -3117,26 +3112,22 @@ public class DexManager {
|
|
|
3117
3112
|
String targetType = convertClassNameToType(className);
|
|
3118
3113
|
|
|
3119
3114
|
try {
|
|
3120
|
-
//
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3115
|
+
// 使用 C++ 实现获取 Smali
|
|
3116
|
+
if (CppDex.isAvailable()) {
|
|
3117
|
+
ApkDexCache cache = getOrCreateDexCache(apkPath, dexPath);
|
|
3118
|
+
if (cache.dexBytes != null) {
|
|
3119
|
+
String smaliJson = CppDex.getClassSmali(cache.dexBytes, targetType);
|
|
3120
|
+
if (smaliJson != null && !smaliJson.contains("\"error\"")) {
|
|
3121
|
+
org.json.JSONObject smaliResult = new org.json.JSONObject(smaliJson);
|
|
3122
|
+
String smali = smaliResult.optString("smali", "");
|
|
3123
|
+
if (!smali.isEmpty()) {
|
|
3124
|
+
result.put("smali", smali);
|
|
3125
|
+
return result;
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3127
3129
|
}
|
|
3128
|
-
|
|
3129
|
-
// 使用 baksmali 库生成正确的 Smali 代码
|
|
3130
|
-
BaksmaliOptions options = new BaksmaliOptions();
|
|
3131
|
-
ClassDefinition classDefinition = new ClassDefinition(options, targetClass);
|
|
3132
|
-
|
|
3133
|
-
java.io.StringWriter stringWriter = new java.io.StringWriter();
|
|
3134
|
-
BaksmaliWriter writer = new BaksmaliWriter(stringWriter, null);
|
|
3135
|
-
classDefinition.writeTo(writer);
|
|
3136
|
-
writer.close();
|
|
3137
|
-
|
|
3138
|
-
result.put("smali", stringWriter.toString());
|
|
3139
|
-
|
|
3130
|
+
result.put("smali", "# 类未找到或 C++ 库不可用: " + className);
|
|
3140
3131
|
} catch (Exception e) {
|
|
3141
3132
|
result.put("smali", "# 加载失败: " + e.getMessage());
|
|
3142
3133
|
}
|