`

android 反编译的一点思路

 
阅读更多
请大家先不否定我,不要先把事情打上不可能的标签. 只是一点思路和探索,就当是活跃思维了。

欢迎留言,不吝赐教.

android 反编译的教程帖子还是很多的,具体流程一般是 android->dex->dex.jar->java source,简单
点的 class 反编译效果还是不错的。一旦 sourcecode 太复杂,反编译效果就强差人意了。所以让我有了写自己反编译器的冲动.
这里, 反编译目标对象是运行在 dalvik 虚拟机的 class 文件. 它运行在 jvm 上的 class 文件基本结构是一样的, 但操作符的数目更少, 操作也更简单, 很多对寄存器的操作都简化了.
我使用 dex 解压 apk 文件 获得 class.dex 然后再转码为 .smali 文件, 这文件其实就是 dalvik bytecode 的文字表达方式, 相对于直接读写 byte位, 基于文字的文件更易读一些.

在我的设想里,反编译的结果应该是:
1 没有语法错误.
2 和 sourcecode 文件等效的代码。力争反编译得到的 sourcecode 再次编译后得到的 class 文件同 sourcecode 得到的 class 文件是一致的.
以下不在设计范围之内:
对于混淆代码, 反编译过程自身不负责替换被混淆的包名和变量名. 替换工作应该在完成反编译之后通过其他工具完成. 例如你如果获得了等效的源代码, 那么只要你使用市面上流行的混淆工具再次混淆源代码即可转码成一个更易读的源码版本.

具体实现上:
我认为反编译的重心是 method 的反编译. java 的基本组成部分是 class, 内部类, 接口, 匿名内部类, 方法, 静态初始化段落. 在编译时所有的类类型都会被处理成一个独立存在的 class 文件, 例如内部类就是 parentclass@innerclass 匿名内部类就是 parentclass@number. 不同的是内部类会含有一个 parent.this. 先完成 method 的反编译, 再考虑内部类的问题.

我用了一个月的时间来分析 android 编译得到的 dalvik bytecode 文件. 可供参考的资料实在不多,于是我就自己动手按照自己的思路写了一些基础的反编译代码。思路分两个部分:
1 理清程序的执行流程,识别出 while,嵌套while、if、else、dowhile等程序结构。
2 在执行结构的基础上反编译出 java code。

对于阶段 (1) 在每个while或者是goto的部分切分 bytecode 成更小的片段, 然后,把 bytecode 转化为执行流程“图”,然后通过分析节点的连通性来分析出各种语句结构(for,while,dowhile,if...)

如果源码结构不太复杂,第一阶段是可以顺利完成的,例如
    public void testContinue6() {
        int a = 0;
        int b = 0;
        int c = 0;

        out1: while (a < 100 && b < 100) {
            for (int i = 0; i < c; i += 2) {
                if (i / 5 == 2) {
                    System.out.println("innter0");
                    break out1;
                }
                if (i % 18 == 3) {
                    System.out.println("innter2");
                    continue out1;
                }
            }
        }
    }

我目前的代码已经能完整的识别出其中的 while、嵌套循环等结构。

如果执行顺序可以确定,那么阶段(2)翻译出 sourcecode 就十分简单。这基于下面的几个假设:
1 java bytecode 是基于寄存器的,bytecode中所可能使用到的寄存器的数目和参数都是可以确定的。
2 程序执行总是顺序的,即便是 while 循环也可以理解成先执行条件判断部分,然后执行while的代码部分。
3 在顺序执行的代码段中,执行过程中会根据程序结构而划分出更多变量的子作用域。
4 子作用域可以使用的变量数目>=父作用域的变量数目,在作用域结束时只有当前作用域中使用的变量结束作用(寄存器被释放). 也就是说如果 current.scope register count > parent.scope register count, 那么就能确定这个变量一定是定义在当前上下文的.

我还发现了一些解释的小技巧:
每个 bytecode 操作符其实都可以看做一个输入输出控制器,永远都是一个或者是多个输入,0 或 1 个输出。
那么语句的执行可以转化为一个"倒置的树结构"的寄存器依赖"图", 所有语句最后都会合并到一点,例如 return, 或者method invoke. 在子作用域中, 按照倒置树的起止范围可以细分更多子结构, 每个子结构都合并到一点. 追查寄存器的依赖关系就可以获得变量的依赖关系, 进而推断出变量的定义位置和作用域.
那倒置树的叶子节点是 "常量" 或者 来自 parent scope 或者可以推断他是一个当前作用域的变量, 那么可以停止树结构的建立了. 如果两个树结构有重叠的节点, 那么这个节点就应该被当作当前上下文的一个变量对象.

这里只是泛泛的说,但我相信通过上面的分析方法是可以确定各个变量的定义位置和作用域的。有了这些信息,只要把所有的 byte code 翻译成 java statement 即可获得可读的代码。再做一次代码语义的优化就可以获得获得可读性更强的代码了。

凡事总有例外,如果源码结构写的太复杂,就很难分析出来了,例如
    public void testContinue18() {
        int a = 0;
        int b = 90;
        int c = 0;

        do {
            System.out.println(a);
            if (test1()) {
                continue;
            }
            System.out.println("bb");
            if (test2()) {
                break;
            }
            System.out.println("cc");
        } while (test7() || test3() || test4());
    }

    public void testContinue20() {
        int count = 0;
        while (true) {
            System.out.println("00");
            count++;
            if (count / 32 + 5 == 113) {
                break;
            }
            System.out.println("aa");
        }
        System.out.println("bb");

        do {
            System.out.println("00");
            count++;
            if (count / 32 + 5 == 113) {
                break;
            }
            System.out.println("aa");
        } while (test2());
        System.out.println("bb");
    }

结构分析的时候就有很多等价的结构,不能确定使用哪种。并且之前在 if else 处断开 bytecode 的划分本身都太粗糙了。这里还没思路.

引用:
dalvik bytecode
http://www.netmite.com/android/mydroid/dalvik/docs/dalvik-bytecode.html
分享到:
评论

相关推荐

    基于动态代理Android插件化研究与实现.pdf

    它成功地欺骗了Android系统的底层安全机制,为Android插件化技术的发展提供了新的思路。 此外,动态代理技术的应用使得插件化方案更加灵活。开发者可以在不改变原有系统架构的情况下,有效地解决插件化带来的挑战,...

    VMP原理1

    反调试思路是利用程序在调试和非调试状态下的行为差异来检测和阻止调试器的使用。混淆代码则通过增加代码复杂度和体积,使逆向分析更加困难。例如,可以使用代码膨胀技术,将原代码复制到IDE中并进行编译,使得逆向...

    电力系统中基于MATLAB的价格型需求响应与电价弹性矩阵优化

    内容概要:本文详细介绍了如何利用MATLAB进行价格型需求响应的研究,特别是电价弹性矩阵的构建与优化。文章首先解释了电价弹性矩阵的概念及其重要性,接着展示了如何通过MATLAB代码实现弹性矩阵的初始化、负荷变化量的计算以及优化方法。文中还讨论了如何通过非线性约束和目标函数最小化峰谷差,确保用户用电舒适度的同时实现负荷的有效调节。此外,文章提供了具体的代码实例,包括原始负荷曲线与优化后负荷曲线的对比图,以及基于历史数据的参数优化方法。 适合人群:从事电力系统优化、能源管理及相关领域的研究人员和技术人员。 使用场景及目标:适用于希望深入了解并掌握价格型需求响应机制的专业人士,旨在帮助他们更好地理解和应用电价弹性矩阵,优化电力系统的负荷分布,提高能源利用效率。 其他说明:文章强调了实际应用中的注意事项,如弹性矩阵的动态校准和用户价格敏感度的滞后效应,提供了实用的技术细节和实践经验。

    一级医院医疗信息管理系统安装调试技术服务合同20240801.pdf

    一级医院医疗信息管理系统安装调试技术服务合同20240801.pdf

    表5 文献综述.doc

    表5 文献综述.doc

    36W低压输入正激电源, 正激变压器设计方法步骤及谐振电感的设计方法,主要讲诉了正激电源变压器测的输入输出参数,按输入的条件设计相关的变压器的参数,同时将输出电感的设计方法一并例出,详细的设计步骤

    36W低压输入正激电源 变压器电感设计

    基于YOLOv8的深度学习课堂行为检测系统源码(含检测图片和视频)

    基于YOLOv8的深度学习课堂行为检测系统源码,软件开发环境python3.9,系统界面开发pyqt5。在使用前安装python3.9,并安装软件所需的依赖库,直接运行MainProgram.py文件即可打开程序。模型训练时,将train,val数据集的绝对路径改为自己项目数据集的绝对路径,运行train.py文件即可开始进行模型训练,内含项目文件说明,以及检测图片和视频。

    odbc-oracle zabbix模版原版

    odbc_oracle zabbix模版原版

    基于纳什谈判理论的风光氢多主体能源系统合作运行方法——综合能源交易与优化模型

    内容概要:本文探讨了利用纳什谈判理论来优化风光氢多主体能源系统的合作运行方法。通过MATLAB代码实现了一个复杂的优化模型,解决了风电、光伏和氢能之间的合作问题。文中详细介绍了ADMM(交替方向乘子法)框架的应用,包括联盟效益最大化和收益分配谈判两个子任务。此外,还涉及了加权残差计算、目标函数构造、可视化工具以及多种博弈模式的对比等功能模块。实验结果显示,合作模式下系统总成本显著降低,氢能利用率大幅提升。 适合人群:从事能源系统研究的专业人士、对博弈论及其应用感兴趣的学者和技术人员。 使用场景及目标:适用于需要优化多主体能源系统合作运行的场合,如工业园区、电网公司等。主要目标是提高能源利用效率,降低成本,增强系统的灵活性和稳定性。 其他说明:代码中包含了丰富的可视化工具,能够帮助研究人员更好地理解和展示谈判过程及结果。同时,提供了多种博弈模式的对比功能,便于进行性能评估和方案选择。

    C#与Halcon联合编程实现高效视觉几何定位与测量框架

    内容概要:本文详细介绍了如何利用C#与Halcon联合编程构建高效的视觉几何定位与测量框架。主要内容涵盖模板创建与匹配、圆测量、数据持久化以及图像采集等方面的技术细节。首先,通过创建形状模板并进行匹配,实现了工件的精确定位。接着,针对圆形物体的测量,提出了动态ROI绘制、亚像素边缘提取和稳健圆拟合的方法。此外,还讨论了模板管理和图像采集的最佳实践,确保系统的稳定性和高效性。最后,强调了Halcon对象的内存管理和错误处理机制,提供了实用的优化建议。 适合人群:具备一定编程基础,尤其是对C#和Halcon有一定了解的研发人员和技术爱好者。 使用场景及目标:适用于工业生产线上的自动化检测设备开发,旨在提高工件定位和尺寸测量的精度与效率。主要目标是帮助开发者掌握C#与Halcon联合编程的具体实现方法,从而构建稳定可靠的视觉检测系统。 其他说明:文中提供了大量实战代码片段和调试技巧,有助于读者快速理解和应用相关技术。同时,作者分享了许多实际项目中的经验和教训,使读者能够避开常见陷阱,提升开发效率。

    QT6 C++视频播放器实现(基于QGraphicsVideo)

    QT视频播放器实现(基于QGraphicsView)

    评估管线钢环焊缝质量及其对氢脆的敏感性.pptx

    评估管线钢环焊缝质量及其对氢脆的敏感性.pptx

    机器学习(预测模型):专注于 2024 年出现的漏洞(CVE)信息数据集

    该是一个在 Kaggle 上发布的数据集,专注于 2024 年出现的漏洞(CVE)信息。以下是关于该数据集的详细介绍:该数据集收集了 2024 年记录在案的各类漏洞信息,涵盖了漏洞的利用方式(Exploits)、通用漏洞评分系统(CVSS)评分以及受影响的操作系统(OS)。通过整合这些信息,研究人员和安全专家可以全面了解每个漏洞的潜在威胁、影响范围以及可能的攻击途径。数据主要来源于权威的漏洞信息平台,如美国国家漏洞数据库(NVD)等。这些数据经过整理和筛选后被纳入数据集,确保了信息的准确性和可靠性。数据集特点:全面性:涵盖了多种操作系统(如 Windows、Linux、Android 等)的漏洞信息,反映了不同平台的安全状况。实用性:CVSS 评分提供了漏洞严重程度的量化指标,帮助用户快速评估漏洞的优先级。同时,漏洞利用信息(Exploits)为安全研究人员提供了攻击者可能的攻击手段,有助于提前制定防御策略。时效性:专注于 2024 年的漏洞数据,反映了当前网络安全领域面临的新挑战和新趋势。该数据集可用于多种研究和实践场景: 安全研究:研究人员可以利用该数据集分析漏洞的分布规律、攻击趋势以及不同操作系统之间的安全差异,为网络安全防护提供理论支持。 机器学习与数据分析:数据集中的结构化信息适合用于机器学习模型的训练,例如预测漏洞的 CVSS 评分、识别潜在的高危漏洞等。 企业安全评估:企业安全团队可以参考该数据集中的漏洞信息,结合自身系统的实际情况,进行安全评估和漏洞修复计划的制定。

    QML Combobox 自动过滤,输入字符串后自动匹配

    博客主页:https://blog.csdn.net/luoyayun361 QML ComboBox控件,输入关键字后自动过滤包含关键字的列表,方便快速查找列表项

    【人工智能领域】人工智能技术发展历程、核心原理及应用指南:涵盖机器学习、深度学习、NLP和计算机视觉的全面介绍

    内容概要:本文全面介绍了人工智能技术的发展历程、核心技术原理、应用方法及其未来趋势。首先阐述了人工智能的定义和核心目标,随后按时间顺序回顾了其从萌芽到爆发的五个发展阶段。接着详细讲解了机器学习、深度学习、自然语言处理和计算机视觉等核心技术原理,并介绍了使用现成AI服务和开发自定义AI模型的应用方法。此外,还展示了智能客服系统、图像分类应用和智能推荐系统的具体实现案例。针对普通用户,提供了使用大模型的指南和提问技巧,强调了隐私保护、信息验证等注意事项。最后展望了多模态AI、可解释AI等未来发展方向,并推荐了相关学习资源。; 适合人群:对人工智能感兴趣的初学者、技术人员以及希望了解AI技术应用的普通大众。; 使用场景及目标:①帮助初学者快速了解AI的基本概念和发展脉络;②为技术人员提供核心技术原理和应用方法的参考;③指导普通用户如何有效地使用大模型进行日常查询和任务处理。; 其他说明:本文不仅涵盖了AI技术的基础知识,还提供了丰富的实际应用案例和实用技巧,旨在帮助读者全面理解人工智能技术,并能在实际工作中加以应用。同时提醒读者关注AI伦理和版权问题,确保安全合法地使用AI工具。

    本学习由 Matrix 工作室制作并开发,包括算法与数据结构的学习路线和各种题解

    本学习由 Matrix 工作室制作并开发,包括算法与数据结构的学习路线和各种题解。

    基于智慧图书馆基础业务流程Axure11高保真原型设计

    本项目致力于构建基于微服务架构的智慧图书馆管理平台,重点突破多校区图书馆异构系统间的数据壁垒。通过建立统一数据治理规范、部署智能分析模块、重构业务流程引擎,系统性实现以下建设目标:构建跨馆业务数据的标准化整合通道,实施容器化部署的弹性资源管理体系,开发具备机器学习能力的业务辅助决策系统,打造可量化评估的管理效能提升模型,最终形成支持PB级数据处理的分布式存储体系与全维度数据资产图谱。

    mysql中慢sql分析

    根据processlist查询出慢sql 1.修改配置文件中的mysql链接 2.目前是15秒执行一次获取执行时间在5秒上的sql,可以在配置中修改 3.执行后查出的慢sql会记录到log文件夹中以日期命名的txt文件中,可自行查验

    全域通航 低空经济服务平台建设实施方案.pptx

    全域通航 低空经济服务平台建设实施方案.pptx

    全国联合交通查询手册,涵盖各大城市

    全国交通一卡通互联互通服务手册,支持在线查询

Global site tag (gtag.js) - Google Analytics