wsl-kali/JRE-DetonateKali.psm1

# See https://www.linuxtechi.com/install-kali-linux-on-windows-wsl/

<#
.SYNOPSIS
Shows usage guidance for the JRE Kali commands.

.DESCRIPTION
Prints the step-by-step workflow for setup, backup, restore, and reset actions.

.EXAMPLE
JRE-KaliHelp
#>

function JRE-KaliHelp {
  [CmdletBinding()]
  param()

  Write-Host "`n=== Detonate Kali Module Loaded ===" -ForegroundColor Cyan

  Write-Host "`nHow to use this module:" -ForegroundColor Yellow
  Write-Host "1. Run " -NoNewline
  Write-Host "JRE-KaliSetup" -ForegroundColor Magenta
  Write-Host "2. If your PowerShell session is not elevated, the module will prompt for administrator rights." -ForegroundColor Cyan
  Write-Host "3. The module will install Kali in WSL if it is not already installed." -ForegroundColor Cyan
  Write-Host "4. The file " -NoNewline
  Write-Host "setupkali.sh" -ForegroundColor Magenta -NoNewline
  Write-Host " will be copied into your Kali home directory." -ForegroundColor Cyan
  Write-Host "5. A Kali terminal will open in your home directory. Run these commands as root:" -ForegroundColor Cyan
  Write-Host " sudo ./setupkali.sh" -ForegroundColor Green
  Write-Host " If you get prompts during setup, select the defaults and continue through the installation." -ForegroundColor Cyan
  Write-Host "6. After " -NoNewline
  Write-Host "setupkali.sh" -ForegroundColor Magenta -NoNewline
  Write-Host " finishes, start the Kali desktop with:" -ForegroundColor Cyan
  Write-Host " kex --win -s" -ForegroundColor Green
  Write-Host "7. If this is the first Kali install, Windows or WSL may pause for initial setup. If that happens, complete the first-launch prompts, then rerun " -NoNewline
  Write-Host "JRE-KaliSetup" -ForegroundColor Magenta -NoNewline
  Write-Host " if needed." -ForegroundColor Cyan

  Write-Host "`nBackup and restore:" -ForegroundColor Yellow
  Write-Host "Run " -NoNewline
  Write-Host "JRE-KaliExport" -ForegroundColor Magenta -NoNewline
  Write-Host " to create a backup at " -NoNewline
  Write-Host "C:\WSL\kali-linux.tar" -ForegroundColor Green
  Write-Host "Recommended: finish " -NoNewline
  Write-Host "JRE-KaliSetup" -ForegroundColor Magenta -NoNewline
  Write-Host " and run " -NoNewline
  Write-Host "setupkali.sh" -ForegroundColor Magenta -NoNewline
  Write-Host " before exporting so the backup includes the fully configured Kali environment." -ForegroundColor Cyan
  Write-Host "Run " -NoNewline
  Write-Host "JRE-KaliImport" -ForegroundColor Magenta -NoNewline
  Write-Host " to restore the backup from " -NoNewline
  Write-Host "C:\WSL" -ForegroundColor Green

  Write-Host "`nTo remove the Kali image later:" -ForegroundColor Yellow
  Write-Host "Run " -NoNewline
  Write-Host "JRE-KaliReset" -ForegroundColor Magenta
  Write-Host ""
}


function ConvertTo-WslPath {
  param(
    [Parameter(Mandatory)]
    [string]$WindowsPath
  )

  $normalized = $WindowsPath -replace '\\', '/'
  if ($normalized -match '^([A-Za-z]):/(.*)$') {
    return "/mnt/$($matches[1].ToLower())/$($matches[2])"
  }

  throw "Unable to convert to WSL path: $WindowsPath"
}


function Test-IsAdministrator {
  return (New-Object Security.Principal.WindowsPrincipal (
      [Security.Principal.WindowsIdentity]::GetCurrent())
  ).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}


function Start-ElevatedSetupKali {
  param(
    [Parameter(Mandatory)]
    [string]$ModulePath
  )

  $escapedModulePath = $ModulePath.Replace("'", "''")
  $elevatedCommand = "try { Import-Module -Name '$escapedModulePath' -Force; JRE-KaliSetup } catch { Write-Host `$_; Read-Host 'Press Enter to close' }; exit"

  Start-Process -FilePath 'pwsh.exe' -Verb RunAs -ArgumentList @(
    '-NoProfile'
    '-ExecutionPolicy'
    'Bypass'
    '-Command'
    $elevatedCommand
  ) | Out-Null
}


