首页
社区
课程
招聘
1
[原创] 对控制PC端微信发送信息的研究
发表于: 2017-12-7 21:51 30125

[原创] 对控制PC端微信发送信息的研究

2017-12-7 21:51
30125

经过断断续续约一个半月的逆向分析与开发之后,终于成功实现了控制微信发送信息。

近日闲来无事,试着实现控制WeChat PC发送信息,没想到断断续续竟搞了一个半月才搞定,踩了不少坑,也在其中学到很多。
本文主要讨论思路,具体代码略过。

先上最终效果图

WeChatForPC有三个比较重要的文件:WeChat.exe、WeChatWin.dll、WeChatResource.dll。

最初为了定位发送信息的函数,我选择从网络事件入手。然而网络收发牵扯到了众多线程(顺便学习Winapi线程相关的函数),加上即使不主动发送信息,微信也会有一些网络IO事件,这使得定位相当困难。

所以我决定从界面入手进行分析,定位发送按钮的单击事件处理函数,最终找到发送信息函数。所以便去学习了Winapi图形界面相关的函数及消息队列机制等,学成归来发现还是分析不动,微信界面并非使用Windows原生api实现,而是使用了一款C++用户界面库:DuiLib,还有一些比较知名的软件也用了这个库,如百度杀毒/卫士、酷我音乐盒、火绒等。于是又去复习了C++开发及逆向的相关内容并稍微学习了一下DuiLib(不得不说,DuiLib的官方文档真烂),感觉DuiLib还挺方便的。

DuiLib官方给出的Demo中处理按钮单击事件的方法基本都是在Notify函数中判断事件类型为click,然后进一步判断事件主体是否为某控件,最终调用响应函数处理。
其中事件类型直接用DuiString类型标注,类型判断直接比较字符串(效率略低,改成枚举类型多好)。事件主体用控件指针标注,判断标准是直接比较指针,指针可以用控件Name靠FindControl函数获得。

这样我们可以通过控件Name定位Notify函数,进而找到事件处理函数。
Name可以靠猜,也可以从Frame类的构造函数入手。DuiLib构造复杂窗口一般依靠XML生成,XML文件储存在WeChatResource.dll中且经过未知方式压缩,不过还好内部内容是靠资源路径检索,在WeChatWin.Dll中搜索".xml"可以找到很多结果,选择其中一个下断点就可以顺藤摸瓜找到XML的解析过程。最后多麻烦几次就可以dump到微信绝大部分的XML,然后经过一番分析就可以找到发送按钮的Name,然后就可以找到发送按钮单击事件处理函数,理想真是美好啊。

事实上,DuiLib提供了多条事件处理路线,Notify函数是最常用的一条,发送按钮单击事件处理函数并不在Notify中,事件主体控件的判断也没用控件Name。推测可能是使用了DuiLib提供的消息映射

该文章详细分析了DuiLib的事件处理流程 https://note.youdao.com/share/?id=66febb0420f97966d16ecbd7bc7aae3f#/

之后我想了另一条思路,发送按钮单击事件处理函数必定要调用输入控件的GetText获取发送信息内容,发送完成之后又必然调用Input的SetText之类的函数清空内容。我的新思路就是利用Input控件的GetText顺藤摸瓜找到目标.

这条思路比较成功,最终定位到了一片经过VMP混淆过的函数,这个函数有好几个参数,其中有接收者的WXID以及发送信息内容字符串这两个参数,直接修改这两个参数也达到了预期的效果。

目标找到了,开始写Hook代码吧,写完个小Demo才发现直接调用这个函数会导致微信崩溃,可能是有些变量没初始化吧。

踩了这么多坑,总算快成功了,最后的思路是放弃直接调用底层实现,转而调用前端层的代码,模拟用户操作来实现控制微信发送信息。这个思路的实现分为三步:

第一步无论是逆向分析还是编写Demo都太顺利了,一次成功,搞得我都忘了我是怎么做到的了...
第二步也很简单,单击事件处理过程中通过虚表调用过GetText,而在DuiLib源码中SetText就在GetText后面(upload/attach/201712/777010_vi27ia77mx9m4w9.png)
那么SetText和GetText在虚表中也应该是相邻的,写个Demo验证一下发现果然如此。
现在看来,最后一步更简单了,事件处理函数我们早就找到了,直接调用就好。

最后成品编写过程中还有一个问题需要解决,三步函数调用都是thiscall,必须要知道类地址。写Demo时吧地址硬编码,编译为DLL,靠StrongOD注入就好,独立程序就不能硬编码地址了。

关于地址,也有两条思路,一条是利用DuiLib向Windows注册的UserData找到m_PainterManager(不知道这玩意是啥可以去看看DuiLibDemo,官方文档就算了吧),调用其成员函数FindControl寻找各控件,这条方向可以参考 https://bbs.pediy.com/thread-220798.htm (作者的水平比我不知道高到哪里去了)(刚看到作者又实现了一个Spy++ For DuiLib,想实现这条思路的可以去拜读一番);另一条思路实现调试器,在控件构造函数下断点,获取控件地址。
相比较,第二种方案比较直接,比较方便,所以我选择了这条方案。

最后完成的太过顺利,感觉意犹未尽就又完成了好友信息的获取、控制修改备注、记录收发信息的功能,具体思路大同小异,实现起来也非常简单,就不再详细说明。

