# andriodlabs
之前手贱又更新到安卓 13 了 又需要重新刷一次机 心累
记住 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
# ARM 汇编学习
用 NDK 编译 C 语言文件出来 ARM 汇编对比研究
C:\Users\98762\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin
建议直接把路径加入环境变量
生成的 ELF 可执行文件就是 ARM 的可放 IDA
也可以 clang -target arm-linux-android21 -S demo.i -o demo.s 得汇编代码
指令,伪指令 (编译器提供,用于指导编译过程) 与符号
从汇编代码到十六进制数据 (二进制文件) 就叫做汇编
arm32 每个指令 4 字节
ARM 是 RISC (精简指令集) 架构的
CPSR 程序状态寄存器
r13 是堆栈寄存器,指向堆栈的栈顶
r14 (lr) 一个函数的返回地址
r15(pc)
r0-r12 通用寄存器
根据调用规则 ATPCS,程序一般都使用 FD(FullDescending)类型的数据栈(满栈)
满减栈
stmfd sp!, {r1-r4} (相当于 push)
跳转指令:
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 的去除签名校验功能
方法三:具体分析签名校验逻辑 (手撕签名校验)