首页
社区
课程
招聘
[原创]某大厂生鲜超市加密协议分析
发表于: 2021-11-18 20:24 14286

[原创]某大厂生鲜超市加密协议分析

2021-11-18 20:24
14286

Charles

关于charles的使用可翻阅我之前的charles专题文章

Nexus 5x

郑重声明,本文只分享思路,不做它用,为保护案例商家安全隐私,敏感信息用xxx代替

curl
所有接口调用url均为https://colour.xxxxxxx.com/api, 通过postbody参数functionId控制获取具体的数据

postBody URL解码后

接口正确返回 responseBody

接口错误返回:接口有调用时效,会检测时间戳参数t,时效性为五分钟,五分钟后再次调用返回异常

接口分析得知,有三个加密参数 sign eu fv

jadx-反编译

frida+objection 动态调试

sign从字符串特征和长度来看,看起来像sha256

jadx打开apk搜索关键字“HmacSha256”,看到加密HmacSha256搜选出多个

image-20211118200626723

frida+objection跟踪调用入参

需要objection个个追踪然后和抓包得到的sign比对,最终确定调用的为 com.xxx.common.http.GatewaySignatureHelper.HMACSHA256
image-20211118200712661

image-20211118200745887

objection追踪

--dump-backtrace追踪调用方法栈

上游重要的方法为这三个:
com.xxx.common.http.GatewaySignatureHelper.HMACSHA256(Native Method)
com.xxx.common.http.GatewaySignatureHelper.signature(TbsSdkJava:60)
com.xxx.common.http.HttpRequest.paramHandler(TbsSdkJava:108)

追signature

多次触发抓包发现调用的是以下方法

多次触发调用后,可确定第二个参数str是加密盐值,且为恒定值:fa5010c35exxxxxxx40060d65d3f3801
第一个参数是map,objection只显示为[object Object],无法显示其具体kv内容
写个frida hook脚本将map kv打印出来

但很遗憾,有反注入检测,执行后app直接重启
也没关系,用笨办法试一下,将postbodyStr按&切开后组装成map,调用signature看看得到的sign是否一致,或者相差多少

好家伙,运行后发现sign和接口抓包的一毛一样
说明postBody中所有的参数都参与了sign的运算,换句话说sign参数是postBody参数构造的最后一步。

这两个一致在变化,应该也是加密
搜下代码

image-20211118201231262
有多个,xxxcrashreport像是崩溃报告类,排除。其他的一个一个watch追吧

定位到

image-20211118201321979

image-20211118201401263
image-20211118201438690

由于eu和fv一致变化,猜测androidId是随机的,即调用了getRandomString方法,此可以通过hook证明确实调用了getRandomString
image-20211118201513898
eu和fv的加工
image-20211118201546631
对象EncryptResult只是个简单的封装,含有eu和fv两个参数
那么java很好还原,做做变体即可。
用到的HexUtils如下,还原时照抄就好了
image-20211118201621038

 
 
