0x01 前言
有时候在对APP抓包的时候,经常会遇到参数加密,app也不像web端一样,可以直接打断点进行调试,找到加密方法, 在app没有加壳的情况下,我们可以反编译找加密点,或者是动态调试,这里使用反编译的方法。
0x02 正文
在登陆处点击登录,然后抓包,具体环境配置教程以及抓包教程可以看前两篇文章,可以看到账号密码被加密了,这时候如果apk没有加壳的话,我们可以使用JADX进行反编译
因为抓包的时候,路由是/user/login,我们反编译apk后,直接搜索这个
基本可以确定就是从这里发起网络请求
跟进addRequestMap方法分析
这一看逻辑就清晰了
先添加一个时间戳,在对sign进行加密后在调用encodeDesMap进行加密
最后put到请求中
在分析encodeDesMap
有KEY和IV,不是AES就是DES加密
encrypt64
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;
};
与抓包结果一样,这样明文就拿到了。
sign分析,回到刚刚那个传递sign参数的那个函数
字符串最后拼接了一个key后在进行md5加密,
hook一下md5这个函数
很明显,拼接除了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)); } }
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);
0x03 工具下载
链接:https://pan.quark.cn/s/b7719b87af8f
原文始发于微信公众号(进击的HACK):安卓渗透第三弹-Apk反编译分析加密编写自动化解密脚本
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论