zoukankan      html  css  js  c++  java
  • 十二. 一步步破解JEB 2.0demo版二

    编写脚本批量还愿JEB 加密字符串

    解密完后效果如下:


    脚本源码:
    https://github.com/bingghost/JebPlugins

    思路:
    下面的该封装的基本都封装了,过程如下:
    1.先遍历类定位到指定的类,
    2.然后遍历该类的所有方法定位到解密函数,对其做交叉引用
       得到所有引用该解密函数的地方
    3. 对每一个引用函数做语法解析AST,拿到所有的语法元素信息,同时得到加密的byte数组信息
    4. 调用解密函数解密得到字符串
    5. 调用jebview接口,使用解密后的字符串替换byte数组,同时刷新界面

    编写代码如下:
    import java.io.*;
    import java.util.List;
    import jeb.api.IScript;
    import jeb.api.JebInstance;
    import jeb.api.ui.*;
    import jeb.api.ast.*;
    import jeb.api.dex.Dex;
    import jeb.api.dex.DexClass;
    import jeb.api.dex.DexClassData;
    import jeb.api.dex.DexMethod;
    import jeb.api.dex.DexMethodData;
    public class Hello implements IScript {
        private final static String DecodeMethodSignature = "Lcom/pnfsoftware/jebglobal/Si;->ob([BII)Ljava/lang/String;";
        private final static String DecodeClassSignature = "Lcom/pnfsoftware/jebglobal/Si;";
        private JebInstance mJebInstance = null;
        private Constant.Builder mBuilder = null;
        private static File logFile;
        private static BufferedWriter writer;
        /**
         * 功能: 遍历所有的类 找到指定的类
         * 
         * @return 指定类的dex索引, 没有找到返回-1
         */
        @SuppressWarnings("unchecked")
        private int findClass(Dex dexString findClassSignature) {
            List<StringlistClassSignatures = dex.getClassSignatures(false);
            int index = 0;
            for (String classSignatures : listClassSignatures) {
                if (classSignatures.equals(findClassSignature)) {
                    mJebInstance.print("find:" + classSignatures);
                    return index;
                }
                index++;
            }
            return -1;
        }
        private int findMethod(Dex dexint classIndexString findMethodSignature) {
            DexClass dexClass = dex.getClass(classIndex);
            DexClassData dexClassData = dexClass.getData();
            DexMethodData[] dexMethods = dexClassData.getDirectMethods();
            for (int i = 0i < dexMethods.lengthi++) {
                int methodIndex = dexMethods[i].getMethodIndex();
                DexMethod dexMethod = dex.getMethod(methodIndex);
                String methodSignature = dexMethod.getSignature(true);
                if (methodSignature.equals(findMethodSignature)) {
                    mJebInstance.print("find:" + methodSignature);
                    return methodIndex;
                }
            }
            return -1;
        }
        
        /***
         * 功能: 遍历指定函数的应用方法
         * @param dex
         * @param methodIndex
         */
        @SuppressWarnings("unchecked")
        private void traverseReferences(Dex dex,int methodIndex) {
            List<IntegermethodReferences = dex.getMethodReferences(methodIndex);
            mJebInstance.print("引用数量:" + methodReferences.size());
            for (Integer refIndex : methodReferences) {
                DexMethod refDexMethod = dex.getMethod(refIndex);
                mJebInstance.print("引用的方法:" + refDexMethod.getSignature(true));
                // 找到AST中对应的Method
                mJebInstance.decompileMethod(refDexMethod.getSignature(true));
                Method decompileMethodTree = mJebInstance.getDecompiledMethodTree(refDexMethod.getSignature(true));
                // 拿到语句块,遍历所有语句
                List<IElementsubElements = decompileMethodTree.getSubElements();
                replaceDecodeMethod(subElementsdecompileMethodTree);
            }
        }
        @SuppressWarnings("unchecked")
        @Override
        public void run(JebInstance jebInstance) {
            // 初始化相关信息
            jebInstance.print("start decode strings plugin");
            init(jebInstance"D:\log.txt");
            mBuilder = new Constant.Builder(jebInstance);
            JebUI ui = jebInstance.getUI();
            JavaView javaView = (JavaViewui.getView(View.Type.JAVA);
            Dex dex = jebInstance.getDex();
            while (true) {
                int classIndex = findClass(dexDecodeClassSignature);
                if (classIndex == -1) {
                    break;
                }
                int methodIndex = findMethod(dexclassIndexDecodeMethodSignature);
                if (methodIndex == -1) {
                    break;
                }
                
                traverseReferences(dex,methodIndex);
                
                // 刷新UI
                javaView.refresh();
                break;
            }
            // 关闭文件
            close();
        }
        
        private void replaceDecodeMethod(List<IElementelementsIElement parentEle) {
            for (IElement element : elements) {
                
                if (!(element instanceof Call)) {
                    // 不是方法
                    List<IElementsubElements = element.getSubElements();
                    replaceDecodeMethod(subElementselement);
                    continue;
                }
                
                Call call = (Callelement;
                Method method = call.getMethod();
                if (!method.getSignature().equals(DecodeMethodSignature)) {
                    // 不是指定函数签名
                    List<IElementsubElements = element.getSubElements();
                    replaceDecodeMethod(subElementselement);
                    continue;
                }
                
                
                analyzeArguments(call,parentEle,element);
                
            }
        }
        
        // 解析引用函数的参数
        private void analyzeArguments(Call call,IElement parentEle,IElement element) {
            try {
                // 拿到函数的参数
                List<IExpressionarguments = call.getArguments();
                
                // 获取第一个参数元素
                NewArray arg1 = (NewArrayarguments.get(0);
                List encBL = arg1.getInitialValues();
                if (encBL == null) {
                    return;
                }
                
                int size = encBL.size();
                byte[] enStrBytes = new byte[size];
                int decFlag;
                int encode;
                int i = 0;
                
                // 设置Flags 有的地方可能是变量形式的参数
                if (arguments.get(1instanceof Constant) {
                    decFlag = ((Constant) (arguments.get(1))).getInt();
                } else {
                    decFlag = 4;
                }
                
                // 初始化加密字节数组
                for (i = 0i < sizei++) {
                    enStrBytes[i] = ((ConstantencBL.get(i)).getByte();
                }
                
                // 设置encode
                encode = ((Constant) (arguments.get(2))).getInt();
                
                String decString = do_dec(enStrBytes,decFlag,encode);
                logWrite("解密后字符串: " + decString);
                // mJebInstance.print("解密后字符串: " + decString);
                
                // 替换原来的表达式
                parentEle.replaceSubElement(elementmBuilder.buildString(decString));
            } catch (Exception e) {
                mJebInstance.print(e.toString());
            }
        }
        
        // 根据情况解密字符串
        private String do_dec(byte[] enStrBytesint decFlagint encode) {
            String dec = "";
            
            while (true) {
                if (decFlag != 4) {
                    dec = decString(enStrBytesdecFlagencode);
                    break;
                }                   
                
                // 穷举可能存在的情况 0 1 2
                dec = decString(enStrBytes2encode);
                if (!isStr(dec)) {
                    dec = decString(enStrBytes1encode);
                }
                
                if (!isStr(dec)) {
                    dec = decString(enStrBytes0encode);
                }
                break;
            }
            return dec;
        }
        
        // 判断字符串是否是一个合理的字符串
        private boolean isStr(String s) {
            int len = s.length() > 3 ? 3 : s.length();
            String str = s.substring(0len);
            if (str.matches("[a-zA-Z0-9_u4e00-u9fa5]*")) {
                return true;
            }
            return false;
        }
        
        private String setString(byte[] bytes_str) {
            String new_str;
            
            try {
                new_str = new String(bytes_str"UTF-8");
            }
            catch(Exception e) {
                new_str = new String(bytes_str);
            }
            return new_str;
        }
        
        // 解密字符串
        public String decString(byte[] enStrBytesint decFlagint encode) {
            byte[] decstrArray;
            int enstrLen;
            if(enStrBytes == null) {
                return "decode error";
            }
            
            if (decFlag == 0 || enStrBytes.length == 0) {
                return setString(enStrBytes);
            }
            
            if(decFlag == 1) {
                enstrLen = enStrBytes.length;
                decstrArray = new byte[enstrLen];
                byte bEncode = ((byte)encode);
                
                for (int i = 0;i < enstrLen;i++) {
                    decstrArray[i] = ((byte)(bEncode ^ enStrBytes[i]));
                    bEncode = decstrArray[i];
                }
                return setString(decstrArray);
            }
            
            if(decFlag == 2) {
                enstrLen = enStrBytes.length;
                decstrArray = new byte[enstrLen];
                String coprightString = "Copyright (c) 1993, 2015, Oracle and/or its affiliates. All rights reserved. ";
                int index = 0;
                for (int i = 0;i < enstrLen;i++) {
                    decstrArray[i] = ((byte)(enStrBytes[i] ^ (((byte)coprightString.charAt(index)))));
                    index = (index + 1) % coprightString.length();
                }
                return setString(decstrArray);
            }
            
            return "decode error";
        }
        
        public void logWrite(String log) {
            try {
                writer.write(log + " ");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public void init(JebInstance jebInstanceString logPath) {
            mJebInstance = jebInstance;
            logFile = new File(logPath);
            try {
                writer = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(logFile), "utf-8"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public void close() {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }











  • 相关阅读:
    NABCD项目分析
    第七周学习进度
    第六周学习进度
    构建之法阅读笔记03
    [算法] 求x的n次方的一种for循环实现
    [算法]分解质因数
    通过索引操作数组
    [swift入门] 数据类型
    二叉排序树 常用函数小结
    剑指 Offer 54. 二叉搜索树的第k大节点 做题小结
  • 原文地址:https://www.cnblogs.com/bingghost/p/5819735.html
Copyright © 2011-2022 走看看