编写脚本批量还愿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 dex, String findClassSignature) {
        List<String> listClassSignatures = 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 dex, int classIndex, String findMethodSignature) {
        DexClass dexClass = dex.getClass(classIndex);
        DexClassData dexClassData = dexClass.getData();
        DexMethodData[] dexMethods = dexClassData.getDirectMethods();
        for (int i = 0; i < dexMethods.length; i++) {
            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<Integer> methodReferences = 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<IElement> subElements = decompileMethodTree.getSubElements();
            replaceDecodeMethod(subElements, decompileMethodTree);
        }
    }
    @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 = (JavaView) ui.getView(View.Type.JAVA);
        Dex dex = jebInstance.getDex();
        while (true) {
            int classIndex = findClass(dex, DecodeClassSignature);
            if (classIndex == -1) {
                break;
            }
            int methodIndex = findMethod(dex, classIndex, DecodeMethodSignature);
            if (methodIndex == -1) {
                break;
            }
            
            traverseReferences(dex,methodIndex);
            
            // 刷新UI
            javaView.refresh();
            break;
        }
        // 关闭文件
        close();
    }
    
    private void replaceDecodeMethod(List<IElement> elements, IElement parentEle) {
        for (IElement element : elements) {
            
            if (!(element instanceof Call)) {
                // 不是方法
                List<IElement> subElements = element.getSubElements();
                replaceDecodeMethod(subElements, element);
                continue;
            }
            
            Call call = (Call) element;
            Method method = call.getMethod();
            if (!method.getSignature().equals(DecodeMethodSignature)) {
                // 不是指定函数签名
                List<IElement> subElements = element.getSubElements();
                replaceDecodeMethod(subElements, element);
                continue;
            }
            
            
            analyzeArguments(call,parentEle,element);
            
        }
    }
    
    // 解析引用函数的参数
    private void analyzeArguments(Call call,IElement parentEle,IElement element) {
        try {
            // 拿到函数的参数
            List<IExpression> arguments = call.getArguments();
            
            // 获取第一个参数元素
            NewArray arg1 = (NewArray) arguments.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(1) instanceof Constant) {
                decFlag = ((Constant) (arguments.get(1))).getInt();
            } else {
                decFlag = 4;
            }
            
            // 初始化加密字节数组
            for (i = 0; i < size; i++) {
                enStrBytes[i] = ((Constant) encBL.get(i)).getByte();
            }
            
            // 设置encode
            encode = ((Constant) (arguments.get(2))).getInt();
            
            String decString = do_dec(enStrBytes,decFlag,encode);
            logWrite("解密后字符串: " + decString);
            // mJebInstance.print("解密后字符串: " + decString);
            
            // 替换原来的表达式
            parentEle.replaceSubElement(element, mBuilder.buildString(decString));
        } catch (Exception e) {
            mJebInstance.print(e.toString());
        }
    }
    
    // 根据情况解密字符串
    private String do_dec(byte[] enStrBytes, int decFlag, int encode) {
        String dec = "";
        
        while (true) {
            if (decFlag != 4) {
                dec = decString(enStrBytes, decFlag, encode);
                break;
            }                   
            
            // 穷举可能存在的情况 0 1 2
            dec = decString(enStrBytes, 2, encode);
            if (!isStr(dec)) {
                dec = decString(enStrBytes, 1, encode);
            }
            
            if (!isStr(dec)) {
                dec = decString(enStrBytes, 0, encode);
            }
            break;
        }
        return dec;
    }
    
    // 判断字符串是否是一个合理的字符串
    private boolean isStr(String s) {
        int len = s.length() > 3 ? 3 : s.length();
        String str = s.substring(0, len);
        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[] enStrBytes, int decFlag, int 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 jebInstance, String 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();
        }
    }
}







