首页
社区
课程
招聘
[原创]Android微信逆向--实现发朋友圈动态
发表于: 2020-3-19 22:24 14278

[原创]Android微信逆向--实现发朋友圈动态

2020-3-19 22:24
14278

最近一直在研究Windows逆向的东西,想着快要把Android给遗忘了。所以就想利用工作之余来研究Android相关的技术,来保持对Android热情。调用微信代码来发送朋友圈动态一直是自己想实现的东西,研究了一下,果然实现了,遂写下本文当作记录。本文主要分析发送纯文字朋友圈动态和发送图片朋友圈动态。

本文用到的工具如下:

在分析代码之前,首先要定位到与之相近的地方,我们首先想到的肯定是发朋友圈那个界面,如何查看发朋友圈的界面是哪个Activity呢?很简单,在手机上打开发送朋友圈的界面

把手机连接电脑,打开USB调试,在PC的cmd窗口中执行以下命令:

可以看到发朋友圈的那个Activity就是com.tencent.mm.plugin.sns.ui.SnsUploadUI

虽然找到了Activity,但还是不能高兴太早,想要通过Activity知道哪部分是发朋友的代码还是比较费力的。于是我们就想到从“发表”按钮入手,找出发表朋友圈的相关代码。点击“发表”按钮会发生什么?发表是一个动态的行为,我们可以通过跟踪点击“发表”按钮时的调用过程,来找到有用的信息。跟踪调用过程,可以使用ddms工具来完成。打开ddms,选中微信进程,在手机中打开发表朋友圈界面,然后在ddms中点击下图圈出的图标开始跟踪:

将朋友圈动态发出,再点一次上图圈出的图标停止跟踪。ddms会生成跟踪结果,对于跟踪结果,怎么找到按钮事件相关的信息呢,学过Android的朋友就会想到onClick方法,那我们就在ddms的搜索结果中搜索这个名称:

成功的定位到了onClick的位置,但是比起这条onClick结果,更加令人引人注目的是它的上一条结果,因为它包含了我们刚才找到的Activity的类名:

知道这个方法被调用,我们去看看com.tencent.mm.plugin.sns.ui.SnsUploadUI类里的OnMemuItemClick究竟是什么。

用jadx打开微信apk,定位到com.tencent.mm.plugin.sns.ui.SnsUploadUI类,在类中搜索onMemuItemClick,结果不多,看起来比较像的就是这个onMemuItemClick了:

在onMemuItemClick方法中看到了:

这行代码有什么特别的呢,在我看来,有两个特别的地方:

我们发朋友圈动态时候,是要写动态的描述的,所以这个desc可能就是发朋友圈动态的描述,如果是描述,我们就可以根据这个描述,顺藤摸瓜找到发朋友圈动态的地方。而且this.desc的值又来自于this.tQN.getText().toString(),即this.tQN很有可能就是我们填写动态描述的文本框。我们来看看this.tQN赋值的地方,它在onCreate方法被赋值:

可以知道它的id是d41,那么d41是哪个控件?打开uiautomatorviewer,对发朋友圈界面截图分析,点击截图中的文本框,uiautomatorviewer右侧跳转到了相应的位置,果然,d41就是发动态时填写描述文本框的id

好了,现在知道this.desc就是发表朋友圈动态时的描述,跟上他应该就可以找到发朋友圈动态的地方。继续往onMemuItemClick方法下部分析,可以看到this.desc被传入了SnsUploadUI.this.tQO.a方法:

SnsUploadUI.this.tQO.a方法定义在接口com.tencent.mm.plugin.sns.ui.z中:

知道它定义在哪个接口并不能解决问题,毕竟接口没有实质性代码,要找还得找接口的的实现类,在com.tencent.mm.plugin.sns.ui.SnsUploadUI类中寻找this.tQO在哪里会被赋值。最终,我们在com.tencent.mm.plugin.sns.ui.SnsUploadUI类的ag方法中看到了许多给this.tQO赋值的地方:

由此,可见this.tQO被赋予什么值是根据this.tMY来决定的,this.tMY是一个int类型的数据,那我们hook com.tencent.mm.plugin.sns.ui.SnsUploadUI类的ag方法就可以知道this.tMY是什么值。在这里,我用frida来hook,frida的javascript部分代码如下:

hook之后,每当我们在手机上打开发布朋友圈动态的界面,ag方法被调用,控制台就会输出相应的数字。经过我的测试,这个数字是发表朋友圈动态的类型。朋友圈类型和其对应类如下:

这些类都直接或间接的实现了上面讲到的com.tencent.mm.plugin.sns.ui.z接口。这样一来,就知道this.tQO会根据朋友圈的动态类型进行初始化,那么,上面的SnsUploadUI.this.tQO.a方法很有可能就是发朋友圈动态的方法。接下来,我们根据不同的朋友圈动态所对应的类来分别分析

