引言
因为导师的方向有android安全的内容,给我看的论文大多也涉及android安全的内容,而我此前一点基础也没有,看的一脸懵
故随便找书先上手再说
书籍详细内容:android软件安全权威指南
搭建环境
需求:分析APP
主要围绕:android软件开发,android软件逆向,android源码编译
- 安装JDK
- 安装Android SDK(使用Android Studio已经包含,无需额外下载)
- 安装Android NDK(同上)
- Android Studio集成开发环境,可以选择下载CMake,LLDB
- Android模拟器
Cygwin或Bash on Ubantu on Windows(win10下linux子系统)
常用逆向分析工具
- ApkTool:APK的反编译与回编译功能
- smali/baksmali:DEX文件的反编译与回编译工具
- dex2jar:DEX文件转换jar包
- 010Editor:跨平台二进制编辑器,提供二进制模版
搭建源码分析环境
推荐Win10,使用Docker编译系统源码
如何分析Android程序
从开发学起,学习路线是线性的,循环渐进的,分析程序是开发的逆过程
从开发到最终分析并破解的完整路线:
编写一个Android程序
创建
hint
是EditText
上的默认提示ems
是将对应控件的宽度设为几个字符的宽度,设置以后,一行最大只能显示x个字符MessageDigest
StringBuilder
编译
1.命令行方式编译
进入工程目录,目录下内容如下
Crackme0201.iml
: Android Studio生成的项目配置文件local.properties
: 本地配置文件,记录了当前系统中安装的Android SDK和Android NDK的路径app
: 项目目录,程序代码和资源setting.gradle
: 指定包含的项目模块的路径build
: 命令执行后输出文件的存放目录,第一次未编译是还没有的build.gradle
: 项目的构建脚本gradlew
: macOS和Linux系统使用的脚本编译命令gradlew.bat
: 与gradlew功能相同,用于Windows
gradlew是基于task来编译项目的,执行gradlew task
命令,列出所有支持的task
生成Debug调试版本的APK,在终端执行./gradlew assembleDebug
命令,编译后在app/build/outputs/apk
安装Debug调试版本的APK,执行./gradlew installDebug
命令,会自动安装到连接的设备或模拟器上
2.Android Studio编译
直接点运行,Android Studio会自动编译APK,并安装到设备上,如果只想编译不想运行,点击Build -> Make Project来编译当前工程。
破解一个Android程序
破解入手
通常方法:使用ApkTool反编译APK文件,生成smali格式的反编译代码。通过阅读smali文件的代码来理解程序的运行机制,找到突破口,并对代码进行修改。使用ApkTool重新编译生成APK文件并对其进行签名,运行测试。
如此循环,直到全部破解。
在实际分析中,还可以使用IDA Pro直接分析APK文件,使用dex2jar与jd-gui配合进行Java源码级的分析等。
反编译
安装Apktool工具,对APK文件进行反编译
apktool d ./app-debug.apk -o outdir
对当前目录下的debug.apk进行反编译,文件生成在outdir目录下
反编译包含一系列目录和文件,smali目录下存放了程序的所有反编译代码,res中是所有资源文件,这些目录的子目录和文件的组织结构与开发一致。
分析
突破口:错误提示信息
错误提示代码附近通常是程序的核心验证代码。
错误提示属于Android资源中的字符串资源,可能会被硬编码到源码中,也可能在res/value/string.xml
中
对smali文件进行分析checkSN()
被调用,进行注册码合法性检查
move-result v0
if-nez v0, :cond_0
第一行将返回结果保存在v0寄存器,第二行对v0寄存器进行判断,如果其值不为0,即条件为真,跳转到cond_0标号处,反之程序继续执行
如果代码不跳转,则继续执行
.line 34
iget-object v0, p0, Lorg/nuaa/crackme0201/MainActivity$1;->this$0:Lorg/nuaa/crackme0201/MainActivity;
const v1, 0x7f06002c
invoke-static {v0, v1, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
move-result-object v0
.line 35
invoke-virtual {v1}, Landroid/widget/Toast;->show()V
goto :goto_0
使用iget-object
指令获取MainActivity实例的引用,其中,->this$0
是内部类MainActivity$1中的一个synthetic字段,存储对父类MainActivity的引用。const v1, 0x7f06002c
指令将v1寄存器传入unsuccess字符串的id,调用Toast;->makeText()
创建字符串,在line35show出来
修改smali
关键在if-nez v0, :cond_0
类似的跳转指令有if-nez, if-eqz, if-gez, if-lez
等
与if-nez
相反的是if-eqz
,等于0时跳转
重新编译
修改代码后,重新编译,打包成APK文件
apktool b outdir_rel
此时编译生成的APK文件是没有签名的,不能进行安装和测试,需要对APK进行签名
我没照书上的做,用的是360签名工具,链接在这里
签名的key用的是之前新建的
安装测试
启动Android模拟器,或者使用设备,在终端直接执行命令先卸载原来版本,再安装破解后的版本
$adb uninstall com.droider.crackme0201
Success
$adb install signed.apk
Success
再启动测试,发现已经破解了
小结
破解的流程:
反编译 -> 分析 -> 修改 -> 回编译 -> 签名
如果觉得繁琐可以采用集成工具
macOS: Android-Crack-Tool, Windows: Android Killer