<#
.SYNOPSIS
Installs and configures Kali Linux in WSL.

.DESCRIPTION
Ensures WSL v2 is configured, installs Kali if needed, copies setup scripts into the Kali home directory,
and opens a Kali shell for post-install commands.
===Use `JRE-KaliHelp` for the full walkthrough text.===

.EXAMPLE
JRE-KaliSetup
#>

function JRE-KaliSetup {
  if (-not (Test-IsAdministrator)) {
    Write-Host 'Current session is not elevated. Requesting administrator privileges...' -ForegroundColor Yellow
    Start-ElevatedSetupKali -ModulePath $PSCommandPath
    return
  }

  $origEncoding = [Console]::OutputEncoding
  try {
    [Console]::OutputEncoding = [System.Text.Encoding]::Unicode
    $wslVersion = wsl --version
    $wslList = wsl --list
  }
  finally {
    [Console]::OutputEncoding = $origEncoding
  }

  $wslMajorVersion = ($wslVersion | Select-String -Pattern 'wsl version: (\d)').Matches.Groups.Where({ $_.Name -eq 1 }).Value

  if ($wslMajorVersion -ne 2) {
    wsl --set-default-version 2
  }

  if ($wslList -match 'kali-linux') {
    Write-Host 'Kali is already installed in WSL.' -ForegroundColor Cyan
  }
  else {
    Write-Host 'Installing Kali Linux in WSL...' -ForegroundColor Cyan
    wsl --install -d kali-linux
  }

  $setupKaliScript = Join-Path $PSScriptRoot 'setupkali.sh'

  if (-not (Test-Path -Path $setupKaliScript -PathType Leaf)) {
    throw "Required file is missing: $setupKaliScript"
  }

  $setupKaliScriptWslPath = ConvertTo-WslPath -WindowsPath $setupKaliScript

  # Resolve the actual Kali default user — $env:USER is a Linux variable and is empty on Windows.
  # $env:USERNAME is the Windows user which may not match the Kali username.
  $kaliUser = (wsl -d kali-linux --exec whoami 2>$null).Trim()

  if ([string]::IsNullOrWhiteSpace($kaliUser)) {
    Write-Host 'Could not detect the Kali default user. Complete Kali first-run setup in the open terminal, then rerun JRE-KaliSetup.' -ForegroundColor Yellow
    wsl -d kali-linux
    return
  }

  $kaliHome = "/home/$kaliUser"
  $kaliHomePath = (wsl -d kali-linux --exec sh -c "test -d '$kaliHome' && echo exists" 2>$null).Trim()

  if ($kaliHomePath -ne 'exists') {
    Write-Host "Home directory '$kaliHome' not found in Kali. Ensure first-run setup is complete, then rerun JRE-KaliSetup." -ForegroundColor Yellow
    wsl -d kali-linux
    return
  }

  Write-Host "Copying setup scripts to $kaliHome..." -ForegroundColor Cyan
  wsl -d kali-linux cp "$setupKaliScriptWslPath" "$kaliHome/setupkali.sh"
  wsl -d kali-linux chmod +x "$kaliHome/setupkali.sh"

  if ($LASTEXITCODE -ne 0) {
    throw "Failed to copy setup scripts into Kali. Check that the Kali home directory exists and is accessible."
  }

  Write-Host ("$([char]0x2193)" * 34) -ForegroundColor Yellow
  Write-Host 'Inside the Kali terminal, run:' -ForegroundColor Cyan
  Write-Host ' sudo ./setupkali.sh' -ForegroundColor Green
  Write-Host 'Finally, start the desktop with:' -ForegroundColor Cyan
  Write-Host ' kex --win -s' -ForegroundColor Green
  Write-Host ("$([char]0x2191)" * 34) -ForegroundColor Yellow

  wsl -d kali-linux --cd $kaliHome
}


<#
.SYNOPSIS
Exports a Kali WSL distro to a tar backup.

.DESCRIPTION
Creates or reuses a base folder and exports the selected distro to `<BasePath>\<DistroName>.tar`.
Requires an elevated PowerShell session.
===Use `JRE-KaliHelp` for the full walkthrough text.===

.PARAMETER BasePath
Folder where the backup archive is stored.