实现调试器的时候也是踩了一堆坑,自己造的轮子总是bug满满,现成的轮子又找不到(后来在x64dbg项目中发现TitanEngine,然后又发现直接搜"Debugger Engine"就能找到巨硬家的轮子,而我当时用的关键词是"Debugger Frame")

一个半月的工作还是挺开心的,学到不少东西,虽然怎么也找不到目标时各种烦躁,最终坚持下来看到自己的作品成功跑起来真是成就感满满。还有莫扎特第21钢琴协奏曲第一乐章真好听。

原文链接:
https://cirn09.github.io/2017/12/06/WeChatControl/

看雪ID居然不能用数字,服了服了

 

[注意]看雪招聘,专注安全领域的专业人才平台!

收藏
免费 1
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2023-2-9 02:27
最新回复 (41)
雪    币: 21
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
沙发!学习学习!
2017-12-7 22:02
0
雪    币: 15
活跃值: (280)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
学习
2017-12-7 23:09
0
雪    币: 12862
活跃值: (9302)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
4
其实这样和直接模拟按键点击也差不了多少了。。
2017-12-8 09:56
0
雪    币: 92
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习一下!
2017-12-12 16:55
0
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
hzqst 其实这样和直接模拟按键点击也差不了多少了。。
差别还是有的,模拟按键必须将界面置于前台,楼主这种方法,可以实现后台操作,后面继续发展可以控制多个微信,做出类似web微信机器人的东西出来
2017-12-13 14:27
0
雪    币: 199
活跃值: (884)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
直接调用函数崩溃是因为消息机制的问题,不是变量初始化的问题。
2017-12-14 19:32
0
雪    币: 34
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
ui事件始终要传达至功能函数,直接从按键往下找就行了。
2017-12-15 10:58
0
雪    币: 0
活跃值: (340)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不是在消息映射里面,发送按钮事件处理在eventsource  里面,在notify  之前
2018-1-2 12:21
0
雪    币: 0
活跃值: (340)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
输入框用的com封装的,非一般edit  封装,所以普通的edit虚表是不对的
2018-1-2 12:24
1
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
能分享发送信息的源码吗大神
2018-1-11 11:25
0
雪    币: 999
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习一下!~
2018-2-9 20:34
0
雪    币: 15
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
13
如何获取好友的微信号?谢谢!
2018-2-24 15:30
0
雪    币: 15
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
14
楼主,您好!用什么方法或什么工具可以获取到底层发送函数?望赐教,谢谢!
2018-2-24 16:46
0
雪    币: 254
活跃值: (37)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
doscho 如何获取好友的微信号?谢谢!
我记得我当时是断点断在好友信息frame设置前端文字的位置,然后顺着字符串向上找
2018-2-27 14:14
0
雪    币: 15
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
16
Cirn 我记得我当时是断点断在好友信息frame设置前端文字的位置,然后顺着字符串向上找
你是用od进行跟踪的?
2018-2-27 17:27
0
雪    币: 254
活跃值: (37)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
17
doscho 你是用od进行跟踪的?
对,和IDA配合使用疗效更佳
2018-2-28 18:53
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
如果这样,为啥不用图像识别+模拟点击?很简单就搞定啊
2018-3-1 08:33
0
雪    币: 1535
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
学习了!感谢楼主分享!
2018-3-1 10:34
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
Windows不是有一套消息处理机制的吗,每一步操作都可以看成是一个消息,然后用spy++看每一步所发出的windows  message,通过向微信模拟发送message来实现输入选择点击等操作,这样应该也可以实现楼主想要的效果的吧。
2018-3-2 23:02
0
雪    币: 254
活跃值: (37)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
走心i Windows不是有一套消息处理机制的吗,每一步操作都可以看成是一个消息,然后用spy++看每一步所发出的windows message,通过向微信模拟发送message来实现输入选择点击等操作,这样 ...
我刚开始的时候也考虑过这种方式,但是这样模拟操作很方便,获取信息就麻烦了
2018-3-7 16:53
0
雪    币: 254
活跃值: (37)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
vgavin 如果这样,为啥不用图像识别+模拟点击?很简单就搞定啊
因为这样实现太low。。。而且无法起到练习逆向技能的作用
2018-3-7 16:55
0
雪    币: 178
活跃值: (2176)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
23
我也用这种方式弄到了,联系人的wxid可以在contact_list里得到,具体断点下在itemclick就好了,我有个问题,如果session_list里面没有这个聊天,我的想法是给contact_btn发个点击,然后选择联系人,然后发送itemclick,最后点击发消息那个,但是好像不太行,一直没能把itemclick模拟出来,不知道你sessionlist是如何模拟的itemclick,想讨教下
2018-3-9 14:27
0
雪    币: 36
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
大魔头 我也用这种方式弄到了,联系人的wxid可以在contact_list里得到,具体断点下在itemclick就好了,我有个问题,如果session_list里面没有这个聊天,我的想法是给contact_ ...
调用Search的那个call比较方便
2018-3-9 15:07
0
雪    币: 178
活跃值: (2176)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
25
巫云雪遥 调用Search的那个call比较方便
OJBK  多谢了  我试试看 
2018-3-9 15:13
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册