Skip to content

Commit 189c567

Browse files
committed
adding config for maximum decoded string length to display in a comment
1 parent ae14694 commit 189c567

6 files changed

Lines changed: 59 additions & 12 deletions

File tree

src/main/java/jadx/plugins/stringdecoder/B64DeobfuscateOptions.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,25 @@
55
public class B64DeobfuscateOptions extends BasePluginOptionsBuilder {
66

77
private boolean enable;
8+
private int maxCommentLength;
89

910
@Override
1011
public void registerOptions() {
1112
boolOption(JadxStringDecoderPlugin.PLUGIN_ID + ".enable")
1213
.description("Enable Base64 string detection and decoding")
1314
.defaultValue(true)
1415
.setter(v -> enable = v);
16+
intOption(JadxStringDecoderPlugin.PLUGIN_ID + ".maxCommentLength")
17+
.description("Maximum decoded string length in comment (0 for unlimited)")
18+
.defaultValue(100)
19+
.setter(v -> maxCommentLength = v);
1520
}
1621

1722
public boolean isEnable() {
1823
return enable;
1924
}
25+
26+
public int getMaxCommentLength() {
27+
return maxCommentLength;
28+
}
2029
}

src/main/java/jadx/plugins/stringdecoder/B64DeobfuscatePass.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717

1818
public class B64DeobfuscatePass implements JadxDecompilePass {
1919

20+
private final int maxCommentLength;
21+
22+
public B64DeobfuscatePass(int maxCommentLength) {
23+
this.maxCommentLength = maxCommentLength;
24+
}
25+
2026
@Override
2127
public JadxPassInfo getInfo() {
2228
return new OrderedJadxPassInfo(
@@ -53,8 +59,8 @@ public void visit(MethodNode mth) {
5359
}
5460
}
5561

56-
private static void processConstString(ConstStringNode insn) {
57-
String decoded = B64Detector.detect(insn.getString());
62+
private void processConstString(ConstStringNode insn) {
63+
String decoded = B64Detector.detect(insn.getString(), maxCommentLength);
5864
if (decoded != null) {
5965
insn.addAttr(AType.CODE_COMMENTS, new CodeComment("b64: " + decoded, CommentStyle.LINE));
6066
}

src/main/java/jadx/plugins/stringdecoder/B64Detector.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ public final class B64Detector {
1414
private static final Pattern BASE64_URL_SAFE = Pattern.compile("^[A-Za-z0-9_-]+=*$");
1515
private static final int MIN_LENGTH = 8;
1616
private static final double MIN_PRINTABLE_RATIO = 0.75;
17-
static final int MAX_COMMENT_LENGTH = 100;
1817

1918
private B64Detector() {
2019
}
2120

22-
/** Returns the decoded+truncated string if {@code str} looks like Base64, otherwise null. */
23-
public static String detect(String str) {
21+
/**
22+
* Returns the decoded string if {@code str} looks like Base64, otherwise null.
23+
* The result is truncated to {@code maxLength} chars (0 = unlimited).
24+
*/
25+
public static String detect(String str, int maxLength) {
2426
if (str.length() < MIN_LENGTH) {
2527
return null;
2628
}
@@ -31,7 +33,7 @@ public static String detect(String str) {
3133
if (decoded == null) {
3234
return null;
3335
}
34-
return truncate(decoded);
36+
return truncate(decoded, maxLength);
3537
}
3638

3739
private static String tryDecode(String str) {
@@ -69,10 +71,10 @@ private static boolean isPrintable(String str) {
6971
return (double) printableCount / str.length() >= MIN_PRINTABLE_RATIO;
7072
}
7173

72-
static String truncate(String str) {
74+
static String truncate(String str, int maxLength) {
7375
String safe = str.replace("\n", "\\n").replace("\r", "\\r");
74-
if (safe.length() > MAX_COMMENT_LENGTH) {
75-
return safe.substring(0, MAX_COMMENT_LENGTH) + "...";
76+
if (maxLength > 0 && safe.length() > maxLength) {
77+
return safe.substring(0, maxLength) + "...";
7678
}
7779
return safe;
7880
}

src/main/java/jadx/plugins/stringdecoder/B64FieldInitPass.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414

1515
public class B64FieldInitPass implements JadxDecompilePass {
1616

17+
private final int maxCommentLength;
18+
19+
public B64FieldInitPass(int maxCommentLength) {
20+
this.maxCommentLength = maxCommentLength;
21+
}
22+
1723
@Override
1824
public JadxPassInfo getInfo() {
1925
return new OrderedJadxPassInfo(
@@ -37,7 +43,7 @@ public boolean visit(ClassNode cls) {
3743
if (!(initInsn instanceof ConstStringNode)) {
3844
continue;
3945
}
40-
String decoded = B64Detector.detect(((ConstStringNode) initInsn).getString());
46+
String decoded = B64Detector.detect(((ConstStringNode) initInsn).getString(), maxCommentLength);
4147
if (decoded != null) {
4248
field.addCodeComment("b64: " + decoded);
4349
}

src/main/java/jadx/plugins/stringdecoder/JadxStringDecoderPlugin.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ public JadxPluginInfo getPluginInfo() {
2424
public void init(JadxPluginContext context) {
2525
context.registerOptions(options);
2626
if (options.isEnable()) {
27-
context.addPass(new B64DeobfuscatePass());
28-
context.addPass(new B64FieldInitPass());
27+
context.addPass(new B64DeobfuscatePass(options.getMaxCommentLength()));
28+
context.addPass(new B64FieldInitPass(options.getMaxCommentLength()));
2929
}
3030
}
3131
}

src/test/java/jadx/plugins/stringdecoder/JadxStringDecoderPluginTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.io.File;
99
import java.net.URISyntaxException;
1010
import java.net.URL;
11+
import java.util.Map;
1112

1213
import static org.assertj.core.api.Assertions.assertThat;
1314

@@ -84,9 +85,32 @@ public void staticFieldB64Test() throws Exception {
8485
assertThat(code).contains("b64: hello");
8586
}
8687

88+
@Test
89+
public void maxCommentLengthOptionTest() throws Exception {
90+
// maxCommentLength=10 should truncate the 650-char decoded string to 10 chars + "..."
91+
String code = decompileSmali("b64/long_b64.smali", Map.of("b64-deobfuscate.maxCommentLength", "10"));
92+
System.out.println(code);
93+
assertThat(code).contains("b64: " + "A".repeat(10) + "...");
94+
assertThat(code).doesNotContain("A".repeat(11));
95+
}
96+
97+
@Test
98+
public void unlimitedCommentLengthOptionTest() throws Exception {
99+
// maxCommentLength=0 should produce a comment with all 650 decoded chars, no truncation
100+
String code = decompileSmali("b64/long_b64.smali", Map.of("b64-deobfuscate.maxCommentLength", "0"));
101+
System.out.println(code);
102+
assertThat(code).contains("b64: " + "A".repeat(650));
103+
assertThat(code).doesNotContain("...");
104+
}
105+
87106
private String decompileSmali(String fileName) throws Exception {
107+
return decompileSmali(fileName, Map.of());
108+
}
109+
110+
private String decompileSmali(String fileName, Map<String, String> pluginOptions) throws Exception {
88111
JadxArgs args = new JadxArgs();
89112
args.getInputFiles().add(getSampleFile(fileName));
113+
args.setPluginOptions(pluginOptions);
90114
try (JadxDecompiler jadx = new JadxDecompiler(args)) {
91115
jadx.load();
92116
JavaClass cls = jadx.getClasses().get(0);

0 commit comments

Comments
 (0)