本帖最后由 Lunction 于 2020-3-6 20:43 编辑
前言:
初来驾到,请多多关照!
这是昨天接的单,破解了结果不要了,没付款,很坑爹,就此分享出来给各位逆向破解sign值的过程
这是我分析的过程,也是自己的一种思路,每个人的思路各不相同,但汇聚起来就是多种思维,在今后中会有更多的解决方案,
没录视频,将就着看吧~
第一步:抓包
首先,我们先用Fiddler开启抓包,手机里进行点击进入直播房间
抓包数据
POST /live/interRoom HTTP/1.1
User-Agent: Mozilla/5.0 (Linux; Android 7.1.1; MI 10 Build/NMF26F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.90 Mobile Safari/537.36 qiezi build-ver:2.4.8
Content-Type: application/json; charset=utf-8
Content-Length: 260
Host: api.XXX.com
Connection: Keep-Alive
Accept-Encoding: gzip
{
"sign": "7DDD0510249D2D2ECF7290618D562050",
"token": "AoZgA2cTJFR5bW+wUsuIxOjDEdzVnQzWEEiA3QTmQgjM6Wp9zezgHjhTbMxMrMBs",
"timestamp": 1583317055150,
"udid": "865902030563036",
"paySign": "1B094DB47EB1970C4CA7DBC732DEB87A",
"liveId": 362112,
"channel": "official",
"os": "1"
}
这里之前经过测试,发现有两个参数sign和paySign是会不断变化的,于是接着往下分析
第二步:操作Jeb
这里没jeb的可以网上下载,或者论坛搜,相信大家想学习的都会自己主动去寻找工具以及教程进行提升自己。
使用jeb教程论坛也有,多搜一下
将APP拖进jeb工具
点击字符串,将我们抓包到的敏感信息进行搜索,进行寻找加密的方法
试了sign、paySign 没搜索到想要的方法,不要灰心
然后尝试下路径,找到后点击进去
我们会发现,这里的代码是指令,我们并不一定会看得懂(前提是学习过,没学过没关系,咱们接着往下走)
按住键盘Tab键,切换到Java代码
经过对比找到是我们post提交的参数和对应的数据方法函数
- public void interRoom(long arg6, Callback arg8) {
- String v1 = ServerAddressManager.getHttpServerDomain() + "/" + "live/interRoom";
- HashMap v0 = CommonHttpRequestParams.getCommonParams();
- v0.put("liveId", Long.valueOf(arg6));
- v0.put("sign", CommonHttpRequestParams.sortMapByValues(v0));
- OkHttpUtil.doJsonPost(v1, new Gson().toJson(v0), arg8);
- }
复制代码图片太多,一个个截图怕你们嫌烦
代码是从上往下执行的,所以我们先一个个进行分析
String v1 = ServerAddressManager.getHttpServerDomain() + "/" + "live/interRoom";
这是不是很熟悉,就是我们提交POST的请求路径
第三步:分析代码
HashMap v0 = CommonHttpRequestParams.getCommonParams();
HashMap,这个就相当于我们的json,用来存储键值对的,就这么理解,如果Java不熟悉说太多会懵,我们进入
我们进入.getCommonParams(); 这个方法
- public static HashMap getCommonParams() {
- HashMap v2 = new HashMap();
- v2.put("os", "1");
- v2.put("udid", PhoneUtils.getIMEI());
- v2.put("timestamp", Long.valueOf(System.currentTimeMillis()));
- v2.put("channel", ChannelUtils.getChannel(com.blankj.utilcode.util.Utils.getApp()));
- if(StringUtils.isEmpty(UserManager.ins().getToken())) {
- v2.put("token", "");
- }
- else {
- v2.put("token", UserManager.ins().getToken());
- }
- v2.put("paySign", EncryptUtils.encryptMD5ToString(PhoneUtils.getIMEI().substring(0, 6) + "8qiezi" + v2.get("timestamp")));
- LogUtils.e(new Object[]{new Gson().toJson(v2)});
- return v2;
- }
复制代码
v2.put("udid", PhoneUtils.getIMEI()); 就是获取我们的手机的IMEI
也就是post提交的 "udid": "865902030563036",
v2.put("timestamp", Long.valueOf(System.currentTimeMillis()));
获取毫秒值,也就是我们的时间戳
接下来咱们分析paySign
v2.put("paySign", EncryptUtils.encryptMD5ToString(PhoneUtils.getIMEI().substring(0, 6) + "8qiezi" + v2.get("timestamp")));
PhoneUtils.getIMEI().substring(0, 6) 这里表示获取我们的IMEI码进行截取前5位
接着拼接字符串8qiezi,然后获取timestamp时间戳的值进行拼接
然后通过encryptMD5ToString方法,把我们拼接的字符串通过参数传递进方法里,继续往下走
- EncryptUtils.encryptMD5(arg1)
复制代码先分析这个encryptMD5方法,走下去
- public static byte[] encryptMD5(byte[] arg1) {
- return EncryptUtils.hashTemplate(arg1, "MD5");
- }
- private static byte[] hashTemplate(byte[] arg4, String arg5) {
- byte[] v2 = null;
- if(arg4 != null && arg4.length > 0) {
- try {
- MessageDigest v1 = MessageDigest.getInstance(arg5);
- v1.update(arg4);
- v2 = v1.digest();
- }
- catch(NoSuchAlgorithmException v0) {
- ThrowableExtension.printStackTrace(((Throwable)v0));
- }
- }
- return v2;
- }
复制代码看出来这里是通过MD5直接进行加密,然后返回 Byte[] 数组,也就是 易语言里的字节集
回到上面,继续分析EncryptUtils.bytes2HexString(EncryptUtils.encryptMD5(arg1));
bytes2HexString这个方法
将我们生成的byte数组进行转换,生成字符串,也就是我们32位的md5,最后进行转成大写字母
例子: "paySign": "1B094DB47EB1970C4CA7DBC732DEB87A"
OK,paySign解密完成了,接着sign
第四步:分析Sign加密
Sign加密在我测试的时候,差点把我给混蒙过去,为什么呢?
因为我也是按照上面的操作,进行一个个方法地点击,寻找他最后的生成方式
于是我接着进行分心CommonHttpRequestParams.sortMapByValues(v0)); 这个函数方法
sortMapByValues(v0)); 这里的v0,表示把我们之前创建的key value 键值对形式的值,根据传参形式传进去
先看下图了解代码... 10秒后
大致就是把我们的键值对 key values中的key,进行sort排序,根据ASCII码表进行从小到大排序,
排序完的键值对,通过键获取值,然后append(); 方法,进行我们的字符串拼接,toString()方法生成字符串
这里最主要的是这个UserManager.ins().getHttpServerKey()
走到这里就发现往下走走不下去了,为啥? 下面就是一个android底层类,打不开,看不到加密
这里说一下我的踩坑,我用其他工具jadx反编译,走到最后指向的是http_key这个常量值,后来拿来测试发现生成的结果不一致,当时缴费脑汁
第五步:JEB动态调试debug
开始我们风骚的办法
usb手机连接电脑,手机上打开APP
我们需要调试的是.getHttpServerKey()这个方法最后返回的值,那么点击进去
按Tab键,跳转到指令界面,子在最后那行,就是我们方法返回的值,
点击到行数,按Ctr + B 键,打上断点,准备进行调试
在APP里,我们点击进入房间,会在断点处停止,右边的VM/局部变量,v0就是我们要返回的值,这里是int型,我们转换成String字符串,得到我们想要的值
最后通过MDTString()方法进行生成32位MD5(相当于易语言的取数据摘要()方法),然后方法里toUpperCase();转换所有md5里的字母为大写
例子:"sign": "7DDD0510249D2D2ECF7290618D562050"
其实分析到这里就差不多完成了,剩下的就是自己进行尝试解密,
各有各的不同,你们可能用其他工具助手,进行生成加密的值,我直接通过Idea里把jeb的里面的Java代码复制进来,生成结果如下
OK,大功告成~
完成解密,有没有学到点知识?
如果看不懂代码,希望去补充学下java基础语法,smali语法
在前进的道路上,基础一定要掌握好,有了基础,在遇到各种问题看不懂的时候派上用场
工欲善其事必先利其器
QQ 技术交流:946091882;(接单)
|