某广告SDK流量加解密-响应

接着上次的写,这次跟一下响应数据的解密

响应

看过这么多广告sdk,他们的流量数据,基本都是放在 JSONObject 中,所以直接从  JSONObject 中下手hook就稳稳的

某广告SDK流量加解密-响应_第1张图片

 某广告SDK流量加解密-响应_第2张图片

 其调用栈为如下:

某广告SDK流量加解密-响应_第3张图片

 根据上面的调用栈对  com.bytedance.sdk.openadsdk.core.q 的 g 函数 hook

某广告SDK流量加解密-响应_第4张图片

 其参数如下:

某广告SDK流量加解密-响应_第5张图片

 发现该函数的参数还是密文,说明密文就是在 g 函数内部进行解密的,其解密函数就是下面的 b 函数:

某广告SDK流量加解密-响应_第6张图片

 在 b 函数中先对密文进行切割,然后将切割的字符串传入 a.b 函数中

某广告SDK流量加解密-响应_第7张图片

 其中参数三还被函数a处理过

某广告SDK流量加解密-响应_第8张图片

由上面可知 a.b 函数的三个参数依次为:

参数一为:密文的第50位到结尾

参数二为:密文第34位到49位

参数三为:密文第2位到33位,前16位与后16位对换

a.b 函数为如下:

某广告SDK流量加解密-响应_第9张图片

函数具体解密逻辑为:

1 对参数一先用base64解密

2 由参数三生成密钥

3 设置解密模式为 "AES/CBC/PKCS5Padding"

4 初始化解密参数,写入参数三生成的密钥,并由参数二生成初始化向量

5 对参数一base64解密后的数据进行解密

到这里穿山甲流量的解密就完成了,直接copy代码写了一个解密的jar包

CSJDcrypt.java
package com.yooha;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileReader;
import java.io.IOException;

public class CSJDcrypt {


    public static void main(String[] args) throws IOException {
        String s = readfile(args[0]);
        System.out.println(decrypt(s));
    }

    public static String readfile(String filename) throws IOException {
        FileReader fileReader=new FileReader(filename);
        int length=0;
        char[] cfile = new char[0X1000 * 100];
        int index = 0;
        while((length=fileReader.read())!=-1) {
            cfile[index++] = (char)length;
        }
        char[] newstr = new char[index + 1];
        for(int i = 0; i < index; i++){
            newstr[i] = cfile[i];
        }
        newstr[index] = 0;
        fileReader.close();
        return new String(newstr);
    }


    public static String a(String str, int i2) {
        if (str == null || str.length() != i2) {
            return null;
        }
        int i3 = i2 / 2;
        return str.substring(i3, i2) + str.substring(0, i3);
    }


    public static String decrypt(String str) {
        if (isEmpty(str) || str.length() < 49) {
            return str;
        }
        String a = a(str.substring(1, 33), 32);
        String substring = str.substring(33, 49);
        return (substring == null || a == null) ? str: _decrypt(str.substring(49), substring, a);
    }

    public static String _decrypt(String str, String str2, String str3) {
        if (isEmpty(str)) {
            return null;
        }
        try {
            byte[] decode = MyBase64.decode(str.getBytes());
            System.out.println("str3 = " + str3);
            SecretKeySpec secretKeySpec = new SecretKeySpec(str3.getBytes(), "AES");
            System.out.println("str3 = " + secretKeySpec.getEncoded());
            Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
            instance.init(2, secretKeySpec, new IvParameterSpec(str2.getBytes()));
            String ret = new String(instance.doFinal(decode), "utf-8");
            return ret;
        } catch (Exception e2) {
            System.out.println("_decrypt -> error = " + e2.getMessage());
            return null;
        }
    }
    public static boolean isEmpty(String str){
        if (str.length() == 0){
            return true;
        }
        return false;
    }


}

MyBase64.java

这个是网上找的一个Base64,你们自己找个能跑起来就行

后来想想,之前有个沙箱当时就是用python调用jar包解密,搞的有点麻烦,沙箱越轻越好,还是直接用python解算了,然后了解了一下Crypto,挺好用的,写了个python的解密脚本

# -*- coding: utf-8 -*-
import base64
from Crypto.Cipher import AES 
 
class AES_CIPHER(object):
 
    #解密函数 ("AES/CBC/PKCS5Padding");
    @classmethod
    def _decrypt(cls, str1, str2, str3):
        cryptor = AES.new(str3.encode("utf8"), AES.MODE_CBC, str2.encode("utf8"))
        plain_text = cryptor.decrypt(base64.b64decode(str1))
        unpad = lambda s: s[0:-ord(s[-1:])]
        return unpad(plain_text)
 
 
    @classmethod
    def decrypt(cls, info):
        if len(info) < 49:
            return info
        else:
            return cls._decrypt(info[49:], info[33:49], info[1:33][16:32] + info[1:33][0:16]).decode('utf-8')
         
 
if __name__ == '__main__':
    with open("flow.txt", "r", encoding='utf-8') as out:
        info = out.readline()
    print(AES_CIPHER.decrypt(info))

没错,用python写代码就是这么少。下面是解密内容

某广告SDK流量加解密-响应_第10张图片

后面我写了一个广告sdk自渲染广告的监控工具,链接:https://github.com/YoooHaaa/renderAd

有兴趣可以去看看,工具拿来把js脚本改改,就能复用到其他业务上

你可能感兴趣的:(安卓逆向,python,java)