Fix change hook entry inject function try fix some Non-Root Hook Framework not work, such as TaiChi

This commit is contained in:
2022-09-30 00:02:48 +08:00
parent a67faed81c
commit 08d7676478
3 changed files with 133 additions and 129 deletions

View File

@@ -24,15 +24,11 @@
package com.fankes.tsbattery.hook package com.fankes.tsbattery.hook
import com.fankes.tsbattery.const.PackageName import com.fankes.tsbattery.const.PackageName
import com.fankes.tsbattery.data.ConfigData
import com.fankes.tsbattery.hook.entity.QQTIMHooker import com.fankes.tsbattery.hook.entity.QQTIMHooker
import com.fankes.tsbattery.hook.entity.WeChatHooker import com.fankes.tsbattery.hook.entity.WeChatHooker
import com.fankes.tsbattery.utils.factory.versionName
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
import com.highcapable.yukihookapi.hook.factory.configs import com.highcapable.yukihookapi.hook.factory.configs
import com.highcapable.yukihookapi.hook.factory.encase import com.highcapable.yukihookapi.hook.factory.encase
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
@InjectYukiHookWithXposed(isUsingResourcesHook = false) @InjectYukiHookWithXposed(isUsingResourcesHook = false)
@@ -50,31 +46,9 @@ class HookEntry : IYukiHookXposedInit {
isEnableDataChannel = false isEnableDataChannel = false
} }
/**
* 装载对象是否为 QQ、TIM、微信
* @return [Boolean]
*/
private fun PackageParam.isCurrentScope() = packageName.let { it == PackageName.QQ || it == PackageName.TIM || it == PackageName.WECHAT }
override fun onHook() = encase { override fun onHook() = encase {
loadApp { loadApp(PackageName.QQ) { loadHooker(QQTIMHooker) }
if (isCurrentScope()) onAppLifecycle { loadApp(PackageName.TIM) { loadHooker(QQTIMHooker) }
attachBaseContext { baseContext, hasCalledSuper -> loadApp(PackageName.WECHAT) { loadHooker(WeChatHooker) }
if (hasCalledSuper) return@attachBaseContext
ConfigData.init(baseContext)
when (baseContext.packageName) {
PackageName.QQ, PackageName.TIM -> loadHooker(QQTIMHooker.apply { appVersionName = baseContext.versionName })
PackageName.WECHAT -> loadHooker(WeChatHooker)
}
}
onCreate {
when (packageName) {
PackageName.QQ, PackageName.TIM ->
registerModuleAppActivities(proxy = "${PackageName.QQ}.activity.QQSettingSettingActivity")
PackageName.WECHAT -> registerModuleAppActivities(proxy = "${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI")
}
}
}
}
} }
} }

View File

