FLUFFI is a distributed evolutionary binary fuzzer for pentesters.
Usage
1)Adding runner systems to FUN
All FuzzJobs are run on dedicated Runner systems in the FLUFFI Utility Network (FUN). You can bring your own system or use the FLUFFI PXE images (recommended). How to build these images is documented here.
To add new systems:
gm.fluffi
. For problems: check the firewallnet use y: \\smb.fluffi\install\initial /user:nobody pass
y:\initialConfiguration.bat
net use y: /Delete /yes
apt-get install openssh-server smbclient net-tools
smbclient '//smb.fluffi/install' -c 'cd initial; get MAC2Host.csv; get initialConfiguration.sh' -U anonymous%pass;
chmod 777 initialConfiguration.sh
/bin/bash initialConfiguration.sh
rm MAC2Host.csv
rm initialConfiguration.sh
Add System
button in FLUFFI’s web GUI. When adding it via the web GUI just use the system’s host name without any domain suffix. When adding it via the hosts file, the line needs to look like this: <hostname> ansible_ssh_host=<hostname>.fluffi
. Remember: When modifying the hosts file, you need to restart the polemarch and fluffi_web containers.Systems
tab. An explication of the location concept can be found here.1.1) Deploying FLUFFI
Now that the new agent system is part of the FUN, the system needs to be configured for FLUFFI. Furthermore, the FLUFFI agent binaries need to be copied to the agent system.
You can do this by navigating to the ‘Systems’ tab in FLUFFI’s web GUI, and clicking on the system’s name. Now you should click on ‘Initial Setup’ and let Pelemarch/Ansible configure the target system for FLUFFI.
Once this is done, you should go to the ‘Deploy FLUFFI’ tab and deploy those FLUFFI binaries that correspond to the target’s architecture. If your target is an X64 system, you might also want to copy the x86 binaries, to be able to fuzz both architectures on a single machine.
2) Preparing your target
2.1) Getting the input into your target
Currently, FLUFFI supports the following types of targets:
2.1.1) File-parsing binaries that run natively
FUN supports x64/x86 (Linux/Windows) systems and ARM/ARMarch64 systems (Linux). If your binary parses files and runs on one of these systems, no further action is required.
PLEASE NOTE Many targets can be converted to this type, either by changing the source code or by patching the binary.
2.1.2) File-parsing binaries that need to be emulated
If your binary parses files and you know how to emulate it with QEMU user mode emulation, no further action is required.
PLEASE NOTE Many targets can be converted to this type, either by changing the source code, or by patching the binary.
2.1.3) Server binaries that run natively
You need to write a so-called Feeder that allows FLUFFI to feed test cases to your target. This feeder can be written in whichever language you prefer. The interface towards FLUFFI that you need to call is implemented by the SharedMemIPC.dll
/libsharedmemipc.so
.
There are already some feeders pre-implemented here:
If you want to test your feeder, you can use the feeder tester implemented at Tester.
2.1.4) GDB Targets
You need a Feeder (see last section). Furthermore, you need a GDB client that speaks the same protocol version as your GDB server.
2.1.5) Windows kernel modules (e.g. Windows drivers)
You need a Feeder (see last section). Furthermore, you need to set up kFuzz for FLUFFI.
2.1.6) Everything else
Contact us if you need anything else. FLUFFI can be extended to a wide variety of targets types, if needed.
2.2) Replacing compare functions with fuzzable versions
Fuzzing of compare functions such as memcmp and strcmp is generally a very difficult task for a black-box coverage-based fuzzer such as FLUFFI.
To help FLUFFI handle this we added the fuzzcmp helper. What this helper does is – in one sentence – replacing standard compare functions with something that FLUFFI can nicely handle.
We recommend using it always!
3) Create a FLUFFI FuzzJob
If you want to create a FuzzJob go to the FLUFFI web page (currently reachable on http://web.fluffi/
).
Having done so, you need to create a FuzzJob via FuzzJobs->Create FuzzJob
.
Name
The name should be something like “MiniWeb” or “MyXMLParser”. Note: for now the name can not contain [-_ ].
Runner Type
Currently the following Runner (aka Testcase Executors) are defined
ALL_GDB
ALL_Lin_QemuUserSingle
ARM_Lin_DynRioMulti
ARM_Lin_DynRioSingle
ARM64_Lin_DynRioMulti
ARM64_Lin_DynRioSingle
X64_Lin_DynRioMulti
X64_Lin_DynRioSingle
X64_Win_DynRioMulti
X64_Win_DynRioSingle
X86_Lin_DynRioMulti
X86_Lin_DynRioSingle
X86_Win_DynRioMulti
X86_Win_DynRioSingle
Which one to choose depends on how you prepared your target. The QemuUserSingle
runner is used for emulated binaries (see section 2.1.2), DynRioMulti
runners are used for server binaries (see section 2.1.3), DynRioSingle
runners are used for native file parsers (see section 2.1.1), and ALL_GDB
is used if you use GDB (see section 2.1.4), or WinDBG (see section 2.1.5).
Generator Types
FLUFFI supports various test case generators. You can use as many of them as you like. The following are currently implemented:
RadamsaMutator
AFLMutator
HonggfuzzMutator
ExternalMutator
(Allows easy addition of custom mutators): in this case you need to specify an additional setting: extGeneratorDirectory
This setting points to a directory, where FLUFFI will insert a file called FuzzJob.name
containing the name of the current FuzzJob. It is the job of the external mutator to:extGeneratorDirectory
named like that UUIDfuzzjob
tablenice_names_managed_instance
table for the chosen UUIDParentGUID_ParentLocalID_GeneratorLocalID
. GeneratorLocalID
needs to be a decimal number that is unique for the current mutator instance (i.e. you must ensure that the touple (UUID
,GeneratorLocalID
) is unique). If you want you can use any information from the FuzzJob’s database to generate good testcases.You need to set the percentage of how many generators should have which generator type. For example, if you only want RadamsaMutators
, set RadamsaMutator
=100 and all others to 0.
Evaluator Types
FLUFFI supports various test case evaluators. You can use as many of them as you like. The following are currently implemented:
CoverageEvaluator
You need to set the percentage of how many evaluators should have which evaluator type. For example, if you only want CoverageEvaluators
set CoverageEvaluator
=100 and all others to 0.
Location
The location(s) in which you want to run your FuzzJob. This can be changed later.
Options
Options for the FuzzJob.
Testcase Runner
The runnerType parameter sets which runner will be used. For possible values see myAgentSubTypes
in TestcaseRunner.cpp.
For *_DynRioSingle:
"C:\FLUFFI\SUT\my target\mytarget.exe" -startnormal
on Windows or /home/<FluffiUser>/fluffi/persistent/SUT/my target/mytargetbin
on Linux). It needs to be absolute! If you specify <INPUT_FILE> somewhere in the command line, FLUFFI will replace it with the filename of the test case. Otherwise, FLUFFI will append the filename of the test case to the end of the command line.LD_PRELOAD=/my/shared/obj.so
.For *_DynRioMulti:
"C:\FLUFFI\SUT\my target\mytarget.exe" -startnormal
on Windows or /home/<FluffiUser>/fluffi/persistent/SUT/my target/mytargetbin
on Linux). It needs to be absolute! FLUFFI will replace <RANDOM_SHAREDMEM> with a randomly generated shared memory name. This makes sense when using the SharedMemFeeder, which expects a shared memory name as the last parameter of the target. Furthermore, FLUFFI will replace <RANDOM_PORT> with a random free port. This makes sense when applications bind to a TCP port that can be specified via command line. Setting it makes it possible to launch multiple target instances on a single machine."C:\FLUFFI\SUT\my target\TCPFeeder.exe" 80
, "C:\FLUFFI\SUT\my target\TCPFeeder.exe"
(not setting a port will cause the feeder to scan the target for the listening port), or "C:\FLUFFI\SUT\my target\SharedMemFeeder.exe"
). The name for the SharedMemory Location (as accessed in the Feeder’s source code) will be added automatically (for the interface between FLUFFI<->Feeder).LD_PRELOAD=/my/shared/obj.so
. Only has an effect if no starter is used.For ALL_Lin_QemuUserSingle:
/bin/qemu-<ARCH>
-trace events=/etc/qemu-events -d nochain
(usualy no need to change this)-f
-E LD_PRELOAD=/my/shared/obj.so
/home/user/fuzztarget
-v -d --please-do-not-crash --config /home/user/conf.conf --read-in
[...] --read-in /fluffi/testcase/00235.bin
in above example)For ALL_GDB:
"C:\FLUFFI\SUT\my target\gdb.exe"
on Windows or /home/<FluffiUser>/fluffi/persistent/SUT/my target/gdb
on Linux). If you you use kFuzz for FLUFFI, specify the path of the GDBEmulator binary. Remember: The command line needs to be absolute in any case!"C:\FLUFFI\SUT\my target\TCPFeeder.exe" 80
). The name for the SharedMemory Location (as accessed in the Feeder’s source code) will be added automatically (for the interface between FLUFFI<->Feeder). IMPORTANT: Due to how the communication with GDB is implemented, the feeder MUST ignore Ctrl+C on Windows (SetConsoleCtrlHandler(NULL, true);
in C);"C:\FLUFFI\SUT\my target\GDBStarter.exe -local C:\FLUFFI\SUT\my target\actual target.exe"
), and creates a GDB initialization file so that the GDB can connect to the target. The starter will be executed only once until a crash occurs (not in each runner pass). Examples for GDB starters are implemented in GDBStarter.PLEASE NOTE: All options can be changed while the job is running. You will however need to restart the agents as they only pull the options upon start.
Target Modules
FLUFFI is a coverage-based evolutionary fuzzer. In order to reduce the noise in the coverage, only those modules that are listed here will be used to calculate the coverage. Examples for modules are test.dll
, or target.exe
.
When creating or modifying a project, you can upload the target modules as files. Their filename and binary will be saved and their path will be initialized with a *
. Therefore, you can edit them in the project view by renaming the filename, path and/or uploading a new binary. FLUFFI itself only uses the filename but some generators will use the binary.
If there are several modules with the same name but different paths, you can specify which one should be used for coverage calculation by specifying the path. If it is left to *
, the path of a module is ignored.
PLEASE NOTE: If you are using a GDB runner, the module name is actually a segment name. An example therefore is target.exe/.text
Target Upload See section 4) below.
Population
Each evolutionary fuzzer needs a set of known-to-be-good input samples to start with. These need to be uploaded here. You can specify more than one at a time. Furthermore, you can always add more while the project is running.
Basic Blocks
Only relevant for ALL_GDB runner. These are the blocks that will be considered for coverage collection. FLUFFI expects a file with the following format:
target.exe/.text,0x1
target.exe/.text,0x2
helper.dll/.text,0x100
If you want, you can alternatively insert the blocks in the database table blocks_to_cover
yourself (e.g. by using this IDA python script).
Testcase Generator
Which generator types should be used is set by the generatorTypes parameter. It is a string of all types to use followed by their percentage. If you want to use only one generator of type A, set A=100
. If you want to use two with the same probability, set A=50|B=50
. For possible type values see myAgentSubTypes
in TestcaseGenerator.cpp.
PLEASE NOTE that the LocalManagers will try to stick as close to your setting as possible. However, if that is not possible (for example, if only generators that have only type A implemented register), the ratio might not be as desired.
Testcase Evaluator
Which evaluator types should be used is set by the evaluatorTypes parameter. It is a string of all types to use followed by their percentage. If you want to use only one evaluator of type A, set A=100
. If you want to use two with the same probability, set A=50|B=50
. For possible type values see myAgentSubTypes
in TestcaseEvaluator.cpp.
PLEASE NOTE that the LocalManagers will try to stick as close to your setting as possible. However, if that is not possible (for example, if only evaluators that have only type A implemented register), the ratio might not be as desired.
4) Deploy the FuzzJob on the target machines
All FuzzJobs are run on dedicated Runner systems in the FLUFFI Utility Network (FUN). Your test target, which should be wrapped as a package, needs to be deployed to these Runner systems.
A package is a zip file containing either an install.bat
, an install.ps1
, or an install.sh
file as well as arbitrary data. When you deploy this package, it is copied to the FLUFFI runner systems, extracted (on Windows to C:\fluffi\SUT\<ZipFileName>\
, on Linux to /home/<FluffiUser>/fluffi/persistent/SUT/<ZipfileName>\
), and the corresponding install script is executed. You should prepare the package so that it installs all the required dependencies for the target as well as the target itself.
If you create a Windows package, you should add page heap checks using gflags for the target binary. This allows FLUFFI to better detect access violations in the heap. As gflags is by default copied to all agent systems, you only need to add a line to your install.ps1
or install.bat
such as: C:\utils\GFlags\x86\gflags.exe /p /enable TargetBinary.exe
The package needs to be copied somehow to the FLUFFI ftp server (ftp.fluffi). You have two options to do so. Option one is you connect directly to the ftp server using anonymous login, and place the package in the SUT folder. Option two is, you upload the package while creating the FuzzJob. It will then be placed in that very folder. Additionally, it will be associated with the FuzzJob.
Once the package is on the FTP server, you can deploy it to runner systems. You can do so in the Systems
tab by selecting a system or group and chosing the ‘Deploy SUT/Dependency’ option (SUT stands for Software Under Test).
5) Start the FLUFFI Agents
Currently there are two ways of how you can manage how many agents (LM, TR, TE, TG) run on which system, and work on which FuzzJob.
Manually
You can connect to the systems directly (SSH, RDP), and start the agents there.
The credentials to do so can be looked up in polemarch’s hosts file. On Windows, start one LM (if there is not already one for your FuzzJob, such as on another machine in the same location) and as many TRs / TGs / TEs as you like, e.g. by clicking on the icons on the Desktop. On Linux, just start the appropriate agent binary from the command line, ensuring that you add the location name as the argument for the agent.
After having been started, LMs register at the GlobalManager (GM) and keep asking for a yet unmanaged FuzzJob in their location. As soon as such a FuzzJob becomes available, the LM will start managing it.
TRs / TGs / TEs will connect to the GM and wait until they are assigned a FuzzJob. This can be done in the Location page of the web application. Once a FuzzJob is assigned, they will connect to the LM in their location managing that FuzzJob.
IMPORTANT: When managing agents manually, you need to disable the agent manager by setting it to INACTIVE
in the Settings
button on the Systems
tab.
Automatically
FLUFFI implements a so called agent manager. This manager checks how many agents should be run on which machine and will enforce that this is actually the case. It runs periodicly every few minutes (so you need a little patience after configuring new instances).
You can control the number of running FLUFFI agents (LM, TR, TE, TG) via the web GUI.
To do so you need go to one of the following locations:
Config System Instances
section on the FuzzJob overview pageSystems
tab (click on a group name)Systems
tab (click on a system name)IMPORTANT: When managing agents with the agent manager, you need to enable the agent manager by setting it to ACTIVE
in the Settings
button on the Systems
tab. Setting it to KILL
will kill all currently running agents. As a result, you can easily replace FLUFFI or targets binaries.
Note: The agent manager is implemented by two components: A periodic polemarch task, and a python REST server that is deployed to the runner machines and waits for commands to execute. The latter is one of the reasons why you should NEVER run FLUFFI in an untrusted environment.
6) Monitoring FLUFFI Agents
You should always monitor your FuzzJob.
First of all, you should make sure that the number of executions and the number of covered blocks is rising. If one of them doesn’t there is something wrong with your setup.
Furthermore, in the Managed Instances
view make sure that:
You can stop running agents by clicking the Managed Instances
button when viewing the FuzzJob overview page.
Finally, you should keep one eye on log messages. Currenlty, FLUFFI agents store all ERROR messages in the database. They can then be displayed in the web application (for agents in the Managed Instances
view, for LMs there is a global tab).
shadow-rs is a Windows kernel rootkit written in Rust, demonstrating advanced techniques for kernel manipulation…
Extract and execute a PE embedded within a PNG file using an LNK file. The…
Embark on the journey of becoming a certified Red Team professional with our definitive guide.…
This repository contains proof of concept exploits for CVE-2024-5836 and CVE-2024-6778, which are vulnerabilities within…
This took me like 4 days (+2 days for an update), but I got it…
MaLDAPtive is a framework for LDAP SearchFilter parsing, obfuscation, deobfuscation and detection. Its foundation is…