From 83fd9d387a558f8f4ef4d1211ec3d56e79581258 Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Thu, 17 Apr 2025 15:38:23 +0200 Subject: [PATCH] add tests and factory extends --- test_apks/dyn_and_ref/AndroidManifest.xml | 5 +- test_apks/dyn_and_ref/Makefile | 15 +- .../theseus/dynandref/APReflectee.java | 2 +- .../example/theseus/dynandref/AReflectee.java | 19 +++ .../example/theseus/dynandref/Collider.java | 19 +++ .../example/theseus/dynandref/PCollider.java | 2 +- .../theseus/dynandref/PCommonParent.java | 16 ++ .../example/theseus/dynandref/Collider.java | 19 +++ .../com/example/theseus/dynandref/Main.java | 47 ++++- .../theseus/dynandref/MethodActivity.java | 38 ++++- .../example/theseus/dynandref/PCollider.java | 2 +- .../theseus/dynandref/PCommonParent.java | 16 ++ .../dyn_and_ref/tests/expected_result.txt | 153 +++++++++++++++++ test_apks/dyn_and_ref/tests/test_apk.py | 161 ++++++++++++++++++ 14 files changed, 494 insertions(+), 20 deletions(-) create mode 100644 test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/PCommonParent.java create mode 100644 test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/PCommonParent.java create mode 100644 test_apks/dyn_and_ref/tests/expected_result.txt create mode 100644 test_apks/dyn_and_ref/tests/test_apk.py diff --git a/test_apks/dyn_and_ref/AndroidManifest.xml b/test_apks/dyn_and_ref/AndroidManifest.xml index c5aa54a..2ae2d8f 100644 --- a/test_apks/dyn_and_ref/AndroidManifest.xml +++ b/test_apks/dyn_and_ref/AndroidManifest.xml @@ -36,8 +36,9 @@ - - + + + diff --git a/test_apks/dyn_and_ref/Makefile b/test_apks/dyn_and_ref/Makefile index aec1dc7..1c8c2fb 100644 --- a/test_apks/dyn_and_ref/Makefile +++ b/test_apks/dyn_and_ref/Makefile @@ -34,10 +34,13 @@ debug: JAVAC_ARGS += -g debug: D8_ARGS += --debug debug: all -test: all grodd-venv +test: all #grodd-venv $(ADB) install build/$(APP).apk - $(ADB) shell am start -n $(PACKAGE)/.$(MAIN_ACTIVITY) - grodd-venv/bin/grodd-runner -d emulator-5554 -r grodd -t 900 -p $(PACKAGE) -s 0.5 + $(ADB) logcat -s THESEUS -c + python3 tests/test_apk.py + $(ADB) logcat -s THESEUS -d + #$(ADB) shell am start -n $(PACKAGE)/.$(MAIN_ACTIVITY) + #grodd-venv/bin/grodd-runner -d emulator-5554 -r grodd -t 900 -p $(PACKAGE) -s 0.5 build/%.v1signed.apk: ./build/%.unsigned.apk ./ToyKey.keystore $(JARSIGNER) -verbose -keystore ./ToyKey.keystore -storepass $(pass) -keypass $(pass) -signedjar $@ $< SignKey @@ -74,9 +77,9 @@ build/%.apk: ./build/%.v2aligned.apk ToyKey.keystore : $(KEYTOOL) -genkeypair -validity 1000 -dname "CN=SomeKey,O=SomeOne,C=FR" -keystore $@ -storepass $(pass) -keypass $(pass) -alias SignKey -keyalg RSA -v -grodd-venv: - python3 -m venv grodd-venv - grodd-venv/bin/pip install 'git+ssh://git@gitlab.inria.fr/CIDRE/malware/grodd-runner.git' +#grodd-venv: +# python3 -m venv grodd-venv +# grodd-venv/bin/pip install 'git+ssh://git@gitlab.inria.fr/CIDRE/malware/grodd-runner.git' clean: $(RM) -r build/* diff --git a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/APReflectee.java b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/APReflectee.java index 4dae25b..cadc028 100644 --- a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/APReflectee.java +++ b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/APReflectee.java @@ -1,6 +1,6 @@ package com.example.theseus.dynandref; -public class APReflectee { +public class APReflectee extends PCommonParent { public String extendedTransfer( boolean bool, byte by, diff --git a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/AReflectee.java b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/AReflectee.java index 13b609d..980091e 100644 --- a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/AReflectee.java +++ b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/AReflectee.java @@ -78,4 +78,23 @@ public class AReflectee extends APReflectee implements AIReflectee, ICommonInter } return getReflecteeId() + ":" + val + "(" + bool + " " + by + " " + sh + " " + ch + " " + in + " " + lo + " " + fl + " " + dou + " " + str + ")"; } + + public String commonParentTransfer( + boolean bool, + byte by, + short sh, + char ch, + int in, + long lo, + float fl, + double dou, + String str, + String... args + ) { + String val = ""; + for (String v : args) { + val += " " + v; + } + return getReflecteeId() + ":" + val + "(" + bool + " " + by + " " + sh + " " + ch + " " + in + " " + lo + " " + fl + " " + dou + " " + str + ")"; + } } diff --git a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/Collider.java b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/Collider.java index 2a895e2..0ae21eb 100644 --- a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/Collider.java +++ b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/Collider.java @@ -78,4 +78,23 @@ public class Collider extends PCollider implements ICollider, ICommonInterface { } return getColliderId() + ":" + val + "(" + bool + " " + by + " " + sh + " " + ch + " " + in + " " + lo + " " + fl + " " + dou + " " + str + ")"; } + + public String commonParentTransfer( + boolean bool, + byte by, + short sh, + char ch, + int in, + long lo, + float fl, + double dou, + String str, + String... args + ) { + String val = ""; + for (String v : args) { + val += " " + v; + } + return getColliderId() + ":" + val + "(" + bool + " " + by + " " + sh + " " + ch + " " + in + " " + lo + " " + fl + " " + dou + " " + str + ")"; + } } diff --git a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/PCollider.java b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/PCollider.java index 3f8ab2d..dd0586c 100644 --- a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/PCollider.java +++ b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/PCollider.java @@ -1,6 +1,6 @@ package com.example.theseus.dynandref; -public class PCollider { +public class PCollider extends PCommonParent{ public String extendedTransfer( boolean bool, byte by, diff --git a/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/PCommonParent.java b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/PCommonParent.java new file mode 100644 index 0000000..5ddca17 --- /dev/null +++ b/test_apks/dyn_and_ref/java/a/com/example/theseus/dynandref/PCommonParent.java @@ -0,0 +1,16 @@ +package com.example.theseus.dynandref; + +public class PCommonParent { + public String commonParentTransfer( + boolean bool, + byte by, + short sh, + char ch, + int in, + long lo, + float fl, + double dou, + String str, + String... args + ) {return "";} +} diff --git a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/Collider.java b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/Collider.java index 4405fa0..603f83b 100644 --- a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/Collider.java +++ b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/Collider.java @@ -78,4 +78,23 @@ public class Collider extends PCollider implements ICollider, ICommonInterface { } return getColliderId() + ":" + val + "(" + bool + " " + by + " " + sh + " " + ch + " " + in + " " + lo + " " + fl + " " + dou + " " + str + ")"; } + + public String commonParentTransfer( + boolean bool, + byte by, + short sh, + char ch, + int in, + long lo, + float fl, + double dou, + String str, + String... args + ) { + String val = ""; + for (String v : args) { + val += " " + v; + } + return getColliderId() + ":" + val + "(" + bool + " " + by + " " + sh + " " + ch + " " + in + " " + lo + " " + fl + " " + dou + " " + str + ")"; + } } diff --git a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/Main.java b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/Main.java index a0ff136..2ab6e38 100644 --- a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/Main.java +++ b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/Main.java @@ -31,6 +31,7 @@ public class Main { public static void run(Activity ac, String clname, boolean hasCollision, boolean hasParent, String methodType) { try { + Log.i("THESEUS", "clname: " + clname + ", hasCollision: " + hasCollision + ", hasParent: " + hasParent + ", methodType: " + methodType); ClassLoader cl; ClassLoader parent; if (hasParent) { @@ -163,8 +164,21 @@ public class Main { "", new String[] {"some", "strings"} ); - } else if (methodType.equals("Factory Pattern")) { - factory( + } else if (methodType.equals("Factory Pattern Interface")) { + factoryInterface( + ac, clz, + true, + (byte)42, + (short)666, + '*', + 0xDEAD_BEEF, + 0xD1AB011C_5EAF00DL, + 0.99f, + 3.1415926535897932384626433d, + new String[] {"some", "strings"} + ); + } else if (methodType.equals("Factory Pattern Extend")) { + factoryExtend( ac, clz, true, (byte)42, @@ -184,7 +198,7 @@ public class Main { } } - public static void factory( + public static void factoryInterface( Activity ac, Class clz, boolean bool, byte by, @@ -211,6 +225,33 @@ public class Main { ); Utils.sink(ac, res); } + public static void factoryExtend( + Activity ac, Class clz, + boolean bool, + byte by, + short sh, + char ch, + int in, + long lo, + float fl, + double dou, + String... args + ) throws Exception { + PCommonParent instance = (PCommonParent)clz.getDeclaredConstructor().newInstance(); + String res = instance.commonParentTransfer( + bool, + by, + sh, + ch, + in, + lo, + fl, + dou, + Utils.source(), + args + ); + Utils.sink(ac, res); + } public static void invoke( Activity ac, boolean instanciate, Class clz, Method mth, Object[] args, diff --git a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/MethodActivity.java b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/MethodActivity.java index b0318d9..1e7cb3b 100644 --- a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/MethodActivity.java +++ b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/MethodActivity.java @@ -103,6 +103,13 @@ public class MethodActivity extends Activity { linLayout.addView(b6); } + Button b7 = new Button(this); + b7.generateViewId(); + if (!classLoaderName.equals("DelegateLastClassLoader") && hasParent) { + // if no parent or use DelegateLastClassLoader, the type of the Interface is incompatible + linLayout.addView(b7); + } + scrollView.addView(linLayout); relLayout.addView(scrollView); setContentView(relLayout); @@ -149,18 +156,37 @@ public class MethodActivity extends Activity { } }); - b6.setText("Factory Pattern"); + b6.setText("Factory Pattern Interface"); b6.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { v.setBackgroundTintList(buttonColor); - Main.run(ac, classLoaderName, hasCollision, hasParent, "Factory Pattern"); + Main.run(ac, classLoaderName, hasCollision, hasParent, "Factory Pattern Interface"); } }); + + b7.setText("Factory Pattern Extend"); + b7.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + v.setBackgroundTintList(buttonColor); + Main.run(ac, classLoaderName, hasCollision, hasParent, "Factory Pattern Extend"); + } + }); + + // Allow to start Main.run from intent for automation + String methodType = intent.getStringExtra("methodType"); + if (methodType != null) { + Main.run(ac, classLoaderName, hasCollision, hasParent, methodType); + } } - public void nextActivity(String classLoaderName) { - Intent intent = new Intent(this, MethodActivity.class); - intent.putExtra("classLoaderName", classLoaderName); - startActivity(intent); + @Override + protected void onNewIntent(Intent intent) { + String classLoaderNameLocal = intent.getStringExtra("classLoaderName"); + boolean hasCollisionLocal = intent.getBooleanExtra("collision", false); + boolean hasParentLocal = intent.getBooleanExtra("parent", false); + String methodType = intent.getStringExtra("methodType"); + if (classLoaderNameLocal != null && methodType != null) { + Main.run(this, classLoaderNameLocal, hasCollisionLocal, hasParentLocal, methodType); + } } } diff --git a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/PCollider.java b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/PCollider.java index 16a6116..98119fe 100644 --- a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/PCollider.java +++ b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/PCollider.java @@ -1,6 +1,6 @@ package com.example.theseus.dynandref; -public class PCollider { +public class PCollider extends PCommonParent { public String extendedTransfer( boolean bool, byte by, diff --git a/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/PCommonParent.java b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/PCommonParent.java new file mode 100644 index 0000000..71c3fef --- /dev/null +++ b/test_apks/dyn_and_ref/java/classes/com/example/theseus/dynandref/PCommonParent.java @@ -0,0 +1,16 @@ +package com.example.theseus.dynandref; + +public class PCommonParent { + public String commonParentTransfer( + boolean bool, + byte by, + short sh, + char ch, + int in, + long lo, + float fl, + double dou, + String str, + String... args + ) {return "";} +} diff --git a/test_apks/dyn_and_ref/tests/expected_result.txt b/test_apks/dyn_and_ref/tests/expected_result.txt new file mode 100644 index 0000000..2cfdc17 --- /dev/null +++ b/test_apks/dyn_and_ref/tests/expected_result.txt @@ -0,0 +1,153 @@ +--------- beginning of main +clname: DelegateLastClassLoader, hasCollision: true, hasParent: true, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: true, hasParent: true, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: true, hasParent: true, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: true, hasParent: true, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: true, hasParent: false, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: true, hasParent: false, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: true, hasParent: false, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: true, hasParent: false, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: false, hasParent: true, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: false, hasParent: true, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: false, hasParent: true, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: false, hasParent: true, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: false, hasParent: false, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: false, hasParent: false, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: false, hasParent: false, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DelegateLastClassLoader, hasCollision: false, hasParent: false, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: true, methodType: Virtual +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: true, methodType: Static +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: true, methodType: Extended +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: true, methodType: Interface +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: true, methodType: Factory Pattern Interface +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: true, methodType: Factory Pattern Extend +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: false, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: false, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: false, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: true, hasParent: false, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: true, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: true, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: true, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: true, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: true, methodType: Factory Pattern Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: true, methodType: Factory Pattern Extend +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: false, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: false, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: false, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: DexClassLoader, hasCollision: false, hasParent: false, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: true, methodType: Virtual +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: true, methodType: Static +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: true, methodType: Extended +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: true, methodType: Interface +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: true, methodType: Factory Pattern Interface +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: true, methodType: Factory Pattern Extend +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: false, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: false, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: false, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: true, hasParent: false, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: true, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: true, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: true, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: true, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: true, methodType: Factory Pattern Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: true, methodType: Factory Pattern Extend +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: false, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: false, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: false, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: InMemoryDexClassLoader, hasCollision: false, hasParent: false, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: true, methodType: Virtual +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: true, methodType: Static +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: true, methodType: Extended +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: true, methodType: Interface +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: true, methodType: Factory Pattern Interface +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: true, methodType: Factory Pattern Extend +POPUP, title: Data leak:, msg: MainAPK: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: false, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: false, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: false, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: true, hasParent: false, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: true, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: true, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: true, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: true, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: true, methodType: Factory Pattern Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: true, methodType: Factory Pattern Extend +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: false, methodType: Virtual +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: false, methodType: Static +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: false, methodType: Extended +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) +clname: PathClassLoader, hasCollision: false, hasParent: false, methodType: Interface +POPUP, title: Data leak:, msg: A: some strings(true 42 666 * -559038737 944260662268981261 0.99 3.141592653589793 Secret) diff --git a/test_apks/dyn_and_ref/tests/test_apk.py b/test_apks/dyn_and_ref/tests/test_apk.py new file mode 100644 index 0000000..6c254e1 --- /dev/null +++ b/test_apks/dyn_and_ref/tests/test_apk.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import time +import subprocess +import os + + +def get_adb() -> str | Path: + if "ANDROID_HOME" in os.environ: + sdk_path = Path(os.environ["ANDROID_HOME"]) + else: + sdk_path = Path.home() / "Android" / "Sdk" + if not sdk_path.exists(): + return "adb" + adb_path = sdk_path / "platform-tools" / "adb" + if adb_path.exists(): + return adb_path + else: + return "adb" + + +def start_activity( + adb: str | Path, + activity: str, + str_extra: dict[str, str], + bool_extra: dict[str, bool], +): + str_extra_args = [ + c for k, v in str_extra.items() for c in ("--es", k, v.replace(" ", "\\ ")) + ] + bool_extra_args = [ + c for k, v in bool_extra.items() for c in ("--ez", k, "true" if v else "false") + ] + print( + " ".join( + [ + str(adb), + "shell", + "am", + "start-activity", + "-n", + activity, + *str_extra_args, + *bool_extra_args, + ] + ) + ) + subprocess.Popen( + [ + adb, + "shell", + "am", + "start-activity", + "-n", + activity, + *str_extra_args, + *bool_extra_args, + ] + ) + + +def kill_app(adb: str | Path, app_id: str): + subprocess.Popen([adb, "shell", "am", "force-stop", app_id]) + + +def clear_log(adb: str | Path): + subprocess.Popen([adb, "logcat", "-c"]) + + +def get_log_proc(adb: str | Path, tag: str) -> subprocess.Popen: + return subprocess.Popen( + [adb, "logcat", "-s", tag, "--format=raw"], + encoding="utf-8", + stdout=subprocess.PIPE, + ) + + +def wait_for_tst_log( + logs: subprocess.Popen, + clname: str, + hasCollision: bool, + hasParent: bool, + methodType: str, +): + hasCollision_p = "true" if hasCollision else "false" + hasParent_p = "true" if hasParent else "false" + first_line_found = False + assert logs.stdout is not None + for line in logs.stdout: + # print(f"= {line}") + # print(f"= {first_line_found=}") + if first_line_found and line.startswith("POPUP,"): + return + if not first_line_found and ( + f"clname: {clname}," in line + and f"hasCollision: {hasCollision_p}," in line + and f"hasParent: {hasParent_p}," + and f"methodType: {methodType}" in line + ): + first_line_found = True + + +CLASS_LOADERS = [ + "DelegateLastClassLoader", + "DexClassLoader", + "InMemoryDexClassLoader", + "PathClassLoader", +] +METHOD_TYPES = [ + "Virtual", + "Static", + "Extended", + "Interface", + # "Interface Static", + "Factory Pattern Interface", + "Factory Pattern Extend", +] +COLLISION_OPT = [True, False] +PARENT_OPT = [True, False] + + +def main(): + adb = get_adb() + clear_log(adb) + logs = get_log_proc(adb, "THESEUS") + for clname in CLASS_LOADERS: + for hasCollision in COLLISION_OPT: + for hasParent in PARENT_OPT: + for methodType in METHOD_TYPES: + if ( + clname == "DelegateLastClassLoader" + and "Factory Pattern" in methodType + ): + continue + if not hasParent and "Factory Pattern" in methodType: + continue + start_activity( + adb, + "com.example.theseus.dynandref/.MethodActivity", + { + "classLoaderName": clname, + "methodType": methodType, + }, + {"collision": hasCollision, "parent": hasParent}, + ) + wait_for_tst_log( + logs, + clname, + hasCollision, + hasParent, + methodType, + ) + # kill_app(adb, "com.example.theseus.dynandref") + # time.sleep(0.2) + # save result afterward: + # adb logcat -s THESEUS -d --format=raw > expected_result.txt + + +if __name__ == "__main__": + main()