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,23 @@ class Hook : IXposedHookLoadPackage {
107132 }
108133 }
109134
135+ // https://cs.android.com/search?q=%22--prefix%20%22%20file:Android.bp
136+ // /(?<=--prefix )([\w\.]+)/
137+ val prefixes = arrayOf(
138+ " android.net.connectivity" ,
139+ " android.net.http.internal" ,
140+ " com.android.captiveportallogin" ,
141+ " com.android.networkstack" ,
142+ " com.android.server.nearby" ,
143+ " com.android.server.remoteauth" ,
144+ " gfxstream_vk" ,
145+ " lvp" ,
146+ " vk_cmd_enqueue" ,
147+ " vk_cmd_enqueue_unless_primary" ,
148+ " vk_common" ,
149+ " wsi" ,
150+ )
151+
110152 fun tryFindClass (classLoader : ClassLoader , classLoaderName : String , packageName : String ) {
111153 BuildConfig .targetClass.forEach { className ->
112154 var cls: Class <* >? = null
@@ -115,12 +157,20 @@ class Hook : IXposedHookLoadPackage {
115157 var successClassLoader: ClassLoader ? = null
116158 var i = 0
117159
118- while (classLoader != null && i++ < 10 ) {
160+ loop@ while (classLoader != null && i++ < 10 ) {
119161 try {
120162 cls = Class .forName(className, false , classLoader)
121163 successClassLoader = classLoader
164+ break @loop
122165 } catch (_: Throwable ) {
123- break
166+ }
167+ prefixes.forEach { prefix ->
168+ try {
169+ cls = Class .forName(" $prefix .$className " , false , classLoader)
170+ successClassLoader = classLoader
171+ break @loop
172+ } catch (_: Throwable ) {
173+ }
124174 }
125175 classLoader = classLoader.parent
126176 }
@@ -131,29 +181,24 @@ class Hook : IXposedHookLoadPackage {
131181 }
132182 }
133183
134- private fun logClass (cls : Class <* >, classLoaderName : String , classLoader : ClassLoader , packageName : String ) {
184+ private fun logClass (cls : Class <* >, classLoaderName : String , classLoader : ClassLoader , packageName : String , dump : Boolean = true ) {
135185 val lines = mutableListOf<String >()
136186 lines.add(" *" .repeat(150 ))
137187
138188 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 " )
189+ if (dump) {
190+ lines.add(" - constructors:" )
191+ cls.declaredConstructors.map { c -> " ${c.name} (${c.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" }
192+ .sorted()
193+ .forEach { c -> lines.add(" - $c " ) }
194+
195+ lines.add(" - methods:" )
196+ cls.declaredMethods.map { m -> " ${m.returnType.name} ${m.name} (${m.parameters.joinToString(" , " ) { p -> p.name + " " + p.type.name }} )" }
197+ .sorted()
198+ .forEach { m -> lines.add(" - $m " ) }
199+
200+ lines.add(" - fields:" )
201+ cls.declaredFields.map { f -> " ${f.type.name} ${f.name} " }.sorted().forEach { f -> lines.add(" - $f " ) }
157202 }
158203
159204 lines.forEach {
@@ -164,5 +209,5 @@ class Hook : IXposedHookLoadPackage {
164209
165210fun Any?.toObjectString (): String {
166211 if (this == null ) return " null"
167- return this ::class .simpleName + " @" + Integer .toHexString(hashCode())
212+ return this ::class .simpleName + " @" + Integer .toHexString(hashCode()).padStart( 8 , ' 0 ' )
168213}
0 commit comments