fixed issues and improved security
This commit is contained in:
+408
-146
@@ -17,30 +17,55 @@ LOG_FILE = f"covert_sd_setup_{TIMESTAMP}.log"
|
||||
CREATE_KALI = False
|
||||
CREATE_DOCS = False
|
||||
CREATE_TAILS = False
|
||||
CREATE_CUSTOM = False
|
||||
KALI_ISO = ""
|
||||
TAILS_ISO = ""
|
||||
CUSTOM_ISO = ""
|
||||
DRIVE = ""
|
||||
|
||||
def log(message):
|
||||
"""Logs a message to both the log file and the terminal."""
|
||||
with open(LOG_FILE, "a") as log_file:
|
||||
log_file.write(message + "\n")
|
||||
print(message)
|
||||
|
||||
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:
|
||||
log(f"Running command: {command}")
|
||||
try:
|
||||
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:
|
||||
result = subprocess.run(
|
||||
command,
|
||||
shell=shell,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
universal_newlines=True
|
||||
)
|
||||
# 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:
|
||||
result = subprocess.run(
|
||||
command,
|
||||
shell=shell,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
universal_newlines=True
|
||||
)
|
||||
if result.stdout:
|
||||
log(result.stdout.strip())
|
||||
if result.stderr:
|
||||
@@ -50,7 +75,11 @@ def run_command(command, shell=False, interactive=False):
|
||||
sys.exit(1)
|
||||
|
||||
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 = []
|
||||
for dep in dependencies:
|
||||
if not shutil.which(dep):
|
||||
@@ -66,23 +95,45 @@ def check_dependencies():
|
||||
sys.exit(1)
|
||||
|
||||
def list_drives():
|
||||
"""Lists all available drives."""
|
||||
log("Available drives:")
|
||||
result = subprocess.run(["lsblk", "-J", "-o", "NAME,SIZE,TYPE"], capture_output=True, text=True)
|
||||
lsblk_output = json.loads(result.stdout)
|
||||
for device in lsblk_output['blockdevices']:
|
||||
if device['type'] == 'disk':
|
||||
name = device['name']
|
||||
size = device['size']
|
||||
drive = f"/dev/{name} {size}"
|
||||
log(drive)
|
||||
try:
|
||||
lsblk_output = json.loads(result.stdout)
|
||||
for device in lsblk_output['blockdevices']:
|
||||
if device['type'] == 'disk':
|
||||
name = device['name']
|
||||
size = device['size']
|
||||
drive = f"/dev/{name} {size}"
|
||||
log(drive)
|
||||
except json.JSONDecodeError:
|
||||
log("Error: Unable to parse lsblk output.")
|
||||
sys.exit(1)
|
||||
|
||||
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:
|
||||
return f"{drive}p{partition_number}"
|
||||
else:
|
||||
return f"{drive}{partition_number}"
|
||||
|
||||
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)
|
||||
for line in result.stdout.strip().splitlines():
|
||||
parts = line.strip().split()
|
||||
@@ -91,6 +142,7 @@ def prepare_drive(drive):
|
||||
log(f"Unmounting {part}...")
|
||||
run_command(["sudo", "umount", "-l", part])
|
||||
|
||||
# Disable swap if it's on the drive
|
||||
with open("/proc/swaps") as swaps_file:
|
||||
for line in swaps_file:
|
||||
if drive in line:
|
||||
@@ -98,6 +150,7 @@ def prepare_drive(drive):
|
||||
log(f"Disabling swap on {swap_part}...")
|
||||
run_command(["sudo", "swapoff", swap_part])
|
||||
|
||||
# Kill any processes using the drive
|
||||
log(f"Checking for processes using {drive}...")
|
||||
result = subprocess.run(["sudo", "lsof", drive], capture_output=True, text=True)
|
||||
if result.stdout.strip():
|
||||
@@ -113,6 +166,9 @@ def prepare_drive(drive):
|
||||
log(f"No processes are using {drive}.")
|
||||
|
||||
def setup_usb():
|
||||
"""
|
||||
Sets up the bootable USB (Tails or Kali) and creates additional partitions if required.
|
||||
"""
|
||||
global DRIVE
|
||||
log("Setting up bootable USB or preparing partitions...")
|
||||
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"
|
||||
if wipe.lower() == "y":
|
||||
log(f"Wiping {DRIVE} and clearing any existing file system or encryption signatures...")
|
||||
run_command(["sudo", "wipefs", "--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.")
|
||||
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", "sgdisk", "--zap-all", DRIVE])
|
||||
|
||||
# Initialize variables to track if ISO has been written
|
||||
iso_written = False
|
||||
|
||||
if CREATE_KALI or CREATE_TAILS:
|
||||
global KALI_ISO, TAILS_ISO
|
||||
if CREATE_KALI or CREATE_TAILS or CREATE_CUSTOM:
|
||||
global KALI_ISO, TAILS_ISO, CUSTOM_ISO
|
||||
if CREATE_KALI:
|
||||
if not KALI_ISO:
|
||||
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}")
|
||||
sys.exit(1)
|
||||
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}...")
|
||||
run_command(f"sudo dd if='{ISO_PATH}' of='{DRIVE}' bs=64M status=progress", shell=True, interactive=True)
|
||||
log(f"ISO written to {DRIVE} successfully.")
|
||||
iso_written = True
|
||||
if CREATE_TAILS:
|
||||
# For Tails, flash the ISO to the entire drive without any partitioning
|
||||
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
|
||||
|
||||
# After writing ISO, set up partitions accordingly
|
||||
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()
|
||||
if CREATE_TAILS:
|
||||
fix_partition_table_tails()
|
||||
|
||||
# If documents partition is requested, set it up
|
||||
if CREATE_DOCS and not (CREATE_KALI or CREATE_TAILS):
|
||||
# If not setting up OS bootable USB, proceed directly
|
||||
fix_partition_table_docs_only()
|
||||
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
|
||||
elif CREATE_TAILS:
|
||||
if CREATE_DOCS:
|
||||
# For Tails with docs, add partitions after Tails
|
||||
fix_partition_table_tails()
|
||||
else:
|
||||
# Tails only, no additional partitions
|
||||
log("Tails installation complete. No additional partitions requested.")
|
||||
elif CREATE_DOCS:
|
||||
# If no ISO was written, just set up documents partition
|
||||
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...")
|
||||
|
||||
# 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 partprobe {DRIVE}", shell=True)
|
||||
run_command("sudo udevadm settle", shell=True)
|
||||
time.sleep(5) # Increased sleep to ensure partitions are recognized
|
||||
|
||||
# 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:
|
||||
total_size_bytes = int(result.stdout.strip())
|
||||
except ValueError:
|
||||
log("Error: Unable to determine drive size.")
|
||||
log(f"Error: Unable to determine drive size. lsblk output: {result.stdout}")
|
||||
sys.exit(1)
|
||||
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
|
||||
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_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():
|
||||
"""
|
||||
Fixes the partition table for Kali Linux by adding persistence and documents partitions.
|
||||
"""
|
||||
log("Fixing partition table to reclaim remaining space...")
|
||||
|
||||
# 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")
|
||||
|
||||
# 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:
|
||||
total_size_bytes = int(result.stdout.strip())
|
||||
except ValueError:
|
||||
log("Error: Unable to determine drive size.")
|
||||
log(f"Error: Unable to determine drive size. lsblk output: {result.stdout}")
|
||||
sys.exit(1)
|
||||
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
|
||||
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)
|
||||
|
||||
# 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.")
|
||||
|
||||
# Set up documents partition
|
||||
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): ")
|
||||
if size_docs:
|
||||
try:
|
||||
@@ -314,27 +504,10 @@ def fix_partition_table():
|
||||
setup_docs_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():
|
||||
"""
|
||||
Configures the persistence partition for Kali Linux.
|
||||
"""
|
||||
global DRIVE
|
||||
PERSIST_PART = get_partition_name(DRIVE, 2)
|
||||
|
||||
@@ -347,6 +520,11 @@ def setup_kali_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:
|
||||
luks_format_cmd = (
|
||||
f"sudo cryptsetup luksFormat '{PERSIST_PART}' "
|
||||
@@ -354,7 +532,8 @@ def setup_kali_partition():
|
||||
f"--cipher aes-cbc-essiv:sha256 "
|
||||
f"--key-size 256 "
|
||||
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"
|
||||
else:
|
||||
@@ -363,7 +542,8 @@ def setup_kali_partition():
|
||||
f"--cipher aes-xts-plain64 "
|
||||
f"--key-size 512 "
|
||||
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"
|
||||
|
||||
@@ -381,6 +561,9 @@ def setup_kali_partition():
|
||||
log("Kali persistence setup complete.")
|
||||
|
||||
def setup_docs_partition():
|
||||
"""
|
||||
Configures the VeraCrypt encrypted documents partition.
|
||||
"""
|
||||
global DRIVE
|
||||
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.")
|
||||
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:
|
||||
veracrypt_create_cmd = (
|
||||
f"veracrypt --text --create '{DOCS_PART}' "
|
||||
f"--encryption AES "
|
||||
f"--hash SHA-256 "
|
||||
f"--filesystem exfat "
|
||||
f"--volume-type normal "
|
||||
f"--quick "
|
||||
)
|
||||
else:
|
||||
veracrypt_create_cmd = (
|
||||
f"veracrypt --text --create '{DOCS_PART}' "
|
||||
f"--encryption AES-Twofish-Serpent "
|
||||
f"--hash whirlpool "
|
||||
f"--filesystem exfat "
|
||||
f"--volume-type normal "
|
||||
)
|
||||
log("\nConfiguring VeraCrypt encryption for documents partition...")
|
||||
|
||||
# Always use maximum security for documents partition (ignore FAST_MODE)
|
||||
# Triple cascade encryption with strongest hash
|
||||
veracrypt_create_cmd = (
|
||||
f"veracrypt --text --create '{DOCS_PART}' "
|
||||
f"--encryption AES-Twofish-Serpent "
|
||||
f"--hash SHA-512 "
|
||||
f"--filesystem ext4 "
|
||||
f"--volume-type normal "
|
||||
f"--pim 2000 " # Enforce strong PIM for maximum security
|
||||
)
|
||||
|
||||
run_command(veracrypt_create_cmd, shell=True, interactive=True)
|
||||
log("Encrypted documents partition setup complete.")
|
||||
|
||||
def setup_unencrypted_partition():
|
||||
"""
|
||||
Sets up the unencrypted partition for scripts and instructions.
|
||||
"""
|
||||
global DRIVE
|
||||
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)
|
||||
|
||||
instructions = f"""
|
||||
To mount the encrypted documents partition, use the provided 'mount_encrypted_partitions.sh' script.
|
||||
To unmount and lock it, use the 'cleanup_encrypted_partitions.sh' script.
|
||||
INSTRUCTIONS FOR ACCESSING SECURE STORAGE
|
||||
|
||||
**Automount Script:**
|
||||
Run: sudo ./mount_encrypted_partitions.sh
|
||||
To access your secure partition:
|
||||
1. Run: sudo ./mount_storage.sh
|
||||
2. Enter your password when prompted
|
||||
3. Your files will be available at /mnt/secure_storage
|
||||
|
||||
**Cleanup Script:**
|
||||
Run: sudo ./cleanup_encrypted_partitions.sh
|
||||
To safely lock your storage:
|
||||
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:
|
||||
@@ -448,60 +652,114 @@ Run: sudo ./cleanup_encrypted_partitions.sh
|
||||
log("Created README.txt with mounting instructions.")
|
||||
|
||||
mount_script = """#!/bin/bash
|
||||
# Script to mount encrypted documents partition
|
||||
# Script to mount secure storage partition
|
||||
|
||||
echo "Available drives:"
|
||||
lsblk -o NAME,SIZE,TYPE | grep disk
|
||||
read -p "Enter the drive path for the documents partition (default: /dev/sdc1): " DRIVE_PATH
|
||||
DRIVE_PATH=${DRIVE_PATH:-/dev/sdc1}
|
||||
echo "=== Secure Storage Mount ==="
|
||||
echo ""
|
||||
echo "Available storage devices:"
|
||||
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
|
||||
echo "Mounting VeraCrypt documents partition at $DRIVE_PATH..."
|
||||
sudo mkdir -p /mnt/veracrypt_docs
|
||||
sudo veracrypt --text --mount "$DRIVE_PATH" /mnt/veracrypt_docs
|
||||
echo "Documents partition mounted at /mnt/veracrypt_docs."
|
||||
if [ -z "$DRIVE_PATH" ]; then
|
||||
echo "Error: No partition specified."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
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
|
||||
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
|
||||
"""
|
||||
|
||||
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)
|
||||
run_command("sudo cp /tmp/mount_encrypted_partitions.sh /mnt/unencrypted/mount_encrypted_partitions.sh", shell=True)
|
||||
run_command("sudo chmod +x /mnt/unencrypted/mount_encrypted_partitions.sh", shell=True)
|
||||
run_command("sudo rm /tmp/mount_encrypted_partitions.sh", shell=True)
|
||||
log("Created mount_encrypted_partitions.sh script.")
|
||||
run_command("sudo cp /tmp/mount_storage.sh /mnt/unencrypted/mount_storage.sh", shell=True)
|
||||
run_command("sudo chmod +x /mnt/unencrypted/mount_storage.sh", shell=True)
|
||||
run_command("sudo rm /tmp/mount_storage.sh", shell=True)
|
||||
log("Created mount_storage.sh script.")
|
||||
|
||||
cleanup_script = """#!/bin/bash
|
||||
# Script to unmount and lock encrypted documents partition
|
||||
# Script to safely lock secure storage
|
||||
|
||||
echo "Available drives:"
|
||||
lsblk -o NAME,SIZE,TYPE | grep disk
|
||||
read -p "Enter the drive path for the documents partition (default: /dev/sdc1): " DRIVE_PATH
|
||||
DRIVE_PATH=${DRIVE_PATH:-/dev/sdc1}
|
||||
echo "=== Secure Storage Lock ==="
|
||||
echo ""
|
||||
|
||||
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
|
||||
sudo veracrypt --text --dismount /mnt/veracrypt_docs
|
||||
echo "VeraCrypt documents partition unmounted."
|
||||
# Check if any processes are using the mount
|
||||
if sudo lsof /mnt/secure_storage 2>/dev/null | grep -q /mnt/secure_storage; then
|
||||
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
|
||||
echo ""
|
||||
echo "ERROR: Failed to lock storage. Try closing all applications and run again."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Documents partition is not currently mounted."
|
||||
echo "Secure storage is not currently mounted."
|
||||
echo "Nothing to lock."
|
||||
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)
|
||||
run_command("sudo cp /tmp/cleanup_encrypted_partitions.sh /mnt/unencrypted/cleanup_encrypted_partitions.sh", shell=True)
|
||||
run_command("sudo chmod +x /mnt/unencrypted/cleanup_encrypted_partitions.sh", shell=True)
|
||||
run_command("sudo rm /tmp/cleanup_encrypted_partitions.sh", shell=True)
|
||||
log("Created cleanup_encrypted_partitions.sh script.")
|
||||
run_command("sudo cp /tmp/lock_storage.sh /mnt/unencrypted/lock_storage.sh", shell=True)
|
||||
run_command("sudo chmod +x /mnt/unencrypted/lock_storage.sh", shell=True)
|
||||
run_command("sudo rm /tmp/lock_storage.sh", shell=True)
|
||||
log("Created lock_storage.sh script.")
|
||||
|
||||
run_command("sudo umount /mnt/unencrypted", shell=True)
|
||||
log("Unencrypted partition setup complete.")
|
||||
|
||||
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)
|
||||
partitions = [line.strip() for line in result.stdout.strip().splitlines() if line.strip()]
|
||||
partition_numbers = []
|
||||
@@ -524,20 +782,35 @@ def get_last_partition_number():
|
||||
return max(partition_numbers)
|
||||
|
||||
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.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("-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("-i", "--iso", help="Path to the Kali or Tails ISO file")
|
||||
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 ISO file (Kali, Tails, or custom)")
|
||||
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")
|
||||
|
||||
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()
|
||||
sys.exit(1)
|
||||
|
||||
@@ -551,35 +824,24 @@ def main():
|
||||
|
||||
if args.all:
|
||||
CREATE_DOCS = True
|
||||
if args.tails:
|
||||
CREATE_TAILS = True
|
||||
else:
|
||||
CREATE_KALI = True
|
||||
# When -a is used without -t, default to creating Kali
|
||||
CREATE_KALI = True
|
||||
else:
|
||||
CREATE_KALI = args.kali
|
||||
CREATE_DOCS = args.docs
|
||||
CREATE_TAILS = args.tails
|
||||
CREATE_CUSTOM = args.custom
|
||||
|
||||
if args.iso:
|
||||
if CREATE_KALI:
|
||||
KALI_ISO = args.iso
|
||||
elif CREATE_TAILS:
|
||||
TAILS_ISO = args.iso
|
||||
elif CREATE_CUSTOM:
|
||||
CUSTOM_ISO = args.iso
|
||||
|
||||
check_dependencies()
|
||||
|
||||
if CREATE_KALI or CREATE_TAILS or CREATE_DOCS:
|
||||
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()
|
||||
|
||||
setup_usb()
|
||||
log("Partition setup complete.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user