本文首发于 公众号: Python编程与实战,转载请联系我,谢谢!!java
前段时间作爬虫遇到一个app,里面的数据须要登陆以后才能拿到,并且登陆不能用密码,只能经过验证码登陆。 这不是明摆着欺负人么,按赵四哥那句话来讲就是:python
生死看淡,不服就干!编程
因此接下来手把手带你们就某个app登录请求的加密参数进行分析破解, 从而实现从网络抓包的密文到明文的转换。服务器
Pyhton Java dex2jar(将apk反编译成java源码) jd_gui(源码查看) jadx 已root的手机或者安卓模拟器 fiddler PS:公众号后台回复 "反编译" 便可获取反编译工具包网络
首先咱们用fiddler抓包工具对app的登录进行抓包,这个app抓包须要开启全局代理,否则会抓不到数据。app
若是还不会使用全局代理抓包的朋友,能够看下前面一篇文章,里面有详细的抓包教程。函数
抓包的数据以下: 工具
咱们能够看到有个 token 的参数,有经验的朋友知道,这是服务器后台生成的,并且在发送登录验证码请求以前并无其它的数据交换! ui
这时候咱们就要去看app源码找到这个参数的加密方式,而后用转换成 Python 代码生成。搜索引擎
接下来就带你们就一步一步来破解这个参数。
咱们要获取app源码,就要对app进行反编译,反编译方式很简单,直接用工具搞定。 有两种反编译方式可供选择,反编译过程以下:
1.将安卓app的后缀更改成可解密的包,并解压
2.将解压后生成的后缀为 .dex 复制到 dex2jar 安装目录中
3.DOS命令行进入此文件夹,而后执行命令: dex2jar.bat classes.dex。 这个app有两个 .dex 文件,因此两个 .dex 文件都须要执行
执行完以后会生成两个对应的 .jar 文件,效果以下:
幸运的是这个app并无加固,有app进行了加固,像腾讯乐固,360加固等等
对于这种咱们不能直接反编译,首先须要脱壳,而后再反编译
5.第二种反编译的方法是直接使用工具 jadx 打开 .apk 文件 剩下的事就是仔细阅读代码,分析其中的逻辑了。
6.根据请求或响应的参数去源码中搜索加密方式
须要注意的是,反编译的代码很是混乱,错误不少,而且apk通过混淆,变量名都消失了,这时必定要有有耐心,仔细研究代码。 根据前面请求、响应参数去搜索,或者请求的 url 地址去搜索,并且经验很重要。
咱们就要根据这些搜索到的结果慢慢去找了。咱们主要找到发送请求的时候定义参数的代码,而后往上追溯 在查找的过程当中要尽量的多尝试,大胆猜想
最后根据 keycode 找到了登陆响应参数的生成函数
这部分代码就是加密的方法!
###验证 咱们把源码拷贝出来,分析加密参数
private String c(String paramString) {
Date localDate = new Date();
Locale localLocale1 = Locale.CHINA;
String str1 = new SimpleDateFormat("yyyyMMdd", localLocale1).format(localDate);
Locale localLocale2 = Locale.CHINA;
String str2 = new SimpleDateFormat("MMdd", localLocale2).format(localDate);
StringBuilder localStringBuilder1 = new StringBuilder();
String str3 = paramString.substring(7);
StringBuilder localStringBuilder2 = localStringBuilder1.append(str3);
StringBuilder localStringBuilder3 = localStringBuilder1.append(str2);
String str4 = localStringBuilder1.toString();
StringBuilder localStringBuilder4 = new StringBuilder();
StringBuilder localStringBuilder5 = localStringBuilder4.append(paramString);
StringBuilder localStringBuilder6 = localStringBuilder4.append("|");
StringBuilder localStringBuilder7 = localStringBuilder4.append(str1);
String str5 = localStringBuilder4.toString();
try
{
str5 = zxw.data.c.b.a(str5, str4);
}
catch (Exception localException)
{
localException.printStackTrace();
str5 = null;
}
return c.a(str5);
}
复制代码
其中生成了两个参数 str5, str4 传到加密函数。 下面是 str5 的生成代码
String str1 = new SimpleDateFormat("yyyyMMdd", localLocale1).format(localDate);
StringBuilder localStringBuilder4 = new StringBuilder();
StringBuilder localStringBuilder5 = localStringBuilder4.append(paramString);
StringBuilder localStringBuilder6 = localStringBuilder4.append("|");
StringBuilder localStringBuilder7 = localStringBuilder4.append(str1);
String str5 = localStringBuilder4.toString();
复制代码
str1 = 20190319,也就是今天的日期 str5 = 传过来的参数 + '|' + '20190319' 那么 str4 呢
String str2 = new SimpleDateFormat("MMdd", localLocale2).format(localDate);
StringBuilder localStringBuilder1 = new StringBuilder();
String str3 = paramString.substring(7);
StringBuilder localStringBuilder2 = localStringBuilder1.append(str3);
StringBuilder localStringBuilder3 = localStringBuilder1.append(str2);
String str4 = localStringBuilder1.toString();
复制代码
java的 substring() 方法相似 python中的字符串切片,只是 substring() 方法返回字符串的子字符串。 也能够推测,paramString 是一个长度大于7的字符串。这里大胆的猜想是咱们提交的那个手机号码,由于咱们请求的时候只提交了这个参数。
因此 str4 = '手机号码后四位' + 0319 若是不知道生成的方式,就用 java运行一波,将这两个参数打印出来,是最方便快捷的方法~~
既然知道加密参数了,接下来就是验证了 源码加密的方法以下:
用 python 代码改造的加密
运行以后的结果为 False,仔细看二者字母,数字基本都是同样的,感受应该是对了,但仍是有点差别! 再返回去看看源码,源码中最后将生成的加密数据再传给了某个函数再返回
return c.a(str5);
复制代码
下面是这个 *c.a *的函数:
public class c {
public static String a(String paramString) {
return paramString.replaceAll("\\+", "!");
}
}
复制代码
原来是将 "+" 替换成了 "!" 因此咱们将以前运行出来的结果中的 "+" 替换成 "!" 就是彻底正确了! so, 咱们就将这个 token 参数给破解了!
###总结 1.对于app加密的要有耐心,尤为是在根据参数在源码中寻找加密方式的时候,更加须要耐心。
2.善于利用搜索引擎,碰到看不懂的方法,就去网上多搜索。
3.若是认识大佬,固然是要抱紧大佬的大腿啊,多问问大佬,会让你事半功倍!
当你解决的问题那一刻,你就会发现以前受的苦都是值得的!