zzzzqxp 发表于 2020-11-15 21:25:21

安卓逆向:某手机应用市场app so层算法还原





前阵子写在公众号的,复制过来吸吸粉



upload/attach/202011/899_NQ37JDQPJAZ3VEM.png




正文



1.抓包








2.分析参数




http://bbs.nightteam.cn/upload/tmp/899_6GTE77B2USJN4FF.png




只有一个加密参数:zsData ,看起来像 base64 编码。那先去在线 base64 网站试着解密一下,如果是就可以少掉很多头发啦




然鹅。。。并不是 ↓

upload/attach/202011/899_T7Q9434F8PEDH53.jpg








所以继续,把apk拖进 jadx,反编译后搜索 zsdata ↓




upload/attach/202011/899_MHYQKADHGB2PD4H.png





点击跳转到图中标记 1 的函数  ↓




upload/tmp/899_YD7FUGP2QAAM2FN.jpg





可以看到最后调用图中标注为 4 的 native 函数。




是个 native 层的函数,如果想省事就用 rpc 调用,

想掉头发就去还原算法。





先简单说下 frida-rpc:

图中标记的 2 的函数 ,里面的操作只是把str 和 str1 转换成 bytes 数组,最后传给 native 函数,没有其他的操作。




啥意思呢,就是这里函数 2 跟函数 4 的返回结果实际上是一样的。





那我们进行 hook 或者 frida-rpc 调用的时候都只需要关注76行的 函数 2 就行了,它参数和返回值都是字符串,都不用转换类型,打印或者传参都十分方便,比较省事。




这个函数第一个参数是 Context ,是上下文,其余三个参数不知道是什么,上frida hook 一下 ↓

upload/attach/202011/899_K4K2J7TH2GHNV34.jpg


可以看到都打印出来了,现在知道了参数,那我们就可以用 frida-rpc 来调用这个函数



upload/attach/202011/899_EB7TP3NUQDFC32M.jpg








native 层分析





1.定位加密函数





用 IDA 打开 so 文件




搜索一下函数名 o000000O 发现搜不到,那就是动态注册的。




那就从 JNI_OnLoad 函数里找到注册函数,再找到真实函数名,具体操作请看上一篇。




顺利的找到真实的函数名为:abc




upload/attach/202011/899_ZXZGBSWA46WCX9J.png





为什么这里有六个参数?

是因为前面两个是JNI的参数,从第三个参数开始才是java层传来的参数,固定用法,记住就好。







2.静态分析




先找到 return,看最后的返回值是哪个变量赋值的




一顿分析




upload/attach/202011/899_KFAPRKYNCTGAUES.png





分析后找到关键函数,最后 return 的值就是 17





v17 = j_j_salt_b64_encode(v31, (int)v13);





继续找v31 和 v13





upload/attach/202011/899_YNNPK4DPAF7S6DZ.jpg





v31是 java 层传进来的第 2 个参数转换成的 bytes 数组,也就是这一长串转换的


upload/attach/202011/899_WB6NPSJH9YY7XHC.jpg





然后找 v13




upload/attach/202011/899_HMMX28C9K8DQ3QN.jpg

因为 a5=null 所以 v13 = 'ZySOWKE3-1.Vtw#!8u&~5XeT%74Mz>bG'
现在知道了 j_j_salt_b64_encode() 函数的两个参数





还要进入这个函数,看看它是怎么加密的




upload/attach/202011/899_XDGC52M32CU9N3D.jpg





简单说下这个算法





这个函数里有两个关键函数:
[*]
23行的 j_j_md5() 函数,
[*]
38行的 j_j_base64() 函数,




j_j_md5() 函数对'ZySOW5KE3-1.Vtw#!8u&~5XeT%74Mz>bG'进行md5编码后转换成 bytes 数组




36行 v5=参数1的数组长度, 只要v5!=v8,就一直循环,33行右边是两个数组的元素进行异或运算,填充到 v7




38行的 result 就是我们要的 zsdata 参数,j_j_base64() 对填充后的 v7 bytes 数组进行 base64 加密。得到 zsdata




python 还原算法:


encode_str = r'{"terminal":"{\"iccid\":\"\",\"romName\":\"\",\"50uid\":\"\",\"geo\":\"\",\"httpAgent\":\"Dalvik/2.1.0 (Linux; U; Android 6.0.1; Nexus 5 Build/MMB29S)\",\"mac\":\"344df73cc3ee\",\"romVersion\":\"\",\"timestamp\":\"' + ts + r'\",\"oaid\":\"\",\"locationInfo\":\"{\\\"area\\\":\\\"\\\",\\\"province\\\":\\\"\\\",\\\"city\\\":\\\"\\\"}\",\"osVerCode\":\"23\",\"imei\":\"359250052185137\",\"50uuid\":\"\",\"brand\":\"google\",\"osVerName\":\"6.0.1\",\"netinfo\":\"WiFi\",\"resolution\":\"1080*1776\",\"adid\":\"874cc857371673e6\",\"userAgent\":\"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5 Build/MMB29S; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36 package/com.market2345 versionName/7.5 versionCode/127\",\"imsi\":\"\",\"model\":\"Nexus 5\"}","page":"1","type":"az_xpyx"}'v3 = list(encode_str.encode())v5 = len(v3)v2 = 'ZySOWKE3-1.Vtw#!8u&~5XeT%74Mz>bG'v16 = list(hashlib.md5(v2.encode()).hexdigest().encode())v7 = []v8 = 0if v5 >= 1: while v5 != v8: v7.append(v16 ^ v3) v8 += 1zsdata = base64.b64encode(''.join().encode()).decode()








测试,通过

http://bbs.nightteam.cn/upload/attach/202011/899_RKQ3DQ7MURR9AXJ.jpg





更多文章请到公众号观看,公众号里的图也比较清晰

http://bbs.nightteam.cn/upload/attach/202011/899_TNUSJREC46MK622.jpg


http://bbs.nightteam.cn/upload/attach/202011/899_J48RSXZSZ6D3BFY.png



franky 发表于 2020-11-16 13:42:20

666

Helious 发表于 2020-11-27 21:11:18

学习学习

hongwang 发表于 2020-12-5 13:54:08

学习学习

化肥 发表于 2020-12-15 20:07:16

666

king1043 发表于 2020-12-16 17:57:25

66666666

Aimer 发表于 2020-12-18 16:18:43

66666666666

zhoubo 发表于 2020-12-18 16:46:52

1

进阶的小菜鸟 发表于 2020-12-18 17:14:43

学习学习

arbrad 发表于 2020-12-21 22:30:33

111111
页: [1] 2 3 4 5 6
查看完整版本: 安卓逆向:某手机应用市场app so层算法还原