编写脚本批量还愿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. VMware三种上网模型

    今天捣鼓了一会虚拟机,对上网方式又学习了一遍,之前摆弄过,现在又捡起来了,主要自己整理一下,方面后面复习.主要有三种网络模型:桥接.仅主机(Host-Only).NAT.自己亲测了这三种方式,都可以上 ...

  2. 了解 JS 原型

    原型概念 当创建了一个函数时,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象.在默认情况下,所有原型对象都会自动获得一个constructor 的属性 这 ...

  3. yii获取当前url和域名

    <?php //当前域名 echo Yii::app()->request->hostInfo; //除域名外的URL echo Yii::app()->request-> ...

  4. spring mvc 项目聚合

    创建一个maven 项目当父项目 创建时选择默认就可以 创建完成后 修改 pom.xml文件  把 packaging 的war改为pom <modelVersion>4.0.0</ ...

  5. 理解C# 4 dynamic(2) – ExpandoObject的使用

    ExpandoObject的使用非常简单,很容易入手.上一篇里面已经有详细的介绍了,可以看这里(理解C# 4 dynamic(1) - var, object, dynamic的区别以及dynamic ...

  6. 【BZOJ-2476】战场的数目 矩阵乘法 + 递推

    2476: 战场的数目 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 58  Solved: 38[Submit][Status][Discuss] D ...

  7. Python基本数据类型之整型和布尔型

    整型和布尔型 获取对象的数据类型 1.type() 2.dir() 3.help() 4.在pycharm里面的操作 数字类型 int 创建: int() 接收数字字符串 .bit_lenght() ...

  8. jQuery datatables

    jQuery datatables 属性,用例 参考:http://datatables.club/example/ http://blog.csdn.net/mickey_miki/article/ ...

  9. JavaScript 中对内存的一些了解

    在使用JavaScript进行开发的过程中,了解JavaScript内存机制有助于开发人员能够清晰的认识到自己写的代码在执行的过程中发生过什么,也能够提高项目的代码质量.其实关于内存的文章也有很多,写 ...

  10. TypeScript Function(函数)

    在JavaScript中,函数是构成任何应用程序的基础块.通过函数,你得以实现建立抽象层.模仿类.信息隐藏和模块化.在TypeScript中,虽然已经存在类和模块化,但是函数依旧在如何去"处 ...