培森的Blog Xposed-微信自动加好友功能实现

Xposed-微信自动加好友功能实现

严重声明本文的意图只有一个就是通过分析app学习更多的逆向技术,如果有人利用本文知识和技术进行非法操作进行牟利…

严重声明
本文的意图只有一个就是通过分析app学习更多的逆向技术,如果有人利用本文知识和技术进行非法操作进行牟利,带来的任何法律责任都将由操作者本人承担,和本文作者无任何关系,最终还是希望大家能够秉着学习的心态阅读此文。

微信6.6.7版本为例,手机root与Xposed框架安装本文不做讨论,如有需要请百度,本文只用于Xposed模块编写。


经坛友提醒,使用文本存储手机号,在进行读取for循环添加时,10个以上的时候就会产生操作过于频繁的提醒,而且这个提醒大概一个小时才能解除。
经过优化后,增加了线程的sleep时间,可实现自动循环查看好友信息,但在运行到25个左右时也会触发操作过于频繁的提醒。
并且如果加好友的功能也增加上的话,也会由于加好友频繁而被限制,所以最好是通过ContentProvider把大量手机号批量写入到手机通讯录数据库中,然后使用微信的添加通讯录好友的方式来添加好友,以下分析流程就仅做参考吧。

1.首先查看微信加好友的页面
是FTSAddFriendUI这个Activity。
2.使用jadx打开app,查找FTSAddFriendUI
3.寻找突破点
 
大体浏览后没有类似EditView的实例对象,但发现一个内部类FTSAddFriendUI$5
 
-1通过简单分析,确定这个内部类是搜索好友后的结果显示
成功的话就intent跳转,失败的话就显示该用户不存在等错误信息
-2直接查找它的使用
是CM方法使用到它了,分析可得这个方法的参数就是输入框的字符串,字符串不为空后进行查询,并显示一个正在查询的Dialog,有结果后回调OnCancelListener,并且触发内部类FTSAddFriendUI$5中的结果显示方法。
 
Hook CM方法,打印string参数,发现就是输入框的文本数据,确认CM方法就是要找的方法
-3xposed直接使用

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
final Class FTSAddFriendUIClass=loadPackageParam.classLoader.loadClass("com.tencent.mm.plugin.fts.ui.FTSAddFriendUI");
                     findAndHookMethod(FTSAddFriendUIClass,
                            "onCreate",Bundle.class,
                            new XC_MethodHook() {
                                @Override
                                protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
                                    super.afterHookedMethod(param);
                                   new Handler().postDelayed(new Runnable() {
                                       @Override
                                       public void run() {
                                           XposedHelpers.callMethod(param.thisObject,"CM","微信号/QQ号/手机号");
                                       }
                                   },1000);
                                }
                            });

 

-4解决问题
结果可以看到只有dialog,dialog结束后并没有反应,但dialog能显示说明代码执行了,那就来看一下FTSAddFriendUI$5这个结果处理类里的方法有没有执行吧。

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
findAndHookMethod("com.tencent.mm.plugin.fts.ui.FTSAddFriendUI$5",loadPackageParam.classLoader,
       "a",int .class, int .class,String.class,XposedHelpers.findClass("com.tencent.mm.ab.l",loadPackageParam.classLoader) ,
       new XC_MethodHook() {
           @Override
           protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
               super.beforeHookedMethod(param);
 
               log("FTSAddFriendUI$5--0="+param.args[0]+"=1="+param.args[1]+
                       "=2="+param.args[2]);
           }
            
       });

打印结果如下:
2019-02-18 17:55:19.347 3872-3872/? I/Xposed: [17:55:19]:  FTSAddFriendUI$5–0=0=1=0=2=Everything is OK
搜索结果处理的方法执行了,说明问题不在CM方法,而是在处理方法中因为某个问题而停止了。
那就来分析一下这个a方法里的哪段代码是有问题的吧。a方法完整代码如下,

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
45
46
47
48
49
50
51
public final void mo2331a(int i, int i2, String str, C0879l c0879l) {
           C1261g.m2963DF().mo8629b(106, (C0874e) this);
           FTSAddFriendUI.this.aQA();
           if (i == 0 && i2 == 0) {
               FTSAddFriendUI.this.iJw = ((C9339f) c0879l).bcS();
               if (FTSAddFriendUI.this.iJw.rHb > 0) {
                   if (FTSAddFriendUI.this.iJw.rHc.isEmpty()) {
                       C35785h.m67602a(FTSAddFriendUI.this, C8733g.search_contact_not_found, 0, true, null);
                       return;
                   }
                   Intent intent = new Intent();
                   intent.putExtra("add_more_friend_search_scene", 3);
                   if (FTSAddFriendUI.this.iJw.rHc.size() > 1) {
                       try {
                           intent.putExtra("result", FTSAddFriendUI.this.iJw.toByteArray());
                           C36379d.m70344b(FTSAddFriendUI.this.mController.tml, "subapp", ".ui.pluginapp.ContactSearchResultUI", intent);
                           return;
                       } catch (Throwable e) {
                           C3327x.printErrStackTrace("MicroMsg.FTS.FTSAddFriendUI", e, "", new Object[0]);
                           return;
                       }
                   }
                   ((C33521h) C1261g.m2977l(C33521h.class)).mo24028a(intent, (biy) FTSAddFriendUI.this.iJw.rHc.getFirst(), FTSAddFriendUI.this.jvZ);
               }
               FTSAddFriendUI.this.jvX = 1;
               FTSAddFriendUI.m48692g(FTSAddFriendUI.this);
           } else {
               switch (i2) {
                   case DownloadResult.CODE_CONNECTION_EXCEPTION /*-24*/:
                       C29477a eV = C29477a.m50825eV(str);
                       if (eV == null) {
                           FTSAddFriendUI.this.jvQ.setText(C8733g.no_contact_result);
                           break;
                       } else {
                           FTSAddFriendUI.this.jvQ.setText(eV.desc);
                           break;
                       }
                   case -4:
                       if (i != 4) {
                           FTSAddFriendUI.this.jvQ.setText(FTSAddFriendUI.this.getString(C8733g.search_contact_err_no_code));
                           break;
                       }
                   default:
                       FTSAddFriendUI.this.jvQ.setText(C8733g.no_contact_result);
                       break;
               }
               FTSAddFriendUI.this.jvX = -1;
               FTSAddFriendUI.this.jvY = 1;
           }
           FTSAddFriendUI.m48693h(FTSAddFriendUI.this);
       }

