capacitor-dex-editor 0.0.71 → 0.0.72

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.
@@ -307,6 +307,31 @@ public class DexEditorPluginPlugin extends Plugin {
307
307
  ));
308
308
  break;
309
309
 
310
+ // ============ 交叉引用分析(C++ 实现)============
311
+ case "findMethodXrefs":
312
+ result.put("data", dexManager.findMethodXrefs(
313
+ params.getString("sessionId"),
314
+ params.getString("className"),
315
+ params.getString("methodName")
316
+ ));
317
+ break;
318
+
319
+ case "findFieldXrefs":
320
+ result.put("data", dexManager.findFieldXrefs(
321
+ params.getString("sessionId"),
322
+ params.getString("className"),
323
+ params.getString("fieldName")
324
+ ));
325
+ break;
326
+
327
+ // ============ Smali 转 Java(C++ 实现)============
328
+ case "smaliToJava":
329
+ result.put("data", dexManager.smaliToJava(
330
+ params.getString("sessionId"),
331
+ params.getString("className")
332
+ ));
333
+ break;
334
+
310
335
  // ============ 工具操作 ============
311
336
  case "fixDex":
312
337
  dexManager.fixDex(
@@ -562,21 +562,42 @@ public class DexManager {
562
562
  }
563
563
 
564
564
  /**
565
- * 获取方法的 Smali 代码
565
+ * 获取方法的 Smali 代码(优先使用 C++ 实现)
566
566
  */
567
567
  public JSObject getMethodSmali(String sessionId, String className,
568
568
  String methodName, String methodSignature) throws Exception {
569
569
  DexSession session = getSession(sessionId);
570
570
 
571
- // 获取类的完整 Smali,然后提取方法部分
572
- String classSmali = classToSmali(sessionId, className).getString("smali");
571
+ // 优先使用 C++ 实现
572
+ if (CppDex.isAvailable() && session.dexBytes != null) {
573
+ try {
574
+ String jsonResult = CppDex.getMethodSmali(session.dexBytes, className, methodName, methodSignature);
575
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
576
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
577
+ String smali = cppResult.optString("smali", "");
578
+ if (!smali.isEmpty()) {
579
+ JSObject result = new JSObject();
580
+ result.put("className", className);
581
+ result.put("methodName", methodName);
582
+ result.put("methodSignature", methodSignature);
583
+ result.put("smali", smali);
584
+ result.put("engine", "cpp");
585
+ return result;
586
+ }
587
+ }
588
+ } catch (Exception e) {
589
+ Log.w(TAG, "C++ getMethodSmali failed, fallback to Java", e);
590
+ }
591
+ }
573
592
 
574
- // 简化处理:返回整个类的 Smali(实际应该解析提取特定方法)
593
+ // Java 回退实现
594
+ String classSmali = classToSmali(sessionId, className).getString("smali");
575
595
  JSObject result = new JSObject();
576
596
  result.put("className", className);
577
597
  result.put("methodName", methodName);
578
598
  result.put("methodSignature", methodSignature);
579
599
  result.put("smali", extractMethodSmali(classSmali, methodName, methodSignature));
600
+ result.put("engine", "java");
580
601
  return result;
581
602
  }
582
603
 
