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-HelpKaliUsage

.EXAMPLE
Get-Help JRE-HelpKaliUsage -Detailed
#>

function JRE-HelpKaliUsage {
  [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-SetupKali" -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 files " -NoNewline
  Write-Host "setupkali.sh" -ForegroundColor Magenta -NoNewline
  Write-Host " and " -NoNewline
  Write-Host "setupwinkex.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 " sudo ./setupwinkex.sh" -ForegroundColor Green
  Write-Host "6. After " -NoNewline
  Write-Host "setupkali.sh" -ForegroundColor Magenta -NoNewline
  Write-Host " finishes, return to Windows PowerShell and run " -NoNewline
  Write-Host "wsl --shutdown" -ForegroundColor Green -NoNewline
  Write-Host " so the WSL automount change takes effect." -ForegroundColor Cyan
  Write-Host "7. After " -NoNewline
  Write-Host "setupwinkex.sh" -ForegroundColor Magenta -NoNewline
  Write-Host " finishes, start the Kali desktop with:" -ForegroundColor Cyan
  Write-Host " kex --win -s" -ForegroundColor Green
  Write-Host "8. 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-SetupKali" -ForegroundColor Magenta -NoNewline
  Write-Host " if needed." -ForegroundColor Cyan

  Write-Host "`nBackup and restore:" -ForegroundColor Yellow
  Write-Host "Run " -NoNewline
  Write-Host "JRE-ExportKali" -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-SetupKali" -ForegroundColor Magenta -NoNewline
  Write-Host " and run both " -NoNewline
  Write-Host "setupkali.sh" -ForegroundColor Magenta -NoNewline
  Write-Host " and " -NoNewline
  Write-Host "setupwinkex.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-ImportKali" -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-ResetKali" -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 = "Import-Module -Name '$escapedModulePath' -Force; JRE-SetupKali"

  Start-Process -FilePath 'powershell.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.

.NOTES
Use `JRE-HelpKaliUsage` for the full walkthrough text.

.EXAMPLE
JRE-SetupKali

.EXAMPLE
Get-Help JRE-SetupKali -Detailed
#>

function JRE-SetupKali {
  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'
  $setupWinKexScript = Join-Path $PSScriptRoot 'setupwinkex.sh'

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

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

  $setupKaliScriptWslPath = ConvertTo-WslPath -WindowsPath $setupKaliScript
  $setupWinKexScriptWslPath = ConvertTo-WslPath -WindowsPath $setupWinKexScript

  Write-Host 'Copying setup scripts into the Kali home directory...' -ForegroundColor Cyan
  wsl -d kali-linux cp "$setupKaliScriptWslPath" "/home/$env:USER/setupkali.sh"
  wsl -d kali-linux cp "$setupWinKexScriptWslPath" "/home/$env:USER/setupwinkex.sh"

  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 'After that completes, return to Windows PowerShell and run:' -ForegroundColor Cyan
  Write-Host ' wsl --shutdown' -ForegroundColor Green
  Write-Host 'Then reopen Kali and run:' -ForegroundColor Cyan
  Write-Host ' sudo ./setupwinkex.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 "/home/$env:USER"
}


<#
.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.

.PARAMETER BasePath
Folder where the backup archive is stored.

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

.EXAMPLE
JRE-ExportKali

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

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

  if (-not (Test-IsAdministrator)) {
    throw 'JRE-ExportKali 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-SetupKali and complete both setupkali.sh and setupwinkex.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.

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

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

.EXAMPLE
JRE-ImportKali

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

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

  if (-not (Test-IsAdministrator)) {
    throw 'JRE-ImportKali 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-ResetKali 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`.

.EXAMPLE
JRE-ResetKali
#>

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


Export-ModuleMember -Function JRE-HelpKaliUsage, JRE-SetupKali, JRE-ExportKali, JRE-ImportKali, JRE-ResetKali