CLONE ENGINE COMPARISON - CMasterCloner (apktool) vs DoubleCloner
Analysis only. Verified from smali + Kotlin source, not markdown.
WHAT THEIRS ACTUALLY DOES
The host is a real Activity (RouterActivity -> m1 -> oOOO00 -> fg -> AppCompat).
The cloned app is NOT an Android Activity: it is an o10 object (extends Object).
m1.OooOoO() gets android.R.id.content (0x1020002), creates the o10, and
o10.OooOoOO(inflater, parent) returns a View placed into the host's content view.
No ActivityThread, no newActivity, no attach, no makeVisible.
The native .so is the code engine, not the window.
Only 7 classes override that view method, so it supports a limited set of apps.
7-ITEM COMPARISON
1) How the cloned activity starts - DIFFERENT - ~15% match
Theirs: RouterActivity.smali, m1.smali, o10.smali
Ours: CloneActivity.kt, CloneRunner.kt
2) Instrumentation / ActivityThread hook - DIFFERENT - ~10% match
Theirs: o0OO00o0.smali, ao0.smali (no ActivityThread hook)
Ours: SandboxActivityThreadHook.kt, SandboxInstrumentationInjector.kt,
SandboxLaunchTransactionSwap.kt
3) Class loader for the clone's APK - DIFFERENT - ~20% match
Theirs: o63.smali, wq.smali, o0000O0.smali (loads its own engine payload)
Ours: CloneClassLoader.kt (loads the target APK)
4) Resources / Context / Application - PARTIAL - ~50% match
Theirs: o10.smali, App.smali, oOO0OO.smali
Ours: CloneContext.kt, CloneApplicationInfo.kt, CloneComponentHost.kt
5) Window and view attachment - DIFFERENT - ~10% match
Theirs: m1.smali, o10.smali:2200, RouterActivity.smali
Ours: CloneRunner.kt (reveal), CloneActivity.kt
6) Process slot mapping - SAME - ~70% match
Theirs: manifest FIEL$A*, FIEL$A0.smali, k20.smali
Ours: ProxyHosts.kt, SandboxProxyActivity.kt, SandboxEngineOrchestrator.kt
7) Lifecycle (resume/pause/back/kick-out) - PARTIAL - ~25% match
Theirs: vz1.smali, m1.smali, o10.smali
Ours: CloneRunner.kt, CloneActivity.kt, SandboxClientTransactionReplayer.kt
FINAL ACTION TABLE
1. Activity start | DIFFERENT | Replace (real host Activity + target View)
2. Instrumentation/Thread | DIFFERENT | Replace (workaround for item 1)
3. Class loader | DIFFERENT | Keep (ours is correct for arbitrary APKs)
4. Resources/Context/App | PARTIAL | Keep + Fix
5. Window and view attach | DIFFERENT | Replace (root cause)
6. Process slot mapping | SAME | Keep
7. Lifecycle | PARTIAL | Fix (real host lifecycle, not manual replay)
TOTAL: about 72% of our manual attach is NOT the same as theirs.
WHITE SCREEN: item 5. Ours creates a second Activity window and tries to attach it.
Theirs uses the host's real window and puts a View inside it. When the manual attach
fails, the host window stays empty and white.
KICK-OUTS: item 7, triggered by item 5. There is no real activity record, so when the
target's lifecycle or onCreate fails, the process dies and you are thrown out.