XMan冬令营 哈尔滨 day2 安卓应用程序逆向分析

安卓应用程序

Why Android?

  • app - 移动互联网的入口

  • 安全研究的交集

  • Android的市场份额

逆向安卓应用的目的?

  • Flag?

  • 漏洞?

  • 恶意代码

  • 好奇心?

认识APK文件

  1. 清单文件 AndroidManifest.xml

    • xml文件

    • 二进制数据

    • 内容

      • 包名 名称 图标 targetSDK 版本号

      • 需要的权限列表

      • 使用的组件信息

    Android应用四大组件

    • Activity 可视界面:生命周期,启动模式

    • Service 服务:前台与后台

    • BroadCast Recevicer 广播:发送接收,静态动态

    • Content Provide 内容提供者: URI 数据库 增删查改

  2. DEX文件

    • Java -> dex

    • Daivik/ART虚拟机

    • Muti-dex

    • Magic: dex.035

  3. so文件

    • C/C++ -> so

    • JNI

    • 第三方库 (opencv、unity)

    • 架构: armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64 ...

  4. 签名文件

    为什么要签名?

    • 防篡改

    • App升级

    • 代码或数据共享: QQ&微信&王者荣耀

  5. META-INF目录

    • MANIFEST.MF 所有文件SHA1/SHA256的base64编码

    • CERT.SF MANIFEST.MF文件SHA1/SHA256的base64编码

    • CERT.RSA/.DES 签名的公钥,SF签名后的数据

    修改文件会导致签名发生变化? NO

    签名格式 v1 v2

    可在此目录中标记渠道号,记录应用市场来源

Android应用的逆向分析与技巧

逆技: 一机(root) 一APK 一椅 一钛合金眼

逆向流程:反编译 -》 目标定位 《-》核心目标逆向

类比追女生: 信息搜集 -》 找突破口 《-》核心突破口

1. 反编译

关注文件

  • Manifest 可读的xml文件

  • Res 可读的资源

  • dex Dex -> Smali -> Java

  • so elf -> asm -> C++

  • dex -> smali baksmali -> java

elf -> arm指令 :

  • IDA

  • Radare2

  • Ghidra

Arm指令 -> C++ :

  • IDA F5

  • Ghidra

  • Arm指令是cpu指令,几乎不会出错

2. 定位逆向目标

  1. 关键字定位

    • 字符串关键字

    • 代码关键字

    • Grep大法

  2. 资源定位

    1. 定位UI中资源变量名

    2. res目录中寻找改变量对应索引

    3. smali

  3. 日志定位

    • adb logcat | grep

    • 日志文件

      • app目录下

      • sdcard

    • App内置的日志文件

      • 重打包

      • hook

    • Smali注入 打印字符串

  4. 调用栈跟踪

    • ddms method profiling

    • hook 系统函数打印 callback

3. 核心目标逆向

静态分析

  • 直接分析smali代码

    • 基本数据类型

    • 寄存器

    • 函数和函数调用

    • 代码块和转跳 goto

  • 分析伪java代码

  • 直接分析arm指令

    • 寄存器 SP, PC, LR

    • 传参方式 低于4个用寄存器 多用堆栈

    • 转跳 B,BL, BX, BLX

    • 储存器访问

    • 数据处理

    • arm和thumb切换 thumb指令占两个字节

  • 分析伪C++代码

 

动态调试

  • Android Studio无源码调试

    1. 配置APP为可调试状态

      • 重打包app,使debuggable为true

      • 修改系统设置ro.debuggable的值为1

      • Xposed插件

    2. 反编译apk将smali导入AndroidStudio工程

      • 安装smalidea插件

    3. 新建remote调试,并配置好端口

    4. 以调试模式启动app,开始调试

      • amstar t–D–W-ncom.anything/.someActivity

        -D debug -W wait for debuger

      • 下断点

  • IDA调试android so

    1. IDA导入so文件

    2. root设备上启动android_server

      • adb push/chmod

      • x86/ arm32/ arm64

    3. IDA新建RemoteAndroidDebuger,配置调试端口

      adb forward tcp:23946 tcp:23946

    4. 选取目标进程,断点调试

      • 断点地址=基地址+相对偏移

      • loadso的时候挂起

      • 区分arm和thumb

  • Smali代码注入 (插桩)

    • 注入方法

      反编译->修改smali代码->重打包

    • 使用场景

      • 批量打印log

      • 控制流分析

      • 数据流分析

    • 可能存在的问题

      • 重打包失败

      • 签名检查

      • 寄存器维护

  • Hook技术

    • 使用场景

      • 注入到目标代码,改变执行结果

      • 获取某一状态下的变量值

    • hook的本质

      • 代码注入

    • Hook工具

      • Xposed 替换app_process

      • Frida Ptrace注入

     

