capacitor-dex-editor 0.0.65 → 0.0.66
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.
|
@@ -152,13 +152,6 @@ public class DexManager {
|
|
|
152
152
|
Map<String, DexBackedDexFile> dexFiles;
|
|
153
153
|
Map<String, byte[]> dexBytes; // DEX 字节数据,用于 Rust 搜索
|
|
154
154
|
Map<String, ClassDef> modifiedClasses;
|
|
155
|
-
// 使用 LRU 缓存限制内存,最多缓存 200 个类
|
|
156
|
-
Map<String, String> smaliCache = new java.util.LinkedHashMap<String, String>(200, 0.75f, true) {
|
|
157
|
-
@Override
|
|
158
|
-
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
|
|
159
|
-
return size() > 200;
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
155
|
boolean modified = false;
|
|
163
156
|
|
|
164
157
|
MultiDexSession(String sessionId, String apkPath) {
|
|
@@ -1764,8 +1757,7 @@ public class DexManager {
|
|
|
1764
1757
|
}
|
|
1765
1758
|
|
|
1766
1759
|
/**
|
|
1767
|
-
* 在多 DEX
|
|
1768
|
-
* 优先使用 Rust 实现,如果不可用则回退到 Java 实现
|
|
1760
|
+
* 在多 DEX 会话中搜索(Rust 实现)
|
|
1769
1761
|
*/
|
|
1770
1762
|
public JSObject searchInMultiSession(String sessionId, String query, String searchType,
|
|
1771
1763
|
boolean caseSensitive, int maxResults) throws Exception {
|
|
@@ -1774,137 +1766,14 @@ public class DexManager {
|
|
|
1774
1766
|
throw new IllegalArgumentException("Session not found: " + sessionId);
|
|
1775
1767
|
}
|
|
1776
1768
|
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
try {
|
|
1780
|
-
return searchWithRust(session, query, searchType, caseSensitive, maxResults);
|
|
1781
|
-
} catch (Exception e) {
|
|
1782
|
-
Log.w(TAG, "Rust search failed, falling back to Java: " + e.getMessage());
|
|
1783
|
-
}
|
|
1769
|
+
if (!RustDex.isAvailable()) {
|
|
1770
|
+
throw new RuntimeException("Rust DEX library not available");
|
|
1784
1771
|
}
|
|
1785
1772
|
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
JSArray results = new JSArray();
|
|
1789
|
-
String queryMatch = caseSensitive ? query : query.toLowerCase();
|
|
1790
|
-
|
|
1791
|
-
outerLoop:
|
|
1792
|
-
for (Map.Entry<String, DexBackedDexFile> entry : session.dexFiles.entrySet()) {
|
|
1793
|
-
String dexName = entry.getKey();
|
|
1794
|
-
DexBackedDexFile dexFile = entry.getValue();
|
|
1795
|
-
|
|
1796
|
-
for (ClassDef classDef : dexFile.getClasses()) {
|
|
1797
|
-
if (results.length() >= maxResults) break outerLoop;
|
|
1798
|
-
|
|
1799
|
-
String className = convertTypeToClassName(classDef.getType());
|
|
1800
|
-
String classNameMatch = caseSensitive ? className : className.toLowerCase();
|
|
1801
|
-
|
|
1802
|
-
switch (searchType) {
|
|
1803
|
-
case "class":
|
|
1804
|
-
if (classNameMatch.contains(queryMatch)) {
|
|
1805
|
-
JSObject item = new JSObject();
|
|
1806
|
-
item.put("type", "class");
|
|
1807
|
-
item.put("className", className);
|
|
1808
|
-
item.put("dexFile", dexName);
|
|
1809
|
-
results.put(item);
|
|
1810
|
-
}
|
|
1811
|
-
break;
|
|
1812
|
-
|
|
1813
|
-
case "package":
|
|
1814
|
-
if (classNameMatch.startsWith(queryMatch)) {
|
|
1815
|
-
JSObject item = new JSObject();
|
|
1816
|
-
item.put("type", "package");
|
|
1817
|
-
item.put("className", className);
|
|
1818
|
-
item.put("dexFile", dexName);
|
|
1819
|
-
results.put(item);
|
|
1820
|
-
}
|
|
1821
|
-
break;
|
|
1822
|
-
|
|
1823
|
-
case "method":
|
|
1824
|
-
for (Method method : classDef.getMethods()) {
|
|
1825
|
-
if (results.length() >= maxResults) break outerLoop;
|
|
1826
|
-
String methodName = method.getName();
|
|
1827
|
-
String methodMatch = caseSensitive ? methodName : methodName.toLowerCase();
|
|
1828
|
-
if (methodMatch.contains(queryMatch)) {
|
|
1829
|
-
JSObject item = new JSObject();
|
|
1830
|
-
item.put("type", "method");
|
|
1831
|
-
item.put("className", className);
|
|
1832
|
-
item.put("methodName", methodName);
|
|
1833
|
-
item.put("dexFile", dexName);
|
|
1834
|
-
results.put(item);
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
break;
|
|
1838
|
-
|
|
1839
|
-
case "field":
|
|
1840
|
-
for (Field field : classDef.getFields()) {
|
|
1841
|
-
if (results.length() >= maxResults) break outerLoop;
|
|
1842
|
-
String fieldName = field.getName();
|
|
1843
|
-
String fieldMatch = caseSensitive ? fieldName : fieldName.toLowerCase();
|
|
1844
|
-
if (fieldMatch.contains(queryMatch)) {
|
|
1845
|
-
JSObject item = new JSObject();
|
|
1846
|
-
item.put("type", "field");
|
|
1847
|
-
item.put("className", className);
|
|
1848
|
-
item.put("fieldName", fieldName);
|
|
1849
|
-
item.put("dexFile", dexName);
|
|
1850
|
-
results.put(item);
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
break;
|
|
1854
|
-
|
|
1855
|
-
case "string":
|
|
1856
|
-
case "code":
|
|
1857
|
-
// 使用缓存的 smali 搜索
|
|
1858
|
-
String smali = getCachedSmali(session, className, dexFile, classDef);
|
|
1859
|
-
String smaliMatch = caseSensitive ? smali : smali.toLowerCase();
|
|
1860
|
-
if (smaliMatch.contains(queryMatch)) {
|
|
1861
|
-
JSObject item = new JSObject();
|
|
1862
|
-
item.put("type", searchType);
|
|
1863
|
-
item.put("className", className);
|
|
1864
|
-
item.put("dexFile", dexName);
|
|
1865
|
-
// 找到匹配的行
|
|
1866
|
-
String[] lines = smali.split("\n");
|
|
1867
|
-
for (int i = 0; i < lines.length; i++) {
|
|
1868
|
-
String lineMatch = caseSensitive ? lines[i] : lines[i].toLowerCase();
|
|
1869
|
-
if (lineMatch.contains(queryMatch)) {
|
|
1870
|
-
item.put("line", i + 1);
|
|
1871
|
-
item.put("content", lines[i].trim());
|
|
1872
|
-
break;
|
|
1873
|
-
}
|
|
1874
|
-
}
|
|
1875
|
-
results.put(item);
|
|
1876
|
-
}
|
|
1877
|
-
break;
|
|
1878
|
-
|
|
1879
|
-
case "int":
|
|
1880
|
-
// 搜索整数常量(使用缓存)
|
|
1881
|
-
String smaliForInt = getCachedSmali(session, className, dexFile, classDef);
|
|
1882
|
-
if (smaliForInt.contains("0x" + query) || smaliForInt.contains(" " + query + "\n") ||
|
|
1883
|
-
smaliForInt.contains(" " + query + " ")) {
|
|
1884
|
-
JSObject item = new JSObject();
|
|
1885
|
-
item.put("type", "int");
|
|
1886
|
-
item.put("className", className);
|
|
1887
|
-
item.put("dexFile", dexName);
|
|
1888
|
-
results.put(item);
|
|
1889
|
-
}
|
|
1890
|
-
break;
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1773
|
+
if (session.dexBytes.isEmpty()) {
|
|
1774
|
+
throw new RuntimeException("No DEX data loaded");
|
|
1893
1775
|
}
|
|
1894
1776
|
|
|
1895
|
-
result.put("query", query);
|
|
1896
|
-
result.put("searchType", searchType);
|
|
1897
|
-
result.put("total", results.length());
|
|
1898
|
-
result.put("results", results);
|
|
1899
|
-
|
|
1900
|
-
return result;
|
|
1901
|
-
}
|
|
1902
|
-
|
|
1903
|
-
/**
|
|
1904
|
-
* 使用 Rust 实现搜索(高性能)
|
|
1905
|
-
*/
|
|
1906
|
-
private JSObject searchWithRust(MultiDexSession session, String query, String searchType,
|
|
1907
|
-
boolean caseSensitive, int maxResults) throws Exception {
|
|
1908
1777
|
JSObject result = new JSObject();
|
|
1909
1778
|
JSArray allResults = new JSArray();
|
|
1910
1779
|
|
|
@@ -1912,11 +1781,9 @@ public class DexManager {
|
|
|
1912
1781
|
String dexName = entry.getKey();
|
|
1913
1782
|
byte[] dexData = entry.getValue();
|
|
1914
1783
|
|
|
1915
|
-
// 调用 Rust 搜索
|
|
1916
1784
|
String jsonResult = RustDex.searchInDex(dexData, query, searchType, caseSensitive, maxResults);
|
|
1917
1785
|
|
|
1918
1786
|
if (jsonResult != null && !jsonResult.contains("\"error\"")) {
|
|
1919
|
-
// 解析 Rust 返回的 JSON
|
|
1920
1787
|
org.json.JSONObject rustResult = new org.json.JSONObject(jsonResult);
|
|
1921
1788
|
org.json.JSONArray rustResults = rustResult.optJSONArray("results");
|
|
1922
1789
|
|
|
@@ -1967,20 +1834,6 @@ public class DexManager {
|
|
|
1967
1834
|
}
|
|
1968
1835
|
}
|
|
1969
1836
|
|
|
1970
|
-
/**
|
|
1971
|
-
* 获取缓存的 Smali 代码(用于搜索优化)
|
|
1972
|
-
*/
|
|
1973
|
-
private String getCachedSmali(MultiDexSession session, String className, DexBackedDexFile dexFile, ClassDef classDef) {
|
|
1974
|
-
// 先查缓存
|
|
1975
|
-
String cached = session.smaliCache.get(className);
|
|
1976
|
-
if (cached != null) {
|
|
1977
|
-
return cached;
|
|
1978
|
-
}
|
|
1979
|
-
// 缓存未命中,反编译并缓存
|
|
1980
|
-
String smali = getSmaliForClass(dexFile, classDef);
|
|
1981
|
-
session.smaliCache.put(className, smali);
|
|
1982
|
-
return smali;
|
|
1983
|
-
}
|
|
1984
1837
|
|
|
1985
1838
|
/**
|
|
1986
1839
|
* 从多 DEX 会话获取类的 Smali 代码
|