在使用 PC 版微信时,遇到这样一个问题:在打游戏或进行全屏操作时,微信的语音/视频通话弹窗会突然跳出,打断当前任务,造成不便,很让人抓狂。
微信设置中虽然提供了关闭“语音和视频通话通知声音”的选项,但实测发现,该设置只能关闭提示音,并不能阻止弹窗本身的出现。
为了解决这个问题,本文尝试通过修改 WeChatWin.dll
的方式来实现对通话弹窗的屏蔽。
实现原理
可以发现每当收到视频或语音电话时这个弹窗总是固定出现在桌面的右下角,内部的代码实现应该就是:创建窗口(CreateWindowExW
)—->移动窗口(SetWindowPos
),经过分析,也确实如此,那么只需要阻止创建窗口即可,语音/视频弹框的窗口类名是 ILinkVoipTrayWnd
根据这个类名来阻止。
好了,废话不多说,接下来开始操作吧。
第一步,扩展 .rsrc 节的大小
PC微信x64版本 [3.9.12.51]
使用 die 来查看 WeChatWin.dll PE 节信息

用x64dbg分析了下,发现这些段都没有足够的空白空间写入屏蔽弹窗的汇编代码,所以只能选一个段来扩大。为了方便,这里选择扩大最后一个 .rsrc 段,为什么选最后一个段?因为这些段信息在物理文件中是按顺序储存的,改中间的段就会影响到其它段的物理文件偏移。
可以看到图中最后一行是有个附加信息的,我们先根据这个物理文件偏移用 winhex 单独提取出来放着,等改完之后再附加到文件末尾,它的偏移不用管,会根据最后一个 .rsrc 段自动计算。
从节信息图中可以看出,附加的证书信息数据范围就是从 0x60a6800 到文件末尾,先把这个证书信息数据单独存到文件,然后再回到 winhex 移除这个范围的数据,移除之后要保存更新一下 dll 文件


修改大小之前需要了解一些知识:
- 实际大小(文件中) SizeOfRawData 对齐到 FileAlignment(通常 0x200)
- 虚拟大小(内存中) VirtualSize 可不对齐,系统加载时自动按 SectionAlignment(通常 0x1000)对齐,可以是任意值,但通常不超过 SizeOfRawData
- 在计算机科学和编程中,内存区域通常用「左闭右开区间」表示,即:[start, end),包含起始地址 start,不包含结束地址 end
从PE信息中可以看到 .rsrc 的 SizeOfRawData(文件实际大小)是 0x600,VirtualSize(虚拟大小)是 0x508,按照 FileAlignment 对齐规定,扩大后的大小是 0x200 的整数倍就行,这里就在原有实际大小上增大 0x200 个字节吧,增大后的内存范围就是左闭右开区间 [0x060a6200,0x060a6200 + 0x600 + 0x200),虚拟大小跟实际大小保持一致
我们用 die 工具重新载入 dll 更改一下


更改完节的大小后还有一个重要的步骤,就是更新 SizeOfImage 的大小,SizeOfImage 是整个 PE 映像加载到内存后占用的总大小,它涵盖了所有节的映像内存区域,包括每个节在内存中的位置和大小。
SizeOfImage = (最后一个节的 VirtualAddress + 对齐后的 VirtualSize) 对齐到 SectionAlignment(0x1000)
看上图,VirtualAddress = 0x61d6000,VirtualSize = 0x800,通过公式可以算出 SizeOfImage = 0x61D7000,我们在 die 工具中转到更改 SizeOfImage 的地方

发现了吗?默认就是 0x61D7000,所以这里不用改动,SizeOfImage 宁可大也不可小,否则会触发错误 0xc000007b 或 “映像损坏”。
接着再用 winhex 在文件末尾处开始追加填充 0x200 个空字节,即十进制 512 个字节,增大后的 .rsrc 节表示的内存范围就是左闭右开区间 [0x060a6200,0x60A6A00),即附加的证书数据是从 0x60A6A00 开始的

把之前保存的附加证书追加到文件末尾,从 0x60A6A00 开始粘贴,粘贴完之后保存更改

验证一下是否附加证书成功,用 die 工具查看 pe 信息,根据下面两张图可以看到附加成功了,自动计算了偏移,且成功显示证书信息


更改 .rsrc 的内存权限标志位,改成可读可运行,要不然你在这个节上写的汇编代码只能读,不能运行,所以必须要改

最后一步,将更改后的 WeChatWin.dll 替换到微信目录下,测试微信是否能正常打开,如果微信能正常打开,则代表成功更改。
第二步,导入屏蔽弹窗汇编代码
x64dbg 版本:

x64dbg 屏蔽微信语音/视频弹窗补丁下载地址:https://be7v.top/static/WeChatWin.1337
至此,我们已经成功扩展了 .rsrc 节的大小,现在开始写入屏蔽弹窗的汇编代码(逆向过程就不写了,比较简单),先把更改后的 dll 替换到微信目录,然后用 x64dbg 打开微信主程序,打开之后应该会自动断下来,一直按 F9 直到微信窗口出现,然后右键汇编代码界面选择导入补丁

导入之后点击修补文件,意思是把补丁的更改永久应用到 dll 文件上,我们选择保存到桌面,这时候得到的 WeChatWin.dll 就带有去除语音弹窗功能了,关闭 x64dbg,将修补后的dll再次替换到微信目录,然后测试屏蔽弹窗功能即可。

屏蔽弹窗的汇编代码:
这里是微信调用 CreateWindowExW 创建语音弹窗的地方
00007FFF02544B5B | 894424 20 | mov dword ptr ss:[rsp+0x20],eax |
00007FFF02544B5F | FF15 7B09EC00 | call qword ptr ds:[<CreateWindowExW>] |
00007FFF02544B65 | E9 981A8A02 | jmp wechatwin.7FFF04DE6602 |
00007FFF02544B6A | 90 | nop |
这里是屏蔽弹窗代码
00007FFF04DE6600 | 0000 | add byte ptr ds:[rax],al |
00007FFF04DE6602 | 48:89C2 | mov rdx,rax |
00007FFF04DE6605 | 48:89F1 | mov rcx,rsi |
00007FFF04DE6608 | 50 | push rax |
00007FFF04DE6609 | 53 | push rbx |
00007FFF04DE660A | 51 | push rcx |
00007FFF04DE660B | 52 | push rdx |
00007FFF04DE660C | 55 | push rbp |
00007FFF04DE660D | 54 | push rsp |
00007FFF04DE660E | 56 | push rsi |
00007FFF04DE660F | 57 | push rdi |
00007FFF04DE6610 | 41:50 | push r8 |
00007FFF04DE6612 | 41:51 | push r9 |
00007FFF04DE6614 | 48:83EC 20 | sub rsp,0x20 |
00007FFF04DE6618 | 48:89D9 | mov rcx,rbx |
00007FFF04DE661B | 48:8D15 3A000000 | lea rdx,qword ptr ds:[0x7FFF04DE665C] | 00007FFF04DE665C:L"voip"
00007FFF04DE6622 | FF15 00EA61FE | call qword ptr ds:[<StrStrIW>] |
00007FFF04DE6628 | 48:83C4 20 | add rsp,0x20 |
00007FFF04DE662C | 48:85C0 | test rax,rax |
00007FFF04DE662F | 74 18 | je wechatwin.7FFF04DE6649 |
00007FFF04DE6631 | 41:59 | pop r9 |
00007FFF04DE6633 | 41:58 | pop r8 |
00007FFF04DE6635 | 5F | pop rdi |
00007FFF04DE6636 | 5E | pop rsi |
00007FFF04DE6637 | 5C | pop rsp |
00007FFF04DE6638 | 5D | pop rbp |
00007FFF04DE6639 | 5A | pop rdx |
00007FFF04DE663A | 59 | pop rcx |
00007FFF04DE663B | 5B | pop rbx |
00007FFF04DE663C | 58 | pop rax |
00007FFF04DE663D | 48:C7C2 00000000 | mov rdx,0x0 |
00007FFF04DE6644 | E9 21E575FD | jmp wechatwin.7FFF02544B6A |
00007FFF04DE6649 | 41:59 | pop r9 |
00007FFF04DE664B | 41:58 | pop r8 |
00007FFF04DE664D | 5F | pop rdi |
00007FFF04DE664E | 5E | pop rsi |
00007FFF04DE664F | 5C | pop rsp |
00007FFF04DE6650 | 5D | pop rbp |
00007FFF04DE6651 | 5A | pop rdx |
00007FFF04DE6652 | 59 | pop rcx |
00007FFF04DE6653 | 5B | pop rbx |
00007FFF04DE6654 | 58 | pop rax |
00007FFF04DE6655 | E9 10E575FD | jmp wechatwin.7FFF02544B6A |
00007FFF04DE665A | 0000 | add byte ptr ds:[rax],al |
00007FFF04DE665C | 76 00 | jbe wechatwin.7FFF04DE665E |
00007FFF04DE665E | 6F | outsd |
00007FFF04DE665F | 0069 00 | add byte ptr ds:[rcx],ch |
00007FFF04DE6662 | 70 00 | jo wechatwin.7FFF04DE6664 |
00007FFF04DE6664 | 0000 | add byte ptr ds:[rax],al |