@@ -35,13 +35,13 @@ import com.fankes.tsbattery.hook.factory.hookSystemWakeLock
import com.fankes.tsbattery.hook.factory.jumpToModuleSettings import com.fankes.tsbattery.hook.factory.jumpToModuleSettings
import com.fankes.tsbattery.hook.factory.startModuleSettings import com.fankes.tsbattery.hook.factory.startModuleSettings
import com.fankes.tsbattery.utils.factory.dp import com.fankes.tsbattery.utils.factory.dp
import com.fankes.tsbattery.utils.factory.versionName
import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.buildOf import com.highcapable.yukihookapi.hook.factory.*
import com.highcapable.yukihookapi.hook.factory.current
import com.highcapable.yukihookapi.hook.factory.field
import com.highcapable.yukihookapi.hook.log.loggerD import com.highcapable.yukihookapi.hook.log.loggerD
import com.highcapable.yukihookapi.hook.log.loggerE import com.highcapable.yukihookapi.hook.log.loggerE
import com.highcapable.yukihookapi.hook.log.loggerI
import com.highcapable.yukihookapi.hook.type.android.* import com.highcapable.yukihookapi.hook.type.android.*
import com.highcapable.yukihookapi.hook.type.java.* import com.highcapable.yukihookapi.hook.type.java.*
@@ -79,7 +79,7 @@ object QQTIMHooker : YukiBaseHooker() {
private val isQQ get() = packageName == PackageName.QQ private val isQQ get() = packageName == PackageName.QQ
/** 当前宿主的版本 */ /** 当前宿主的版本 */
var appVersionName = "<unknown>" private var appVersionName = "<unknown>"
/** /**
* 这个类 QQ 的 BaseChatPie 是控制聊天界面的 * 这个类 QQ 的 BaseChatPie 是控制聊天界面的
@@ -500,67 +500,74 @@ object QQTIMHooker : YukiBaseHooker() {
} }
override fun onHook() { override fun onHook() {
/** Hook 跳转事件 */ onAppLifecycle {
JumpActivityClass.hook { onCreate {
injectMember { appVersionName = versionName
method { ConfigData.init(context = this)
name = "doOnCreate" registerModuleAppActivities(QQSettingSettingActivityClass)
param(BundleClass) if (ConfigData.isDisableAllHook) return@onCreate
} hookSystemWakeLock()
afterHook { instance<Activity>().jumpToModuleSettings() } hookQQBaseChatPie()
hookCoreService()
hookQQDisgusting()
loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"")
} }
} }
/** 将条目注入设置界面 */ /** 仅注入主进程 */
QQSettingSettingActivityClass.hook { withProcess(mainProcessName) {
injectMember { /** Hook 跳转事件 */
method { JumpActivityClass.hook {
name = "doOnCreate" injectMember {
param(BundleClass) method {
name = "doOnCreate"
param(BundleClass)
}
afterHook { instance<Activity>().jumpToModuleSettings() }
} }
afterHook { }
/** 当前的顶级 Item 实例 */ /** 将条目注入设置界面 */
val formItemRefRoot = field { QQSettingSettingActivityClass.hook {
type(FormSimpleItemClass).index(num = 1) injectMember {
}.ignored().get(instance).cast() ?: field { method {
type(FormCommonSingleLineItemClass).index(num = 1) name = "doOnCreate"
}.ignored().get(instance).cast<View?>() param(BundleClass)
/** 创建一个新的 Item */ }
FormSimpleItemClass.toClassOrNull()?.buildOf<View>(instance) { param(ContextClass) }?.current { afterHook {
method { /** 当前的顶级 Item 实例 */
name = "setLeftText" val formItemRefRoot = field {
param(CharSequenceType) type(FormSimpleItemClass).index(num = 1)
}.call("TSBattery") }.ignored().get(instance).cast() ?: field {
method { type(FormCommonSingleLineItemClass).index(num = 1)
name = "setRightText" }.ignored().get(instance).cast<View?>()
param(CharSequenceType) /** 创建一个新的 Item */
}.call(BuildConfig.VERSION_NAME) FormSimpleItemClass.toClassOrNull()?.buildOf<View>(instance) { param(ContextClass) }?.current {
method { method {
name = "setBgType" name = "setLeftText"
param(IntType) param(CharSequenceType)
}.call(if (isQQ) 0 else 2) }.call("TSBattery")
}?.apply { setOnClickListener { instance<Activity>().startModuleSettings() } }?.also { item -> method {
var listGroup = formItemRefRoot?.parent as? ViewGroup? name = "setRightText"
val lparam = (if (listGroup?.childCount == 1) { param(CharSequenceType)
listGroup = listGroup.parent as? ViewGroup }.call(BuildConfig.VERSION_NAME)
(formItemRefRoot?.parent as? View?)?.layoutParams method {
} else formItemRefRoot?.layoutParams) name = "setBgType"
?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) param(IntType)
/** 设置圆角和间距 */ }.call(if (isQQ) 0 else 2)
if (isQQ) (lparam as? ViewGroup.MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0) }?.apply { setOnClickListener { instance<Activity>().startModuleSettings() } }?.also { item ->
/** 将 Item 添加到设置界面 */ var listGroup = formItemRefRoot?.parent as? ViewGroup?
listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) } val lparam = (if (listGroup?.childCount == 1) {
listGroup = listGroup.parent as? ViewGroup
(formItemRefRoot?.parent as? View?)?.layoutParams
} else formItemRefRoot?.layoutParams)
?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
/** 设置圆角和间距 */
if (isQQ) (lparam as? ViewGroup.MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0)
/** 将 Item 添加到设置界面 */
listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) }
}
} }
} }
} }
} }
if (ConfigData.isDisableAllHook) return
/** Hook 系统电源锁 */
hookSystemWakeLock()
/** Hook 聊天界面 */
hookQQBaseChatPie()
/** Hook CoreService */
hookCoreService()
/** Hook QQ 不省电的功能 */
hookQQDisgusting()
} }
} }

View File

