# andriodlabs

之前手贱又更新到安卓 13 了 又需要重新刷一次机 心累

image-20230712124358034

记住 frida-server 在 /data/local/tmp/

有关 jar 包:https://zhuanlan.zhihu.com/p/82320492

# 安卓架构

Android 是一个开源的,基于 Linux 的移动设备操作系统

应用程序组件是一个 Android 应用程序的基本构建块。这些组件由应用清单文件松耦合的组织。AndroidManifest.xml 描述了应用程序的每个组件,以及他们如何交互。

以下是可以在 Android 应用程序中使用的四个主要组件。

组件 描述
Activities (活动) 描述 UI,并且处理用户与机器屏幕的交互。
Services (服务) 处理与应用程序关联的后台操作。
Broadcast Receivers (广播接收器) 处理 Android 操作系统和应用程序之间的通信。
Content Providers (内容提供者) 处理数据和数据库管理方面的问题。

Android 的分 4 层,java 应用程序,java 框架,本地框架和 java 运行环境,Linux 内核空间

Java 应用程序无需过多解释,基本可以理解为各个 App,由 Java 语言实现。

Java 框架层(系统服务)就是常说的 Framework,这层里东西很多也很复杂,比如说主要的一些系统服务如 ActivityManagerService、PackageManagerService 等,我们编写的 Android 代码之所以能够正常识别和动作,都要依赖这一层的支持。这一层也是由 Java 语言实现。

Native 层(本地服务)这部分常见一些本地服务和一些链接库等。这一层的一个特点就是通过 C 和 C 语言实现。比如我们现在要执行一个复杂运算,如果通过 java 代码去实现,那么效率会非常低,此时可以选择通过 C 或 C 代码去实现,然后和我们上层的 Java 代码通信(这部分在 android 中称为 jni 机制)。又比如我们的设备需要运行,那么必然要和底层的硬件驱动交互,也要通过 Native 层。

Linux 内核空间就不过多解释了

# lab1

image-20230711222422735

image-20230712144054758

image-20230712144128626

img

# ARM 汇编学习

用 NDK 编译 C 语言文件出来 ARM 汇编对比研究

image-20230713130819423

C:\Users\98762\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin

建议直接把路径加入环境变量

image-20230713134827964

生成的 ELF 可执行文件就是 ARM 的可放 IDA

也可以 clang -target arm-linux-android21 -S demo.i -o demo.s 得汇编代码

指令,伪指令 (编译器提供,用于指导编译过程) 与符号

从汇编代码到十六进制数据 (二进制文件) 就叫做汇编

arm32 每个指令 4 字节

ARM 是 RISC (精简指令集) 架构的

image-20230713144140075

image-20230713144404690

CPSR 程序状态寄存器

image-20230714195334674

r13 是堆栈寄存器,指向堆栈的栈顶

r14 (lr) 一个函数的返回地址

r15(pc)

r0-r12 通用寄存器

根据调用规则 ATPCS,程序一般都使用 FD(FullDescending)类型的数据栈(满栈)

满减栈

stmfd sp!, {r1-r4} (相当于 push)

image-20231004143920320

跳转指令:

B 无条件跳转

BL 带链接的无条件跳转

BX 带状态切换的无条件跳转

BLX 带链接和状态切换的无条件跳转 (BLX 指令从 ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由 ARM 状态切换到 Thumb 状态)

# apk 结构

apk 全称 Android Package,它相当于一个压缩文件,只要在电脑上将 apk 后缀改为 zip 即可解压。

文件 注释
assets 目录 存放 APK 的静态资源文件,比如视频,音频,图片等
lib 目录 armeabi-v7a 基本通用所有 android 设备,arm64-v8a 只适用于 64 位的 android 设备,x86 常见用于 android 模拟器,其目录下的.so 文件是 c 或 c++ 编译的动态链接库文件
META-INF 目录 保存应用的签名信息,签名信息可以验证 APK 文件的完整性,相当于 APK 的身份证 (验证文件是否又被修改)
res 目录 res 目录存放资源文件,包括图片,字符串等等,APK 的脸蛋由他的 layout 文件设计
AndroidMainfest.xml 文件 APK 的应用清单信息,它描述了应用的名字,版本,权限,引用的库文件等等信息
classes.dex 文件 classes.dex 是 java 源码编译后生成的 java 字节码文件,APK 运行的主要逻辑
resources.arsc 文件 resources.arsc 是编译后的二进制资源文件,它是一个映射表,映射着资源和 id,通过 R 文件中的 id 就可以找到对应的资源

APK 的双开 (改包名)

汉化:使用专门的工具对外文版的软件资源进行读取、翻译、修改、回写等一系列处理,使软件的菜单、对话框、提示等用户界面显示为中文,而程序的内核和功能保持不变,这个过程即为软件汉化

基本上字符串都是在 arsc 里,建议一键汉化,然后再润色。
少量没汉化到的字符串参考视频中的方法定位去逐个汉化。

注意签名校验

# JNI 静态注册与动态注册

1、按照 JNI 规范的命名规则进行查找,这种方式叫静态注册。(包名 - 类名 - 方法名 - 方法参数)
2、调用 JNI 提供的 RegisterNatives 函数,将本地函数注册到 JVM 中,这种方式叫动态注册。

# HOOK 相关

# 动静态 hook

动态函数:需要得到其实例($new 或 Java.choose), 如果是 Java.choose 则在 onMatch 进行具体操作;
静态函数:直接用 Java.use 出来的类来调用具体的静态函数即可。

frida 日常使用可参考 http://www.juziss.cn/2020/11/14/Frida% E6%97% A5% E5% B8% B8% E4% BD% BF% E7%94% A8% E6%80% BB% E7% BB%93/

有空做 lab8-lab11

