How to Parse and Interpret Patator XML and CSV Output Formats
Patator writes machine-readable attack results through CSVFormatter and XMLFormatter classes located in src/patator/patator.py, storing them in a structured log directory created by build_logdir that includes runtime logs, result files, and individual response dumps.
When conducting brute-force or fuzzing campaigns, analyzing results programmatically is critical for automation. The Patator framework provides native support for structured data export, enabling security engineers to integrate findings directly into parsing pipelines without manual log scraping.
Where Patator's Output Formatters Are Implemented
Both output formatters inherit from Python’s logging.Formatter and are defined in the core engine file src/patator/patator.py.
CSVFormatter Class
The CSVFormatter resides at lines 86–100 in src/patator/patator.py. This class formats each request result as a comma-separated line containing temporal data, log level, response indicators, and the tested candidate string.
XMLFormatter Class
The XMLFormatter follows immediately at lines 102–123 in the same file. It serializes results into XML elements, providing identical data to the CSV format but with additional structural metadata including a <target> element containing the raw target string.
The process_logs Entry Point
The process_logs function (lines 32–73) serves as the entry point for Patator’s logging subprocess. When you invoke Patator with --csv or --xml options, this function instantiates the appropriate formatter, checks for existing files to write headers only once, and attaches handlers to the logger.
Understanding the Log Directory Structure
Patator constructs its output workspace through a dedicated directory builder that supports both manual and automatic path generation.
How build_logdir Creates the Output Location
The build_logdir function (lines 890–899 in src/patator/patator.py) validates and prepares the logging directory. Called during Controller.__init__, it accepts the --log-dir (-l) path and handles directory creation with optional user confirmation via --assume-yes.
Automatic Timestamped Directories with create_time_dir
When using the -L SFX flag, Patator invokes create_time_dir (lines 914–928) to generate a time-stamped subdirectory under /tmp/patator. The naming convention follows YYYY-MM-DD/HHMMSS_<suffix>/, preventing result collisions across multiple runs.
Directory Contents and File Layout
A typical Patator log directory contains:
- RUNTIME.log – Raw command-line arguments and execution timestamps
- RESULTS.csv – CSV output (when
--csvis specified) - RESULTS.xml – XML output (when
--xmlis specified) - HITS – Flat text file listing successful candidates (one per line)
- Response dumps – Raw HTTP/TCP responses saved as
<num>_<indicators>.txt(e.g.,001_200_532_0.450.txt)
The response dumps are written by Logger.save_response (lines 55–58), which embeds the iteration number and indicator values (status code, size, time) directly into filenames for immediate correlation with CSV or XML entries.
Parsing Patator CSV Output Format
The CSV file includes a header row written by process_logs using the pattern 'time,level,%s\n' % ','.join(names), where names represents the dynamic indicator list. Standard columns include time, level, code, size, time (elapsed), candidate, num (iteration), and mesg.
import csv
from pathlib import Path
csv_path = Path("/tmp/patator/2024-03-05/153012_ftp/RESULTS.csv")
with csv_path.open(newline="") as f:
reader = csv.DictReader(f, delimiter=",")
for row in reader:
print(f"[{row['time']}] {row['candidate']}: {row['mesg']} (HTTP {row['code']})")
Use csv.DictReader to automatically map the header fields, allowing direct access to columns by name rather than index.
Parsing Patator XML Output Format
The XML structure wraps all results in a <root> element. Each request generates a <result> tag with time and level attributes, plus child elements for each indicator and a <target> element containing connection details.
import xml.etree.ElementTree as ET
from pathlib import Path
xml_path = Path("/tmp/patator/2024-03-05/153012_ftp/RESULTS.xml")
tree = ET.parse(xml_path)
for result in tree.getroot().findall("result"):
candidate = result.findtext("candidate")
code = result.findtext("code")
mesg = result.findtext("mesg")
# Access target attributes if needed
target_elem = result.find("target")
target_str = target_elem.text if target_elem is not None else "N/A"
print(f"{candidate} -> {mesg} (code={code}, target={target_str})")
The XML format preserves the same data as CSV but structures multi-word messages unambiguously and includes the raw target string in the <target> element, useful for forensic reconstruction of complex pivot attacks.
Practical Command-Line Examples
Generate both formats in an auto-managed directory:
patator http_fuzz url=FILE0 method=GET 0=urls.txt -L webscan --csv RESULTS.csv --xml RESULTS.xml
This creates /tmp/patator/2024-XX-XX/XXXXXX_webscan/ containing both structured files plus the HITS file and response dumps.
Save only CSV to a specific location:
patator ssh_login host=10.0.0.1 user=FILE0 password=FILE1 0=users.txt 1=pass.txt -l /var/log/patator --csv scan.csv
Inspect successful candidates without parsing structured files:
cat /var/log/patator/HITS
Summary
- Patator XML and CSV output formats are generated by
XMLFormatterandCSVFormatterclasses insrc/patator/patator.py, activated via--xmland--csvcommand-line switches. - The
process_logsfunction manages formatter initialization and header writing, appending results as the scan progresses. build_logdirandcreate_time_dirconstruct the output hierarchy, defaulting to/tmp/patatorwhen using the-Lflag.- The log directory contains
RUNTIME.log, result files, aHITSsummary, and individual response dumps named with iteration numbers and indicator values. - Parse CSV output using Python’s
csv.DictReaderand XML usingxml.etree.ElementTreeto extract candidate strings, response codes, and timing data for further analysis.
Frequently Asked Questions
What columns appear in Patator's CSV output?
Patator’s CSV includes the columns: time, level, code, size, time (response time in milliseconds), candidate, num (iteration number), and mesg (response message). The header is generated dynamically in process_logs based on the module’s indicator configuration.
How does Patator name response dump files?
Response dumps follow the format <num>_<code>_<size>_<time>.txt, where <num> is the zero-padded iteration number and the remaining fields represent response indicators. These files are written by Logger.save_response in the log directory when logging is enabled.
Can I generate both CSV and XML output simultaneously?
Yes. Patator accepts both --csv FILE and --xml FILE arguments in the same command. The process_logs function creates separate handlers and formatters for each, writing both formats concurrently to the specified log directory.
Where does Patator store logs by default?
When using -L <suffix>, Patator stores logs in a timestamped subdirectory under /tmp/patator. When using -l <dir>, it stores them in the specified directory. If the directory does not exist, build_logdir creates it after user confirmation (unless --assume-yes is passed).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →