安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

admin 2024年9月3日09:18:22评论11 views字数 4835阅读16分7秒阅读模式

0x01 前言

有时候在对APP抓包的时候,经常会遇到参数加密,app也不像web端一样,可以直接打断点进行调试,找到加密方法, 在app没有加壳的情况下,我们可以反编译找加密点,或者是动态调试,这里使用反编译的方法。

0x02 正文

在登陆处点击登录,然后抓包,具体环境配置教程以及抓包教程可以看前两篇文章,可以看到账号密码被加密了,这时候如果apk没有加壳的话,我们可以使用JADX进行反编译

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

因为抓包的时候,路由是/user/login,我们反编译apk后,直接搜索这个

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

基本可以确定就是从这里发起网络请求
跟进addRequestMap方法分析

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

这一看逻辑就清晰了
先添加一个时间戳,在对sign进行加密后在调用encodeDesMap进行加密
最后put到请求中
在分析encodeDesMap

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

有KEY和IV,不是AES就是DES加密
encrypt64

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

DES加密后在Base64加密
那么data就是明文了,hook这个方法取到参数

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
let RequestUtil = Java.use("com.xxx.xxx.http.RequestUtil");
        RequestUtil["encodeDesMap"].overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function (data, desKey, desIV) {
            console.log("**********获取DES明文**********");
            console.log(`参数明文----> ${data}, desKey= ${desKey}, desIV= ${desIV}`);
            let result = this["encodeDesMap"](data, desKey, desIV);
            console.log(`参数加密结果----> ${result}`);
            return result;
        };

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

与抓包结果一样,这样明文就拿到了。
sign分析,回到刚刚那个传递sign参数的那个函数

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

字符串最后拼接了一个key后在进行md5加密,
hook一下md5这个函数

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

很明显,拼接除了sign参数其余全部在添加一个key=sdlkjsdljf0j2fsjk 的最终字符串在进行md5加密。
这样sign与参数加密都分析完了。
再使用java模拟加密过程,反写解密就OK了。

package APP;//import android.util.Base64;  
import java.net.URLEncoder;  
import java.nio.charset.StandardCharsets;  
import java.security.MessageDigest;  
import java.util.*;  
import java.util.stream.Collectors;  
import javax.crypto.Cipher;  
import javax.crypto.SecretKey;  
import javax.crypto.SecretKeyFactory;  
import javax.crypto.spec.DESKeySpec;  
import javax.crypto.spec.IvParameterSpec;  
  
/* loaded from: classes.dex */  
public class DuDu {  
    Cipher deCipher;  
    Cipher enCipher;  
  
    public DuDu(String key, String iv) throws Exception {  
        if (key == null) {  
            throw new NullPointerException("Parameter is null!");  
        }  
        InitCipher(key.getBytes(), iv.getBytes());  
    }  
  
    private void InitCipher(byte[] secKey, byte[] secIv) throws Exception {  
        MessageDigest md = MessageDigest.getInstance("MD5");  
        md.update(secKey);  
        DESKeySpec dsk = new DESKeySpec(md.digest());  
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
        SecretKey key = keyFactory.generateSecret(dsk);  
        IvParameterSpec iv = new IvParameterSpec(secIv);  
        this.enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");  
        this.deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");  
        this.enCipher.init(1, key, iv);  
        this.deCipher.init(2, key, iv);  
    }  
  
    public String encrypt64(byte[] data) throws Exception {  
        byte[] encryptedBytes = this.enCipher.doFinal(data);  
        return Base64.getEncoder().encodeToString(encryptedBytes);  
    }  
  
    public byte[] decrypt64(String data) throws Exception {  
        return this.deCipher.doFinal(Base64.getDecoder().decode(data));  
    }  
  
    public String sign(String data) throws Exception {  
        String append = "sdlkjsdljf0j2fsjk";  
  
        // 将 JSON 字符串转换为 Map        Map<String, String> paramMap = Arrays.stream(data.replace("{", "").replace("}", "").split(","))  
                .map(pair -> pair.split(":"))  
                .collect(Collectors.toMap(  
                        kv -> kv[0].trim().replace("\"", ""),  
                        kv -> kv[1].trim().replace("\"", "")  
                ));  
  
        // 对 Map 中的键进行排序  
        List<String> keys = new ArrayList<>(paramMap.keySet());  
        Collections.sort(keys);  
  
        // 拼接参数字符串  
        String paramStr = keys.stream()  
                .filter(key -> !"sign".equals(key))  
                .map(key -> {  
                    return key + "=" + URLEncoder.encode(paramMap.get(key), StandardCharsets.UTF_8);  
                })  
                .collect(Collectors.joining("&")) + "&key=" + URLEncoder.encode(append, StandardCharsets.UTF_8);  
  
        System.out.println("sign明文:" + paramStr);  
        // 对拼接后的参数字符串进行 MD5 加密  
        MessageDigest md = MessageDigest.getInstance("MD5");  
        byte[] digest = md.digest(paramStr.getBytes(StandardCharsets.UTF_8));  
        StringBuilder hexString = new StringBuilder();  
  
        for (byte b : digest) {  
            String hex = Integer.toHexString(0xFF & b);  
            if (hex.length() == 1) {  
                hexString.append('0');  
            }  
            hexString.append(hex);  
        }  
  
        return hexString.toString().toUpperCase();  
    }  
    public static void main(String[] args) throws Exception {  
        DuDu du = new DuDu("65102933","32028092");  
          
        String enc = "";  
        String decryptedString = new String(du.decrypt64(enc));  
        System.out.println("明文:" + decryptedString);  
  
        System.out.println("sign密文:" + du.sign(decryptedString));  
    }  
}
Frida hook脚本
function duduhook() {
    Java.perform(function () {
        let RequestUtil = Java.use("com.xxx.xxx.http.RequestUtil");
        RequestUtil["encodeDesMap"].overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function (data, desKey, desIV) {
            console.log("**********获取DES明文**********");
            console.log(`参数明文----> ${data}, desKey= ${desKey}, desIV= ${desIV}`);
            let result = this["encodeDesMap"](data, desKey, desIV);
            console.log(`参数加密结果----> ${result}`);
            return result;
        };

        let Utils = Java.use("com.xxx.xxx.util.Utils");
        Utils["md5"].implementation = function (string) {
            console.log("**********获取SIGN明文**********");
            console.log(`SIGN明文----> ${string}`);
            let result = this["md5"](string);
            console.log(`MD5加密结果----> ${result}`);
            return result;
        };


        let RequestUtil1 = Java.use("com.xxx.xxx.http.RequestUtil");
        RequestUtil1["paraMap"].overload('java.util.Map', 'java.lang.String', 'java.lang.String').implementation = function (addMap, append, sign) {
            console.log(`RequestUtil.paraMap is called: addMap=${addMap}, append=${append}, sign=${sign}`);
            let result = this["paraMap"](addMap, append, sign);
            console.log(`RequestUtil.paraMap result=${result}`);
            return result;
        };
    });
}


setImmediate(duduhook);
效果如下:

安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

0x03 工具下载

链接:https://pan.quark.cn/s/b7719b87af8f

原文始发于微信公众号(进击的HACK):安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月3日09:18:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本http://cn-sec.com/archives/3121423.html

发表评论

匿名网友 填写信息