文字动态分析起来应该比图片动态来说简单一些,我们就先来分析它。上面讲到,这类动态对应类是com.tencent.mm.plugin.sns.ui.ae,这个类里我们主要看a方法,在看a方法之前,先看它传入什么参数,为了看清楚,这就要回看上文onMenuItemClick方法调用a方法的地方:

这就是a方法调用的地方,根据这段代码和编写hook a方法的代码来推出它的参数。hook代码如下:

hook成功后,发一条纯文字的朋友圈动态,打印出:

所以,可得:

好多参数我们不知道是什么,不过问题不大,那些我们需要的参数已经能搞懂了。懂得a方法的参数,那能否尝试直接调用它?先来看一下com.tencent.mm.plugin.sns.ui.ae类的构造函数能否调用:

构造函数有Activity类型的参数,Activity类型的参数是很难构造的,所以放弃构造com.tencent.mm.plugin.sns.ui.ae类来调用a方法。那我们直接去看a方法,看能不能找到有用的东西。由于是文字动态,所以我们着重关注传入的文本,即com.tencent.mm.plugin.sns.ui.SnsUploadUI类的desc成员,在a方法中它是第4个参数:

可见this.desc在a方法中它是str,而且在a方法中,str只有一处引用:

str传给了ayVar.adk()方法,找一下ayVar来自哪里,它在a方法里初始化,而且初始化方式很简单:

只传入一个数字就能初始化,我们初始化ay类的时候不用深究这个数字是什么,和它传入一样的值即可。在a方法的尾部,还看到一个引人注目的commit方法:

猜测这就是发布朋友圈的方法,写个简单的frida脚本来验证一下:

文字动态的内容是:To be, or not to be, that is a question.。果不其然,脚本运行后,文字动态发表成功了

经过对com.tencent.mm.plugin.sns.ui.ae的a方法的分析,我们可以知道,a方法主要传入一些发朋友圈动态所需要的通用的数据,比如动态是否私密,动态的文字描述,艾特的人,定位信息等,这些信息在其他类型的朋友圈动态中也会用得到。我们还知道发文字动态只需要文字描述就能发表成功。

带图片的的动态和文字动态差不多,只是多加了图片的参数,我们在分析此类动态时多关注图片在哪传入即可。带图片的动态对应的类是com.tencent.mm.plugin.sns.ui.ai,有了上面的经验,我们直接去看它的a方法(ai类有许多a方法,注意这里说的a方法参数和com.tencent.mm.plugin.sns.ui.z接口里的a方法参数一致)。在a方法的开头,看到利用迭代器去遍历一个列表,遍历过程中组装com.tencent.mm.plugin.sns.data.j类的数据,然后把j类放入链表linkedList2中:

在组装数据的时候,我们看到j类构造时传入一个字符串和数字,而这个字符串对应j类的path字段,这可能就是图片的路径:

那么我们猜测j类就是存储朋友圈的动态图片信息的类,上面提到j类被放入链表linkedList2中,那么来看linkedList2被哪里引用了

看到醒目的字符串:commit pic size,这应该是日志要打印的字符串,现在基本上可以确定j类就是存储要发表的图片的信息的类了,那么linkedList2就是存储所有将要发表的图片信息,继续往下寻找linkedList2还被哪里引用了

可以看到linkedList2传入两个地方,一处传入a方法:

另一处传入com.tencent.mm.plugin.sns.ui.ai$a类构造函数:

linkedList2传入a类后,又赋值给成员变量tPF,这个tPF成员变量只在a类的dU方法中被引用

而dU方法在哪里调用呢?在a类的父类:com.tencent.mm.plugin.sns.model.h中,我们看到dU方法在u方法被调用:

而u方法在ai类的a方法中调用(可以回看前面的图)。分析到这,上面的linkedList2传出去之后都终有所属了,即最终都传入了com.tencent.mm.plugin.sns.model.ay类ey方法。知道图片往哪传了,就写段frida代码调用试试吧

上面的代码在发送文本动态代码的基础上初始化三个j类,分别传入三个本地图片路径,再将三个类实例添加到链表,再将链表传入ay类的ey方法,最后调用ay类的commit方法将动态发送出去,代码运行,发现带图片的朋友圈动态发表成功:

 
 
 
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 14
支持
分享
打赏 + 2.00雪花
打赏次数 1 雪花 + 2.00
 
