Android逆向

1 背景

面经总结第四篇–Android逆向。

下面的部分内容可能引用自其他师傅的文章,有的忘记引用了,侵删。

2 分析APK的常见流程;IDA Pro Debug动态调试so库

2.1 分析APK的常见流程

(1) 真机运行APP,猜测APK模块正向开发使用的字符串、方法和SDK,确定待破解点;
(2) 使用Fiddler抓取APP运行过程中的数据包并进行分析;
(3) 使用Jadx或者JEB打开APK文件并静态分析Java源码,同时使用IDA静态分析APK文件中的so库;
(4) 通过特征字符串、特征函数、代码注入、栈跟踪和方法剖析快速定位关键代码;
(5) 搭配Hook和动态调试查看并修改Java层或so层的关键字段;
(6) 使用AndroidKiller和IDA修改对应的smali和so文件,最后重新打包并签名。

2.2 IDA Pro Debug动态调试so库

(1) 把android_server发送到手机目录data/local/tmp,并以root权限运行;
(2) 开启端口转发,使用命令adb shell am start -D -n 包名+类名挂起程序;
(3) 打开DDMS窗口,记录调试程序的端口号;
(4) 打开IDA,填写主机号,端口号,选择对应进程,勾选三项,F9运行;
(5) 利用jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8614命令启动jdb调试器,加载so库;
(6) 在模块中找到目标so库,查找动态注册函数jni_onload或者以java_开头的静态注册函数,进而分析相关函数运行逻辑。

【注】安卓APK加固后,DEX文件被修改或隐藏,使用反编译工具通常无法获得程序代码。程序运行时会使用dvmDexFileOpenPartial函数将DEX文件加载到内存中,这时可以使用IDC脚本指定内存来dump出真实的DEX文件。

3 模拟器检测和反调试检测

3.1 模拟器检测

模拟器检测的本质就是要利用模拟器和真机之间的微小差异,从而判断当前设备是否为模拟器。

(1) Linux内核:/sys/目录中的硬件驱动信息、/dev/目录中设备节点特征、/proc/目录运行时的内核信息映射;
(2) 硬件:CPU型号和温度、电池电压电量是否实时变化、相机前后像素是否不同、传感器;
(3) 软件:APK安装量、手机使用频率、正常应用场景APP。

3.2 反调试检测

(1) 关键文件检测:/data/local/tmp/文件夹是否有android_server文件;
(2) 端口检测:android_server的默认监听的端口号是23946;
(3) 进程执行时间检测:由于调试会减慢进程的执行速度,因此可以利用执行时间的差异来检测是否调试;
(4) Java反调试检测:
① 检查AndroidManifest.xml文件中ApplicationInfo对象的Debuggable属性;
② 利用android.os.Debug类的isDebuggerConnected方法可以判断JDWP调试器是否正在工作;
(5) Native反调试检测:
① 检测TracerPid字段:通常/proc/pid/status的TracerPid字段是0,但在调试状态下,TracerPid字段会保存调试进程的pid;
② 使用Fork和ptrace:一个进程只能被一个进程附加,所以通过Fork子进程并将其作为调试器附加到父进程来达到反调试效果。

【注】根据OWASP移动应用测试指南的描述,上述模拟器和反调试检测手段需要分散在整个应用程序的源代码中,而不是全部都放在一个方法或函数中。

4 插桩、栈跟踪、方法剖析

4.1 插桩

插桩技术又称代码注入法,在不影响程序上下文情况下,在程序特定的位置插入Log和Toast等函数,从而收集程序运行时的上下文信息。

4.2 栈跟踪

与插桩类似,利用Java异常在程序中插入栈跟踪代码,通过栈跟踪查看程序执行的顺序。

4.3 方法剖析

(1) 使用DDMS自动生成trace文件;
(2) 通过调用android.os.Debug类提供的startMethodTracing()与stopMethodTracing()方法生成trace文件。

5 DEX和ELF文件结构、Frida Hook

5.1 DEX

