protocol-fuzzing/protocol-state-fuzzer
GitHub: protocol-fuzzing/protocol-state-fuzzer
一个模块化、可扩展的通用协议状态模糊测试框架,支持自动学习协议实现的状态机模型、执行测试序列以及计时分析。
Stars: 11 | Forks: 8
# ProtocolState-Fuzzer
[](https://github.com/protocol-fuzzing/protocol-state-fuzzer/actions/workflows/ci.yml)
## 目录
* [描述](#description)
* [前置条件](#prerequisites)
* [安装说明](#installation)
* [快速开始](#quick-start)
* [学习](#learning)
* [测试](#testing)
* [计时](#timing)
* [日志](#logging)
* [资源文件](#resource-files)
* [被使用于](#used-by)
## 描述
ProtocolState-Fuzzer 是一个_通用_、_模块化_且_可扩展_的协议状态模糊器,
可用作框架,用于对不同网络协议实现进行状态机学习和模糊测试。
ProtocolState-Fuzzer 为特定的协议客户端或服务器实现提供以下功能:
1. 学习实现的状态机模型。
2. 通过执行测试输入序列对实现进行测试。
3. 在测试输入序列上对实现进行计时,以建议超时值,
从而避免在学习或测试期间出现与时间相关的非确定性。
## 前置条件
* Java 21 JDK。
* 正确配置 maven 以指向 Java 21 JDK。
* graphviz 库,包含 dot 实用程序,该程序应位于系统的 PATH 中。
## 安装说明
假设命令是从根目录执行的:
1. 要检查前置条件,请使用:
```
java -version
mvn -version
dot -V
```
2. 要安装 ProtocolState-Fuzzer,请使用:
```
mvn install
```
此命令将:
* 在 `target` 目录中创建包含已编译类的 **jar** 文件,并将其安装在本地 Maven 仓库中;
* 在 `target` 目录中创建 **html** 和 **jar** 格式的 javadocs。**html** 页面将位于 `target/apidocs` 目录中,
可以使用 Web 浏览器查看。**jar** 格式将安装在本地 Maven 仓库中,
可在编程期间用于内联文档;
* 在 `target` 目录中创建包含源文件的 **jar** 文件,
并将其安装在本地 Maven 仓库中。这可用于调试目的以及编程期间源代码的内联浏览。
## 快速开始
一个主类可以如下所示:
```
public class Main {
public static void main(String[] args) {
// Multibuilder implements all necessary builders
MultiBuilder mb = new MultiBuilder();
// single parentLogger, if Main resides in the outermost package
String[] parentLoggers = {Main.class.getPackageName()};
CommandLineParser> commandLineParser = new CommandLineParser<>(mb, mb, mb, mb);
commandLineParser.setExternalParentLoggers(parentLoggers);
List results = commandLineParser.parse(args, true);
// further process the results if needed
}
}
```
注意:
* [CommandLineParser](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/entrypoints/CommandLineParser.java)
类是 ProtocolState-Fuzzer 的一个入口点。其构造函数需要一些构建器,
例如可以按照下面定义的 `MultiBuilder` 类来实现,
该类特定于 `MealyMachine` 模型。
* 当 Main 类位于最外层的包中时,*Main* 类的包名足以作为应用程序的 *外部父记录器*。`setExternalParentLoggers`
方法用于在遇到 `-debug` 或 `-quiet` 参数时,使应用程序的日志级别遵循 ProtocolState-Fuzzer 的日志级别。
* `CommandLineParser` 中有不同的 `parse` 方法,可以解析并执行提供的参数,将学习到的 `DOT` 文件导出为 `PDF`,
并对结果使用指定的 `Consumers`。上面使用的 `parse` 方法会将学习到的 `DOT` 文件导出为 `PDF`。
```
public class MultiBuilder implements
StateFuzzerConfigBuilder,
StateFuzzerBuilder>,
TestRunnerBuilder,
TimingProbeBuilder {
// InputImpl, OutputImpl, AlphabetPojoXmlImpl need to be implemented
protected AlphabetBuilder alphabetBuilder = new AlphabetBuilderStandard<>(
new AlphabetSerializerXml(InputImpl.class, AlphabetPojoXmlImpl.class)
);
// ExecutionContextImpl, SULBuilderImpl need to be implemented
protected SULBuilder sulBuilder = new SULBuilderImpl();
@Override
public StateFuzzerClientConfig buildClientConfig() {
return new StateFuzzerClientConfigStandard(
new LearnerConfigStandard(),
new SULClientConfigStandard(new MapperConfigStandard(), new SULAdapterConfigStandard()),
new TestRunnerConfigStandard(),
new TimingProbeConfigStandard()
);
}
@Override
public StateFuzzerServerConfig buildServerConfig() {
return new StateFuzzerServerConfigStandard(
new LearnerConfigStandard(),
new SULServerConfigStandard(new MapperConfigStandard(), new SULAdapterConfigStandard()),
new TestRunnerConfigStandard(),
new TimingProbeConfigStandard()
);
}
@Override
public StateFuzzer> build(StateFuzzerEnabler stateFuzzerEnabler) {
return new StateFuzzerStandard<>(
new StateFuzzerComposerStandard<>(stateFuzzerEnabler, alphabetBuilder, sulBuilder).initialize()
);
}
@Override
public TestRunner build(TestRunnerEnabler testRunnerEnabler) {
return new TestRunnerStandard<>(testRunnerEnabler, alphabetBuilder, sulBuilder).initialize();
}
@Override
public TimingProbe build(TimingProbeEnabler timingProbeEnabler) {
return new TimingProbeStandard<>(timingProbeEnabler, alphabetBuilder, sulBuilder).initialize();
}
}
```
注意:
* [StateFuzzer](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/statefuzzer/core/StateFuzzer.java)
接口代表学习过程,并使用
[StateFuzzerStandard](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/statefuzzer/core/StateFuzzerStandard.java)
和 [StateFuzzerComposerStandard](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/statefuzzer/core/StateFuzzerComposerStandard.java) 实现。
* [TestRunner](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/statefuzzer/testrunner/core/TestRunner.java)
接口代表测试过程,并使用
[TestRunnerStandard](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/statefuzzer/testrunner/core/TestRunnerStandard.java) 实现。
* [TimingProbe](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/statefuzzer/testrunner/timingprobe/TimingProbe.java)
接口代表计时过程,并使用
[TimingProbeStandard](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/statefuzzer/testrunner/timingprobe/TimingProbeStandard.java) 实现。
## 学习
在基于 ProtocolState-Fuzzer 和目标 SUL 设置好特定工具后,
可以使用参数文件或提供命令行参数来启动学习。
参数文件可以简单地包含命令行参数及其值。
也可以提供命令行参数来覆盖参数文件中的内容。
参数文件前面的 `@` 符号可以省略。
最简单的命令是:
```
java -jar specific-fuzzer.jar @path/to/argfile
```
上述不带参数文件的命令将列出所有可用的命令行选项。
## 测试
测试不仅需要参数文件,还需要测试序列,该序列通常存储在文件中。
测试序列文件可以每行包含一个输入符号。
测试命令为:
```
java -jar specific-fuzzer.jar @path/to/arg/file -test path/to/test/file [-additional_param]
Additional Testing Parameters:
-times N
Run each test sequence N number of times, defaults to 1
-testSpecification path/to/dot/model
If a .dot model is provided as a specification, the resulting outputs are
compared against it. The test file will be run both on the implementation
and on the specification model
-showTransitionSequence
Shows the sequence of transitions at the end in a nicer format
```
## 计时
计时是测试的扩展,需要指定 `-test` 和 `-probeCmd` 参数。
它用于查找防止 SUL 产生非确定性输出的计时值。
它对 `-probeCmd` 中的所有命令使用相同的初始范围,并**仅**基于 `-test` 提供的测试执行搜索。
因此,对于学习而言,计时值可能需要进一步的手动调整。
计时探针命令为:
```
java -jar specific-fuzzer.jar @path/to/arg/file -test path/to/test/file -probeCmd [-additional_param]
Available comma-separated probe commands:
- responseWait (time to wait for an SUL response)
- startWait (time to wait after starting the SUL)
- (time to wait for the response of this alphabet input symbol)
Example: -probeCmd responseWait,startWait,input1,input2
Additional Timing Parameters:
-times N
Run each test sequence N number of times, defaults to 1
-probeLow N
The lowest non-negative integer probe timing value, defaults to 0
-probeHigh N
The highest integer probe timing value, defaults to 1000
-probeTol N
Search tolerance value that defines the desired precision, defaults to 10
Small tolerance values increase accuracy but may require more iterations
-probeExport path/to/alphabet/out
The output file for the alphabet augmented with timing values
Useful when an input symbol has been provided in -probeCmd
```
## 日志
ProtocolState-Fuzzer 的默认日志级别是 `ERROR`。更改它的一种方法是
通过 `log4j2.xml` 配置。[此处](src/test/resources/log4j2.xml)用于测试的配置示例将日志级别设置为 `TRACE`。
日志级别可以更改为:
* `INFO`,以获得最少且足够的日志记录,或者
* `DEBUG`,以便同时记录交换的输入和输出消息
## 资源文件
可以在 `src/main/resources` 目录中提供以下文件,
以便 ProtocolState-Fuzzer 能够发现它们。
* `default_alphabet.xml` **(必填)** 此文件充当默认字母表
文件,以防没有通过 `-alphabet` 参数指定其他字母表文件。此文件的模板位于[此处](src/test/resources/default_alphabet.xml),
可以使用
[AlphabetPojoXml](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/components/learner/alphabet/xml/AlphabetPojoXml.java) 的实现进行读取。
如果没有通过 `-alphabet` 参数指定字母表文件,并且在资源中找不到
`default_alphabet.xml`,则会发生致命异常,
因为无法构建字母表且进程无法继续。
* `default_fuzzer.properties` **(可选)** 它允许指定一些
可在参数文件中使用的属性。您可以在[此处](src/test/resources/default_fuzzer.properties)查看此文件的示例。
关于条目 `results.learning.clients=results/clients`,属性
`results.learning.clients` 可以在参数文件中写为 `${results.learning.clients}`,
以便将其解析为 `results/clients`。此外,JVM 属性
`-Dfuzzer.properties=file` 可用于加载特定的属性文件,而不是
`default_fuzzer.properties`,例如 `java -Dfuzzer.properties=file -jar ...`。
* `default_mapper_connection.config` **(可选)** 此文件允许为
特定的 mapper 指定一些配置选项。也可以使用 `-mapperConnectionConfig`
参数来使用其他配置文件代替默认文件。配置文件的输入流可以通过
[MapperConfig](src/main/java/com/github/protocolfuzzing/protocolstatefuzzer/components/sul/mapper/config/MapperConfig.java) 中的
`getMapperConnectionConfigInputStream()` 获取。
此文件的内容格式取决于用户。请注意,如果未通过 `-mapperConnectionConfig` 指定配置文件,并且在资源中
找不到 `default_mapper_connection.config`,则 `getMapperConnectionConfigInputStream()` 将返回 `null`。
## 被使用于
* [BLE-Fuzzer](https://github.com/protocol-fuzzing/ble-fuzzer)
* [DTLS-Fuzzer](https://github.com/assist-project/dtls-fuzzer)
* [EDHOC-Fuzzer](https://github.com/protocol-fuzzing/edhoc-fuzzer)
* [TCP-Fuzzer](https://github.com/protocol-fuzzing/tcp-fuzzer)
标签:CISA项目, Graphviz, Maven, 内存取证对抗, 协议安全评估, 协议实现分析, 协议状态模糊器, 域名枚举, 密码管理, 时间非确定性测试, 模块化架构, 模糊测试框架, 漏洞验证, 状态机学习, 网络协议分析, 网络协议模糊测试, 网络安全, 自动化状态机提取, 隐私保护