请大家先不否定我,不要先把事情打上不可能的标签. 只是一点思路和探索,就当是活跃思维了。
欢迎留言,不吝赐教.
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系统的底层安全机制,为Android插件化技术的发展提供了新的思路。 此外,动态代理技术的应用使得插件化方案更加灵活。开发者可以在不改变原有系统架构的情况下,有效地解决插件化带来的挑战,...
反调试思路是利用程序在调试和非调试状态下的行为差异来检测和阻止调试器的使用。混淆代码则通过增加代码复杂度和体积,使逆向分析更加困难。例如,可以使用代码膨胀技术,将原代码复制到IDE中并进行编译,使得逆向...
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
《基于YOLOv8的智慧社区独居老人生命体征监测系统》(包含源码、可视化界面、完整数据集、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计
Android Studio Meerkat 2024.3.1 Patch 1(android-studio-2024.3.1.14-mac.dmg)适用于macOS Intel系统,文件使用360压缩软件分割成两个压缩包,必须一起下载使用: part1: https://download.csdn.net/download/weixin_43800734/90557060 part2: https://download.csdn.net/download/weixin_43800734/90557056
侧轴承杯加工工艺编制及夹具设计.zip
NASA数据集锂电池容量特征提取(Matlab完整源码和数据) 作者介绍:机器学习之心,博客专家认证,机器学习领域创作者,2023博客之星TOP50,主做机器学习和深度学习时序、回归、分类、聚类和降维等程序设计和案例分析,文章底部有博主联系方式。从事Matlab、Python算法仿真工作8年,更多仿真源码、数据集定制私信。
板料折弯机液压系统设计.zip
C6150车床的设计.zip
机器学习之KNN实现手写数字
python爬虫;智能切换策略,反爬检测机制
mpls-vpn-optionA-all
56tgyhujikolp[
GB 6442-86企业职工伤亡事故调查分析规则.pdf
汽车液压式主动悬架系统的设计().zip
2000-2024年各省专利侵权案件结案数数据 1、时间:2000-2024年 2、来源:国家知识产权J 3、指标:专利侵权案件结案数 4、范围:31省 5、用途:可用于衡量知识产权保护水平
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
内容概要:本文档详细复现了金融数学课程作业,涵盖欧式看涨期权定价和投资组合优化两大部分。对于欧式看涨期权定价,分别采用Black-Scholes模型和蒙特卡洛方法进行了计算,并对彩虹期权进行了基于最大值的看涨期权定价。投资组合优化部分则探讨了最小方差组合、给定收益的最小方差组合、最大效用组合以及给定风险的最大收益组合四种情形,还对比了拉格朗日乘数法和二次规划求解器两种方法。文中不仅提供了详细的MATLAB代码,还有详尽的中文解释,确保每一步骤清晰明了。 适合人群:金融工程专业学生、量化分析师、金融数学爱好者。 使用场景及目标:①帮助学生理解和掌握金融衍生品定价的基本原理和方法;②为从事量化分析的专业人士提供实用工具和技术支持;③作为教学材料辅助高校教师讲授相关内容。 其他说明:文档还包括了完整的论文结构建议,从封面页到结论,再到附录,涵盖了所有必要元素,确保提交的作业符合学术规范。此外,还特别强调了数据预处理步骤,确保代码可以顺利运行。
脉冲电解射流加工喷射装置设计(1)
ThinkPad S1 (2nd Generation) 和ThinkPad Yoga 260 用户指南V3.0,包含如何拆机更换硬件