# 什么是 JVM、Dalvik、ART

JVM 是 JAVA 虚拟机,运行 JAVA 字节码程序
Dalvik 是 Google 专门为 Android 设计的一个虚拟机,Dalvik 有专属的文件执行格式 dex (Dalvik executable)
Art (Android Runtime) 相当于 Dalvik 的升级版,本质与 Dalvik 无异

# smali 及其语法

寄存器采用 v 和 p 来命名,v 表示本地寄存器 (局部变量),p 表示参数寄存器

smali 是 Dalvik 的寄存器语言,smali 代码是 dex 反编译而来的。

关键字

名称 注释
.class 类名
.super 父类名,继承的上级类名名称
.source 源名
.field 变量
.method 方法名
.register 寄存器
.end method 方法名的结束
public 公有
protected 半公开,只有同一家人才能用
private 私有,只能自己使用
.parameter 方法参数
.prologue 方法开始
.line xxx 位于第 xxx 行

数据类型对应

smali 类型 java 类型 注释
V void 无返回值
Z boolean 布尔值类型,返回 0 或 1
B byte 字节类型,返回字节
S short 短整数类型,返回数字
C char 字符类型,返回字符
I int 整数类型,返回数字
J long (64 位 需要 2 个寄存器存储) 长整数类型,返回数字
F float 单浮点类型,返回数字
D double (64 位 需要 2 个寄存器存储) 双浮点类型,返回数字
string String 文本类型,返回字符串
Lxxx/xxx/xxx object 对象类型,返回对象

常用指令

关键字 注释
const 重写整数属性,真假属性内容,只能是数字类型
const-string 重写字符串内容
const-wide 重写长整数类型,多用于修改到期时间。
return 返回指令
if-eq 全称 equal (a=b),比较寄存器 ab 内容,相同则跳
if-ne 全称 not equal (a!=b),ab 内容不相同则跳
if-eqz 全称 equal zero (a=0),z 即是 0 的标记,a 等于 0 则跳
if-nez 全称 not equal zero (a!=0),a 不等于 0 则跳
if-ge 全称 greater equal (a>=b),a 大于或等于则跳
if-le 全称 little equal (a<=b),a 小于或等于则跳
goto 强制跳到指定位置
switch 分支跳转,一般会有多个分支线,并根据指令跳转到适当位置
iget 获取寄存器数据

其余指令可用语法工具查询

定位方法:搜索弹窗关键字 (MT,jadx)、抓取按钮 id (开发者助手)

静态分析工具:jadx

修改工具:MT 管理器

# Activity 生命周期

函数名称 描述
onCreate() 一个 Activity 启动后第一个被调用的函数,常用来在此方法中进行 Activity 的一些初始化操作。例如创建 View,绑定数据,注册监听,加载参数等。
onStart() 当 Activity 显示在屏幕上时,此方法被调用但此时还无法进行与用户的交互操作。
onResume() 这个方法在 onStart () 之后调用,也就是在 Activity 准备好与用户进行交互的时候调用,此时的 Activity 一定位于 Activity 栈顶,处于运行状态。
onPause() 这个方法是在系统准备去启动或者恢复另外一个 Activity 的时候调用,通常在这个方法中执行一些释放资源的方法,以及保存一些关键数据。
onStop() 这个方法是在 Activity 完全不可见的时候调用的。
onDestroy() 这个方法在 Activity 销毁之前调用,之后 Activity 的状态为销毁状态。
onRestart() 当 Activity 从停止 stop 状态恢进入 start 状态时调用状态。

# 动态调试步骤

# 1. 修改 debug 权限

方法一:在 AndroidManifest.xml 里添加可调试权限

复制代码 隐藏代码
android:debuggable="true"

方法二:XappDebug 模块 hook 对应的 app

项目地址

XappDebug

# 2. 端口转发以及开启 adb 权限

# 3. 下段点

ctrl+b 下断点

# 4.debug 模式启动

 复制代码 隐藏代码
adb shell am start -D -n com.zj.wuaipojie/.ui.MainActivity

adb shell am start -D -n
adb shell am start -D -n 包名 / 类名
am start -n 表示启动一个 activity
am start -D 表示将应用设置为可调试模式

# 5.Jeb 附加调试进程

快捷键:
R 运行到光标处

# Log 插桩

定义:Log 插桩指的是反编译 APK 文件时,在对应的 smali 文件里,添加相应的 smali 代码,将程序中的关键信息,以 log 日志的形式进行输出。

调用命令

invoke-static {对应寄存器}, Lcom/mtools/LogUtils;->v(Ljava/lang/Object;)V

# 签名校验

如何判断是否有签名校验?
不做任何修改,直接签名安装,应用闪退则说明大概率有签名校验

kill/killProcess-----kill/KillProcess () 可以杀死当前应用活动的进程,这一操作将会把所有该进程内的资源(包括线程全部清理掉). 当然,由于 ActivityManager 时刻监听着进程,一旦发现进程被非正常 Kill,它将会试图去重启这个进程。这就是为什么,有时候当我们试图这样去结束掉应用时,发现它又自动重新启动的原因.
system.exit----- 杀死了整个进程,这时候活动所占的资源也会被释放。
finish---------- 仅仅针对 Activity,当调用 finish () 时,只是将活动推向后台,并没有立即释放内存,活动的资源并没有被清理
 所谓三角校验,就是so检测dex,动态加载的dex(在软件运行时会解压释放一段dex文件,检测完后就删除)检测so,dex检测动态加载的dex

# 签名校验对抗

方法一:核心破解插件,不签名安装应用
方法二:一键过签名工具,例如 MT、NP、ARMPro、CNFIX、Modex 的去除签名校验功能
方法三:具体分析签名校验逻辑 (手撕签名校验)