一、抓包
先看看12.25.1版本的APP是不是还能使用,如果还能使用我们就先破解低版本的。打开APP后发现还能正常使用,因为低版本的难度低我们就破解这个版本。低版本和高版本的算法是一样的,算法破解之后我们后续抓包替换接口就行了。手机安装上drony之后低版本的很容易就抓到包了,高版本有VPN检测,是不能直接抓包的,你可以hook之后再抓包,或者使用hook okhttp的脚本抓包。抓包我只说思路,就不一步一步展示了,没有什么可说的。对于Frida的检测也很低级,直接hook就过掉了。
多抓几次网络请求,我们对比发现,加密参数是nsign,get_md5,signature,ajk_sign4个加密参数,我们就拿ajk_sign这个最难的加密参数破解做一个演练吧。
二、分析apk
低版本好抓包带来的麻烦就是APP加固了,你需要脱壳,然后才能分析。github上一堆脱壳机你自己下载脱一下就行了。我比较懒,能省一步是一步,加密参数有了,我直接分析高版本的APP也是一样的,不要怀疑参数会不会变,8成是不会变的,一般APP都是变加密算法或者是风控策略。直接jadx打开高版本app,直接搜索大法就定位到加密方法了。
hook java我们验证一下。
很完美,定位到了加密算法java层的位置。为了减少后面对SO分析的干扰,我们写一个主动调用吧。
也很完美,主动调用结果和我们刚才java hook的结果是一样的。
三、分析so
分析高版本或者低版本的SO都是一样的,高版本的SO直接解压APP就能得到,低版本的我们取APP的安装目录下面拉一下就行了。然后拖到IDA里面去,搜索导出函数就能找到我们的加密方法。
一步步分析,我们最终定位到方法MD5Update,依然是hook验证一下。
把hexdump的结果再逆向之友中格式化一下然后再MD5一下,和我们主动调用的结果是一样的。
四、算法还原
下面就是根据我们的JAVA方法的入参和MD5的入参做一下格式化,然后再把salt加上,我们的算法就实现了。
def get_ajk_sign(url):
url_dict = urlparse(url)
query = url_dict.query
dict1 = {}
for item in query.split('&'):
if 'ajk_sign' in item:
continue
list1 = item.split('=')
key = list1[0]
value = list1[1]
dict1[key] = value
update_str = ''
for i in sorted(dict1):
update_str += '&{}={}'.format(i,dict1[i])
update_str2 = update_str[1:] + '加V:z_xiansheng88'
update_str3 = unquote(update_str2)
ajk_sign = md5_encory(update_str3)
return ajk_sign