【安卓逆向】某瓣app sig参数分析

今天我们要分析的app 是6LGG55OjdjcuMTguMA== (base64解码),小伙伴们可以去各大应用商定自行下载。赶紧记录下分析流程,是作为一个逆向分析的很好案例。

参考链接:

  1. https://blog.csdn.net/weixin_43582101/article/details/121670287
  2. https://blog.csdn.net/qq_23594799/article/details/108446352
    转载文章,请注明出处,谢谢!https://blog.csdn.net/weixin_38819889/article/details/122005142

1.抓包找参数

在这里插入图片描述

如上图所示,通过charles抓包,找接口,然后找到我们最终要研究的参数 _sig,
其他接口比如udid 猜测是用户uid是固定值,apikey ,device_id和apple应该代表的就是当前设备参数信息,直接固定就能用(ps:没有大批量测试,只是猜测,不是研究的重点,请忽略。)

2.反编译apk

找到加密参数_sig,接下来就是反编译apk,看看里面的加密逻辑到底是咋写的,这时候拿出我们的大宝贝jadx,有不会的同学可自行百度下如何使用。然后把豆瓣app拖进到jadx中,一会就会反编译好。

在这里我们直接搜索 “_sig” 关键字,还好 还好,找到的相似代码不是很多,来我们一个一个的看 ,这里觉得 builder.add("_sig", (String) a2.first);很可疑,点进去看看。
在这里插入图片描述

跳转进去以后,可以看到 "_sig"参数 是 a2.first 的方法返回来的,具体是干嘛目前不知道,不过不要紧,继续跟进发现 a2 是Pair<String, String> a2 = ApiSignatureHelper.a(request);这个方法声明实例化的一个对象(ps:java学的不好,表述可能不准)。然后点进去看看ApiSignatureHelper这个类具体是咋实现的。
在这里插入图片描述

然后就来到这里了,可以看到ApiSignatureHelper类的下面的a方法,就是我们今天要搞的加密地方。
在这里插入图片描述
整个加密代码如下,然后我们先静态分析一下java代码,一会再用frida动态分析一波验证下我们的猜想。

3.分析加密逻辑

首先看到a方法传入三个参数str,str2 和 str3,然后定义一个变量decode 具体干嘛的不知道, 之后定义一个str4,这是一个AES加密的秘钥key(很重要,后来才知道的),然后用StringBuilder类创建一个sb对象 ,你可以理解为用python 定义一个字符串 对象,再然后 定义一个encodedPath 这个东西就是请求url的path(后来动态分析以后才知道的),同时还把url路径path 给url 编码了,然后又拼接了一个StringPool.AMPERSAND 这是啥东西 点进去看看

在这里插入图片描述
发现是一个&符号,最后是拼接一个10位时间戳currentTimeMillis,最后把拼接好的字符串sb,最后调用HMACHash1.a()该方法,并把str4和sb作为参数传进去,最后得到加密的结果。那好,我们再点进去看看HMACHash1.a()方法是咋写的,继续往下走。

public class ApiSignatureHelper {
    static Pair<String, String> a(Request request) {
        if (request == null) {
            return null;
        }
        String header = request.header(com.douban.push.internal.api.Request.HEADER_AUTHORIZATION);
        if (!TextUtils.isEmpty(header)) {
            header = header.substring(7);
        }
        return a(request.url().toString(), request.method(), header);
    }

    public static Pair<String, String> a(String str, String str2, String str3) {
        String decode;
        if (TextUtils.isEmpty(str)) {
            return null;
        }
        String str4 = FrodoApi.a().e.b;
        if (TextUtils.isEmpty(str4)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(str2);
        String encodedPath = HttpUrl.parse(str).encodedPath();
        if (encodedPath == null || (decode = Uri.decode(encodedPath)) == null) {
            return null;
        }
        if (decode.endsWith("/")) {
            decode = decode.substring(0, decode.length() - 1);
        }
        sb.append(StringPool.AMPERSAND);
        sb.append(Uri.encode(decode));
        if (!TextUtils.isEmpty(str3)) {
            sb.append(StringPool.AMPERSAND);
            sb.append(str3);
        }
        long currentTimeMillis = System.currentTimeMillis() / 1000;
        sb.append(StringPool.AMPERSAND);
        sb.append(currentTimeMillis);
        return new Pair<>(HMACHash1.a(str4, sb.toString()), String.valueOf(currentTimeMillis));
    }
}

然后我们就来到了这里,根据关键词 HMACHash1 和Base64
,可以大胆的猜测下这是hmac和base64加密算法,恭喜你猜对了。要是对hmac不熟悉的看看这篇文章:https://blog.csdn.net/weixin_38819889/article/details/122457122?spm=1001.2014.3001.5501

public class HMACHash1 {
    public static final String a(String str, String str2) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(str.getBytes(), LiveHelper.HMAC_SHA1);
            Mac instance = Mac.getInstance(LiveHelper.HMAC_SHA1);
            instance.init(secretKeySpec);
            return Base64.encodeToString(instance.doFinal(str2.getBytes()), 2);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

静态分析的差不多了,接下来用我们的frida动态调试一下,看看实际的效果是什么样子的。

4.frida调试一下:

首先启动frida服务,把js注入到进程里面 执行一下命令:

frida -U com.douban.frodo -l hook_douban.js
Java.perform(
    function(){
            var apisig = Java.use("com.douban.frodo.network.ApiSignatureHelper");

            apisig.a.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function (a1,a2, a3){
                console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓豆瓣hook--sig 开始↓↓↓↓↓↓↓↓↓↓↓↓↓");
                console.log("apisig传入参数1:", a1);
                console.log("apisig传入参数2:", a3);
                console.log("apisig传入参数3:", a3);
                var sig_res = apisig.a(a1, a2, a3)
                console.log("apisig加密result:" + sig_res);
                console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑豆瓣hook--sig 结束↑↑↑↑↑↑↑↑↑↑↑↑↑");
                return sig_res;
            }

            apisig.a.overload('okhttp3.Request').implementation = function (a0){
                console.log("apisig传入参数0:", a0);
                var sig_res1 = apisig.a(a0)
                console.log("apisig重载加密result:" + sig_res1);
                return sig_res1;
            }

            var HMACHash1 = Java.use("com.douban.frodo.utils.crypto.HMACHash1");
            HMACHash1.a.overload('java.lang.String', 'java.lang.String').implementation = function (a1,a2) {
                console.log("HMACHash1传入参数1:", a1);
                console.log("HMACHash1传入参数2:", a2);
                var res = HMACHash1.a(a1,a2);
                console.log("HMACHash加密result:" + res);
                return res;
            }

    }
)

动态运行的效果如下:

在这里插入图片描述

详细分析的已经差不多了,总结下就是把get请求+请求url的path+时间戳作为sb和str4作为hmac加密的参数,计算出来一个值,再然后base64加密一下,就得到最终加密参数_sig
最后 用python还原一波,看看拿到的数据。
在这里插入图片描述
具体代码就不公布了,有兴趣的可以自己尝试分析一下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值