Skip to content

Commit 7d39934

Browse files
committed
Feedback Features
1 parent e1da180 commit 7d39934

File tree

7 files changed

+793
-66
lines changed

7 files changed

+793
-66
lines changed

src/main/java/com/jarida/jadxfrida/FridaPluginOptions.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public class FridaPluginOptions extends BasePluginOptionsBuilder {
2828
private boolean templateAppend = false;
2929
private String templateName = "None";
3030
private String templateContent = "";
31+
private String customScriptPaths = "";
3132

3233
public FridaPluginOptions() {
3334
registerOptions();
@@ -116,6 +117,10 @@ public void registerOptions() {
116117
.description("Custom script content")
117118
.defaultValue(templateContent)
118119
.setter(v -> templateContent = v);
120+
strOption(PREFIX + "customScriptPaths")
121+
.description("Custom script file paths (one per line)")
122+
.defaultValue(customScriptPaths)
123+
.setter(v -> customScriptPaths = v);
119124
}
120125

121126
public FridaSessionConfig toSessionConfig() {
@@ -190,4 +195,14 @@ public String getTemplateName() {
190195
public String getTemplateContent() {
191196
return templateContent;
192197
}
198+
199+
public String getCustomScriptPaths() {
200+
return customScriptPaths;
201+
}
202+
203+
public void setCustomScripts(String paths) {
204+
if (paths != null) {
205+
this.customScriptPaths = paths;
206+
}
207+
}
193208
}

src/main/java/com/jarida/jadxfrida/FridaTracePlugin.java

Lines changed: 169 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141
import java.util.Map;
4242
import java.util.Set;
4343
import java.util.WeakHashMap;
44+
import java.io.IOException;
4445
import javax.swing.JFrame;
4546
import javax.swing.JOptionPane;
4647
import javax.swing.SwingUtilities;
48+
import java.util.prefs.Preferences;
4749

4850
public class FridaTracePlugin implements JadxPlugin {
4951
private JadxPluginContext pluginContext;
@@ -66,6 +68,9 @@ public class FridaTracePlugin implements JadxPlugin {
6668
private FridaSessionConfig lastSessionConfig = new FridaSessionConfig();
6769
private ScriptOptions lastScriptOptions = new ScriptOptions();
6870
private FridaSessionConfig activeSessionConfig;
71+
private String customScriptPaths = "";
72+
private final java.util.Set<String> missingCustomScripts = new java.util.HashSet<>();
73+
private static final Preferences PREFS = Preferences.userRoot().node("com.jarida.jadxfrida");
6974

7075
@Override
7176
public JadxPluginInfo getPluginInfo() {
@@ -86,6 +91,8 @@ public void init(JadxPluginContext context) {
8691
context.registerOptions(pluginOptions);
8792
this.lastSessionConfig = pluginOptions.toSessionConfig();
8893
this.lastScriptOptions = pluginOptions.toScriptOptions();
94+
this.customScriptPaths = pluginOptions.getCustomScriptPaths();
95+
loadSavedPaths();
8996
if (guiContext != null) {
9097
initGui();
9198
guiContext.settings().setCustomSettingsGroup(
@@ -156,12 +163,15 @@ private void openConsole(boolean focus) {
156163
String pkg = PackageNameResolver.resolvePackageName(decompiler);
157164
String version = getVersionString();
158165
connectionPanel = new JaridaConnectionPanel(fridaController, lastSessionConfig, pkg,
159-
this::applyConnectionConfig, this::startSessionFromConnection, this::stopTrace);
160-
consoleNode = new FridaConsoleNode(this::removeHook, this::toggleHook, this::removeAllHooks, connectionPanel, version);
166+
this::applyConnectionConfig, this::startSessionFromConnection, this::stopTrace, this::savePathsConfig);
167+
consoleNode = new FridaConsoleNode(this::removeHook, this::toggleHook, this::removeAllHooks,
168+
connectionPanel, version, this::applyCustomScriptsFromConsole);
161169
}
162-
mainWindow.getTabsController().openTab(consoleNode);
170+
jadx.gui.ui.tab.TabsController controller = mainWindow.getTabsController();
171+
controller.openTab(consoleNode);
172+
ContentPanel consolePanelRef = tabs.getTabByNode(consoleNode);
163173
if (focus) {
164-
mainWindow.getTabsController().selectTab(consoleNode, true);
174+
selectConsoleTab(tabs, controller, consoleNode, consolePanelRef);
165175
} else {
166176
if (prevPanel != null && tabs.indexOfComponent(prevPanel) >= 0) {
167177
tabs.setSelectedComponent(prevPanel);
@@ -178,6 +188,7 @@ private void openConsole(boolean focus) {
178188
if (consolePanel != null) {
179189
consolePanel.setSessionActive(fridaController.isRunning());
180190
consolePanel.setConnectionVisible(!fridaController.isRunning());
191+
consolePanel.setCustomScripts(customScriptPaths);
181192
}
182193
if (consolePanel != null && !pendingLogs.isEmpty()) {
183194
for (String line : pendingLogs) {
@@ -213,6 +224,30 @@ private void ensureTabComponent(TabbedPane tabs, FridaConsoleNode node) {
213224
}
214225
}
215226

227+
private void selectConsoleTab(TabbedPane tabs, Object controller, JNode node, ContentPanel panel) {
228+
if (tabs != null && panel != null) {
229+
try {
230+
tabs.setSelectedComponent(panel);
231+
return;
232+
} catch (Exception ignored) {
233+
}
234+
}
235+
if (controller == null || node == null) {
236+
return;
237+
}
238+
try {
239+
java.lang.reflect.Method method = controller.getClass().getMethod("selectTab", JNode.class, boolean.class);
240+
method.invoke(controller, node, true);
241+
return;
242+
} catch (Exception ignored) {
243+
}
244+
try {
245+
java.lang.reflect.Method method = controller.getClass().getMethod("selectTab", JNode.class);
246+
method.invoke(controller, node);
247+
} catch (Exception ignored) {
248+
}
249+
}
250+
216251
private void openSettings(ICodeNodeRef ref, boolean patchDefault, boolean showReturnTab,
217252
boolean focusReturnTab, boolean requireConnection) {
218253
if (requireConnection && !fridaController.isRunning()) {
@@ -269,7 +304,7 @@ record = new HookRecord(hookKey, target.getDisplaySignature(), ref);
269304
}
270305
HookSpec spec = new HookSpec(target, lastScriptOptions, patchRule, dialog.getExtraScript(), hookKey);
271306
hookSpecs.put(hookKey, spec);
272-
String script = HookScriptGenerator.generateCombined(getActiveSpecs());
307+
String script = buildCombinedScript();
273308
boolean canReuseNow = fridaController.isRunning()
274309
&& activeSessionConfig != null
275310
&& fixedConfig != null
@@ -582,7 +617,7 @@ private String getVersionString() {
582617
}
583618
} catch (Exception ignored) {
584619
}
585-
return "0.1.0";
620+
return "unknown";
586621
}
587622

588623
private void showError(String message) {
@@ -613,6 +648,72 @@ private void applyConnectionConfig(FridaSessionConfig cfg) {
613648
pluginOptions.isTemplateAppend(), pluginOptions.getTemplateName(), pluginOptions.getTemplateContent());
614649
}
615650

651+
private void applyCustomScriptsFromConsole(String paths) {
652+
customScriptPaths = paths == null ? "" : paths;
653+
pluginOptions.setCustomScripts(customScriptPaths);
654+
String script = buildCombinedScript();
655+
if (consolePanel != null) {
656+
consolePanel.setScript(script);
657+
} else {
658+
pendingScript = script;
659+
}
660+
if (fridaController.isRunning()) {
661+
try {
662+
fridaController.updateSessionScript(script, this::appendLog);
663+
} catch (IOException e) {
664+
appendLog("Failed to update Jarida session: " + e.getMessage());
665+
}
666+
}
667+
}
668+
669+
private void savePathsConfig(FridaSessionConfig cfg) {
670+
if (cfg == null) {
671+
return;
672+
}
673+
String adb = cfg.getAdbPath();
674+
String frida = cfg.getFridaPath();
675+
String fridaPs = cfg.getFridaPsPath();
676+
try {
677+
if (adb != null && !adb.trim().isEmpty()) {
678+
PREFS.put("path.adb", adb.trim());
679+
lastSessionConfig.setAdbPath(adb.trim());
680+
}
681+
if (frida != null && !frida.trim().isEmpty()) {
682+
PREFS.put("path.frida", frida.trim());
683+
lastSessionConfig.setFridaPath(frida.trim());
684+
}
685+
if (fridaPs != null && !fridaPs.trim().isEmpty()) {
686+
PREFS.put("path.fridaPs", fridaPs.trim());
687+
lastSessionConfig.setFridaPsPath(fridaPs.trim());
688+
}
689+
} catch (Exception ignored) {
690+
}
691+
pluginOptions.updateFrom(lastSessionConfig, lastScriptOptions,
692+
pluginOptions.isTemplateAppend(), pluginOptions.getTemplateName(), pluginOptions.getTemplateContent());
693+
}
694+
695+
private void loadSavedPaths() {
696+
try {
697+
String adb = PREFS.get("path.adb", null);
698+
String frida = PREFS.get("path.frida", null);
699+
String fridaPs = PREFS.get("path.fridaPs", null);
700+
if (adb != null && !adb.trim().isEmpty()) {
701+
lastSessionConfig.setAdbPath(adb.trim());
702+
}
703+
if (frida != null && !frida.trim().isEmpty()) {
704+
lastSessionConfig.setFridaPath(frida.trim());
705+
}
706+
if (fridaPs != null && !fridaPs.trim().isEmpty()) {
707+
lastSessionConfig.setFridaPsPath(fridaPs.trim());
708+
}
709+
if (pluginOptions != null) {
710+
pluginOptions.updateFrom(lastSessionConfig, lastScriptOptions,
711+
pluginOptions.isTemplateAppend(), pluginOptions.getTemplateName(), pluginOptions.getTemplateContent());
712+
}
713+
} catch (Exception ignored) {
714+
}
715+
}
716+
616717
private void startSessionFromConnection(FridaSessionConfig cfg) {
617718
if (cfg == null) {
618719
return;
@@ -627,7 +728,7 @@ private void startSessionFromConnection(FridaSessionConfig cfg) {
627728
return;
628729
}
629730
try {
630-
String script = HookScriptGenerator.generateCombined(getActiveSpecs());
731+
String script = buildCombinedScript();
631732
fridaController.startWithScript(cfg, script, this::appendLog);
632733
activeSessionConfig = cfg;
633734
if (consolePanel != null) {
@@ -712,7 +813,7 @@ private void reloadCombinedHooks() {
712813
return;
713814
}
714815
try {
715-
String script = HookScriptGenerator.generateCombined(getActiveSpecs());
816+
String script = buildCombinedScript();
716817
fridaController.updateSessionScript(script, this::appendLog);
717818
if (consolePanel != null) {
718819
consolePanel.setScript(script);
@@ -733,6 +834,66 @@ private java.util.List<HookSpec> getActiveSpecs() {
733834
return active;
734835
}
735836

837+
private String buildCombinedScript() {
838+
java.util.List<String> globals = new java.util.ArrayList<>();
839+
java.util.List<CustomScriptEntry> scripts = parseCustomScriptPaths(customScriptPaths);
840+
for (CustomScriptEntry entry : scripts) {
841+
if (!entry.enabled || entry.path.isEmpty()) {
842+
continue;
843+
}
844+
try {
845+
java.nio.file.Path p = java.nio.file.Paths.get(entry.path);
846+
String content = java.nio.file.Files.readString(p);
847+
globals.add("// -- " + entry.path + "\n" + content);
848+
} catch (Exception e) {
849+
if (missingCustomScripts.add(entry.path)) {
850+
appendLog("Custom script not found: " + entry.path);
851+
}
852+
}
853+
}
854+
return HookScriptGenerator.generateCombined(getActiveSpecs(), globals);
855+
}
856+
857+
private static final class CustomScriptEntry {
858+
final String path;
859+
final boolean enabled;
860+
861+
private CustomScriptEntry(String path, boolean enabled) {
862+
this.path = path == null ? "" : path.trim();
863+
this.enabled = enabled;
864+
}
865+
}
866+
867+
private java.util.List<CustomScriptEntry> parseCustomScriptPaths(String raw) {
868+
java.util.List<CustomScriptEntry> entries = new java.util.ArrayList<>();
869+
if (raw == null || raw.trim().isEmpty()) {
870+
return entries;
871+
}
872+
String[] lines = raw.split("\\R");
873+
for (String line : lines) {
874+
if (line == null) {
875+
continue;
876+
}
877+
String trimmed = line.trim();
878+
if (trimmed.isEmpty()) {
879+
continue;
880+
}
881+
boolean enabled = true;
882+
String path = trimmed;
883+
if (trimmed.startsWith("1|") || trimmed.startsWith("0|")) {
884+
enabled = trimmed.startsWith("1|");
885+
path = trimmed.substring(2).trim();
886+
} else if (trimmed.startsWith("[x]") || trimmed.startsWith("[ ]")) {
887+
enabled = trimmed.startsWith("[x]");
888+
path = trimmed.substring(3).trim();
889+
}
890+
if (!path.isEmpty()) {
891+
entries.add(new CustomScriptEntry(path, enabled));
892+
}
893+
}
894+
return entries;
895+
}
896+
736897
private void toggleHook(HookRecord record) {
737898
if (record == null) {
738899
return;

src/main/java/com/jarida/jadxfrida/frida/HookScriptGenerator.java

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,27 @@ public static String generate(HookSpec spec) {
1818
}
1919

2020
public static String generateCombined(java.util.Collection<HookSpec> specs) {
21-
if (specs == null || specs.isEmpty()) {
22-
StringBuilder sb = new StringBuilder();
23-
sb.append("'use strict';\n");
24-
sb.append("setImmediate(function() {\n");
25-
sb.append(" Java.perform(function() {\n");
26-
sb.append(" // no hooks\n");
27-
sb.append(" });\n");
28-
sb.append("});\n");
29-
return sb.toString();
30-
}
21+
return generateCombined(specs, null);
22+
}
23+
24+
public static String generateCombined(java.util.Collection<HookSpec> specs, java.util.List<String> globalScripts) {
3125
StringBuilder sb = new StringBuilder();
3226
sb.append("'use strict';\n");
27+
appendGlobalScripts(sb, globalScripts);
3328
sb.append("setImmediate(function() {\n");
3429
sb.append(" Java.perform(function() {\n");
3530
appendHelpers(sb);
3631
int idx = 0;
37-
for (HookSpec spec : specs) {
38-
if (spec == null || spec.getTarget() == null) {
39-
continue;
32+
if (specs == null || specs.isEmpty()) {
33+
sb.append(" // no hooks\n");
34+
} else {
35+
for (HookSpec spec : specs) {
36+
if (spec == null || spec.getTarget() == null) {
37+
continue;
38+
}
39+
idx++;
40+
appendHook(sb, spec, idx);
4041
}
41-
idx++;
42-
appendHook(sb, spec, idx);
4342
}
4443
sb.append(" });\n");
4544
sb.append("});\n");
@@ -99,6 +98,20 @@ private static void appendExtraScript(StringBuilder sb, String extraScript, Stri
9998
}
10099
}
101100

101+
private static void appendGlobalScripts(StringBuilder sb, java.util.List<String> scripts) {
102+
if (scripts == null || scripts.isEmpty()) {
103+
return;
104+
}
105+
for (String script : scripts) {
106+
if (script == null || script.trim().isEmpty()) {
107+
continue;
108+
}
109+
sb.append("\n// ---- Jarida custom script ----\n");
110+
sb.append(script).append("\n");
111+
}
112+
sb.append("\n");
113+
}
114+
102115
private static void appendHelpers(StringBuilder sb) {
103116
sb.append(" function safeToString(obj, opts) {\n");
104117
sb.append(" try {\n");

src/main/java/com/jarida/jadxfrida/ui/FridaConfigDialog.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ private JPanel buildTemplatePanel() {
413413
return panel;
414414
}
415415

416+
416417
private void loadTemplate() {
417418
ScriptTemplate template = (ScriptTemplate) templateList.getSelectedItem();
418419
if (template != null) {
@@ -670,6 +671,7 @@ public String getExtraScript() {
670671
return "";
671672
}
672673

674+
673675
public boolean isTemplateAppend() {
674676
return templateAppend.isSelected();
675677
}

0 commit comments

Comments
 (0)