main.com.highcapable.yukihookapi.factory.CodeSourceFileFactory.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ksp-xposed Show documentation
Show all versions of ksp-xposed Show documentation
An efficient Hook API and Xposed Module solution built in Kotlin.
The newest version!
/*
* YukiHookAPI - An efficient Hook API and Xposed Module solution built in Kotlin.
* Copyright (C) 2019-2024 HighCapable
* https://github.com/HighCapable/YukiHookAPI
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is created by fankes on 2022/9/20.
*/
@file:Suppress("ConstPropertyName")
package com.highcapable.yukihookapi.factory
import com.highcapable.yukihookapi.bean.GenerateData
import com.highcapable.yukihookapi.generated.YukiHookAPIProperties
import com.highcapable.yukihookapi.utils.SymbolConverterTool
import java.text.SimpleDateFormat
import java.util.Date
/**
* 包名常量定义类
*/
object PackageName {
const val YukiHookAPI_Impl = "com.highcapable.yukihookapi"
const val ModuleApplication_Impl = "com.highcapable.yukihookapi.hook.xposed.application"
const val YukiXposedModuleStatus_Impl = "com.highcapable.yukihookapi.hook.xposed.bridge.status"
const val HandlerDelegateImpl_Impl = "com.highcapable.yukihookapi.hook.xposed.parasitic.activity.delegate.impl"
const val HandlerDelegateClass = "com.highcapable.yukihookapi.hook.xposed.parasitic.activity.delegate"
const val IActivityManagerProxyImpl_Impl = "com.highcapable.yukihookapi.hook.xposed.parasitic.activity.delegate.impl"
const val IActivityManagerProxyClass = "com.highcapable.yukihookapi.hook.xposed.parasitic.activity.delegate"
}
/**
* 类名常量定义类
*/
object ClassName {
const val YukiHookAPI_Impl = "YukiHookAPI_Impl"
const val ModuleApplication_Impl = "ModuleApplication_Impl"
const val YukiXposedModuleStatus_Impl = "YukiXposedModuleStatus_Impl"
const val YukiXposedModuleStatus_Impl_Impl = "YukiXposedModuleStatus_Impl_Impl"
const val HandlerDelegateImpl_Impl = "HandlerDelegateImpl_Impl"
const val HandlerDelegateClass = "HandlerDelegate"
const val IActivityManagerProxyImpl_Impl = "IActivityManagerProxyImpl_Impl"
const val IActivityManagerProxyClass = "IActivityManagerProxy"
const val XposedInit = "xposed_init"
const val XposedInit_Impl = "xposed_init_Impl"
}
/**
* 外部调用者包名和类名定义类
*/
object ExternalCallerName {
val HandlerDelegateCaller = Pair(
"com.highcapable.yukihookapi.hook.xposed.parasitic.activity.delegate.caller.HandlerDelegateCaller",
"HandlerDelegateCaller"
)
val IActivityManagerProxyCaller = Pair(
"com.highcapable.yukihookapi.hook.xposed.parasitic.activity.delegate.caller.IActivityManagerProxyCaller",
"IActivityManagerProxyCaller"
)
val YukiXposedEventCaller = Pair(
"com.highcapable.yukihookapi.hook.xposed.bridge.event.caller.YukiXposedEventCaller",
"YukiXposedEventCaller"
)
val YukiXposedModuleCaller = Pair(
"com.highcapable.yukihookapi.hook.xposed.bridge.caller.YukiXposedModuleCaller",
"YukiXposedModuleCaller"
)
val YukiXposedResourcesCaller = Pair(
"com.highcapable.yukihookapi.hook.xposed.bridge.resources.caller.YukiXposedResourcesCaller",
"YukiXposedResourcesCaller"
)
}
/**
* YukiXposedModuleStatus 方法名称定义类
*/
object YukiXposedModuleStatusJvmName {
const val IS_ACTIVE_METHOD_NAME = "__--"
const val IS_SUPPORT_RESOURCES_HOOK_METHOD_NAME = "_--_"
const val GET_EXECUTOR_NAME_METHOD_NAME = "_-_-"
const val GET_EXECUTOR_API_LEVEL_METHOD_NAME = "-__-"
const val GET_EXECUTOR_VERSION_NAME_METHOD_NAME = "-_-_"
const val GET_EXECUTOR_VERSION_CODE_METHOD_NAME = "___-"
}
/**
* 创建尾部包名名称
* @param name 前置名称
* @return [String]
*/
private fun GenerateData.tailPackageName(name: String) = "${name}_${modulePackageName.replace(".", "_")}"
/**
* 创建文件注释
* @param currrentClassTag 当前注入类标签
* @return [String]
*/
private fun createCommentContent(currrentClassTag: String) =
"""
/**
* $currrentClassTag Class
*
* Compiled from YukiHookXposedProcessor
*
* Generate Date: ${SimpleDateFormat.getDateTimeInstance().format(Date())}
*
* Powered by YukiHookAPI (C) HighCapable 2019-2024
*
* Project URL: [${YukiHookAPIProperties.PROJECT_NAME}](${YukiHookAPIProperties.PROJECT_URL})
*/
""".trimIndent()
/**
* 获得注入文件代码内容
* @return [Map]<[String], [String]>
*/
fun GenerateData.sources() = mapOf(
ClassName.YukiHookAPI_Impl to """
@file:Suppress("ClassName")
package ${PackageName.YukiHookAPI_Impl}
""".trimIndent() + "\n\n" + createCommentContent(ClassName.YukiHookAPI_Impl) + "\n" + """
object ${ClassName.YukiHookAPI_Impl} {
val compiledTimestamp get() = ${System.currentTimeMillis()}
}
""".trimIndent(),
ClassName.ModuleApplication_Impl to """
@file:Suppress("ClassName")
package ${PackageName.ModuleApplication_Impl}
import ${SymbolConverterTool.process(entryPackageName)}.$entryClassName
""".trimIndent() + "\n\n" + createCommentContent(ClassName.ModuleApplication_Impl) + "\n" + """
object ${ClassName.ModuleApplication_Impl} {
fun callHookEntryInit() = try {
${if (isEntryClassKindOfObject) "$entryClassName.onInit()" else "$entryClassName().onInit()"}
} catch (_: Throwable) {
}
}
""".trimIndent(),
ClassName.YukiXposedModuleStatus_Impl to """
@file:Suppress("ClassName")
package ${PackageName.YukiXposedModuleStatus_Impl}
""".trimIndent() + "\n\n" + createCommentContent(ClassName.YukiXposedModuleStatus_Impl) + "\n" + """
object ${ClassName.YukiXposedModuleStatus_Impl} {
val className get() = "${PackageName.YukiXposedModuleStatus_Impl}.${tailPackageName(ClassName.YukiXposedModuleStatus_Impl_Impl)}"
}
""".trimIndent(),
ClassName.YukiXposedModuleStatus_Impl_Impl to """
@file:Suppress("ClassName")
package ${PackageName.YukiXposedModuleStatus_Impl}
import android.util.Log
import androidx.annotation.Keep
""".trimIndent() + "\n\n" + createCommentContent(ClassName.YukiXposedModuleStatus_Impl) + "\n" + """
@Keep
object ${tailPackageName(ClassName.YukiXposedModuleStatus_Impl_Impl)} {
@JvmStatic
@JvmName("${YukiXposedModuleStatusJvmName.IS_ACTIVE_METHOD_NAME}")
fun function${(1000..99999).random()}(): Boolean {
phe()
return false
}
@JvmStatic
@JvmName("${YukiXposedModuleStatusJvmName.IS_SUPPORT_RESOURCES_HOOK_METHOD_NAME}")
fun function${(1000..99999).random()}(): Boolean {
phe()
return false
}
@JvmStatic
@JvmName("${YukiXposedModuleStatusJvmName.GET_EXECUTOR_NAME_METHOD_NAME}")
fun function${(1000..99999).random()}(): String {
phe()
return "unknown"
}
@JvmStatic
@JvmName("${YukiXposedModuleStatusJvmName.GET_EXECUTOR_API_LEVEL_METHOD_NAME}")
fun function${(1000..99999).random()}(): Int {
phe()
return -1
}
@JvmStatic
@JvmName("${YukiXposedModuleStatusJvmName.GET_EXECUTOR_VERSION_NAME_METHOD_NAME}")
fun function${(1000..99999).random()}(): String {
phe()
return "unknown"
}
@JvmStatic
@JvmName("${YukiXposedModuleStatusJvmName.GET_EXECUTOR_VERSION_CODE_METHOD_NAME}")
fun function${(1000..99999).random()}(): Int {
phe()
return -1
}
@JvmStatic
@JvmName("_${(1000..99999).random()}")
private fun phe() {
/** Consume a long method body */
if (System.currentTimeMillis() == 0L) Log.d("${(1000..9999).random()}", "${(100000..999999).random()}")
}
}
""".trimIndent(),
ClassName.HandlerDelegateImpl_Impl to """
@file:Suppress("ClassName", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package ${PackageName.HandlerDelegateImpl_Impl}
import android.os.Handler
import ${PackageName.HandlerDelegateClass}.${tailPackageName(ClassName.HandlerDelegateClass)}
""".trimIndent() + "\n\n" + createCommentContent(ClassName.HandlerDelegateImpl_Impl) + "\n" + """
object ${ClassName.HandlerDelegateImpl_Impl} {
val wrapperClassName get() = "${PackageName.HandlerDelegateClass}.${tailPackageName(ClassName.HandlerDelegateClass)}"
fun createWrapper(baseInstance: Handler.Callback? = null): Handler.Callback = ${tailPackageName(ClassName.HandlerDelegateClass)}(baseInstance)
}
""".trimIndent(),
ClassName.HandlerDelegateClass to """
@file:Suppress("ClassName", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package ${PackageName.HandlerDelegateClass}
import android.os.Handler
import android.os.Message
import androidx.annotation.Keep
import ${ExternalCallerName.HandlerDelegateCaller.first}
""".trimIndent() + "\n\n" + createCommentContent(ClassName.HandlerDelegateClass) + "\n" + """
@Keep
class ${tailPackageName(ClassName.HandlerDelegateClass)}(private val baseInstance: Handler.Callback?) : Handler.Callback {
override fun handleMessage(msg: Message) = ${ExternalCallerName.HandlerDelegateCaller.second}.callHandleMessage(baseInstance, msg)
}
""".trimIndent(),
ClassName.IActivityManagerProxyImpl_Impl to """
@file:Suppress("ClassName", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package ${PackageName.IActivityManagerProxyImpl_Impl}
import android.os.Handler
import ${ExternalCallerName.IActivityManagerProxyCaller.first}
import ${PackageName.IActivityManagerProxyClass}.${tailPackageName(ClassName.IActivityManagerProxyClass)}
import java.lang.reflect.Proxy
""".trimIndent() + "\n\n" + createCommentContent(ClassName.IActivityManagerProxyImpl_Impl) + "\n" + """
object ${ClassName.IActivityManagerProxyImpl_Impl} {
fun createWrapper(clazz: Class<*>?, instance: Any) =
Proxy.newProxyInstance(${ExternalCallerName.IActivityManagerProxyCaller.second}.currentClassLoader, arrayOf(clazz), ${
tailPackageName(
ClassName.IActivityManagerProxyClass
)
}(instance))
}
""".trimIndent(),
ClassName.IActivityManagerProxyClass to """
@file:Suppress("ClassName", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package ${PackageName.IActivityManagerProxyClass}
import androidx.annotation.Keep
import ${ExternalCallerName.IActivityManagerProxyCaller.first}
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
""".trimIndent() + "\n\n" + createCommentContent(ClassName.IActivityManagerProxyClass) + "\n" + """
@Keep
class ${tailPackageName(ClassName.IActivityManagerProxyClass)}(private val baseInstance: Any) : InvocationHandler {
override fun invoke(proxy: Any?, method: Method?, args: Array?) = ${ExternalCallerName.IActivityManagerProxyCaller.second}.callInvoke(baseInstance, method, args)
}
""".trimIndent(),
ClassName.XposedInit to """
@file:Suppress("ClassName", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package ${SymbolConverterTool.process(entryPackageName)}
import androidx.annotation.Keep
import ${ExternalCallerName.YukiXposedEventCaller.first}
${if (isUsingResourcesHook) "import de.robv.android.xposed.IXposedHookInitPackageResources" else ""}
import de.robv.android.xposed.IXposedHookLoadPackage
import de.robv.android.xposed.IXposedHookZygoteInit
${if (isUsingResourcesHook) "import de.robv.android.xposed.callbacks.XC_InitPackageResources" else ""}
import de.robv.android.xposed.callbacks.XC_LoadPackage
""".trimIndent() + "\n\n" + createCommentContent("Xposed Init") + "\n" + """
@Keep
class $xInitClassName : IXposedHookZygoteInit, IXposedHookLoadPackage${if (isUsingResourcesHook) ", IXposedHookInitPackageResources" else ""} {
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
${entryClassName}_Impl.callInitZygote(sparam)
${ExternalCallerName.YukiXposedEventCaller.second}.callInitZygote(sparam)
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
${entryClassName}_Impl.callHandleLoadPackage(lpparam)
${ExternalCallerName.YukiXposedEventCaller.second}.callHandleLoadPackage(lpparam)
}
""".trimIndent() +
(if (isUsingResourcesHook)
"\n" + """
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {
${entryClassName}_Impl.callHandleInitPackageResources(resparam)
${ExternalCallerName.YukiXposedEventCaller.second}.callHandleInitPackageResources(resparam)
}
}
""".trimIndent()
else "\n}"),
ClassName.XposedInit_Impl to """
@file:Suppress("ClassName", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package ${SymbolConverterTool.process(entryPackageName)}
import ${ExternalCallerName.YukiXposedModuleCaller.first}
import ${ExternalCallerName.YukiXposedResourcesCaller.first}
import com.highcapable.yukihookapi.hook.xposed.bridge.type.HookEntryType
import de.robv.android.xposed.IXposedHookZygoteInit
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.callbacks.XC_InitPackageResources
import de.robv.android.xposed.callbacks.XC_LoadPackage
""".trimIndent() + "\n\n" + createCommentContent("Xposed Init Impl") + "\n" + """
object ${entryClassName}_Impl {
private const val MODULE_PACKAGE_NAME = "${customMPackageName.ifBlank { modulePackageName }}"
private var isZygoteCalled = false
private val hookEntry = ${if (isEntryClassKindOfObject) entryClassName else "$entryClassName()"}
private fun callOnXposedModuleLoaded(
isZygoteLoaded: Boolean = false,
lpparam: XC_LoadPackage.LoadPackageParam? = null,
resparam: XC_InitPackageResources.InitPackageResourcesParam? = null
) {
if (isZygoteCalled.not()) runCatching {
hookEntry.onXposedEvent()
hookEntry.onInit()
if (${ExternalCallerName.YukiXposedModuleCaller.second}.isXposedCallbackSetUp) {
${ExternalCallerName.YukiXposedModuleCaller.second}.callLogError("You cannot load a hooker in \"onInit\" or \"onXposedEvent\" method! Aborted")
return
}
hookEntry.onHook()
${ExternalCallerName.YukiXposedModuleCaller.second}.callOnFinishLoadModule()
}.onFailure { ${ExternalCallerName.YukiXposedModuleCaller.second}.callLogError("YukiHookAPI try to load hook entry class failed", it) }
${ExternalCallerName.YukiXposedModuleCaller.second}.callOnPackageLoaded(
type = when {
isZygoteLoaded -> HookEntryType.ZYGOTE
lpparam != null -> HookEntryType.PACKAGE
resparam != null -> HookEntryType.RESOURCES
else -> HookEntryType.ZYGOTE
},
packageName = lpparam?.packageName ?: resparam?.packageName,
processName = lpparam?.processName,
appClassLoader = lpparam?.classLoader ?: runCatching { XposedBridge.BOOTCLASSLOADER }.getOrNull(),
appInfo = lpparam?.appInfo,
appResources = ${ExternalCallerName.YukiXposedResourcesCaller.second}.createYukiResourcesFromXResources(resparam?.res)
)
}
fun callInitZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
if (sparam == null) return
runCatching {
${ExternalCallerName.YukiXposedModuleCaller.second}.callOnStartLoadModule(MODULE_PACKAGE_NAME, sparam.modulePath)
callOnXposedModuleLoaded(isZygoteLoaded = true)
isZygoteCalled = true
}.onFailure { ${ExternalCallerName.YukiXposedModuleCaller.second}.callLogError("An exception occurred when YukiHookAPI loading Xposed Module", it) }
}
fun callHandleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
if (lpparam != null && isZygoteCalled) callOnXposedModuleLoaded(lpparam = lpparam)
}
fun callHandleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {
if (resparam != null && isZygoteCalled) callOnXposedModuleLoaded(resparam = resparam)
}
}
""".trimIndent()
)