From 4fea61426864e8d8c9747d5f2b51f3329145ce25 Mon Sep 17 00:00:00 2001 From: Translator Date: Thu, 4 Sep 2025 02:38:19 +0000 Subject: [PATCH] Translated ['src/generic-methodologies-and-resources/basic-forensic-meth --- .../malware-analysis.md | 101 +++++++++------- .../reversing-native-libraries.md | 109 +++++++++++------ .../android-app-pentesting/smali-changes.md | 111 ++++++++++++------ 3 files changed, 205 insertions(+), 116 deletions(-) diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md index fb35799e5..b56a5802d 100644 --- a/src/generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md @@ -2,7 +2,7 @@ {{#include ../../banners/hacktricks-training.md}} -## 取证备忘单 +## 取证速查表 [https://www.jaiminton.com/cheatsheet/DFIR/#](https://www.jaiminton.com/cheatsheet/DFIR/) @@ -24,8 +24,8 @@ sudo apt-get install -y yara ``` #### 准备规则 -使用此脚本从github下载并合并所有yara恶意软件规则: [https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9](https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9)\ -创建_**rules**_目录并执行它。这将创建一个名为_**malware_rules.yar**_的文件,其中包含所有恶意软件的yara规则。 +使用此脚本从 github 下载并合并所有 yara malware rules: [https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9](https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9)\ +创建 _**rules**_ 目录并执行它。 这将创建一个名为 _**malware_rules.yar**_ 的文件,包含所有 yara malware 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: 检查恶意软件并创建规则 +#### YaraGen: 检查 malware 并创建 yara rules -您可以使用工具 [**YaraGen**](https://github.com/Neo23x0/yarGen) 从二进制文件生成 yara 规则。查看这些教程: [**第 1 部分**](https://www.nextron-systems.com/2015/02/16/write-simple-sound-yara-rules/), [**第 2 部分**](https://www.nextron-systems.com/2015/10/17/how-to-write-simple-but-sound-yara-rules-part-2/), [**第 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) 从 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/) ```bash python3 yarGen.py --update python3.exe yarGen.py --excludegood -m ../../mals/ @@ -57,25 +57,25 @@ clamscan folderpath #Scan the whole folder ``` ### [Capa](https://github.com/mandiant/capa) -**Capa** 检测可执行文件中的潜在恶意 **能力**:PE、ELF、.NET。因此,它会找到诸如 Att\&ck 策略或可疑能力,例如: +**Capa** 在可执行文件:PE、ELF、.NET 中检测潜在恶意的 **能力**。因此它会发现诸如 Att\&ck tactics 的条目,或以下可疑能力: -- 检查 OutputDebugString 错误 -- 作为服务运行 -- 创建进程 +- check for OutputDebugString error +- run as a service +- create process -在 [**Github repo**](https://github.com/mandiant/capa) 中获取它。 +可在 [**Github repo**](https://github.com/mandiant/capa) 获取。 ### IOCs -IOC 代表妥协指标。IOC 是一组 **条件,用于识别** 一些潜在的不需要的软件或确认的 **恶意软件**。蓝队使用这种定义来 **搜索这种恶意文件** 在他们的 **系统** 和 **网络** 中。\ -共享这些定义非常有用,因为当恶意软件在计算机中被识别并为该恶意软件创建 IOC 时,其他蓝队可以使用它更快地识别恶意软件。 +IOC 表示入侵指标。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) 等工具来 **搜索设备中的定义 IOC**。 +用于创建或修改 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的恶意软件扫描器,发布于GNU GPLv2许可证,旨在应对共享托管环境中面临的威胁。它使用来自网络边缘入侵检测系统的威胁数据,提取正在攻击中积极使用的恶意软件,并生成检测签名。此外,威胁数据还来自用户提交的LMD结账功能和恶意软件社区资源。 +[**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。 ### rkhunter -像[**rkhunter**](http://rkhunter.sourceforge.net)这样的工具可以用来检查文件系统中可能存在的**rootkits**和恶意软件。 +像 [**rkhunter**](http://rkhunter.sourceforge.net) 这样的工具可用于检查文件系统以查找可能的 **rootkits** 和 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) 是一个工具,会尝试使用不同的技术在可执行文件中查找混淆的字符串。 ### PEpper -[PEpper](https://github.com/Th3Hurrican3/PEpper) 检查可执行文件中的一些基本内容(如二进制数据、熵、URLs 和 IPs,以及一些 yara 规则)。 +[PEpper ](https://github.com/Th3Hurrican3/PEpper) 会检查可执行文件中的一些基本内容(二进制数据、熵、URLs 和 IPs、一些 yara 规则)。 ### PEstudio -[PEstudio](https://www.winitor.com/download) 是一个工具,可以获取 Windows 可执行文件的信息,如导入、导出、头部信息,同时还会检查病毒总数并找到潜在的 Att\&ck 技术。 +[PEstudio](https://www.winitor.com/download) 是一个可以获取 Windows 可执行文件信息的工具,例如 imports、exports、headers,同时也会检查 VirusTotal 并发现潜在的 Att\&ck 技术。 ### Detect It Easy(DiE) -[**DiE**](https://github.com/horsicq/Detect-It-Easy/) 是一个工具,用于检测文件是否 **加密**,并找到 **打包器**。 +[**DiE**](https://github.com/horsicq/Detect-It-Easy/) 是一个用于检测文件是否 **encrypted** 并查找 **packers** 的工具。 ### NeoPI -[**NeoPI**](https://github.com/CiscoCXSecurity/NeoPI) 是一个 Python 脚本,使用多种 **统计方法** 来检测文本/脚本文件中的 **混淆** 和 **加密** 内容。NeoPI 的预期目的是帮助 **检测隐藏的 web shell 代码**。 +[**NeoPI** ](https://github.com/CiscoCXSecurity/NeoPI) 是一个 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) 尽力检测 **混淆**/**可疑代码** 以及使用 **PHP** 函数的文件,这些函数通常用于 **恶意软件**/webshells。 +[**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** 有关联。 ```bash #Get signer codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier" @@ -139,27 +139,39 @@ spctl --assess --verbose /Applications/Safari.app ``` ## 检测技术 -### 文件堆叠 +### File Stacking -如果你知道某个包含**文件**的文件夹**最后更新于某个日期**。**检查**所有**文件**在**web 服务器**中的**创建和修改日期**,如果有任何日期是**可疑的**,请检查该文件。 +如果你知道某个包含 web 服务器 **文件** 的文件夹在某个 **日期被最后更新**。请**检查**该 web 服务器中所有 **文件** 的创建和修改 **日期**,如果有任何日期 **可疑**,就检查那个文件。 -### 基线 +### Baselines -如果一个文件夹的文件**不应该被修改**,你可以计算该文件夹**原始文件**的**哈希**并与**当前**文件进行**比较**。任何被修改的文件都将是**可疑的**。 +如果一个文件夹的文件 **不应该被修改**,你可以计算该文件夹原始文件的 **hash** 并将其与当前文件 **比较**。任何被修改的文件都应视为 **可疑**。 -### 统计分析 +### Statistical Analysis -当信息保存在日志中时,你可以**检查统计数据,比如每个web服务器的文件被访问的次数,因为web shell可能是其中之一**。 +当信息记录在日志中时,你可以**检查统计信息**,例如每个 web 服务器文件被访问的次数,因为 web shell 可能是被访问次数最多的之一。 --- -## 反混淆动态控制流 (JMP/CALL RAX 调度器) +### Android in-app native telemetry (no root) -现代恶意软件家族严重滥用控制流图 (CFG) 混淆:它们不是直接跳转/调用,而是在运行时计算目标并执行`jmp rax`或`call rax`。一个小型*调度器*(通常九条指令)根据CPU的`ZF`/`CF`标志设置最终目标,完全破坏静态CFG恢复。 +在 Android 上,你可以通过在其他 JNI 库初始化之前预加载一个小型 logger 库,在目标应用进程内对 native 代码进行 instrument。这样可以在不依赖系统范围 hook 或 root 的情况下,尽早观察 native 行为。一种常用方法是 SoTap:将 libsotap.so 放到 APK 的对应 ABI 路径下,并尽早注入一个 System.loadLibrary("sotap") 调用(例如静态初始化器或 Application.onCreate),然后从内部/外部路径收集日志,或使用 Logcat 作为回退。 -该技术 - 由SLOW#TEMPEST加载器展示 - 可以通过一个仅依赖于IDAPython和Unicorn CPU模拟器的三步工作流程来击败。 +查看 Android native reversing 页面以获取设置细节和日志路径: -### 1. 定位每个间接跳转/调用 +{{#ref}} +../../../mobile-pentesting/android-app-pentesting/reversing-native-libraries.md +{{#endref}} + +--- + +## Deobfuscating Dynamic Control-Flow (JMP/CALL RAX Dispatchers) + +现代恶意软件家族大量滥用 Control-Flow Graph (CFG) 混淆:它们不是直接跳转/调用,而是在运行时计算目标并执行 `jmp rax` 或 `call rax`。一个小的 *dispatcher*(通常九条指令)会根据 CPU 的 `ZF`/`CF` flags 设置最终目标,这会完全破坏静态 CFG 恢复。 + +该技术 —— 由 SLOW#TEMPEST loader 展示 —— 可以通过一个仅依赖 IDAPython 和 Unicorn CPU emulator 的三步工作流来破解。 + +### 1. Locate every indirect jump / call ```python import idautils, idc @@ -168,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. 提取调度程序字节码 +### 2. 提取 dispatcher 字节码 ```python import idc @@ -183,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 * @@ -201,7 +213,7 @@ return mu.reg_read(UC_X86_REG_RAX) ``` 运行 `run(code,0,0)` 和 `run(code,1,1)` 以获取 *false* 和 *true* 分支目标。 -### 4. 修补直接跳转 / 调用 +### 4. 将其修补回直接 jump / call ```python import struct, ida_bytes @@ -210,27 +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(' cat lib/arm64-v8a/libfoo.so" > libfoo.so -# 或从 APK(zip) +# Or from the APK (zip) unzip -j target.apk "lib/*/libfoo.so" -d extracted_libs/ ``` -2. **识别架构和保护** +2. **Identify architecture & protections** ```bash -file libfoo.so # arm64 或 arm32 / x86 -readelf -h libfoo.so # OS ABI, PIE, NX, RELRO 等 +file libfoo.so # arm64 or arm32 / x86 +readelf -h libfoo.so # OS ABI, PIE, NX, RELRO, etc. checksec --file libfoo.so # (peda/pwntools) ``` -3. **列出导出符号和 JNI 绑定** +3. **List exported symbols & JNI bindings** ```bash -readelf -s libfoo.so | grep ' Java_' # 动态链接的 JNI -strings libfoo.so | grep -i "RegisterNatives" -n # 静态注册的 JNI +readelf -s libfoo.so | grep ' Java_' # dynamic-linked JNI +strings libfoo.so | grep -i "RegisterNatives" -n # static-registered JNI ``` -4. **加载到反编译器中**(Ghidra ≥ 11.0, IDA Pro, Binary Ninja, Hopper 或 Cutter/Rizin)并运行自动分析。更新的 Ghidra 版本引入了一个 AArch64 反编译器,能够识别 PAC/BTI 存根和 MTE 标签,极大地改善了对使用 Android 14 NDK 构建的库的分析。 -5. **决定静态反向工程还是动态反向工程:** 被剥离和混淆的代码通常需要 *插桩*(Frida, ptrace/gdbserver, LLDB)。 +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)。 --- -### 动态插桩(Frida ≥ 16) +### Dynamic Instrumentation (Frida ≥ 16) -Frida 的 16 系列带来了几个 Android 特定的改进,帮助在目标使用现代 Clang/LLD 优化时: +Frida 的 16 系列带来了若干 Android 专用的改进,这些改进在目标使用现代 Clang/LLD 优化时非常有帮助: -* `thumb-relocator` 现在可以 *挂钩由 LLD 的激进对齐(`--icf=all`)生成的小型 ARM/Thumb 函数*。 -* 枚举和重新绑定 *ELF 导入槽* 在 Android 上有效,使得在内联钩子被拒绝时能够进行按模块的 `dlopen()`/`dlsym()` 修补。 -* Java 钩子已针对在 Android 14 上使用 `--enable-optimizations` 编译的应用程序的新 **ART 快速入口点** 进行了修复。 +* `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**。 -示例:枚举通过 `RegisterNatives` 注册的所有函数并在运行时转储它们的地址: +Example: enumerating all functions registered through `RegisterNatives` and dumping their addresses at runtime: ```javascript Java.perform(function () { var Runtime = Java.use('java.lang.Runtime'); @@ -58,38 +61,76 @@ console.log('[+] RegisterNatives on ' + clazz.getName() + ' -> ' + count + ' met }); }); ``` -Frida将在启用PAC/BTI的设备(Pixel 8/Android 14+)上开箱即用,只要使用frida-server 16.2或更高版本——早期版本无法找到内联钩子的填充。 citeturn5search2turn5search0 +Frida 在启用 PAC/BTI 的设备上(Pixel 8/Android 14+)开箱即可工作,只要你使用 frida-server 16.2 或更高版本 —— 早期版本无法定位 inline hooks 的 padding。 + +### Process-local JNI telemetry via preloaded .so (SoTap) + +当完整的 instrumentation 过于繁重或被阻止时,你仍然可以通过在目标进程内预加载一个小型 logger 来获取本地级别的可见性。SoTap 是一个轻量级的 Android native (.so) 库,它记录同一应用进程内其他 JNI (.so) 库的运行时行为(不需要 root)。 + +Key properties: +- 在加载它的进程中尽早初始化并观察 JNI/native 交互。 +- 使用多个可写路径持久化日志,在存储受限时优雅地回退到 Logcat。 +- 源码可定制:编辑 sotap.c 以扩展/调整记录内容,并按 ABI 重新构建。 + +Setup (repack the APK): +1) 将对应 ABI 的构建放入 APK 中以便加载器可以解析 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 代码示例: +```smali +const-string v0, "sotap" +invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V +``` +3) 重建/签名/安装,运行应用,然后收集日志。 + +Log paths (checked in order): +``` +/data/user/0/%s/files/sotap.log +/data/data/%s/files/sotap.log +/sdcard/Android/data/%s/files/sotap.log +/sdcard/Download/sotap-%s.log +# If all fail: fallback to Logcat only +``` +注意事项与故障排除: +- ABI 对齐是必须的。对齐不匹配会抛出 UnsatisfiedLinkError,导致 logger 无法加载。 +- 现代 Android 常见存储限制;如果文件写入失败,SoTap 仍会通过 Logcat 输出。 +- 行为/冗长度(verbosity)可按需定制;在编辑 sotap.c 后请从源码重新构建。 + +该方法适用于 malware 分析和 JNI 调试,特别是在需要从进程启动阶段观察 native 调用流程且无法使用 root/系统范围 hook 时。 --- -### 最近值得在APK中寻找的漏洞 +### 值得在 APK 中寻找的近期漏洞 | 年份 | CVE | 受影响的库 | 备注 | |------|-----|------------------|-------| -|2023|CVE-2023-4863|`libwebp` ≤ 1.3.1|从解码WebP图像的本地代码可达的堆缓冲区溢出。多个Android应用程序捆绑了易受攻击的版本。当你在APK中看到`libwebp.so`时,检查其版本并尝试利用或修补。| citeturn2search0| -|2024|多个|OpenSSL 3.x系列|多个内存安全和填充预言机问题。许多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(软件组成分析)在移动设备上不常见,因此过时的易受攻击构建普遍存在。 +当你在 APK 内发现第三方 `.so` 文件时,务必将其哈希与上游通告核对。移动端很少做 SCA (Software Composition Analysis),因此过期的易受影响构建非常普遍。 --- ### 反逆向与加固趋势(Android 13-15) -* **指针认证(PAC)和分支目标识别(BTI):** Android 14在支持的ARMv8.3+硅片上启用PAC/BTI。反编译器现在显示与PAC相关的伪指令;对于动态分析,Frida在去除PAC后注入跳板,但你的自定义跳板应在必要时调用`pacda`/`autibsp`。 -* **MTE和Scudo加固分配器:** 内存标记是可选的,但许多Play-Integrity感知的应用程序使用`-fsanitize=memtag`构建;使用`setprop arm64.memtag.dump 1`加上`adb shell am start ...`来捕获标记故障。 -* **LLVM混淆器(不透明谓词,控制流扁平化):** 商业打包工具(例如Bangcle,SecNeo)越来越多地保护*本地*代码,而不仅仅是Java;预计在`.rodata`中会出现虚假的控制流和加密字符串块。 +* **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。 --- ### 资源 -- **学习ARM汇编:** [Azeria Labs – ARM汇编基础](https://azeria-labs.com/writing-arm-assembly-part-1/) -- **JNI和NDK文档:** [Oracle JNI规范](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html) · [Android JNI技巧](https://developer.android.com/training/articles/perf-jni) · [NDK指南](https://developer.android.com/ndk/guides/) -- **调试本地库:** [使用JEB反编译器调试Android本地库](https://medium.com/@shubhamsonani/how-to-debug-android-native-libraries-using-jeb-decompiler-eec681a22cf3) +- **学习 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) ### 参考 -- Frida 16.x变更日志(Android钩子,微型函数重定位) – [frida.re/news](https://frida.re/news/) citeturn5search0 -- `libwebp`溢出CVE-2023-4863的NVD公告 – [nvd.nist.gov](https://nvd.nist.gov/vuln/detail/CVE-2023-4863) citeturn2search0 +- 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) +- 如何使用 SoTap? – [t.me/ForYouTillEnd/13](https://t.me/ForYouTillEnd/13) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/mobile-pentesting/android-app-pentesting/smali-changes.md b/src/mobile-pentesting/android-app-pentesting/smali-changes.md index e04aae77a..0036ef924 100644 --- a/src/mobile-pentesting/android-app-pentesting/smali-changes.md +++ b/src/mobile-pentesting/android-app-pentesting/smali-changes.md @@ -1,85 +1,86 @@ -# Smali - 反编译/\[修改]/编译 +# Smali - 反编译/[修改]/编译 {{#include ../../banners/hacktricks-training.md}} -有时修改应用程序代码以访问隐藏信息(可能是经过良好混淆的密码或标志)是很有趣的。然后,反编译apk,修改代码并重新编译可能会很有趣。 -**操作码参考:** [http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html](http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html) +有时修改应用代码以访问隐藏信息(例如高度混淆的密码或 flags)会很有用。此时,反编译 apk、修改代码并重新编译可能很有价值。 + +**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) 扩展,您可以 **自动反编译**、修改、**重新编译**、签名并安装应用程序,而无需执行任何命令。 +使用 **Visual Studio Code** 和 [APKLab](https://github.com/APKLab/APKLab) 扩展,你可以 **自动反编译**、修改、**重新编译**、签名并安装应用,而无需执行任何命令。 -另一个大大简化此任务的 **脚本** 是 [**https://github.com/ax/apk.sh**](https://github.com/ax/apk.sh) +另一个极大简化此任务的 **script** 是 [**https://github.com/ax/apk.sh**](https://github.com/ax/apk.sh) -## 反编译APK +## 反编译 APK -使用APKTool,您可以访问 **smali代码和资源**: +使用 APKTool 可以访问 **smali 代码和资源**: ```bash apktool d APP.apk ``` -如果 **apktool** 给你任何错误,尝试[安装 **最新版本**](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_ (以及 res/values/* 中的所有 xml) - _AndroidManifest.xml_ - 任何扩展名为 _.sqlite_ 或 _.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 扩展**,编辑器会告诉你是否有任何 **指令不正确**。\ -一些 **示例** 可以在这里找到: +你可以**更改****指令**、修改某些变量的**值**或**添加**新的指令。我使用 [**VS Code**](https://code.visualstudio.com) 来修改 Smali 代码,安装 **smalise extension** 后,编辑器会告诉你是否有任何**指令不正确**。\ +一些**示例**可以在这里找到: -- [Smali 更改示例](smali-changes.md) +- [Smali changes examples](smali-changes.md) - [Google CTF 2018 - Shall We Play a Game?](google-ctf-2018-shall-we-play-a-game.md) -或者你可以 [**查看下面一些 Smali 更改的解释**](smali-changes.md#modifying-smali)。 +Or you can [**check below some Smali changes explained**](smali-changes.md#modifying-smali). ## 重新编译 APK -在修改代码后,你可以使用 **重新编译** 代码: +修改代码后,你可以使用以下方式**重新编译**代码: ```bash apktool b . #In the folder generated when you decompiled the application ``` -它将**编译**新的APK**在**_**dist**_文件夹中。 +它会在 _**dist**_ 文件夹中 **compile** 新的 APK。 -如果**apktool**抛出**错误**,请尝试[安装**最新版本**](https://ibotpeaches.github.io/Apktool/install/) +如果 **apktool** 抛出 **error**,尝试[ installing the **latest version**](https://ibotpeaches.github.io/Apktool/install/) -### **签署新的APK** +### **为新的 APK 签名** -然后,您需要**生成一个密钥**(系统会要求您输入密码和一些您可以随机填写的信息): +然后,你需要 **generate a key**(会要求你输入密码以及一些可以随机填写的信息): ```bash keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias ``` -最后,**签名**新的APK: +最后,**sign** 新的 APK: ```bash jarsigner -keystore key.jks path/to/dist/* ``` -### 优化新应用程序 +### 优化新应用 -**zipalign** 是一个归档对齐工具,为 Android 应用程序 (APK) 文件提供重要的优化。[More information here](https://developer.android.com/studio/command-line/zipalign). +**zipalign** 是一个归档对齐工具,可为 Android 应用 (APK) 文件提供重要的优化。 [更多信息](https://developer.android.com/studio/command-line/zipalign). ```bash zipalign [-f] [-v] infile.apk outfile.apk zipalign -v 4 infile.apk ``` -### **再次签署新的APK(再一次?)** +### **Sign the new APK (again?)** -如果您**更喜欢**使用 [**apksigner**](https://developer.android.com/studio/command-line/) 而不是 jarsigner,**您应该在应用** zipalign **优化后签署apk**。但请注意,您只需**使用 jarsigner 签署应用一次**(在 zipalign 之前)或使用 aspsigner(在 zipalign 之后)。 +如果你 **更愿意** 使用 [**apksigner**](https://developer.android.com/studio/command-line/) 而不是 jarsigner,**你应该对 apk 进行签名**,在应用 **使用 zipaling 的优化** 之后。但请注意,你只需要使用 jarsigner(在 zipalign 之前)或使用 aspsigner(在 zipaling 之后)**对应用签名一次**。 ```bash apksigner sign --ks key.jks ./dist/mycompiled.apk ``` ## 修改 Smali -对于以下 Hello World Java 代码: +对于下面的 Hello World Java 代码: ```java public static void printHelloWorld() { System.out.println("Hello World") } ``` -Smali 代码将是: +Smali 代码如下: ```java .method public static printHelloWorld()V .registers 2 @@ -89,13 +90,13 @@ invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V return-void .end method ``` -Smali 指令集可在 [这里](https://source.android.com/devices/tech/dalvik/dalvik-bytecode#instructions) 获取。 +Smali 指令集可在 [here](https://source.android.com/devices/tech/dalvik/dalvik-bytecode#instructions). ### 轻微更改 ### 修改函数内部变量的初始值 -某些变量在函数开始时使用操作码 _const_ 定义,您可以修改其值,或者可以定义新的值: +有些变量在函数开始处使用操作码 _const_ 定义,你可以修改它们的值,或者定义新的变量: ```bash #Number const v9, 0xf4240 @@ -126,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 @@ -139,17 +140,17 @@ invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/Strin ``` 建议: -- 如果您打算在函数内部使用声明的变量(声明为 v0, v1, v2...),请将这些行放在 _.local \_ 和变量声明 (_const v0, 0x1_) 之间。 -- 如果您想在函数的代码中间放置日志记录代码: - - 将声明的变量数量加 2:例如,从 _.locals 10_ 到 _.locals 12_。 - - 新变量应为已声明变量的下一个数字(在此示例中应为 _v10_ 和 _v11_,请记住它从 v0 开始)。 - - 更改日志记录函数的代码,并使用 _v10_ 和 _v11_ 代替 _v5_ 和 _v1_。 +- 如果你打算在函数内部使用已声明的变量 (declared v0,v1,v2...),将这些行放在 _.local _ 和变量声明 (_const v0, 0x1_) 之间 +- 如果你想把日志代码放在函数代码的中间: +- 把已声明变量的数量加 2:例如:从 _.locals 10_ 到 _.locals 12_ +- 新变量应为已声明变量之后的连续编号(在此例中应为 _v10_ 和 _v11_,记住编号从 v0 开始)。 +- 更改日志函数的代码,使用 _v10_ 和 _v11_ 替换 _v5_ 和 _v1_。 -### Toasting +### Toast 提示 -请记得在函数开始时将 _.locals 的数量加 3。 +记得在函数开头将 _.locals_ 的数量增加 3。 -此代码准备插入到 **函数的中间**(**根据需要更改** **变量** 的 **数量**)。它将获取 **this.o** 的 **值**,**转换** 为 **String**,然后 **制作** 一个 **toast** 以显示其值。 +此代码准备插入到函数的 **中间**(**根据需要更改变量的数量**)。它会获取 **this.o 的值**,将其 **转换** 为 **String**,然后用该值显示一个 **toast**。 ```bash const/4 v10, 0x1 const/4 v11, 0x1 @@ -161,4 +162,38 @@ invoke-static {p0, v11, v12}, Landroid/widget/Toast;->makeText(Landroid/content/ move-result-object v12 invoke-virtual {v12}, Landroid/widget/Toast;->show()V ``` +### 在启动时加载本地库 (System.loadLibrary) + +有时需要预先加载本地库,以便在其他 JNI 库之前完成初始化(例如,用于启用进程本地的遥测/日志记录)。你可以在静态初始化器或在 Application.onCreate() 的早期注入对 System.loadLibrary() 的调用。下面是用于静态类初始化器 () 的 smali 示例: +```smali +.class public Lcom/example/App; +.super Landroid/app/Application; + +.method static constructor ()V +.registers 1 +const-string v0, "sotap" # library name without lib...so prefix +invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V +return-void +.end method +``` +或者,将相同的两条指令放在你的 Application.onCreate() 开始处,以确保该库尽早加载: +```smali +.method public onCreate()V +.locals 1 + +const-string v0, "sotap" +invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V + +invoke-super {p0}, Landroid/app/Application;->onCreate()V +return-void +.end method +``` +注意: +- 确保库的正确 ABI 变体存在于 lib// 下(例如 arm64-v8a/armeabi-v7a),以避免 UnsatisfiedLinkError。 +- 尽早加载(class static initializer)可以保证 native logger 能观察到后续的 JNI 活动。 + +## 参考 + +- SoTap:轻量级应用内 JNI (.so) 行为 logger – [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap) + {{#include ../../banners/hacktricks-training.md}}