ProtocolState-Fuzzer is a generic, modular and extensible protocol state fuzzer, which can be used as a framework for the state machine learning and fuzzing of different network protocol implementations.
ProtocolState-Fuzzer supports the following functionality:
- Learning a state machine model of a protocol-specific client or server implementation.
- Testing (executing sequences of inputs) of a protocol-specific client or server implementation.
- Java 17 JDK.
- maven correctly setup to point to Java 17 JDK.
- graphviz library, containing the dot utility, which should be located in the system's PATH.
Assuming the commands are executed from the root directory:
- To check the prerequisites use:
java -version
mvn -version
dot -V- To install the ProtocolState-Fuzzer use:
mvn installThis command will:
-
create in the
targetdirectory the jar file containing the compiled classes and install it in the local Maven repository; -
create in the
targetdirectory the javadocs in html and jar format. The html pages will be located in thetarget/apidocsdirectory and can be viewed using a web browser. The jar format will be installed in the local Maven repository and can be used for inline documentation during programming; -
create in the
targetdirectory the jar file containing the source files, and install it in the local Maven repository. This can be used for debugging purposes and for inline browsing of the source code during programming.
In the output of
mvn installcommand, the installation of the above jars will be shown above the Build Success message. If the javadocs or the sources jar are not needed, they can be manually removed from the local Maven repository.
The import statements are omitted from the following snippets for brevity.
A main class can be like this:
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<LearnerResult> results = commandLineParser.parse(args, true);
// further process the results if needed
}
}Notes:
-
The CommandLineParser class is one entrypoint to the ProtocolState-Fuzzer. Its constructor needs some builders, which can be implemented for instance as in the
MultiBuilderclass defined below, which is specific toMealyMachinemodels. -
The package name of the Main class suffices as the external parent logger of the application, when the Main class resides in the outermost package. The
setExternalParentLoggersmethod is used in order to have the application's log level follow the ProtocolState-Fuzzer's log level in case the arguments-debugor-quietare encountered. -
There are different
parsemethods inCommandLineParser, which can parse and execute the provided arguments, export the learnedDOTfiles toPDFand use specifiedConsumerson the results. Theparsemethod used above, exports the learnedDOTfiles toPDF.
public class MultiBuilder implements
StateFuzzerConfigBuilder,
StateFuzzerBuilder<MealyMachineWrapper<InputImpl, OutputImpl>>,
TestRunnerBuilder,
TimingProbeBuilder {
// InputImpl, OutputImpl, AlphabetPojoXmlImpl need to be implemented
protected AlphabetBuilder<InputImpl> alphabetBuilder = new AlphabetBuilderStandard<>(
new AlphabetSerializerXml<InputImpl, AlphabetPojoXmlImpl>(InputImpl.class, AlphabetPojoXmlImpl.class)
);
// ExecutionContextImpl, SulBuilderImpl need to be implemented
protected SulBuilder<InputImpl, OutputImpl, ExecutionContextImpl> 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<MealyMachineWrapper<InputImpl, OutputImpl>> 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();
}
}The default log level of ProtocolState-Fuzzer is ERROR. One way to change this is
via a log4j2.xml configuration. An example is the configuration used for testing
here, which sets the log level to TRACE.
The log level can be changed to:
INFO, in order to have minimal and sufficient logging orDEBUG, in order to also log the exchanged input and output messages
The following files can be provided in the src/main/resources directory, in
order to be discovered by ProtocolState-Fuzzer.
-
default_alphabet.xml(Mandatory) This file acts as the default alphabet file, in case no other alphabet file is specified via the-alphabetargument parameter. A template of this file is here, which can be read using an implementation of AlphabetPojoXml. If no alphabet file is specified via the-alphabetargument parameter and thedefault_alphabet.xmlis not found in resources, then a fatal exception occurs, because an alphabet cannot be built and the process cannot continue. -
default_fuzzer.properties(Optional). It allows to specify some properties that can be used in the argument files. You can see an example of this file here. Regarding the entryresults.learning.clients=results/clients, the propertyresults.learning.clientscan be used in an argument file as${results.learning.clients}, in order to be resolved toresults/clients. Additionally, the JVM property-Dfuzzer.properties=filecan be used to load a specific properties file instead ofdefault_fuzzer.properties, likejava -Dfuzzer.properties=file -jar .... -
default_mapper_connection.config(Optional). This file allows to specify some configuration options for the specific mapper. Also the-mapperConnectionConfigargument parameter can be used in order to use another configuration file instead of the default one. The input stream of the configuration file can be obtained viagetMapperConnectionConfigInputStream()in MapperConfig. The content format of this file relies on the user. Note that if no configuration file is specified via-mapperConnectionConfigand thedefault_mapper_connection.configis not found in resources, thengetMapperConnectionConfigInputStream()returnsnull.