Skip to content

Commit 54e51f1

Browse files
committed
improving tests
1 parent 8bfd109 commit 54e51f1

12 files changed

Lines changed: 596 additions & 74 deletions

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

Lines changed: 52 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void b64DecodableNotEncodedTest() throws Exception {
5050

5151
@Test
5252
public void fieldB64Test() throws Exception {
53-
// Base64 string assigned to a static field in <clinit>
53+
// Base64 string in a const-string in a regular method body (instance field via iput-object)
5454
String code = decompileSmali("b64/field_b64.smali");
5555
System.out.println(code);
5656
assertThat(code).contains("b64: Hello, World!");
@@ -205,14 +205,6 @@ public void multilineFieldB64Test() throws Exception {
205205
assertThat(code).contains("b64(mime): Hello, World!");
206206
}
207207

208-
@Test
209-
public void pemB64FieldTest() throws Exception {
210-
// PEM Base64 String CONSTANT_VALUE + byte[] field via Base64.decode — both should get b64(mime): comment
211-
String code = decompileSmali("b64/pem_b64_field.smali");
212-
System.out.println(code);
213-
assertThat(code).contains("b64(mime):");
214-
}
215-
216208
@Test
217209
public void antifridas8kTest() throws Exception {
218210
// Real-world anti-frida/xposed detection class (s8.k) with filled-new-array/range.
@@ -283,17 +275,6 @@ public void camelCaseNotFlaggedTest() throws Exception {
283275
assertThat(code).doesNotContain("b64:");
284276
}
285277

286-
@Test
287-
public void camelCaseSkipDisabledTest() throws Exception {
288-
// with skipCamelCase=false, "getContext" is no longer suppressed by the camelCase filter;
289-
// other filters (printable ratio, alnum ratio) will still apply
290-
String code = decompileSmali("b64/camelcase_b64.smali",
291-
Map.of(opt("skipCamelCase"), "false"));
292-
System.out.println(code);
293-
// "getContext" decodes to non-UTF-8 bytes so no comment expected even without the filter
294-
assertThat(code).doesNotContain("b64:");
295-
}
296-
297278
@Test
298279
public void allCapsNotFlaggedTest() throws Exception {
299280
// "CURSOR" is all-uppercase and decodes to "\tDR9" — suppressed by skipSnakeCase (default true)
@@ -302,16 +283,6 @@ public void allCapsNotFlaggedTest() throws Exception {
302283
assertThat(code).doesNotContain("b64:");
303284
}
304285

305-
@Test
306-
public void allCapsSkipDisabledTest() throws Exception {
307-
// With skipSnakeCase=false, "CURSOR" is no longer suppressed by the pattern filter;
308-
// it decodes to "\tDR9" (75% printable), which fails the 90% default printable threshold
309-
String code = decompileSmali("b64/allcaps_b64.smali",
310-
Map.of(opt("skipSnakeCase"), "false"));
311-
System.out.println(code);
312-
assertThat(code).doesNotContain("b64:");
313-
}
314-
315286
@Test
316287
public void allLowerNotFlaggedTest() throws Exception {
317288
// "closed" is all-lowercase and decodes to "rZ,y" — suppressed by skipSnakeCase (default true)
@@ -341,16 +312,6 @@ public void dictionaryWordNotFlaggedTest() throws Exception {
341312
assertThat(code).doesNotContain("b64:");
342313
}
343314

344-
@Test
345-
public void dictionarySkipDisabledTest() throws Exception {
346-
// Disabling skipDictionaryWords must not crash; "callback" is still rejected by the
347-
// UTF-8 decode step so no b64: comment is expected
348-
String code = decompileSmali("b64/dict_word_b64.smali",
349-
Map.of(opt("skipDictionaryWords"), "false"));
350-
System.out.println(code);
351-
assertThat(code).doesNotContain("b64:");
352-
}
353-
354315
@Test
355316
public void pascalCaseNotFlaggedTest() throws Exception {
356317
// "FileUtil" matches PascalCase — suppressed by skipPascalCase (default true)
@@ -360,13 +321,16 @@ public void pascalCaseNotFlaggedTest() throws Exception {
360321
}
361322

362323
@Test
363-
public void pascalCaseSkipDisabledTest() throws Exception {
364-
// With skipPascalCase=false, "FileUtil" is no longer suppressed by the pattern filter;
365-
// it decodes to bytes that are ~60% printable, failing the 90% default threshold
366-
String code = decompileSmali("b64/pascalcase_b64.smali",
324+
public void pascalCaseSkipDisabledDecodesTest() throws Exception {
325+
// "SiteWith" is PascalCase and decodes to "J+^Z+a" (100% printable, 50% alnum).
326+
// With the filter on (default) it is suppressed; with it off it should be annotated.
327+
String codeDefault = decompileSmali("b64/pascalcase_decodable_b64.smali");
328+
assertThat(codeDefault).doesNotContain("b64:");
329+
330+
String codeDisabled = decompileSmali("b64/pascalcase_decodable_b64.smali",
367331
Map.of(opt("skipPascalCase"), "false"));
368-
System.out.println(code);
369-
assertThat(code).doesNotContain("b64:");
332+
System.out.println(codeDisabled);
333+
assertThat(codeDisabled).contains("b64: J+^Z+a");
370334
}
371335

372336
@Test
@@ -419,4 +383,46 @@ public void b64InTryCatchTest() throws Exception {
419383
assertThat(code).contains("b64: getPackageInfo");
420384
}
421385

386+
@Test
387+
public void b64ConditionalTryCatchTest() throws Exception {
388+
// Real-world pattern: cache==null branch initialises via two Base64.decode reflection
389+
// strings; an sdk>=33 conditional selects a delegate path; else branch uses a third
390+
// Base64.decode string. All three must be annotated despite the branching structure.
391+
String code = decompileSmali("b64/b64_conditional_trycatch.smali");
392+
System.out.println(code);
393+
assertThat(code).contains("b64[0]: android.app.ActivityThread");
394+
assertThat(code).contains("b64[1]: getPackageManager");
395+
assertThat(code).contains("b64: getPackageInfo");
396+
}
397+
398+
@Test
399+
public void b64DecodePassDisabledTest() throws Exception {
400+
// enableB64DecodePass=false must suppress all b64: comments from the main detection pass
401+
String code = decompileSmali("b64/hello.smali",
402+
Map.of(opt("enableB64DecodePass"), "false"));
403+
System.out.println(code);
404+
assertThat(code).doesNotContain("b64:");
405+
}
406+
407+
@Test
408+
public void b64DecodePassDisabledAlsoDisablesFieldInitPassTest() throws Exception {
409+
// enableB64DecodePass=false gates all three passes, including B64FieldInitPass.
410+
// A static field initialised with a Base64 string must not be annotated.
411+
String code = decompileSmali("b64/static_field_b64.smali",
412+
Map.of(opt("enableB64DecodePass"), "false"));
413+
System.out.println(code);
414+
assertThat(code).doesNotContain("b64:");
415+
}
416+
417+
@Test
418+
public void filledArrayNoAnchorNotAnnotatedTest() throws Exception {
419+
// String[] where every element ("aGVs") decodes to valid Base64+UTF-8 ("hel", 3 chars)
420+
// but fails full heuristic detection (decoded length 3 < default minDecodedLength=4).
421+
// hasAnchor=false so neither b64: nor b64[N]: comments are emitted.
422+
String code = decompileSmali("b64/filled_array_no_anchor.smali");
423+
System.out.println(code);
424+
assertThat(code).doesNotContain("b64:");
425+
assertThat(code).doesNotContain("b64[");
426+
}
427+
422428
}

0 commit comments

Comments
 (0)