静态: dex so
资源逆向工具 AXMKPrinter2(Android binary XML):
java -jar AXMLPrinter2.jar xxx.xml output.xml
查看源码工具dex2jar(dex->jar)、jd-GUI(jar->java):
APK逆向工具APKTool(resources.arsc/xml资源文件/.dex文件):
apktool d input.apk -o output
Android逆向助手(APKTOOL/jd-gui/dex2jar/jarsigner):
反汇编工具IDA PRO:
APK文件:
zip压缩包
解释性语言smali语言
反编译前结构:
assets 声音、字体、网页······资源【无编译可以直接查看】
com 第三方库,不解释
lib 应用中使用到的库
armeabi .so文件,C/C++代码库文件【重要】
META-INF APK的签名文件【***.RSA、***.SF、***.MF3文件】
org 第三方库,如org.apache.http库
res 应用中使用到的资源目录,已编译无法直接阅读
anim 动画资源animation
color 颜色资源
drawable 可绘制的图片资源
drawable-hdpi 图片资源高清
drawable-land 图片资源横向
drawable-land-hdpi 图片资源横向高清
drawable-mdpi 图片资源中等清晰度
drawable-port 图片资源纵向
drawable-port-hdpi 图片资源纵向高清
layout 页面布局文件
layout-land 页面布局文件横向
layout-port 页面布局文件纵向
xml 应用属性配置文件
AndroidManifest.xml 应用的属性定义文件,已压缩无法直接阅读【重要】
classes.dex Java源码编译后的代码文件【重要】
resources.arsc 编译后的资源文件,如strings.xml文件【重要】
反编译后结构:
assets 声音、字体、网页······资源
lib 应用中使用到的库
armeabi .so文件,C/C++代码库文件【重要】【JNI部分】【无法阅读】
META-INF APK的签名文件【***.RSA、***.SF、***.MF3文件】
org 第三方库,如org.apache.http库
res 应用中使用到的资源目录,目录下的东西可以直接阅读
anim 动画资源animation【可以直接阅读】
color 颜色资源【可以直接阅读】
drawable 可绘制的图片资源【可以直接阅读】
drawable-hdpi 图片资源高清【可以直接阅读】
drawable-land 图片资源横向【可以直接阅读】
drawable-land-hdpi 图片资源横向高清【可以直接阅读】
drawable-mdpi 图片资源中等清晰度【可以直接阅读】
drawable-port 图片资源纵向【可以直接阅读】
drawable-port-hdpi 图片资源纵向高清【可以直接阅读】
layout 页面布局文件【可以直接阅读】【重要】
layout-land 页面布局文件横向【可以直接阅读】【重要】
layout-port 页面布局文件纵向【可以直接阅读】【重要】
values
strings.xml 应用中使用到的字符串常量【可以直接阅读】【重要】
dimens.xml 间隔(dip、sp)常量【可以直接阅读】
xml 应用属性配置文件【可以直接阅读】
AndroidManifest.xml 应用的属性定义文件,【可以直接阅读】【重要】
smali Java 代码反编译后生成的代码文件,【smali语法】【重要】
apktool.ymlapktool 反编译的配置文件,用于重新打包
学习Smali语言的语法与结构
逆向分析.so文件,.so文件是二进制文件
分析DEX文件:Dalvik Executable
smali:DEX执行文件格式的汇编器
baksmali:DEX执行文件格式的反汇编器
DEX文件生成过程:
JVM虚拟机 Dalvik虚拟机
.Java文件-->Javac编译-->.class文件-->dx编译-->.dex文件
DEX文件结构: Header、Table、Data
Header:存储的是所有区域片段的大小、偏移量
Table:存储的是各种结构化数据、引用数据以及数据的偏移量
Data:存储的是具体的数据以及代码逻辑
虚拟机指令smali:
smali:寄存器指令
Java: 解释性语言
Smali语法基础:
Java语法 Smali语法 说明
private boolean isFlag .field private isFlag:z 定义变量
Package .class 指定当前的类名
.super 所继承的父类
.local 定义使用局部变量
.method 方法
.parameter 方法参数
.prologue 方法开始
.line 12 此方法位于.java中的第12行,可去除,不影响运行结果
super invoke-super 调用父函数
const/high16 v0,0x7fo3 把ox7fo3赋值给v0
invoke-direct 调用函数
return Return-void 函数返回void
.end method 函数结束
new new-instance 创建实例
iput-object 对象赋值
iget-object 调用对象
invoke-static 调用静态函数
if(vA == vB) if-eq vA,vB 如果vA等于vB
先写java代码,再反编译获取smali指令
分析SO文件:
广告植入与去除:
挂广告:导入SDK、权限配置、广告组件配置、初始化、加载插屏广告
收费限制:逻辑反转
汉化:strings.xml
动态:DDMS、emulator、Andbug、IDA PRO
代码安全分析: APK文件
组件安全分析:四大组件
存储安全分析:数据、私有文件
通信安全分析:证书密码技术
TraceView:方法跟踪
加入调试函数: Debug.startMethodTracing()/Debug.stopMethodTracing()
dmtracedump
graphviz
IDA PRO: so dex
Hook技术:劫持函数调用
java层级的hook:java反射
native层级的hook:ELF文件
ptrace函数附加进程:动态地attach(跟踪一个目标进程)、detach(结束跟踪一个目标进程)、peektext(获取内存字节)、poketext(向内存写入地址)等
加载so库:dlopen,以指定模式打开指定的动态链接库文件
目标进程的虚拟地址空间解析与ELF文件解析:
通过读取/proc/<PID>/maps文件找到链接库的基地址
读取动态库,解析ELF文件,找到符号(需要对ELF文件格式的深入理解)
计算目标函数ude绝对地址
目标进程函数绝对地址=函数地址+动态库基地址
用ptrace函数attach上目标进程
发现装载共享库so函数
装载指定的.so
让目标进程的执行流程转到注入的代码执行
使用ptrace函数的detach释放目标进程
ptrace函数:
int ptrace(int requets, int pid, int addr, int data)
request: 请求ptrace执行的操作
pid:目标进程的ID
addr:目标进程的地址值
data:作用的数据
Android中so库文件: Got表Hook、Sym表Hook、inline Hook
java反射问题: 无法反射调用关键字为native的方法函数(JNI实现的函数)、基本类型的静态常量无法反射修改
zygote进程:Hook框架Xposed、Cydiasubstrate(app_process)
Hook工具:
Xposed框架:/system/bin/app_process java层级
Per App Setting(为每个应用设置单独的dpi或修改权限)
Cydia
XPrivacy(防止隐私泄露)
BootManager(开启自启动程序管理应用)
安装本地服务XposedInstaller
下载使用API库
Cydiasubstrate框架:java/native层级
安装Cydiasubstrate框架本地服务
下载使用Cydiasubstrate库
ADBI/DDI框架:java/native层级
命令行工具
虚拟文件系统:/proc目录
Android内核空间和用户空间之间进行通信,查看当前进程的一些状态信息
maps文件查看进程的虚拟地址空间如何使用
cat /proc/<PID>/maps
/data/*.dex //java层级
/data/*.so //native层级
dev/__properties__
https://www.qubes-os.org/screenshots/
应用加固:
最小化组件暴露:
android:exported="false" //不跨应用,私有
protectionLevel=["normal" | "dangerous" | "signature" | "signatureOrSystem" //签名权限
android:permission= //访问权限
Activity安全:
私有Activity:android:exported="false"
公共Activity:android:exported="true"
伙伴Activity:android:exported="false" GetSignature getPackageInfo //应用签名
内部Activity:android:exported="true" protectionLevel="signature" GetSignature getPackageInfo //应用签名
Broadcast Receiver安全:LocalBroadcastManager
私有Broadcast Receiver:android:exported="false"
公共Broadcast Receiver:android:exported="true"
内部Broadcast Receiver:android:exported="true" protectionLevel="signature"
Service安全:
私有Service:android:exported="false"
公共Service:android:exported="true"
合作Service:android:exported="true" GetSignature getPackageInfo //应用签名
内部Service:android:exported="true" protectionLevel="signature"
Provider安全:
私有Content Provider:android:exported="false"
公共Content Provider:android:exported="true"
合作Content Provider:android:exported="true" GetSignature getPackageInfo //应用签名
内部Content Provider:android:exported="true" protectionLevel="signature" GetSignature getPackageInfo //应用签名
部分Content Provider:android:exported="false"
防止逆向:
代码混淆:花指令
ProGuard:压缩、优化和混淆代码
DEX保护:
DEX优化与混淆:
dalvik-obfuscato
加壳与解壳:
APKProtect、android-unpacker
SO文件保护:
upx
防止jd-GUI查看代码:
这个工具的bug
防止二次打包:
java层签名验证:
PackageInfo;->Signatures
底层签名验证:
/content/pm/Signature
防止动态分析:
调试程序:android_server、gdbserver
模拟器:Build.MODE="sdk"/"google_sdk"
系统安全:
启动验证:device-mapper-verity(dm-verity)
build/make/target/product/verity.mk PRODUCT_SUPPORTS_VERITY := true
SELinux:
对象管理器(Object Manager, OM)
访问权限缓存(Access Vector Cache, AVC)
安全服务
安全策略
主体(Subject): 进程
目标(Object): 资源
MAC: 对访问的控制强制化
TE:对于进程只赋予最小的权限
domain:迁移、防止权限升级
RBAC:对于用户只赋予最小的权限
安全上下文:user、role、type、sensitivity
身份认证:user
角色:role
安全类型:type
安全等级:sensitivity
App进程:service_contexts
App数据文件: seapp_contexts
系统文件: file_contexts
系统属性: property_contexts