微信 macOS 客户端无限多开功能实践

2017-03-18 10:05:35来源:https://blog.sunnyyoung.net/wei-xin-macos-ke-hu-duan-wu-xian作者:Sunnyyoung's Blog人点击

继上一次的 微信 macOS 客户端拦截撤回功能实践 之后,有热心网友给我提了个 issue :macOS微信客户端的多开问题,才发现原来在 macOS 上微信客户端是不能多开的,于是接受挑战~


0x00 传统多开方法

在 macOS 平台上,大部分应用都是支持多开的,比如:


⌘ + N 大法:适用于 QQ
open -n /Applications/xxx.app 大法:适用于大部分的应用

那么对于微信客户端来说, 以上两种方法都是无效的 。其中第一种只能新建新的聊天对象),第二种直接什么反应都没有。


但是也没有难倒机智的广大网民,网上流传的 macOS 平台微信客户端多开方法有:


微信客户端 + 网页客户端(最笨的做法)
open /Applications/WeChat.app/Contents/MacOS/WeChat 直接通过命令行打开微信包里的二进制文件(会弹出一个 Terminal 窗口什么鬼,而且还不能关掉=。=)
0x01 准备工作
安装各种工具
Dump 出头文件
通过 Hopper Disassembler 导出静态分析文件
...

这里就不再赘述了,参考之前的实践文。


0x02 找出入口

由上文所说到的网传多开方法得知是通过 open 命令直接打开二进制文件可以实现双开,那么为什么打开第三个就不行呢,执行命令打开第三个微信客户端:



可以看到,命令行运行结果提示 Instance is already running! ,既然有这样的提示,那么就可以作为寻找入口的线索,因为一般这种 Log 都是 Hardcode 在代码里的,于是我们又可以祭出神器: Hopper Disassembler!


通过 Hopper Disassembler 一下子就能定位出该字符串所在的方法:



居然在 EntryPoint() 中,也就是应用的 main() 方法,不过这不是重点,重点可以看出判断客户端是否多开的方法在 if 语句中: if ([CUtility HasWechatInstance] != 0x0) {...} ,因此可以更近一步看看 [CUtility HasWechatInstance] 方法的内部实现:



Hopper Disassembler 解析出的伪代码已经接近源码,阅读难度大大降低。同时可以发现微信客户端是通过读取应用 BundleIdentifier 的对应实例个数来判断应用是否多开,从 if (r12 >= 0x2) {...} 中得知最多可以存在两个实例,这就是为什么上文中通过 open 命令可以双开的原因吧,但是为什么不能通过 open -n 直接打开呢,还没弄清楚。


因此,猜想是通过修改 [CUtility HasWechatInstance] 的返回值来绕过多开检测。


0x03 验证猜想

验证猜想的主要方法是通过动态调试,那么又可以祭出一神器:LLDB!


使用 LLDB 进行调试前我们需要找出断点地址:



上文中提及的 r12 变量即为实例数量变量,因此我们可以在 mov r12, rax 上做手脚,即断点地址为 0x0000000100511644 。由于该方法在 main() 方法中,因此不能通过 attach process 方法来进行动态调试。于是利用 LLDB 创建 Target 并预先设置好断点,通过 LLDB process launch 来启动应用并触发断点:



执行 ni ,并执行 p $r12 查看值:



因为没有打开客户端,因此实例数量值为0,于是可以通过 LLDB 的 register write 将 r12 值修改为 2,并执行 c 让应用跳出断点继续运行:



果然出现提示 Instance is already running! ,然而并没有任何微信客户端实例正在运行,因此可以得出结论猜想是正确的!


0x04 编写 Tweak

同样的使用 constructor 来进行 Tweak。


constructor / destructor


顾名思义,构造器和析构器,加上这两个属性的函数会在分别在可执行文件(或 shared library)load 和 unload 时被调用,可以理解为在 main() 函数调用前和 return 后执行。


参考资料: Clang Attributes 黑魔法小记


__attribute__((constructor(102))) static void multipleInstanceTweak(void) {
Class class = object_getClass(NSClassFromString(@"CUtility"));
SEL selector = NSSelectorFromString(@"HasWechatInstance");
Method method = class_getInstanceMethod(class, selector);
IMP imp = imp_implementationWithBlock(^(id self) {
return 0; //永远返回0
});
class_replaceMethod(class, selector, imp, method_getTypeEncoding(method));
}

以上,通过方法替换,使 [CUtility HasWechatInstance] 永远返回 0,通过 open -n 来打开多个微信便可以实现微信 macOS 客户端无限多开。


0x05 最后

通过命令行来多开会不会有点麻烦?通过 Tweak 来添加快捷的多开方式?


先扔出个项目源码: WeChatTweak-macOS


最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台