您好!您可以使用Simplify这款通用Android反混淆工具。该工具通过模拟Dalvik虚拟机执行混淆代码,简化反编译后的代码,便于分析人员理解。Simplify的两个核心模块——smalivm和simplify,以及如何使用它们,可以参考CSDN博客。
此外,还有其他一些Android反混淆工具,例如Threadtear和dex2jar等。
由于该项目包含Android框架的子模块,因此可以通过以下两种方式获取代码:
1. 使用`git clone --recursive https://github.com/CalebFenton/simplify.git`命令克隆整个项目;或者使用`git submodule update --init --recursive`命令更新并初始化子模块。
2. 确保系统已经安装了`gradlew`,然后执行`./gradlew fatjar`命令编译jar文件。编译成功后,可以在`simplify/build/libs/simplify.jar`目录下找到生成的`Simplify.jar`文件。接下来,可以使用以下命令行测试`Simplify.jar`是否安装成功:
```bash
java -jar simplify/build/libs/simplify.jar -it 'org/cf' simplify/obfuscated-example
```
注意:由于该工具还在前期开发阶段,作者提到它可能不是很稳定。在尝试使用时,可以参考以下建议:
1. 当分析的smali文件包含较少的method或classes时,可以使用-it命令。
2. 如果超过了最大的地址访问长度、函数调用分析深度、最大的方法遍历次数等限制,可以通过修改参数 –max-address-visits, –max-call-depth, –max-method-visits来修正。
3. 如果仍然无法解决问题,可以使用-v参数报告问题。
完整的使用命令可以在GitHub上找到,这里不再赘述。
示例分析:
以GitHub上的一个引导性示例为例,介绍该工具是如何工作的。在介绍该工具如何工作之前,首先简单介绍一下该项目里面包含的模块:
1. smalivm:该模块是Dalvik虚拟机的模拟器模块,主要用于模拟Dalvik虚拟机的执行。它能够根据输入的smali文件返回所有可能的执行路径以及对应的路径得到的寄存器的值。该模拟器能够在不知道一个函数参数的情况下进一步分析,它的方式就是将函数中存在分支的所有结果模拟执行一遍,在完全执行完毕之后,该工具会返回程序执行的每条路径的寄存器的结果,从而便于simplify模块进一步分析,简化混淆的代码。
2. simplify:
该模块是解混淆的主要模块,主要基于smalivm的分析结果,简化混淆的反编译代码,得到易于理解的反编译代码。接下来,我们将通过一个Java代码的例子来演示如何使用此模块。
首先,需要新建一个模拟器。在这个例子中,我们需要配置待分析的smali文件路径(SMALI_PATH)。这里不再展示完整的main.smali文件,因为它太长了。你可以从这个GitHub仓库获取:https://github.com/smali/smali
创建VirtualMachineFactory实例:
```java
VirtualMachineFactory vmFactory = new VirtualMachineFactory();
```
然后构建模拟器实例:
```java
VirtualMachine vm = vmFactory.build(SMALI_PATH);
```
接下来,我们需要使用hook函数的功能将某些函数hook掉。由于有些函数会影响模拟器的外部输出结果,比如System.out.println(),因此,需要将这些函数hook,以在保证函数正常运行的情况下,得到smalivm正常输出的结果。这里我们使用MethodEmulator.addMethod()方法来hook System.out.println()函数:
```java
MethodEmulator.addMethod("Ljava/io/PrintStream;-->println(Ljava/lang/String;)V", java_io_PrintStream_println.class);
```
现在,我们可以执行待分析的smali文件的main函数:
```java
vm.execute("Lorg/cf/demosmali/Main;-->main([Ljava/lang/String;)V");
```
最后,根据不同的函数参数输入类型,选择对应的函数分析方式分析Android程序的功能。此外,除了函数本身参数的类型,分析的方式还需根据自己的需求选择有参数还是无参数分析。有参数的方式能够加快分析速度,但是往往很多情况下,我们并不知道参数应该设置成什么值,不恰当的值会导致错误。以下是一些示例:
```java
executePrintParameter(42); // 有参数分析
executeParameterLogicWithUnknownParameter(); // 无参数分析(未知参数)
executeParameterLogicWithKnownParameter(10); // 无参数分析(已知参数)
```
由于在无参数分析的情况下,该工具会穷举所有可能的分支结构,因此需要将前面提到的三个参数的数值设置大一些,分析的时间也将响应的变长。此外,smalivm执行在无参数情况下设置下的函数时,应当输出两个结果,这代表了smalivm执行了两条路径。获取smalivm分析得到所有的分析路径后,不同路径有不同的返回结果,因此能够输出所有的返回结果。getTerminatingRegisterConsensus这个函数可以很方便获得所有返回寄存器的地址,从而得到输出的结果。
总结:该工具simplify是我目前看到过的唯一一个通用的能够用来解任何混淆的工具,该工具的思路较为巧妙,实现难度较大,因此是一个很不错的工作。但在优化执行效率方面也还有许多的提升空间,比如,在无参数分析函数的设置下,该工具会将所有可能的输入都执行,因此执行的时间可能会很长。从污点分析技术中借鉴剪枝的技术可能是一个有前景的优化方向。