首页
社区
课程
招聘
[原创]头条系 懂车帝 6.5.1 返回值解密【之抹去儿时的恐惧】
发表于: 2021-8-30 17:59 22143

[原创]头条系 懂车帝 6.5.1 返回值解密【之抹去儿时的恐惧】

2021-8-30 17:59
22143

这个故事要从儿时开始讲起,记得我还是个小孩的时候,有一天接到了一个任务,就是搞懂车帝。我心想:我之前搞过汽车之家、易车之类的,既然他们都是车相关的app,四舍五入就等于一样呗。我摆出了个OK的姿势,对方以为我只收0K的钱,就欣然的说交给你了。
规范性动作,抓个包吧

返回值加密了,不慌,我之前搞过易车,易车也返回值加密过,只要jadx反编译一下,找到解密位置,把解密的java代码复制出来就可以了,这个我熟,搜索关键词errorMessage找一下。
图片描述
需要调用JNI,那时的我知道有个叫unidbg的宝剑,你可以拿它斩杀恶龙,你不需要会什么ida武功,只要挥舞起unidbg,剑指恶龙即可。我试着拿起宝剑,传入方法名和参数,启动。妈蛋,竟然报错了,这个项目bug真多,垃圾。
-2000 years later-
此时的我长大了,一个男人也出生了,他就是千与千寻里浪里白条的白龙(简称龙哥(其实性别我没有考证过))
龙哥:宝,想学unidbg斩杀恶龙呀,我教你啊。
宝:不行啊,龙王,我很傻的。
龙哥:傻宝,没事的,我传你心法,你把上衣脱了。
傻宝:这样不太好吧(- -)脱衣中...
龙哥:好了,现在你已经拥有我1天的功力了(龙哥今年30好几岁)

从此以后我起早贪黑,勤加练习,挥汗如雨、浪里白嫖。终于在此刻1629949911,我拿起了屠龙宝刀,向恶龙发起最后的冲锋(可以脑补下詹姆·蘭尼斯特冲向恶龙的场景)

如今,两千年过去了,当时的少年是否斩杀恶龙呢,他究竟经历了什么奇妙之旅呢,那我们就开始一探究竟吧。
---正文---
首先先frida hook下native方法的参数
图片描述
知道了参数,运行下yang神脚本,看一下用的哪个so
图片描述
OK,是libcjtfcc.so,那把基础的unidbg代码写好,运行一下
图片描述
没有报错,native方法地址偏移量也拿到了0xa2ac,这也太顺利了,接着把调用native方法的业务逻辑写上,调用一下吧。
图片描述
报错了,这个错误也没见过呀,把DEBUG开启重新运行,打印一下bt

