From aece524564a13091207f7ddf0f34beead0fc89e7 Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Mon, 8 Sep 2025 14:05:43 +0200 Subject: [PATCH] demo app --- test_apks/simple_demo/.gitignore | 3 + test_apks/simple_demo/AndroidManifest.xml | 21 +++++ test_apks/simple_demo/Makefile | 77 +++++++++++++++++++ .../classes/com/example/theseus/Main.java | 54 +++++++++++++ .../com/example/theseus/MainActivity.java | 20 +++++ .../classes/com/example/theseus/Utils.java | 26 +++++++ .../inline/com/example/theseus/Malicious.java | 13 ++++ 7 files changed, 214 insertions(+) create mode 100644 test_apks/simple_demo/.gitignore create mode 100644 test_apks/simple_demo/AndroidManifest.xml create mode 100644 test_apks/simple_demo/Makefile create mode 100644 test_apks/simple_demo/java/classes/com/example/theseus/Main.java create mode 100644 test_apks/simple_demo/java/classes/com/example/theseus/MainActivity.java create mode 100644 test_apks/simple_demo/java/classes/com/example/theseus/Utils.java create mode 100644 test_apks/simple_demo/java/inline/com/example/theseus/Malicious.java diff --git a/test_apks/simple_demo/.gitignore b/test_apks/simple_demo/.gitignore new file mode 100644 index 0000000..de18d4e --- /dev/null +++ b/test_apks/simple_demo/.gitignore @@ -0,0 +1,3 @@ +build +ToyKey.keystore +java/classes/com/example/theseus/reflection/R.java diff --git a/test_apks/simple_demo/AndroidManifest.xml b/test_apks/simple_demo/AndroidManifest.xml new file mode 100644 index 0000000..d01d880 --- /dev/null +++ b/test_apks/simple_demo/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/test_apks/simple_demo/Makefile b/test_apks/simple_demo/Makefile new file mode 100644 index 0000000..882da1a --- /dev/null +++ b/test_apks/simple_demo/Makefile @@ -0,0 +1,77 @@ +VERSION=34.0.0 +SDK_TOOLS=$(HOME)/Android/Sdk +JAVA_PATH=/usr/lib/jvm/java-17-openjdk/bin +JAVAC=/usr/lib/jvm/java-17-openjdk/bin/javac +JAR=/usr/lib/jvm/java-17-openjdk/bin/jar +PYTHON=python3 +APP=tests + +PACKAGE=com.example.theseus +MAIN_ACTIVITY=MainActivity + +JAVAC_ARGS = +D8_ARGS = + + +VERSION_B=$(basename $(basename $(VERSION))) + +pass=ahahah + +export PATH := $(JAVA_PATH):$(PATH) + +all: $(shell mkdir -p build) +all: clean build/$(APP).apk +signature_v1: clean build/$(APP).v1.apk + +debug: JAVAC_ARGS += -g +debug: D8_ARGS += --debug +debug: all + +test: all + adb install build/$(APP).apk + adb shell am start -n $(PACKAGE)/.$(MAIN_ACTIVITY) + +build/%.v1signed.apk: ./build/%.unsigned.apk ./ToyKey.keystore + jarsigner -verbose -keystore ./ToyKey.keystore -storepass $(pass) -keypass $(pass) -signedjar $@ $< SignKey + +build/%.v1.apk: ./build/%.v1signed.apk + $(SDK_TOOLS)/build-tools/$(VERSION)/zipalign -v -f 4 $< $@ + +build/deps.jar: $(shell find java/ -type f -regex ".*\.java" ) + mkdir -p ./build/jar/ + $(JAVAC) -d ./build/jar/ -classpath $(SDK_TOOLS)/platforms/android-$(VERSION_B)/android.jar $$(find java -type f -regex ".*\.java") + $(JAR) cvf build/deps.jar -C build/jar/ . + +# TODO: fix dep somehow? cannot find a way to use % or $* in (shell ..) +build/%/classes: build/deps.jar $(shell find java/ -type f -regex ".*\.java" ) + mkdir -p ./build/$*/classes + $(JAVAC) $(JAVAC_ARGS) -d ./build/$*/classes -classpath build/deps.jar:$(SDK_TOOLS)/platforms/android-$(VERSION_B)/android.jar $$(find java/$*/ -type f -regex ".*\.java") + +build/classes/classes: build/deps.jar build/inline/classes.dex $(shell find java/ -type f -regex ".*\.java" ) + mkdir -p ./build/classes/classes + sed -i "s# private static final String DEX =.*# private static final String DEX = \"$$(base64 -w 0 build/inline/classes.dex)\";#" java/classes/com/example/theseus/Main.java + $(JAVAC) $(JAVAC_ARGS) -d ./build/classes/classes -classpath build/deps.jar:$(SDK_TOOLS)/platforms/android-$(VERSION_B)/android.jar $$(find java/$*/ -type f -regex ".*\.java") + +build/%/classes.dex: build/%/classes + mkdir -p ./build/$* + $(SDK_TOOLS)/build-tools/$(VERSION)/d8 $(D8_ARGS) --classpath $(SDK_TOOLS)/platforms/android-$(VERSION_B)/android.jar $(shell find build/$*/classes -type f -regex ".*\.class" -printf "'%p'\n") --output ./build/$*/ + +build/%.unsigned.apk: build/classes/classes.dex + mkdir -p ./build/$*_files + mv ./build/classes/classes.dex ./build/$*_files/classes.dex + $(SDK_TOOLS)/build-tools/$(VERSION)/aapt package -v -f -M ./AndroidManifest.xml -I $(SDK_TOOLS)/platforms/android-$(VERSION_B)/android.jar -F $@ ./build/$*_files + +build/%.v2aligned.apk: ./build/%.unsigned.apk ./ToyKey.keystore + $(SDK_TOOLS)/build-tools/$(VERSION)/zipalign -v -f 4 $< $@ + +build/%.apk: ./build/%.v2aligned.apk + $(SDK_TOOLS)/build-tools/$(VERSION)/apksigner sign -ks ./ToyKey.keystore --v2-signing-enabled true --in $< --out $@ --ks-pass pass:$(pass) + +ToyKey.keystore : + keytool -genkeypair -validity 1000 -dname "CN=SomeKey,O=SomeOne,C=FR" -keystore $@ -storepass $(pass) -keypass $(pass) -alias SignKey -keyalg RSA -v + +clean: + $(RM) -r build/* + +clean_all: clean + $(RM) ToyKey.keystore diff --git a/test_apks/simple_demo/java/classes/com/example/theseus/Main.java b/test_apks/simple_demo/java/classes/com/example/theseus/Main.java new file mode 100644 index 0000000..d78b57e --- /dev/null +++ b/test_apks/simple_demo/java/classes/com/example/theseus/Main.java @@ -0,0 +1,54 @@ +package com.example.theseus; + +import android.app.Activity; +import android.util.Base64; +import android.util.Log; +import dalvik.system.InMemoryDexClassLoader; +import java.lang.Class; +import java.lang.ClassLoader; +import java.nio.ByteBuffer; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.security.Key; + +public class Main { + + private static final String DEX = "ZGV4CjAzNQAvtfp88wvPHZi+B2FO1HZ02SatJfZGyA94BAAAcAAAAHhWNBIAAAAAAAAAANgDAAAVAAAAcAAAAAcAAADEAAAABQAAAOAAAAAAAAAAAAAAAAgAAAAcAQAAAQAAAFwBAAD8AgAAfAEAACACAAAoAgAAKwIAAC8CAAA0AgAATAIAAG0CAACKAgAAngIAALICAADNAgAA3QIAAOoCAADtAgAA8gIAAPUCAAD9AgAABwMAABIDAAAYAwAAIgMAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAwAAAABAAAABAAAAAAAAAADAAAABAAAAAgCAAACAAAABQAAABACAAAMAAAABgAAAAAAAAANAAAABgAAABgCAAABAAMAAAAAAAEAAQAQAAAAAQABABEAAAACAAQAEgAAAAMAAwAAAAAABQADAAAAAAAFAAIADwAAAAUAAAATAAAAAQAAAAEAAAADAAAAAAAAAAoAAAAAAAAAwAMAAAAAAAADAAIAAgAAAPQBAAAaAAAAIgIFAHAQBQACABoACwBuIAYAAgAMAm4gBgASAAwBGgIOAG4gBgAhAAwBbhAHAAEADAERAQIAAgACAAAA+gEAAAUAAABxIAMAAQASABEAAAABAAEAAQAAAAECAAAEAAAAcBAEAAAADgAGAgAADgAKAgAADjwABAAOAAAAAAIAAAAEAAAAAQAAAAQAAAACAAAAAAAEAAY8aW5pdD4AAUwAAkxMAANMTEwAFkxhbmRyb2lkL2FwcC9BY3Rpdml0eTsAH0xjb20vZXhhbXBsZS90aGVzZXVzL01hbGljaW91czsAG0xjb20vZXhhbXBsZS90aGVzZXVzL1V0aWxzOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsADk1hbGljaW91cy5qYXZhAAtTZWNyZXREYXRhWwABVgADVkxMAAFdAAZhcHBlbmQACGdldF9kYXRhAAlzZW5kX2RhdGEABHNpbmsACHRvU3RyaW5nAJsBfn5EOHsiYmFja2VuZCI6ImRleCIsImNvbXBpbGF0aW9uLW1vZGUiOiJkZWJ1ZyIsImhhcy1jaGVja3N1bXMiOmZhbHNlLCJtaW4tYXBpIjoxLCJzaGEtMSI6ImZhY2VkZjQxYmJkMjhiNTYzZDFlOWUwOWM1ZjcyZDdjNWNhNTk4ZDUiLCJ2ZXJzaW9uIjoiOC4yLjItZGV2In0AAAADAACBgATcAwEJ/AIBCcADAAAAAAAADQAAAAAAAAABAAAAAAAAAAEAAAAVAAAAcAAAAAIAAAAHAAAAxAAAAAMAAAAFAAAA4AAAAAUAAAAIAAAAHAEAAAYAAAABAAAAXAEAAAEgAAADAAAAfAEAAAMgAAADAAAA9AEAAAEQAAADAAAACAIAAAIgAAAVAAAAIAIAAAAgAAABAAAAwAMAAAMQAAABAAAA1AMAAAAQAAABAAAA2AMAAA=="; + private Key key; + ClassLoader cl; + Activity ac; + + + public Main(Activity ac) throws Exception { + this.key = new SecretKeySpec("_-_Secret Key_-_".getBytes(), "AES"); + this.ac = ac; + byte[] bytes = Base64.decode(DEX, Base64.NO_WRAP); + this.cl = new InMemoryDexClassLoader(ByteBuffer.wrap(bytes), Main.class.getClassLoader()); + } + + public void main() throws Exception { + String[] methods = {"n6WGYJzjDrUvR9cYljlNlw==", "dapES0wl/iFIPuMnH3fh7g=="}; + Class cls = cl.loadClass(decrypt("W5f3xRf3wCSYcYG7ckYGR5xuuESDZ2NcDUzGxsq3sls=")); + + Object val = "imei"; + + for (String method : methods) { + val = cls.getMethod(decrypt(method), String.class, Activity.class).invoke(null, val, ac); + } + } + + public String encrypt(String s) throws Exception { + Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");// Doubious choise of encryption but it's just a demo + c.init(Cipher.ENCRYPT_MODE, key); + byte[] cpt = c.doFinal(s.getBytes()); + return Base64.encodeToString(cpt, Base64.NO_WRAP); + } + + public String decrypt(String s) throws Exception { + Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");// Doubious choise of encryption but it's just a demo + c.init(Cipher.DECRYPT_MODE, key); + byte[] clt = c.doFinal(Base64.decode(s, Base64.NO_WRAP)); + return new String(clt); + } +} diff --git a/test_apks/simple_demo/java/classes/com/example/theseus/MainActivity.java b/test_apks/simple_demo/java/classes/com/example/theseus/MainActivity.java new file mode 100644 index 0000000..a931f5d --- /dev/null +++ b/test_apks/simple_demo/java/classes/com/example/theseus/MainActivity.java @@ -0,0 +1,20 @@ +package com.example.theseus; + +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; + +public class MainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + try { + Main main = new Main(this); + main.main(); + } catch (Exception e) { + Log.i("THESEUS", "Error", e); + } + } +} diff --git a/test_apks/simple_demo/java/classes/com/example/theseus/Utils.java b/test_apks/simple_demo/java/classes/com/example/theseus/Utils.java new file mode 100644 index 0000000..0c8ca2a --- /dev/null +++ b/test_apks/simple_demo/java/classes/com/example/theseus/Utils.java @@ -0,0 +1,26 @@ +package com.example.theseus; + +import android.app.Activity; +import android.app.AlertDialog; + + +public class Utils { + public static String source() { + return "Secret"; + } + public static String source(String tag) { + return "[" + tag + "] Secret"; + } + + public static void popup(Activity ac, String title, String msg) { + (new AlertDialog.Builder(ac)) + .setMessage(msg) + .setTitle(title) + .create() + .show(); + } + + public static void sink(Activity ac, String data) { + popup(ac, "Data leak:", data); + } +} diff --git a/test_apks/simple_demo/java/inline/com/example/theseus/Malicious.java b/test_apks/simple_demo/java/inline/com/example/theseus/Malicious.java new file mode 100644 index 0000000..3ccc67a --- /dev/null +++ b/test_apks/simple_demo/java/inline/com/example/theseus/Malicious.java @@ -0,0 +1,13 @@ +package com.example.theseus; +import android.app.Activity; + +public class Malicious { + public static String get_data(String data, Activity ac) { + return "SecretData[" + data + "]"; + } + + public static String send_data(String data, Activity ac) { + Utils.sink(ac, data); + return null; + } +}