编写脚本批量还愿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. Python-09-paramiko模块

    开发堡垒机之前,先来学习一下Python的paramiko模块,该模块基于SSH用于连接远程服务器并执行相关操作. SSHClient 用于连接远程服务器并执行基本命令 基于用户名密码连接 impor ...

  2. 配置文件类 Properties

    Properties(配置文件类): 主要用于生产配置文件与读取配置文件的信息. Properties属于集合类,继承于Hashtable. Properties要注意的细节:    1. 如果配置文 ...

  3. ASM, AAM

    名称 下载网址 am_tools http://www.isbe.man.ac.uk/~bim/software/am_tools_doc/index.html VOSM http://sourcef ...

  4. input 禁止输入法

    <INPUT TYPE = text STYLE = "ime-mode:disabled" > 即可禁止输入法 js形式: active 代表输入法为中文inacti ...

  5. Query节点操作,jQuery插入节点,jQuery删除节点,jQuery Dom操作

    一.创建节点 var box = $('<div>节点</div>'); //创建一个节点,或者var box = "<div>节点</div> ...

  6. JQUERY获取当前页面的URL信息

    以前在做网站的时候,经常会遇到当前页的分类高亮显示,以便让用户了解当前处于哪个页面.之前一直是在每个不 同页面写方法.工程量大,也不便于修改.一直在想有什么简便的方法实现.后来在网上查到可以用获取当前 ...

  7. 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇

    上一篇文章说到了.NET中的打印机,在PrintDocument类也暴露一些本质上上的问题,前面也提到过了,虽然使用PrintDcoument打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...

  8. CCF 201604-4 游戏

    /* 广度优先搜索 左右两个方向 node{x,y,step} 到了就返回step,不到就检查左右两边符合条件就入队. 用一个结构体保存 危险时间 time[i][j]{beg,time} beg=e ...

  9. 多兼容的JS获取鼠标坐标

    //第一.相对于屏幕 function getMousePos(event) { var e = event || window.event; return {'x':e.screenX,'y':sc ...

  10. 项目分析_xxoo-master

    项目介绍:使用java1.5的原生xml操作类实现 对象<-->xml字符串的相互转化 项目分析:主要分为是三个部分 1.容器类:AbstractContainer         存储x ...