偷懒打卡的新姿式

我不想我不想我不想迟到~

公司使用的是xxapp打卡。要想本身打卡, 那么我抓包获取接口和参数,本身组装,本身访问接口便可。 说干就干,我开始在登陆界面进行抓包:

https抓包.png

从图上能够发现:web

  • 在请求的时候,herades 里面有一些参数,包括了custom-device-idcustom-versioncustom-oscustom-company-idx-json-web-token等,这些内容是自定义header加上去的,后期调用接口时可能会用到
  • 采用了https链接

既然XXX采用https方式,咱们没有证书,就没法拦截获取信息,接口调用基本行不通了,那么咱们采用AccessibilityService辅助功能的方式进行打卡如何呢?json

思路是:将一台手机放到公司,链接网络,另外一台手机远程QQ发送消息,公司这台手机接收到消息,点亮屏幕,向上滑动解锁,打开XXX,此时咱们的打开app是在运行的,而后经过AccessibilityService进行辅助点击从而进行打卡。或者直接设置定时器,时间到以后自动触发以上过程并打卡。但这种思路对进程保活有至关高的要求,不太好实现。数组


使用https以前的XXX,确定是http,那么http接口今安在?bash

http访问,试接口.png

竟然200,并且从返回的json来看,登陆接口对于服务器的逻辑来讲是没问题的,应该是在使用中,那么下一步咱们只须要拿到入参就行。服务器


下一步,反编译xxxx.apk,用到的工具是AndroidCrakTool网络

反编译XXX.png

这里要提一下,反编译后咱们能拿到资源文件们,资源文件对于定位页面,控件,以及此控件接下来的逻辑是相当重要颇有帮助的。app

  • 反编译后,将AndroidManifest.xmlres文件夹留下,其余的删除便可,由于咱们这次不对smali进行分析
  • 另外,反编译后咱们发现XXX并无对代码进行加壳,只是单纯的混淆了。因此这就更加轻松简单

接下来,咱们将XXX.apk后缀名改成zip,而后解压,获得以下内容:ide

解压XXX.png

能够看到,获得了两个dex文件,一个classes.dexclasses2.dex,这是由于他的方法数超过了65536,进行multidex的结果。如今咱们使用AndroidCrakTool对这两个dex进行dex2jar,目的是将dex转成jar包,方便咱们阅读源码。工具

dex2jar.png

获得jar包以后,咱们用JD-GUI打开阅读,也可使用AS或者IDEA进行源码阅读。这里采用JD-GUI布局


打开这两个jar以下图:

打开后.png

如今来理一理思路,咱们刚才测试的是登陆接口,咱们目的是打卡,那么咱们就须要登陆后,获得token,而后带上token和一大堆参数进行打卡接口的访问,因此第一步,咱们须要获得登陆接口的参数。


咱们经过使用TopActivity,在手机上找到登陆界面的Activity名字:

登陆界面截图.png

从图中左上角能够知道这个界面的名字和包名,因此咱们在JD-GUI中找到对应的包名进入寻找登陆界面。因为咱们有两个jar,因此就先挨个找吧。但从顺序来讲,这个登陆界面通常会在dex1中,固然这也是猜想,不过通常按照代码量和顺序来看的话是这样的。果不其然,以下图:

登陆界面代码截图.png

从界面上看,咱们是点击了button以后进行网络请求的,因此咱们当作员变量,发现一个button,变量名i,而后紧接着下面有个b()方法,内部将i初始化了,findviewbyid()内部传入的正是这个buttonidR文件中的静态常量值。这里插一句,若是有须要对界面和id进行分析的话,就须要从这些dex中找到R文件,而后将这个id的数值拿去寻找匹配,就能在R文件中反向获得这个控件的id,而后将这个id拿到以前反编译后的res文件夹中搜索匹配,从而获得布局文件,控件id等。固然也能经过ASDDMS进行布局分析,从而获得id,不过那个id是混淆后的,在jar中是没法找到的,由于jar中使用的idint静态常量。

接下来咱们将i变量的id2131362755用来进行搜索,获得设置点击事件的地方。这里为什么不直接用变量i呢?由于i是混淆后的,搜出来可能会有不少,很差排除。

搜索button.png

从图上能够看到,咱们找到了onClick()回调,而且找到了点击后的逻辑。图中有个方法,叫executeOnExecutor(),看起来像是AsyncTask的线程池执行方法,咱们看看是否是,这时候点击前面new b(),看看这个b对象是啥,以下图:

AsyncTask.png

能够看到果真是AsyncTask。那么结果就显而易见了,这次请求使用AsyncTask发起,因此咱们在AsynctTask内部就能找到网络请求的相关内容了。先看第一个:

protected Void a(Void... paramVarArgs){
          this.b = b.w(this.d, this.e);
          return null;
    }
复制代码

此方法一看就知道,他是doInBackground方法混淆后的,由于他的返回值是Void而不是void。在这个AsyncTask实现的时候,泛型定义以下:

private class b extends AsyncTask<Void, Void, Void>{}
复制代码

三个Void,因此能够判定第一个a()方法是doInBackground。那么网络请求就在这里面了。再来看第二个a()方法。

protected void a(Void paramVoid){}
复制代码

从返回值和参数来看,多是onCancelled()onPoseExcute(),可是从总体代码和代码量来看,能够判定是onPoseExcute()

登陆接口发起请求.png


如今回过头来分析doInBackground()

this.b = b.w(this.d, this.e);
复制代码

咱们点击w()进入看看:

登陆参数组装.png

能够看到,这个b对象的w()方法,就是组装登陆接口所需参数的,登陆接口须要2个参数,最下面那个是接口地址,红色部分是一串字符串。而经过大码部分的字符串,咱们能够知道第二个参数是密码,那么后面跟一串字符串是什么呢?是否是加密?,咱们点击e.a()中的a()方法去看看:

加密.png

从图上能够看到a()方法接收一个参数,联系刚才组装数据的地方,能够知道,密码是由明文加后面红色部分字符串,再总体通过MD5加密以后的。至于为什么知道是明文密码,咱们返回到LoginActivity,在AsyncTask实例化的时候传入了两个参数,后者就是密码。这个密码字符串的获取方式是反推出来的,以下图:

明文密码.png

因此,如今咱们有了接口地址,参数,加密方式,咱们试试看可否访问成功。

通过调试,登录成功,server返回了一堆数据,其中包括了token,id等:

登录成功.png

咱们如今至关于完成了50%

接下来的步骤要比以前简单太多了。经过抓包,获取到打卡接口的大概路径,而后在刚才组装登陆接口参数的b类中,查询匹配这个接口地址,因而获得了打卡的完整接口地址。而且获得了入参。剩下的就是慢慢组装数据了。咱们须要打卡,那么就须要经纬度。经过反编译发现他是用的是高德地图,因而咱们使用高德的地理位置反编码,将咱们想打卡的位置的经纬度获得,而后传入参数体,从而实现登陆并打卡。


其实整个过程走下来,最主要的几个点:

  • 在替换成https后,原http接口未关闭,多是为了兼容老版本
  • apk未进行更深层的保护,仅仅只是混淆
  • 密码加密的关键信息未进行有效保护,直接暴露了出来

最后,此次尝试主要是利用了http接口未关闭的漏洞,其实说到底也就是一次抓包分析数据的过程。


  • 以上敏感信息均作马赛克处理
  • app名字也替换成了XXX
  • 请勿用做商业用途和非法途径,仅供学习参考
  • 若有侵权,联系我删除
相关文章
相关标签/搜索