使用frida发送微信消息给好友

前言

之前说过怎么用python来发送微信文本消息,原理大概就是构造内存机器码。其实frida也可以做类似操作,构造数据和机器码,然后调用。我就不重复操作了,这里说下另一种方法。

想使用frida来发送消息这个想法很早之前就有了,只是搜了很久,一直没有frida在Windows端的操作,教程基本都是针对安卓的。

最早是在吾爱看到一篇使用frida来hook接收消息的函数,帖子看这里

我还在下面评论了下怎么用frida来发送消息,可惜没有回应,直到最近我看到一个教程(赵庆明老师的Frida快速入门/OD/CE/IDA/Python/TS/JS),链接就不放了,避免做广告的嫌疑,有兴趣的自己百度
在这里插入图片描述

准备工作

我假设你已经熟悉了frida的开发环境和使用,只讲一些关键思路

调用安卓的so函数,可以使用NativeFunction调用地址。但是 ,Windows相对于安卓而言,x86函数有多种调用约定,无法自动处理。我没有找到frida如何处理调用约定,再加上微信逆出来的函数,有些还不是标准的调用约定,也就是说很难在外部直接调用call,只能用汇编的形式来调用

那只能换一种思路来搜了,如何使用frida来写汇编,在x86平台用的是 x86writer

写汇编

比如用frida翻译一下发消息的函数
在这里插入图片描述
先分配一块内存地址,用来写汇编:

let m2 = Memory.alloc(Process.pageSize);

开始往内存地址里写入内容:

Memory.patchCode(m2, Process.pageSize, (code) => {
    console.log("code", code); 
    let asm = new X86Writer(code);
});

Memory.patchCode就是往地址里写入汇编代码的,第一个参数是内存地址,第二个参数是内存大小,第三个则是写入的函数 参数code就是m2

翻译上面的汇编:

  1. push edi
// putPushReg是push一个寄存器
asm.putPushReg('edi')
  1. lea eax, dword ptr ds:[wxNull]
    因为frida内置的lea只能将一个寄存器赋值给另一个寄存器,而这里是对地址操作,所以我这里用mov来赋值。按我的理解来看,这里应该需要先构造个指针,然后在mov给eax。但是测试发现这样操作居然报错了,直接将wxNull赋值给eax就没问题。
// let wxNull = Memory.alloc(0x100);
// let wxNullPointer = Memory.alloc(Process.pointerSize);
// wxNullPointer.writePointer(wxNull);
// asm.putMovRegAddress("eax", wxNullPointer);

let wxNull = Memory.alloc(0x100);
asm.putMovRegAddress("eax", wxNull );
  1. push 0x1
asm.putPushU32(0x1);
  1. mov edi, dword ptr ds:[pWxmsg]
    pWxmsg是个结构体,后面再看怎么赋值
asm.putMovRegAddress("edi", pWxmsg);
  1. push edi
asm.putPushReg('edi');
  1. lea edx, dword ptr ds:[wxWxid]
    正常也是应该赋值给一个指针再mov,也是报错,直接mov就没问题。可能是我理解的有问题,算了,能跑就行了
asm.putMovRegAddress('edx', wxWxid);
  1. lea ecx, dword ptr ds:[buffer]
let buffer = Memory.alloc(0x3B0);
asm.putMovRegAddress('ecx', buffer);
  1. call address
    版本还是用的上一篇python发消息里的版本。其他版本的偏移自己找下吧
let ModAddress = Process.getModuleByName('wechatwin.dll');
let callAddress = ModAddress.base.add('0x521D30');
asm.putCallAddress(callAddress);
  1. 最后三个
asm.putAddRegImm("esp", 0xC);
asm.putPopReg("edi");
asm.putRet();
  1. 写入内存
asm.flush();
构造结构体

wxWxid和pWxmsg都需要是结构体的形式,所以得构造出一个结构体,这个和python是一样操作的。分配内存,如何写地址进去

function build_struct(content) {
    let struct_address = Memory.alloc(20);
    let length = content.readUtf16String().length;
    struct_address.writePointer(content);
    struct_address.add(0x4).writeU32(length);
    struct_address.add(0x8).writeU32(length * 2);
    struct_address.add(0xC).writeU32(0);
    struct_address.add(0x10).writeU32(0);
    // console.log(hexdump(struct_address));
    return struct_address;
}
let U16Wxid = Memory.allocUtf16String(wxid);
let wxWxid = build_struct(U16Wxid);
完整代码:

效果图:
在这里插入图片描述

// 打印汇编代码, 直接抄的课程代码
function show_asm(start, length = 50) {
    for (let index = 0; index < length; index++) {
        let inst = Instruction.parse(start);
        // console.log(JSON.stringify(inst));
        let byteArray = start.readByteArray(inst.size);
        let byteCode = Array.prototype.slice.call(new Uint8Array(byteArray));
        let mCode = byteCode.map(x => x.toString(16).padStart(2, "0")).join(" ").toUpperCase();
        console.log(inst.address.toString().toUpperCase().replace("0X", "0x"), mCode.padEnd(14, " "), "\t", inst.toString().toUpperCase().replace("0X", "0x"));
        start = inst.next;
        if (start.readU32() == 0)
            break;
    }
}

// 构造微信通用结构体
function build_struct(content, length) {
    let struct_address = Memory.alloc(20);
    struct_address.writePointer(content);
    struct_address.add(0x4).writeU32(length);
    struct_address.add(0x8).writeU32(length * 2);
    struct_address.add(0xC).writeU32(0);
    struct_address.add(0x10).writeU32(0);
    // console.log(hexdump(struct_address));
    return struct_address;
}


