11package de.binarynoise.classHunter
22
3+ import java.io.File
34import java.net.URLClassLoader
45import java.security.SecureClassLoader
56import android.os.Build
@@ -10,15 +11,18 @@ import dalvik.system.DexClassLoader
1011import dalvik.system.InMemoryDexClassLoader
1112import dalvik.system.PathClassLoader
1213import de.binarynoise.ClassHunter.BuildConfig
14+ import de.binarynoise.logger.Logger.log
15+ import de.binarynoise.reflection.cast
1316import de.robv.android.xposed.IXposedHookLoadPackage
17+ import de.robv.android.xposed.IXposedHookZygoteInit
1418import de.robv.android.xposed.XposedBridge
1519import de.robv.android.xposed.XposedHelpers
1620import de.robv.android.xposed.callbacks.XC_LoadPackage
1721import de.robv.android.xposed.XC_MethodHook as MethodHook
1822
1923const val TAG = " Hook"
2024
21- class Hook : IXposedHookLoadPackage {
25+ class Hook : IXposedHookLoadPackage , IXposedHookZygoteInit {
2226
2327 override fun handleLoadPackage (lpparam : XC_LoadPackage .LoadPackageParam ) {
2428 Log .d(TAG , " handleLoadPackage: ${lpparam.packageName} " )
@@ -36,14 +40,35 @@ class Hook : IXposedHookLoadPackage {
3640 override fun afterHookedMethod (param : MethodHookParam ) {
3741 with (param) {
3842 val cls = result as ? Class <* >? ? : return
39- if (! cls.isAssignableFrom( ClassLoader ::class .java)) return
43+ if (! ClassLoader ::class .java.isAssignableFrom(cls )) return
4044 Log .i(TAG , " loadClass afterHookedMethod: loaded new classLoader class: ${cls.name} " )
4145 }
4246 }
4347 })
4448
4549 // //////////////////////////////////////////////////////////////////////////////////////////////////
4650
51+ try {
52+ val SystemServerClassLoaderFactoryClass = XposedHelpers .findClass(" com.android.internal.os.SystemServerClassLoaderFactory" , null )
53+ val sLoadedPaths: Map <String , PathClassLoader > =
54+ XposedHelpers .getStaticObjectField(SystemServerClassLoaderFactoryClass , " sLoadedPaths" ).cast()
55+ Log .v(TAG , " sLoadedPaths:" )
56+ sLoadedPaths.forEach { (path, loader) ->
57+ Log .v(TAG , " sLoadedPaths: $path -> ${loader.toObjectString()} " )
58+ tryFindClass(loader, " SystemServerClassLoaderFactory" , lpparam.packageName)
59+ }
60+ } catch (_: NoSuchMethodError ) {
61+ } catch (_: NoSuchMethodException ) {
62+ } catch (_: XposedHelpers .ClassNotFoundError ) {
63+ } catch (_: ClassNotFoundException ) {
64+ } catch (e: Exception ) {
65+ log(" failed to hook" , e)
66+ }
67+ }
68+
69+ override fun initZygote (startupParam : IXposedHookZygoteInit .StartupParam ) {
70+ val packageName = File (" /proc/self/cmdline" ).readText().replace(0 .toChar(), ' ' )
71+
4772 @Suppress(" RemoveExplicitTypeArguments" ) //
4873 val classLoaderClasses = mutableSetOf<Class <out ClassLoader >>(
4974 ClassLoader ::class .java,
@@ -61,8 +86,7 @@ class Hook : IXposedHookLoadPackage {
6186 }
6287
6388 try {
64- @Suppress(" UNCHECKED_CAST" ) //
65- classLoaderClasses.add(Class .forName(" android.app.LoadedApk\$ WarningContextClassLoader" , false , null ) as Class <out ClassLoader >)
89+ classLoaderClasses.add(Class .forName(" android.app.LoadedApk\$ WarningContextClassLoader" , false , null ).cast())
6690 } catch (_: Throwable ) {
6791 }
6892
@@ -88,12 +112,13 @@ class Hook : IXposedHookLoadPackage {
88112 " dalvik.system.PathClassLoader[null]" ,
89113 " dalvik.system.PathClassLoader[DexPathList[[],nativeLibraryDirectories=[/system/lib64, /system_ext/lib64]]]" ,
90114 " LspModuleClassLoader[instantiating]" ,
115+ """ dalvik.system.PathClassLoader[DexPathList[[directory "/proc/self/task"],nativeLibraryDirectories=[/system/lib64, /system_ext/lib64]]]""" ,
91116 )
92117 if (string !in ignored) {
93118 Log .v(TAG , " ClassLoader constructor: created new classLoader: ${newClassLoader.toObjectString()} $string " )
94119 }
95120
96- tryFindClass(newClassLoader, " constructor" , lpparam. packageName)
121+ tryFindClass(newClassLoader, " constructor" , packageName)
97122
98123 }
99124 }
@@ -107,6 +132,21 @@ class Hook : IXposedHookLoadPackage {
107132 }
108133 }
109134
135+ val prefixes = arrayOf(
136+ " android.net.connectivity" ,
137+ " android.net.http.internal" ,
138+ " com.android.captiveportallogin" ,
139+ " com.android.networkstack" ,
140+ " com.android.server.nearby" ,
141+ " com.android.server.remoteauth" ,
142+ " gfxstream_vk" ,
143+ " lvp" ,
144+ " vk_cmd_enqueue" ,
145+ " vk_cmd_enqueue_unless_primary" ,
146+ " vk_common" ,
147+ " wsi" ,
148+ )
149+
110150 fun tryFindClass (classLoader : ClassLoader , classLoaderName : String , packageName : String ) {
111151 BuildConfig .targetClass.forEach { className ->
112152 var cls: Class <* >? = null
@@ -115,12 +155,20 @@ class Hook : IXposedHookLoadPackage {
115155 var successClassLoader: ClassLoader ? = null
116156 var i = 0
117157
118- while (classLoader != null && i++ < 10 ) {
158+ loop@ while (classLoader != null && i++ < 10 ) {
119159 try {
120160 cls = Class .forName(className, false , classLoader)
121161 successClassLoader = classLoader
162+ break @loop
122163 } catch (_: Throwable ) {
123- break
164+ }
165+ prefixes.forEach { prefix ->
166+ try {
167+ cls = Class .forName(" $prefix .$className " , false , classLoader)
168+ successClassLoader = classLoader
169+ break @loop
170+ } catch (_: Throwable ) {
171+ }
124172 }
125173 classLoader = classLoader.parent
126174 }
@@ -131,29 +179,24 @@ class Hook : IXposedHookLoadPackage {
131179 }
132180 }
133181
134- private fun logClass (cls : Class <* >, classLoaderName : String , classLoader : ClassLoader , packageName : String ) {
182+ private fun logClass (cls : Class <* >, classLoaderName : String , classLoader : ClassLoader , packageName : String , dump : Boolean = true ) {
135183 val lines = mutableListOf<String >()
136184 lines.add(" *" .repeat(150 ))
137185
138186 lines.add(" found class: ${cls.name} in package $packageName by $classLoaderName : ${classLoader.toObjectString()} - $classLoader " )
139-
140- lines.add(" - constructors:" )
141- cls.declaredConstructors.map { c -> " ${c.name} (${c.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" }
142- .sorted()
143- .forEach { c ->
144- lines.add(" - $c " )
145- }
146-
147- lines.add(" - methods:" )
148- cls.declaredMethods.map { m -> " ${m.returnType.name} ${m.name} (${m.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" }
149- .sorted()
150- .forEach { m ->
151- lines.add(" - $m " )
152- }
153-
154- lines.add(" - fields:" )
155- cls.declaredFields.map { f -> " ${f.type.name} ${f.name} " }.sorted().forEach { f ->
156- lines.add(" - $f " )
187+ if (dump) {
188+ lines.add(" - constructors:" )
189+ cls.declaredConstructors.map { c -> " ${c.name} (${c.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" }
190+ .sorted()
191+ .forEach { c -> lines.add(" - $c " ) }
192+
193+ lines.add(" - methods:" )
194+ cls.declaredMethods.map { m -> " ${m.returnType.name} ${m.name} (${m.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" }
195+ .sorted()
196+ .forEach { m -> lines.add(" - $m " ) }
197+
198+ lines.add(" - fields:" )
199+ cls.declaredFields.map { f -> " ${f.type.name} ${f.name} " }.sorted().forEach { f -> lines.add(" - $f " ) }
157200 }
158201
159202 lines.forEach {
@@ -164,5 +207,5 @@ class Hook : IXposedHookLoadPackage {
164207
165208fun Any?.toObjectString (): String {
166209 if (this == null ) return " null"
167- return this ::class .simpleName + " @" + Integer .toHexString(hashCode())
210+ return this ::class .simpleName + " @" + Integer .toHexString(hashCode()).padStart( 8 , ' 0 ' )
168211}
0 commit comments