编写脚本批量还愿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. Xcode8与iOS10那些事

    一.证书管理 用Xcode8打开工程后,比较明显的就是下图了,这个是苹果的新特性,可以帮助我们自动管理证书.建议大家勾选这个Automatically manage signing(Ps.但是在bea ...

  2. linux swap 分区那点事儿

    前言 前段时间在用程序对较大数据进行处理时,发现自己电脑原有内存不够用而经常行卡死,于是想到了利用swap分区来扩容内存的方式.现在做一个简要的总结: swap分区的概念 初试swap分区是在进入实验 ...

  3. 1089 最长回文子串 V2(Manacher算法)

    1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa ...

  4. C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 忘记密码功能改进、手机短信、电子邮件

    由于我们的系统接近有100000个用户账户,经常会有忘记密码的时候,用户多了,很小的一个功能,每天都会有很多人在用,每个功能都非常友善,会提高提系统的效率,提高用户体验. 一天最多能返回3次手机短信, ...

  5. XML中输入特殊符号

    XML中输入特殊符号 周银辉 特殊符号比如 ™, 要在xml中使用的话, 其实和html的转码是一样的, 参考下面这个表(使用十进制编码那一列) 特殊符号 命名实体 十进制编码 特殊符号 命名实体 十 ...

  6. 基于webmagic的爬虫项目经验小结

    大概在1个月前,利用webmagic做了一个爬虫项目,下面是该项目的一些个人心得,贴在这里备份: 一.为什么选择webmagic? 说实话,开源的爬虫框架已经很多了,有各种语言(比如:python.j ...

  7. Libsvm Matlab 快速安装教程 (适用于Win7+, 64bit, and Matlab2016a+)

    近日在开始学习Machine Learning SVM 相关算法,将Matlab平台安装SVM的步骤记录如下,亲测可用: 开发环境: Windows 8 64 bit, Matlab 2016a, S ...

  8. 【原】Learning Spark (Python版) 学习笔记(二)----键值对、数据读取与保存、共享特性

    本来应该上周更新的,结果碰上五一,懒癌发作,就推迟了 = =.以后还是要按时完成任务.废话不多说,第四章-第六章主要讲了三个内容:键值对.数据读取与保存与Spark的两个共享特性(累加器和广播变量). ...

  9. 格雷码原理与Verilog实现

    格雷码原理 格雷码是一个叫弗兰克*格雷的人在1953年发明的,最初用于通信.格雷码是一种循环二进制码或者叫作反射二进制码.格雷码的特点是从一个数变为相邻的一个数时,只有一个数据位发生跳变,由于这种特点 ...

  10. .pop ----remove 删除

    s = {1,2,3,4,5,6,'sn','7'} s.pop()#删除随机值 print(s)#{2, 3, 4, 5, 6, '7', 'sn'} s.remove('sn')#删除值 prin ...