function build_function_sendmsg() {
    let wxNull = Memory.alloc(0x100);
    let buffer = Memory.alloc(0x3B0);
    // 构建wxid结构体
    let wxid = "filehelper";
    let U16Wxid = Memory.allocUtf16String(wxid);
    let wxid_struct_address = build_struct(U16Wxid, wxid.length);
    // 构造消息结构体
    let msg = (new Date()).toJSON();
    console.log("当前发送消息内容: ", msg);
    let U16Msg = Memory.allocUtf16String(msg);
    let msg_struct_address = build_struct(U16Msg, msg.length);
    // 计算函数地址
    let ModAddress = Process.getModuleByName('wechatwin.dll');
    let callAddress = ModAddress.base.add('0x521D30');
    // 写入汇编
    let m2 = Memory.alloc(Process.pageSize);
    Memory.patchCode(m2, Process.pageSize, (code) => {
        // console.log("code", code);
        let asm = new X86Writer(code);
        asm.putPushReg('edi');
        asm.putMovRegAddress("eax", wxNull);
        asm.putPushU32(0x1);
        asm.putPushReg('eax');
        asm.putMovRegAddress("edi", msg_struct_address);
        asm.putPushReg('edi');
        asm.putMovRegAddress('edx', wxid_struct_address);
        asm.putMovRegAddress('ecx', buffer);
        asm.putCallAddress(callAddress);
        asm.putAddRegImm("esp", 0xC);
        asm.putPopReg("edi");
        asm.putRet();
        asm.flush();
    });
    show_asm(m2);
    // 调用函数, 第一个是地址,第二个是返回值类型,第三个是参数列表
    let sendmsg_call = new NativeFunction(m2, "void", []);
    sendmsg_call();
}

// build_function_sendmsg();

如果想更新最新版本,一般情况下只需要更改callAddress 后面的偏移,发文本消息一般不会怎么变

如果想再python端调用,只需要用rpc.exports导出build_function_sendmsg给python。这些都和安卓是一样的,就不重复说了

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: 很抱歉,作为AI语言模型,我不能提供关于微信hook发送视频号消息的代码。这种行为可能会违反微信使用协议,也可能会对其他用户造成不必要的麻烦和风险。建议您遵守微信的规定和原则,保持良好的网络行为和安全意识。 ### 回答2: 微信hook发送视频号消息的代码可以参考如下: ```python import frida def on_message(message, data): if message['type'] == 'send': payload = message['payload'] if 'message' in payload and 'mp_video_xml' in payload['message']: # 提取视频号的XML数据 mp_video_xml = payload['message']['mp_video_xml'] # 在此对视频号消息进行处理或记录 print(mp_video_xml) # 启动Frida session = frida.get_usb_device().attach('WeChat') # 加载JavaScript脚本 js_code = """ function hookSendMessage() { // 寻找消息发送的入口 var sendMessage = Module.findExportByName("WeChat", "SendMessage") if (sendMessage) { console.log("SendMessage address: " + sendMessage) // hook发送消息的函数 Interceptor.attach(sendMessage, { onEnter: function (args) { // 提取消息内容 var xmlBuffer = args[1] var xmlData = xmlBuffer.readCString() // 解析XML数据 var xmlDoc = new XMLDocument(xmlData) var messageNode = xmlDoc.getRootNode() var messageType = messageNode.getAttribute("datatype") if (messageType == "47") { var mpVideoXml = messageNode.getNodeByName("wxv") send({message: {mp_video_xml: mpVideoXml}}) } } }) } } // 调用函数进行hook hookSendMessage() """ script = session.create_script(js_code) script.on('message', on_message) script.load() ``` 上述代码使用Frida来进行hook操作,通过hooking WeChat的SendMessage函数,获取发送消息的XML数据,从中解析出视频号消息的XML字段`wxv`,并进行处理或记录。 注意,此代码只是演示了hook操作的基本原理,具体实现还需要结合微信的实际运行环境来进行调试和适配。 ### 回答3: 要实现微信hook发送视频号消息的代码,需要借助一些工具和技术。下面是一个基本的 Python 代码示例: ```python import frida def on_message(message, data): if message['type'] == 'send': if 'video' in message['payload']: video_url = message['payload']['video'] # 在这里可以对视频链接进行处理,比如下载到本地或者转发给其他用户 print(f"收到视频链接:{video_url}") def hook_wechat_send_video(): # 获取微信进程 session = frida.attach("com.tencent.mm") # 读取 JavaScript hooking 脚本 with open("hook_wechat_send_video.js", "r") as f: hook_script = f.read() # 加载 JavaScript hooking 脚本 script = session.create_script(hook_script) # 设置消息回调函数 script.on("message", on_message) # 运行 JavaScript hooking 脚本 script.load() # 保持脚本持续运行 frida.resume(pid) # 执行 Hook hook_wechat_send_video() # 保持主线程运行 while True: pass ``` 上述代码中,我们使用了 `frida` 这个 Python 包来实现与手机应用的通信和 hook 功能。通过运行 `hook_wechat_send_video()` 函数,首先获取微信应用进程,然后加载 JavaScript hooking 脚本。在回调函数 `on_message()` 中,我们可以对接收到的视频链接进行任意处理,比如打印、下载或转发给其他用户。最后,保持主线程运行以保证持续监听微信应用的消息。 请注意,以上代码只是提供一个示例,并不能直接运行,因为具体的 hook 逻辑需要写在 JavaScript 脚本 `hook_wechat_send_video.js` 中,并且需要根据具体的微信版本和手机操作系统进行适配。对于较新版本的微信可能需要更高级的 hook 技术,同时需要越狱或者 root 权限。因此,如果需要实现微信 hook 功能,建议参考专业的 hook 工具和文档,并遵守法律和道德规范。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值