DEX文件的整体结构包括文件头、索引区和数据区三部分。文件头指定DEX文件的一些属性并记录其他6部分数据结构在DEX文件中的物理偏移和大小;索引区记录着一些偏移和索引;数据区用于存放真正所需要的数据。

DEX文件头大小为0x70字节,包括如下内容:魔术头、adler32校验和、SHA-1值、文件大小、文件头大小、大小端、连接段大小和偏移、mapItem偏移、字符大小和偏移、类型大小和偏移、原型大小和偏移、字段大小和偏移、方法大小和偏移、类大小和偏移、数据大小和偏移。

5.2 ELF

ELF文件的整体结构包括文件头、程序头表和节区头表三部分。

ELF头部作用:表明文件格式;记录一些该文件与环境的基本信息(文件类型、机器架构、版本);程序的入口地址;程序头表的起始地址与其结构表项的数量及大小;节区头表的起始地址与其结构表项的数量及大小。

程序头表作用:表明段的类型及段在文件中的偏移量;记录虚拟地址和物理地址;段在文件和内存中的大小;段权限和对齐方式。程序头表记录每个段(segment)在文件中的位置、大小及如何被加载到内存中执行等信息。

节区头表作用:节区的名称、类型及在文件中的偏移量;节区大小、权限;索引链接、地址对齐。节区头表记录每个节(section)的位置、大小、对齐方式及访问限制等信息,这些节可以被链接器用于组成可执行文件或共享库。

5.3 Frida Hook

Frida会在目标进程的地址空间中注入一段共享库代码,并利用ptrace系统调用使共享库中的JavaScript脚本能够读写目标进程的内存。此后,Frida可以使用JavaScript API来访问和修改目标进程内存中的数据、执行函数、拦截函数调用等。
计算机使用pip安装即可,手机端需要安装特定CPU架构和对应计算机版本的frida-server到/data/local/tmp文件夹,frida-server默认端口是27042。
Java层Hook:比较简单,指定修改Java层的函数参数和返回值即可。
Native层Hook:需要找到so文件名和函数名,然后通过maps文件中so的基地址+函数的相对地址计算出函数在内存中的绝对地址,此外还需要判断是Arm指令还是Thumb指令进行+1操作。

6 隐私合规漏洞和发现思路;Android 7.0以上版本HTTPS抓包解决方法

6.1 APP隐私合规的概念和法律标准

APP隐私合规通常是指APP应用程序提供的隐私政策,用于告知用户个人信息如何被搜集、使用、与第三方共享的情况。目前所有提交上架市场或各平台的APP都需要通过隐私合规性检测后才能上线,参考依据主要是《App违法违规收集使用个人信息行为认定方法》。

6.2 漏洞发现思路

首先使用Jadx或者JEB打开APK文件并静态分析Java源码,同时使用IDA静态分析APK文件中的so库,并对比查看隐私政策的第三方SDK目录;然后利用DDMS或者Fiddler查看APP运行过程中的流量;接着也可以参照美团APP的隐私政策来对比其他APP的隐私政策是否规范;此外搭配Hook和动态调试查看Java层或so层的关键字段。

(1) 通常推送通知消息会调用国内5大厂商(华为、小米、OPPO、VIVO、魅族)的SDK,有的APP隐私政策中没有完整列举;
(2) 第三方支付方式通常都会包括微信支付和支付宝,部分APP只列举微信支付,没有列举支付宝;
(3) APP隐私政策调用的第三方SDK通常都会有官网链接,可能是由于某些官网对开发文档的网站路径进行调整或者设置文档权限,所以导致部分APP隐私政策的官网链接失效或无法访问。

6.3 Android 7.0以上版本HTTPS抓包解决方法

(1) 系统Root后,将CA证书装入系统目录
(2) 调低targetSdkVersion至24以下
(3) 配置networkSecurityConfig,针对此App信任用户证书

7 Dalvik虚拟机与Java虚拟机的区别;ART和Dalvik的区别;签名和验证过程;Android中的ANR和崩溃的区别

