十二. 一步步破解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 + "\r\n");
        } 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();
        }
    }
}












免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM