Skip to content

Commit

Permalink
refactor: MultiForwardAvatarHook: using DexKit to find method
Browse files Browse the repository at this point in the history
  • Loading branch information
klxiaoniu committed Jul 29, 2023
1 parent e10c645 commit 81a8997
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 8 deletions.
61 changes: 53 additions & 8 deletions app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.text.buildSpannedString
import cc.hicore.QApp.QAppUtils
import cc.ioctl.hook.profile.OpenProfileCard
import cc.ioctl.util.HostInfo
import cc.ioctl.util.HostStyledViewBuilder
import cc.ioctl.util.LayoutHelper
import cc.ioctl.util.Reflex
import cc.ioctl.util.hookBeforeIfEnabled
import cc.ioctl.util.ui.FaultyDialog
import com.github.kyuubiran.ezxhelper.utils.findMethod
import com.github.kyuubiran.ezxhelper.utils.hookBefore
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
import de.robv.android.xposed.XC_MethodHook.MethodHookParam
Expand All @@ -51,14 +51,19 @@ import io.github.qauxv.base.annotation.FunctionHookEntry
import io.github.qauxv.base.annotation.UiItemAgentEntry
import io.github.qauxv.dsl.FunctionEntryRouter
import io.github.qauxv.hook.CommonSwitchFunctionHook
import io.github.qauxv.step.Step
import io.github.qauxv.ui.CommonContextWrapper
import io.github.qauxv.ui.CustomDialog
import io.github.qauxv.util.Initiator
import io.github.qauxv.util.Log
import io.github.qauxv.util.QQVersion
import io.github.qauxv.util.UiThread
import io.github.qauxv.util.dexkit.CAIOUtils
import io.github.qauxv.util.dexkit.DexDeobfsProvider.getCurrentBackend
import io.github.qauxv.util.dexkit.DexKit
import io.github.qauxv.util.dexkit.DexKit.loadClassFromCache
import io.github.qauxv.util.dexkit.DexKitFinder
import io.github.qauxv.util.dexkit.Multiforward_Avatar_setListener_NT
import io.github.qauxv.util.requireMinQQVersion
import me.ketal.dispacher.BaseBubbleBuilderHook
import me.ketal.dispacher.OnBubbleBuilder
Expand All @@ -69,32 +74,70 @@ import java.lang.reflect.Modifier

@FunctionHookEntry
@UiItemAgentEntry
object MultiForwardAvatarHook : CommonSwitchFunctionHook(arrayOf(CAIOUtils)), OnBubbleBuilder {
object MultiForwardAvatarHook : CommonSwitchFunctionHook(arrayOf(CAIOUtils, Multiforward_Avatar_setListener_NT)), OnBubbleBuilder, DexKitFinder {

override val name = "转发消息点头像查看详细信息"
override val description = "仅限合并转发的消息"
override val uiItemLocation = FunctionEntryRouter.Locations.Auxiliary.MESSAGE_CATEGORY

private var mChatItemHeadIconViewId = 0


override val isNeedFind = QAppUtils.isQQnt() && Multiforward_Avatar_setListener_NT.descCache == null

override fun doFind(): Boolean {
getCurrentBackend().use { backend ->
val dexKit = backend.getDexKitBridge()
val m = dexKit.findMethodCaller {
callerMethodDeclareClass = "com.tencent.mobileqq.aio.msglist.holder.component.avatar.AIOAvatarContentComponent"
callerMethodReturnType = "V"
callerMethodParameterTypes = emptyArray()
methodName = "setOnClickListener"
}
if (m.size != 1) return false
Multiforward_Avatar_setListener_NT.descCache = m.keys.first().descriptor
return true
}
}

private val mStep: Step = object : Step {
override fun step(): Boolean {
return doFind()
}

override fun isDone(): Boolean {
return !isNeedFind
}

override fun getPriority(): Int {
return 0
}

override fun getDescription(): String {
return "点击事件相关方法查找中"
}
}

override fun makePreparationSteps(): Array<Step> {
return arrayOf(mStep)
}


@SuppressLint("DiscouragedApi")
@Throws(Exception::class)
public override fun initOnce(): Boolean {
if (requireMinQQVersion(QQVersion.QQ_8_9_63)) {
val clz = Initiator.loadClass("com.tencent.mobileqq.aio.msglist.holder.component.avatar.AIOAvatarContentComponent")
// 设置头像点击和长按事件的方法
clz.findMethod {
name == if (requireMinQQVersion(QQVersion.QQ_8_9_68)) "Q0"
else "R0" //8.9.63
}.hookBefore { param ->
DexKit.requireMethodFromCache(Multiforward_Avatar_setListener_NT).hookBefore { param ->
var layout: RelativeLayout?
clz.declaredFields.first { it.name == "h" }.let {
clz.declaredFields.single { it.name == "h" }.let {
it.isAccessible = true //Lazy
layout = (it.get(param.thisObject))!!.invoke("getValue") as RelativeLayout
}
if (layout!!.context.javaClass.name == "com.tencent.mobileqq.activity.MultiForwardActivity") {
layout!!.setOnClickListener {
clz.declaredFields.first {
clz.declaredFields.single {
it.type.name == "com.tencent.mobileqq.aio.msg.AIOMsgItem"
}.let {
it.isAccessible = true
Expand All @@ -114,6 +157,8 @@ object MultiForwardAvatarHook : CommonSwitchFunctionHook(arrayOf(CAIOUtils)), On
}
return true
}


BaseBubbleBuilderHook.initialize()
val kBaseBubbleBuilder = Initiator.loadClass("com/tencent/mobileqq/activity/aio/BaseBubbleBuilder")
val onClick = kBaseBubbleBuilder.getMethod("onClick", View::class.java)
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/io/github/qauxv/util/dexkit/DexKitTarget.kt
Original file line number Diff line number Diff line change
Expand Up @@ -763,3 +763,9 @@ data object FileBrowserActivity_InnerClass_onItemClick : DexKitTarget.UsingStrin
override val declaringClass = ""
override val filter = DexKitFilter.strInClsName("FileBrowserActivity")
}

data object Multiforward_Avatar_setListener_NT : DexKitTarget.UsingDexkit() {
override val findMethod: Boolean = true
override val declaringClass = "com.tencent.mobileqq.aio.msglist.holder.component.avatar.AIOAvatarContentComponent"
override val filter = DexKitFilter.allowAll
}

0 comments on commit 81a8997

Please sign in to comment.