某APPsign签名参数分析

分析该APP的包请求,在Fiddler中发现一个请求包:

bdf9d4736452188d229c52753518f957.png

想把其中的签名弄清楚,然后用python去模拟协议。

原始返回的数据是protobuf的格式,通过修改请求头Accept,可以让服务器返回json的数据格式。

具体操作步骤为:直接将请求头中的Accept: application/x2-protostuff; charset=UTF-8,更改为:Accept: application/json; charset=UTF-8

但是如果直接请求,浏览器会报签名错误:

483de67dc3186174dd449d26157e7ddf.jpeg

注意看请求头中,有两个签名(sign和sg字段),因此这两个签名需要逆向解决,另外还需要知道oak(可能是key)是什么东西。

所以直接将app拖到jeb里面,首先通过查找网址,可以搜索到其构造URL的代码逻辑块,位于:

f023dc695e6c07126a2c0d02d51514f5.png

通过上述定位,可以找到发起请求的入口:

3fce25edd9f840e289dbb554439aa169.png

再往下分析,查看函数makeRequestByPkgName,这个调用就是通过包名获取信息的函数接口:

d1d3d5cc53e065669f289091c8c1ccee.png

这里new了一个请求ProductDetailRequest,实现了com.nearme.network.request.IRequest接口,进入到请求类中,查看具体的实现:

bdce4824e4d8aed415c5bb0266e5aaa6.png

上图中可以发现,请求操作在com.nearme.network.c类中的函数中,查看函数上一跳,发现请求接口:com.nearme.network.extend.d.request

继续分析可以发现该请求接口设置了拦截器并通过initHeader函数初始化了请求头:

62b3a4d34c11e5015a371d7339e5d073.png

通过分析请求头中的参数来源,将部分重要参数和对应的说明,以及抓包中获取的值列表如下:

参数
参数说明抓包获取的值
otaverOTA版本,即系统属性”ro.build.version.ota“PERM00_11.C.08_1080_202201271341
device_type设备类型

0:手机

1:折叠设备

2:平板

0
User-Agent

浏览器UA信息(URLEncode)

数据格式是:设备生产商/设备型号/安卓系统版本号/安卓版本/设备ROM版本号/APP_CODE/APP渠道号(默认为0)/应用市场版本号/应用市场版本名

OPPO%2FPERM00%2F30%2F11%2FV11.1%2F2%2F2101%2F110005%2F11.0.1
t当前时间戳1699251997861
id

代码中的openid

数据格式是:GUID/OUID/DUID/AndroidId

/2bcba0937bc629468b9886c10bf3cbbada3d743768ece4f548a80e41d9360e6a/AA177E8E54FA42CA928C9638A9BDFB8C5bb7929185700b4a882306a43cc6710f/CD623898E41E4FB18BD2ED0842CC0AADEC7D424979CC9C51C70EAC900ECAD017
ocs数据格式:设备生产商/设备型号/安卓系统版本号/安卓版本/设备ROM版本号/APP_CODE/ro.build.display.id/应用市场版本号

然后经过URLencode处理

OPPO%2FPERM00%2F30%2F11%2FV11.1%2F2%2FPERM00_11_C.08%2F110005
sign签名147e29daacff4479021520eac9100a1cd
sg签名2
4df40cedbd7d5fec9876600cccb235a9
oak签名密钥keycdb09c43063ea6bb

通过请求测试,签名sign、sg、oak是服务器作为校验的依据,所以需要对上面三个参数做分析。

①:参数”oak“来源的分析

java层获取该参数的代码块是:

598ff69a9ddd91184093126d30717528.jpeg

函数跳转到native层,so文件名称:libocstool.so。

上述JNI函数通过静态注册,查看b函数:

55234f7b71e54e08c2d159b5828fa4c1.png

发现key1通过a函数初始化得出,在请求之前进行初始化,并校验APP的签名。

如果APP签名校验不通过,则key得不到初始化,应用内所有的请求都会返回错误。

