Xposed实战:Java层常用加密通杀模块

  最近在学xposed,照着各种案例和API写了个Hook无混淆加壳下的Java层常用加密算法的xposed模块。我的硬盘快撑不住了,随时可能挂掉,我已经开始备份各种代码准备等他炸了换硬盘了,所以在这留个xposed模块的代码,不想努力付之东流~~~

  原理比较简单,就是单纯的去Hook JDK自带的加密方法,把结果和调用栈通过log打印出来。对非标准加密算法无效,加壳的也一样。主要覆盖了:

  • 消息摘要算法:MD5/SHA/HMAC算法的明文、密钥和结果

  • 对称加密:AES/DES/3DES算法的明文、密钥、IV和结果

  • 非对称加密:RSA算法的明文、公钥和结果

  • 数字签名算法:SHA256withRSA等签名算法的明文、密钥、结果

      代码仅供参考:

package com.xp.killall;

import android.util.Base64;
import android.util.Log;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.Signature;

import javax.crypto.Cipher;
import javax.crypto.Mac;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

public class Hook implements IXposedHookLoadPackage {
    public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
        Log.d("KillAll", "Kill All Encrypt start Hooking...");
        // 消息摘要算法 MD5 SHA update
        XposedBridge.hookAllMethods(XposedHelpers.findClass("java.security.MessageDigest", lpparam.classLoader),
                "update",
                new XC_MethodHook() {
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        MessageDigest md = (MessageDigest) param.thisObject;
                        String Algorithm = md.getAlgorithm();
                        byte[] params = (byte[]) param.args[0];
                        String data = new String(params);
                        String dataHex = byteToHexString(params);
                        String dataB64 = Base64.encodeToString(params, 0);
                        Log.d("KillAll", Algorithm + " updatedata:" + data);
                        Log.d("KillAll", Algorithm + " updatedataHex:" + dataHex);
                        Log.d("KillAll", Algorithm + " updatedataB64:" + dataB64);
                        Log.d("KillAll", "================================================");
                    }
                });
        // 消息摘要算法digest
        XposedBridge.hookAllMethods(XposedHelpers.findClass("java.security.MessageDigest", lpparam.classLoader),
                "digest",
                new XC_MethodHook() {
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        MessageDigest md = (MessageDigest) param.thisObject;
                        String Algorithm = md.getAlgorithm();
                        if (param.args.length >= 1) {
                            byte[] params = (byte[]) param.args[0];
                            String data = new String(params);
                            String dataHex = byteToHexString(params);
                            String dataB64 = Base64.encodeToString(params, 0);
                            Log.d("KillAll", Algorithm + " digestdata:" + data);
                            Log.d("KillAll", Algorithm + " digestdataHex:" + dataHex);
                            Log.d("KillAll", Algorithm + " digestdataB64:" + dataB64);
                        }
                        byte[] res = (byte[]) param.getResult();
                        String resHex = byteToHexString(res);
                        String resB64 = Base64.encodeToString(res, 0);
                        Log.d("KillAll", Algorithm + " digestResultHex:" + resHex);
                        Log.d("KillAll", Algorithm + " digestResultB64:" + resB64);
                        Log.d("KillAll", "================================================");
                    }
                });
        //MAC
        XposedBridge.hookAllMethods(XposedHelpers.findClass("javax.crypto.Mac", lpparam.classLoader),
                "doFinal",
                new XC_MethodHook() {
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        if (param.args.length == 2) return;
                        Mac mac = (Mac) param.thisObject;
                        String Algorithm = mac.getAlgorithm();
                        if (param.args.length == 1) {
                            byte[] params = (byte[]) param.args[0];
                            String data = new String(params);
                            String dataHex = byteToHexString(params);
                            String dataB64 = Base64.encodeToString(params, 0);
                            Log.d("KillAll", Algorithm + " data:" + data);
                            Log.d("KillAll", Algorithm + " dataHex:" + dataHex);
                            Log.d("KillAll", Algorithm + " dataB64:" + dataB64);
                            Log.d("KillAll", "================================================");
                        }
                        byte[] res = (byte[]) param.getResult();
                        String resHex = byteToHexString(res);
                        String resB64 = Base64.encodeToString(res, 0);
                        Log.d("KillAll", Algorithm + " resultHex:" + resHex);
                        Log.d("KillAll", Algorithm + " resultB64:" + resB64);
                        Log.d("KillAll", "================================================");
                    }
                });
        //MAC
        XposedBridge.hookAllMethods(XposedHelpers.findClass("javax.crypto.Mac", lpparam.classLoader),
                "update",
                new XC_MethodHook() {
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        Mac mac = (Mac) param.thisObject;
                        String Algorithm = mac.getAlgorithm();
                        byte[] params = (byte[]) param.args[0];
                        String data = new String(params);
                        String dataHex = byteToHexString(params);
                        String dataB64 = Base64.encodeToString(params, 0);
                        Log.d("KillAll", Algorithm + " updatedata:" + data);
                        Log.d("KillAll", Algorithm + " updatedataHex:" + dataHex);
                        Log.d("KillAll", Algorithm + " updatedataB64:" + dataB64);
                        Log.d("KillAll", "================================================");
                    }
                });

        // DES 3DES AES MAC
        // HOOK密钥
        XposedBridge.hookAllConstructors(XposedHelpers.findClass("javax.crypto.spec.SecretKeySpec", lpparam.classLoader),
                new XC_MethodHook() {
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        byte[] secretKey = (byte[]) param.args[0];
                        int offset = 0;
                        int size = 0;
                        String Algorithm = null;
                        if (param.args.length != 2) {
                            offset = ((Integer) param.args[1]).intValue();
                            size = ((Integer) param.args[2]).intValue();
                            Algorithm = (String) param.args[3];
                        } else {
                            size = secretKey.length;
                            Algorithm = (String) param.args[1];
                        }
                        byte[] keybyte = new byte[size];
                        System.arraycopy(secretKey, offset, keybyte, 0, size);
                        String keyHex = byteToHexString(keybyte);
                        String keyB64 = Base64.encodeToString(keybyte, 0);
                        Log.d("KillAll", Algorithm + " SecretKey:" + new String(keybyte));
                        Log.d("KillAll", Algorithm + " SecretKeyHex:" + keyHex);
                        Log.d("KillAll", Algorithm + " SecretKeyB64:" + keyB64);
                        Log.d("KillAll", "================================================");
                    }
                });

        // Hook AES DES iv向量
        XposedBridge.hookAllConstructors(XposedHelpers.findClass("javax.crypto.spec.IvParameterSpec",
                lpparam.classLoader),
                new XC_MethodHook() {
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        byte[] ivParameter = ((byte[]) param.args[0]);
                        int offset = 0;
                        int size = 0;
                        if (param.args.length != 1) {
                            offset = ((Integer) param.args[1]).intValue();
                            size = ((Integer) param.args[2]).intValue();
                        } else {
                            size = ivParameter.length;
                        }
                        byte[] ivbyte = new byte[size];
                        String ivHex = byteToHexString(ivbyte);
                        String ivB64 = Base64.encodeToString(ivbyte, 0);
                        Log.d("KillAll", "ivParameter:" + new String(ivbyte));
                        Log.d("KillAll", "ivParameterHex:" + ivHex);
                        Log.d("KillAll", "ivParameterB64:" + ivB64);
                        Log.d("KillAll", "================================================");
                    }
                });

        // Hook Cipher(RSA,DES,3DES,AES)
        XposedBridge.hookAllMethods(XposedHelpers.findClass("javax.crypto.Cipher",
                lpparam.classLoader),
                "doFinal",
                new XC_MethodHook() {
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        if (!(param.args.length == 0 || param.args.length == 1 || param.args.length == 3)) return;
                        // param.args[0].getClass().getName(); 获取参数的类名
                        Cipher cip = (Cipher) param.thisObject;
                        String Algorithm = cip.getAlgorithm();
                        byte[] dataAll = (byte[]) param.args[0];
                        if (param.args.length == 3) {
                            int offset = ((Integer) param.args[1]).intValue();
                            int size = ((Integer) param.args[2]).intValue();
                            byte[] databyte = new byte[size];
                            System.arraycopy(dataAll, offset, databyte, 0, size);
                            String data = new String(databyte);
                            String dataHex = byteToHexString(databyte);
                            String dataB64 = Base64.encodeToString(databyte, 0);
                            Log.d("KillAll", Algorithm + " data:" + data);
                            Log.d("KillAll", Algorithm  + " dataHex:" + dataHex);
                            Log.d("KillAll", Algorithm + " idataB64:" + dataB64);
                            Log.d("KillAll", "================================================");
                        } else if (param.args.length == 1) {
                            String data = new String(dataAll);
                            String dataHex = byteToHexString(dataAll);
                            String dataB64 = Base64.encodeToString(dataAll, 0);
                            Log.d("KillAll", Algorithm + " data:" + data);
                            Log.d("KillAll", Algorithm + " dataHex:" + dataHex);
                            Log.d("KillAll", Algorithm + " idataB64:" + dataB64);
                            Log.d("KillAll", "================================================");
                        }

                        byte[] res = ((byte[]) param.getResult());
                        String resHex = byteToHexString(res);
                        String resB64 = Base64.encodeToString(res, 0);
                        Log.d("KillAll", Algorithm + " resDataHex:" + resHex);
                        Log.d("KillAll", Algorithm + " resDataB64:" + resB64);
                        Log.d("KillAll", "================================================");
                    }
                });

        // Hook update(RSA,DES,3DES,AES)
        XposedBridge.hookAllMethods(XposedHelpers.findClass("javax.crypto.Cipher", lpparam.classLoader),
                "update",
                new XC_MethodHook() {
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        Cipher cipher = (Cipher) param.thisObject;
                        String Algorithm = cipher.getAlgorithm();
                        byte[] params = (byte[]) param.args[0];
                        String data = new String(params);
                        String dataHex = byteToHexString(params);
                        String dataB64 = Base64.encodeToString(params, 0);
                        Log.d("KillAll", Algorithm + " updatedata:" + data);
                        Log.d("KillAll", Algorithm + " updatedataHex:" + dataHex);
                        Log.d("KillAll", Algorithm + " updatedataB64:" + dataB64);
                        Log.d("KillAll", "================================================");
                    }
                });

        //Hook RSA密钥 base64形式
        XposedBridge.hookAllConstructors(XposedHelpers.findClass("java.security.spec.X509EncodedKeySpec",
                lpparam.classLoader),
                new XC_MethodHook() {
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        byte[] keybyte = ((byte[]) param.args[0]);
                        String ivB64 = Base64.encodeToString(keybyte, 0);
                        Log.d("KillAll", "(RSA)X509KeyB64:" + ivB64);
                        Log.d("KillAll", "================================================");
                    }
                });

        //Hook RSA密钥 hex形式
        XposedBridge.hookAllConstructors(XposedHelpers.findClass("java.security.spec.RSAPublicKeySpec",
                lpparam.classLoader),
                new XC_MethodHook() {
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        String n = ((BigInteger) param.args[0]).toString(16);
                        String e = ((BigInteger) param.args[1]).toString(16);
                        Log.d("KillAll", "RSAKeyHex:" + n + "||" + e);
                        Log.d("KillAll", "================================================");
                    }
                });

        // Hook数字签名算法 SHA1withDSA SHA1withRSA SHA256withRSA 结果
        XposedBridge.hookAllMethods(XposedHelpers.findClass("java.security.Signature", lpparam.classLoader),
                "sign",
                new XC_MethodHook() {
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        if (param.args.length == 3) return;
                        Signature signature = (Signature) param.thisObject;
                        String Algorithm = signature.getAlgorithm();
                        byte[] res = (byte[]) param.getResult();
                        String resHex = byteToHexString(res);
                        String resB64 = Base64.encodeToString(res, 0);
                        Log.d("KillAll", Algorithm + " resultHex:" + resHex);
                        Log.d("KillAll", Algorithm + " resultB64:" + resB64);
                        Log.d("KillAll", "================================================");
                    }
                });

        // Hook数字签名算法 SHA1withDSA SHA1withRSA SHA256withRSA 明文
        XposedBridge.hookAllMethods(XposedHelpers.findClass("java.security.Signature", lpparam.classLoader),
                "update",
                new XC_MethodHook() {
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.e("KillAll", "Stack:", new Throwable("stack dump"));
                        Signature signature = (Signature) param.thisObject;
                        String Algorithm = signature.getAlgorithm();

                        byte[] params = ((byte[]) param.args[0]);
                        int offset = 0;
                        int size = 0;
                        if (param.args.length != 1) {
                            offset = ((Integer) param.args[1]).intValue();
                            size = ((Integer) param.args[2]).intValue();
                        } else {
                            size = params.length;
                        }
                        byte[] databyte = new byte[size];
                        System.arraycopy(params, offset, databyte, 0, size);
                        String data = new String(databyte);
                        String dataHex = byteToHexString(databyte);
                        String dataB64 = Base64.encodeToString(databyte, 0);
                        Log.d("KillAll", Algorithm + " updatedata:" + data);
                        Log.d("KillAll", Algorithm + " updatedataHex:" + dataHex);
                        Log.d("KillAll", Algorithm + " updatedataB64:" + dataB64);
                        Log.d("KillAll", "================================================");
                    }
                });

    }

    public static String byteToHexString(byte[] by) {
        StringBuffer sb = new StringBuffer();
        for (byte k : by) {
            int j = k;
            if (k < 0) {
                j = k + 256;
            }
            if (j < 16) {
                sb.append("0");
            }
            sb.append(Integer.toHexString(j));
        }
        return sb.toString();
    }
}

  使用的话需要开启DDMS,筛选标签为KillAll的log,然后打开App触发即可。

  我就随便截一段了,最上面就是算法的名称:MD5,updatedata是传入的明文值,下面也会输出明文的Hex及Base64形式,红的是调用堆栈。
  紧接着下面是加密的结果,按不同算法会输出不同的值,这里MD5输出的是hex和base64两种形式。

  成品:

链接:https://pan.baidu.com/s/1TxovT7CNupslFkFMwztUng
提取码:umiw
复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V4的分享

声明

本文分析过程仅供学习,并无任何个人以及商业或其他用途,如因参考文章造成违法行为本人概不负责。如有不慎侵权,请联系我删除。

推荐阅读更多精彩内容