|
1 |
| -[TOC] |
2 |
| -# 震惊!!! macOS版微信竟可以这样消息防撤回 |
3 |
| -## 一、 前言 |
4 |
| -前一阵子入了 iOS 逆向的坑,整了个微信机器人,不过由于是用自己的证书打包,因此只能用7天,之后还得重新打包,实在麻烦。于是就拿macOS动刀了。 |
5 | 1 |
|
6 |
| -本篇主要制作 mac OS 版微信的插件,实现<a>消息防撤回与自动回复</a>的功能,从而熟悉 mac OS 插件制作,由于 ~~(lan ai)~~ mac OS 逆向分析与 iOS 类似,且不像 iOS 有那么多的工具,因此花费的时间较多,这里暂不阐述。~~之后有时间再整理 iOS 逆向分析过程。~~ |
7 |
| - |
8 |
| -* 基本原理:与 iOS 注入动态库类似,通过 app 启动时调用我们注入的动态库,从而进行 hook。 |
9 |
| -* 插件 GitHub 地址: [WeChatPlugin](https://github.com/tusiji7/WeChatPlugin) |
10 |
| -* Demo 演示 |
| 2 | +本插件主要实现 macOS 版微信的<a>消息防撤回与自动回复</a>的功能,详细内容,请参考[我的博客](http://www.jianshu.com/p/7f65287a2e7a) |
| 3 | +### Demo 演示 |
11 | 4 |
|
12 | 5 | 消息防撤回
|
13 | 6 | 
|
14 | 7 |
|
15 | 8 | 自动回复
|
16 | 9 | 
|
17 | 10 |
|
18 |
| -## 二、安装与使用 |
19 |
| -* 下载 WeChatPlugin, 先进行 build (`command + B`),之后 run (`command + R`)即可启动微信,此时插件注入完成。~~(若出现 error 请往下看 **3.5 注意** 部分)~~ |
20 |
| - |
21 |
| -* 登录微信,可在**菜单栏-帮助**中看到消息防撤回与自动回复。 |
| 11 | +### 安装 |
| 12 | +* 下载 WeChatPlugin, 先进行 Build (`command + B`),之后 Run (`command + R`)即可启动微信,此时插件注入完成。 |
| 13 | + |
| 14 | +* 若 Error,提示无权限,请对 WeChat 赋予权限。 |
| 15 | +`sudo chmod -R 777 /Applications/WeChat.app` |
| 16 | +* 若 Error,提示找不到 Framework,先进行 Build。 |
22 | 17 |
|
| 18 | +* 登录微信,在**菜单栏-帮助**中看到消息防撤回与自动回复即安装成功。 |
23 | 19 | 
|
24 | 20 |
|
| 21 | +### 使用 |
| 22 | + |
25 | 23 | * 消息防撤回:点击`开启消息防撤回`或者快捷键`command + t`,即可开启、关闭。
|
26 | 24 | * 自动回复:点击`开启自动回复`或者快捷键`conmand + k`,将弹出自动回复设置的窗口,在窗口中输入关键字与回复内容,点击保存即可。~~(若无关键字保存,则所有消息都会自动回复)~~
|
27 | 25 |
|
28 | 26 | 
|
29 | 27 |
|
30 |
| -* 卸载 |
31 |
| - |
32 |
| - 在 `/Applications/WeChat.app/Contents/MacOS` 目录中,删除 `WeChat` 与 `WeChatPlugin.framework`,将`WeChat_backup` 重命名为 `WeChat` 即可。 |
33 |
| - |
34 |
| -## 三、plugin 制作 |
35 |
| -### 3.1 创建Framework |
36 |
| -使用 Xcode 创建 macOS 的 Cocoa Framework. |
37 |
| - |
38 |
| - |
39 |
| - |
40 |
| - |
41 |
| -### 3.2 Edit Scheme… |
42 |
| -编辑 scheme,在 debug 模式下启动 WeChat。 |
43 |
| - |
44 |
| - |
45 |
| - |
46 |
| - |
47 |
| -###3.3 添加Run Script |
48 |
| -在 Build Phases 中添加 run script |
49 |
| - |
50 |
| - |
51 |
| - |
52 |
| -script 内容如下 |
53 |
| - |
54 |
| -``` bash |
55 |
| -#!/bin/bash |
56 |
| -# 要注入的的app |
57 |
| -app_name="WeChat" |
58 |
| -# 此framework名字 |
59 |
| -framework_name="WeChatPlugin" |
60 |
| -app_bundle_path="/Applications/${app_name}.app/Contents/MacOS" |
61 |
| -app_executable_path="${app_bundle_path}/${app_name}" |
62 |
| -app_executable_backup_path="${app_executable_path}_backup" |
63 |
| -framework_path="${app_bundle_path}/${framework_name}.framework" |
64 |
| -# 备份WeChat原始可执行文件 |
65 |
| -if [ ! -f "$app_executable_backup_path" ] |
66 |
| -then |
67 |
| -cp "$app_executable_path" "$app_executable_backup_path" |
68 |
| -fi |
69 |
| -cp -r "${BUILT_PRODUCTS_DIR}/${framework_name}.framework" ${app_bundle_path} |
70 |
| -# 注入动态库 |
71 |
| -./insert_dylib --all-yes "${framework_path}/${framework_name}" "$app_executable_backup_path" "$app_executable_path" |
72 |
| -``` |
73 |
| - |
74 |
| -**其中insert_dylib来源于[github](https://github.com/Tyilo/insert_dylib)(~~与iOS的insert_dylib不同~~)** |
75 |
| - |
76 |
| -### 3.4 创建 main.mm |
77 |
| - |
78 |
| -创建 main.mm 文件,添加构造方法。 |
79 |
| - |
80 |
| - |
81 |
| - |
82 |
| -此时,一运行,即可执行`initalize`中的方法,并启动微信。 |
83 |
| - |
84 |
| -<a>因此,我们就可以在这里愉快的进行hook!!!</a> |
85 |
| - |
86 |
| -### 3.5 **注意** |
87 |
| - |
88 |
| -* 若 error,提示无权限,请对 WeChat 赋予权限。 |
89 |
| -`sudo chmod -R 777 /Applications/WeChat.app` |
90 |
| -* 若 error,提示找不到 framework,先进行 build。 |
91 |
| - |
92 |
| -## 四、愉快的 hook (以撤回消息为例) |
93 |
| -### 4.1 创建 NSObject 分类 |
94 |
| -新建 NSObject 分类,加入类方法`+(void)hookWeChat;`并在 main.mm 中执行该方法。之后所有的hook都可以在该类方法中进行。 |
95 |
| - |
96 |
| -``` |
97 |
| -#import "WeChat+hook.h" |
98 |
| -
|
99 |
| -static void __attribute__((constructor)) initialize(void) { |
100 |
| - NSLog(@"++++++++ WeChatPlugin loaded ++++++++"); |
101 |
| - [NSObject hook_WeChat]; |
102 |
| -} |
103 |
| -``` |
104 |
| - |
105 |
| -### 4.2 寻找注入点 |
106 |
| -首先使用`class-dump`,dump 出微信的头文件信息。~~(如何使用请左转[iOS 逆向 - 微信 helloWorld](http://www.jianshu.com/p/04495a429324))~~ |
107 |
| -因为在 iOS 中,微信撤回的函数为`- (void)onRevokeMsg:(id)arg1;`因此,我们在微信的头文件中搜索该方法,最终在`MessageService.h`中找到。 |
108 |
| - |
109 |
| -### 4.3 runtime 登场 |
110 |
| -到这里就要开始进行 hook 了,在`+(void)hookWeChat;`中进行`methodExchange`。 |
111 |
| -将`MessageService`的`- (void)onRevokeMsg:(id)arg1;`方法实现替换成`NSObject`的`- (void)hook_onRevokeMsg:(id)msg`方法。 |
112 |
| - |
113 |
| -``` |
114 |
| -+ (void)hookWeChat { |
115 |
| - // 微信撤回消息 |
116 |
| - Method originalMethod = class_getInstanceMethod(objc_getClass("MessageService"), @selector(onRevokeMsg:)); |
117 |
| - Method swizzledMethod = class_getInstanceMethod([self class], @selector(hook_onRevokeMsg:)); |
118 |
| - if(originalMethod && swizzledMethod) { |
119 |
| - method_exchangeImplementations(originalMethod, swizzledMethod); |
120 |
| - } |
121 |
| -} |
122 |
| -
|
123 |
| -- (void)hook_onRevokeMsg:(id)msg { |
124 |
| - NSLog(@"=== TK-LOG-msg = %@===",msg); |
125 |
| - [self hook_onRevokeMsg:msg]; |
126 |
| -} |
127 |
| -``` |
128 |
| - |
129 |
| -### 4.4 验证 |
130 |
| -由于是使用 Xcode,就不用像 iOS 逆向那样只能用 lldb 调试了。可以在`- (void)hook_onRevokeMsg:(id)msg`中打个断点,然后撤回消息看是否会触发。结果证明该方法确实是微信消息撤回的处理方法。 |
131 |
| - |
132 |
| -### 4.5 使用 Hopper Disassembler |
133 |
| -接着我们在`- (void)hook_onRevokeMsg:(id)msg`中直接`return`就可以了。 |
134 |
| -然而这时候看不到到底是撤回了哪一条信息。我们可以在用户撤回的时候将下面的内容改成"拦截 xx 的一条撤回消息:xxxx"。 |
135 |
| - |
136 |
| - |
137 |
| - |
138 |
| -这时候就要使用神器 `Hopper Disassembler`.用`hopper Disassembler` 进行分析,分析`- (void)onRevokeMsg:(id)arg1;`的实现。~~(分析过程与iOS类似,这里暂不阐述)~~ |
139 |
| -最终得到了主要的代码实现。~~(完整代码在工程中)~~ |
140 |
| - |
141 |
| -``` |
142 |
| -MessageService *msgService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")]; |
143 |
| -MessageData *revokeMsgData = [msgService GetMsgData:session svrId:[newmsgid integerValue]]; |
144 |
| -MessageData *newMsgData = ({ |
145 |
| - MessageData *msg = [[objc_getClass("MessageData") alloc] initWithMsgType:0x2710]; |
146 |
| - [msg setFromUsrName:revokeMsgData.toUsrName]; |
147 |
| - [msg setToUsrName:revokeMsgData.fromUsrName]; |
148 |
| - [msg setMsgStatus:4]; |
149 |
| - [msg setMsgContent:newMsgContent]; |
150 |
| - [msg setMsgCreateTime:[revokeMsgData msgCreateTime]]; |
151 |
| - [msg setMesLocalID:[revokeMsgData mesLocalID]]; |
152 |
| - |
153 |
| - msg; |
154 |
| - }); |
155 |
| - |
156 |
| -[msgService AddLocalMsg:session msgData:newMsgData]; |
157 |
| -``` |
158 |
| - |
159 |
| -## 五、效果 |
160 |
| -点击 `菜单栏-帮助-开启消息防撤回`,当好友撤回消息是可以看到提示。 |
161 |
| - |
162 |
| - |
163 |
| -## 六、小结 |
164 |
| -最终我们得到了拥有消息防撤回与自动回复的 macOS 版微信,虽然整个过程挺简单的,但主要目标是为了熟悉了如何制作 macOS 插件的过程,这样以后就可以给 macOS 上的 app 增加点小功能了。 |
165 |
| - |
166 |
| -由于本人还只是个逆向新手,难免会有所疏漏,还请大牛们指正。 |
167 |
| -本项目仅供学习参考。 |
168 |
| - |
169 |
| -## 七、参考 |
| 28 | +### 卸载 |
170 | 29 |
|
171 |
| -[如何愉快地在Mac上刷朋友圈](http://www.iosre.com/t/mac/7014/2) |
| 30 | +在 `/Applications/WeChat.app/Contents/MacOS` 目录中,删除 `WeChat` 与 `WeChatPlugin.framework`,将`WeChat_backup` 重命名为 `WeChat` 即可。 |
172 | 31 |
|
0 commit comments