动静结合

Android应用安全保护和对抗

如何保护Android应用?

反编译 => 目标定位 => 核心目标逆向

干扰反编译 代码混淆 反调试 加壳

1. 干扰反编译

  • 利用反编译工具的bug或漏洞

    • AndroidManifest.xml

    • dex

    • So

  • 转换成伪代码时的bug

    • Smali->Java

    • Arm指令->C++

  • 链接资源文件时的bug

    • 特殊的资源文件

    • 超长的资源id

案例

  • 2017年12月,apktool XXE漏洞导致远程代码执行

  • 添加大量的无效代码,耗尽反编译工具的CPU

  • 添加无效的资源文件,使apktool编译失败

  • 资源id越界导致链接时Crash

  • 添加特殊编码字符,使反编译工具Crash

对抗

  • 反编译时不链接资源文件–no-resource

  • 使用新版本的反编译工具

  • 分析底层的反编译代码

    • Smali

    • Arm指令

  • 打造自己的逆向工具链

2. 代码混淆

目的

目的:将代码变得难以阅读

变量名、类名、方法名混淆

  • 超长名字 00o0ooo00ooo000ooo

  • 相似字符 mabin -> m4bln

  • 特定含义的代码 intint = 5

  • 特殊编码 ȷava \u0237

  • 难以阅读的字符

字符串加密

  • 编码

    ascii码、Base64、Unicode

  • 自己实现的字符串加密

    自写函数实现的加密方法

控制流混淆

  • 运算混淆 a + b -> a + c/d – c/d + b

  • 控制流伪造

  • 控制流平坦化

代码混淆工具

  • Java代码

    • ProGuard

    • DexGuard

  • C++代码

    • OLLVM

混淆带来的问题

  • 运行不稳定

  • 开发调试困难

  • 执行效率低

什么APP会使用混淆

  • 受众基础大的APP不会使用“变态”的混淆方式

  • 即使混淆,也只是一小部分核心逻辑

  • 老版本的APP一般不会混淆

  • 纯混淆的CTF题目很无聊

  • 企业级的APP

对抗代码混淆

  • 变量名、类名、方法名混淆

    • 变量重命名jeb、重打包

    • 寻找老版本app

    • 根据开源代码映射

    • 自动化 -> 自动化相似代码检测

  • 字符串加密

    • 静态分析替换

    • 动态hook

  • 控制流混淆

    • 优化反编译工具

    • 符号执行

    • 硬核逆向 状态机、经验、耐心

3. 反调试

  1. Ptrace

    先占坑:自己ptrace自己

  2. 检测Trace Pid的值

    /proc/pid/status 和/proc/pid/task/pid/status

    普通状态下,Tracer Pid这项应该为0;调试状态下为调试进程的PID

  3. 检测调试器

    • 进程名

      • gdb_server

      • android-server

    • 端口号

      • IDA:23946

      • Frida: 27042

    • 内存特征码

  4. 基于时间的检测

     

    看两段代码之间时间,看是否被下断点

  5. 多种策略结合

    • 多进程ptrace

    • 暗桩

    • 守护进程

    • 断点扫描

对抗反调试

  • 找到所有的检测点并Patch

  • 抢占先机式的Hook

  • 开启上帝模式–修改系统

4. 加壳与脱壳

加固

  • Dex加固

    • 指令抽取

    • Dex加密

    • Java -> C

  • So加固

    无源码

    • So加密

    • section 加密

    • 函数动态加解密

    有源码

    • 虚拟机(vmp)

    • 各种壳

dex加密过程

加固后的APK运行过程

Process.start -> Application创建 -> attachBaseContext -> onCreate -> onStart -> onResume -> Activity生命周期

在程序运行时dump内存

脱壳

Dex脱壳

  • Dex脱壳

    • Hook dex加载函数

    • Dump内存重建dex

    • 定制化系统

  • 脱壳工具

    • dumpDex

    • FDex2

    • Frida

So脱壳

  • 解密so

    • hook loader

    • 修复section

    • dump内存

  • vmp

    • 硬逆

    • 状态机

    • 虚拟机入口

练习 & 逆向经验分享



猜你喜欢

转载自www.cnblogs.com/r3t7rn/p/12194592.html