@@ -782,21 +803,40 @@ public class DexManager {
782
803
  // ==================== Smali 操作 ====================
783
804
 
784
805
  /**
785
- * 将类转换为 Smali 代码
806
+ * 将类转换为 Smali 代码(优先使用 C++ 实现)
786
807
  */
787
808
  public JSObject classToSmali(String sessionId, String className) throws Exception {
788
809
  DexSession session = getSession(sessionId);
810
+
811
+ // 优先使用 C++ 实现
812
+ if (CppDex.isAvailable() && session.dexBytes != null) {
813
+ try {
814
+ String jsonResult = CppDex.getClassSmali(session.dexBytes, className);
815
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
816
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
817
+ String smali = cppResult.optString("smali", "");
818
+ if (!smali.isEmpty()) {
819
+ JSObject result = new JSObject();
820
+ result.put("className", className);
821
+ result.put("smali", smali);
822
+ result.put("engine", "cpp");
823
+ return result;
824
+ }
825
+ }
826
+ } catch (Exception e) {
827
+ Log.w(TAG, "C++ classToSmali failed, fallback to Java", e);
828
+ }
829
+ }
830
+
831
+ // Java 回退实现
789
832
  ClassDef classDef = findClass(session, className);
790
-
791
833
  if (classDef == null) {
792
834
  throw new IllegalArgumentException("Class not found: " + className);
793
835
  }
794
836
 
795
- // 使用 baksmali 转换
796
837
  StringWriter writer = new StringWriter();
797
838
  BaksmaliOptions options = new BaksmaliOptions();
798
839
 
799
- // 创建临时 DEX 只包含该类
800
840
  List<ClassDef> singleClass = new ArrayList<>();
801
841
  singleClass.add(classDef);
802
842
  ImmutableDexFile singleDex = new ImmutableDexFile(
@@ -804,7 +844,6 @@ public class DexManager {
804
844
  singleClass
805
845
  );
806
846
 
807
- // 使用临时目录输出
808
847
  File tempDir = File.createTempFile("smali_", "_temp");
809
848
  tempDir.delete();
810
849
  tempDir.mkdirs();
@@ -812,7 +851,6 @@ public class DexManager {
812
851
  try {
813
852
  Baksmali.disassembleDexFile(singleDex, tempDir, 1, options);
814
853
 
815
- // 读取生成的 smali 文件
816
854
  String smaliPath = className.substring(1, className.length() - 1) + ".smali";
817
855
  File smaliFile = new File(tempDir, smaliPath);
818
856
 
@@ -821,6 +859,7 @@ public class DexManager {
821
859
  JSObject result = new JSObject();
822
860
  result.put("className", className);
823
861
  result.put("smali", smali);
862
+ result.put("engine", "java");
824
863
  return result;
825
864
  } else {
826
865
  throw new IOException("Failed to generate smali for: " + className);
@@ -887,30 +926,51 @@ public class DexManager {
887
926
  // ==================== 搜索操作 ====================
888
927
 
889
928
  /**
890
- * 搜索字符串
929
+ * 搜索字符串(优先使用 C++ 实现)
891
930
  */
892
931
  public JSArray searchString(String sessionId, String query,
893
932
  boolean regex, boolean caseSensitive) throws Exception {
894
933
  DexSession session = getSession(sessionId);
934
+
935
+ // 优先使用 C++ 实现
936
+ if (CppDex.isAvailable() && session.dexBytes != null && !regex) {
937
+ try {
938
+ String jsonResult = CppDex.searchInDex(session.dexBytes, query, "string", caseSensitive, 1000);
939
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
940
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
941
+ org.json.JSONArray cppResults = cppResult.optJSONArray("results");
942
+ if (cppResults != null) {
943
+ JSArray results = new JSArray();
944
+ for (int i = 0; i < cppResults.length(); i++) {
945
+ org.json.JSONObject r = cppResults.getJSONObject(i);
946
+ JSObject item = new JSObject();
947
+ item.put("value", r.optString("value"));
948
+ item.put("index", r.optInt("index"));
949
+ results.put(item);
950
+ }
951
+ return results;
952
+ }
953
+ }
954
+ } catch (Exception e) {
955
+ Log.w(TAG, "C++ searchString failed, fallback to Java", e);
956
+ }
957
+ }
958
+
959
+ // Java 回退实现
895
960
  JSArray results = new JSArray();
896
-
897
961
  Pattern pattern = null;
898
962
  if (regex) {
899
963
  int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
900
964
  pattern = Pattern.compile(query, flags);
901
965
  }
902
966
 
903
- // 遍历所有类中的字符串引用进行搜索
904
967
  Set<String> searchedStrings = new HashSet<>();
905
968
  for (ClassDef classDef : session.originalDexFile.getClasses()) {
906
- // 类名
907
969
  checkAndAddString(classDef.getType(), query, regex, caseSensitive, pattern, searchedStrings, results);
908
- // 父类
909
970
  if (classDef.getSuperclass() != null) {
910
971
  checkAndAddString(classDef.getSuperclass(), query, regex, caseSensitive, pattern, searchedStrings, results);
911
972
  }
912
973
  }
913
-
914
974
  return results;
915
975
  }
916
976
 
@@ -945,16 +1005,41 @@ public class DexManager {
945
1005
  }
946
1006
 
947
1007
  /**
948
- * 搜索方法
1008
+ * 搜索方法(优先使用 C++ 实现)
949
1009
  */
950
1010
  public JSArray searchMethod(String sessionId, String query) throws Exception {
951
1011
  DexSession session = getSession(sessionId);
1012
+
1013
+ // 优先使用 C++ 实现
1014
+ if (CppDex.isAvailable() && session.dexBytes != null) {
1015
+ try {
1016
+ String jsonResult = CppDex.searchInDex(session.dexBytes, query, "method", false, 1000);
1017
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
1018
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1019
+ org.json.JSONArray cppResults = cppResult.optJSONArray("results");
1020
+ if (cppResults != null) {
1021
+ JSArray results = new JSArray();
1022
+ for (int i = 0; i < cppResults.length(); i++) {
1023
+ org.json.JSONObject r = cppResults.getJSONObject(i);
1024
+ JSObject item = new JSObject();
1025
+ item.put("className", r.optString("className"));
1026
+ item.put("methodName", r.optString("name"));
1027
+ item.put("returnType", r.optString("returnType", ""));
1028
+ results.put(item);
1029
+ }
1030
+ return results;
1031
+ }
1032
+ }
1033
+ } catch (Exception e) {
1034
+ Log.w(TAG, "C++ searchMethod failed, fallback to Java", e);
1035
+ }
1036
+ }
1037
+
1038
+ // Java 回退实现
952
1039
  JSArray results = new JSArray();
953
1040
  String queryLower = query.toLowerCase();
954
-
955
1041
  for (ClassDef classDef : session.originalDexFile.getClasses()) {
956
1042
  if (session.removedClasses.contains(classDef.getType())) continue;
957
-
958
1043
  for (Method method : classDef.getMethods()) {
959
1044
  if (method.getName().toLowerCase().contains(queryLower)) {
960
1045
  JSObject item = new JSObject();
@@ -965,21 +1050,45 @@ public class DexManager {
965
1050
  }
966
1051
  }
967
1052
  }
968
-
969
1053
  return results;
970
1054
  }
971
1055
 
972
1056
  /**
973
- * 搜索字段
1057
+ * 搜索字段(优先使用 C++ 实现)
974
1058
  */
975
1059
  public JSArray searchField(String sessionId, String query) throws Exception {
976
1060
  DexSession session = getSession(sessionId);
1061
+
1062
+ // 优先使用 C++ 实现
1063
+ if (CppDex.isAvailable() && session.dexBytes != null) {
1064
+ try {
1065
+ String jsonResult = CppDex.searchInDex(session.dexBytes, query, "field", false, 1000);
1066
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
1067
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1068
+ org.json.JSONArray cppResults = cppResult.optJSONArray("results");
1069
+ if (cppResults != null) {
1070
+ JSArray results = new JSArray();
1071
+ for (int i = 0; i < cppResults.length(); i++) {
1072
+ org.json.JSONObject r = cppResults.getJSONObject(i);
1073
+ JSObject item = new JSObject();
1074
+ item.put("className", r.optString("className"));
1075
+ item.put("fieldName", r.optString("name"));
1076
+ item.put("fieldType", r.optString("type", ""));
1077
+ results.put(item);
1078
+ }
1079
+ return results;
1080
+ }
1081
+ }
1082
+ } catch (Exception e) {
1083
+ Log.w(TAG, "C++ searchField failed, fallback to Java", e);
1084
+ }
1085
+ }
1086
+
1087
+ // Java 回退实现
977
1088
  JSArray results = new JSArray();
978
1089
  String queryLower = query.toLowerCase();
979
-
980
1090
  for (ClassDef classDef : session.originalDexFile.getClasses()) {
981
1091
  if (session.removedClasses.contains(classDef.getType())) continue;
982
-
983
1092
  for (Field field : classDef.getFields()) {
984
1093
  if (field.getName().toLowerCase().contains(queryLower)) {
985
1094
  JSObject item = new JSObject();
@@ -990,10 +1099,109 @@ public class DexManager {
990
1099
  }
991
1100
  }
992
1101
  }
993
-
994
1102
  return results;
995
1103
  }
996
1104
 
1105
+ // ==================== 交叉引用分析(C++ 实现)====================
1106
+
1107
+ /**
1108
+ * 查找方法的交叉引用
1109
+ */
1110
+ public JSObject findMethodXrefs(String sessionId, String className, String methodName) throws Exception {
1111
+ DexSession session = getSession(sessionId);
1112
+
1113
+ if (!CppDex.isAvailable() || session.dexBytes == null) {
1114
+ throw new UnsupportedOperationException("C++ library not available for xref analysis");
1115
+ }
1116
+
1117
+ String jsonResult = CppDex.findMethodXrefs(session.dexBytes, className, methodName);
1118
+ if (jsonResult == null || jsonResult.contains("\"error\"")) {
1119
+ throw new Exception("Failed to find method xrefs");
1120
+ }
1121
+
1122
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1123
+ JSObject result = new JSObject();
1124
+ result.put("className", className);
1125
+ result.put("methodName", methodName);
1126
+
1127
+ org.json.JSONArray xrefs = cppResult.optJSONArray("xrefs");
1128
+ JSArray xrefArray = new JSArray();
1129
+ if (xrefs != null) {
1130
+ for (int i = 0; i < xrefs.length(); i++) {
1131
+ org.json.JSONObject x = xrefs.getJSONObject(i);
1132
+ JSObject xref = new JSObject();
1133
+ xref.put("callerClass", x.optString("callerClass"));
1134
+ xref.put("callerMethod", x.optString("callerMethod"));
1135
+ xref.put("offset", x.optInt("offset"));
1136
+ xrefArray.put(xref);
1137
+ }
1138
+ }
1139
+ result.put("xrefs", xrefArray);
1140
+ result.put("count", xrefArray.length());
1141
+ return result;
1142
+ }
1143
+
1144
+ /**
1145
+ * 查找字段的交叉引用
1146
+ */
1147
+ public JSObject findFieldXrefs(String sessionId, String className, String fieldName) throws Exception {
1148
+ DexSession session = getSession(sessionId);
1149
+
1150
+ if (!CppDex.isAvailable() || session.dexBytes == null) {
1151
+ throw new UnsupportedOperationException("C++ library not available for xref analysis");
1152
+ }
1153
+
1154
+ String jsonResult = CppDex.findFieldXrefs(session.dexBytes, className, fieldName);
1155
+ if (jsonResult == null || jsonResult.contains("\"error\"")) {
1156
+ throw new Exception("Failed to find field xrefs");
1157
+ }
1158
+
1159
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1160
+ JSObject result = new JSObject();
1161
+ result.put("className", className);
1162
+ result.put("fieldName", fieldName);
1163
+
1164
+ org.json.JSONArray xrefs = cppResult.optJSONArray("xrefs");
1165
+ JSArray xrefArray = new JSArray();
1166
+ if (xrefs != null) {
1167
+ for (int i = 0; i < xrefs.length(); i++) {
1168
+ org.json.JSONObject x = xrefs.getJSONObject(i);
1169
+ JSObject xref = new JSObject();
1170
+ xref.put("accessorClass", x.optString("accessorClass"));
1171
+ xref.put("accessorMethod", x.optString("accessorMethod"));
1172
+ xref.put("accessType", x.optString("accessType"));
1173
+ xrefArray.put(xref);
1174
+ }
1175
+ }
1176
+ result.put("xrefs", xrefArray);
1177
+ result.put("count", xrefArray.length());
1178
+ return result;
1179
+ }
1180
+
1181
+ // ==================== Smali 转 Java(C++ 实现)====================
1182
+
1183
+ /**
1184
+ * 将 Smali 代码转换为 Java 伪代码
1185
+ */
1186
+ public JSObject smaliToJava(String sessionId, String className) throws Exception {
1187
+ DexSession session = getSession(sessionId);
1188
+
1189
+ if (!CppDex.isAvailable() || session.dexBytes == null) {
1190
+ throw new UnsupportedOperationException("C++ library not available for smali to java conversion");
1191
+ }
1192
+
1193
+ String jsonResult = CppDex.smaliToJava(session.dexBytes, className);
1194
+ if (jsonResult == null || jsonResult.contains("\"error\"")) {
1195
+ throw new Exception("Failed to convert smali to java");
1196
+ }
1197
+
1198
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1199
+ JSObject result = new JSObject();
1200
+ result.put("className", className);
1201
+ result.put("java", cppResult.optString("java", ""));
1202
+ return result;
1203
+ }
1204
+
997
1205
  // ==================== 工具操作 ====================
998
1206
 
999
1207
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-dex-editor",
3
- "version": "0.0.71",
3
+ "version": "0.0.72",
4
4
  "description": "Capacitor-plugin-for-editing-DEX-files-in-APK",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",