oriori1703/sigmatcher

GitHub: oriori1703/sigmatcher

一个基于特征签名的 Java 类与方法跨版本自动匹配工具,用于 Android 逆向工程中持续追踪代码元素。

Stars: 12 | Forks: 5

# sigmatcher [![PyPI - Version](https://img.shields.io/pypi/v/sigmatcher.svg)](https://pypi.org/project/sigmatcher) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/sigmatcher.svg)](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, 云安全监控, 代码匹配, 恶意软件分析, 无后门, 版本差异分析, 特征提取, 目录枚举, 移动安全, 签名匹配, 逆向工具, 静态分析