oriori1703/sigmatcher
GitHub: oriori1703/sigmatcher
一个基于特征签名的 Java 类与方法跨版本自动匹配工具,用于 Android 逆向工程中持续追踪代码元素。
Stars: 12 | Forks: 5
# sigmatcher
[](https://pypi.org/project/sigmatcher)
[](https://pypi.org/project/sigmatcher)
Sigmatcher 是一个强大的工具,旨在自动化匹配应用程序不同版本间的 Java 类和方法的过程。
它利用 smali(反汇编的 Java 代码)上的签名来识别和关联代码元素,使其成为长期逆向工程项目中极具价值的资源。
## 目录
- [安装说明](#installation)
- [快速上手](#quick-usage)
- [创建签名文件](#creating-signature-files)
- [签名文件 JSON Schema](#signature-file-json-schema)
- [签名文件的结构](#structure-of-a-signature-file)
- [在签名中使用宏](#using-macros-in-signatures)
- [许可证](#license)
## 安装说明
在安装 `sigmatcher` 之前,请确保您已安装以下前置条件:
- `ripgrep`:一个命令行搜索工具,用于在当前目录中递归搜索正则表达式模式。
按照其 [GitHub 页面](https://github.com/BurntSushi/ripgrep)上的说明安装 `ripgrep`。
- `apktool`:一个用于逆向工程和反汇编 Android apk 文件的工具。
按照其 [官方网站](https://ibotpeaches.github.io/Apktool/install/)上的说明安装 `apktool`。
```
git clone https://github.com/oriori1703/sigmatcher.git
pip install ./sigmatcher
```
## 快速上手
要开始使用 sigmatcher,请按照以下步骤操作:
1. **创建签名文件**:签名文件(.yaml)定义了 Sigmatcher 将用于分析 APK 文件的模式和签名。
这些文件应指定您感兴趣的类、方法和字段,以及任何特定版本的信息。有关格式,请参阅 [创建签名文件](#creating-signature-files) 部分的示例。
2. **分析 APK**:准备好签名文件后,您现在可以分析 APK 以查找与您的签名匹配的内容。
使用 sigmatcher analyze 命令,指定 APK 的路径和签名文件:
sigmatcher analyze path/to/your/app.apk --signatures path/to/your/signature_file.yaml
此命令将解码 APK,应用签名,并输出分析结果,突出显示匹配的类、方法和字段。
## 创建签名文件
签名文件是 `sigmatcher` 用来识别和匹配 APK 文件中 Java 类、方法和字段的 YAML 格式文档。这些文件允许您指定希望在不同版本的应用程序中跟踪的元素。
### 签名文件 JSON Schema
为了帮助您创建签名文件,`sigmatcher` 提供了一个 JSON schema,您可以使用它来验证您的签名,并获得 IDE 的自动补全和智能感知功能。
您可以通过运行以下命令来获取它:
```
sigmatcher schema --output definitions.schema.json
```
根据您的 IDE,您可以将以下注释之一添加到签名文件的顶部:
Intellij IDEs:
```
# $schema: ./definitions.schema.json
```
yaml-language-server IDEs(vs-code, neovim 等):
```
# yaml-language-server: $schema=./definitions.schema.json
```
您也可以将它们组合起来以同时支持两者:
```
# $schema: ./definitions.schema.json
# yaml-language-server: $schema=./definitions.schema.json
```
### 签名文件的结构
一个签名文件由定义列表组成,其中每个定义代表您想要匹配的一个类、方法或字段。每个定义可以包含一个或多个签名,这些签名是 `sigmatcher` 将用于在 smali 代码中查找匹配项的模式。
以下是签名文件的基本示例:
```
# $schema: ./definitions.schema.json
# yaml-language-server: $schema=./definitions.schema.json
- name: "ConnectionManager"
package: "com.example.package.network"
signatures:
- signature: 'ConnectionManager/openConnection: could not open connection due to a DNS error'
type: regex
count: 1
methods:
- name: "read"
signatures:
- signature: 'const-string v\d+, "Failed to read data from the server"'
type: regex
count: 1
version_range: ">=1.0.0, <1.3.7"
- signature: 'const-string v\d+, "Failed to read data because of a network error"'
type: regex
count: 1
version_range: ">=1.3.7"
fields:
- name: "socket"
signatures:
- signature: '^\.field private final (?P.+:Ljava/net/Socket;)'
type: regex
count: 1
```
#### 关键组件
- name:类、方法或字段的名称。
- methods:类内的方法定义列表。遵循与类定义类似的结构。
- fields:类内的字段定义列表。遵循与类定义类似的结构。
- exports:类内的导出定义列表。导出可以是代码中的任何字符串。它们主要用于结合宏来创建更复杂的签名。
- signatures:类、方法或字段的签名列表。每个签名包括:
- type:签名的类型(目前只有 `regex` 和 `glob`)。
- signature:要匹配的模式,取决于签名类型。
对于类和方法,它们只需要在类/方法内的任何位置匹配即可。对于字段和导出,它们需要匹配完整的字段表达式/导出字符串,即对 regex 签名使用 `match` 捕获组。
- count:签名被视为匹配时应出现的次数。可以是整数,也可以是 "min-max" 形式的字符串。默认为 1。
- version_range:可选。指定此签名适用的应用程序版本,使用类似于 pip 的版本说明符,如 [PEP-440](https://packaging.python.org/en/latest/specifications/version-specifiers/#version-specifiers) 中所述。
它也可以包含一个说明符列表,其作用类似于逻辑“或”运算符。
这些字段大多是可选的,您可以根据需要使用它们。
### 在签名中使用宏
宏允许您在签名中引用来自其他匹配结果的属性,从而实现动态和上下文感知的模式匹配。
当您需要创建依赖于先前匹配的类、方法、字段或导出信息的签名时,宏特别有用。
#### 宏语法
宏使用格式 `${.}`,其中:
- `result_name` 是签名文件中另一个定义的名称
- `property` 是匹配结果对象的一个属性
#### 可用属性
根据结果类型的不同,可用的属性也不同:
**对于类 (Classes):**
- `name`:类名(例如 "ConnectionManager")
- `package`:包名(例如 "com.example.package.network")
- `full_name`:带包名的完整类名(例如 "com.example.package.network.ConnectionManager")
- `java`:Java 表示形式(例如 "Lcom/example/package/network/ConnectionManager;")
- `fields.FieldName`:访问特定字段结果(例如 `fields.socket` 返回匹配的字段对象)
- `methods.MethodName`:访问特定方法结果(例如 `methods.read` 返回匹配的方法对象)
- `exports.ExportName`:访问特定导出结果(例如 `exports.someExport` 返回匹配的导出对象)
**对于方法 (Methods):**
- `name`:方法名(例如 "read")
- `argument_types`:方法参数类型(例如 "Ljava/lang/String;")
- `return_type`:方法返回类型(例如 "V")
- `java`:完整的 Java 表示形式(例如 "read(Ljava/lang/String;)V")
**对于字段 (Fields):**
- `name`:字段名(例如 "socket")
- `type`:字段类型(例如 "Ljava/net/Socket;")
- `java`:完整的 Java 表示形式(例如 "socket:Ljava/net/Socket;")
**对于导出 (Exports):**
- `value`:导出的字符串值
#### 宏示例
以下示例展示了如何使用宏来创建相互依赖的签名:
```
# $schema: ./definitions.schema.json
# yaml-language-server: $schema=./definitions.schema.json
- name: "ConnectionManager"
package: "com.example.package.network"
signatures:
- signature: 'ConnectionManager/openConnection: could not open connection due to a DNS error'
type: regex
count: 1
fields:
- name: "socket"
signatures:
- signature: '^\.field private final (?P.+:Ljava/net/Socket;)'
type: regex
count: 1
- name: "NetworkHandler"
package: "com.example.package.network"
signatures:
- signature: 'new-instance v\d+, ${ConnectionManager.java}'
type: regex
count: 1
methods:
- name: "handleConnection"
signatures:
- signature: 'iget-object v\d+, v\d+, ${ConnectionManager.fields.socket.java}'
type: regex
count: 1
```
在此示例中:
- `NetworkHandler` 类使用宏来引用 `ConnectionManager` 类的 Java 表示形式
- `handleConnection` 方法使用宏来引用 `ConnectionManager` 类中的 socket 字段
#### 重要说明
- **定义顺序无关紧要**:Sigmatcher 会自动对依赖图进行排序,因此宏可以引用在 YAML 文件中较后定义的结果
- 宏是在依赖图排序后的分析阶段解析的
- 如果宏引用的结果无法匹配,则签名将匹配失败
- 当您需要类、方法或字段的完整 Java/Smali 表示形式时,请使用 `java` 属性
- 宏适用于 `regex` 和 `glob` 两种签名类型
## 许可证
`sigmatcher` 根据 [MIT](https://spdx.org/licenses/MIT.html) 许可证的条款分发。
标签:Android安全, apktool, APK分析, DAST, Java逆向工程, Python, ripgrep, Smali, 云安全监控, 代码匹配, 恶意软件分析, 无后门, 版本差异分析, 特征提取, 目录枚举, 移动安全, 签名匹配, 逆向工具, 静态分析