11package de.binarynoise.classHunter
22
3+ import java.security.SecureClassLoader
4+ import android.os.Build
35import android.util.Log
6+ import dalvik.system.BaseDexClassLoader
7+ import dalvik.system.DelegateLastClassLoader
8+ import dalvik.system.PathClassLoader
49import de.binarynoise.ClassHunter.BuildConfig
510import de.robv.android.xposed.IXposedHookLoadPackage
11+ import de.robv.android.xposed.IXposedHookZygoteInit
12+ import de.robv.android.xposed.XposedBridge
613import de.robv.android.xposed.callbacks.XC_LoadPackage
14+ import de.robv.android.xposed.XC_MethodHook as MethodHook
715
816const val TAG = " Hook"
917
10- class Hook : IXposedHookLoadPackage {
18+ class Hook : IXposedHookLoadPackage , IXposedHookZygoteInit {
1119 override fun handleLoadPackage (lpparam : XC_LoadPackage .LoadPackageParam ) {
1220 Log .i(TAG , " *" .repeat(50 ))
1321 Log .i(TAG , " loading package: ${lpparam.packageName} " )
@@ -34,16 +42,25 @@ class Hook : IXposedHookLoadPackage {
3442 BuildConfig .targetClass.forEach { className ->
3543 try {
3644 val cls = Class .forName(className, false , it)
37- Log .i(TAG , " - found class: ${cls.name} in package ${lpparam.packageName} by $it " )
45+ Log .i(TAG , " - found class: ${cls.name} in package ${lpparam.packageName} by ${it.toObjectString()} " )
46+
47+ Log .i(TAG , " - constructors:" )
48+ cls.declaredConstructors.map { c -> " ${c.name} (${c.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" }
49+ .sorted()
50+ .forEach { c ->
51+ Log .v(TAG , " - $it " )
52+ }
3853
3954 Log .i(TAG , " - methods:" )
40- cls.declaredMethods.forEach { m ->
41- Log .v(TAG , " - ${m.returnType.name} ${m.name} (${m.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" )
42- }
55+ cls.declaredMethods.map { m -> " ${m.returnType.name} ${m.name} (${m.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" }
56+ .sorted()
57+ .forEach { m ->
58+ Log .v(TAG , " - $it " )
59+ }
4360
4461 Log .i(TAG , " - fields:" )
45- cls.declaredFields.forEach { f ->
46- Log .v(TAG , " - ${f.type.name} ${f.name} " )
62+ cls.declaredFields.map { f -> " ${f.type.name} ${f.name} " }.sorted(). forEach { f ->
63+ Log .v(TAG , " - $it " )
4764 }
4865 } catch (_: Throwable ) {
4966 }
@@ -52,9 +69,69 @@ class Hook : IXposedHookLoadPackage {
5269 }
5370
5471 private fun collectParents (classLoader : ClassLoader , name : String , classLoaders : MutableSet <ClassLoader >) {
55- generateSequence(classLoader) { it.parent }.forEach {
72+ classLoaders.addAll( generateSequence(classLoader) { it.parent }.onEach {
5673 Log .v(TAG , name + " - ${it.toObjectString()} " )
57- classLoaders.add(it)
74+ })
75+ }
76+
77+ override fun initZygote (startupParam : IXposedHookZygoteInit .StartupParam ) {
78+ val classLoaderClasses = mutableSetOf<Class <* >>(
79+ ClassLoader ::class .java,
80+ SecureClassLoader ::class .java,
81+ // URLClassLoader::class.java,
82+ BaseDexClassLoader ::class .java,
83+ // PathClassLoader::class.java,
84+ // InMemoryDexClassLoader::class.java,
85+ // DexClassLoader::class.java,
86+ ClassLoader .getSystemClassLoader()::class .java, // BootClassLoader
87+ )
88+
89+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O_MR1 ) {
90+ classLoaderClasses.add(DelegateLastClassLoader ::class .java)
91+ }
92+
93+ try {
94+ classLoaderClasses.add(Class .forName(" android.app.LoadedApk\$ WarningContextClassLoader" , false , null ))
95+ } catch (_: Throwable ) {
96+ }
97+
98+ val targetClassesShortName = BuildConfig .targetClass.map { it.substringAfterLast(" ." ) }.toSet()
99+
100+ classLoaderClasses.forEach {
101+ val loadClassHook = object : MethodHook () {
102+ override fun afterHookedMethod (param : MethodHookParam ) {
103+ val cls = param.result as ? Class <* > ? : return
104+
105+ if (cls.name.substringAfterLast(" ." ) in targetClassesShortName) {
106+ Log .i(TAG , " Maybe found class: ${cls.name} by ${param.thisObject.toObjectString()} " )
107+ }
108+ }
109+ }
110+ var loadNewClassloaderHook: MethodHook ? = null
111+ loadNewClassloaderHook = object : MethodHook () {
112+ override fun afterHookedMethod (param : MethodHookParam ) {
113+ if (param.thisObject !is PathClassLoader ) {
114+ Log .v(TAG , " Created a new ClassLoader: ${param.thisObject.toObjectString()} ${param.thisObject} " )
115+ }
116+
117+ val cls: Class <* > = param.thisObject::class .java
118+ if (cls !in classLoaderClasses) {
119+ Log .i(TAG , " Found a new ClassLoader class: ${cls} , created by ${cls.classLoader} " )
120+ }
121+ try {
122+
123+ XposedBridge .hookAllConstructors(it, loadNewClassloaderHook)
124+ XposedBridge .hookAllMethods(it, " loadClass" , loadClassHook)
125+ } catch (_: Throwable ) {
126+ }
127+ }
128+ }
129+
130+ try {
131+ XposedBridge .hookAllConstructors(it, loadNewClassloaderHook)
132+ XposedBridge .hookAllMethods(it, " loadClass" , loadClassHook)
133+ } catch (_: Throwable ) {
134+ }
58135 }
59136 }
60137}
0 commit comments