4c1ccd71974fee00634bb5280d8684b3.png

进入init_key,key1的来源通过包名进行绑定,所以与该应用市场对应的包名的key1为cdb09c43063ea6bb

3bfccae4047257f92067989c3b33807e.png

②:参数”sign“来源的分析

在java层,通过组合特定的参数传入签名函数中:

5d098858b61167c65c082ea0638c5f7d.png

hook一下,可以看到值,通过分析也可以知道传入的参数为:设备生产商/设备型号/安卓系统版本号/安卓版本/设备ROM版本号/APP_CODE/ro.build.display.id/应用市场版本号+当前时间戳/GUID/OUID/DUID/AndroidId/URL_Path+URL_Query

3dfd36052879e9fd9c771bf20de5dba6.png

参数已经分析完毕,接下来来看sign的签名算法:

在上述初始化key1结束后,函数立即初始化了key2:

b18da0f0ed8d0a25488ebb376de2b7dd.jpeg

跟踪调用实现,发现key2 通过计算得出:

0634dd1acea44acac84285ea95cdcd66.png

简单描述一下生成逻辑:算法:通过去掉v1前两位,然后将v1剩下的部分头尾交换,再拼接上key1,组成一个48位的key2:

key1v1key2
cdb09c43063ea6bb09bdc58acb383220be08f4fe8a43775179cdb09c43063ea6bb08f4fe8a43775179bdc58acb383220be

进入到c函数,可以发现sign的签名是通过MD5计算得出:

4f3bd260fe30ab2d977b4f5aa2627176.png

算法可以概括为:toHex(MD5(key2 + a1 +(a1的长度+key2的长度)+OBSCURE_CODE))

③:参数”sg“来源的分析

java层中,签名1将作为参数传递给签名2:

c433892255a31613ef7040bcfe6995fc.png

然后再组合相应的参数,丢到native层中:

5076b58f22b96e1319a99a96fd6f5e2a.jpeg

通过分析也可以知道d函数的两个参数是什么,参数a3为Url_path + Url_query+Accept+请求类型字符串(get、post、put、head四选一)+openid+时间戳,参数a4为上面计算的sign。

查看函数d,首先这里将参数a3、key1和a4字符串相合并,然后计算长度,然后再加上计算的长度数字,计算一轮MD5,即MD5(a3+key1+a4+长度数字字符串):

0af378469daac3e9001b3e9e311ca0fb.png

然后这里计算出MD5之后,拿着MD5的byte字节数据数组,数组中的每一个数字取绝对值之后,取个位数字(%10)相加再%10:

261f5c46bf331d6fd1181e0916abdc37.jpeg

最后得到的v28其实是个数字,取值范围为0-9。然后,对得到的数字再%5,取密钥数组的下标:

b0c45c0c843a8ee4486d96de723543b8.jpeg

密钥数组sgk和sgsk是一个长度为5的数组:

b4235d04bd3187e0a19ef85f97b4a4f6.png

通过上面的计算得到目标密钥sgk_sel和sgsk_sel。然后将参数a3与两个目标密钥相加,最后链接上相加后字符串的长度作为待签名数据

对累加后的字符串,根据上面计算的v28数字选择不同的签名算法,最后再转为String,即得到签名sg的值:

  • v28大于5,使用SHA1算法签名,即:SHA1(a3+sgk_sel+sgsk_sel+长度)

  • v28小于5,使用MD5算法签名,即:MD5(a3+sgk_sel+sgsk_sel+长度)

47bf7b30ab74c7c863a268997b09d3f2.png

基于上述分析,就可以编写一个简单的python request请求。通过请求就能获取到正确的返回数据了:

bb84c1b760f25bbcfd2ac5c0f8226bae.png

原文链接:https://bbs.kanxue.com/thread-280869.htm

关注我获取更多知识或者投稿

eeaa80504d830f6f31de5cb0174071fd.jpeg

b0a549624486fad15b9e459d06943b25.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值