capacitor-dex-editor 0.0.72 → 0.0.74
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.
|
@@ -213,15 +213,29 @@ public class DexManager {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
/**
|
|
216
|
-
* 保存 DEX
|
|
216
|
+
* 保存 DEX 文件(优先使用 C++ 修改的字节数据)
|
|
217
217
|
*/
|
|
218
218
|
public void saveDex(String sessionId, String outputPath) throws Exception {
|
|
219
219
|
DexSession session = getSession(sessionId);
|
|
220
|
+
|
|
221
|
+
File outputFile = new File(outputPath);
|
|
222
|
+
if (outputFile.getParentFile() != null) {
|
|
223
|
+
outputFile.getParentFile().mkdirs();
|
|
224
|
+
}
|
|
220
225
|
|
|
221
|
-
//
|
|
226
|
+
// 如果使用 C++ 修改了 dexBytes,直接保存
|
|
227
|
+
if (session.dexBytes != null && session.modified &&
|
|
228
|
+
session.modifiedClasses.isEmpty() && session.removedClasses.isEmpty()) {
|
|
229
|
+
try (java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFile)) {
|
|
230
|
+
fos.write(session.dexBytes);
|
|
231
|
+
}
|
|
232
|
+
Log.d(TAG, "Saved DEX (C++ modified) to: " + outputPath);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Java 回退实现
|
|
222
237
|
DexPool dexPool = new DexPool(session.originalDexFile.getOpcodes());
|
|
223
238
|
|
|
224
|
-
// 添加所有类(排除已删除的,使用修改后的版本)
|
|
225
239
|
Set<String> modifiedClassTypes = new HashSet<>();
|
|
226
240
|
for (ClassDef modifiedClass : session.modifiedClasses) {
|
|
227
241
|
modifiedClassTypes.add(modifiedClass.getType());
|
|
@@ -235,13 +249,6 @@ public class DexManager {
|
|
|
235
249
|
}
|
|
236
250
|
}
|
|
237
251
|
|
|
238
|
-
// 写入文件 (使用官方推荐方式)
|
|
239
|
-
File outputFile = new File(outputPath);
|
|
240
|
-
if (outputFile.getParentFile() != null) {
|
|
241
|
-
outputFile.getParentFile().mkdirs();
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// 创建临时 DexFile 用于写入
|
|
245
252
|
List<ClassDef> allClasses = new ArrayList<>();
|
|
246
253
|
for (ClassDef c : session.modifiedClasses) {
|
|
247
254
|
allClasses.add(c);
|
|
@@ -404,12 +411,27 @@ public class DexManager {
|
|
|
404
411
|
}
|
|
405
412
|
|
|
406
413
|
/**
|
|
407
|
-
*
|
|
414
|
+
* 添加类(优先使用 C++ 实现)
|
|
408
415
|
*/
|
|
409
416
|
public void addClass(String sessionId, String smaliCode) throws Exception {
|
|
410
417
|
DexSession session = getSession(sessionId);
|
|
411
418
|
|
|
412
|
-
//
|
|
419
|
+
// 优先使用 C++ 实现
|
|
420
|
+
if (CppDex.isAvailable() && session.dexBytes != null) {
|
|
421
|
+
try {
|
|
422
|
+
byte[] newDexBytes = CppDex.addClass(session.dexBytes, smaliCode);
|
|
423
|
+
if (newDexBytes != null) {
|
|
424
|
+
session.dexBytes = newDexBytes;
|
|
425
|
+
session.modified = true;
|
|
426
|
+
Log.d(TAG, "Added class via C++");
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
} catch (Exception e) {
|
|
430
|
+
Log.w(TAG, "C++ addClass failed, fallback to Java", e);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Java 回退实现
|
|
413
435
|
ClassDef newClass = compileSmaliToClass(smaliCode, session.originalDexFile.getOpcodes());
|
|
414
436
|
session.modifiedClasses.add(newClass);
|
|
415
437
|
session.modified = true;
|
|
@@ -418,10 +440,27 @@ public class DexManager {
|
|
|
418
440
|
}
|
|
419
441
|
|
|
420
442
|
/**
|
|
421
|
-
*
|
|
443
|
+
* 删除类(优先使用 C++ 实现)
|
|
422
444
|
*/
|
|
423
445
|
public void removeClass(String sessionId, String className) throws Exception {
|
|
424
446
|
DexSession session = getSession(sessionId);
|
|
447
|
+
|
|
448
|
+
// 优先使用 C++ 实现
|
|
449
|
+
if (CppDex.isAvailable() && session.dexBytes != null) {
|
|
450
|
+
try {
|
|
451
|
+
byte[] newDexBytes = CppDex.deleteClass(session.dexBytes, className);
|
|
452
|
+
if (newDexBytes != null) {
|
|
453
|
+
session.dexBytes = newDexBytes;
|
|
454
|
+
session.modified = true;
|
|
455
|
+
Log.d(TAG, "Removed class via C++: " + className);
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
} catch (Exception e) {
|
|
459
|
+
Log.w(TAG, "C++ removeClass failed, fallback to Java", e);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Java 回退实现
|
|
425
464
|
session.removedClasses.add(className);
|
|
426
465
|
session.modified = true;
|
|
427
466
|
|
|
@@ -602,28 +641,39 @@ public class DexManager {
|
|
|
602
641
|
}
|
|
603
642
|
|
|
604
643
|
/**
|
|
605
|
-
* 设置方法的 Smali
|
|
644
|
+
* 设置方法的 Smali 代码(优先使用 C++ 实现)
|
|
606
645
|
*/
|
|
607
646
|
public void setMethodSmali(String sessionId, String className,
|
|
608
647
|
String methodName, String methodSignature,
|
|
609
648
|
String smaliCode) throws Exception {
|
|
610
649
|
DexSession session = getSession(sessionId);
|
|
650
|
+
|
|
651
|
+
// 获取原类的 Smali 并替换方法
|
|
652
|
+
String classSmali = classToSmali(sessionId, className).getString("smali");
|
|
653
|
+
String modifiedSmali = replaceMethodInSmali(classSmali, methodName, methodSignature, smaliCode);
|
|
654
|
+
|
|
655
|
+
// 优先使用 C++ 实现
|
|
656
|
+
if (CppDex.isAvailable() && session.dexBytes != null) {
|
|
657
|
+
try {
|
|
658
|
+
byte[] newDexBytes = CppDex.modifyClass(session.dexBytes, className, modifiedSmali);
|
|
659
|
+
if (newDexBytes != null) {
|
|
660
|
+
session.dexBytes = newDexBytes;
|
|
661
|
+
session.modified = true;
|
|
662
|
+
Log.d(TAG, "Modified method via C++: " + className + "->" + methodName);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
} catch (Exception e) {
|
|
666
|
+
Log.w(TAG, "C++ modifyClass failed, fallback to Java", e);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// Java 回退实现
|
|
611
671
|
ClassDef classDef = findClass(session, className);
|
|
612
|
-
|
|
613
672
|
if (classDef == null) {
|
|
614
673
|
throw new IllegalArgumentException("Class not found: " + className);
|
|
615
674
|
}
|
|
616
|
-
|
|
617
|
-
// 获取原类的 Smali
|
|
618
|
-
String classSmali = classToSmali(sessionId, className).getString("smali");
|
|
619
675
|
|
|
620
|
-
// 替换方法
|
|
621
|
-
String modifiedSmali = replaceMethodInSmali(classSmali, methodName, methodSignature, smaliCode);
|
|
622
|
-
|
|
623
|
-
// 重新编译
|
|
624
676
|
ClassDef modifiedClass = compileSmaliToClass(modifiedSmali, session.originalDexFile.getOpcodes());
|
|
625
|
-
|
|
626
|
-
// 更新会话
|
|
627
677
|
session.removedClasses.add(className);
|
|
628
678
|
session.modifiedClasses.add(modifiedClass);
|
|
629
679
|
session.modified = true;
|
|
@@ -894,7 +944,7 @@ public class DexManager {
|
|
|
894
944
|
}
|
|
895
945
|
|
|
896
946
|
/**
|
|
897
|
-
* 汇编 Smali 目录为 DEX
|
|
947
|
+
* 汇编 Smali 目录为 DEX(优先使用 C++ 实现)
|
|
898
948
|
*/
|
|
899
949
|
public JSObject assemble(String smaliDir, String outputPath) throws Exception {
|
|
900
950
|
File inputDir = new File(smaliDir);
|
|
@@ -905,7 +955,35 @@ public class DexManager {
|
|
|
905
955
|
}
|
|
906
956
|
|
|
907
957
|
outputFile.getParentFile().mkdirs();
|
|
958
|
+
|
|
959
|
+
// 优先使用 C++ 实现
|
|
960
|
+
if (CppDex.isAvailable()) {
|
|
961
|
+
try {
|
|
962
|
+
// 读取所有 smali 文件并合并
|
|
963
|
+
List<File> smaliFiles = collectSmaliFiles(inputDir);
|
|
964
|
+
StringBuilder allSmali = new StringBuilder();
|
|
965
|
+
for (File f : smaliFiles) {
|
|
966
|
+
allSmali.append(readFileContent(f));
|
|
967
|
+
allSmali.append("\n\n");
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
byte[] dexBytes = CppDex.smaliToDex(allSmali.toString());
|
|
971
|
+
if (dexBytes != null && dexBytes.length > 0) {
|
|
972
|
+
try (java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFile)) {
|
|
973
|
+
fos.write(dexBytes);
|
|
974
|
+
}
|
|
975
|
+
JSObject result = new JSObject();
|
|
976
|
+
result.put("success", true);
|
|
977
|
+
result.put("outputPath", outputPath);
|
|
978
|
+
result.put("engine", "cpp");
|
|
979
|
+
return result;
|
|
980
|
+
}
|
|
981
|
+
} catch (Exception e) {
|
|
982
|
+
Log.w(TAG, "C++ smaliToDex failed, fallback to Java", e);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
908
985
|
|
|
986
|
+
// Java 回退实现
|
|
909
987
|
SmaliOptions options = new SmaliOptions();
|
|
910
988
|
options.outputDexFile = outputPath;
|
|
911
989
|
|
|
@@ -920,6 +998,7 @@ public class DexManager {
|
|
|
920
998
|
JSObject result = new JSObject();
|
|
921
999
|
result.put("success", success);
|
|
922
1000
|
result.put("outputPath", outputPath);
|
|
1001
|
+
result.put("engine", "java");
|
|
923
1002
|
return result;
|
|
924
1003
|
}
|
|
925
1004
|
|