赞赏  orz1ruo   +2.00 2020/03/20 助人为乐~
最新回复 (33)
雪    币: 105
活跃值: (4412)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
老哥 图片没了
2020-3-20 01:48
0
雪    币: 7756
活跃值: (3465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
分析的很详细,赞一个
2020-3-20 08:16
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
分析的 很到位 图片更是亮点
2020-3-20 16:29
0
雪    币: 54
活跃值: (705)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习了 ~~
2020-3-20 16:33
0
雪    币: 19
活跃值: (331)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习了~~
2020-3-20 17:12
0
雪    币: 5573
活跃值: (2153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢分享!
2020-3-22 19:47
0
雪    币: 570
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
吾爱一遍,看雪一遍
2020-3-23 11:26
0
雪    币: 2227
活跃值: (345)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习了~~
2020-3-23 14:15
0
雪    币: 1985
活跃值: (1800)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
牛逼老哥。。
2020-3-23 14:57
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
支持支持
2020-3-23 15:02
0
雪    币: 298
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
感谢大佬分享
2020-3-24 23:02
0
雪    币: 248
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
分析很详细!!!
2020-3-25 09:37
0
雪    币: 0
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
能不能告知用frida有封号风险吗?
2020-3-31 18:05
0
雪    币: 4
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
老哥,分析的很详细,感谢。
2020-3-31 18:23
0
雪    币: 2685
活跃值: (3680)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
16
Eli_291771 能不能告知用frida有封号风险吗?
我也不懂,目前没被封
2020-3-31 20:57
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
使用frida hook时微信闪退,请大佬指导
2020-4-2 16:41
0
雪    币: 2685
活跃值: (3680)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
18
四个圈儿~~ 使用frida hook时微信闪退,请大佬指导
目前想到的是传参错误
2020-4-2 17:23
0
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
专门注册的账号,来回复的,这个调用commit函数后,只是在本地创建了一个model,会在SnsMicroMsg.db里面插入一条SnsId为0的类似草稿的记录,在别的手机端是看不到的(可以拿另外有好友的一个微信测试下),或者你在正常发一条朋友圈,在朋友圈界面OnActivityResult的时候会select 数据库中localFlag !=2 也就是草稿类型的记录,统一上传到微信服务器。  正确的应该是需要在回调一个函数:“com.tencent.mm.plugin.sns.model.af.cnB().cmp()“,cmp是遍历朋友圈数据库,找到未发布的,然后统一发布。另外Commit函数需要在主线程调用,子线程调用直接卡死,java端写代码的时候需要注意下,不要写在线程中调用。
2020-4-3 22:33
1
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
忘了说了,我用的是wx 7.0.4版本的,类名和方法名,可能有些变化.
2020-4-3 22:34
0
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
21
四个圈儿~~ 使用frida hook时微信闪退,请大佬指导
hook函数尽量最少,hook点尽量最精确。
2020-4-3 22:36
0
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
Eli_291771 能不能告知用frida有封号风险吗?
我是看了楼主的文章,才发现frida的神奇之处的,调试代码很方便,xposed微信半天就封了,如果是小号的话,目前用frida两天了,还没有发现异常。frida配合Jeb 简直天衣无缝
2020-4-3 22:37
0
雪    币: 2685
活跃值: (3680)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
23
wx_李金山 专门注册的账号,来回复的,这个调用commit函数后,只是在本地创建了一个model,会在SnsMicroMsg.db里面插入一条SnsId为0的类似草稿的记录,在别的手机端是看不到的(可以拿另外有好 ...
谢谢指正,之前没有注意
2020-4-4 17:03
0
雪    币: 232
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
看起来必须学习下frida,分析过程非常详细,重要的是成品代码短小精悍~  @wx_李金山 的这个补充研究得更深入。
2020-4-4 22:36
0
雪    币: 222
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
为啥我不管是用fdex还是用frida脱出来的方法具体实现都是报错呢

Error: jadx.core.utils.exceptions.DecodeException: Load method exception: bogus opcode: 00e8 in method: com.tencent.mm.plugin.setting.ui.setting.SettingsModifyUserAuthUI.2.<init>(com.tencent.mm.plugin.setting.ui.setting.SettingsModifyUserAuthUI, com.tencent.mm.plugin.setting.model.h):void, dex: 
       at jadx.core.dex.nodes.MethodNode.load(MethodNode.java:116)
       at jadx.core.dex.nodes.ClassNode.load(ClassNode.java:249)
       at jadx.core.dex.nodes.ClassNode.load(ClassNode.java:256)
       at jadx.core.ProcessClass.process(ProcessClass.java:31)
       at jadx.api.JadxDecompiler.processClass(JadxDecompiler.java:282)
       at jadx.api.JavaClass.decompile(JavaClass.java:62)
       at jadx.api.JavaClass.getCode(JavaClass.java:48)
Caused by: java.lang.IllegalArgumentException: bogus opcode: 00e8
       at com.android.dx.io.OpcodeInfo.get(OpcodeInfo.java:1217)
       at com.android.dx.io.OpcodeInfo.getName(OpcodeInfo.java:1224)
       at jadx.core.dex.instructions.InsnDecoder.decode(InsnDecoder.java:590)
       at jadx.core.dex.instructions.InsnDecoder.process(InsnDecoder.java:74)
       at jadx.core.dex.nodes.MethodNode.load(MethodNode.java:102)
       ... 6 more

2020-4-7 11:45
0
游客
登录 | 注册 方可回帖
返回
//