.PARAMETER DistroName
Name of the registered WSL distro to export.

.EXAMPLE
JRE-KaliExport

.EXAMPLE
JRE-KaliExport -BasePath 'D:\WSL' -DistroName 'kali-linux'
#>

function JRE-KaliExport {
  [CmdletBinding()]
  param(
    [string]$BasePath = 'C:\WSL',
    [string]$DistroName = 'kali-linux'
  )

  if (-not (Test-IsAdministrator)) {
    throw 'JRE-KaliExport must be run from an elevated PowerShell session.'
  }

  $archivePath = Join-Path $BasePath "$DistroName.tar"

  if (-not (Test-Path -Path $BasePath -PathType Container)) {
    New-Item -Path $BasePath -ItemType Directory -Force | Out-Null
  }

  if (Test-Path -Path $archivePath -PathType Leaf) {
    Remove-Item -Path $archivePath -Force
  }

  Write-Host 'Recommendation: run JRE-KaliSetup and complete setupkali.sh before exporting.' -ForegroundColor Yellow
  Write-Host "Exporting '$DistroName' to $archivePath..." -ForegroundColor Cyan
  wsl --export $DistroName $archivePath

  if ($LASTEXITCODE -ne 0) {
    throw "WSL export failed for distro '$DistroName'."
  }

  Write-Host "Export complete." -ForegroundColor Green
  Write-Host "Backup archive: $archivePath" -ForegroundColor Green
}


<#
.SYNOPSIS
Imports a Kali WSL distro from a tar backup.

.DESCRIPTION
Imports `<BasePath>\<DistroName>.tar` into `<BasePath>\<DistroName>` as a WSL2 distro.
Requires an elevated PowerShell session.
===Use `JRE-KaliHelp` for the full walkthrough text.===

.PARAMETER BasePath
Folder containing the backup archive and target install path.

.PARAMETER DistroName
Name to assign to the restored WSL distro.

.EXAMPLE
JRE-KaliImport

.EXAMPLE
JRE-KaliImport -BasePath 'D:\WSL' -DistroName 'kali-linux'
#>

function JRE-KaliImport {
  [CmdletBinding()]
  param(
    [string]$BasePath = 'C:\WSL',
    [string]$DistroName = 'kali-linux'
  )

  if (-not (Test-IsAdministrator)) {
    throw 'JRE-KaliImport must be run from an elevated PowerShell session.'
  }

  $archivePath = Join-Path $BasePath "$DistroName.tar"
  $installPath = Join-Path $BasePath $DistroName

  if (-not (Test-Path -Path $archivePath -PathType Leaf)) {
    throw "Backup archive not found: $archivePath"
  }

  $registeredDistros = @(
    wsl --list --quiet 2>$null |
      ForEach-Object { $_.Trim() } |
      Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
  )

  if ($registeredDistros -contains $DistroName) {
    throw "Distro '$DistroName' is already registered. Run JRE-KaliReset first or use a different DistroName."
  }

  if (Test-Path -Path $installPath) {
    $existingItems = Get-ChildItem -Path $installPath -Force -ErrorAction SilentlyContinue
    if ($existingItems) {
      throw "Install path already exists and is not empty: $installPath"
    }
  }
  else {
    New-Item -Path $installPath -ItemType Directory -Force | Out-Null
  }

  Write-Host "Importing '$DistroName' from $archivePath..." -ForegroundColor Cyan
  Write-Host "Install path: $installPath" -ForegroundColor Cyan
  wsl --import $DistroName $installPath $archivePath --version 2

  if ($LASTEXITCODE -ne 0) {
    throw "WSL import failed for distro '$DistroName'."
  }

  Write-Host "Import complete." -ForegroundColor Green
  Write-Host "Launch it with: wsl -d $DistroName" -ForegroundColor Green
}


<#
.SYNOPSIS
Unregisters and removes the Kali WSL distro.

.DESCRIPTION
Runs `wsl --unregister kali-linux`.
===Use `JRE-KaliHelp` for the full walkthrough text.===

.EXAMPLE
JRE-KaliReset
#>

function JRE-KaliReset {
  Write-Host 'Resetting Kali-linux image...' -ForegroundColor Yellow
  wsl --unregister kali-linux
}


Export-ModuleMember -Function JRE-KaliHelp, JRE-KaliSetup, JRE-KaliExport, JRE-KaliImport, JRE-KaliReset