curl -H 'Host: colour.xxxxxxx.com' -H 'x-mlaas-at: wl=0' -H 'user-agent: xxxxxxxapp_android' -H 'content-type: application/x-www-form-urlencoded; charset=utf-8' --data-binary "commonExtend=&loginType=4&sign=b6beeee33ad4142cc54f3e55a045fbb1c70ecdfdbffa985b559cc36797d20357&screen=1794*1080&d_brand=LGE&body=%7B%22commonExtend%22%3A%22%22%2C%22data%22%3A%7B%22lon%22%3A%22120.02877%22%2C%22lat%22%3A%223x.278442%22%7D%2C%22appName%22%3A%22xxxxxxx%22%2C%22screen%22%3A%221794*1080%22%2C%22lon%22%3A%221xx.143936%22%2C%22platformId%22%3A%221%22%2C%22clientVersion%22%3A%223.6.4%22%2C%22storeId%22%3A%22232686%22%2C%22recommendSwitch%22%3A%22true%22%2C%22eu%22%3A%2275B6364667C69667%22%2C%22fv%22%3A%220333461727947597%22%2C%22osVersion%22%3A%228.1.0%22%2C%22partner%22%3A%22huawei%22%2C%22v%22%3A2%2C%22tenantId%22%3A%221%22%2C%22client%22%3A%22android%22%2C%22clientVersionBuild%22%3A%222110251117%22%2C%22model%22%3A%22Nexus5X%22%2C%22networkType%22%3A%22wifi%22%2C%22brand%22%3A%22LGE%22%2C%22lat%22%3A%223x.323437%22%7D&clientVersion=3.6.4&eu=75B6364667C69667&fv=0333461727947597&d_model=Nexus5X&functionId=xxxxxxx_platform_address_getPosition&t=1636957653670&partner=huawei&osVersion=8.1.0&build=2110251117&appid=****fresh_APP&client=xxxxxxx_android&lang=zh_CN&networkType=wifi" --compressed 'https://colour.xxxxxxx.com/api'
curl -H 'Host: colour.xxxxxxx.com' -H 'x-mlaas-at: wl=0' -H 'user-agent: xxxxxxxapp_android' -H 'content-type: application/x-www-form-urlencoded; charset=utf-8' --data-binary "commonExtend=&loginType=4&sign=b6beeee33ad4142cc54f3e55a045fbb1c70ecdfdbffa985b559cc36797d20357&screen=1794*1080&d_brand=LGE&body=%7B%22commonExtend%22%3A%22%22%2C%22data%22%3A%7B%22lon%22%3A%22120.02877%22%2C%22lat%22%3A%223x.278442%22%7D%2C%22appName%22%3A%22xxxxxxx%22%2C%22screen%22%3A%221794*1080%22%2C%22lon%22%3A%221xx.143936%22%2C%22platformId%22%3A%221%22%2C%22clientVersion%22%3A%223.6.4%22%2C%22storeId%22%3A%22232686%22%2C%22recommendSwitch%22%3A%22true%22%2C%22eu%22%3A%2275B6364667C69667%22%2C%22fv%22%3A%220333461727947597%22%2C%22osVersion%22%3A%228.1.0%22%2C%22partner%22%3A%22huawei%22%2C%22v%22%3A2%2C%22tenantId%22%3A%221%22%2C%22client%22%3A%22android%22%2C%22clientVersionBuild%22%3A%222110251117%22%2C%22model%22%3A%22Nexus5X%22%2C%22networkType%22%3A%22wifi%22%2C%22brand%22%3A%22LGE%22%2C%22lat%22%3A%223x.323437%22%7D&clientVersion=3.6.4&eu=75B6364667C69667&fv=0333461727947597&d_model=Nexus5X&functionId=xxxxxxx_platform_address_getPosition&t=1636957653670&partner=huawei&osVersion=8.1.0&build=2110251117&appid=****fresh_APP&client=xxxxxxx_android&lang=zh_CN&networkType=wifi" --compressed 'https://colour.xxxxxxx.com/api'
commonExtend=&loginType=4&sign=b6beeee33ad4142cc54f3e55a045fbb1c70ecdfdbffa985b559cc36797d20357&screen=1794*1080&d_brand=LGE&body={"commonExtend":"","data":{"lon":"xxx.02877","lat":"xx.278442"},"appName":"xxxxxxx","screen":"1794*1080","lon":"xxx.143936","platformId":"1","clientVersion":"3.6.4","storeId":"232686","recommendSwitch":"true","eu":"75B6364667C69667","fv":"0333461727947597","osVersion":"8.1.0","partner":"huawei","v":2,"tenantId":"1","client":"android","clientVersionBuild":"2110251117","model":"Nexus5X","networkType":"wifi","brand":"LGE","lat":"xx.323437"}&clientVersion=3.6.4&eu=75B6364667C69667&fv=0333461727947597&d_model=Nexus5X&functionId=xxxxxxx_platform_address_getPosition&t=1636957653670&partner=huawei&osVersion=8.1.0&build=2110251117&appid=****fresh_APP&client=xxxxxxx_android&lang=zh_CN&networkType=wifi
commonExtend=&loginType=4&sign=b6beeee33ad4142cc54f3e55a045fbb1c70ecdfdbffa985b559cc36797d20357&screen=1794*1080&d_brand=LGE&body={"commonExtend":"","data":{"lon":"xxx.02877","lat":"xx.278442"},"appName":"xxxxxxx","screen":"1794*1080","lon":"xxx.143936","platformId":"1","clientVersion":"3.6.4","storeId":"232686","recommendSwitch":"true","eu":"75B6364667C69667","fv":"0333461727947597","osVersion":"8.1.0","partner":"huawei","v":2,"tenantId":"1","client":"android","clientVersionBuild":"2110251117","model":"Nexus5X","networkType":"wifi","brand":"LGE","lat":"xx.323437"}&clientVersion=3.6.4&eu=75B6364667C69667&fv=0333461727947597&d_model=Nexus5X&functionId=xxxxxxx_platform_address_getPosition&t=1636957653670&partner=huawei&osVersion=8.1.0&build=2110251117&appid=****fresh_APP&client=xxxxxxx_android&lang=zh_CN&networkType=wifi
{
    "code": "0",
    "success": true,
    "msg": null,
    "data": {
        "success": true,
        "businessCode": 0,
        "msg": null,
        "type": 1,
        "locationInfo": {
            "addressExt": "浙江xxxxxxx",
            "addressSummary": "浙江省xxx",
            "storeId": null,
            "lat": "xx.27x442",
            "lon": "xxx.02x77",
            "testShop": false
        },
        "defaultAddress": null,
        "tenantShopInfoList": [{
            "storeId": 232xxx,
            "storeName": "华东****鲜云超",
            "storeAddress": "江东中路与江东门北街交汇处",
            "promiseInfo": "最快30分钟达 | 230.96KM",
            "tenantDesc": "",
            "businessInfo": "",
            "tenantInfo": {
                "tenantId": 1,
                "tenantName": "****鲜",
                "bigLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/144864/26/9153/27011/5f6ae507E9dfc96a5/fc2f58d77bcbf2cd.png",
                "smallLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/143548/8/13335/6626/5fa4affbE87f4ded3/f46b57081818d3ba.png",
                "circleLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/140501/2/9085/6589/5f6ae50bE0508f49c/ae52b1fc1dc2aa59.png",
                "contactTel": "4006068768",
                "supportGiftCard": false,
                "supportEmployeeCard": false,
                "supportInvoiceCenter": false,
                "supportBalance": false,
                "clientInfo": null
            },
            "lon": "118.737681",
            "lat": "32.036757",
            "valid": true,
            "freeBuy": false,
            "delivery": false
        }, {
            "storeId": 196243,
            "storeName": "华中****鲜云超",
            "storeAddress": "光谷保利广场",
            "promiseInfo": "最快30分钟达 | 539.52KM",
            "tenantDesc": "",
            "businessInfo": "",
            "tenantInfo": {
                "tenantId": 1,
                "tenantName": "****鲜",
                "bigLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/144864/26/9153/27011/5f6ae507E9dfc96a5/fc2f58d77bcbf2cd.png",
                "smallLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/143548/8/13335/6626/5fa4affbE87f4ded3/f46b57081818d3ba.png",
                "circleLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/140501/2/9085/6589/5f6ae50bE0508f49c/ae52b1fc1dc2aa59.png",
                "contactTel": "4006068768",
                "supportGiftCard": false,
                "supportEmployeeCard": false,
                "supportInvoiceCenter": false,
                "supportBalance": false,
                "clientInfo": null
            },
            "lon": "114.410486",
            "lat": "30.490744",
            "valid": true,
            "freeBuy": false,
            "delivery": false
        }],
        "nearStore": false,
        "fix": false,
        "fixLat": null,
        "fixLon": null
    },
    "extMap": {}
}
{
    "code": "0",
    "success": true,
    "msg": null,
    "data": {
        "success": true,
        "businessCode": 0,
        "msg": null,
        "type": 1,
        "locationInfo": {
            "addressExt": "浙江xxxxxxx",
            "addressSummary": "浙江省xxx",
            "storeId": null,
            "lat": "xx.27x442",
            "lon": "xxx.02x77",
            "testShop": false
        },
        "defaultAddress": null,
        "tenantShopInfoList": [{
            "storeId": 232xxx,
            "storeName": "华东****鲜云超",
            "storeAddress": "江东中路与江东门北街交汇处",
            "promiseInfo": "最快30分钟达 | 230.96KM",
            "tenantDesc": "",
            "businessInfo": "",
            "tenantInfo": {
                "tenantId": 1,
                "tenantName": "****鲜",
                "bigLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/144864/26/9153/27011/5f6ae507E9dfc96a5/fc2f58d77bcbf2cd.png",
                "smallLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/143548/8/13335/6626/5fa4affbE87f4ded3/f46b57081818d3ba.png",
                "circleLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/140501/2/9085/6589/5f6ae50bE0508f49c/ae52b1fc1dc2aa59.png",
                "contactTel": "4006068768",
                "supportGiftCard": false,
                "supportEmployeeCard": false,
                "supportInvoiceCenter": false,
                "supportBalance": false,
                "clientInfo": null
            },
            "lon": "118.737681",
            "lat": "32.036757",
            "valid": true,
            "freeBuy": false,
            "delivery": false
        }, {
            "storeId": 196243,
            "storeName": "华中****鲜云超",
            "storeAddress": "光谷保利广场",
            "promiseInfo": "最快30分钟达 | 539.52KM",
            "tenantDesc": "",
            "businessInfo": "",
            "tenantInfo": {
                "tenantId": 1,
                "tenantName": "****鲜",
                "bigLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/144864/26/9153/27011/5f6ae507E9dfc96a5/fc2f58d77bcbf2cd.png",
                "smallLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/143548/8/13335/6626/5fa4affbE87f4ded3/f46b57081818d3ba.png",
                "circleLogo": "http://img12.360buyimg.com/freshapp/jfs/t1/140501/2/9085/6589/5f6ae50bE0508f49c/ae52b1fc1dc2aa59.png",
                "contactTel": "4006068768",
                "supportGiftCard": false,
                "supportEmployeeCard": false,
                "supportInvoiceCenter": false,
                "supportBalance": false,
                "clientInfo": null
            },
            "lon": "114.410486",
            "lat": "30.490744",
            "valid": true,
            "freeBuy": false,
            "delivery": false
        }],
        "nearStore": false,
        "fix": false,
        "fixLat": null,
        "fixLon": null
    },
    "extMap": {}
}
{"code":"1","echo":"invalid signature"}
{"code":"1","echo":"invalid signature"}
 
 
 
 
 
 
 
