Advertisement
nitestryker

Secure Eraser.py

Apr 5th, 2025 (edited)
444
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 25.51 KB | None | 0 0
  1. """
  2.  
  3. Full Advanced Version Here ---> https://github.com/nitestryker/secure-eraser
  4.  
  5. © 2025 Nitestryker Software  
  6. You are free to edit and distribute this file, but this copyright notice must remain.
  7. """
  8.  
  9. import os
  10. import random
  11. import subprocess
  12. import platform
  13. import argparse
  14. import shutil
  15. import tempfile
  16. import time
  17. import sys
  18.  
  19. class SecureEraser:
  20.     """
  21.    A comprehensive secure deletion tool that can:
  22.    1. Securely delete individual files
  23.    2. Wipe free space to prevent recovery of previously deleted files
  24.    3. Securely delete entire directories
  25.    4. Wipe entire drives for resale preparation
  26.    """
  27.    
  28.     # DoD 5220.22-M standard wipe patterns
  29.     DOD_PATTERNS = [
  30.         b'\x00',                         # Pass 1: All zeros
  31.         b'\xFF',                         # Pass 2: All ones
  32.         b'\x00\xFF\x00\xFF\x00\xFF',     # Pass 3: Alternating bit pattern
  33.         b'\x55\xAA\x55\xAA\x55\xAA',     # Pass 4: Another alternating bit pattern
  34.         b'\x92\x49\x24',                 # Pass 5: Random pattern
  35.         b'\x49\x92\x24\x49\x92',         # Pass 6: Another random pattern
  36.         b'\xDB\xB6\xDB\x6D\xB6\xDB',     # Pass 7: Another random pattern
  37.     ]
  38.    
  39.     # Gutmann 35-pass method patterns (simplified representation)
  40.     GUTMANN_PASSES = 35
  41.    
  42.     def __init__(self, passes=3, method="standard"):
  43.         """
  44.        Initialize with the number of overwrite passes and wiping method.
  45.        
  46.        Args:
  47.            passes: Number of overwrite passes (higher = more secure but slower)
  48.            method: Wiping method - "standard", "dod", "gutmann", or "paranoid"
  49.                - standard: Uses basic random data (passes parameter determines count)
  50.                - dod: Uses DoD 5220.22-M standard (7 passes minimum)
  51.                - gutmann: Uses Gutmann 35-pass method
  52.                - paranoid: Combines DoD and Gutmann methods plus additional passes
  53.        """
  54.         self.method = method.lower()
  55.        
  56.         # Set passes based on method
  57.         if self.method == "dod":
  58.             self.passes = max(passes, 7)  # Minimum 7 passes for DoD
  59.         elif self.method == "gutmann":
  60.             self.passes = 35  # Always 35 passes for Gutmann
  61.         elif self.method == "paranoid":
  62.             self.passes = max(passes, 49)  # DoD + Gutmann + additional
  63.         else:  # standard
  64.             self.passes = passes
  65.            
  66.         self.system = platform.system()
  67.    
  68.     def secure_delete_file(self, file_path):
  69.         """
  70.        Securely delete a single file by overwriting it multiple times before deletion.
  71.        Uses the specified wiping method (standard, DoD, Gutmann, or paranoid).
  72.        """
  73.         if not os.path.exists(file_path) or not os.path.isfile(file_path):
  74.             print(f"File {file_path} does not exist or is not a file.")
  75.             return False
  76.            
  77.         try:
  78.             # Get file size
  79.             file_size = os.path.getsize(file_path)
  80.             file_name = os.path.basename(file_path)
  81.            
  82.             # Skip empty files
  83.             if file_size == 0:
  84.                 os.remove(file_path)
  85.                 print(f"Empty file {file_name} removed.")
  86.                 return True
  87.                
  88.             print(f"Securely wiping {file_name} ({file_size/1024/1024:.2f} MB) with {self.passes} passes")
  89.            
  90.             # For large files, use a chunked approach with progress reporting
  91.             chunk_size = 1024 * 1024 * 10  # 10MB chunks
  92.            
  93.             # Multiple overwrite passes
  94.             for i in range(self.passes):
  95.                 pass_type = "zeros" if i == 0 else "ones" if i == 1 else f"random data (pass {i+1})"
  96.                 print(f"Pass {i+1}/{self.passes}: Writing {pass_type}")
  97.                
  98.                 chunks_total = (file_size + chunk_size - 1) // chunk_size
  99.                 chunks_done = 0
  100.                 last_percent = -1
  101.                
  102.                 with open(file_path, 'wb') as f:
  103.                     remaining_size = file_size
  104.                    
  105.                     while remaining_size > 0:
  106.                         # Determine chunk size for last chunk
  107.                         current_chunk = min(chunk_size, remaining_size)
  108.                        
  109.                         # Generate appropriate data for this pass
  110.                         if i == 0:
  111.                             # Pass 1: zeros
  112.                             data = b'\x00' * current_chunk
  113.                         elif i == 1:
  114.                             # Pass 2: ones
  115.                             data = b'\xFF' * current_chunk
  116.                         else:
  117.                             # Other passes: random data
  118.                             data = bytes(random.getrandbits(8) for _ in range(current_chunk))
  119.                        
  120.                         # Write the chunk
  121.                         f.write(data)
  122.                        
  123.                         # Update progress
  124.                         remaining_size -= current_chunk
  125.                         chunks_done += 1
  126.                         percent = int((chunks_done / chunks_total) * 100)
  127.                        
  128.                         # Only update display when percent changes
  129.                         if percent != last_percent:
  130.                             progress_bar = "#" * (percent // 2) + " " * (50 - (percent // 2))
  131.                             print(f"Progress: [{progress_bar}] {percent}%", end="\r")
  132.                             last_percent = percent
  133.                            
  134.                             # Flush stdout for real-time updates
  135.                             sys.stdout.flush()
  136.                
  137.                 # Ensure data is written to disk
  138.                 f.flush()
  139.                 os.fsync(f.fileno())
  140.                 print()  # New line after progress bar
  141.                    
  142.             # Finally delete the file
  143.             os.remove(file_path)
  144.             print(f"File {file_name} has been securely wiped.")
  145.             return True
  146.        
  147.         except Exception as e:
  148.             print(f"Error wiping file {file_path}: {e}")
  149.             return False
  150.    
  151.     def secure_delete_directory(self, directory_path):
  152.         """
  153.        Securely delete an entire directory and its contents.
  154.        """
  155.         if not os.path.exists(directory_path) or not os.path.isdir(directory_path):
  156.             print(f"Directory {directory_path} does not exist or is not a directory.")
  157.             return False
  158.        
  159.         try:
  160.             # Walk through the directory and delete all files securely
  161.             for root, dirs, files in os.walk(directory_path, topdown=False):
  162.                 for file in files:
  163.                     self.secure_delete_file(os.path.join(root, file))
  164.                
  165.                 # Remove empty directories
  166.                 for dir in dirs:
  167.                     dir_path = os.path.join(root, dir)
  168.                     if os.path.exists(dir_path):
  169.                         os.rmdir(dir_path)
  170.            
  171.             # Remove the top directory
  172.             os.rmdir(directory_path)
  173.             print(f"Directory {directory_path} has been securely wiped.")
  174.             return True
  175.        
  176.         except Exception as e:
  177.             print(f"Error wiping directory {directory_path}: {e}")
  178.             return False
  179.    
  180.     def wipe_free_space(self, drive_path):
  181.         """
  182.        Wipe free space to prevent recovery of previously deleted files.
  183.        This is the most important function for ensuring already deleted files can't be recovered.
  184.        """
  185.         print(f"Wiping free space on {drive_path}...")
  186.         print(f"Method: {self.method.upper()} with {self.passes} passes")
  187.        
  188.         # Get available free space to estimate progress
  189.         if self.system == "Windows":
  190.             import ctypes
  191.             free_bytes = ctypes.c_ulonglong(0)
  192.             ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(drive_path), None, None, ctypes.pointer(free_bytes))
  193.             total_free_space = free_bytes.value
  194.         else:
  195.             # Unix-based systems
  196.             st = os.statvfs(drive_path)
  197.             total_free_space = st.f_bavail * st.f_frsize
  198.        
  199.         print(f"Detected {total_free_space / (1024**3):.2f} GB of free space to wipe")
  200.        
  201.         # Create a temporary directory on the specified drive
  202.         temp_dir = os.path.join(drive_path, "temp_secure_wipe")
  203.         os.makedirs(temp_dir, exist_ok=True)
  204.        
  205.         try:
  206.             # Method: Fill the drive with large files until it's full, then delete them
  207.             large_file_path = os.path.join(temp_dir, "wipe_file")
  208.             chunk_size = 1024 * 1024 * 10  # 10MB chunks
  209.             bytes_written = 0
  210.             last_percent = 0
  211.            
  212.             print("Progress: [" + " " * 50 + "] 0%", end="\r")
  213.            
  214.             # For each pass
  215.             for current_pass in range(self.passes):
  216.                 # Get pattern based on method and current pass
  217.                 pattern = self._get_wipe_pattern(current_pass)
  218.                 pattern_name = self._get_pattern_name(current_pass)
  219.                
  220.                 print(f"\nPass {current_pass+1}/{self.passes}: Writing {pattern_name}")
  221.                 bytes_written = 0
  222.                 last_percent = 0
  223.                
  224.                 # Create pattern data for this chunk
  225.                 pattern_data = self._generate_pattern_data(pattern, chunk_size)
  226.                
  227.                 # Write until disk is full
  228.                 try:
  229.                     with open(large_file_path, 'wb') as f:
  230.                         while True:
  231.                             f.write(pattern_data)
  232.                             f.flush()
  233.                             os.fsync(f.fileno())
  234.                            
  235.                             # Update progress
  236.                             bytes_written += chunk_size
  237.                             percent = min(100, int((bytes_written / total_free_space) * 100))
  238.                            
  239.                             # Only update display when percent changes to avoid console spam
  240.                             if percent > last_percent:
  241.                                 progress_bar = "#" * (percent // 2) + " " * (50 - (percent // 2))
  242.                                 print(f"Progress: [{progress_bar}] {percent}%", end="\r")
  243.                                 last_percent = percent
  244.                                
  245.                 except IOError:
  246.                     # Expected - disk full
  247.                     print(f"\nPass {current_pass+1}/{self.passes} complete - disk full")
  248.                
  249.                 # Delete the file before next pass
  250.                 if os.path.exists(large_file_path):
  251.                     os.remove(large_file_path)
  252.            
  253.             print("\nFinal cleanup - securely removing wipe file")
  254.            
  255.             # Clean up
  256.             shutil.rmtree(temp_dir, ignore_errors=True)
  257.             print(f"Complete! Free space on {drive_path} has been wiped with {self.passes} passes using {self.method.upper()} method.")
  258.             return True
  259.        
  260.         except Exception as e:
  261.             print(f"\nError wiping free space on {drive_path}: {e}")
  262.             # Clean up in case of error
  263.             if os.path.exists(temp_dir):
  264.                 shutil.rmtree(temp_dir, ignore_errors=True)
  265.             return False
  266.    
  267.     def _get_wipe_pattern(self, pass_number):
  268.         """Get the appropriate pattern for the current pass based on wiping method."""
  269.         if self.method == "dod":
  270.             # DoD 5220.22-M method
  271.             pattern_index = min(pass_number, len(self.DOD_PATTERNS) - 1)
  272.             return self.DOD_PATTERNS[pattern_index]
  273.         elif self.method == "gutmann" or self.method == "paranoid":
  274.             # Gutmann method patterns (simplified)
  275.             if pass_number < 4:
  276.                 # Passes 1-4: Random data
  277.                 return None  # Signal to use random data
  278.             elif pass_number < 10:
  279.                 # Passes 5-10: Specific patterns from DoD
  280.                 dod_index = (pass_number - 4) % len(self.DOD_PATTERNS)
  281.                 return self.DOD_PATTERNS[dod_index]
  282.             elif pass_number < 32:
  283.                 # Passes 11-32: Specific bit patterns (simplified to random)
  284.                 return None  # Signal to use random data
  285.             else:
  286.                 # Passes 33-35: Random data again
  287.                 return None  # Signal to use random data
  288.         else:
  289.             # Standard method
  290.             if pass_number == 0:
  291.                 return b'\x00'  # First pass: zeros
  292.             elif pass_number == 1:
  293.                 return b'\xFF'  # Second pass: ones
  294.             else:
  295.                 return None  # Other passes: random data
  296.    
  297.     def _get_pattern_name(self, pass_number):
  298.         """Get a human-readable name for the current pass pattern."""
  299.         pattern = self._get_wipe_pattern(pass_number)
  300.        
  301.         if pattern is None:
  302.             return f"random data"
  303.         elif pattern == b'\x00':
  304.             return "zeros (0x00)"
  305.         elif pattern == b'\xFF':
  306.             return "ones (0xFF)"
  307.         elif pattern == b'\x00\xFF\x00\xFF\x00\xFF':
  308.             return "alternating zeros and ones"
  309.         elif pattern == b'\x55\xAA\x55\xAA\x55\xAA':
  310.             return "alternating 01010101 and 10101010"
  311.         elif pattern == b'\x92\x49\x24':
  312.             return "DoD pattern 10010010..."
  313.         elif pattern == b'\x49\x92\x24\x49\x92':
  314.             return "DoD pattern 01001001..."
  315.         elif pattern == b'\xDB\xB6\xDB\x6D\xB6\xDB':
  316.             return "DoD pattern 11011011..."
  317.         else:
  318.             return f"special pattern {pattern[:10].hex()}..."
  319.    
  320.     def _generate_pattern_data(self, pattern, chunk_size):
  321.         """Generate a chunk of data using the specified pattern or random data if pattern is None."""
  322.         if pattern is None:
  323.             # Random data
  324.             return bytes(random.getrandbits(8) for _ in range(chunk_size))
  325.         else:
  326.             # Repeat the pattern to fill the chunk
  327.             pattern_length = len(pattern)
  328.             repeats = chunk_size // pattern_length
  329.             remainder = chunk_size % pattern_length
  330.            
  331.             return pattern * repeats + pattern[:remainder]
  332.    
  333.     def wipe_free_space_advanced(self, drive_path):
  334.         """
  335.        Use platform-specific tools for more thorough free space wiping.
  336.        This is a more advanced option that uses built-in OS tools where available.
  337.        """
  338.         if self.system == "Windows":
  339.             return self._wipe_free_space_windows(drive_path)
  340.         elif self.system == "Darwin":  # macOS
  341.             return self._wipe_free_space_macos(drive_path)
  342.         else:  # Linux and other UNIX-like systems
  343.             return self._wipe_free_space_linux(drive_path)
  344.    
  345.     def _wipe_free_space_windows(self, drive_path):
  346.         """
  347.        Use sdelete from Sysinternals to wipe free space on Windows.
  348.        Note: sdelete must be installed and in the system PATH.
  349.        """
  350.         try:
  351.             # Check if sdelete is available
  352.             subprocess.run(['sdelete', '-?'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
  353.            
  354.             # Run sdelete to clean free space with progress monitoring
  355.             print(f"Using sdelete to wipe free space on {drive_path}...")
  356.            
  357.             # Configure sdelete based on passes
  358.             if self.passes <= 1:
  359.                 # Single pass of zeros
  360.                 args = ['sdelete', '-z', '-nobanner', drive_path]
  361.             else:
  362.                 # Multiple passes (sdelete uses 3 passes with -p)
  363.                 args = ['sdelete', '-p', str(min(self.passes, 3)), '-nobanner', drive_path]
  364.            
  365.             print(f"Starting {self.passes} pass(es) with sdelete - This may take a while")
  366.             print("Progress indicator from sdelete:")
  367.            
  368.             # Run sdelete with real-time output
  369.             process = subprocess.Popen(
  370.                 args,
  371.                 stdout=subprocess.PIPE,
  372.                 stderr=subprocess.STDOUT,
  373.                 universal_newlines=True,
  374.                 bufsize=1
  375.             )
  376.            
  377.             # Show real-time progress from sdelete
  378.             for line in process.stdout:
  379.                 line = line.strip()
  380.                 if line:
  381.                     print(f"  {line}")
  382.            
  383.             # Wait for process to complete
  384.             return_code = process.wait()
  385.            
  386.             if return_code == 0:
  387.                 print(f"Free space on {drive_path} has been wiped using sdelete.")
  388.                 return True
  389.             else:
  390.                 raise subprocess.CalledProcessError(return_code, args)
  391.        
  392.         except FileNotFoundError:
  393.             print("sdelete not found. Please install SysInternals Suite from Microsoft.")
  394.             print("Falling back to basic free space wiping method...")
  395.             return self.wipe_free_space(drive_path)
  396.        
  397.         except subprocess.CalledProcessError as e:
  398.             print(f"Error running sdelete: {e}")
  399.             print("Falling back to basic free space wiping method...")
  400.             return self.wipe_free_space(drive_path)
  401.    
  402.     def _wipe_free_space_macos(self, drive_path):
  403.         """
  404.        Use diskutil to wipe free space on macOS.
  405.        """
  406.         try:
  407.             # Get the disk identifier for the given path
  408.             df_output = subprocess.check_output(['df', drive_path]).decode('utf-8').strip().split('\n')
  409.             disk_id = df_output[1].split()[0]
  410.            
  411.             print(f"Using diskutil to wipe free space on {disk_id}...")
  412.            
  413.             # Use diskutil to securely erase free space
  414.             # 1 pass for speed, but can be increased for more security
  415.             subprocess.run(['diskutil', 'secureErase', 'freespace', str(self.passes), disk_id], check=True)
  416.            
  417.             print(f"Free space on {drive_path} ({disk_id}) has been wiped using diskutil.")
  418.             return True
  419.        
  420.         except Exception as e:
  421.             print(f"Error using diskutil to wipe free space: {e}")
  422.             print("Falling back to basic free space wiping method...")
  423.             return self.wipe_free_space(drive_path)
  424.    
  425.     def _wipe_free_space_linux(self, drive_path):
  426.         """
  427.        Use secure-delete tools (if available) or fallback to manual method on Linux.
  428.        """
  429.         try:
  430.             # Check if sfill (part of secure-delete) is available
  431.             subprocess.run(['sfill', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
  432.            
  433.             print(f"Using sfill to wipe free space on {drive_path}...")
  434.            
  435.             # Use sfill to securely erase free space
  436.             # -l option makes it less secure but faster
  437.             subprocess.run(['sfill', '-l', '-v', drive_path], check=True)
  438.            
  439.             print(f"Free space on {drive_path} has been wiped using sfill.")
  440.             return True
  441.        
  442.         except FileNotFoundError:
  443.             print("sfill not found. Please install the secure-delete package.")
  444.             print("Falling back to basic free space wiping method...")
  445.             return self.wipe_free_space(drive_path)
  446.        
  447.         except subprocess.CalledProcessError as e:
  448.             print(f"Error running sfill: {e}")
  449.             print("Falling back to basic free space wiping method...")
  450.             return self.wipe_free_space(drive_path)
  451.  
  452.  
  453. def main():
  454.     parser = argparse.ArgumentParser(description='Securely wipe files, directories, and free space for safe computer resale.')
  455.    
  456.     # Create subparsers for different commands
  457.     subparsers = parser.add_subparsers(dest='command', help='Command to execute')
  458.    
  459.     # Parser for the file command
  460.     file_parser = subparsers.add_parser('file', help='Securely delete a file')
  461.     file_parser.add_argument('path', help='Path to the file')
  462.     file_parser.add_argument('--passes', type=int, default=3, help='Number of overwrite passes (default: 3)')
  463.     file_parser.add_argument('--method', choices=['standard', 'dod', 'gutmann', 'paranoid'], default='standard',
  464.                           help='Wiping method: standard, dod (DoD 5220.22-M), gutmann (35-pass), or paranoid (default: standard)')
  465.    
  466.     # Parser for the directory command
  467.     dir_parser = subparsers.add_parser('directory', help='Securely delete a directory')
  468.     dir_parser.add_argument('path', help='Path to the directory')
  469.     dir_parser.add_argument('--passes', type=int, default=3, help='Number of overwrite passes (default: 3)')
  470.     dir_parser.add_argument('--method', choices=['standard', 'dod', 'gutmann', 'paranoid'], default='standard',
  471.                           help='Wiping method: standard, dod (DoD 5220.22-M), gutmann (35-pass), or paranoid (default: standard)')
  472.    
  473.     # Parser for the freespace command
  474.     free_parser = subparsers.add_parser('freespace', help='Wipe free space to prevent recovery of previously deleted files')
  475.     free_parser.add_argument('path', help='Path to the drive/partition')
  476.     free_parser.add_argument('--advanced', action='store_true', help='Use advanced OS-specific methods if available')
  477.     free_parser.add_argument('--passes', type=int, default=3, help='Number of overwrite passes (default: 3)')
  478.     free_parser.add_argument('--method', choices=['standard', 'dod', 'gutmann', 'paranoid'], default='standard',
  479.                           help='Wiping method: standard, dod (DoD 5220.22-M), gutmann (35-pass), or paranoid (default: standard)')
  480.    
  481.     # Parser for fullwipe command - new command for computer resale preparation
  482.     fullwipe_parser = subparsers.add_parser('fullwipe', help='Complete system wipe for computer resale (WARNING: destroys all data)')
  483.     fullwipe_parser.add_argument('drive', help='Drive to wipe (e.g., C:, /dev/sda)')
  484.     fullwipe_parser.add_argument('--method', choices=['standard', 'dod', 'gutmann', 'paranoid'], default='dod',
  485.                           help='Wiping method: standard, dod (DoD 5220.22-M), gutmann (35-pass), or paranoid (default: dod)')
  486.     fullwipe_parser.add_argument('--passes', type=int, default=7, help='Number of overwrite passes (default: 7)')
  487.     fullwipe_parser.add_argument('--force', action='store_true', help='Skip confirmation prompt (USE WITH CAUTION)')
  488.    
  489.     args = parser.parse_args()
  490.    
  491.     # Create the secure eraser
  492.     eraser = SecureEraser(passes=args.passes)
  493.    
  494.     # Execute the requested command
  495.     if args.command == 'file':
  496.         eraser = SecureEraser(passes=args.passes, method=args.method)
  497.         eraser.secure_delete_file(args.path)
  498.     elif args.command == 'directory':
  499.         eraser = SecureEraser(passes=args.passes, method=args.method)
  500.         eraser.secure_delete_directory(args.path)
  501.     elif args.command == 'freespace':
  502.         eraser = SecureEraser(passes=args.passes, method=args.method)
  503.         if args.advanced:
  504.             eraser.wipe_free_space_advanced(args.path)
  505.         else:
  506.             eraser.wipe_free_space(args.path)
  507.     elif args.command == 'fullwipe':
  508.         # Special handling for full drive wiping (computer resale preparation)
  509.         print("\n" + "="*80)
  510.         print("WARNING: FULL DRIVE WIPE REQUESTED".center(80))
  511.         print("This will PERMANENTLY DESTROY ALL DATA on the drive!".center(80))
  512.         print("Intended for computer resale preparation.".center(80))
  513.         print("="*80 + "\n")
  514.        
  515.         if not args.force:
  516.             confirmation = input(f"Are you ABSOLUTELY SURE you want to wipe ALL DATA on {args.drive}? (yes/NO): ")
  517.             if confirmation.lower() != "yes":
  518.                 print("Operation canceled. No data was modified.")
  519.                 return
  520.                
  521.             confirmation2 = input(f"FINAL WARNING: Type 'I UNDERSTAND THIS DESTROYS ALL DATA' to confirm: ")
  522.             if confirmation2 != "I UNDERSTAND THIS DESTROYS ALL DATA":
  523.                 print("Operation canceled. No data was modified.")
  524.                 return
  525.        
  526.         print(f"\nInitiating full drive wipe on {args.drive} using {args.method.upper()} method with {args.passes} passes")
  527.         print("This process may take several hours to several days depending on drive size and method.")
  528.        
  529.         # TODO: Implement actual drive wiping using platform-specific tools
  530.         # For now we'll just show a message about the appropriate tool to use
  531.         if platform.system() == "Windows":
  532.             print("\nFor Windows systems, please use DBAN (Darik's Boot and Nuke) for full drive wiping.")
  533.             print("Download DBAN from https://dban.org/")
  534.             print("Create a bootable USB/DVD and boot from it to wipe the entire drive.")
  535.         elif platform.system() == "Darwin":  # macOS
  536.             print("\nFor macOS, please use Disk Utility's secure erase feature:")
  537.             print("1. Open Disk Utility")
  538.             print("2. Select the drive")
  539.             print("3. Click 'Erase'")
  540.             print("4. Click 'Security Options' and choose the appropriate wiping level")
  541.         else:  # Linux
  542.             print("\nFor Linux, you can use the 'shred' command for full drive wiping:")
  543.             print(f"sudo shred -v -n {args.passes} -z {args.drive}")
  544.            
  545.         print("\nRecommendation: For the most thorough wipe for computer resale, use dedicated")
  546.         print("wiping tools that can create a verification report, such as:")
  547.         print("- DBAN (Darik's Boot and Nuke)")
  548.         print("- Blancco Drive Eraser")
  549.         print("- KillDisk")
  550.     else:
  551.         parser.print_help()
  552.  
  553.  
  554. if __name__ == "__main__":
  555.     main()
  556.  
  557.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement