PC微信版本 [3.9.12.51]
在电脑上成功登录第一个微信实例后,尝试启动第二个微信时,系统会自动将第一个微信窗口激活并置顶以阻止我们运行第二个微信。推测其内部可能调用了 BringWindowToTop
或 SetForegroundWindow
函数。为验证这一点,我们使用 x64dbg 对上述函数设置断点。
不出所料,确实在 BringWindowToTop
处断下来了

接着观察堆栈窗口,查看是从哪里调用的 BringWindowToTop
,在堆栈中双击“返回到 wechatwin.TlsGetData+AC6273 自 ???
”这一项,进入调用位置。

跳转后,定位到地址 00007FFE792D74A3
处,分析调用 BringWindowToTop
的上下文。

发现 00007FFE792D749D 这里调用了 BringWindowToTop
,而且还调用了 SwitchToThisWindow
,继续往上看,寻找关键跳转
00007FFE792D7465 | 4D:85F6 | test r14,r14 |
00007FFE792D7468 | 0F84 DE03 | je wechatwin.7FFE792D784C |
上面贴的代码就是关键跳转 je
指令,它根据 ZF
(零标志位)决定是否跳转。前面的 test
指令用于判断 r14
寄存器是否为空:若 r14
为零,则设置 ZF = 1
,从而使 je
条件成立,程序发生跳转;若 r14
非零,则 ZF = 0
,不会跳转。
简而言之,这段逻辑的作用是判断 r14
是否为空:若为空,则跳过后续操作;若不为空,则继续执行 SwitchToThisWindow
和 BringWindowToTop
,实现窗口激活和置顶的行为。
继续分析 r14
的来源,看它是如何被赋值的。

00007FFE792D73A5 | FF15 BDDD | call qword ptr ds:[<FindWindowW>] |
00007FFE792D73AB | 48:8BD8 | mov rbx,rax | rax:"(2025-6-4:7:42:16:393 15104)-i/WeChat:mainwnd is null? 0\n"
00007FFE792D73AE | 33D2 | xor edx,edx |
00007FFE792D73B0 | 48:8D0D 2 | lea rcx,qword ptr ds:[0x7FFE7B0D44E0] | 00007FFE7B0D44E0:L"WeChatLoginWndForPC"
00007FFE792D73B7 | FF15 ABDD | call qword ptr ds:[<FindWindowW>] |
00007FFE792D73BD | 4C:8BF0 | mov r14,rax | rax:"(2025-6-4:7:42:16:393 15104)-i/WeChat:mainwnd is null? 0\n"
00007FFE792D73C0 | 48:85DB | test rbx,rbx |
00007FFE792D73C3 | 4C:0F45F3 | cmovne r14,rbx |
原来 r14 里面是放的是 FindWindowW
的返回值,看到这里应该能猜到微信是通过什么来判断微信是否被多开了吧?它是通过检测是否有运行的微信窗口来判断,检测两个窗口,一个是登录窗口(类名为 WeChatLoginWndForPC
),另一个是主窗口(类名为 WeChatLoginWndForPC
),只要满足一个就不允许再开微信了。
情况1:你打开了微信程序,并没有登录,此时类名为 WeChatLoginWndForPC
的窗口存在
情况2:你打开了微信,并成功登录了微信号,此时类名为 WeChatLoginWndForPC
的窗口存在
知道这些逻辑之后,想要实现多开,那么只需要让 r14
为 0 或者将关键跳转 je
改成 jmp
就可实现多开微信了,这里就直接更改 r14
为 0 吧,将 mov r14, rax
指令改为 xor r14, r14
即可实现多开。

修改位置:WeChatWin.dll 基址 + 0x31173C3