- Description
- Prerequisites
- Installation
- Quick Start
- Learning
- Testing
- Timing
- Logging
- Resource Files
- Used By
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 for a protocol-specific client or server implementation:
- Learning the state machine model of the implementation.
- Testing the implementation by executing test input sequences.
- Timing the implementation on test input sequences to suggest timeout values for avoiding time-related non-determinism during Learning or Testing.
- Java 21 JDK.
- maven correctly setup to point to Java 21 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();
}
}Notes:
-
The StateFuzzer interface represents the learning procedure and is implemented using the StateFuzzerStandard and the StateFuzzerComposerStandard.
-
The TestRunner interface represents the testing procedure and is implemented using the TestRunnerStandard.
-
The TimingProbe interface represents the timing procedure and is implemented using the TimingProbeStandard.
After setting up the specific tool based on ProtocolState-Fuzzer and the SUL of interest,
one can initiate learning using argument files or providing command line arguments.
The argument files can simply contain command-line arguments and their values.
Command-line arguments can also be provided to overwrite those in the argument files.
The @ symbol before the argument file can be omitted.
The simplest command is:
java -jar specific-fuzzer.jar @path/to/argfile
The above command without the argument file lists all the available command line options.
Testing requires not only an argument file but also a test sequence, usually stored in a file. Test sequence files can contain input symbols one-per-line.
The test command is:
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
Timing is an extension of testing and requires the -test and -probeCmd parameters to be specified.
It is used to find timing values that prevent non-deterministic outputs from the SUL.
It uses the same initial range for all commands in -probeCmd and performs the search
based only on the provided tests of -test. Thus for learning, the timing values
might need further manual adjustment.
The timing probe command is:
java -jar specific-fuzzer.jar @path/to/arg/file -test path/to/test/file -probeCmd <probe commands> [-additional_param]
Available comma-separated probe commands:
- responseWait (time to wait for an SUL response)
- startWait (time to wait after starting the SUL)
- <input symbol> (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
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.