当前位置: 首页 > news >正文

Github每日精选(第38期):Java 8+ Jar 和 Android APK 逆向工程套件(反编译器、编辑器、调试器等)bytecode-viewer

bytecode-viewer

bytecode-viewer 是一个 轻量级用户友好的 Java/Android 字节码查看器、反编译器。

BCV 由几个开源工具提供支持,旨在帮助逆向过程。

BCV 带有 6 个反编译器、3 个反汇编器、2 个汇编器、2 个 APK 转换器、高级搜索、调试等。

它完全用 Java 编写,并且是开源的。它目前由 Konloch 维护和开发。

github 的地址在这里。

在这里插入图片描述

主要特征

  • 只需拖放即可反编译和搜索 Java Jars 和 Android APK
  • 文件格式支持:Class、Jar、XAPK、APK、DEX、WAR、JSP、图像资源、文本资源等
  • 6 个内置 Java 反编译器:Krakatau、CFR、Procyon、FernFlower、JADX、JD-GUI
  • 3 个内置字节码反汇编器,包括 2 个汇编器:Krakatau 和 Smali/BakSmali
  • 来自 Dex2Jar 和 Enjarify 的 APK/DEX 支持
  • 内置Java编译器
  • 高级静态搜索功能
  • 可定制的用户界面
  • 插件+脚本引擎设计
  • 恶意代码扫描API
  • 翻译成 30 多种语言,包括:阿拉伯语、德语、日语、普通话、俄语、西班牙语)
  • 将功能导出为 Runnable Jar、Zip、APK、反编译为 Zip 等。

命令行输入

	-help                         Displays the help menu
	-clean                        Deletes the BCV directory
	-english                      Forces English language translations
	-list                         Displays the available decompilers
	-decompiler <decompiler>      Selects the decompiler, procyon by default
	-i <input file>               Selects the input file (Jar, Class, APK, ZIP, DEX all work automatically)
	-o <output file>              Selects the output file (Java or Java-Bytecode)
	-t <target classname>         Must either be the fully qualified classname or "all" to decompile all as zip
	-nowait                       Doesn't wait for the user to read the CLI messages

如何使用

  • 从 Jar、Zip、ClassFile 或 Android 文件(APK、DEX、XAPK 等)开始,将其拖入 BCV。它将自动开始解码过程。
  • 从这里您可以通过选择 View Pane>View 1、View 2、View 3 等来选择您想要使用的反编译器。
  • 视图窗格用于并排显示最多 3 个反编译器,您也可以在此处切换可编辑性。
  • 通过使用资源列表导航选择您要打开的资源,BCV 将尽力显示它(反编译、反汇编等)。
  • 您可以使用插件来帮助您搜索以及使用左下角的搜索窗格。

代码分析

这里主要分析MethodNodeDecompiler.java 下的反编译代码,反编译代码也是这个项目的核心,通过反编译代码可以看看这种逆向工具是如何做到对编译的代码进行逆向的。

