mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/mobile-pentesting/android-app-pentesting/smali-changes.
This commit is contained in:
parent
85b274747c
commit
b25307e0d6
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 取证速查表
|
||||
## 取证 速查表
|
||||
|
||||
[https://www.jaiminton.com/cheatsheet/DFIR/#](https://www.jaiminton.com/cheatsheet/DFIR/)
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
- [Intezer](https://analyze.intezer.com)
|
||||
- [Any.Run](https://any.run/)
|
||||
|
||||
## 离线杀毒和检测工具
|
||||
## 离线防病毒及检测工具
|
||||
|
||||
### Yara
|
||||
|
||||
@ -24,8 +24,8 @@ sudo apt-get install -y yara
|
||||
```
|
||||
#### 准备规则
|
||||
|
||||
使用此脚本从 github 下载并合并所有 yara malware rules: [https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9](https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9)\
|
||||
创建 _**rules**_ 目录并执行它。 这将创建一个名为 _**malware_rules.yar**_ 的文件,包含所有 yara malware rules。
|
||||
使用此脚本从 github 下载并合并所有 yara malware 规则: [https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9](https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9)\
|
||||
创建 _**rules**_ 目录并执行该脚本。该操作会生成一个名为 _**malware_rules.yar**_ 的文件,包含所有用于 malware 的 yara rules。
|
||||
```bash
|
||||
wget https://gist.githubusercontent.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9/raw/4ec711d37f1b428b63bed1f786b26a0654aa2f31/malware_yara_rules.py
|
||||
mkdir rules
|
||||
@ -36,9 +36,9 @@ python malware_yara_rules.py
|
||||
yara -w malware_rules.yar image #Scan 1 file
|
||||
yara -w malware_rules.yar folder #Scan the whole folder
|
||||
```
|
||||
#### YaraGen: 检查 malware 并创建 yara rules
|
||||
#### YaraGen: 检测 malware 并创建 yara rules
|
||||
|
||||
你可以使用工具 [**YaraGen**](https://github.com/Neo23x0/yarGen) 从 binary 生成 yara rules。查看这些教程:[**Part 1**](https://www.nextron-systems.com/2015/02/16/write-simple-sound-yara-rules/), [**Part 2**](https://www.nextron-systems.com/2015/10/17/how-to-write-simple-but-sound-yara-rules-part-2/), [**Part 3**](https://www.nextron-systems.com/2016/04/15/how-to-write-simple-but-sound-yara-rules-part-3/)
|
||||
你可以使用工具 [**YaraGen**](https://github.com/Neo23x0/yarGen) 从二进制文件生成 yara rules。查看这些教程: [**Part 1**](https://www.nextron-systems.com/2015/02/16/write-simple-sound-yara-rules/), [**Part 2**](https://www.nextron-systems.com/2015/10/17/how-to-write-simple-but-sound-yara-rules-part-2/), [**Part 3**](https://www.nextron-systems.com/2016/04/15/how-to-write-simple-but-sound-yara-rules-part-3/)
|
||||
```bash
|
||||
python3 yarGen.py --update
|
||||
python3.exe yarGen.py --excludegood -m ../../mals/
|
||||
@ -57,9 +57,9 @@ clamscan folderpath #Scan the whole folder
|
||||
```
|
||||
### [Capa](https://github.com/mandiant/capa)
|
||||
|
||||
**Capa** 在可执行文件:PE、ELF、.NET 中检测潜在恶意的 **能力**。因此它会发现诸如 Att\&ck tactics 的条目,或以下可疑能力:
|
||||
**Capa** 会在可执行文件:PE、ELF、.NET 中检测潜在的恶意 **capabilities**。因此它可以发现诸如 Att\&ck tactics,或下列可疑能力:
|
||||
|
||||
- check for OutputDebugString error
|
||||
- 检查 OutputDebugString 错误
|
||||
- run as a service
|
||||
- create process
|
||||
|
||||
@ -67,15 +67,15 @@ clamscan folderpath #Scan the whole folder
|
||||
|
||||
### IOCs
|
||||
|
||||
IOC 表示入侵指标。IOC 是一组 **用于识别** 某些潜在不受欢迎软件或已确认 **malware** 的 **条件**。Blue Teams 使用这种定义在其 **系统** 和 **网络** 中 **搜索此类恶意文件**。\
|
||||
共享这些定义非常有用,因为当在一台计算机中识别出 malware 并为其创建 IOC 后,其他 Blue Teams 可以使用该 IOC 更快地识别该 malware。
|
||||
IOC 意味着 Indicator Of Compromise(入侵指示器)。IOC 是一组**识别条件**,用于识别某些可能不受欢迎的软件或已确认的**malware**。Blue Teams 使用这种定义在其**系统**和**网络**中**搜索此类恶意文件**。\
|
||||
共享这些定义非常有用:当在一台计算机上识别出 malware 并为其创建了 IOC 时,其他 Blue Teams 可以使用该 IOC 更快地识别该 malware。
|
||||
|
||||
用于创建或修改 IOCs 的工具有 [**IOC Editor**](https://www.fireeye.com/services/freeware/ioc-editor.html)**.**\
|
||||
你可以使用诸如 [**Redline**](https://www.fireeye.com/services/freeware/redline.html) 的工具来 **在设备中搜索已定义的 IOCs**。
|
||||
用于创建或修改 IOCs 的工具是 [**IOC Editor**](https://www.fireeye.com/services/freeware/ioc-editor.html)**.**\
|
||||
你可以使用诸如 [**Redline**](https://www.fireeye.com/services/freeware/redline.html) 的工具来**在设备中搜索已定义的 IOCs**。
|
||||
|
||||
### Loki
|
||||
|
||||
[**Loki**](https://github.com/Neo23x0/Loki) 是一个用于扫描简单入侵指标的扫描器。\
|
||||
[**Loki**](https://github.com/Neo23x0/Loki) 是一个用于检测简单入侵指示器的扫描器。\
|
||||
检测基于四种检测方法:
|
||||
```
|
||||
1. File Name IOC
|
||||
@ -92,41 +92,41 @@ Compares process connection endpoints with C2 IOCs (new since version v.10)
|
||||
```
|
||||
### Linux Malware Detect
|
||||
|
||||
[**Linux Malware Detect (LMD)**](https://www.rfxn.com/projects/linux-malware-detect/) 是一个面向 Linux 的 malware 扫描器,基于 GNU GPLv2 许可发布,专为共享托管环境所面临的威胁而设计。它使用来自 network edge intrusion detection systems 的威胁数据来提取正在被用于攻击的 malware 并生成用于检测的签名。此外,威胁数据也来自用户通过 LMD checkout 功能提交的样本以及 malware community resources。
|
||||
[**Linux Malware Detect (LMD)**](https://www.rfxn.com/projects/linux-malware-detect/) 是一个面向 Linux 的 malware 扫描器,基于 GNU GPLv2 许可发布,针对共享托管环境所面临的威胁进行设计。它利用来自网络边缘入侵检测系统的威胁数据来提取正在被用于攻击的 malware,并生成检测签名。此外,威胁数据还来源于用户通过 LMD checkout feature 提交的数据和 malware 社区资源。
|
||||
|
||||
### rkhunter
|
||||
|
||||
像 [**rkhunter**](http://rkhunter.sourceforge.net) 这样的工具可用于检查文件系统以查找可能的 **rootkits** 和 malware。
|
||||
Tools like [**rkhunter**](http://rkhunter.sourceforge.net) can be used to check the filesystem for possible **rootkits** and malware.
|
||||
```bash
|
||||
sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--skip-keypress]
|
||||
```
|
||||
### FLOSS
|
||||
|
||||
[**FLOSS**](https://github.com/mandiant/flare-floss) 是一个工具,会尝试使用不同的技术在可执行文件中查找混淆的字符串。
|
||||
[**FLOSS**](https://github.com/mandiant/flare-floss) 是一个工具,尝试使用不同的技术在 executables 内查找 obfuscated strings。
|
||||
|
||||
### PEpper
|
||||
|
||||
[PEpper ](https://github.com/Th3Hurrican3/PEpper) 会检查可执行文件中的一些基本内容(二进制数据、熵、URLs 和 IPs、一些 yara 规则)。
|
||||
[PEpper ](https://github.com/Th3Hurrican3/PEpper) checks 一些可执行文件内部的基本内容(binary data, entropy, URLs and IPs, some yara rules)。
|
||||
|
||||
### PEstudio
|
||||
|
||||
[PEstudio](https://www.winitor.com/download) 是一个可以获取 Windows 可执行文件信息的工具,例如 imports、exports、headers,同时也会检查 VirusTotal 并发现潜在的 Att\&ck 技术。
|
||||
[PEstudio](https://www.winitor.com/download) 是一个工具,可以获取 Windows executables 的信息,例如 imports、exports、headers,但也会检查 virus total 并发现潜在的 Att\&ck techniques。
|
||||
|
||||
### Detect It Easy(DiE)
|
||||
|
||||
[**DiE**](https://github.com/horsicq/Detect-It-Easy/) 是一个用于检测文件是否 **encrypted** 并查找 **packers** 的工具。
|
||||
[**DiE**](https://github.com/horsicq/Detect-It-Easy/) 是一个用于检测文件是否为 **encrypted** 并且查找 **packers** 的工具。
|
||||
|
||||
### NeoPI
|
||||
|
||||
[**NeoPI** ](https://github.com/CiscoCXSecurity/NeoPI) 是一个 Python 脚本,使用多种 **statistical methods** 来检测文本/脚本文件中 **obfuscated** 和 **encrypted** 的内容。NeoPI 的目的是帮助 **detection of hidden web shell code**。
|
||||
[**NeoPI** ](https://github.com/CiscoCXSecurity/NeoPI)is 一个 Python 脚本,使用多种 **statistical methods** 来检测文本/脚本文件中 **obfuscated** 和 **encrypted** 的内容。NeoPI 的目的是协助 **detection of hidden web shell code**。
|
||||
|
||||
### **php-malware-finder**
|
||||
|
||||
[**PHP-malware-finder**](https://github.com/nbs-system/php-malware-finder) 尽其所能检测 **obfuscated**/**dodgy code**,以及使用常见于 **malwares**/webshells 的 **PHP** 函数的文件。
|
||||
[**PHP-malware-finder**](https://github.com/nbs-system/php-malware-finder) 尽最大努力检测 **obfuscated**/**dodgy code**,以及使用常见于 **malwares**/webshells 的 **PHP** 函数的文件。
|
||||
|
||||
### Apple Binary Signatures
|
||||
|
||||
在检查某些 **malware sample** 时,你应始终 **check the signature** 二进制,因为签名的 **developer** 可能已经与 **malware** 有关联。
|
||||
在检查某些 **malware sample** 时,您应始终 **check the signature** 二进制文件,因为签名的 **developer** 可能已与 **malware.** 有所 **related**。
|
||||
```bash
|
||||
#Get signer
|
||||
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"
|
||||
@ -139,25 +139,25 @@ spctl --assess --verbose /Applications/Safari.app
|
||||
```
|
||||
## 检测技术
|
||||
|
||||
### File Stacking
|
||||
### 文件堆叠
|
||||
|
||||
如果你知道某个包含 web 服务器 **文件** 的文件夹在某个 **日期被最后更新**。请**检查**该 web 服务器中所有 **文件** 的创建和修改 **日期**,如果有任何日期 **可疑**,就检查那个文件。
|
||||
如果你知道某个包含 **web 服务器文件** 的文件夹在某个日期被**最后更新**,请**检查**该 web 服务器中所有 **文件** 的**创建和修改日期**,如果有任何日期显得**可疑**,就检查该文件。
|
||||
|
||||
### Baselines
|
||||
### 基线
|
||||
|
||||
如果一个文件夹的文件 **不应该被修改**,你可以计算该文件夹原始文件的 **hash** 并将其与当前文件 **比较**。任何被修改的文件都应视为 **可疑**。
|
||||
如果某个文件夹的文件**不应该被修改**,你可以计算该文件夹**原始文件**的 **hash**,并将其与**当前**文件进行**比对**。任何被修改的都会很**可疑**。
|
||||
|
||||
### Statistical Analysis
|
||||
### 统计分析
|
||||
|
||||
当信息记录在日志中时,你可以**检查统计信息**,例如每个 web 服务器文件被访问的次数,因为 web shell 可能是被访问次数最多的之一。
|
||||
当信息保存在日志中时,你可以**检查统计数据**,例如每个 web 服务器文件被访问的次数,因为 web shell 可能是被访问次数最多的之一。
|
||||
|
||||
---
|
||||
|
||||
### Android in-app native telemetry (no root)
|
||||
|
||||
在 Android 上,你可以通过在其他 JNI 库初始化之前预加载一个小型 logger 库,在目标应用进程内对 native 代码进行 instrument。这样可以在不依赖系统范围 hook 或 root 的情况下,尽早观察 native 行为。一种常用方法是 SoTap:将 libsotap.so 放到 APK 的对应 ABI 路径下,并尽早注入一个 System.loadLibrary("sotap") 调用(例如静态初始化器或 Application.onCreate),然后从内部/外部路径收集日志,或使用 Logcat 作为回退。
|
||||
在 Android 上,你可以通过在其他 JNI 库初始化之前预加载一个小型 logger 库,在目标应用进程内对 native 代码进行插桩。这样可以在不依赖系统范围 hooks 或 root 的情况下,尽早观察 native 行为。一个常用方法是 SoTap:将对应 ABI 的 libsotap.so 放入 APK,并尽早注入 System.loadLibrary("sotap") 调用(例如在静态初始化器或 Application.onCreate 中),然后从内部/外部路径收集日志,或回退到 Logcat。
|
||||
|
||||
查看 Android native reversing 页面以获取设置细节和日志路径:
|
||||
有关设置细节和日志路径,请参阅 Android native reversing 页面:
|
||||
|
||||
{{#ref}}
|
||||
../../mobile-pentesting/android-app-pentesting/reversing-native-libraries.md
|
||||
@ -167,11 +167,11 @@ spctl --assess --verbose /Applications/Safari.app
|
||||
|
||||
## Deobfuscating Dynamic Control-Flow (JMP/CALL RAX Dispatchers)
|
||||
|
||||
现代恶意软件家族大量滥用 Control-Flow Graph (CFG) 混淆:它们不是直接跳转/调用,而是在运行时计算目标并执行 `jmp rax` 或 `call rax`。一个小的 *dispatcher*(通常九条指令)会根据 CPU 的 `ZF`/`CF` flags 设置最终目标,这会完全破坏静态 CFG 恢复。
|
||||
现代恶意软件家族严重滥用 Control-Flow Graph (CFG) 混淆:它们不是直接跳转/调用,而是在运行时计算目标并执行 `jmp rax` 或 `call rax`。一个小的 *dispatcher*(通常九条指令)根据 CPU 的 `ZF`/`CF` 标志设置最终目标,完全破坏了静态 CFG 恢复。
|
||||
|
||||
该技术 —— 由 SLOW#TEMPEST loader 展示 —— 可以通过一个仅依赖 IDAPython 和 Unicorn CPU emulator 的三步工作流来破解。
|
||||
这种技术 — 由 SLOW#TEMPEST loader 展示 — 可以通过一个只依赖 IDAPython 和 Unicorn CPU emulator 的三步工作流程来破解。
|
||||
|
||||
### 1. Locate every indirect jump / call
|
||||
### 1. 定位每个间接跳转 / 调用
|
||||
```python
|
||||
import idautils, idc
|
||||
|
||||
@ -180,7 +180,7 @@ mnem = idc.print_insn_mnem(ea)
|
||||
if mnem in ("jmp", "call") and idc.print_operand(ea, 0) == "rax":
|
||||
print(f"[+] Dispatcher found @ {ea:X}")
|
||||
```
|
||||
### 2. 提取 dispatcher 字节码
|
||||
### 2. 提取 dispatcher byte-code
|
||||
```python
|
||||
import idc
|
||||
|
||||
@ -195,7 +195,7 @@ size = jmp_ea + idc.get_item_size(jmp_ea) - start
|
||||
code = idc.get_bytes(start, size)
|
||||
open(f"{start:X}.bin", "wb").write(code)
|
||||
```
|
||||
### 3. 使用 Unicorn 对其进行两次模拟
|
||||
### 3. 使用 Unicorn 模拟两次
|
||||
```python
|
||||
from unicorn import *
|
||||
from unicorn.x86_const import *
|
||||
@ -211,9 +211,9 @@ mu.reg_write(UC_X86_REG_RAX, 0)
|
||||
mu.emu_start(BASE, BASE+len(code))
|
||||
return mu.reg_read(UC_X86_REG_RAX)
|
||||
```
|
||||
运行 `run(code,0,0)` 和 `run(code,1,1)` 以获取 *false* 和 *true* 分支目标。
|
||||
运行 `run(code,0,0)` 和 `run(code,1,1)` 以获取 *false* 与 *true* 分支目标。
|
||||
|
||||
### 4. 将其修补回直接 jump / call
|
||||
### 4. 回补直接的 jump / call
|
||||
```python
|
||||
import struct, ida_bytes
|
||||
|
||||
@ -222,28 +222,28 @@ op = 0xE8 if is_call else 0xE9 # CALL rel32 or JMP rel32
|
||||
disp = target - (ea + 5) & 0xFFFFFFFF
|
||||
ida_bytes.patch_bytes(ea, bytes([op]) + struct.pack('<I', disp))
|
||||
```
|
||||
在打补丁之后,强制 IDA 重新分析该函数,以恢复完整的 CFG 和 Hex-Rays 输出:
|
||||
打补丁后,强制 IDA 重新分析该函数,以便恢复完整的 CFG 和 Hex-Rays 输出:
|
||||
```python
|
||||
import ida_auto, idaapi
|
||||
idaapi.reanalyze_function(idc.get_func_attr(ea, idc.FUNCATTR_START))
|
||||
```
|
||||
### 5. 标注间接 API 调用
|
||||
### 5. Label indirect API calls
|
||||
|
||||
一旦每个 `call rax` 的真实目标已知,你就可以告诉 IDA 那是什么,这样参数类型 & 变量名会被自动恢复:
|
||||
一旦每个 `call rax` 的真实目标被确定,你可以告诉 IDA 它是什么,从而自动恢复参数类型 & 变量名:
|
||||
```python
|
||||
idc.set_callee_name(call_ea, resolved_addr, 0) # IDA 8.3+
|
||||
```
|
||||
### 实际好处
|
||||
|
||||
* 恢复真实的 CFG → 反编译结果从 *10* 行变成数千行。
|
||||
* 恢复真实的 CFG → 反编译结果从 *10* 行扩展到数千行。
|
||||
* 启用 string-cross-reference & xrefs,使行为重建变得轻而易举。
|
||||
* 脚本可复用:将它们放入受相同技巧保护的任何 loader 中。
|
||||
* 脚本可重用:将它们放入任何使用相同技巧保护的 loader 中。
|
||||
|
||||
---
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [Unit42 – Evolving Tactics of SLOW#TEMPEST: A Deep Dive Into Advanced Malware Techniques](https://unit42.paloaltonetworks.com/slow-tempest-malware-obfuscation/)
|
||||
- SoTap: Lightweight in-app JNI (.so) behavior logger – [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap)
|
||||
- SoTap:轻量级的 in-app JNI (.so) 行为记录器 – [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -1,48 +1,48 @@
|
||||
# Reversing Native Libraries
|
||||
# 反向分析本地库
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
**欲了解更多信息请参阅:** [**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html)
|
||||
**更多信息请参见:** [**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html)
|
||||
|
||||
Android 应用可以使用 native libraries,通常用 C 或 C++ 编写,以处理性能关键的任务。恶意软件作者也滥用这些库,因为 ELF shared objects 仍然比 DEX/OAT byte-code 更难反编译。
|
||||
本页侧重于 *practical* 工作流程和 *recent* 工具改进(2023–2025),这些改进使得逆向 Android `.so` 文件更容易。
|
||||
Android 应用可以使用本地库,通常用 C 或 C++ 编写,用于性能关键的任务。恶意软件作者也滥用这些库,因为 ELF 共享对象比 DEX/OAT byte-code 更难反编译。
|
||||
本页侧重于使逆向 Android `.so` 文件更容易的*实用*工作流程和*近期*工具改进(2023–2025)。
|
||||
|
||||
---
|
||||
|
||||
### Quick triage-workflow for a freshly pulled `libfoo.so`
|
||||
### 新提取 `libfoo.so` 的快速初筛流程
|
||||
|
||||
1. **Extract the library**
|
||||
1. **提取库文件**
|
||||
```bash
|
||||
# From an installed application
|
||||
adb shell "run-as <pkg> cat lib/arm64-v8a/libfoo.so" > libfoo.so
|
||||
# Or from the APK (zip)
|
||||
unzip -j target.apk "lib/*/libfoo.so" -d extracted_libs/
|
||||
```
|
||||
2. **Identify architecture & protections**
|
||||
2. **识别架构与保护**
|
||||
```bash
|
||||
file libfoo.so # arm64 or arm32 / x86
|
||||
readelf -h libfoo.so # OS ABI, PIE, NX, RELRO, etc.
|
||||
checksec --file libfoo.so # (peda/pwntools)
|
||||
```
|
||||
3. **List exported symbols & JNI bindings**
|
||||
3. **列出导出符号与 JNI 绑定**
|
||||
```bash
|
||||
readelf -s libfoo.so | grep ' Java_' # dynamic-linked JNI
|
||||
strings libfoo.so | grep -i "RegisterNatives" -n # static-registered JNI
|
||||
```
|
||||
4. **Load in a decompiler** (Ghidra ≥ 11.0, IDA Pro, Binary Ninja, Hopper or Cutter/Rizin) 并运行自动分析。
|
||||
较新的 Ghidra 版本引入了 AArch64 decompiler,能识别 PAC/BTI stubs 和 MTE tags,极大改善了使用 Android 14 NDK 构建的库的分析效果。
|
||||
5. **Decide on static vs dynamic reversing:** 已剥离或混淆的代码通常需要 *instrumentation*(Frida、ptrace/gdbserver、LLDB)。
|
||||
4. **在反编译器中加载** (Ghidra ≥ 11.0, IDA Pro, Binary Ninja, Hopper or Cutter/Rizin) 并运行自动分析。
|
||||
较新的 Ghidra 版本引入了对 AArch64 的反编译器,能够识别 PAC/BTI stubs 和 MTE tags,大幅改善使用 Android 14 NDK 构建的库的分析。
|
||||
5. **决定使用静态还是动态逆向:** 被剥离符号或混淆的代码通常需要*插桩*(Frida, ptrace/gdbserver, LLDB)。
|
||||
|
||||
---
|
||||
|
||||
### Dynamic Instrumentation (Frida ≥ 16)
|
||||
### 动态插桩 (Frida ≥ 16)
|
||||
|
||||
Frida 的 16 系列带来了若干 Android 专用的改进,这些改进在目标使用现代 Clang/LLD 优化时非常有帮助:
|
||||
Frida 16 系列带来了一些针对 Android 的改进,当目标使用现代 Clang/LLD 优化时这些改进很有用:
|
||||
|
||||
* `thumb-relocator` 现在可以 *hook tiny ARM/Thumb functions*,这些函数由 LLD 的激进对齐(`--icf=all`)生成。
|
||||
* 在 Android 上可以枚举并重新绑定 *ELF import slots*,当 inline hooks 被拒绝时,这使得可以按模块进行 `dlopen()`/`dlsym()` 修补。
|
||||
* 修复了 Java hooking,以适配在 Android 14 上使用 `--enable-optimizations` 编译时的 **ART quick-entrypoint**。
|
||||
* `thumb-relocator` 现在可以 hook 由 LLD 的激进对齐(`--icf=all`)生成的小型 ARM/Thumb 函数。
|
||||
* 在 Android 上,枚举并重新绑定 *ELF import slots* 已可行,当内联 hooks 被拒绝时,可对每个模块进行 `dlopen()`/`dlsym()` 修补。
|
||||
* 修复了 Java hooking 针对新的 **ART quick-entrypoint** 的兼容性,该入口在 Android 14 上使用 `--enable-optimizations` 编译的应用中被采用。
|
||||
|
||||
Example: enumerating all functions registered through `RegisterNatives` and dumping their addresses at runtime:
|
||||
```javascript
|
||||
@ -61,27 +61,27 @@ console.log('[+] RegisterNatives on ' + clazz.getName() + ' -> ' + count + ' met
|
||||
});
|
||||
});
|
||||
```
|
||||
Frida 在启用 PAC/BTI 的设备上(Pixel 8/Android 14+)开箱即可工作,只要你使用 frida-server 16.2 或更高版本 —— 早期版本无法定位 inline hooks 的 padding。
|
||||
Frida will work out of the box on PAC/BTI-enabled devices (Pixel 8/Android 14+) as long as you use frida-server 16.2 or later – earlier versions failed to locate padding for inline hooks.
|
||||
|
||||
### Process-local JNI telemetry via preloaded .so (SoTap)
|
||||
|
||||
当完整的 instrumentation 过于繁重或被阻止时,你仍然可以通过在目标进程内预加载一个小型 logger 来获取本地级别的可见性。SoTap 是一个轻量级的 Android native (.so) 库,它记录同一应用进程内其他 JNI (.so) 库的运行时行为(不需要 root)。
|
||||
当完整功能的 instrumentation 过于繁重或被阻止时,你仍然可以通过在目标进程内预加载一个小型 logger 来获得本地级别的可见性。SoTap 是一个轻量级的 Android native (.so) 库,记录同一应用进程内其他 JNI (.so) 库的运行时行为(不需要 root)。
|
||||
|
||||
Key properties:
|
||||
- 在加载它的进程中尽早初始化并观察 JNI/native 交互。
|
||||
- 使用多个可写路径持久化日志,在存储受限时优雅地回退到 Logcat。
|
||||
- 源码可定制:编辑 sotap.c 以扩展/调整记录内容,并按 ABI 重新构建。
|
||||
- 初始化较早,观察加载它的进程内的 JNI/native 交互。
|
||||
- 使用多个可写路径持久化日志,当存储受限时优雅回退到 Logcat。
|
||||
- 源代码可定制:编辑 sotap.c 来扩展/调整要记录的内容,并按 ABI 重新构建。
|
||||
|
||||
Setup (repack the APK):
|
||||
1) 将对应 ABI 的构建放入 APK 中以便加载器可以解析 libsotap.so:
|
||||
1) 将对应 ABI 的构建放入 APK,以便 loader 能解析 libsotap.so:
|
||||
- lib/arm64-v8a/libsotap.so (for arm64)
|
||||
- lib/armeabi-v7a/libsotap.so (for arm32)
|
||||
2) 确保 SoTap 在其他 JNI 库之前加载。尽早注入一次调用(例如,在 Application 子类的 static initializer 或 onCreate 中),以便 logger 先被初始化。Smali 代码示例:
|
||||
2) 确保 SoTap 在其他 JNI 库之前加载。尽早注入一次调用(例如,在 Application 子类的静态初始化器或 onCreate 中),以便 logger 优先初始化。Smali snippet example:
|
||||
```smali
|
||||
const-string v0, "sotap"
|
||||
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
|
||||
```
|
||||
3) 重建/签名/安装,运行应用,然后收集日志。
|
||||
3) 重新构建/签名/安装,运行应用,然后收集日志。
|
||||
|
||||
Log paths (checked in order):
|
||||
```
|
||||
@ -91,31 +91,31 @@ Log paths (checked in order):
|
||||
/sdcard/Download/sotap-%s.log
|
||||
# If all fail: fallback to Logcat only
|
||||
```
|
||||
注意事项与故障排除:
|
||||
- ABI 对齐是必须的。对齐不匹配会抛出 UnsatisfiedLinkError,导致 logger 无法加载。
|
||||
注意事项与故障排查:
|
||||
- ABI 对齐是强制的。不匹配会抛出 UnsatisfiedLinkError,且 logger 无法加载。
|
||||
- 现代 Android 常见存储限制;如果文件写入失败,SoTap 仍会通过 Logcat 输出。
|
||||
- 行为/冗长度(verbosity)可按需定制;在编辑 sotap.c 后请从源码重新构建。
|
||||
- 行为/详细程度可自定义;在编辑 sotap.c 后需从源码重新构建。
|
||||
|
||||
该方法适用于 malware 分析和 JNI 调试,特别是在需要从进程启动阶段观察 native 调用流程且无法使用 root/系统范围 hook 时。
|
||||
该方法适用于恶意软件初筛和 JNI 调试,在需要从进程启动就观察本地调用流但无法使用 root/系统级 hooks 时尤其有用。
|
||||
|
||||
---
|
||||
|
||||
### 值得在 APK 中寻找的近期漏洞
|
||||
### 在 APK 中值得寻找的近期漏洞
|
||||
|
||||
| 年份 | CVE | 受影响的库 | 备注 |
|
||||
| Year | CVE | Affected library | Notes |
|
||||
|------|-----|------------------|-------|
|
||||
|2023|CVE-2023-4863|`libwebp` ≤ 1.3.1|本地代码在解码 WebP 图像时可能触发堆缓冲区溢出。若干 Android 应用捆绑了易受影响的版本。当你在 APK 中看到 `libwebp.so` 时,应检查其版本并尝试利用或修补。| |
|
||||
|2024|Multiple|OpenSSL 3.x series|存在多种内存安全问题和 padding-oracle 漏洞。许多 Flutter 与 ReactNative 包会随附自家的 `libcrypto.so`。|
|
||||
|2023|CVE-2023-4863|`libwebp` ≤ 1.3.1|堆缓冲区溢出,可由解码 WebP 图像的本地代码触发。若干 Android 应用捆绑了易受影响的版本。当在 APK 中看到 `libwebp.so` 时,请检查其版本并尝试利用或修补。| |
|
||||
|2024|Multiple|OpenSSL 3.x series|多项内存安全和 padding-oracle 问题。许多 Flutter & ReactNative 包会自带它们自己的 `libcrypto.so`。|
|
||||
|
||||
当你在 APK 内发现第三方 `.so` 文件时,务必将其哈希与上游通告核对。移动端很少做 SCA (Software Composition Analysis),因此过期的易受影响构建非常普遍。
|
||||
当你在 APK 中发现第三方 `.so` 文件时,务必将其哈希与上游通报进行交叉核对。移动端很少做 SCA (Software Composition Analysis),因此过时且易受攻击的构建非常普遍。
|
||||
|
||||
---
|
||||
|
||||
### 反逆向与加固趋势(Android 13-15)
|
||||
|
||||
* **Pointer Authentication (PAC) & Branch Target Identification (BTI):** Android 14 在支持的 ARMv8.3+ 芯片上在系统库中启用 PAC/BTI。反编译器现在会显示与 PAC 相关的伪指令;用于动态分析时,Frida 会在去除 PAC 后注入 trampolines,但自定义的 trampolines 在必要时应调用 `pacda`/`autibsp`。
|
||||
* **MTE & Scudo hardened allocator:** memory-tagging 是可选的,但许多启用 Play-Integrity 的应用会使用 `-fsanitize=memtag` 构建;可用 `setprop arm64.memtag.dump 1` 加上 `adb shell am start ...` 来捕获 tag fault。
|
||||
* **LLVM Obfuscator (opaque predicates, control-flow flattening):** 商业加壳器(例如 Bangcle、SecNeo)越来越多地保护 *native* 代码,而不仅仅是 Java;在 `.rodata` 中会看到伪造的控制流和加密的字符串 blob。
|
||||
* **Pointer Authentication (PAC) & Branch Target Identification (BTI):** Android 14 在支持的 ARMv8.3+ 硬件上在系统库启用了 PAC/BTI。反编译器现在会显示与 PAC 相关的伪指令;对于动态分析,Frida 在去除 PAC 后注入 trampolines,但你的自定义 trampolines 在必要时应调用 `pacda`/`autibsp`。
|
||||
* **MTE & Scudo hardened allocator:** 内存标记(memory-tagging)是可选的,但许多关注 Play-Integrity 的应用使用 `-fsanitize=memtag` 构建;使用 `setprop arm64.memtag.dump 1` 加上 `adb shell am start ...` 来捕获标记错误。
|
||||
* **LLVM Obfuscator (opaque predicates, control-flow flattening):** 商业 packers(例如 Bangcle、SecNeo)越来越多地保护 *native* 代码,而不仅仅是 Java;在 `.rodata` 中预计会看到伪造的控制流和加密的字符串块。
|
||||
|
||||
---
|
||||
|
||||
@ -123,14 +123,14 @@ Log paths (checked in order):
|
||||
|
||||
- **学习 ARM 汇编:** [Azeria Labs – ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/)
|
||||
- **JNI 与 NDK 文档:** [Oracle JNI Spec](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html) · [Android JNI Tips](https://developer.android.com/training/articles/perf-jni) · [NDK Guides](https://developer.android.com/ndk/guides/)
|
||||
- **调试 Native 库:** [Debug Android Native Libraries Using JEB Decompiler](https://medium.com/@shubhamsonani/how-to-debug-android-native-libraries-using-jeb-decompiler-eec681a22cf3)
|
||||
- **调试本地库:** [Debug Android Native Libraries Using JEB Decompiler](https://medium.com/@shubhamsonani/how-to-debug-android-native-libraries-using-jeb-decompiler-eec681a22cf3)
|
||||
|
||||
### 参考
|
||||
### 参考资料
|
||||
|
||||
- Frida 16.x 更新日志(Android hooking,tiny-function relocation) – [frida.re/news](https://frida.re/news/)
|
||||
- 关于 `libwebp` 溢出的 NVD 咨询 CVE-2023-4863 – [nvd.nist.gov](https://nvd.nist.gov/vuln/detail/CVE-2023-4863)
|
||||
- SoTap: 轻量级的应用内 JNI (.so) 行为记录器 – [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap)
|
||||
- SoTap 发布 – [github.com/RezaArbabBot/SoTap/releases](https://github.com/RezaArbabBot/SoTap/releases)
|
||||
- Frida 16.x 变更日志 (Android hooking, tiny-function relocation) – [frida.re/news](https://frida.re/news/)
|
||||
- 关于 `libwebp` 溢出的 NVD 通报 CVE-2023-4863 – [nvd.nist.gov](https://nvd.nist.gov/vuln/detail/CVE-2023-4863)
|
||||
- SoTap:轻量级应用内 JNI (.so) 行为记录器 – [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap)
|
||||
- SoTap Releases – [github.com/RezaArbabBot/SoTap/releases](https://github.com/RezaArbabBot/SoTap/releases)
|
||||
- 如何使用 SoTap? – [t.me/ForYouTillEnd/13](https://t.me/ForYouTillEnd/13)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -3,15 +3,15 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
有时修改应用代码以访问隐藏信息(例如高度混淆的密码或 flags)会很有用。此时,反编译 apk、修改代码并重新编译可能很有价值。
|
||||
有时修改应用代码以访问隐藏信息(可能是高度混淆的密码或 flags)会很有趣。此时,反编译 apk、修改代码并重新编译可能就很有用。
|
||||
|
||||
**Opcodes 参考:** [http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html](http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html)
|
||||
**Opcodes 参考:** [http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html](http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html)
|
||||
|
||||
## 快速方法
|
||||
|
||||
使用 **Visual Studio Code** 和 [APKLab](https://github.com/APKLab/APKLab) 扩展,你可以 **自动反编译**、修改、**重新编译**、签名并安装应用,而无需执行任何命令。
|
||||
|
||||
另一个极大简化此任务的 **script** 是 [**https://github.com/ax/apk.sh**](https://github.com/ax/apk.sh)
|
||||
另一个大大简化该任务的 **脚本** 是 [**https://github.com/ax/apk.sh**](https://github.com/ax/apk.sh)
|
||||
|
||||
## 反编译 APK
|
||||
|
||||
@ -19,19 +19,19 @@
|
||||
```bash
|
||||
apktool d APP.apk
|
||||
```
|
||||
如果 **apktool** 给你任何错误,尝试[ installing the **latest version**](https://ibotpeaches.github.io/Apktool/install/)
|
||||
如果 **apktool** 给你任何错误,试试[ installing the **latest version**](https://ibotpeaches.github.io/Apktool/install/)
|
||||
|
||||
一些**你应该查看的有趣文件**:
|
||||
一些你应该查看的**有趣的文件**:
|
||||
|
||||
- _res/values/strings.xml_ (以及 res/values/* 中的所有 xml)
|
||||
- _res/values/strings.xml_ (and all xmls inside res/values/*)
|
||||
- _AndroidManifest.xml_
|
||||
- 任何扩展名为 _.sqlite_ 或 _.db_ 的文件
|
||||
- Any file with extension _.sqlite_ or _.db_
|
||||
|
||||
如果 `apktool` 在**解码应用**时有问题,请查看 [https://ibotpeaches.github.io/Apktool/documentation/#framework-files](https://ibotpeaches.github.io/Apktool/documentation/#framework-files) 或尝试使用参数 **`-r`**(不要解码资源)。然后,如果问题出在资源而不是源代码,你就不会遇到这个问题(你也不会反编译这些资源)。
|
||||
如果 `apktool` 在**解码应用**时有问题,请查看 [https://ibotpeaches.github.io/Apktool/documentation/#framework-files](https://ibotpeaches.github.io/Apktool/documentation/#framework-files) 或尝试使用参数 **`-r`**(不解码资源)。这样,如果问题出在资源而不是源代码,你就不会遇到该问题(但也不会反编译资源)。
|
||||
|
||||
## 更改 smali 代码
|
||||
|
||||
你可以**更改****指令**、修改某些变量的**值**或**添加**新的指令。我使用 [**VS Code**](https://code.visualstudio.com) 来修改 Smali 代码,安装 **smalise extension** 后,编辑器会告诉你是否有任何**指令不正确**。\
|
||||
你可以**更改**指令、改变某些变量的**值**或**添加**新指令。我使用 [**VS Code**](https://code.visualstudio.com) 修改 Smali 代码,安装 **smalise extension** 后编辑器会告诉你是否有任何**指令不正确**。\
|
||||
一些**示例**可以在这里找到:
|
||||
|
||||
- [Smali changes examples](smali-changes.md)
|
||||
@ -41,34 +41,34 @@ Or you can [**check below some Smali changes explained**](smali-changes.md#modif
|
||||
|
||||
## 重新编译 APK
|
||||
|
||||
修改代码后,你可以使用以下方式**重新编译**代码:
|
||||
修改代码后,你可以使用以下命令**重新编译**代码:
|
||||
```bash
|
||||
apktool b . #In the folder generated when you decompiled the application
|
||||
```
|
||||
它会在 _**dist**_ 文件夹中 **compile** 新的 APK。
|
||||
它会 **编译** 新的 APK,且在 _**dist**_ 文件夹**内部**。
|
||||
|
||||
如果 **apktool** 抛出 **error**,尝试[ installing the **latest version**](https://ibotpeaches.github.io/Apktool/install/)
|
||||
如果 **apktool** 抛出 **错误**,请尝试[ installing the **latest version**](https://ibotpeaches.github.io/Apktool/install/)
|
||||
|
||||
### **为新的 APK 签名**
|
||||
|
||||
然后,你需要 **generate a key**(会要求你输入密码以及一些可以随机填写的信息):
|
||||
然后,你需要 **生成密钥**(系统会要求你输入密码以及一些可以随机填写的信息):
|
||||
```bash
|
||||
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
|
||||
```
|
||||
最后,**sign** 新的 APK:
|
||||
最后,为新的 APK **签名**:
|
||||
```bash
|
||||
jarsigner -keystore key.jks path/to/dist/* <your-alias>
|
||||
```
|
||||
### 优化新应用
|
||||
|
||||
**zipalign** 是一个归档对齐工具,可为 Android 应用 (APK) 文件提供重要的优化。 [更多信息](https://developer.android.com/studio/command-line/zipalign).
|
||||
**zipalign** 是一个归档对齐工具,为 Android 应用 (APK) 文件 提供重要的优化。 [更多信息请见](https://developer.android.com/studio/command-line/zipalign).
|
||||
```bash
|
||||
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
|
||||
zipalign -v 4 infile.apk
|
||||
```
|
||||
### **Sign the new APK (again?)**
|
||||
### **为新的 APK 重新签名(又一次?)**
|
||||
|
||||
如果你 **更愿意** 使用 [**apksigner**](https://developer.android.com/studio/command-line/) 而不是 jarsigner,**你应该对 apk 进行签名**,在应用 **使用 zipaling 的优化** 之后。但请注意,你只需要使用 jarsigner(在 zipalign 之前)或使用 aspsigner(在 zipaling 之后)**对应用签名一次**。
|
||||
如果你 **更喜欢** 使用 [**apksigner**](https://developer.android.com/studio/command-line/) 而不是 jarsigner,**应在使用 zipaling 进行优化后对 APK 进行签名**。但请注意,你只需使用 jarsigner(在 zipalign 之前)或使用 aspsigner(在 zipaling 之后)**仅对应用签名一次**。
|
||||
```bash
|
||||
apksigner sign --ks key.jks ./dist/mycompiled.apk
|
||||
```
|
||||
@ -80,7 +80,7 @@ public static void printHelloWorld() {
|
||||
System.out.println("Hello World")
|
||||
}
|
||||
```
|
||||
Smali 代码如下:
|
||||
Smali 代码将是:
|
||||
```java
|
||||
.method public static printHelloWorld()V
|
||||
.registers 2
|
||||
@ -94,9 +94,9 @@ Smali 指令集可在 [here](https://source.android.com/devices/tech/dalvik/dalv
|
||||
|
||||
### 轻微更改
|
||||
|
||||
### 修改函数内部变量的初始值
|
||||
### 修改函数内变量的初始值
|
||||
|
||||
有些变量在函数开始处使用操作码 _const_ 定义,你可以修改它们的值,或者定义新的变量:
|
||||
有些变量在函数开头使用操作码 _const_ 定义,您可以修改它们的值,或定义新的变量:
|
||||
```bash
|
||||
#Number
|
||||
const v9, 0xf4240
|
||||
@ -127,7 +127,7 @@ iput v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save v0 inside
|
||||
if-ne v0, v9, :goto_6 #If not equals, go to: :goto_6
|
||||
goto :goto_6 #Always go to: :goto_6
|
||||
```
|
||||
### 重大更改
|
||||
### 更大的改动
|
||||
|
||||
### 日志记录
|
||||
```bash
|
||||
@ -138,19 +138,19 @@ move-result-object v1 #Move to v1
|
||||
const-string v5, "wins" #Save "win" inside v5
|
||||
invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I #Logging "Wins: <num>"
|
||||
```
|
||||
建议:
|
||||
Recommendations:
|
||||
|
||||
- 如果你打算在函数内部使用已声明的变量 (declared v0,v1,v2...),将这些行放在 _.local <number>_ 和变量声明 (_const v0, 0x1_) 之间
|
||||
- 如果你想把日志代码放在函数代码的中间:
|
||||
- 把已声明变量的数量加 2:例如:从 _.locals 10_ 到 _.locals 12_
|
||||
- 新变量应为已声明变量之后的连续编号(在此例中应为 _v10_ 和 _v11_,记住编号从 v0 开始)。
|
||||
- 更改日志函数的代码,使用 _v10_ 和 _v11_ 替换 _v5_ 和 _v1_。
|
||||
- 如果你打算在函数内部使用已声明的变量(声明 v0,v1,v2...),将这些行放在 _.local <number>_ 和变量声明 (_const v0, 0x1_) 之间。
|
||||
- 如果你想把日志代码插入到函数代码的中间:
|
||||
- 在已声明变量的数量上加 2:例如:从 _.locals 10_ 到 _.locals 12_
|
||||
- 新的变量应该是已声明变量之后的下一个编号(在本例中应为 _v10_ 和 _v11_,记住编号从 v0 开始)。
|
||||
- 修改日志函数的代码,使用 _v10_ 和 _v11_ 替换 _v5_ 和 _v1_。
|
||||
|
||||
### Toast 提示
|
||||
|
||||
记得在函数开头将 _.locals_ 的数量增加 3。
|
||||
请记得在函数开头将 _.locals_ 的数量增加 3。
|
||||
|
||||
此代码准备插入到函数的 **中间**(**根据需要更改变量的数量**)。它会获取 **this.o 的值**,将其 **转换** 为 **String**,然后用该值显示一个 **toast**。
|
||||
该代码已准备好插入到函数的**中间**(必要时**修改**变量**数量**)。它会取 **this.o** 的**值**,将其**转换**为 **String**,然后用该值**显示**一个 **toast**。
|
||||
```bash
|
||||
const/4 v10, 0x1
|
||||
const/4 v11, 0x1
|
||||
@ -164,7 +164,7 @@ invoke-virtual {v12}, Landroid/widget/Toast;->show()V
|
||||
```
|
||||
### 在启动时加载本地库 (System.loadLibrary)
|
||||
|
||||
有时需要预先加载本地库,以便在其他 JNI 库之前完成初始化(例如,用于启用进程本地的遥测/日志记录)。你可以在静态初始化器或在 Application.onCreate() 的早期注入对 System.loadLibrary() 的调用。下面是用于静态类初始化器 (<clinit>) 的 smali 示例:
|
||||
有时你需要预先加载本地库,以便它在其他 JNI 库之前初始化(例如,用于启用进程级的遥测/日志)。你可以在静态初始化器或在 Application.onCreate() 早期注入对 System.loadLibrary() 的调用。下面是用于静态类初始化器 (<clinit>) 的 smali 示例:
|
||||
```smali
|
||||
.class public Lcom/example/App;
|
||||
.super Landroid/app/Application;
|
||||
@ -190,10 +190,10 @@ return-void
|
||||
```
|
||||
注意:
|
||||
- 确保库的正确 ABI 变体存在于 lib/<abi>/ 下(例如 arm64-v8a/armeabi-v7a),以避免 UnsatisfiedLinkError。
|
||||
- 尽早加载(class static initializer)可以保证 native logger 能观察到后续的 JNI 活动。
|
||||
- 尽早加载(class static initializer)可确保 native logger 能观察到随后的 JNI 活动。
|
||||
|
||||
## 参考
|
||||
## 参考资料
|
||||
|
||||
- SoTap:轻量级应用内 JNI (.so) 行为 logger – [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap)
|
||||
- SoTap: 轻量级的应用内 JNI (.so) 行为记录器 – [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user