@@ -36,10 +36,14 @@ import com.fankes.tsbattery.hook.factory.jumpToModuleSettings
import com.fankes.tsbattery.hook.factory.startModuleSettings import com.fankes.tsbattery.hook.factory.startModuleSettings
import com.fankes.tsbattery.utils.factory.absoluteStatusBarHeight import com.fankes.tsbattery.utils.factory.absoluteStatusBarHeight
import com.fankes.tsbattery.utils.factory.dp import com.fankes.tsbattery.utils.factory.dp
import com.fankes.tsbattery.utils.factory.versionCode
import com.fankes.tsbattery.utils.factory.versionName
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.current import com.highcapable.yukihookapi.hook.factory.current
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
import com.highcapable.yukihookapi.hook.log.loggerD import com.highcapable.yukihookapi.hook.factory.processName
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
import com.highcapable.yukihookapi.hook.log.loggerI
import com.highcapable.yukihookapi.hook.type.android.BundleClass import com.highcapable.yukihookapi.hook.type.android.BundleClass
/** /**
@@ -52,57 +56,76 @@ object WeChatHooker : YukiBaseHooker() {
/** 微信存在的类 - 未测试每个版本是否都存在 */ /** 微信存在的类 - 未测试每个版本是否都存在 */
const val LauncherUIClass = "${PackageName.WECHAT}.ui.LauncherUI" const val LauncherUIClass = "${PackageName.WECHAT}.ui.LauncherUI"
/** 微信存在的类 - 未测试每个版本是否都存在 */
private const val EmptyActivityClass = "${PackageName.WECHAT}.ui.EmptyActivity"
/** 微信存在的类 - 未测试每个版本是否都存在 */
private const val WelabMainUIClass = "${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI"
/** 微信存在的类 - 未测试每个版本是否都存在 */ /** 微信存在的类 - 未测试每个版本是否都存在 */
private const val SettingsUIClass = "${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI" private const val SettingsUIClass = "${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI"
override fun onHook() { override fun onHook() {
/** Hook 跳转事件 */ onAppLifecycle {
LauncherUIClass.hook { onCreate {
injectMember { ConfigData.init(context = this)
method { registerModuleAppActivities(
name = "onResume" when {
emptyParam() EmptyActivityClass.hasClass() -> EmptyActivityClass
} WelabMainUIClass.hasClass() -> WelabMainUIClass
afterHook { instance<Activity>().jumpToModuleSettings(isFinish = false) } else -> error("Inject WeChat Activity Proxy failed, unsupport version $versionName($versionCode)")
}
)
if (ConfigData.isDisableAllHook) return@onCreate
hookSystemWakeLock()
loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"")
} }
} }
/** 向设置界面右上角添加按钮 */ /** 仅注入主进程 */
SettingsUIClass.hook { withProcess(mainProcessName) {
injectMember { /** Hook 跳转事件 */
method { LauncherUIClass.hook {
name = "onCreate" injectMember {
param(BundleClass)
}
afterHook {
method { method {
name = "get_fragment" name = "onResume"
emptyParam() emptyParam()
superClass(isOnlySuperClass = true) }
}.get(instance).call()?.current() afterHook { instance<Activity>().jumpToModuleSettings(isFinish = false) }
?.field { name = "mController" } }
?.current()?.method { name = "getContentView" } }
?.invoke<ViewGroup>()?.addView(LinearLayout(instance()).apply { /** 向设置界面右上角添加按钮 */
context.injectModuleAppResources() SettingsUIClass.hook {
gravity = Gravity.END or Gravity.BOTTOM injectMember {
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) method {
addView(ImageView(context).apply { name = "onCreate"
layoutParams = ViewGroup.MarginLayoutParams(20.dp(context), 20.dp(context)).apply { param(BundleClass)
topMargin = context.absoluteStatusBarHeight + 15.dp(context) }
rightMargin = 20.dp(context) afterHook {
} method {
setColorFilter(ResourcesCompat.getColor(resources, R.color.colorTextGray, null)) name = "get_fragment"
setImageResource(R.drawable.ic_icon) emptyParam()
if (Build.VERSION.SDK_INT >= 26) tooltipText = "TSBattery 设置" superClass(isOnlySuperClass = true)
setOnClickListener { context.startModuleSettings() } }.get(instance).call()?.current()
?.field { name = "mController" }
?.current()?.method { name = "getContentView" }
?.invoke<ViewGroup>()?.addView(LinearLayout(instance()).apply {
context.injectModuleAppResources()
gravity = Gravity.END or Gravity.BOTTOM
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
addView(ImageView(context).apply {
layoutParams = ViewGroup.MarginLayoutParams(20.dp(context), 20.dp(context)).apply {
topMargin = context.absoluteStatusBarHeight + 15.dp(context)
rightMargin = 20.dp(context)
}
setColorFilter(ResourcesCompat.getColor(resources, R.color.colorTextGray, null))
setImageResource(R.drawable.ic_icon)
if (Build.VERSION.SDK_INT >= 26) tooltipText = "TSBattery 设置"
setOnClickListener { context.startModuleSettings() }
})
}) })
}) }
} }
} }
} }
if (ConfigData.isDisableAllHook) return
/** Hook 系统电源锁 */
hookSystemWakeLock()
/** 日志省电大法 */
loggerD(msg = "ウイチャット:それが機能するかどうかはわかりませんでした")
} }
} }