fixed issues and improved security
This commit is contained in:
+58
@@ -1 +1,59 @@
|
|||||||
|
# Python cache and bytecode
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Log files - may contain sensitive paths/device info
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
ENV/
|
||||||
|
.venv
|
||||||
|
|
||||||
|
# IDE and editor files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
.pytest_cache/
|
||||||
|
.coverage
|
||||||
|
htmlcov/
|
||||||
|
|
||||||
|
# Claude docs
|
||||||
|
.claude_docs
|
||||||
|
|
||||||
|
# Sensitive files that should never be committed
|
||||||
|
*.iso
|
||||||
|
*.img
|
||||||
|
*.key
|
||||||
|
*.pem
|
||||||
|
*.p12
|
||||||
|
*.pfx
|
||||||
|
test_*
|
||||||
|
*.bak
|
||||||
|
*.backup
|
||||||
@@ -2,31 +2,38 @@
|
|||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
The **Covert SD Card Tool** is a Python script designed to automate the process of setting up a bootable USB drive with either Kali Linux or Tails OS. It includes options to create encrypted persistence partitions, encrypted documents partitions, and an unencrypted partition containing helpful scripts and instructions. This tool simplifies the complex steps involved in preparing a secure, portable operating system on a USB drive.
|
The **Covert SD Card Tool** is a Python script designed to automate the process of setting up a bootable USB/SD card with either Kali Linux or Tails OS. It includes options to create encrypted persistence partitions, secure document storage, and user-friendly access scripts. This tool simplifies the complex steps involved in preparing a secure, portable operating system on a USB drive or SD card.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Install Kali Linux or Tails OS** on a USB drive.
|
- **Install Kali Linux or Tails OS** on a USB/SD card
|
||||||
- **Create an encrypted persistence partition** for Kali Linux.
|
- **Create an encrypted persistence partition** for Kali Linux (LUKS encryption)
|
||||||
- **Create an encrypted documents partition** using VeraCrypt.
|
- **Create a maximum-security encrypted documents partition** with triple-cascade encryption
|
||||||
- **Add an unencrypted partition** containing automount scripts and instructions.
|
- **Secure drive wiping** using multi-pass shred for data sanitization
|
||||||
- **Customizable encryption options** with a fast setup mode.
|
- **User-friendly access scripts** for mounting and locking secure storage
|
||||||
- **Automated dependency checking and installation**.
|
- **OPSEC-focused design** - generated scripts use generic terminology
|
||||||
|
- **Automated dependency checking and installation**
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- **Operating System:** Linux (Debian-based distributions recommended).
|
- **Operating System:** Linux (Debian-based distributions recommended)
|
||||||
- **Python Version:** Python 3.x.
|
- **Python Version:** Python 3.x
|
||||||
|
- **Root Access:** Required for disk operations
|
||||||
- **Dependencies:**
|
- **Dependencies:**
|
||||||
- `parted`
|
- `parted` - Partition management
|
||||||
- `cryptsetup`
|
- `cryptsetup` - LUKS encryption
|
||||||
- `lsblk`
|
- `lsblk` - Block device listing
|
||||||
- `dd`
|
- `dd` - Disk writing
|
||||||
- `sgdisk`
|
- `sgdisk` - GPT partition manipulation
|
||||||
- `wipefs`
|
- `wipefs` - Filesystem signature removal
|
||||||
- `bc`
|
- `shred` - Secure data wiping
|
||||||
- `fdisk`
|
- `bc` - Calculator for partition math
|
||||||
- `veracrypt` (The script can install this if not present).
|
- `fdisk` - Partition table manipulation
|
||||||
|
- `veracrypt` - Document partition encryption
|
||||||
|
- `lsof`, `fuser` - Process detection
|
||||||
|
- `udevadm` - Device management
|
||||||
|
|
||||||
|
**Note:** The script will automatically detect missing dependencies and offer to install them.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -53,13 +60,14 @@ sudo ./covert_sd_card_tool.py [options]
|
|||||||
|
|
||||||
### Command-Line Options
|
### Command-Line Options
|
||||||
|
|
||||||
- `-a`, `--all` : Set up both the OS bootable USB and the documents partition.
|
- `-a`, `--all` : Set up both the OS bootable USB and the documents partition (defaults to Kali)
|
||||||
- `-k`, `--kali` : Create a Kali bootable USB and persistence partition.
|
- `-k`, `--kali` : Create a Kali bootable USB and persistence partition
|
||||||
- `-t`, `--tails` : Create a Tails bootable USB (no persistence).
|
- `-t`, `--tails` : Create a Tails bootable USB (no persistence, mutually exclusive with `-a`)
|
||||||
- `-d`, `--docs` : Create an encrypted documents partition.
|
- `-c`, `--custom` : Create a custom ISO bootable USB (uses Kali-style partitioning with persistence)
|
||||||
- `-i`, `--iso` : Path to the Kali or Tails ISO file.
|
- `-d`, `--docs` : Create an encrypted documents partition
|
||||||
- `--fast` : Enable fast setup with less secure encryption.
|
- `-i`, `--iso` : Path to the ISO file (Kali, Tails, or custom)
|
||||||
- `--debug` : Enable debug mode.
|
- `--fast` : Enable fast setup mode (Note: Documents partition always uses maximum security)
|
||||||
|
- `--debug` : Enable debug mode with verbose logging
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@@ -69,20 +77,192 @@ sudo ./covert_sd_card_tool.py [options]
|
|||||||
sudo ./covert_sd_card_tool.py -a -i /path/to/kali.iso
|
sudo ./covert_sd_card_tool.py -a -i /path/to/kali.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Install Tails and Encrypted Documents Partition:**
|
- **Install Tails with Encrypted Documents Partition:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo ./covert_sd_card_tool.py -a -t -i /path/to/tails.iso
|
sudo ./covert_sd_card_tool.py -t -d -i /path/to/tails.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Install Tails Without Encrypted Documents Partition:**
|
- **Install Tails Only (No Documents Partition):**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo ./covert_sd_card_tool.py -t -i /path/to/tails.iso
|
sudo ./covert_sd_card_tool.py -t -i /path/to/tails.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Install Encrypted Documents Partition Only:**
|
- **Create Encrypted Documents Partition Only (No OS):**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo ./covert_sd_card_tool.py -d
|
sudo ./covert_sd_card_tool.py -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- **Install Custom ISO (e.g., Parrot OS, BlackArch) with Persistence and Documents:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./covert_sd_card_tool.py -c -d -i /path/to/custom.iso
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Install Custom ISO with Persistence Only (No Documents):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./covert_sd_card_tool.py -c -i /path/to/custom.iso
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Features
|
||||||
|
|
||||||
|
### Documents Partition Encryption
|
||||||
|
|
||||||
|
The documents partition uses **maximum security settings** regardless of the `--fast` flag:
|
||||||
|
|
||||||
|
- **Triple Cascade Encryption:** AES-Twofish-Serpent (3 layers)
|
||||||
|
- **Hash Algorithm:** SHA-512
|
||||||
|
- **Key Derivation:** PIM 2000 (enforced for strong key stretching)
|
||||||
|
- **Filesystem:** ext4
|
||||||
|
- **Full Format:** Always performs full format (no quick format) to overwrite old data
|
||||||
|
|
||||||
|
This configuration provides **military-grade security** suitable for sensitive documents like travel documents, credentials, and confidential files.
|
||||||
|
|
||||||
|
### Persistence Partition Encryption (Kali)
|
||||||
|
|
||||||
|
- **Normal Mode:** AES-XTS-PLAIN64, 512-bit keys, SHA-512, 5 second iteration time
|
||||||
|
- **Fast Mode:** AES-CBC-ESSIV:SHA256, 256-bit keys, SHA-256, 1 second iteration time
|
||||||
|
|
||||||
|
### Secure Drive Wiping
|
||||||
|
|
||||||
|
When you choose to wipe the drive, the tool uses `shred`:
|
||||||
|
- **3 passes** of random data overwriting
|
||||||
|
- **Final pass** with zeros
|
||||||
|
- Makes data recovery virtually impossible
|
||||||
|
- Confirmation required (must type 'WIPE')
|
||||||
|
|
||||||
|
### OPSEC (Operational Security)
|
||||||
|
|
||||||
|
The generated helper scripts use **generic terminology** to avoid disclosing encryption methods:
|
||||||
|
|
||||||
|
- Scripts renamed to `mount_storage.sh` and `lock_storage.sh` (instead of mentioning encryption types)
|
||||||
|
- README uses terms like "secure storage" instead of specific encryption names
|
||||||
|
- No algorithm disclosure in user-facing documentation on the device
|
||||||
|
- Suitable for travel scenarios where device inspection may occur
|
||||||
|
|
||||||
|
## Generated Helper Scripts
|
||||||
|
|
||||||
|
The tool creates a small unencrypted partition (TOOLS) containing:
|
||||||
|
|
||||||
|
### `mount_storage.sh`
|
||||||
|
- Interactive script to mount the encrypted documents partition
|
||||||
|
- Shows available devices and validates input
|
||||||
|
- Mounts to `/mnt/secure_storage`
|
||||||
|
- Clear error messages and success confirmations
|
||||||
|
|
||||||
|
### `lock_storage.sh`
|
||||||
|
- Safely dismounts and locks the encrypted storage
|
||||||
|
- Checks for open files before locking
|
||||||
|
- Shows warnings if applications are still using the storage
|
||||||
|
- Syncs pending writes before dismount
|
||||||
|
- Prevents data loss from improper ejection
|
||||||
|
|
||||||
|
### `README.txt`
|
||||||
|
- Simple instructions for non-technical users
|
||||||
|
- Generic terminology (no encryption disclosure)
|
||||||
|
- Step-by-step mount/lock procedures
|
||||||
|
|
||||||
|
## Important Security Notes
|
||||||
|
|
||||||
|
⚠️ **Password Strength:** Use strong passphrases (20+ characters, mixed case, numbers, symbols)
|
||||||
|
|
||||||
|
⚠️ **No Password Recovery:** If you forget your password, your data is **permanently inaccessible**
|
||||||
|
|
||||||
|
⚠️ **PIM Value:** The tool enforces PIM 2000 for documents partition - this adds 2-3 seconds to unlock time but massively increases security
|
||||||
|
|
||||||
|
⚠️ **Always Lock Before Removal:** Use `lock_storage.sh` before removing the device to prevent data corruption
|
||||||
|
|
||||||
|
⚠️ **Fast Mode:** While available for persistence partition, documents partition **always uses maximum security**
|
||||||
|
|
||||||
|
## Partition Layout Examples
|
||||||
|
|
||||||
|
### Kali + Documents (`-a`)
|
||||||
|
1. **Partition 1:** Kali Live OS (bootable)
|
||||||
|
2. **Partition 2:** LUKS encrypted persistence (configurable size, e.g., 4GB)
|
||||||
|
3. **Partition 3:** VeraCrypt encrypted documents (remaining space minus 1GB)
|
||||||
|
4. **Partition 4:** Unencrypted tools partition (1GB, FAT32, contains scripts)
|
||||||
|
|
||||||
|
### Tails Only (`-t`)
|
||||||
|
- **Entire Drive:** Tails Live OS (bootable, no additional partitions)
|
||||||
|
|
||||||
|
### Tails + Documents (`-t -d`)
|
||||||
|
1. **Partition 1:** Tails Live OS (bootable, 12MB EFI System)
|
||||||
|
2. **Partition 2:** Tails system partition (~2-3GB depending on Tails version)
|
||||||
|
3. **Partition 3:** VeraCrypt encrypted documents (remaining space minus 1GB)
|
||||||
|
4. **Partition 4:** Unencrypted tools partition (1GB, FAT32, contains scripts)
|
||||||
|
|
||||||
|
### Documents Only (`-d`)
|
||||||
|
1. **Partition 1:** VeraCrypt encrypted documents (remaining space minus 1GB)
|
||||||
|
2. **Partition 2:** Unencrypted tools partition (1GB, FAT32, contains scripts)
|
||||||
|
|
||||||
|
### Custom ISO + Documents (`-c -d`)
|
||||||
|
1. **Partition 1:** Custom Live OS (bootable)
|
||||||
|
2. **Partition 2:** LUKS encrypted persistence (configurable size, e.g., 4GB)
|
||||||
|
3. **Partition 3:** VeraCrypt encrypted documents (remaining space minus 1GB)
|
||||||
|
4. **Partition 4:** Unencrypted tools partition (1GB, FAT32, contains scripts)
|
||||||
|
|
||||||
|
**Note:** Custom ISO mode uses Kali-style partitioning. Works well with Debian-based live ISOs like Parrot OS, BlackArch, BackBox, etc.
|
||||||
|
|
||||||
|
## Using Custom ISOs
|
||||||
|
|
||||||
|
The `-c` (custom) flag allows you to use **any bootable ISO** and set it up with encrypted persistence and documents partitions. This is useful for:
|
||||||
|
|
||||||
|
### Compatible ISOs
|
||||||
|
- **Parrot Security OS** - Privacy-focused security distro
|
||||||
|
- **BlackArch Linux** - Penetration testing distro
|
||||||
|
- **BackBox** - Ubuntu-based penetration testing
|
||||||
|
- **Pentoo** - Gentoo-based security distro
|
||||||
|
- **Any Debian/Ubuntu-based live ISO**
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
Custom ISOs are treated like Kali Linux:
|
||||||
|
1. ISO is flashed to the drive
|
||||||
|
2. LUKS encrypted persistence partition is created (if you want settings to persist)
|
||||||
|
3. VeraCrypt encrypted documents partition is added (if `-d` flag is used)
|
||||||
|
4. Tools partition with mount/lock scripts
|
||||||
|
|
||||||
|
### Example: Parrot OS with Docs
|
||||||
|
```bash
|
||||||
|
sudo ./covert_sd_card_tool.py -c -d -i ~/Downloads/parrot-security.iso
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compatibility Notes
|
||||||
|
- **Best for:** Debian/Ubuntu-based live ISOs
|
||||||
|
- **May not work with:** Arch-based ISOs (different partition structure), Windows ISOs
|
||||||
|
- **Persistence:** Depends on the ISO supporting LUKS persistence (Debian-based usually do)
|
||||||
|
- If persistence doesn't work with your ISO, you can still use the documents partition
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Device Busy Errors
|
||||||
|
- The tool automatically unmounts partitions and kills processes using the drive
|
||||||
|
- If problems persist, manually unmount: `sudo umount /dev/sdX*`
|
||||||
|
- Check for processes: `sudo lsof /dev/sdX`
|
||||||
|
|
||||||
|
### VeraCrypt Not Found
|
||||||
|
- On Debian/Ubuntu: `sudo apt install veracrypt`
|
||||||
|
- Or the script will offer to install it automatically
|
||||||
|
|
||||||
|
### Permission Denied
|
||||||
|
- Always run with `sudo`
|
||||||
|
- Ensure your user has sudo privileges
|
||||||
|
|
||||||
|
### Drive Not Detected
|
||||||
|
- Check if drive is connected: `lsblk`
|
||||||
|
- Verify drive path (e.g., `/dev/sdb` not `/dev/sdb1`)
|
||||||
|
- Try unplugging and reconnecting the device
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This tool is provided as-is for educational and legitimate security purposes only. Use responsibly and in compliance with applicable laws.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions, bug reports, and feature requests are welcome! Please open an issue or submit a pull request.
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
|
||||||
|
This tool performs destructive operations on storage devices. **Always verify you've selected the correct drive** before proceeding. The authors are not responsible for data loss.
|
||||||
+380
-118
@@ -17,21 +17,46 @@ LOG_FILE = f"covert_sd_setup_{TIMESTAMP}.log"
|
|||||||
CREATE_KALI = False
|
CREATE_KALI = False
|
||||||
CREATE_DOCS = False
|
CREATE_DOCS = False
|
||||||
CREATE_TAILS = False
|
CREATE_TAILS = False
|
||||||
|
CREATE_CUSTOM = False
|
||||||
KALI_ISO = ""
|
KALI_ISO = ""
|
||||||
TAILS_ISO = ""
|
TAILS_ISO = ""
|
||||||
|
CUSTOM_ISO = ""
|
||||||
DRIVE = ""
|
DRIVE = ""
|
||||||
|
|
||||||
def log(message):
|
def log(message):
|
||||||
|
"""Logs a message to both the log file and the terminal."""
|
||||||
with open(LOG_FILE, "a") as log_file:
|
with open(LOG_FILE, "a") as log_file:
|
||||||
log_file.write(message + "\n")
|
log_file.write(message + "\n")
|
||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
def run_command(command, shell=False, interactive=False):
|
def run_command(command, shell=False, interactive=False):
|
||||||
|
"""
|
||||||
|
Runs a system command.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (list or str): The command to execute.
|
||||||
|
shell (bool): Whether to execute the command through the shell.
|
||||||
|
interactive (bool): If True, streams the command's output live.
|
||||||
|
"""
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
log(f"Running command: {command}")
|
log(f"Running command: {command}")
|
||||||
try:
|
try:
|
||||||
if interactive:
|
if interactive:
|
||||||
subprocess.run(command, shell=shell, check=True)
|
# Use subprocess.run with no stdout/stderr capture for truly interactive commands
|
||||||
|
# This allows the command to directly interact with the terminal
|
||||||
|
result = subprocess.run(command, shell=shell, check=True)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# Handle non-interactive commands
|
||||||
|
if isinstance(command, list):
|
||||||
|
result = subprocess.run(
|
||||||
|
command,
|
||||||
|
shell=shell,
|
||||||
|
check=True,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
universal_newlines=True
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
command,
|
command,
|
||||||
@@ -50,7 +75,11 @@ def run_command(command, shell=False, interactive=False):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def check_dependencies():
|
def check_dependencies():
|
||||||
dependencies = ["parted", "cryptsetup", "lsblk", "dd", "sgdisk", "wipefs", "bc", "fdisk", "veracrypt", "lsof", "fuser", "mountpoint", "udevadm"]
|
"""Checks and installs missing dependencies."""
|
||||||
|
dependencies = [
|
||||||
|
"parted", "cryptsetup", "lsblk", "dd", "sgdisk", "wipefs",
|
||||||
|
"bc", "fdisk", "veracrypt", "lsof", "fuser", "mountpoint", "udevadm"
|
||||||
|
]
|
||||||
missing = []
|
missing = []
|
||||||
for dep in dependencies:
|
for dep in dependencies:
|
||||||
if not shutil.which(dep):
|
if not shutil.which(dep):
|
||||||
@@ -66,8 +95,10 @@ def check_dependencies():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def list_drives():
|
def list_drives():
|
||||||
|
"""Lists all available drives."""
|
||||||
log("Available drives:")
|
log("Available drives:")
|
||||||
result = subprocess.run(["lsblk", "-J", "-o", "NAME,SIZE,TYPE"], capture_output=True, text=True)
|
result = subprocess.run(["lsblk", "-J", "-o", "NAME,SIZE,TYPE"], capture_output=True, text=True)
|
||||||
|
try:
|
||||||
lsblk_output = json.loads(result.stdout)
|
lsblk_output = json.loads(result.stdout)
|
||||||
for device in lsblk_output['blockdevices']:
|
for device in lsblk_output['blockdevices']:
|
||||||
if device['type'] == 'disk':
|
if device['type'] == 'disk':
|
||||||
@@ -75,14 +106,34 @@ def list_drives():
|
|||||||
size = device['size']
|
size = device['size']
|
||||||
drive = f"/dev/{name} {size}"
|
drive = f"/dev/{name} {size}"
|
||||||
log(drive)
|
log(drive)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
log("Error: Unable to parse lsblk output.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def get_partition_name(drive, partition_number):
|
def get_partition_name(drive, partition_number):
|
||||||
|
"""
|
||||||
|
Generates the partition name based on the drive and partition number.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
drive (str): The drive path (e.g., /dev/sda).
|
||||||
|
partition_number (int): The partition number.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The full partition path (e.g., /dev/sda1 or /dev/nvme0n1p1).
|
||||||
|
"""
|
||||||
if 'nvme' in drive or 'mmcblk' in drive:
|
if 'nvme' in drive or 'mmcblk' in drive:
|
||||||
return f"{drive}p{partition_number}"
|
return f"{drive}p{partition_number}"
|
||||||
else:
|
else:
|
||||||
return f"{drive}{partition_number}"
|
return f"{drive}{partition_number}"
|
||||||
|
|
||||||
def prepare_drive(drive):
|
def prepare_drive(drive):
|
||||||
|
"""
|
||||||
|
Unmounts any mounted partitions, disables swap, and kills processes using the drive.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
drive (str): The drive to prepare (e.g., /dev/sda).
|
||||||
|
"""
|
||||||
|
# Unmount all mounted partitions
|
||||||
result = subprocess.run(["lsblk", "-lnp", drive], capture_output=True, text=True)
|
result = subprocess.run(["lsblk", "-lnp", drive], capture_output=True, text=True)
|
||||||
for line in result.stdout.strip().splitlines():
|
for line in result.stdout.strip().splitlines():
|
||||||
parts = line.strip().split()
|
parts = line.strip().split()
|
||||||
@@ -91,6 +142,7 @@ def prepare_drive(drive):
|
|||||||
log(f"Unmounting {part}...")
|
log(f"Unmounting {part}...")
|
||||||
run_command(["sudo", "umount", "-l", part])
|
run_command(["sudo", "umount", "-l", part])
|
||||||
|
|
||||||
|
# Disable swap if it's on the drive
|
||||||
with open("/proc/swaps") as swaps_file:
|
with open("/proc/swaps") as swaps_file:
|
||||||
for line in swaps_file:
|
for line in swaps_file:
|
||||||
if drive in line:
|
if drive in line:
|
||||||
@@ -98,6 +150,7 @@ def prepare_drive(drive):
|
|||||||
log(f"Disabling swap on {swap_part}...")
|
log(f"Disabling swap on {swap_part}...")
|
||||||
run_command(["sudo", "swapoff", swap_part])
|
run_command(["sudo", "swapoff", swap_part])
|
||||||
|
|
||||||
|
# Kill any processes using the drive
|
||||||
log(f"Checking for processes using {drive}...")
|
log(f"Checking for processes using {drive}...")
|
||||||
result = subprocess.run(["sudo", "lsof", drive], capture_output=True, text=True)
|
result = subprocess.run(["sudo", "lsof", drive], capture_output=True, text=True)
|
||||||
if result.stdout.strip():
|
if result.stdout.strip():
|
||||||
@@ -113,6 +166,9 @@ def prepare_drive(drive):
|
|||||||
log(f"No processes are using {drive}.")
|
log(f"No processes are using {drive}.")
|
||||||
|
|
||||||
def setup_usb():
|
def setup_usb():
|
||||||
|
"""
|
||||||
|
Sets up the bootable USB (Tails or Kali) and creates additional partitions if required.
|
||||||
|
"""
|
||||||
global DRIVE
|
global DRIVE
|
||||||
log("Setting up bootable USB or preparing partitions...")
|
log("Setting up bootable USB or preparing partitions...")
|
||||||
list_drives()
|
list_drives()
|
||||||
@@ -129,16 +185,24 @@ def setup_usb():
|
|||||||
wipe = input(f"Do you want to wipe the drive {DRIVE} before starting? (y/n) [Default: n]: ") or "n"
|
wipe = input(f"Do you want to wipe the drive {DRIVE} before starting? (y/n) [Default: n]: ") or "n"
|
||||||
if wipe.lower() == "y":
|
if wipe.lower() == "y":
|
||||||
log(f"Wiping {DRIVE} and clearing any existing file system or encryption signatures...")
|
log(f"Wiping {DRIVE} and clearing any existing file system or encryption signatures...")
|
||||||
|
log("This will securely overwrite the entire drive with random data. This may take a while...")
|
||||||
|
confirm_wipe = input(f"Are you ABSOLUTELY sure you want to completely wipe {DRIVE}? Type 'WIPE' to confirm: ")
|
||||||
|
if confirm_wipe == "WIPE":
|
||||||
|
run_command(["sudo", "wipefs", "--all", DRIVE])
|
||||||
|
run_command(["sudo", "sgdisk", "--zap-all", DRIVE])
|
||||||
|
# Secure wipe using shred - 3 passes with random data, then zeros
|
||||||
|
run_command(["sudo", "shred", "-vfz", "-n", "3", DRIVE], interactive=True)
|
||||||
|
log(f"{DRIVE} securely wiped successfully.")
|
||||||
|
else:
|
||||||
|
log("Wipe canceled. Proceeding without full wipe (only clearing partition table)...")
|
||||||
run_command(["sudo", "wipefs", "--all", DRIVE])
|
run_command(["sudo", "wipefs", "--all", DRIVE])
|
||||||
run_command(["sudo", "sgdisk", "--zap-all", DRIVE])
|
run_command(["sudo", "sgdisk", "--zap-all", DRIVE])
|
||||||
run_command(["sudo", "dd", "if=/dev/zero", f"of={DRIVE}", "bs=1M", "count=10"])
|
|
||||||
log(f"{DRIVE} wiped successfully.")
|
|
||||||
|
|
||||||
# Initialize variables to track if ISO has been written
|
# Initialize variables to track if ISO has been written
|
||||||
iso_written = False
|
iso_written = False
|
||||||
|
|
||||||
if CREATE_KALI or CREATE_TAILS:
|
if CREATE_KALI or CREATE_TAILS or CREATE_CUSTOM:
|
||||||
global KALI_ISO, TAILS_ISO
|
global KALI_ISO, TAILS_ISO, CUSTOM_ISO
|
||||||
if CREATE_KALI:
|
if CREATE_KALI:
|
||||||
if not KALI_ISO:
|
if not KALI_ISO:
|
||||||
KALI_ISO = input("Enter the path to the Kali ISO file: ")
|
KALI_ISO = input("Enter the path to the Kali ISO file: ")
|
||||||
@@ -153,46 +217,68 @@ def setup_usb():
|
|||||||
log(f"Error: Tails ISO file not found at {TAILS_ISO}")
|
log(f"Error: Tails ISO file not found at {TAILS_ISO}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
ISO_PATH = TAILS_ISO
|
ISO_PATH = TAILS_ISO
|
||||||
|
elif CREATE_CUSTOM:
|
||||||
|
if not CUSTOM_ISO:
|
||||||
|
CUSTOM_ISO = input("Enter the path to your custom ISO file: ")
|
||||||
|
if not os.path.isfile(CUSTOM_ISO):
|
||||||
|
log(f"Error: Custom ISO file not found at {CUSTOM_ISO}")
|
||||||
|
sys.exit(1)
|
||||||
|
ISO_PATH = CUSTOM_ISO
|
||||||
|
|
||||||
log(f"Writing ISO to {DRIVE}...")
|
if CREATE_TAILS:
|
||||||
run_command(f"sudo dd if='{ISO_PATH}' of='{DRIVE}' bs=64M status=progress", shell=True, interactive=True)
|
# For Tails, flash the ISO to the entire drive without any partitioning
|
||||||
log(f"ISO written to {DRIVE} successfully.")
|
log(f"Flashing Tails ISO to {DRIVE}...")
|
||||||
|
run_command(f"sudo dd if='{ISO_PATH}' of='{DRIVE}' bs=64M status=progress conv=fdatasync", shell=True, interactive=True)
|
||||||
|
log(f"Tails ISO flashed to {DRIVE} successfully.")
|
||||||
|
iso_written = True
|
||||||
|
else:
|
||||||
|
# For Kali or Custom ISO, flash and proceed with partition setup
|
||||||
|
log(f"Flashing ISO to {DRIVE}...")
|
||||||
|
run_command(f"sudo dd if='{ISO_PATH}' of='{DRIVE}' bs=64M status=progress conv=fdatasync", shell=True, interactive=True)
|
||||||
|
log(f"ISO flashed to {DRIVE} successfully.")
|
||||||
iso_written = True
|
iso_written = True
|
||||||
|
|
||||||
# After writing ISO, set up partitions accordingly
|
# After writing ISO, set up partitions accordingly
|
||||||
if iso_written:
|
if iso_written:
|
||||||
if CREATE_KALI:
|
if CREATE_KALI or CREATE_CUSTOM:
|
||||||
|
# Both Kali and custom ISOs use the same partitioning approach
|
||||||
fix_partition_table()
|
fix_partition_table()
|
||||||
if CREATE_TAILS:
|
elif CREATE_TAILS:
|
||||||
|
if CREATE_DOCS:
|
||||||
|
# For Tails with docs, add partitions after Tails
|
||||||
fix_partition_table_tails()
|
fix_partition_table_tails()
|
||||||
|
else:
|
||||||
# If documents partition is requested, set it up
|
# Tails only, no additional partitions
|
||||||
if CREATE_DOCS and not (CREATE_KALI or CREATE_TAILS):
|
log("Tails installation complete. No additional partitions requested.")
|
||||||
# If not setting up OS bootable USB, proceed directly
|
elif CREATE_DOCS:
|
||||||
fix_partition_table_docs_only()
|
# If no ISO was written, just set up documents partition
|
||||||
elif CREATE_DOCS and (CREATE_KALI or CREATE_TAILS):
|
|
||||||
# If setting up OS bootable USB, documents partition is handled in fix_partition_table() or fix_partition_table_tails()
|
|
||||||
# Depending on the specific needs, you might want to call fix_partition_table_docs_only() here
|
|
||||||
# Let's call it to ensure documents partition is created
|
|
||||||
fix_partition_table_docs_only()
|
fix_partition_table_docs_only()
|
||||||
|
|
||||||
def fix_partition_table_docs_only():
|
def fix_partition_table_docs_only():
|
||||||
|
"""
|
||||||
|
Sets up partitions solely for encrypted documents without altering existing OS partitions.
|
||||||
|
"""
|
||||||
log("Setting up partitions for documents only...")
|
log("Setting up partitions for documents only...")
|
||||||
|
|
||||||
# Clear existing partitions if any
|
# Clear existing GPT label to start fresh
|
||||||
run_command(f"sudo parted -a optimal -s {DRIVE} mklabel gpt", shell=True)
|
run_command(f"sudo parted -a optimal -s {DRIVE} mklabel gpt", shell=True)
|
||||||
run_command(f"sudo partprobe {DRIVE}", shell=True)
|
run_command(f"sudo partprobe {DRIVE}", shell=True)
|
||||||
run_command("sudo udevadm settle", shell=True)
|
run_command("sudo udevadm settle", shell=True)
|
||||||
time.sleep(5) # Increased sleep to ensure partitions are recognized
|
time.sleep(5) # Increased sleep to ensure partitions are recognized
|
||||||
|
|
||||||
# Get the total size of the drive in bytes
|
# Get the total size of the drive in bytes
|
||||||
result = subprocess.run(["lsblk", "-b", "-n", "-o", "SIZE", DRIVE], capture_output=True, text=True)
|
result = subprocess.run(["lsblk", "-b", "-d", "-n", "-o", "SIZE", DRIVE], capture_output=True, text=True)
|
||||||
try:
|
try:
|
||||||
total_size_bytes = int(result.stdout.strip())
|
total_size_bytes = int(result.stdout.strip())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
log("Error: Unable to determine drive size.")
|
log(f"Error: Unable to determine drive size. lsblk output: {result.stdout}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
total_size_mib = total_size_bytes / (1024 * 1024) # Convert to MiB
|
total_size_mib = total_size_bytes / (1024 * 1024) # Convert to MiB
|
||||||
|
total_size_gb = total_size_mib / 1024 # Convert to GiB
|
||||||
|
available_gb = (total_size_mib - 1024) / 1024 # Minus 1GB reserved for scripts
|
||||||
|
|
||||||
|
log(f"Total drive size: {total_size_gb:.2f} GB ({total_size_mib:.0f} MiB)")
|
||||||
|
log(f"Available space for documents (minus 1GB for scripts): {available_gb:.2f} GB")
|
||||||
|
|
||||||
# Ask for document partition size
|
# Ask for document partition size
|
||||||
size_docs = input("Enter size for documents partition in GB (leave blank to use remaining space minus 1GB): ")
|
size_docs = input("Enter size for documents partition in GB (leave blank to use remaining space minus 1GB): ")
|
||||||
@@ -227,7 +313,103 @@ def fix_partition_table_docs_only():
|
|||||||
setup_unencrypted_partition()
|
setup_unencrypted_partition()
|
||||||
setup_docs_partition()
|
setup_docs_partition()
|
||||||
|
|
||||||
|
def fix_partition_table_tails():
|
||||||
|
"""
|
||||||
|
Adds encrypted documents partition after Tails installation without breaking boot.
|
||||||
|
Tails creates its own partition table, so we extend it carefully.
|
||||||
|
"""
|
||||||
|
log("Adding encrypted documents partition after Tails installation...")
|
||||||
|
|
||||||
|
# Wait for Tails partitions to settle
|
||||||
|
run_command(f"sudo partprobe {DRIVE}", shell=True)
|
||||||
|
run_command("sudo udevadm settle", shell=True)
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
# Get current partition information
|
||||||
|
result = subprocess.run(["sudo", "parted", "-s", DRIVE, "unit", "MiB", "print"], capture_output=True, text=True)
|
||||||
|
log("Current partition table after Tails installation:")
|
||||||
|
log(result.stdout)
|
||||||
|
|
||||||
|
# Find the end of the last Tails partition
|
||||||
|
last_partition_end = None
|
||||||
|
partition_lines = [line for line in result.stdout.strip().splitlines() if line.strip() and line.strip()[0].isdigit()]
|
||||||
|
|
||||||
|
if partition_lines:
|
||||||
|
# Get the last partition's end position
|
||||||
|
last_line = partition_lines[-1]
|
||||||
|
parts = last_line.strip().split()
|
||||||
|
if len(parts) >= 3:
|
||||||
|
last_partition_end = parts[2].replace('MiB', '')
|
||||||
|
|
||||||
|
if last_partition_end is None:
|
||||||
|
log("Error: Could not determine end of Tails partitions.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
log(f"Last Tails partition ends at: {last_partition_end}MiB")
|
||||||
|
|
||||||
|
# Get the total size of the drive
|
||||||
|
result = subprocess.run(["lsblk", "-b", "-d", "-n", "-o", "SIZE", DRIVE], capture_output=True, text=True)
|
||||||
|
try:
|
||||||
|
total_size_bytes = int(result.stdout.strip())
|
||||||
|
except ValueError:
|
||||||
|
log(f"Error: Unable to determine drive size. lsblk output: {result.stdout}")
|
||||||
|
sys.exit(1)
|
||||||
|
total_size_mib = total_size_bytes / (1024 * 1024)
|
||||||
|
total_size_gb = total_size_mib / 1024
|
||||||
|
available_after_tails_mib = total_size_mib - float(last_partition_end)
|
||||||
|
available_after_tails_gb = available_after_tails_mib / 1024
|
||||||
|
|
||||||
|
log(f"Total drive size: {total_size_gb:.2f} GB ({total_size_mib:.0f} MiB)")
|
||||||
|
log(f"Available space after Tails: {available_after_tails_gb:.2f} GB")
|
||||||
|
|
||||||
|
if available_after_tails_gb < 2:
|
||||||
|
log(f"Warning: Only {available_after_tails_gb:.2f} GB available after Tails. Need at least 2GB for docs + tools partitions.")
|
||||||
|
proceed = input("Continue anyway? (y/n) [Default: n]: ") or "n"
|
||||||
|
if proceed.lower() != "y":
|
||||||
|
log("Partition setup canceled.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Set up documents partition
|
||||||
|
start_docs_mib = float(last_partition_end)
|
||||||
|
remaining_after_tails_gb = (total_size_mib - start_docs_mib) / 1024
|
||||||
|
log(f"Remaining space for documents: {remaining_after_tails_gb:.2f} GB (will reserve 1GB for tools partition)")
|
||||||
|
|
||||||
|
size_docs = input("Enter size for documents partition in GB (leave blank to use remaining space minus 1GB): ")
|
||||||
|
if size_docs:
|
||||||
|
try:
|
||||||
|
size_docs_gb = float(size_docs)
|
||||||
|
end_docs_mib = start_docs_mib + (size_docs_gb * 1024)
|
||||||
|
if end_docs_mib > (total_size_mib - 1024):
|
||||||
|
log("Error: Documents partition size exceeds available space when reserving 1GB for tools partition.")
|
||||||
|
sys.exit(1)
|
||||||
|
except ValueError:
|
||||||
|
log("Invalid size entered for documents partition. Exiting.")
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
end_docs_mib = total_size_mib - 1024 # Reserve 1GB for tools partition
|
||||||
|
|
||||||
|
run_command(f"sudo parted -a optimal -s {DRIVE} mkpart primary {start_docs_mib}MiB {end_docs_mib}MiB", shell=True)
|
||||||
|
log("Created documents partition after Tails.")
|
||||||
|
|
||||||
|
# Create unencrypted tools partition
|
||||||
|
start_unencrypted_mib = end_docs_mib
|
||||||
|
run_command(f"sudo parted -a optimal -s {DRIVE} mkpart primary {start_unencrypted_mib}MiB 100%", shell=True)
|
||||||
|
log("Created tools partition for scripts/instructions.")
|
||||||
|
|
||||||
|
# Refresh partition table
|
||||||
|
run_command(f"sudo partprobe {DRIVE}", shell=True)
|
||||||
|
run_command("sudo udevadm settle", shell=True)
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
setup_docs_partition()
|
||||||
|
setup_unencrypted_partition()
|
||||||
|
|
||||||
|
log("Tails + encrypted documents partition setup complete!")
|
||||||
|
|
||||||
def fix_partition_table():
|
def fix_partition_table():
|
||||||
|
"""
|
||||||
|
Fixes the partition table for Kali Linux by adding persistence and documents partitions.
|
||||||
|
"""
|
||||||
log("Fixing partition table to reclaim remaining space...")
|
log("Fixing partition table to reclaim remaining space...")
|
||||||
|
|
||||||
# Attempt to delete partition 2 if it exists
|
# Attempt to delete partition 2 if it exists
|
||||||
@@ -253,13 +435,18 @@ def fix_partition_table():
|
|||||||
log(f"End of partition 1: {end_of_p1}MiB")
|
log(f"End of partition 1: {end_of_p1}MiB")
|
||||||
|
|
||||||
# Get the total size of the drive in bytes
|
# Get the total size of the drive in bytes
|
||||||
result = subprocess.run(["lsblk", "-b", "-n", "-o", "SIZE", DRIVE], capture_output=True, text=True)
|
result = subprocess.run(["lsblk", "-b", "-d", "-n", "-o", "SIZE", DRIVE], capture_output=True, text=True)
|
||||||
try:
|
try:
|
||||||
total_size_bytes = int(result.stdout.strip())
|
total_size_bytes = int(result.stdout.strip())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
log("Error: Unable to determine drive size.")
|
log(f"Error: Unable to determine drive size. lsblk output: {result.stdout}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
total_size_mib = total_size_bytes / (1024 * 1024) # Convert to MiB
|
total_size_mib = total_size_bytes / (1024 * 1024) # Convert to MiB
|
||||||
|
total_size_gb = total_size_mib / 1024 # Convert to GiB
|
||||||
|
available_after_p1_gb = (total_size_mib - float(end_of_p1)) / 1024
|
||||||
|
|
||||||
|
log(f"Total drive size: {total_size_gb:.2f} GB ({total_size_mib:.0f} MiB)")
|
||||||
|
log(f"Available space after partition 1: {available_after_p1_gb:.2f} GB")
|
||||||
|
|
||||||
# Ask for persistence partition size
|
# Ask for persistence partition size
|
||||||
size_persistence = input("Enter size for persistence partition in GB (e.g., 4): ") or "4"
|
size_persistence = input("Enter size for persistence partition in GB (e.g., 4): ") or "4"
|
||||||
@@ -277,11 +464,14 @@ def fix_partition_table():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Create persistence partition
|
# Create persistence partition
|
||||||
run_command(f"sudo parted -a optimal -s {DRIVE} mkpart primary {start_persistence_mib}MiB {end_persistence_mib}MiB", shell=True)
|
run_command(f"sudo parted -a optimal -s {DRIVE} mkpart primary ext4 {start_persistence_mib}MiB {end_persistence_mib}MiB", shell=True)
|
||||||
log("Created persistence partition.")
|
log("Created persistence partition.")
|
||||||
|
|
||||||
# Set up documents partition
|
# Set up documents partition
|
||||||
start_docs_mib = end_persistence_mib
|
start_docs_mib = end_persistence_mib
|
||||||
|
remaining_after_persistence_gb = (total_size_mib - end_persistence_mib) / 1024
|
||||||
|
log(f"Remaining space after persistence partition: {remaining_after_persistence_gb:.2f} GB (will reserve 1GB for scripts)")
|
||||||
|
|
||||||
size_docs = input("Enter size for documents partition in GB (leave blank to use remaining space minus 1GB): ")
|
size_docs = input("Enter size for documents partition in GB (leave blank to use remaining space minus 1GB): ")
|
||||||
if size_docs:
|
if size_docs:
|
||||||
try:
|
try:
|
||||||
@@ -314,27 +504,10 @@ def fix_partition_table():
|
|||||||
setup_docs_partition()
|
setup_docs_partition()
|
||||||
setup_unencrypted_partition()
|
setup_unencrypted_partition()
|
||||||
|
|
||||||
def fix_partition_table_tails():
|
|
||||||
log("Setting up partition table for Tails...")
|
|
||||||
|
|
||||||
# Clear existing partitions if any
|
|
||||||
run_command(f"sudo parted -a optimal -s {DRIVE} mklabel gpt", shell=True)
|
|
||||||
run_command(f"sudo partprobe {DRIVE}", shell=True)
|
|
||||||
run_command("sudo udevadm settle", shell=True)
|
|
||||||
time.sleep(5) # Increased sleep to ensure partitions are recognized
|
|
||||||
|
|
||||||
# Tails typically does not require a persistence partition, but we'll create an unencrypted partition for scripts/instructions
|
|
||||||
run_command(f"sudo parted -a optimal -s {DRIVE} mkpart primary 1MiB 100%", shell=True)
|
|
||||||
log("Created unencrypted partition for scripts/instructions.")
|
|
||||||
|
|
||||||
# Refresh partition table to recognize new partitions
|
|
||||||
run_command(f"sudo partprobe {DRIVE}", shell=True)
|
|
||||||
run_command("sudo udevadm settle", shell=True)
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
setup_unencrypted_partition()
|
|
||||||
|
|
||||||
def setup_kali_partition():
|
def setup_kali_partition():
|
||||||
|
"""
|
||||||
|
Configures the persistence partition for Kali Linux.
|
||||||
|
"""
|
||||||
global DRIVE
|
global DRIVE
|
||||||
PERSIST_PART = get_partition_name(DRIVE, 2)
|
PERSIST_PART = get_partition_name(DRIVE, 2)
|
||||||
|
|
||||||
@@ -347,6 +520,11 @@ def setup_kali_partition():
|
|||||||
|
|
||||||
log("Configuring encrypted persistence partition...")
|
log("Configuring encrypted persistence partition...")
|
||||||
|
|
||||||
|
log("You will be prompted to enter a passphrase for the persistence partition.")
|
||||||
|
log("Please choose a strong passphrase and remember it!")
|
||||||
|
log("When asked 'Are you sure? (Type YES in capital letters):', type: YES")
|
||||||
|
log("Then enter your passphrase twice when prompted.")
|
||||||
|
|
||||||
if FAST_MODE:
|
if FAST_MODE:
|
||||||
luks_format_cmd = (
|
luks_format_cmd = (
|
||||||
f"sudo cryptsetup luksFormat '{PERSIST_PART}' "
|
f"sudo cryptsetup luksFormat '{PERSIST_PART}' "
|
||||||
@@ -355,6 +533,7 @@ def setup_kali_partition():
|
|||||||
f"--key-size 256 "
|
f"--key-size 256 "
|
||||||
f"--hash sha256 "
|
f"--hash sha256 "
|
||||||
f"--iter-time 1000 "
|
f"--iter-time 1000 "
|
||||||
|
f"--verify-passphrase"
|
||||||
)
|
)
|
||||||
mkfs_cmd = f"sudo mkfs.ext3 -L persistence /dev/mapper/kali_USB"
|
mkfs_cmd = f"sudo mkfs.ext3 -L persistence /dev/mapper/kali_USB"
|
||||||
else:
|
else:
|
||||||
@@ -364,6 +543,7 @@ def setup_kali_partition():
|
|||||||
f"--key-size 512 "
|
f"--key-size 512 "
|
||||||
f"--hash sha512 "
|
f"--hash sha512 "
|
||||||
f"--iter-time 5000 "
|
f"--iter-time 5000 "
|
||||||
|
f"--verify-passphrase"
|
||||||
)
|
)
|
||||||
mkfs_cmd = f"sudo mkfs.ext4 -L persistence /dev/mapper/kali_USB"
|
mkfs_cmd = f"sudo mkfs.ext4 -L persistence /dev/mapper/kali_USB"
|
||||||
|
|
||||||
@@ -381,6 +561,9 @@ def setup_kali_partition():
|
|||||||
log("Kali persistence setup complete.")
|
log("Kali persistence setup complete.")
|
||||||
|
|
||||||
def setup_docs_partition():
|
def setup_docs_partition():
|
||||||
|
"""
|
||||||
|
Configures the VeraCrypt encrypted documents partition.
|
||||||
|
"""
|
||||||
global DRIVE
|
global DRIVE
|
||||||
DOCS_PART = get_partition_name(DRIVE, get_last_partition_number() - 1)
|
DOCS_PART = get_partition_name(DRIVE, get_last_partition_number() - 1)
|
||||||
|
|
||||||
@@ -389,32 +572,48 @@ def setup_docs_partition():
|
|||||||
log(f"Error: Partition {DOCS_PART} does not exist.")
|
log(f"Error: Partition {DOCS_PART} does not exist.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
run_command(["sudo", "wipefs", "--all", DOCS_PART])
|
# Force wipe existing filesystem signatures
|
||||||
|
run_command(["sudo", "wipefs", "--all", "--force", DOCS_PART])
|
||||||
|
log(f"Removed existing filesystem signatures from {DOCS_PART}.")
|
||||||
|
|
||||||
log("Configuring VeraCrypt encryption for documents partition...")
|
log("\n" + "="*70)
|
||||||
|
log("ENCRYPTED VOLUME SETUP")
|
||||||
|
log("="*70)
|
||||||
|
log("\nYou will now create an encrypted volume for sensitive documents.")
|
||||||
|
log("\nWhat you'll be asked:")
|
||||||
|
log(" 1. PASSWORD: Enter a strong passphrase (you'll type it twice)")
|
||||||
|
log(" - Use at least 20 characters")
|
||||||
|
log(" - Mix uppercase, lowercase, numbers, and symbols")
|
||||||
|
log(" - Avoid dictionary words or personal information")
|
||||||
|
log(" 2. PIM (Personal Iterations Multiplier):")
|
||||||
|
log(" - RECOMMENDED: Enter 2000 for maximum security")
|
||||||
|
log(" - Minimum acceptable: 1000")
|
||||||
|
log(" - Higher = more secure but slower unlock (2-3 seconds)")
|
||||||
|
log(" 3. KEYFILES: Leave blank unless you know what you're doing")
|
||||||
|
log("\nIMPORTANT: Remember your password! There is NO password recovery!")
|
||||||
|
log("="*70)
|
||||||
|
input("\nPress ENTER to continue with encryption setup...")
|
||||||
|
|
||||||
if FAST_MODE:
|
log("\nConfiguring VeraCrypt encryption for documents partition...")
|
||||||
veracrypt_create_cmd = (
|
|
||||||
f"veracrypt --text --create '{DOCS_PART}' "
|
# Always use maximum security for documents partition (ignore FAST_MODE)
|
||||||
f"--encryption AES "
|
# Triple cascade encryption with strongest hash
|
||||||
f"--hash SHA-256 "
|
|
||||||
f"--filesystem exfat "
|
|
||||||
f"--volume-type normal "
|
|
||||||
f"--quick "
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
veracrypt_create_cmd = (
|
veracrypt_create_cmd = (
|
||||||
f"veracrypt --text --create '{DOCS_PART}' "
|
f"veracrypt --text --create '{DOCS_PART}' "
|
||||||
f"--encryption AES-Twofish-Serpent "
|
f"--encryption AES-Twofish-Serpent "
|
||||||
f"--hash whirlpool "
|
f"--hash SHA-512 "
|
||||||
f"--filesystem exfat "
|
f"--filesystem ext4 "
|
||||||
f"--volume-type normal "
|
f"--volume-type normal "
|
||||||
|
f"--pim 2000 " # Enforce strong PIM for maximum security
|
||||||
)
|
)
|
||||||
|
|
||||||
run_command(veracrypt_create_cmd, shell=True, interactive=True)
|
run_command(veracrypt_create_cmd, shell=True, interactive=True)
|
||||||
log("Encrypted documents partition setup complete.")
|
log("Encrypted documents partition setup complete.")
|
||||||
|
|
||||||
def setup_unencrypted_partition():
|
def setup_unencrypted_partition():
|
||||||
|
"""
|
||||||
|
Sets up the unencrypted partition for scripts and instructions.
|
||||||
|
"""
|
||||||
global DRIVE
|
global DRIVE
|
||||||
UNENCRYPTED_PART = get_partition_name(DRIVE, get_last_partition_number())
|
UNENCRYPTED_PART = get_partition_name(DRIVE, get_last_partition_number())
|
||||||
|
|
||||||
@@ -431,14 +630,19 @@ def setup_unencrypted_partition():
|
|||||||
run_command(f"sudo mount {UNENCRYPTED_PART} /mnt/unencrypted", shell=True)
|
run_command(f"sudo mount {UNENCRYPTED_PART} /mnt/unencrypted", shell=True)
|
||||||
|
|
||||||
instructions = f"""
|
instructions = f"""
|
||||||
To mount the encrypted documents partition, use the provided 'mount_encrypted_partitions.sh' script.
|
INSTRUCTIONS FOR ACCESSING SECURE STORAGE
|
||||||
To unmount and lock it, use the 'cleanup_encrypted_partitions.sh' script.
|
|
||||||
|
|
||||||
**Automount Script:**
|
To access your secure partition:
|
||||||
Run: sudo ./mount_encrypted_partitions.sh
|
1. Run: sudo ./mount_storage.sh
|
||||||
|
2. Enter your password when prompted
|
||||||
|
3. Your files will be available at /mnt/secure_storage
|
||||||
|
|
||||||
**Cleanup Script:**
|
To safely lock your storage:
|
||||||
Run: sudo ./cleanup_encrypted_partitions.sh
|
1. Close all files and applications using the storage
|
||||||
|
2. Run: sudo ./lock_storage.sh
|
||||||
|
3. Your data is now secured
|
||||||
|
|
||||||
|
IMPORTANT: Always lock your storage before removing the device.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with open("/tmp/README.txt", "w") as readme_file:
|
with open("/tmp/README.txt", "w") as readme_file:
|
||||||
@@ -448,60 +652,114 @@ Run: sudo ./cleanup_encrypted_partitions.sh
|
|||||||
log("Created README.txt with mounting instructions.")
|
log("Created README.txt with mounting instructions.")
|
||||||
|
|
||||||
mount_script = """#!/bin/bash
|
mount_script = """#!/bin/bash
|
||||||
# Script to mount encrypted documents partition
|
# Script to mount secure storage partition
|
||||||
|
|
||||||
echo "Available drives:"
|
echo "=== Secure Storage Mount ==="
|
||||||
lsblk -o NAME,SIZE,TYPE | grep disk
|
echo ""
|
||||||
read -p "Enter the drive path for the documents partition (default: /dev/sdc1): " DRIVE_PATH
|
echo "Available storage devices:"
|
||||||
DRIVE_PATH=${DRIVE_PATH:-/dev/sdc1}
|
lsblk -o NAME,SIZE,TYPE,LABEL | grep -E 'disk|part'
|
||||||
|
echo ""
|
||||||
|
read -p "Enter the partition path (e.g., /dev/sdb3): " DRIVE_PATH
|
||||||
|
|
||||||
if [ -b "$DRIVE_PATH" ]; then
|
if [ -z "$DRIVE_PATH" ]; then
|
||||||
echo "Mounting VeraCrypt documents partition at $DRIVE_PATH..."
|
echo "Error: No partition specified."
|
||||||
sudo mkdir -p /mnt/veracrypt_docs
|
exit 1
|
||||||
sudo veracrypt --text --mount "$DRIVE_PATH" /mnt/veracrypt_docs
|
fi
|
||||||
echo "Documents partition mounted at /mnt/veracrypt_docs."
|
|
||||||
|
if [ ! -b "$DRIVE_PATH" ]; then
|
||||||
|
echo "Error: $DRIVE_PATH is not a valid block device."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Mounting secure storage from $DRIVE_PATH..."
|
||||||
|
sudo mkdir -p /mnt/secure_storage
|
||||||
|
|
||||||
|
# Mount the encrypted volume
|
||||||
|
if sudo veracrypt --text --mount "$DRIVE_PATH" /mnt/secure_storage; then
|
||||||
|
echo ""
|
||||||
|
echo "SUCCESS: Secure storage is now accessible at /mnt/secure_storage"
|
||||||
|
echo ""
|
||||||
|
echo "Remember to run ./lock_storage.sh when finished!"
|
||||||
else
|
else
|
||||||
echo "Error: Partition $DRIVE_PATH not found."
|
echo ""
|
||||||
|
echo "ERROR: Failed to mount storage. Check your password and try again."
|
||||||
|
sudo rmdir /mnt/secure_storage 2>/dev/null
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with open("/tmp/mount_encrypted_partitions.sh", "w") as script_file:
|
with open("/tmp/mount_storage.sh", "w") as script_file:
|
||||||
script_file.write(mount_script)
|
script_file.write(mount_script)
|
||||||
run_command("sudo cp /tmp/mount_encrypted_partitions.sh /mnt/unencrypted/mount_encrypted_partitions.sh", shell=True)
|
run_command("sudo cp /tmp/mount_storage.sh /mnt/unencrypted/mount_storage.sh", shell=True)
|
||||||
run_command("sudo chmod +x /mnt/unencrypted/mount_encrypted_partitions.sh", shell=True)
|
run_command("sudo chmod +x /mnt/unencrypted/mount_storage.sh", shell=True)
|
||||||
run_command("sudo rm /tmp/mount_encrypted_partitions.sh", shell=True)
|
run_command("sudo rm /tmp/mount_storage.sh", shell=True)
|
||||||
log("Created mount_encrypted_partitions.sh script.")
|
log("Created mount_storage.sh script.")
|
||||||
|
|
||||||
cleanup_script = """#!/bin/bash
|
cleanup_script = """#!/bin/bash
|
||||||
# Script to unmount and lock encrypted documents partition
|
# Script to safely lock secure storage
|
||||||
|
|
||||||
echo "Available drives:"
|
echo "=== Secure Storage Lock ==="
|
||||||
lsblk -o NAME,SIZE,TYPE | grep disk
|
echo ""
|
||||||
read -p "Enter the drive path for the documents partition (default: /dev/sdc1): " DRIVE_PATH
|
|
||||||
DRIVE_PATH=${DRIVE_PATH:-/dev/sdc1}
|
|
||||||
|
|
||||||
echo "Unmounting and locking encrypted documents partition at $DRIVE_PATH..."
|
# Check if storage is mounted
|
||||||
|
if mountpoint -q /mnt/secure_storage; then
|
||||||
|
echo "Checking for open files..."
|
||||||
|
|
||||||
if mountpoint -q /mnt/veracrypt_docs; then
|
# Check if any processes are using the mount
|
||||||
sudo veracrypt --text --dismount /mnt/veracrypt_docs
|
if sudo lsof /mnt/secure_storage 2>/dev/null | grep -q /mnt/secure_storage; then
|
||||||
echo "VeraCrypt documents partition unmounted."
|
echo ""
|
||||||
|
echo "WARNING: Files are still open in the secure storage!"
|
||||||
|
echo "Open files/processes:"
|
||||||
|
sudo lsof /mnt/secure_storage 2>/dev/null
|
||||||
|
echo ""
|
||||||
|
read -p "Force close and lock anyway? (y/N): " FORCE
|
||||||
|
if [ "$FORCE" != "y" ] && [ "$FORCE" != "Y" ]; then
|
||||||
|
echo "Lock cancelled. Please close all files and try again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Locking secure storage..."
|
||||||
|
|
||||||
|
# Sync any pending writes
|
||||||
|
sync
|
||||||
|
|
||||||
|
# Dismount the encrypted volume
|
||||||
|
if sudo veracrypt --text --dismount /mnt/secure_storage; then
|
||||||
|
sudo rmdir /mnt/secure_storage 2>/dev/null
|
||||||
|
echo ""
|
||||||
|
echo "SUCCESS: Secure storage is now locked."
|
||||||
|
echo "Your data is safe."
|
||||||
else
|
else
|
||||||
echo "Documents partition is not currently mounted."
|
echo ""
|
||||||
|
echo "ERROR: Failed to lock storage. Try closing all applications and run again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Secure storage is not currently mounted."
|
||||||
|
echo "Nothing to lock."
|
||||||
fi
|
fi
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with open("/tmp/cleanup_encrypted_partitions.sh", "w") as script_file:
|
with open("/tmp/lock_storage.sh", "w") as script_file:
|
||||||
script_file.write(cleanup_script)
|
script_file.write(cleanup_script)
|
||||||
run_command("sudo cp /tmp/cleanup_encrypted_partitions.sh /mnt/unencrypted/cleanup_encrypted_partitions.sh", shell=True)
|
run_command("sudo cp /tmp/lock_storage.sh /mnt/unencrypted/lock_storage.sh", shell=True)
|
||||||
run_command("sudo chmod +x /mnt/unencrypted/cleanup_encrypted_partitions.sh", shell=True)
|
run_command("sudo chmod +x /mnt/unencrypted/lock_storage.sh", shell=True)
|
||||||
run_command("sudo rm /tmp/cleanup_encrypted_partitions.sh", shell=True)
|
run_command("sudo rm /tmp/lock_storage.sh", shell=True)
|
||||||
log("Created cleanup_encrypted_partitions.sh script.")
|
log("Created lock_storage.sh script.")
|
||||||
|
|
||||||
run_command("sudo umount /mnt/unencrypted", shell=True)
|
run_command("sudo umount /mnt/unencrypted", shell=True)
|
||||||
log("Unencrypted partition setup complete.")
|
log("Unencrypted partition setup complete.")
|
||||||
|
|
||||||
def get_last_partition_number():
|
def get_last_partition_number():
|
||||||
"""Returns the highest partition number on the DRIVE."""
|
"""
|
||||||
|
Returns the highest partition number on the DRIVE.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: The highest partition number.
|
||||||
|
"""
|
||||||
result = subprocess.run(["lsblk", "-ln", "-o", "NAME", DRIVE], capture_output=True, text=True)
|
result = subprocess.run(["lsblk", "-ln", "-o", "NAME", DRIVE], capture_output=True, text=True)
|
||||||
partitions = [line.strip() for line in result.stdout.strip().splitlines() if line.strip()]
|
partitions = [line.strip() for line in result.stdout.strip().splitlines() if line.strip()]
|
||||||
partition_numbers = []
|
partition_numbers = []
|
||||||
@@ -524,20 +782,35 @@ def get_last_partition_number():
|
|||||||
return max(partition_numbers)
|
return max(partition_numbers)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global DEBUG, FAST_MODE, CREATE_KALI, CREATE_DOCS, CREATE_TAILS, KALI_ISO, TAILS_ISO, DRIVE
|
"""
|
||||||
|
The main function that parses arguments and orchestrates the setup process.
|
||||||
|
"""
|
||||||
|
global DEBUG, FAST_MODE, CREATE_KALI, CREATE_DOCS, CREATE_TAILS, KALI_ISO, TAILS_ISO, DRIVE, CREATE_CUSTOM, CUSTOM_ISO
|
||||||
|
|
||||||
|
CREATE_CUSTOM = False
|
||||||
|
CUSTOM_ISO = ""
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Covert SD Card Tool")
|
parser = argparse.ArgumentParser(description="Covert SD Card Tool")
|
||||||
parser.add_argument("-a", "--all", action="store_true", help="Set up both OS bootable USB and documents partition")
|
|
||||||
|
# Creating a mutually exclusive group for -a and -t to prevent their simultaneous use
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument("-a", "--all", action="store_true", help="Set up both OS bootable USB and documents partition")
|
||||||
|
group.add_argument("-t", "--tails", action="store_true", help="Create Tails bootable USB (no persistence)")
|
||||||
|
|
||||||
|
# Other arguments remain outside the mutually exclusive group
|
||||||
parser.add_argument("-k", "--kali", action="store_true", help="Create Kali bootable USB and persistence partition")
|
parser.add_argument("-k", "--kali", action="store_true", help="Create Kali bootable USB and persistence partition")
|
||||||
parser.add_argument("-d", "--docs", action="store_true", help="Create encrypted documents partition")
|
parser.add_argument("-d", "--docs", action="store_true", help="Create encrypted documents partition")
|
||||||
parser.add_argument("-t", "--tails", action="store_true", help="Create Tails bootable USB (no persistence)")
|
parser.add_argument("-c", "--custom", action="store_true", help="Create custom ISO bootable USB (like Kali, with persistence)")
|
||||||
parser.add_argument("-i", "--iso", help="Path to the Kali or Tails ISO file")
|
parser.add_argument("-i", "--iso", help="Path to the ISO file (Kali, Tails, or custom)")
|
||||||
parser.add_argument("--fast", action="store_true", help="Enable fast setup with less secure encryption")
|
parser.add_argument("--fast", action="store_true", help="Enable fast setup with less secure encryption")
|
||||||
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
|
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if not any([args.all, args.kali, args.docs, args.tails]):
|
# Prevent using -a with -t; argparse handles this due to mutually exclusive group
|
||||||
|
# However, if you want to provide a custom error message or additional handling, you can add it here
|
||||||
|
|
||||||
|
if not any([args.all, args.kali, args.docs, args.tails, args.custom]):
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
@@ -551,35 +824,24 @@ def main():
|
|||||||
|
|
||||||
if args.all:
|
if args.all:
|
||||||
CREATE_DOCS = True
|
CREATE_DOCS = True
|
||||||
if args.tails:
|
# When -a is used without -t, default to creating Kali
|
||||||
CREATE_TAILS = True
|
|
||||||
else:
|
|
||||||
CREATE_KALI = True
|
CREATE_KALI = True
|
||||||
else:
|
else:
|
||||||
CREATE_KALI = args.kali
|
CREATE_KALI = args.kali
|
||||||
CREATE_DOCS = args.docs
|
CREATE_DOCS = args.docs
|
||||||
CREATE_TAILS = args.tails
|
CREATE_TAILS = args.tails
|
||||||
|
CREATE_CUSTOM = args.custom
|
||||||
|
|
||||||
if args.iso:
|
if args.iso:
|
||||||
if CREATE_KALI:
|
if CREATE_KALI:
|
||||||
KALI_ISO = args.iso
|
KALI_ISO = args.iso
|
||||||
elif CREATE_TAILS:
|
elif CREATE_TAILS:
|
||||||
TAILS_ISO = args.iso
|
TAILS_ISO = args.iso
|
||||||
|
elif CREATE_CUSTOM:
|
||||||
|
CUSTOM_ISO = args.iso
|
||||||
|
|
||||||
check_dependencies()
|
check_dependencies()
|
||||||
|
|
||||||
if CREATE_KALI or CREATE_TAILS or CREATE_DOCS:
|
|
||||||
setup_usb()
|
setup_usb()
|
||||||
else:
|
|
||||||
list_drives()
|
|
||||||
DRIVE = input("Enter the drive to use (e.g., /dev/sda) [Default: /dev/sda]: ") or "/dev/sda"
|
|
||||||
prepare_drive(DRIVE)
|
|
||||||
|
|
||||||
if CREATE_DOCS:
|
|
||||||
fix_partition_table_docs_only()
|
|
||||||
else:
|
|
||||||
setup_unencrypted_partition()
|
|
||||||
|
|
||||||
log("Partition setup complete.")
|
log("Partition setup complete.")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user