chore: RevokeMsgHook: clean up code

This commit is contained in:
ACh Sulfate
2024-07-20 11:28:27 +08:00
parent 1992894374
commit 10a1eefd48
2 changed files with 7 additions and 431 deletions

View File

@@ -55,252 +55,10 @@ jclass klassRevokeMsgHook = nullptr;
jobject gInstanceRevokeMsgHook = nullptr;
jmethodID handleRecallSysMsgFromNtKernel = nullptr;
uintptr_t gfnCreatePBMessage = 0;
uintptr_t gOffsetForTmpRev5048 = 0;
NOINLINE
uint64_t ThunkGetInt64Property(const void* thiz, int property) {
// vtable
// 4160. [[this+8]+0x58]
void* thisp8 = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(thiz) + 8);
uintptr_t vtable = *reinterpret_cast<uintptr_t*>(thisp8);
void* func = *reinterpret_cast<void**>(vtable + 0x58);
return reinterpret_cast<decltype(ThunkGetInt64Property)*>(func)(thisp8, property);
}
NOINLINE
uint32_t ThunkGetInt32Property(const void* thiz, int property) {
// vtable
// 4160. [[this+8]+0x38]
void* thisp8 = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(thiz) + 8);
uintptr_t vtable = *reinterpret_cast<uintptr_t*>(thisp8);
void* func = *reinterpret_cast<void**>(vtable + 0x38);
return reinterpret_cast<decltype(ThunkGetInt32Property)*>(func)(thisp8, property);
}
NOINLINE
std::string ThunkGetStringProperty(void* thiz, int property) {
// vtable
// 4160. [[this+8]+0x70]
void* thisp8 = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(thiz) + 8);
uintptr_t vtable = *reinterpret_cast<uintptr_t*>(thisp8);
void* func = *reinterpret_cast<void**>(vtable + 0x70);
return reinterpret_cast<decltype(ThunkGetStringProperty)*>(func)(thisp8, property);
}
template<typename ReturnType, uintptr_t vtableOffset, uintptr_t thizOffset, typename... ArgTypes>
requires((std::is_same_v<ReturnType, void> || std::is_integral_v<ReturnType> || std::is_pointer_v<ReturnType>)
&& ((std::is_integral_v<ArgTypes> || std::is_pointer_v<ArgTypes>) && ...))
NOINLINE
ReturnType vcall(void* thiz, ArgTypes... args) {
// vtable
// [[this+thizOff]+offsetVT]
void* thisp8 = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(thiz) + thizOffset);
uintptr_t vtable = *reinterpret_cast<uintptr_t*>(thisp8);
void* func = *reinterpret_cast<void**>(vtable + vtableOffset);
if constexpr (std::is_same_v<ReturnType, void>) {
reinterpret_cast<ReturnType(*)(void*, ArgTypes...)>(func)(thisp8, args...);
return;
} else {
return reinterpret_cast<ReturnType(*)(void*, ArgTypes...)>(func)(thisp8, args...);
}
}
template<typename... ArgTypes>
requires(((std::is_integral_v<ArgTypes> || std::is_pointer_v<ArgTypes>) && ...))
NOINLINE
void vcall_x8_v2(void* thiz, uintptr_t vtableOffset, uintptr_t thizOffset, void* x8, ArgTypes... args) {
// vtable
// [[this+thizOff]+offsetVT]
void* thisp8 = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(thiz) + thizOffset);
uintptr_t vtable = *reinterpret_cast<uintptr_t*>(thisp8);
void* func = *reinterpret_cast<void**>(vtable + vtableOffset);
static_assert(sizeof...(args) <= 3);
std::array<void*, 3> argArray = {reinterpret_cast<void*>(args)...};
call_func_with_x8(func, x8, thisp8, argArray[0], argArray[1], argArray[2]);
}
// helper for uintptr_t as this
template<typename ReturnType, uintptr_t vtableOffset, uintptr_t thizOffset, typename... ArgTypes>
requires((std::is_same_v<ReturnType, void> || std::is_integral_v<ReturnType> || std::is_pointer_v<ReturnType>)
&& ((std::is_integral_v<ArgTypes> || std::is_pointer_v<ArgTypes>) && ...))
static inline ReturnType vcall(uintptr_t thiz, ArgTypes... args) {
if constexpr (std::is_same_v<ReturnType, void>) {
vcall<vtableOffset, thizOffset, ArgTypes...>(reinterpret_cast<void*>(thiz), args...);
return;
} else {
return vcall<vtableOffset, thizOffset, ArgTypes...>(reinterpret_cast<void*>(thiz), args...);
}
}
template<typename... ArgTypes> requires((std::is_integral_v<ArgTypes> || std::is_pointer_v<ArgTypes>) && ...)
static inline void vcall_x8_v2(uintptr_t thiz, uintptr_t vtableOffset, uintptr_t thizOffset, void* x8, ArgTypes... args) {
vcall_x8_v2<ArgTypes...>(reinterpret_cast<void*>(thiz), vtableOffset, thizOffset, x8, args...);
}
//void ThunkCallAPI(void* x0, uintptr_t api_caller_id, int x2, int x3, int& x4, std::string& x5) {
// // 4160. 0x00cc0750
// // "CallAPI"
// // "!!! RegisterAPIHandler Error crash: api_caller_id is empty can not use You can use GlobalAPI or set other value to api_caller_id !!!"
// auto func = reinterpret_cast<decltype(ThunkCallAPI)*>((uintptr_t) gLibkernelBaseAddress + 0x00cc0750);
// func(x0, api_caller_id, x2, x3, x4, x5);
//}
class RevokeMsgInfoAccess {
public:
struct UnknownObjectStub16 {
void* _unk0_8;
void* _unk8_8;
};
};
void NotifyRecallSysMsgEvent(int chatType, const std::string& peerUid, const std::string& recallOpUid, const std::string& msgAuthorUid,
const std::string& toUid, uint64_t random64, uint64_t timeSeconds, uint64_t msgUid, uint64_t msgSeq, uint32_t msgClientSeq) {
JavaVM* vm = HostInfo::GetJavaVM();
if (vm == nullptr) {
LOGE("NotifyRecallSysMsgEvent fatal vm == null");
return;
}
if (klassRevokeMsgHook == nullptr) {
LOGE("NotifyRecallSysMsgEvent fatal klassRevokeMsgHook == null");
return;
}
// check if current thread is attached to jvm
JNIEnv* env = nullptr;
bool isAttachedManually = false;
jint err = vm->GetEnv((void**) &env, JNI_VERSION_1_6);
if (err == JNI_EDETACHED) {
if (vm->AttachCurrentThread(&env, nullptr) != JNI_OK) {
LOGE("NotifyRecallSysMsgEvent fatal AttachCurrentThread failed");
return;
}
isAttachedManually = true;
} else if (env == nullptr) {
LOGE("NotifyRecallSysMsgEvent fatal GetEnv failed, err = {}", err);
return;
}
// call java method
env->CallStaticVoidMethod(klassRevokeMsgHook, handleRecallSysMsgFromNtKernel,
jint(chatType), env->NewStringUTF(peerUid.c_str()), env->NewStringUTF(recallOpUid.c_str()),
env->NewStringUTF(msgAuthorUid.c_str()), env->NewStringUTF(toUid.c_str()),
jlong(random64), jlong(timeSeconds), jlong(msgUid), jlong(msgSeq), jint(msgClientSeq));
// check if exception occurred
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
// detach thread if attached manually
if (isAttachedManually) {
vm->DetachCurrentThread();
}
}
void NotifyRecallMsgEventForC2c(const std::string& fromUid, const std::string& toUid,
uint64_t random64, uint64_t timeSeconds,
uint64_t msgUid, uint64_t msgSeq, uint32_t msgClientSeq) {
NotifyRecallSysMsgEvent(1, fromUid, fromUid, fromUid, toUid, random64, timeSeconds, msgUid, msgSeq, msgClientSeq);
}
void NotifyRecallMsgEventForGroup(const std::string& peerUid, const std::string& recallOpUid, const std::string& msgAuthorUid,
uint64_t random64, uint64_t timeSeconds, uint64_t msgSeq) {
NotifyRecallSysMsgEvent(2, peerUid, recallOpUid, msgAuthorUid, peerUid, random64, timeSeconds, 0, msgSeq, 0);
}
void (* sOriginHandleGroupRecallSysMsgCallback)(void*, void*, void*) = nullptr;
void HandleGroupRecallSysMsgCallback([[maybe_unused]] void* x0, void* x1, [[maybe_unused]] void* x2, [[maybe_unused]] int x3) {
LOGD("HandleGroupRecallSysMsgCallback start p1={:p}, p2={:p}, p3={:p}", x0, x1, x2);
return;
// we can still do it... hitherto p3 == null... we need to decode the message manually...
uintptr_t base = (uintptr_t) gLibkernelBaseAddress;
void* pVar1 = *(void**) x1;
if ((vcall<int, 0x118, 8, int>(pVar1, 3) & 1) == 0) {
LOGE("msg_recall: HandleRecallSysMsg: on recall group sys msg! hasn't msg_common::Msg::kBody");
return;
}
void* pVar2 = *(void**) x1;
STACK_GUARD;
std::array<uint8_t, 0x100> objVar1 = {}; // actual size unknown, maybe 0x90
STACK_GUARD;
vcall_x8_v2<int>(pVar2, gOffsetForTmpRev5048, 0, &objVar1, 3);
auto pVar3 = *(void**) (objVar1.data());
if (pVar3 == nullptr) {
LOGE("msg_recall: HandleRecallSysMsg: on recall group sys msg! msg_common::Msg::kBody = null");
return;
}
if ((vcall<int, 0x118, 8, int>(pVar3, 2) & 1) == 0) {
LOGE("msg_recall: HandleRecallSysMsg: on recall group sys msg! hasn't im_msg_body::MsgBody::kBytesMsgContent");
return;
}
STACK_GUARD;
std::vector<uint8_t> msgContentBytes;
STACK_GUARD;
vcall_x8_v2<int>(pVar3, 0x78, 8, &msgContentBytes, 2);
if (msgContentBytes.size() < 8) {
LOGE("msg_recall: HandleRecallSysMsg: on recall group sys msg! im_msg_body::MsgBody::kBytesMsgContent is error");
return;
}
std::vector<uint8_t> content = {msgContentBytes.begin() + 7, msgContentBytes.end()};
STACK_GUARD;
std::array<void*, 2> objVar3 = {}; // actual size 0x10, maybe shared_ptr, but we don't have dtor
STACK_GUARD;
call_func_with_x8((void*) gfnCreatePBMessage, &objVar3, 0, 0, 0, 0);
void* notifyMsgBody = objVar3[0];
if ((vcall<int, 0x100, 8, std::vector<uint8_t>*>(notifyMsgBody, &content) & 1) == 0) {
LOGE("on recall group sys msg! decode kBytesMsgContent fail");
return;
}
uint64_t groupCode = vcall<uint64_t, 0x58, 8, int>(notifyMsgBody, 4);
if (groupCode == 0) {
LOGE("on recall group sys msg! group code is 0");
return;
}
uint64_t opType = vcall<uint64_t, 0x58, 8, int>(notifyMsgBody, 1);
if (opType != 7) {
LOGW("HandleGroupRecallSysMsgCallback: on recall group sys msg! no Prompt_MsgRecallReminder op_type:{}", opType);
return;
}
if ((vcall<uint64_t, 0x118, 8, int>(notifyMsgBody, 0xb) & 1) == 0) {
LOGE("HandleGroupRecallSysMsgCallback: on recall group sys msg! no NotifyMsgBody::opt_msg_recall");
return;
}
STACK_GUARD;
std::array<void*, 2> optMsgRecall = {}; // actual size 0x10, maybe shared_ptr, but we don't have dtor
STACK_GUARD;
vcall_x8_v2<int>(notifyMsgBody, gOffsetForTmpRev5048, 0, &optMsgRecall, 0xb);
if (optMsgRecall[0] == nullptr) {
LOGE("HandleGroupRecallSysMsgCallback: on recall group sys msg! NotifyMsgBody::opt_msg_recall == null");
return;
}
if ((vcall<int, 0x118, 8, int>(optMsgRecall[0], 3) & 1) == 0) {
LOGE("HandleGroupRecallSysMsgCallback: on recall group sys msg! on recall group sys msg! no msg_infos");
return;
}
std::array<void*, 3> vectorResultStub = {nullptr, nullptr, nullptr};
vcall_x8_v2<int>(optMsgRecall[0], 0xf0, 8, &vectorResultStub, 3);
std::string recallOpUid = ThunkGetStringProperty(optMsgRecall[0], 1);
const auto& msgInfoList = *reinterpret_cast<const std::vector<RevokeMsgInfoAccess::UnknownObjectStub16>*>(&vectorResultStub);
if (msgInfoList.empty()) {
LOGE("HandleGroupRecallSysMsgCallback: on recall group sys msg! no any msg info");
return;
}
std::string peerUid = fmt::format("{}", groupCode);
for (const auto& msgInfo: msgInfoList) {
uint32_t msgSeq = ThunkGetInt32Property(msgInfo._unk0_8, 1);
uint32_t random = ThunkGetInt32Property(msgInfo._unk0_8, 3);
uint64_t time = ThunkGetInt64Property(msgInfo._unk0_8, 2);
std::string msgAuthorUid = ThunkGetStringProperty(msgInfo._unk0_8, 6);
// Unfortunately, I didn't find a way to find the origMsgSenderUid.
// The only thing we can do is to get message by msgSeq, and get senderUid from it, iff we have the message.
NotifyRecallMsgEventForGroup(peerUid, recallOpUid, msgAuthorUid, random, time, msgSeq);
}
// LOGD("HandleGroupRecallSysMsgCallback start p1={:p}, p2={:p}, p3={:p}", x0, x1, x2);
}
void (* sOriginHandleC2cRecallSysMsgCallback)(void*, void*, void*) = nullptr;
@@ -310,54 +68,7 @@ void HandleC2cRecallSysMsgCallback([[maybe_unused]] void* p1, [[maybe_unused]] v
LOGE("HandleC2cGroupSysMsgCallback BUG !!! *p3 = null, this should not happen!!!");
return;
}
LOGD("HandleC2cRecallSysMsgCallback start p1={:p}, p2={:p}, p3={:p}", p1, p2, p3);
return;
std::array<void*, 3> vectorResultStub = {nullptr, nullptr, nullptr};
void* v1 = *(void**) p3;
void** v2 = (void**) ((uintptr_t) v1 + 8);
// 4160. 0xf0
auto func = reinterpret_cast<std::array<void*, 3>(*)(void*, int)>(*(void**) ((uintptr_t) *v2 + 0xf0));
// XXX: memory leak, no dtor available
vectorResultStub = func(v2, 1);
static_assert(sizeof(std::vector<int>) == sizeof(std::array<void*, 3>), "libcxx vector size not match");
const auto& objects = *reinterpret_cast<const std::vector<RevokeMsgInfoAccess::UnknownObjectStub16>*>(&vectorResultStub);
if (!objects.empty()) {
// void* x0 = nullptr;
// uintptr_t x1 = 0;
// {
// uint8_t* param_1 = static_cast<uint8_t*>(p1) + 8;
// uint8_t* pbVar1;
// uint64_t uVar2;
// uVar2 = *(uint64_t*) (param_1 + 8);
// pbVar1 = *(uint8_t**) (param_1 + 0x10);
// if ((*param_1 & 1) == 0) {
// pbVar1 = param_1 + 1;
// uVar2 = (uint64_t) (*param_1 >> 1);
// }
// x0 = pbVar1;
// x1 = uVar2;
// }
// int tmpInt = 0x138b;
// std::string tmpString;
// ThunkCallAPI(x0, x1, 0x10, 1, tmpInt, tmpString);
for (const auto& obj: objects) {
auto fromUid = ThunkGetStringProperty(obj._unk0_8, 1);
auto toUid = ThunkGetStringProperty(obj._unk0_8, 2);
auto randomId = ThunkGetInt64Property(obj._unk0_8, 6);
auto timeSeconds = ThunkGetInt64Property(obj._unk0_8, 5);
auto msgUid = ThunkGetInt64Property(obj._unk0_8, 4);
auto msgSeq = ThunkGetInt64Property(obj._unk0_8, 0x14);
auto msgClientSeq = ThunkGetInt32Property(obj._unk0_8, 3);
NotifyRecallMsgEventForC2c(fromUid, toUid, randomId, timeSeconds, msgUid, msgSeq, msgClientSeq);
}
}
// LOGD("HandleC2cRecallSysMsgCallback start p1={:p}, p2={:p}, p3={:p}", p1, p2, p3);
}
// Nobody uses PaiYiPai, right?
@@ -389,39 +100,11 @@ bool PerformNtRecallMsgHook(uint64_t baseAddress) {
.WithOffsetsForResult({-0x18, -0x24, -0x28})
.WithResultValidator(CommonAobScanValidator::kArm64StpX29X30SpImm);
//OffsetForTmpRev5048
//61 01 80 52 mov w1,#0xb
//?? ?? ?? ?? ??? ??,??
//?? 10 00 94 bl FUN_?
//?? ?? 00 36 tbz w0,#0x0,LAB_?
//?? ?? 40 f9 ldr x?,[x??]
//61 01 80 52 mov w1,#0xb
// ---------- THE GAP ----------
//e0 03 ?? aa mov x0,x??
//09 !! 40 f9 ldr x9,[x8, #0x!!] <-- we need to find this
//e8 ?? ?? 91 add x8,sp,#0x??
//20 01 3f d6 blr x9
auto targetInstructionOffsetForTmpRev5048 = AobScanTarget()
.WithName("InstructionOffsetForTmpRev5048")
// 0x61 0x01 0x80 0x52 0x?? 0x?? 0x?? 0x??
// 0x?? 0x10 0x00 0x94 0x?? 0x?? 0x00 0x36
// 0x?? 0x?? 0x40 0xf9 0x61 0x01 0x80 0x52
.WithSequence({0x61, 0x01, 0x80, 0x52, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x00, 0x94, 0x00, 0x00, 0x00, 0x36,
0x00, 0x00, 0x40, 0xf9, 0x61, 0x01, 0x80, 0x52})
.WithMask({ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})
.WithStep(4)
.WithExecMemOnly(true)
.WithOffsetsForResult({7 * 4});
//@formatter:on
std::vector<std::string> errorMsgList;
// auto start = std::chrono::steady_clock::now();
if (!SearchForAllAobScanTargets({&targetRecallC2cSysMsg, &targetRecallGroupSysMsg,
&targetInstructionOffsetForTmpRev5048},
gLibkernelBaseAddress, true, errorMsgList)) {
if (!SearchForAllAobScanTargets({&targetRecallC2cSysMsg, &targetRecallGroupSysMsg}, gLibkernelBaseAddress, true, errorMsgList)) {
LOGE("InitInitNtKernelRecallMsgHook SearchForAllAobScanTargets failed");
// sth went wrong
for (const auto& msg: errorMsgList) {
@@ -431,120 +114,13 @@ bool PerformNtRecallMsgHook(uint64_t baseAddress) {
return false;
}
{
// nt::IPBMessage::createPBMessage is an exported symbol for libbasic_share.so since 9.0.70.
// libbasic_share.so must be already loaded, for 9.0.70+, it's DT_NEEDED by libkernel.so.
void* createPBMessage = nullptr;
void* libbasic_share = loader_dlopen("libbasic_share.so", RTLD_NOW | RTLD_NOLOAD, gLibkernelBaseAddress);
if (libbasic_share != nullptr) {
const char* sym = "_ZN2nt10IPBMessage15createPBMessageEv";
createPBMessage = dlsym(libbasic_share, sym);
}
LOGD("libbasic_share.so: {:p}, createPBMessage: {:p}", libbasic_share, createPBMessage);
if (createPBMessage != nullptr) {
// we are all set
gfnCreatePBMessage = reinterpret_cast<uintptr_t>(createPBMessage);
} else {
// AOB scan for QQ before 9.0.70
// nt::IPBMessage::createPBMessage() 3f 8d 01 f8 f4 03 00 aa 1f 10 00 f9
auto targetCreatePBMessage = AobScanTarget()
.WithName("nt::IPBMessage::createPBMessage()")
.WithSequence({0x3f, 0x8d, 0x01, 0xf8, 0xf4, 0x03, 0x00, 0xaa, 0x1f, 0x10, 0x00, 0xf9})
.WithStep(4)
.WithExecMemOnly(true)
.WithOffsetsForResult({-0x78})
.WithResultValidator(CommonAobScanValidator::kArm64StpX29X30SpImm);
errorMsgList.clear();
if (!SearchForAllAobScanTargets({&targetCreatePBMessage}, gLibkernelBaseAddress, true, errorMsgList)) {
LOGE("InitInitNtKernelRecallMsgHook targetCreatePBMessage failed");
// sth went wrong
for (const auto& msg: errorMsgList) {
// report error to UI somehow
TraceError(nullptr, gInstanceRevokeMsgHook, msg);
}
return false;
}
uint64_t offsetCreatePBMessage = targetCreatePBMessage.GetResultOffset();
gfnCreatePBMessage = reinterpret_cast<uintptr_t>(gLibkernelBaseAddress) + offsetCreatePBMessage;
}
}
// auto end = std::chrono::steady_clock::now();
// LOGD("InitInitNtKernelRecallMsgHook AobScan elapsed: {}us", std::chrono::duration_cast<std::chrono::microseconds>(end - start).count());
if (auto pkg = HostInfo::GetPackageName(); pkg != "com.tencent.mobileqq") {
TraceErrorF(nullptr, gInstanceRevokeMsgHook, "InitInitNtKernelRecallMsgHook failed, unexpected package name: {}", pkg);
return false;
}
uint64_t offsetC2c = targetRecallC2cSysMsg.GetResultOffset();
uint64_t offsetGroup = targetRecallGroupSysMsg.GetResultOffset();
uint64_t offsetInstForTmpRev5048 = targetInstructionOffsetForTmpRev5048.GetResultOffset();
{
using ::platform::arch::endian::btoh32;
uint32_t instructionForTmpRev5048m0 = *reinterpret_cast<uint32_t*>(
reinterpret_cast<uintptr_t>(gLibkernelBaseAddress) + offsetInstForTmpRev5048);
uint32_t instructionForTmpRev5048m4 = *reinterpret_cast<uint32_t*>(
reinterpret_cast<uintptr_t>(gLibkernelBaseAddress) + offsetInstForTmpRev5048 - 4u);
// LOGD("instructionForTmpRev5048={:08x}", instructionForTmpRev5048);
if ((instructionForTmpRev5048m0 & btoh32(0xff00ffffu)) == btoh32(0x090040f9u)) {
// try 1: for case w/o function outline
// 09 !! 40 f9 ldr x9,[x8, #0x!!]
uint32_t imm12 = ((instructionForTmpRev5048m0 >> 10u) & 0xfffu) << 3u;
// LOGD("imm12={:x}", imm12);
gOffsetForTmpRev5048 = imm12;
} else if ((instructionForTmpRev5048m4 & (0b11111100u << 24u)) == (0b10010100u << 24u)) {
// try 2: for case w/ function outline
// bl xxx
uint32_t ins_bl = instructionForTmpRev5048m4;
auto imm26 = int32_t(ins_bl & 0x3ffffffu);
// sign extend
imm26 <<= 6u;
imm26 >>= 6u;
uint64_t curr_pc = reinterpret_cast<uintptr_t>(gLibkernelBaseAddress) + offsetInstForTmpRev5048 - 4u;
uint64_t target = curr_pc + (imm26 << 2u);
LOGD("imm26={:x}, target={:p}(base+{:x})", imm26, (void*) target, target - baseAddress);
if (IsMemoryReadable(reinterpret_cast<const void*>(target), 16)) {
// try 4 instructions at most
std::vector<uint32_t> instructions;
instructions.reserve(4);
for (int i = 0; i < 4; i++) {
instructions.push_back(*reinterpret_cast<const uint32_t*>(target + i * 4));
}
for (int i = 0; i < 4; i++) {
auto ins = instructions[i];
if ((ins & btoh32(0xff00ffffu)) == btoh32(0x090040f9u)) {
// try 1: for case w/o function outline
// 09 !! 40 f9 ldr x9,[x8, #0x!!]
uint32_t imm12 = ((ins >> 10u) & 0xfffu) << 3u;
// LOGD("imm12={:x}", imm12);
gOffsetForTmpRev5048 = imm12;
}
}
} else {
TraceErrorF(nullptr, gInstanceRevokeMsgHook,
"InitInitNtKernelRecallMsgHook failed, target is not readable, target={:p}(base+{:x})",
(void*) target, target - baseAddress);
return false;
}
}
if (gOffsetForTmpRev5048 == 0) {
TraceErrorF(nullptr,
gInstanceRevokeMsgHook,
"InitInitNtKernelRecallMsgHook failed, gOffsetForTmpRev5048 == 0, offsetInstForTmpRev5048 == 0, "
"ins[0]={:08x}, ins[-4]={:08x}",
instructionForTmpRev5048m0,
instructionForTmpRev5048m4);
return false;
}
}
LOGD("offsetC2c={:x}, offsetGroup={:x}, gfnCreatePBMessage={:p}, gOffsetForTmpRev5048={:x}",
offsetC2c, offsetGroup, (void*) gfnCreatePBMessage, gOffsetForTmpRev5048);
LOGD("offsetC2c={:x}, offsetGroup={:x}", offsetC2c, offsetGroup);
if (offsetC2c != 0) {
void* c2c = (void*) (baseAddress + offsetC2c);

View File

@@ -445,9 +445,9 @@ public class RevokeMsgHook extends CommonConfigFunctionHook {
String authorUid = msgInfo.getMsgAuthorUid();
long random64 = msgInfo.getRandomId();
Log.d("handleMsgPushForGroupRecall: groupCode=" + groupCodeText + ", operatorUid=" + operatorUid
+ ", authorUid=" + authorUid + ", random64=" + random64 + ", timeSeconds=" + timeSeconds
+ ", msgSeq=" + msgSeq);
// Log.d("handleMsgPushForGroupRecall: groupCode=" + groupCodeText + ", operatorUid=" + operatorUid
// + ", authorUid=" + authorUid + ", random64=" + random64 + ", timeSeconds=" + timeSeconds
// + ", msgSeq=" + msgSeq);
// invoke the handler
onRecallSysMsgForNT(ChatTypeConstants.GROUP, groupCodeText, operatorUid, authorUid, groupCodeText, random64, timeSeconds, 0, msgSeq, 0);