图片描述
最近的错误调用栈就一条,ida总查看下吧
图片描述
图片描述
图片描述
啥!啥!这都是啥,只看懂一个R2,装模作样看看R2的值吧
图片描述
嗯,我知道了,我是个菜逼
-郁闷了 2000 years later-
傻宝:龙哥,这次真的搞不出来了
龙哥:样本
傻宝:文件传输中....(1%)250B/s
-2 seconds later-
龙哥:把调用native方法的第二个参数,改成传jobject或jobject,别传0
傻宝:为什么?
龙哥:第二个参数被用到了,不被用到的时候传0
傻宝:你怎么知道第二个参数被用到了?
龙哥:我先去拍个小视频?
傻宝:不太好吧?
图片描述
我:可以和家人一起看吗?
龙哥:学习资料,自己学吧
-2000 seconds later-
我悟了
小视频不太好光明正大的分享,感兴趣的可以在底部加星球看呦,也可以加我交流技术呦。
在龙哥的指点过后,改完代码再执行一次
图片描述
图片描述
这个报错咱们就熟悉了,补环境嘛
图片描述
再次运行
图片描述
unidbg竟然不报错了,才补了一个就没有了?这样太顺利了吧。但是虽然unidbg不报错了,但这个报错应该是so层打印的错误日志,看着像是说解码失败了。哎,这就麻烦了,补环境最好弄了,闭着眼就能补。那就进ida看下伪代码吧
图片描述
看这逻辑是有三个判单,判单不通过就打印东西,感觉这三个判断像校验之类的。我用console debugger验证了一下,前两个判断都通过了,最后一个判单的时候没有通过,打印了日志,也就是说只要把最后一个校验让他通过就可以了。tab切换到汇编看下最后一个校验是怎么判断的
图片描述
cmp ro, #0,如果r0是0就走下面的打印错误日志逻辑。那我们就把他改成如果r0是1,才走,这样他就永远不会走那个逻辑,转而走解密逻辑(聪明脸)
图片描述
运行一下
图片描述
不提示解密失败了,但解密数据为空肯定也是不对的,这个应该是解密的什么逻辑出问题了,经过群友@NZ大神的分析,解密函数应该在if判断之前的那个函数,我们看看if判断前的那个函数什么样
图片描述
既然又走错逻辑了,我们再次用魔法棒,让函数强行走上面那个解密逻辑
(我是图,图中有返回值了,但是返回值是乱码)图丢了
看来不能这样强制换逻辑
到目前为止,我已经灰心了,经过漫长岁月的试错,我总感觉关键点就在解密函数的第一个参数上面
private native String tfccDecrypt(int i, int i2, String str, String str2);
第一个参数 是引用计数的一个值,每次调用会加1(我严重怀疑这个参数,但是有不知道它有什么问题)
第二个参数 一直是1(良民)
第三个参数 一个是一个字符串(良民)
第四个参数 待解密的字符串
就目前试过的结果来看,参数1和参数4可能有某种关联,因为123不变,4变就不行,或234不变,1变也不行。
通过看jadx源码,好像没什么特别的地方,就是初始化Tfcc对象后,对象中的b字段(也就是第一个参数)就会有一个默认值,然后解密时候就把这个值传过去。
图片描述
然后我frida也新建一个对象,然后用这个对象里的b值作为参数调用native方法解密,不行。也就是参数1和参数4确实存在某种关联,不单单是新建一个Tfcc对象,把里面的b作为参数就行,而是这个b必须和参数4关联起来才行。
而参数4是服务器返回的待解密数据,也即是服务器是知道参数4对应的b是多少,那它怎么能知道呢?
我操,可能有一种可能,客户端发给服务器的,这样服务器返回数据的时候,就可以给数据动手脚,让这个数据只能有客户端发送过来的那个b给结了,也就是下图的逻辑
图片描述
那我们就去看下发送url的地方,有没有发送什么特别的参数吧
**,jadx又打不开了(改死的小内存mac)
我直接说吧,就是在发送请求的时候,客户端给服务器发送了一个body t_key
图片描述
而这个t_key正是我们解密的那个对象,调用加密natvie生成的,生成这个t_key的时候,它的参数1和解密的时候的参数1是一样的。
private native String tfccEncrypt(int i, int i2, String str, String str2);
private native String tfccDecrypt(int i, int i2, String str, String str2);
也即是说,解密的参数1和返回值关联了起来
图片描述
ok,那基本就明白了,他们的加密逻辑应该是这样的(狂喜中...)
1,新建一个Tfcc对象D1(此对象会根据引用计数,将其字段b设置为某个数字)
2,用D1对象调用native tfccEncrypt方法加密(b, 1, "固定字符串S", "dongchedi+时间戳"),得到加密字符串t_key
3,发起http请求(将上一步生成的t_key作为body传过去),得到加密的返回值R1
4,还是用步骤1生成的D1对象调用它的native ftccDecrypt方法解密(b, 1, "固定字符串S", R1),得到解密结果
我们实际验证一下
我们生成一个t_key
图片描述
然后用这个t_key请求数据
图片描述
那这个数据,还有相同的第一个参数去解密(要成功啦,我能感觉到)
图片描述
妈蛋,不玩啦,不玩啦,睡觉,头发不多了。
-the second morning-
我的第一个参数没错啊,绝地的没错啊,我都把源码看看的清清澈澈,它就是这么加密解密的,难道让我看so?你瞧瞧现在哪有会so的呀,这都是只有龙哥才会so。
有经过长时间的试错,我还是感觉我分析他们的逻辑没错,我的第一个参数绝对没问题,却察觉出了问题。而第一个参数关联的是t_key,而t_key本身有没有参与到native方法到调用(我用unidbg模拟执行了一次,返现jni层没有调用java层多少方法,都是getBytes啊之类的,没有调用获取t_key的值)。那不是t_key本身,难道是t_key的相关属性?啊?难道是t_key传到服务器的时间?
但感觉如果是时间也太简单了,头条系的水平就这?但是也没有其他思路了,是一下吧。这次我们获取到t_key后立马用代码发送请求数据,拿到数据后,立马解密,看下效果。
图片描述

欢迎加我微信交流技术:zhoutianxing_
也欢迎加龙哥星球学习unidbg:https://t.zsxq.com/NVVrBYJ
图片描述
图片描述

https://ib.snssdk.com/motor/owner_price_api/car_price_list?car_id=50223&owner_price_region_name=%E5%8C%97%E4%BA%AC&sort_type=time_reverse&offset=0&page_size=10&iid=3035074666959895&device_id=1469370100097725&ac=wifi&channel=wandoujia&aid=36&app_name=automobile&version_code=651&version_name=6.5.1&device_platform=android&ab_client=a1%2Cc2%2Ce1%2Cf2%2Cg2%2Cf7&ab_group=2589722&ssmix=a&device_type=Pixel&device_brand=google&language=zh&os_api=29&os_version=10&manifest_version_code=651&resolution=1080*1794&dpi=420&update_version_code=6512&_rticket=1629894505066&cdid=f3034d66-09c7-4a46-a724-b1334073e9b4&city_name=%E5%8C%97%E4%BA%AC&gps_city_name=%E5%8C%97%E4%BA%AC&selected_city_name&rom_version=29&longi_lati_type=1&longi_lati_time=1629894505693&content_sort_mode=0&overall_score=6.8389&cpu_score=6.8915&host_abi=armeabi-v7a
 