7.1 Dalvik虚拟机与Java虚拟机的区别

(1) 运行的字节码不同
Java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Dalvik字节码。传统的Java程序经过编译,生成Java字节码并保存在class文件中,Java虚拟机通过解码class文件的内容来运行程序。而Dalvik虚拟机运行的是Dalvik字节码,所有Dalvik字节码由Java字节码转换而来,并被打包到一个DEX可执行文件中,Dalvik虚拟机通过解释DEX文件来执行这些字节码。

(2) 可执行文件的大小不同
在Android SDK中,dx工具将Java字节码转换为Dalvik字节码,重新排列Java类文件,消除在类文件中出现的所有冗余信息,避免虚拟机在初始化时反复加载和解析文件。

(3) 虚拟机架构不同
Java虚拟机是基于栈架构的。当程序运行时,Java虚拟机会频繁地对栈进行读写数据的操作。在这个过程中,不仅会多次进行指令分派与内存访问,而且会耗费大量的CPU时间。因此,对一些资源有限的设备来说,这是一笔相当大的开销。
Dalvik虚拟机是基于寄存器架构的。数据的访问直接在寄存器之间传递,因此该访问方式比基于栈的访问方式快很多。

7.2 ART和Dalvik的区别

Dalvik在Android 2.2到5.0之间版本运行,采用JIT编译技术,每次应用启动都需要重新编译,因此运行速度较慢,但占用的存储空间较少。
ART运行在Android 4.4或更高版本,采用AOT编译技术,在应用安装时就将字节码转换为本地代码,采用空间换时间的策略,因此运行速度较快。ART改进和优化了垃圾回收机制。

7.3 签名和验证过程

(1) 对APK中的每个文件做一次算法(Hash+Base64编码),保存到MANIFEST.MF文件中;
(2) 对MANIFEST.MF整个文件做一次算法(Hash+Base64编码),存放到CERT.SF文件的头属性中,再对MANIFEST.MF文件中各个属性块做一次算法(Hash+Base64编码),存放到属性块中。
(3) 用私钥对CERT.SF进行签名,并将签名信息、公钥信息和签名算法保存到CERT.RSA文件中。

7.4 Android中的ANR和崩溃的区别

ANR表示应用程序无响应,通常是因为主线程被长时间阻塞或执行耗时操作而导致。在这种情况下,系统会弹出ANR对话框,提示用户等待或关闭应用程序。
崩溃则表示应用程序在运行时发生了严重的错误或异常,导致应用程序停止运行并关闭。常见的崩溃原因包括空指针引用、数组越界、内存泄漏等。崩溃会导致应用程序无法继续运行,需要重新启动才能恢复正常运行。

8 C语言的编译链接过程;Python调用C代码

8.1 C语言的编译链接过程:预处理、编译、汇编、链接

(1) 预处理:主要处理源代码中以#开头的预编译指令(宏定义、条件编译、头文件)并生hello.i文件

gcc -E hello.c -o hello.i

(2) 编译:对hello.i文件进行词法、语法、语义分析和优化后,生成相应的汇编代码文件hello.s

gcc -S hello.i -o hello.s

(3) 汇编:将汇编代码翻译成机器指令,生成目标文件(Windows生成hello.o,Linux生成hello.obj)

gcc -c hello.s -o hello.o

(4) 链接:将不同的源文件产生的目标文件和库文件进行链接,从而生成可执行程序

gcc hello.o -o hello

[1] https://zhuanlan.zhihu.com/p/88255667

8.2 Python调用C代码

(1) 使用gcc将.c文件编译为.so共享库文件

gcc c_so.c -shared -fPIC -o c_so.so

(2) 在.py文件中导入ctypes头文件

from ctypes import *

(3) 用变量接收.so文件的引用

result=cdll.LoadLibrary(“./c_so.so”)

(4) 通过引用调用.so文件中的方法

result.add(1,2)


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。

×

喜欢就点赞,疼爱就打赏