七少月 发表于 2016-1-29 02:10:48

微信红包辅助实现分析

本文作者为七少月,此次为github上一个项目,微信抢红包辅助,本文主要是以此为例,先对其进行逆向,再进行分析。一方面讲述微信抢红包辅助的基本实现原理,另一方面也提高通过dex2jar获得的java伪代码的分析能力,并体现java伪代码与真实代码的不同。本文仅用于教学目地,不得用于任何商业和非法用途,否则与本人无关。 前言:首先,新年之际,祝大家新年快乐,感谢所有支持我的朋友,在新的一年里,万事如意。在上篇文章《某微信红包辅助插件破解分析》中,很多朋友表示比较感兴趣。但很抱歉的说,我做的是逆向安全,当时那篇文章目地更多是在逆向,而不是微信辅助。由于上段时间比较忙,一直没有发什么帖子,最近过年,大牛他们也需要休息,而我学艺不精,在现在基本忙完后,准备陆续发一些技术贴。思来想去,决定从大家比较感兴趣且最为简单的微信红包辅助入手,也当补充了我上一篇文章。 教材说明:这次教材为他人在github上一个项目,项目源码:https://github.com/geeeeeeeeek/WeChatLuckyMoney。项目已经将软件更新到了2.0,但本文主要是讲解实现的基本原理,所以使用了1.3版本,把一些非关键性代码进行删除,只保留关键性代码。在本文最后,会有资料,资料中包含样本和详细的java伪代码的分析,几乎分析了每一句,每一个关键点,同时包括了使用的视频演示。 微信红包辅助实现的三种方法:微信红包辅助的实现大概有三种方法,这里我们简单说一下,并进行比较。1.自动屏幕点击:如果将其看作游戏辅助的话,那么这种方法实际上就是按键精灵那样的模拟辅助类型,为自动点击屏幕,代替手动操作。本例就是典型的这种方法,核心的实现方法就是窗口事件回调方法。从整体的smali来看,本例在主入口点的oncreate()方法中调用updateServiceStatus()函数,该函数用于开启和关闭抢红包服务,该服务就是HongbaoService。这种方法简单易行,且早已出现,但和所有的模拟辅助缺点一样,适配性和成功率不高,功能过弱,且容易被检测和处罚;2.注入微信:这种案例就类似于我的上一篇文章中的样本,具体不再分析,缺点显而易见,微信版本一旦更新,就要重写,重用性太低;3.微信服务器协议:首先要提醒,如果你通过抓取微信的服务器协议来制作辅助,是处于法律底线的,微信的服务器协议分析也常常只能想想,其分析难度可想而知。很多人想实现后台控制辅助,也就是每次都能抢到金额最大的一个红包,这可能是不现实的。因为能否抢到大包,这取决于微信红包的随机算法,应该是在服务器。就好像很多游戏抽奖道具一样,修改服务器的随机算法近乎不可能。 本例的抢红包实现算法逻辑:逻辑非常重要,因为红包存在很多种情况,如有没有被戳开,有没有被抢完,会不会出现重复,会不会出现误判等等问题。所以,一个好的抢红包辅助最主要是好的算法,来处理这些问题。其实我们可以看出,红包类型在算法里尤为重要。本例的核心在我看来就两点:1、利用Accessibility服务实现屏幕的自动点击;2、利用对于红包节点信息的检测,即红包匹配文字,来判断红包类型,进而得出是否可以戳开或抢。 本例的主要逻辑流程:1.判断屏幕上是否有微信红包;2.获取屏幕的红包根节点;3.检测红包的节点(根节点的子节点)信息,主要针对戳开后,得到待抢队列;4.自动点击,戳没有戳开的红包;5.自动点击,抢戳开后但未领取的红包。当然,上述已经说过,要处理的问题还有很多,特别是到底怎么才能得到可以抢的红包,以及那么多的情况,要怎么样去安排,先做什么后做什么,最主要的,是如何来抢这些红包,是先全部都去抢,然后再去判断结果,还是先获得正确的红包,接着再去抢。 具体的实现分析都在资料中,非常详细,但这里我说两点可能会出现疑问的地方,原因一个是Accessibility服务需要配置,再者就是dex2jar获得的java代码是伪代码,跟真实代码差距比较大:1.我们看如下代码,可以知道,Accessibility服务需要配置:private final Intent mAccessibleIntent = new Intent("android.settings.ACCESSIBILITY_SETTINGS");本例的配置是在逆向后的目录:/res/xml/accessible_service_config文件之中。我们只说一个配置,本例是微信红包辅助,所以Accessibility服务在配置时需要指定包名:<accessibility-service android:description="@string/app_name" android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowContentChanged|typeWindowStateChanged" android:packageNames="com.tencent.mm"2.很多人对于java伪代码中performAction(16)的16不知道什么意思,先分析这个函数可以知道,这是一个进行屏幕操作的函数,先看出现位置: ((AccessibilityNodeInfo)this.mReceiveNode.get(i - 1)).getParent().performAction(16); 如果想理解这个16的意思并不困难,我们需要知道它肯定是使用了Accessibility的函数库,16的十六进制为0x10,我们到函数库的地方,一目了然,16就是ACTION_CLICK..field public static final ACTION_CLEAR_FOCUS:I = 0x2
.field public static final ACTION_CLEAR_SELECTION:I = 0x8
.field public static final ACTION_CLICK:I = 0x10
.field public static final ACTION_COPY:I = 0x4000
.field public static final ACTION_CUT:I = 0x10000
.field public static final ACTION_FOCUS:I = 0x1ACTION_CLICK也就是自动点击,这就告诉我们,当分析java伪代码时,不能囫囵吞枣,对相应的支持性函数库也要分析,这就像分析so的ARM,不能只看寄存器和代码,要结合这个so本身的一些信息,和它要达到的功能。想起小雨Eriky的那个cm试题,很多人F5之后,静态分析得到的c伪代码非常少,没有关键的加密算法,原因是因为IDA被小雨写的代码误导,误以为malloc是一个函数块trunk,而不是函数。回到本例,从功能来看,这一个功能也一定是自动点击屏幕。 最后,就是检测节点信息的重点分析截图,可见非常详细:private void checkNodeInfo() {    if (this.rootNodeInfo == null) {} //如果红包根节点信息不为空    do    {      do      {      do      {          return;                                    //该函数主要是利用findAccessibilityNodeInfosByTexts()函数匹配红包文字内容,来检测节点,                  //进而判断出是否接收、是否打开,是否需要抢等结论,以及得到接收队列和待抢队列                                    //遍历节点匹配“领取红包”和"查看红包"          localList = findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[] { "领取红包", "查看红包" });          if (localList.isEmpty()) { //如果队列为空,则退出            break;          }                  //利用红包文字内容+节点ID的HASH值,进行判断红包是否重复,避免红包重复      } while (Integer.toHexString(System.identityHashCode(this.rootNodeInfo)).equals(this.lastFetchedHongbaoId));      this.mLuckyMoneyReceived = true; //已经接收      this.mReceiveNode = localList; //得到接收队列      return;                                //戳开红包,红包还没抢完,遍历节点匹配“拆红包”      List localList = findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[] { "拆红包", "Open" });      if (!localList.isEmpty()) //如果队列不为空      {          this.mUnpackNode = localList; //得到待抢队列          this.mNeedUnpack = true; //需要抢          return;      }      } while (!this.mLuckyMoneyPicked); //没有被打开过                    //戳开红包,红包已被抢完,遍历节点匹配“红包详情”和“手慢了”    } while (findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[] { "手慢了", "红包详情", "Better luck next time!", "Details" }).isEmpty());    this.mNeedBack = true;//需要返回    this.mLuckyMoneyPicked = false; //没有被打开过} 资料下载链接:http://pan.baidu.com/s/1eRyK9LS

何须执手问年华 发表于 2016-1-29 11:20:17

请问github上的代码不都是开源的吗?为什么还需要逆向啊?

我放不下你 发表于 2016-1-30 17:58:40

少月大牛就是刁,虽然没看懂,希望能给详细点思路

maikesoft 发表于 2016-1-30 20:25:07

厉害支持{:4_87:}

Foooooooood 发表于 2016-1-30 22:14:45

厉害支持{:4_87:}
页: [1]
查看完整版本: 微信红包辅助实现分析