public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb,
                                                  MethodNode m, ClassNode cn) {
        String class_;
        if (cn.name.contains("/")) {
            class_ = cn.name.substring(cn.name.lastIndexOf("/") + 1);
        } else {
            class_ = cn.name;
        }

        String s = getAccessString(m.access);
        sb.append("     ");
        sb.append(s);
        if (s.length() > 0)
            sb.append(" ");

        if (m.name.equals("<init>")) {
            sb.append(class_);
        } else if (!m.name.equals("<clinit>")) {
            Type returnType = Type.getReturnType(m.desc);
            sb.append(returnType.getClassName());
            sb.append(" ");
            sb.append(m.name);
        }

        TypeAndName[] args = new TypeAndName[0];

        if (!m.name.equals("<clinit>")) {
            sb.append("(");

            final Type[] argTypes = Type.getArgumentTypes(m.desc);
            args = new TypeAndName[argTypes.length];

            for (int i = 0; i < argTypes.length; i++) {
                final Type type = argTypes[i];

                final TypeAndName tan = new TypeAndName();
                final String argName = "arg" + i;

                tan.name = argName;
                tan.type = type;

                args[i] = tan;

                sb.append(type.getClassName() + " " + argName
                        + (i < argTypes.length - 1 ? ", " : ""));
            }

            sb.append(")");
        }

        int amountOfThrows = m.exceptions.size();
        if (amountOfThrows > 0) {
            sb.append(" throws ");
            sb.append(m.exceptions.get(0));// exceptions is list<string>
            for (int i = 1; i < amountOfThrows; i++) {
                sb.append(", ");
                sb.append(m.exceptions.get(i));
            }
        }

        if (s.contains("abstract")) {
            sb.append(" {}");
            sb.append(" //");
            sb.append(m.desc);
            sb.append(nl);
        } else {

            sb.append(" {");

            if (BytecodeViewer.viewer.debugHelpers.isSelected()) {
                if (m.name.equals("<clinit>"))
                    sb.append(" // <clinit>");
                else if (m.name.equals("<init>"))
                    sb.append(" // <init>");
            }

            sb.append(" //");
            sb.append(m.desc);

            sb.append(nl);

            if (m.signature != null) {
                sb.append("         <sig:").append(m.signature).append(">");
            }

            if (m.annotationDefault != null) {
                sb.append(m.annotationDefault);
                sb.append("\n");
            }

            InstructionPrinter insnPrinter = new InstructionPrinter(m, args);

            addAttrList(m.attrs, "attr", sb, insnPrinter);
            addAttrList(m.invisibleAnnotations, "invisAnno", sb, insnPrinter);
            addAttrList(m.invisibleAnnotations, "invisLocalVarAnno", sb,
                    insnPrinter);
            addAttrList(m.invisibleTypeAnnotations, "invisTypeAnno", sb,
                    insnPrinter);
            addAttrList(m.localVariables, "localVar", sb, insnPrinter);
            addAttrList(m.visibleAnnotations, "visAnno", sb, insnPrinter);
            addAttrList(m.visibleLocalVariableAnnotations, "visLocalVarAnno",
                    sb, insnPrinter);
            addAttrList(m.visibleTypeAnnotations, "visTypeAnno", sb,
                    insnPrinter);

            List<TryCatchBlockNode> tryCatchBlocks = m.tryCatchBlocks;
            for (int i = 0; i < tryCatchBlocks.size(); i++) {
                TryCatchBlockNode o = tryCatchBlocks.get(i);
                sb.append("         ");
                sb.append("TryCatch").append(i).append(": L");
                sb.append(insnPrinter.resolveLabel(o.start));
                sb.append(" to L");
                sb.append(insnPrinter.resolveLabel(o.end));
                sb.append(" handled by L");
                sb.append(insnPrinter.resolveLabel(o.handler));
                sb.append(": ");
                if (o.type != null)
                    sb.append(o.type);
                else
                    sb.append("Type is null.");
                sb.append(nl);
            }
            for (String insn : insnPrinter.createPrint()) {
                sb.append("         ");
                sb.append(insn);
                sb.append(nl);
            }
            sb.append("     }" + nl);
        }
        return sb;
    }

相关文章:

  • Pandas 操作数据(三)
  • 查题系统API无限搜题接口搭建
  • python之爬虫基础(1)
  • CVE-2022-22978 Spring-security 认证绕过漏洞分析和漏洞挖掘思考
  • 小孩取名:瑭字的寓意和含义
  • 7、IOC 之Bean定义继承 parent
  • J9数字论:模块化公链能否成为公链新趋势?
  • UVM环境中reset复位的处理
  • 示波器探头的选择和作用及原理
  • 新学期,我的FLAG不能倒~
  • 好心情精神心理科医生:精神病人为何会出现幻觉?
  • java计算机毕业设计ssm电子元件仓库管理系统
  • 数据结构与算法--数组
  • jvm oom内存溢出,导出dump,使用mat进行问题分析
  • 百钱百鸡问题(C++枚举法)
  • [译]Python中的类属性与实例属性的区别
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • centos安装java运行环境jdk+tomcat
  • docker-consul
  • HTML5新特性总结
  • Nodejs和JavaWeb协助开发
  • PaddlePaddle-GitHub的正确打开姿势
  • Python - 闭包Closure
  • Travix是如何部署应用程序到Kubernetes上的
  • 从输入URL到页面加载发生了什么
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 和 || 运算
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 前端技术周刊 2019-01-14:客户端存储
  • 思维导图—你不知道的JavaScript中卷
  • 微信小程序开发问题汇总
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • PostgreSQL之连接数修改
  • zabbix3.2监控linux磁盘IO
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • #前后端分离# 头条发布系统
  • (arch)linux 转换文件编码格式
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (C语言)球球大作战
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (六)c52学习之旅-独立按键
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (一)RocketMQ初步认识
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .net Signalr 使用笔记
  • .netcore 获取appsettings
  • .Net的DataSet直接与SQL2005交互
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)