因为上面打印log时前两个参数都是0,所以精简后如下

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public final void mo2331a(int i, int i2, String str, C0879l c0879l) {
           C1261g.m2963DF().mo8629b(106, (C0874e) this);
           FTSAddFriendUI.this.aQA();
           if (i == 0 && i2 == 0) {
               FTSAddFriendUI.this.iJw = ((C9339f) c0879l).bcS();
               if (FTSAddFriendUI.this.iJw.rHb > 0) {
                   if (FTSAddFriendUI.this.iJw.rHc.isEmpty()) {
                       C35785h.m67602a(FTSAddFriendUI.this, C8733g.search_contact_not_found, 0, true, null);
                       return;
                   }
                   Intent intent = new Intent();
                   intent.putExtra("add_more_friend_search_scene", 3);
                   if (FTSAddFriendUI.this.iJw.rHc.size() > 1) {
                       try {
                           intent.putExtra("result", FTSAddFriendUI.this.iJw.toByteArray());
                           C36379d.m70344b(FTSAddFriendUI.this.mController.tml, "subapp", ".ui.pluginapp.ContactSearchResultUI", intent);
                           return;
                       } catch (Throwable e) {
                           C3327x.printErrStackTrace("MicroMsg.FTS.FTSAddFriendUI", e, "", new Object[0]);
                           return;
                       }
                   }
                   ((C33521h) C1261g.m2977l(C33521h.class)).mo24028a(intent, (biy) FTSAddFriendUI.this.iJw.rHc.getFirst(), FTSAddFriendUI.this.jvZ);
               }
               FTSAddFriendUI.this.jvX = 1;
               FTSAddFriendUI.m48692g(FTSAddFriendUI.this);
           }
           FTSAddFriendUI.m48693h(FTSAddFriendUI.this);
       }

前面代码分析后无问题,但 if (FTSAddFriendUI.this.iJw.rHb > 0) 判断时不知rHb的值,此处需要hook一下。

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
findAndHookMethod("com.tencent.mm.plugin.fts.ui.FTSAddFriendUI$5",loadPackageParam.classLoader,
                            "a",int .class, int .class,String.class,XposedHelpers.findClass("com.tencent.mm.ab.l",loadPackageParam.classLoader) ,
                            new XC_MethodHook() {
                                @Override
                                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                    super.beforeHookedMethod(param);
                                    log("FTSAddFriendUI$5--0="+param.args[0]+"=1="+param.args[1]+
                                            "=2="+param.args[2]+                                    "=rHb="+XposedHelpers.findField(XposedHelpers.findClass("com.tencent.mm.protocal.c.bja",loadPackageParam.classLoader),"rHb").get(XposedHelpers.callMethod((param.args[3]),"bcS"))
                                    );
                                }

打印得知rHb=0,所以不会走if语句内的代码,只有两个方法m48692g与m48693h有可能有问题,按顺序检查参数

最终发现是这两个方法中使用了FTSAddFriendUI的变量bWm,而在输入框使用addTextChangedListener进行绑定后,bWm存储了输入的字符串,所以如果直接调用CM方法的话,导致bWm变量为空,所以解决方法如下:

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
final Class FTSAddFriendUIClass=loadPackageParam.classLoader.loadClass("com.tencent.mm.plugin.fts.ui.FTSAddFriendUI");
                     findAndHookMethod(FTSAddFriendUIClass,
                            "onCreate",Bundle.class,
                            new XC_MethodHook() {
                                @Override
                                protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
                                    super.afterHookedMethod(param);
                                   new Handler().postDelayed(new Runnable() {
                                       @Override
                                       public void run() {
                                           XposedHelpers.setObjectField(param.thisObject,"bWm","微信号/QQ号/手机号");
                                           XposedHelpers.callMethod(param.thisObject,"CM","微信号/QQ号/手机号");
                                       }
                                   },1000);
                                }
                            });

 
可以看到进入加好友界面后不需要输入,直接进入好友详情界面。

当然如果输入数据搜索不到好友,结果处理方法的参数是
2019-02-18 17:58:34.082 3872-3872/? I/Xposed: [17:58:34]:  FTSAddFriendUI$5–0=4=1=-4=2=User do not exist

由以上功能可以在此基础上进行拓展
通过读取文件中的大量客户信息,以此方法判断是否存在微信号
也可以自动搜索进入好友界面后,增加点击添加到通讯录按钮的方法,实现自动批量添加到通讯录

本文来自网络,不代表培森的Blog立场,转载请注明出处:https://blog.xupeisen.com/archives/93

作者: 培森

联系我们

联系我们

13262951234

在线咨询: QQ交谈

邮箱: admin@xupeisen.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部