{
  "status": "ok",
  "errorMessage": "",
  "data": "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"
}
https://ib.snssdk.com/motor/owner_price_api/car_price_list?car_id=50223&owner_price_region_name=%E5%8C%97%E4%BA%AC&sort_type=time_reverse&offset=0&page_size=10&iid=3035074666959895&device_id=1469370100097725&ac=wifi&channel=wandoujia&aid=36&app_name=automobile&version_code=651&version_name=6.5.1&device_platform=android&ab_client=a1%2Cc2%2Ce1%2Cf2%2Cg2%2Cf7&ab_group=2589722&ssmix=a&device_type=Pixel&device_brand=google&language=zh&os_api=29&os_version=10&manifest_version_code=651&resolution=1080*1794&dpi=420&update_version_code=6512&_rticket=1629894505066&cdid=f3034d66-09c7-4a46-a724-b1334073e9b4&city_name=%E5%8C%97%E4%BA%AC&gps_city_name=%E5%8C%97%E4%BA%AC&selected_city_name&rom_version=29&longi_lati_type=1&longi_lati_time=1629894505693&content_sort_mode=0&overall_score=6.8389&cpu_score=6.8915&host_abi=armeabi-v7a
 
{

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-10-21 11:56 被贪吃虫编辑 ,原因: 细节调整
收藏
免费 7
支持
分享
最新回复 (14)
雪    币: 2058
活跃值: (1636)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Good
2021-8-30 20:29
0
雪    币: 2380
活跃值: (573)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
6666666
2021-9-1 10:04
0
雪    币: 1114
活跃值: (2094)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
4
"知道了参数,运行下yang神脚本,看一下用的哪个so"
这个脚本是啥呀
2021-9-1 11:48
1
雪    币: 1
活跃值: (832)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
DiamondH "知道了参数,运行下yang神脚本,看一下用的哪个so" 这个脚本是啥呀
https://github.com/lasting-yang/frida_hook_libart
第二个样例:2. hook_RegisterNatives
yang神牛逼
2021-9-1 12:34
1
雪    币: 2089
活跃值: (3933)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
儿时的恐惧是看见开着大奔,拉下黑色反光车窗,出现戴着墨镜的脸。
现在大奔C级竟然就两台卡罗拉的价格,所以我看见开奔驰C的都使劲黑,破坏了我对大奔的所有幻想,差评!
2021-9-1 16:00
0
雪    币: 1
活跃值: (832)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
lhxdiao 儿时的恐惧是看见开着大奔,拉下黑色反光车窗,出现戴着墨镜的脸。 现在大奔C级竟然就两台卡罗拉的价格,所以我看见开奔驰C的都使劲黑,破坏了我对大奔的所有幻想,差评!
以后不知道电动新势力能不能把传统车厂**掉
2021-9-1 16:17
0
雪    币: 117
活跃值: (1557)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
对于 so层 ,直接反射,挂载,省时省力
2021-9-1 17:53
0
雪    币: 1
活跃值: (832)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
小爱逆天 对于 so层 ,直接反射,挂载,省时省力
大佬,缺腿部挂件吗
2021-9-1 17:59
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
10
相声说得挺好,改汇编那个IDA就直接改了,方便省事,可以不用代码patch
2021-9-3 10:02
0
雪    币: 1
活跃值: (832)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
0x指纹 相声说得挺好,改汇编那个IDA就直接改了,方便省事,可以不用代码patch
嗯,我再练习unidbg,就用这个试试,感谢大佬指点
2021-9-3 11:33
0
雪    币: 18
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
恶龙没有死,正在悄悄复苏,正在谋划一场更大的灾难,骑士该如何面对,预知下集精彩,请持续关注白龙与傻宝的历练之路。
2021-9-5 22:11
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
建议写成连续剧
2021-10-25 18:08
0
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
拜读了大佬的文章 感觉受益匪浅 但感觉逻辑层面还是有一点说不懂 t_key是客户端通过参数1加密生成的 加密内容是"dongchedi" + t_key生成的时间戳字符串 那么服务器那边可以解密t_key得到客户端的参数1和生成时间 从而使客户端解密时提供正确的参数1以及合理的时间戳才能成功解密数据 但问题的关键是 服务器又是怎么解密t_key的呢 服务器不也得有参数1才能解密吗 除非参数1通过其他形式传给了服务器 不然就解释不通 仅靠t_key是肯定不行的 或者说服务器端有不需要参数1就能对t_key进行解密的魔法函数?感觉这个可能性不大呀...
2021-10-26 09:49
1
雪    币: 1
活跃值: (832)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
tkey是通过4个参数生成的,参数1是其中一个,对方可能是通过参数3最为密钥加密。服务端拿到后再用这个密钥解密,就能拿到这4个参数。
2021-10-29 12:20
0
游客
登录 | 注册 方可回帖
返回
//