十二. 一步步破解JEB 2.0demo版二的更多相关文章

  1. 十一. 一步步破解JEB 2.0demo版一

    字符串解密算法还愿 jeb.jar为核心功能,所以主要分析这个 1. jar转dex在使用jeb分析 Android\sdk\build-tools\23.0.3 dx.bat --dex --out ...

  2. VB 共享软件防破解设计技术初探(二)

    VB 共享软件防破解设计技术初探(二) ×××××××××××××××××××××××××××××××××××××××××××××× 其他文章快速链接: VB 共享软件防破解设计技术初探(一)http ...

  3. 2017-2018-1 20155219《信息安全技术》实验二——Windows口令破解

    2017-2018-1 20155320<信息安全技术>实验二--Windows口令破解 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 实验 ...

  4. 2017-2018-1 20155312《信息安全技术》实验二——Windows口令破解实验报告

    2017-2018-1 20155312<信息安全技术>实验二--Windows口令破解实验报告 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破 ...

  5. 2017-2018-1 201552326《信息安全技术》实验二——Windows口令破解

    2017-2018-1 201552326<信息安全技术>实验二--Windows口令破解 姓名:刘美岑 学号:20155326 班级:1553班 日期:10.24 一.实验环境 操作系统 ...

  6. java应用破解之破解 jeb mips 2.3.3

    前言 jeb 的新版支持 mips的反编译 ,于是去官网申请一个试用版,试用版的限制还是比较多的,比如 使用时间验证,没法复制粘贴 等,于是想尝试看看能否破解,同时填了 java破解 这个坑. 修改版 ...

  7. 《信息安全技术》实验二 Windows口令破解

    <信息安全技术>实验二 Windows口令破解 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 实验环境 实验机Windows Server ...

  8. 2017-2018-1 《信息安全技术》实验二——Windows口令破解

    2017-2018-1 <信息安全技术>实验二--Windows口令破解 所用工具 系统:能勾起我回忆的Windows 2003 工具:LC5.SuperDic Windows口令破解 口 ...

  9. 20155231 信息安全技术概论实验二 Windows口令破解

    20155231 信息安全技术概论实验二 Windows口令破解 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 实验人数 每组一人 系统环境 windo ...

随机推荐

  1. 为WebService指定线程池

    通过阅读WebService发布过程的源代码,可以配置自定义的线程池 package org.zln.ws.server;import com.sun.xml.internal.ws.api.Bind ...

  2. codevs 2894 保留小数

    时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 给你一个实数,小数点后不超过50位,请你保留到小数点后n位(四舍五入!!!) 输 ...

  3. 【C#】【Thread】Barrier任务并行

    Barrier  是一个对象,它可以在并行操作中的所有任务都达到相应的关卡之前,阻止各个任务继续执行. 如果并行操作是分阶段执行的,并且每一阶段要求各任务之间进行同步,则可以使用该对象. --MSDN ...

  4. JS数组去重比较

    数组去重复是一个常见的需求,我们暂时考虑同类型的数组去重复.主要是理清思路和考虑执行性能. for循环删除后面重复的 var uniqueFor = function(arr) { for (var ...

  5. 种子填充算法描述及C++代码实现

    项目需要看了种子填充算法,改进了算法主要去除面积小的部分.种子填充算法分为两种,简单的和基于扫描线的方法,简单的算法如下描述(笔者针对的是二值图像): (1)从上到下,从左到有,依次扫描每个像素: ( ...

  6. 有border和没有border是两回事

    id="box"设立border的话,里边的p样式为display:block;margin-top:20px; 如果你把margin-top的值不断添加的话,会显示为距borde ...

  7. 【JavaScript】图片上传预览

    上传文件实时显示[一张图片]: 个人理解:给img的src传值:这个值就是input[type='file']的value: 不过你要判断浏览器类型[很多]:IE6.0,IE7/8/9,Fixfox7 ...

  8. Windows 10一周年更新正式版官方ISO镜像(1607)

    微软已经开始推送Win10一周年更新正式版系统,按照此前预告微软官方网站也同步推出了Win10一周年更新正式版ISO官方镜像下载,版本已经升级到最新的1607,也就是Win10 Build 1607, ...

  9. Java的多线程机制系列:(一)总述及基础概念

    前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...

  10. js中遍历删除数组中的项(项目中遇到的问题解决)

    代码如下: for (var key=0;key<$scope.pageContent.messages.length;key++){ if($scope.pageContent.message ...