大家好,我是TheWeiJun,不知不觉已经来到了2022年底。回顾这一年,发生了太多事迹;有挫折、有喜悦、其中最开心的是结交了许多志同道合的朋友。本文将是笔者2022年最后一篇文章收官之战,全程高能,在阅读的同时不要忘记点赞+关注哦⛽️
特别声明:本公众号文章只作为学术研究,不用于其它不法用途;如有侵权请联系作者删除。
目录
一、抓包分析
二、Jadx反编译
三、frida hook调试
四、ida动态注册分析
五、算法还原
六、思路总结
趣味模块
新年新气象,永远行大运。2022年的最后一战由小军出场!小军的职业是一名计算机高级开发工程师,小军的爱好是喜欢玩游戏。他特别喜欢玩一些新游,然后关注下大家对新游的一些体验和看法。于是小军找到了某游戏社区,在小军想时刻关注游戏社区更新动态时,他遇到了难题,通过jadx定位到加密参数后,遇到了So层文件。今天我们将与小军并肩作战去探索我们未知的领域,感兴趣的读者记得给我一个star!
公众号:逆向与爬虫的故事
专注于网络爬虫、JS逆向、APP逆向、安全攻防实战经验分享及总结。
一、抓包分析
1、打开我们本次需要抓取的App,使用charles设置代理进行抓包,抓包截图如下所示:
说明:之所以进行打码处理,也是为了避免不必要的麻烦,希望大家能理解。我们的目的是要学习别人的加固思路而非破解!
2、搜索指定关键字,定位我们想要获取的数据包,然后截图如下所示:
总结:观察上图,确定我们本次需要还原的参数authorization后,初步判断该参数后,无法确定使用的什么加密手段;接下来让我们进入反编译调试环节吧!
二、Jadx反编译
1、使用Fart对指定App的apk脱壳后,直接使用jadx打开脱壳后保存的zip包,截图如下所示:
2、等待jadx反编译完毕后,我们使用查找参数名和关键字的方法进行加密位置定位,截图如下所示:
温馨提示:此刻如果你电脑内存不够16个G,介意还是换个电脑再来操作,相信我绝对没有错。
3、经过分析及追踪java源代码,最后定位到authorization参数加密的位置如下图所示:
总结:分析上面authorization的加密逻辑,我们需要确定return返回值中包含的多个参数的初始值即可完成对该参数的算法还原,接下来我们一起进入hook调试环节分析一下该算法吧。
三、frida hook调试
1、想要获取加密逻辑,我们首先需要先拿到str、e3、d2、f2的初始值,先hook一下c方法,构建frida代码如下所示:
2、启动frida脚本,执行刚刚写好的hook代码后,刷新手机界面,分析截图如下所示:
此刻,我们将charles中的该请求包也截图,进行对比分析,截图如下:
总结:观察上面两张图的参数值,我们可以清楚地看到入参、出参和charles中的参数一一对应,接下来我们只需要还原每一个参数算法即可。
3、各个参数hook调试分析后,所有参数初判断总结如下:
- e3 当前unix时间戳,10位
- d2 五位随机字符,由字母和数字组合。
- str 40位长度,初步怀疑为sha1加密 待定分析
- str2 40位长度,初步怀疑为sha1加密 待定分析
- f2 hmac sha1加密,通过分析java源码得出
3.1 f2 参数 hook代码如下所示:
3.2 终端打印入参及出参输出如下所示:
4、接下来我们分析下str、str2两个参数的生成规则,只要解决掉这两个参数,我们就可以实现authorization参数的算法还原。经过多次hook,我们发现str、str2的值好像是固定不变的,截图如下所示:
结论:由于没有突破口,进行app卸载后重新安装,使用frida脚本重新hook,将hook到的str、str2的值进行查找,发现了该值是有新的接口返回的,截图如下所示:
frida hook界面截图如下:
charles定位截图如下:
总结:此刻我们已经知道了str、str2的生成规律,我们只需要还原该接口请求就能实现str、str2的参数生成,接下来我们需要对sign参数进行解密分析。
5、使用jadx查找sign参数,最后定位到该参数位置截图如下所示:
5.1 编写frida脚本进行函数hook,代码截图如下:
5.2 启动刚刚编写的hook脚本,终端输出截图如下:
5.3 此刻我们查看charles中的数据包sign截图如下:
总结:sign参数生成方法定位后,我们只需要还原sign加密方法即可完成所有代码闭环。
6、sign加密方法定位后,我们追踪java代码,最后确定到native层路径,截图如下:
总结:加载so、通过native关键字定义了需要调用的方法getSign,也就是说,它这里调用的是so层的加密算法,so是什么?简单来说,它是c/c++编译后的产物。context、bArr变量我们都已经知道明文信息,接下来,我们需要用ida打开so文件,去探索so层对该方法做了哪些加密操作吧。
四、ida动态注册分析
1、两个参数值确定了,下面要做的工作就是分析so层的加密算法获取sign值。我们通过压缩软件打开apk,因为我手机的cpu类型是arm64-v8a, 是向下兼容的,选择使用armeabi-v7a中的so文件是可以的。找到目标文件,使用ida打开后截图如下所示:
2、使用ctrl+F查找静态注册的指定方法名,结果无法搜寻到,这个时候可以肯定java调用的方法名在so文件中是动态注册的。找到JNI_Onload,点击该方法,使用F5打开该方法,截图如下所示:
3、点击v4后面的地址off_5004[0]进入指定代码块进行分析,截图如下所示:
总结:这个时候我们看到了java层的getSign方法和java层该方法的两个参数类型,接下来我们继续追踪分析so层是如何加密的。
4、点击sub_131c+1地址,然后按F5进入指定代码块,截图如下所示:
说明:这个地方会有签名校验,判断我们是否重新打包。如果为true,则直接返回0,否则执行下面的操作。
5、继续点击sub_1094地址方法,进入新的代码块,最新截图如下图所示:
总结:这个代码逻辑是拿我们在java native接口函数中传递的字符串与So中的字符串进行比较,然后给v8变量赋值,之后的加密逻辑会使用到v8变量。
6、点击sub_1B04地址进入到最新代码块区域,截图如下所示:
7、点击上图四个常量,然后点击按键H格式化常量值转为16进制,截图如下所示:
总结:看过md5源码的同学,应该对这个四个常量比较熟悉吧,这不就是A、B、C、D四个常量值吗?到这里,我们可以肯定,sign的加密算法就是md5加密;sign值的生成规则其实是指定参数拼接不同包名对应的salt进行md5加密即可。接下来,让我们进入算法还原环节吧!
五、算法还原
1、sign参数算法还原如下:
import hashlib
def get_sign():
salt = "PeCkE6Fu0B10Vm9BKfPfANwCUAn5POcs"
data = f'X-UA=V=1&PN=xxx&VN_CODE=224003000&LOC=CN&LANG=zh_CN&CH=seo-baidu&UID=07e90f02-7def-4f28-a0b4-70098396e1df&NT=1&SR=1080x1794&DEB=Google&DEM=Pixel+2&OSV=10&action=active&android_id=84c16aaccd10a6e5&cpu=arm64-v8a&model=Pixel 2&name=Google&nonce=istb4&pn=0&push_id=6ce79a19f68c48779463dc893589c46c&screen=1080x1794&supplier=1&time=1671172755&uuid=07e90f02-7def-4f28-a0b4-70098396e1df&version=10{salt}'
sign = hashlib.md5(data.encode(encoding='UTF-8')).hexdigest()
print("e6a071ae2dc6cd117278b0f9d2fa04b1")
print(sign)
pycharm终端输出如下:
总结:解决sign参数后,也就意味着str、str2参数我们能够获取到了,接下来我们对authorization参数mac做算法还原。
2、mac参数算法还原如下:
def get_mac():
data = "1649340509\nhi9b4\nGET\n/landing/v5/timeline-with-device?action=refresh&X-UA=V%3D1%26PN%3D%26VN_CODE%3D224003000%26LOC%3DCN%26LANG%3Dzh_CN%26CH%3Dseo-baidu%26UID%3Dc2ff8daf-08ca-4e54-b051-6c5fde70bdda%26NT%3D1%26SR%3D1080x1794%26DEB%3DGoogle%26DEM%3DPixel%2B2%26OSV%3D10&show_channel_app=1\napi.xxxdada.com\n443\n\n"
str2 = "d1e76439035449b521ea6c3d27aae758ef05ec65"
mac = hash_hmac(data, str2)
print("new--------")
print(mac)
print('ori--------')
print("qrcn7ei6EBAPs/LkBO+undcifsk=")
def hash_hmac(code, key):
hmac_code = hmac.new(key.encode(), code.encode(), sha1).digest()
return base64.b64encode(hmac_code).decode()
pycharm终端输出如下:
总结:走到这里所有算法还原就结束了。我们只需要把分析的每个参数进行字符串拼接即可实现对authorization参数的生成!最后一步流程就省略了,结果已经很明朗了,感谢各位读者朋友阅读!
六、总结分享
回顾整个分析流程,本次难点主要概括为以下几点:
- 如何快速定位加密参数的位置
- 熟悉hmac sha1加密算法
- 熟悉md5源码加密实现
- 熟悉ida、jadx、frida使用
今天分享到这里就结束了,欢迎大家关注下期文章,我们不见不散⛽️
文章来源:逆向与爬虫的故事(公众号)
原文链接:某游戏社区App | So层逆向分析
微信搜:逆向与爬虫的故事;给我一个关注!
版权归原作者 逆向与爬虫的故事 所有, 如有侵权,请联系我们删除。