macOSiOS开发iOS开发

震惊! macOS 版微信竟可以这样消息防撤回

2017-04-21  本文已影响9070人  TKkk

2017-10-11 ==> 新增窗口置顶 & 会话多选删除
2017-09-17 ==> 新增置底 & 免认证
2017-09-11 ==> 修复聊天记录消失的bug
2017-08-23 ==> 支持多回复
2017-08-16 ==> 新增远程控制 & 微信多开


一、 前言

前一阵子入了 iOS 逆向的坑,整了个微信机器人,不过由于是用自己的证书打包,因此只能用7天,之后还得重新打包,实在麻烦。于是就拿 macOS 动刀了。

本篇主要制作 macOS 版微信的插件,实现消息防撤回与自动回复的功能,从而熟悉 mac OS 插件制作,由于 (lan ai) macOS 逆向分析与 iOS 类似,且不像 iOS 有那么多的工具,因此花费的时间较多,这里暂不阐述。之后有时间再整理 iOS 逆向分析过程。

消息防撤回.gif
自动回复.gif

二、安装与使用

自动回复设置.png

三、plugin 制作

3.1 创建Framework

使用 Xcode 创建 macOS 的 Cocoa Framework.

创建Cocoa Framework.png

3.2 Edit Scheme…

编辑 Scheme,在 Debug 模式下启动 WeChat。


Edit Scheme.png choose executable.gif

3.3 添加Run Script

在 Build Phases 中添加 Run Script

add run scripe.gif

Script 内容如下

其中 app_name为要注入的app名称,framework_name`为插件名称。

#!/bin/bash
# 要注入的的app
app_name="WeChat"
# 此framework名字
framework_name="WeChatPlugin"
app_bundle_path="/Applications/${app_name}.app/Contents/MacOS"
app_executable_path="${app_bundle_path}/${app_name}"
app_executable_backup_path="${app_executable_path}_backup"
framework_path="${app_bundle_path}/${framework_name}.framework"
# 备份WeChat原始可执行文件
if [ ! -f "$app_executable_backup_path" ]
then
cp "$app_executable_path" "$app_executable_backup_path"
fi
cp -r "${BUILT_PRODUCTS_DIR}/${framework_name}.framework" ${app_bundle_path}
# 注入动态库
./insert_dylib --all-yes "${framework_path}/${framework_name}" "$app_executable_backup_path" "$app_executable_path"

其中insert_dylib来源于github(与iOS的insert_dylib不同)

3.4 创建 main.mm

创建 main.mm 文件,添加构造方法。

main.mm.png

此时,一运行,即可执行initalize中的方法,并启动微信。

因此,我们就可以在这里愉快的进行hook!!!

3.5 注意

四、愉快的 hook (以撤回消息为例)

4.1 创建 NSObject 分类

新建 NSObject 分类,加入类方法+(void)hookWeChat;并在 main.mm 中执行该方法。之后所有的 hook 都可以在该类方法中进行。

#import "WeChat+hook.h"

static void __attribute__((constructor)) initialize(void) {
    NSLog(@"++++++++ WeChatPlugin loaded ++++++++");
    [NSObject hook_WeChat];
}

4.2 寻找注入点

首先使用class-dump,dump 出微信的头文件信息。(如何使用请左转iOS 逆向 - 微信 helloWorld)
因为在 iOS 中,微信撤回的函数为- (void)onRevokeMsg:(id)arg1;因此,我们在微信的头文件中搜索该方法,最终在MessageService.h中找到。

4.3 runtime 登场

到这里就要开始进行 hook 了,在+(void)hookWeChat;中进行methodExchange
MessageService- (void)onRevokeMsg:(id)arg1;方法实现替换成NSObject- (void)hook_onRevokeMsg:(id)msg方法。

+ (void)hookWeChat {
    //      微信撤回消息
    Method originalMethod = class_getInstanceMethod(objc_getClass("MessageService"), @selector(onRevokeMsg:));
    Method swizzledMethod = class_getInstanceMethod([self class], @selector(hook_onRevokeMsg:));
    if(originalMethod && swizzledMethod) {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

- (void)hook_onRevokeMsg:(id)msg {
    NSLog(@"=== TK-LOG-msg = %@===",msg);
    [self hook_onRevokeMsg:msg];
}

4.4 验证

由于是使用 Xcode,就不用像 iOS 逆向那样只能用 lldb 调试了。可以在- (void)hook_onRevokeMsg:(id)msg中打个断点,然后撤回消息看是否会触发。结果证明该方法确实是微信消息撤回的处理方法。

4.5 使用 Hopper Disassembler

接着我们在- (void)hook_onRevokeMsg:(id)msg中直接return就可以了。
然而这时候看不到到底是撤回了哪一条信息。我们可以在用户撤回的时候将下面的内容改成"拦截 xx 的一条撤回消息:xxxx"。

撤回.png

这时候就要使用神器 Hopper Disassembler.用hopper Disassembler 进行分析,分析- (void)onRevokeMsg:(id)arg1;的实现。(分析过程与 iOS 类似,这里暂不阐述)
最终得到了主要的代码实现。(完整代码在工程中)

MessageService *msgService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")];
MessageData *revokeMsgData = [msgService GetMsgData:session svrId:[newmsgid integerValue]];
MessageData *newMsgData = ({
        MessageData *msg = [[objc_getClass("MessageData") alloc] initWithMsgType:0x2710];
        [msg setFromUsrName:revokeMsgData.toUsrName];
        [msg setToUsrName:revokeMsgData.fromUsrName];
        [msg setMsgStatus:4];
        [msg setMsgContent:newMsgContent];
        [msg setMsgCreateTime:[revokeMsgData msgCreateTime]];
        [msg setMesLocalID:[revokeMsgData mesLocalID]];
        
        msg;
    });
    
[msgService AddLocalMsg:session msgData:newMsgData];

五、效果

点击菜单栏-帮助-开启消息防撤回,当好友撤回消息是可以看到提示。

消息防撤回.gif

六、小结

最终我们得到了拥有消息防撤回与自动回复的 macOS 版微信,虽然整个过程挺简单的,但主要目标是为了熟悉了如何制作 macOS 插件的过程,这样以后就可以给 macOS 上的 app 增加点小功能了。

由于本人还只是个逆向新手,难免会有所疏漏,还请大牛们指正。
本项目仅供学习参考。

七、参考

如何愉快地在Mac上刷朋友圈

上一篇 下一篇

猜你喜欢

热点阅读