android hooking watch class_method com.xxx.common.http.GatewaySignatureHelper.HMACSHA2
56  --dump-args --dump-return --dump-backtrace
android hooking watch class_method com.xxx.common.http.GatewaySignatureHelper.HMACSHA2
56  --dump-args --dump-return --dump-backtrace
(agent) [172759] Called com.xxx.common.http.GatewaySignatureHelper.HMACSHA256([B, [B)
(agent) [172759] Backtrace:
    com.xxx.common.http.GatewaySignatureHelper.HMACSHA256(Native Method)
    com.xxx.common.http.GatewaySignatureHelper.signature(TbsSdkJava:60)
    com.xxx.common.http.HttpRequest.paramHandler(TbsSdkJava:108)
    com.xxx.common.http.HttpRequest.add(TbsSdkJava:9)
    com.xstore.****fresh.modules.search.SearchRequest.getWareInfosIcon(TbsSdkJava:11)
    com.xstore.****fresh.modules.productdetail.utils.GetWareInfoIconUtils.getWareInfoMsg(TbsSdkJava:7)
    com.xstore.****fresh.modules.category.menulist.NewProductCategoryFragment.setListView(TbsSdkJava:34)
    com.xstore.****fresh.modules.category.menulist.NewProductCategoryFragment.initView(TbsSdkJava:32)
    com.xstore.****fresh.modules.category.menulist.NewProductCategoryFragment.onCreateView(TbsSdkJava:3)
    androidx.fragment.app.Fragment.performCreateView(TbsSdkJava:4)
    androidx.fragment.app.FragmentStateManager.createView(TbsSdkJava:15)
    androidx.fragment.app.FragmentStateManager.moveToExpectedState(TbsSdkJava:23)
    androidx.fragment.app.FragmentManager.executeOpsTogether(TbsSdkJava:34)
    androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(TbsSdkJava:10)
    androidx.fragment.app.FragmentManager.execPendingActions(TbsSdkJava:4)
    androidx.fragment.app.FragmentManager$5.run(TbsSdkJava:1)
    android.os.Handler.handleCallback(Handler.java:790)
    android.os.Handler.dispatchMessage(Handler.java:99)
    android.os.Looper.loop(Looper.java:164)
    android.app.ActivityThread.main(ActivityThread.java:6494)
    java.lang.reflect.Method.invoke(Native Method)
    com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 
(agent) [172759] Arguments com.xxx.common.http.GatewaySignatureHelper.HMACSHA256([object Object], [object Object])
(agent) [172759] Return Value: b196066d6b926a9e032ea9ae1b0a52a048b03ac063ad55bfbc3fca0fe88959c6
(agent) [172759] Called com.xxx.common.http.GatewaySignatureHelper.HMACSHA256([B, [B)
(agent) [172759] Backtrace:
    com.xxx.common.http.GatewaySignatureHelper.HMACSHA256(Native Method)
    com.xxx.common.http.GatewaySignatureHelper.signature(TbsSdkJava:60)
    com.xxx.common.http.HttpRequest.paramHandler(TbsSdkJava:108)
    com.xxx.common.http.HttpRequest.add(TbsSdkJava:9)
    com.xstore.****fresh.modules.search.SearchRequest.getWareInfosIcon(TbsSdkJava:11)
    com.xstore.****fresh.modules.productdetail.utils.GetWareInfoIconUtils.getWareInfoMsg(TbsSdkJava:7)
    com.xstore.****fresh.modules.category.menulist.NewProductCategoryFragment.setListView(TbsSdkJava:34)
    com.xstore.****fresh.modules.category.menulist.NewProductCategoryFragment.initView(TbsSdkJava:32)
    com.xstore.****fresh.modules.category.menulist.NewProductCategoryFragment.onCreateView(TbsSdkJava:3)
    androidx.fragment.app.Fragment.performCreateView(TbsSdkJava:4)
    androidx.fragment.app.FragmentStateManager.createView(TbsSdkJava:15)
    androidx.fragment.app.FragmentStateManager.moveToExpectedState(TbsSdkJava:23)
    androidx.fragment.app.FragmentManager.executeOpsTogether(TbsSdkJava:34)
    androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(TbsSdkJava:10)
    androidx.fragment.app.FragmentManager.execPendingActions(TbsSdkJava:4)
    androidx.fragment.app.FragmentManager$5.run(TbsSdkJava:1)
    android.os.Handler.handleCallback(Handler.java:790)
    android.os.Handler.dispatchMessage(Handler.java:99)
    android.os.Looper.loop(Looper.java:164)
    android.app.ActivityThread.main(ActivityThread.java:6494)
    java.lang.reflect.Method.invoke(Native Method)
    com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 
(agent) [172759] Arguments com.xxx.common.http.GatewaySignatureHelper.HMACSHA256([object Object], [object Object])
(agent) [172759] Return Value: b196066d6b926a9e032ea9ae1b0a52a048b03ac063ad55bfbc3fca0fe88959c6
 
android hooking watch class_method com.xxx.common.http.GatewaySignatureHelper.signature  --dump-args --dump-return
android hooking watch class_method com.xxx.common.http.GatewaySignatureHelper.signature  --dump-args --dump-return
public static String signature(Map<String, String> map, String str) {
        if (map == null || map.isEmpty() || TextUtils.isEmpty(str)) {
            return null;
        }
        TreeSet treeSet = new TreeSet();
        for (String str2 : map.keySet()) {
            treeSet.add(str2);
        }
        StringBuffer stringBuffer = new StringBuffer();
        Iterator it = treeSet.iterator();
        while (it.hasNext()) {
            String obj = it.next().toString();
            String str3 = map.get(obj);
            if (DEBUG) {
                String str4 = TAG;
                Log.d(str4, "sorted key : " + obj + ", value : " + str3);
            }
            if (!TextUtils.isEmpty(str3)) {
                stringBuffer.append(str3);
                stringBuffer.append("&");
            }
        }
        String stringBuffer2 = stringBuffer.toString();
        if (stringBuffer2.endsWith("&") && stringBuffer2.length() > 1) {
            stringBuffer2 = stringBuffer2.substring(0, stringBuffer2.length() - 1);
        }
        if (DEBUG) {
            String str5 = TAG;
            Log.d(str5, "raw signature param str : " + stringBuffer2);
        }
        return HMACSHA256(strToByteArray(stringBuffer2), strToByteArray(str));
    }
public static String signature(Map<String, String> map, String str) {
        if (map == null || map.isEmpty() || TextUtils.isEmpty(str)) {
            return null;
        }
        TreeSet treeSet = new TreeSet();
        for (String str2 : map.keySet()) {
            treeSet.add(str2);

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

最后于 2021-11-19 10:33 被灵风_spirit编辑 ,原因: 脱敏
收藏
免费 3
支持
分享
最新回复 (4)
雪    币: 891
活跃值: (591)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
位置暴露了,注意屏蔽
2021-11-19 09:56
0
雪    币: 589
活跃值: (1727)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
多谢
2021-11-19 10:35
0
雪    币: 589
活跃值: (1727)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
位置暴露了,注意屏蔽
多谢
2021-11-19 10:36
0
游客
登录 | 注册 方可回帖
返回
//