点击上方蓝字关注我们
现在只对常读和星标的公众号才展示大图推送,建议大家能把星落安全团队“设为星标”,否则可能就看不到了啦!
文章前言
来源:看雪论坛,作者:马先越
b站刷到一位老师分享了hook pc端微信信息撤回功能的视频,跟着动手操作了一遍之后,尝试了一下hook Android端的微信,下面分享一下学习过程。
视频链接:https://www.bilibili.com/video/BV1di421U7qD
PC端
PC端那位老师已经演示的很清楚了,我就简单的复述一遍,感兴趣的可以看一下视频。微信的核心功能都是在WeChatwin.dll(windows下)里实现的,信息撤回也不例外。
我们使用ida分析,通过字符串进行定位,试试相关的字符,如:撤回、revoke、withdrawn等关键字
我们逐一hook使用到这些字符串的函数,然后点击微信的撤回,如果有log输出,就代表是关键函数。
测试脚本如下,首先我们获取了dll的加载地址,然后通过ida查看到函数的偏移地址,将dll地址加上该偏移地址,即可得到内存中该函数的地址,那么如何确定哪一个才是撤回相关函数? 就是靠试,使用到msg相关字符串的函数我们都hook一遍,然后触发撤回功能,如果打印出来revokeMsg就说明hook成功。
import frida,sys
# 创建脚本
jsCode="""
//写入js脚本 就和之前一样
//下面的代码获取dll的加载地址
const baseAddr=Module.findBaseAddress('WeChatWin.dll');
console.log("baseAddr:"+baseAddr);
//每次需要修改的只有这里
const revokeMsgFunAddr=getRealAddr('0x1823CD710');
console.log("function addr:",revokeMsgFunAddr);
//根据地址进行frida注入
Interceptor.attach(revokeMsgFunAddr,{
//一旦进入hook的函数,该回调函数就会被调用
onEnter(args){
console.log("-----revokeMsg------")
}
});
//dll地址加上偏移地址,定位到这个函数
function getRealAddr(addr){
//基地址
const idaBase=ptr('0x180000000');
const offset=ptr(addr).sub(idaBase);
const result=ptr(baseAddr).add(offset);
return result;
}
"""
#使用任务管理器查看微信的PID然后填入
session = frida.attach(7876)
# 运行脚本
script = session.create_script(jsCode)
script.load()
print("Successfully attached!!!!")
# 防止运行完进程直接退出
sys.stdin.read()
运行测设脚本
当我们测试到字符串SyncMgr::ProcessRevokeMsg所在的函数时,有了revokeMsg的回显
函数逻辑比较复杂,hook点也是比较难找
但是我们知道每次撤回信息,这个函数都要被调用,我们直接查看他的交叉引用,发现这个函数在一个switch语句里被调用
我们只需要让这个不为4,这里就不会被执行
edi为4的时候就会执行撤回相关的函数,修改思路就是当程序运行到这里时修改edi寄存器的值
Interceptor.attach(revokeMsgFunAddr,{ / / 一旦进入hook的函数,该回调函数就会被调用 onEnter(args){ console.log( "-----revokeMsg------" ) console.log(this.context.rdi); this.context.rdi = 0 ; } }); |
最终实现的效果:
PC端显示
移动端 消息1 已经被撤回
Android端
大致思路也是向PC端演示的那样,但是因为没有参考的教程,所以走了不少弯路
还是直接搜索字符串进行定位,考虑到PC端那里时revoke关键字,所以也是直接搜索revoke
其实也不用逐个尝试,因为有几个特别明显的,hook这几个特别明显的方法测试就行
直接右键方法名选择复制为frida片段即可,最终是定位到了这个RevokeMsgEvent方法,每当我们撤回信息,都会打印 RevokeMsgEvent.$init is called
Java.perform(function(){
console.log("==========begain==========")
letRevokeMsgEvent = Java.use("com.tencent.mm.autogen.events.RevokeMsgEvent");
RevokeMsgEvent["$init"].implementation = function () {
console.log(`RevokeMsgEvent.$init is called`);
this["$init"]();
};
});
这个方法其实没啥有价值的东西,尝试了直接置空这个方法,也就是将上面的 this["$init"]();
直接删除,并没有起到什么效果
然后就是查看了这个方法的交叉引用
整个程序只有这一出引用,微信应该做了一些混淆,名字都奇奇怪怪的,可读性很差,一时见不知从何下手。首先尝试了修改RevokeMsgEvent的赋值,它将 变量赋值为falsethis.f153351e = false;
,我尝试了一下将该变量赋值为true,注意没有f153351e,这是jadx帮它命名的,实际的变量名是e
Java.choose("com.tencent.mm.autogen.events.RevokeMsgEvent",{//遍历内存中的所有对象
onMatch:function(obj){
obj.e.value=true;
console.log("value : ",obj.e.value);
},onComplete:function(){
console.log("内存对象搜索完毕")
}
})
修改成功,但是信息还是被撤回。
这条路行不通就考虑另外的方案,hook掉调用这个方法的方法,和pc端相同的操作
该方法是被s类下的h方法所调用的,复制h方法的frida片段进行hook
let s = Java.use("tj0.s");
s["h"].implementation = function (str, j15, n0Var, str2, str3, str4) {
console.log(`s.h is called: str=${str}, j15=${j15}, n0Var=${n0Var}, str2=${str2}, str3=${str3}, str4=${str4}`);
this["h"](str, j15, n0Var, str2, str3, str4);
};
报错,提示没有找到tj0.s这个类,于是我想这个类可能不是被默认的类加载器所加载的,遍历一下所有的类加载器然后再hook
functionmain() {
Java.perform(function () {
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
var factory = Java.ClassFactory.get(loader);
var s = factory.use("tj0.s");
s["h"].implementation = function (str, j15, n0Var, str2, str3, str4) {
console.log(`s.h is called: str=${str}, j15=${j15}, n0Var=${n0Var}, str2=${str2}, str3=${str3}, str4=${str4}`);
this["h"](str, j15, n0Var, str2, str3, str4);
};
} catch (e) {
console.log("Error accessing class or method: " + e);
}
},
onComplete: function () {}
});
});
}
结果遍历了所有的类加载器也没有这个类
而且我使用objection打印加载的类也没有这个tj0.s
最后想到了打印方法的调用堆栈
Java.perform(function(){
console.log("==========begain==========")
let RevokeMsgEvent = Java.use("com.tencent.mm.autogen.events.RevokeMsgEvent");
//hook构造方法
RevokeMsgEvent["$init"].implementation = function () {
console.log(`RevokeMsgEvent.$init is called`);
showStacks();
this["$init"]();
};
functionshowStacks(){
console.log(
Java.use("android.util.Log") //首先找到log类
.getStackTraceString( //调用log类的该方法
Java.use("java.lang.Throwable").$new() //new一个对象
)
)
}
});
通过函数的调用堆栈,发现RevokeMsgEvent是被ij0.s.i方法调用的,我们直接将这个方法置空
var sClass=Java.use("ij0.s");
sClass.i.implementation=function(){
console.log("======================");
};
最终实现的效果,左边是pc显示的,右边是手机显示的
Xposed实现hook的持久化
使用xposed将上面的代码重写一下即可,frida逻辑如下
Java.perform(function(){
var sClass=Java.use("ij0.s");
sClass.i.implementation=function(){
console.log("======================");
};
});
xposed代码
package com.example.xposeddemo;
import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
publicclassHookimplementsIXposedHookLoadPackage {
publicvoidhandleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam)throws Throwable {
if(!loadPackageParam.packageName.equals("com.tencent.mm")) return;
Class<?> clazz=XposedHelpers.findClass("ij0.s",loadPackageParam.classLoader);
Log.d("mxy", clazz.toString());
XposedHelpers.findAndHookMethod(clazz, "i", newXC_MethodReplacement() {
protected Object replaceHookedMethod(MethodHookParam methodHookParam)throws Throwable {
Log.d("mxy", "hook successfully");
returnnull;
}
});
}
}
这个xposed等价的应该是没什么问题的,但是就是hook不上这个i方法,也尝试了使用算法助手,都是以失败告终
后续如果找到解决方案我会进行更新。。。。。。。
小结:
写hook代码很简单,难的是分析的过程,如果定位到了关键代码,只需要短短几行代码就能成功hook。
圈子介绍
博主介绍:
目前工作在某安全公司攻防实验室,一线攻击队选手。自2022-2024年总计参加过30+次省/市级攻防演练,擅长工具开发、免杀、代码审计、信息收集、内网渗透等安全技术。
目前已经更新的免杀内容:
一键击溃360+核晶
一键击溃奇安信天擎V10进程
一键击溃windows defender
一键击溃火绒进程
CobaltStrike4.9.1二开
CobaltStrike免杀加载器
数据库直连工具免杀版
aspx文件自动上线cobaltbrike
jsp文件自动上线cobaltbrike
哥斯拉免杀工具 XlByPassGodzilla
冰蝎免杀工具 XlByPassBehinder
冰蝎星落专版 xlbehinder
正向代理工具 xleoreg
反向代理工具xlfrc
内网扫描工具 xlscan
CS免杀加载器 xlbpcs
Todesk/向日葵密码读取工具
导出lsass内存工具 xlrls
绕过WAF免杀工具 ByPassWAF
等等...
目前星球已满200人,价格由208元调整为218元(交个朋友啦),300名以后涨价至248元!
关注微信公众号后台回复“入群”,即可进入星落安全交流群!
往期推荐
1.
3
4
5.
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...