PC端WeChat逆向注入

写在前面
首先是好久都没写原创的技术博客了,上一篇还是去海参崴的旅行回记:滨海远东之后(After Vladivostok)
起笔这篇文章的时候,实际上已经是25年12月,但事情大概是25年5月发生的事情,也就是其实我只咕了一年不到!(理直气壮x
之所以有时间来写写这一年来遇到的技术趣事,是因为一方面到年底了,一方面我又要开始漂泊了(为什么我要说又),细节的原因大家有兴趣可以看看 食用指南 下面的每年记事,我大概会把这几篇文章更完后一并更新之
言归正传,所有的这种如题所示需求都是公司需要,以下都是情节模拟,并非具体情况,请细加甄别
在24年底其实就有 TL 找我,说目前我们的私域运营效率比较低,还要用批量的实机统一调度操作,问我能不能破解企业微信的私有协议,让后端能直接修改数据传参,调用接口,回复用户、发朋友圈等……
呵,我当然不会答应,只是“好好好,我有时间看看”的说法,可要知道这是在法律边缘疯狂试探的,当然,后面还有老板要我去爬竞品公司数据啥的,只能说这个公司简直了= =
总而言之
总而言之,虽然我推辞了,但到半年后这件事情再被捞起来的时候,我就推不掉了,我只能想办法实现而又不让它上线,也就是拿出达成目标的证据但给出不能这么做的足够理由
前置准备
我在做前期信息搜集的时候,参考了:基于wireshark对网页版微信抓包和ios微信抓包分析 和 微信3.9.8.25机器人(Hook注入)搭建教程文档 还有一众相关文章
前者让我抛弃了直接破解加密协议的想法,且先不说能否实现,也太麻烦了
后者让我转向了另一个实现方向:我能不能 Hook 微信,通过这样的方式进行一些功能调用和传参修改呢?
摸索开始了——
在查阅了大量前人的资料和看到无数的卖技术贩子后,我大概了解了目前做这一块的“灰产技术”大概的执行方式:利用低版本的 PC 端微信,对其进行功能调用内存地址的发掘,然后通过外置函数模拟接口数据,再写入微信进行接口请求篡改或直接执行
定制DLL
其实现在所有主流的 PC 微信 Hook 几乎都来自一个项目:https://github.com/ttttupup/wxhelper
我也就借用这个项目的示例,高概括的向大家说一下步骤是如何进行的,如何实现的:
- 用 Cheat Engine(CE)去找微信触发接口的回调地址,先在固定对话框(文件传输助手)发送特定的语句,然后在 CE 中寻找相应语句所在地址;
- 然后用 x64DBG 或者 OD 在地址处下断点,断点后一步步跟进到调用函数,或者直接用 IDA Pro 或 Ghidra 对关键地址进行搜索后,一步步向上找调用函数;
- 再结合这个关键函数,让 AI 帮忙分析一下,写一下带汇编语句的 C 代码,作为一个业务功能(给特定对象发消息)的回调(Call),然后再编译成一个动态连结库(.DLL),供外部拓展使用(http)
接口调用
如何运用编写出的 DLL 以及如何撰写接口的调用,示例在 wxhelper 的 client.py 中都有,这里只展示部分代码:
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
32
33
34
35
36
37
38
39
40
41
42
43
44 >import requests
>import json
>def check_login():
"""
0.检查是否登录
:return:
"""
url = "127.0.0.1:19088/api/?type=0"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
>def user_info():
"""
登录用户信息
:return:
"""
url = "127.0.0.1:19088/api/?type=8"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
>def send_text():
"""
发送文本
:return:
"""
url = "127.0.0.1:19088/api/?type=2"
payload = json.dumps({
"wxid": "filehelper",
"msg": "123"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
......
最终实现
当前面两步实现后,就可以进行简单的功能调用了,以下是获取个人信息以及发送消息的实际情况:
后续推辞
当然,这只是我给“私域优化建议”的一部分,对于这部分,我表示:实现了,但不能做,有封号风险
为什么不能用这种方式?一方面,这种方式需要一个人固定维护这份 .DLL 文件,每个版本的微信对应调用函数的映射地址都是会变化的,在企微强更较频繁的环境下难以如此费精力的去再做一遍(我不负责!);另一方面,在思考企微协议相关的利用与分析这段时间里,我在许多群组里都看到了因为使用这种方式不恰当导致企业账号被封禁的情况,从流量请求来看,这部分从本地发出的请求很容易被识别,属于腾讯自己灰产的一部分
如此辩解就好,也算是完成了任务,也没走上违法犯罪的道路,可喜可贺,可喜可贺







