Skip to content

Commit 9c6cb7e

Browse files
authored
Update README.md
1 parent bba7bdc commit 9c6cb7e

File tree

1 file changed

+13
-154
lines changed

1 file changed

+13
-154
lines changed

README.md

Lines changed: 13 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,31 @@
1-
[TOC]
2-
# 震惊!!! macOS版微信竟可以这样消息防撤回
3-
## 一、 前言
4-
前一阵子入了 iOS 逆向的坑,整了个微信机器人,不过由于是用自己的证书打包,因此只能用7天,之后还得重新打包,实在麻烦。于是就拿macOS动刀了。
51

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 演示
114

125
消息防撤回
136
![消息防撤回.gif](http://upload-images.jianshu.io/upload_images/965383-30cbea645661e627.gif?imageMogr2/auto-orient/strip)
147

158
自动回复
169
![自动回复.gif](http://upload-images.jianshu.io/upload_images/965383-b61b6d983c90e0c5.gif?imageMogr2/auto-orient/strip)
1710

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。
2217

18+
* 登录微信,在**菜单栏-帮助**中看到消息防撤回与自动回复即安装成功。
2319
![菜单栏-帮助.png](http://upload-images.jianshu.io/upload_images/965383-7c6ec7a738f81c0c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2420

21+
### 使用
22+
2523
* 消息防撤回:点击`开启消息防撤回`或者快捷键`command + t`,即可开启、关闭。
2624
* 自动回复:点击`开启自动回复`或者快捷键`conmand + k`,将弹出自动回复设置的窗口,在窗口中输入关键字与回复内容,点击保存即可。~~(若无关键字保存,则所有消息都会自动回复)~~
2725

2826
![自动回复设置.png](http://upload-images.jianshu.io/upload_images/965383-060903126e9da7a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2927

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-
![创建Cocoa Framework.png](http://upload-images.jianshu.io/upload_images/965383-f975dee2f0c956f2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
40-
41-
### 3.2 Edit Scheme…
42-
编辑 scheme,在 debug 模式下启动 WeChat。
43-
![Edit Scheme.png](http://upload-images.jianshu.io/upload_images/965383-26dbb068acb8998f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
44-
45-
![choose executable.gif](http://upload-images.jianshu.io/upload_images/965383-7fbd4dc6e8d161dc.gif?imageMogr2/auto-orient/strip)
46-
47-
###3.3 添加Run Script
48-
在 Build Phases 中添加 run script
49-
50-
![add run scripe.gif](http://upload-images.jianshu.io/upload_images/965383-c4c94d035b7def3c.gif?imageMogr2/auto-orient/strip)
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-
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/965383-bd6a3a36c065a8b2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
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-
![撤回.png](http://upload-images.jianshu.io/upload_images/965383-3ca5031305263ca2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
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-
![消息防撤回.gif](http://upload-images.jianshu.io/upload_images/965383-30cbea645661e627.gif?imageMogr2/auto-orient/strip)
162-
163-
## 六、小结
164-
最终我们得到了拥有消息防撤回与自动回复的 macOS 版微信,虽然整个过程挺简单的,但主要目标是为了熟悉了如何制作 macOS 插件的过程,这样以后就可以给 macOS 上的 app 增加点小功能了。
165-
166-
由于本人还只是个逆向新手,难免会有所疏漏,还请大牛们指正。
167-
本项目仅供学习参考。
168-
169-
## 七、参考
28+
### 卸载
17029

171-
[如何愉快地在Mac上刷朋友圈](http://www.iosre.com/t/mac/7014/2)
30+
`/Applications/WeChat.app/Contents/MacOS` 目录中,删除 `WeChat``WeChatPlugin.framework`,将`WeChat_backup` 重命名为 `WeChat` 即可。
17231

0 commit comments

Comments
 (0)