在 MAS 版本的 QQ 更新到版本 5.5.1 之后,终于支持撤回消息了(当然也就不能防撤回了)
通过万能的 Google 查找了一下防撤回方法,没想到还真的找到了
尝试一:反编译二进制文件(参考:美女驱动型程序猿)
用 Hopper Disassembler 打开 /Applications/QQ.app/Contents/MacOS/QQ
需要注意的是,当二进制文件被打开之后不要急于操作,要等待右下角
Working
消失,这个时间会非常长在左边
Labels
一栏搜索handleRecallNotify
关键词,得到如下结果选中
push rbp
这一行,按住Option + A
并输入ret
,之后再点击Assembler and Go Next
并按ESC
结束编辑,大概意思是,直接让这个函数返回,不做任何操作(为啥每次都把 rbp 看成 rbq 呢?捂脸……)按住
Shift + Command + E
来输出新的二进制文件,会提示是否移除原有的签名,确认即可,这个时候把新的二进制文件复制到 /Applications/QQ.app/Contents/MacOS/ 把原来的替换掉就行
P.S. 经过参考链接评论区提醒,在测试发现修后的 QQ 把缓存全都放到了 ~/Documents/,本来好好的文档目录多出了一堆乱七八糟的文件,对于强迫症患者而言是绝对不能忍的
尝试二:动态库注入 hook(参考:0xBBC)
新建 OC 源文件
QQUnrecall.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void handleRecallNotifyIsOnline(id _i, SEL _s, void * _p, BOOL _b) {
NSLog(@"已经阻止 QQ 撤回一条消息");
}
static void __attribute__((constructor)) initialize(void) {
method_setImplementation(
class_getInstanceMethod(
NSClassFromString(@"QQMessageRevokeEngine"),
@selector(handleRecallNotify:isOnline:)
),
(IMP)&handleRecallNotifyIsOnline
);
}编译成动态库文件
clang -dynamiclib -framework Foundation QQUnrecall.m -o libQQUnrecall.dylib
使用
export DYLD_INSERT_LIBRARIES=libQQUnrecall.dylib
后运行/Applications/QQ.app/Contents/MacOS/QQ
得到如下测试结果简单包装一下避免每次通过终端启动 QQ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
char path[M], buff[M];
unsigned long len, i;
int main(int argc, char **argv) {
strcpy(path, argv[0]);
len = strlen(path);
for (i = len - 1; i; i--) {
if (path[i] == '/')
break ;
path[i] = 0;
}
sprintf(buff, CMD, path);
system(buff);
return 0;
}
P.S. 点击 这里 下载成品(macOS 10.12 以下版本最好自行编译,否则可能会出现问题),理论上只要撤回函数名称和参数不改,对于所有版本 QQ 都可用此方法