Version 1.0
This commit is contained in:
64
Elysium.ps1
64
Elysium.ps1
@@ -1,34 +1,74 @@
|
|||||||
|
##################################################
|
||||||
|
## ____ ___ ____ _____ _ _ _____ _____ ##
|
||||||
|
## / ___/ _ \| _ \| ____| | \ | | ____|_ _| ##
|
||||||
|
## | | | | | | |_) | _| | \| | _| | | ##
|
||||||
|
## | |__| |_| | _ <| |___ _| |\ | |___ | | ##
|
||||||
|
## \____\__\_\_| \_\_____(_)_| \_|_____| |_| ##
|
||||||
|
##################################################
|
||||||
|
## Project: Elysium ##
|
||||||
|
## File: Elysium.ps1 ##
|
||||||
|
## Version: 1.0 ##
|
||||||
|
## Support: support@cqre.net ##
|
||||||
|
##################################################
|
||||||
|
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
This is the main script for the Elysium tool for testing weak AD passwords.
|
This is the main script for the Elysium tool for testing weak AD passwords.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Elysium.ps1 offers a menu to perform various actions:
|
Elysium.ps1 offers a menu to perform various actions:
|
||||||
1. Update Known-Hashes Database (KHDB)
|
1. Download/Update Known-Hashes Database (KHDB)
|
||||||
2. Test Weak AD Passwords
|
2. Test Weak AD Passwords
|
||||||
3. Extract and Send Current Hashes for KHDB Update
|
3. Extract and Send Current Hashes for KHDB Update
|
||||||
4. Exit
|
4. Uninstall the tool
|
||||||
|
5. Exit
|
||||||
#>
|
#>
|
||||||
|
|
||||||
|
# Define the path to the settings file
|
||||||
|
$settingsFilePath = "ElysiumSettings.txt"
|
||||||
|
|
||||||
|
# Check if the settings file exists
|
||||||
|
if (-Not (Test-Path $settingsFilePath)) {
|
||||||
|
Write-Host "ElysiumSettings.txt does not exist. Please ensure your settings file is in the correct location."
|
||||||
|
exit
|
||||||
|
} else {
|
||||||
|
Write-Host "ElysiumSettings.txt found."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Attempt to retrieve the passphrase from the environment variable
|
||||||
|
$passphrase = [System.Environment]::GetEnvironmentVariable("ELYSIUM_PASSPHRASE", [System.EnvironmentVariableTarget]::User)
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($passphrase)) {
|
||||||
|
Write-Host "No passphrase found in environment variables."
|
||||||
|
$passphrase = Read-Host "Please enter your passphrase."
|
||||||
|
# Here you could choose to set the environment variable or simply use the passphrase for the current session
|
||||||
|
[System.Environment]::SetEnvironmentVariable("ELYSIUM_PASSPHRASE", $passphrase, [System.EnvironmentVariableTarget]::User)
|
||||||
|
Write-Host "Passphrase stored as environment variable 'ELYSIUM_PASSPHRASE'."
|
||||||
|
} else {
|
||||||
|
Write-Host "Passphrase found in environment variables."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Continue with the rest of your script...
|
||||||
|
|
||||||
function Show-Menu {
|
function Show-Menu {
|
||||||
param (
|
param (
|
||||||
[string]$Title = 'Elysium Tool Main Menu'
|
[string]$Title = 'Elysium Tool Main Menu'
|
||||||
)
|
)
|
||||||
Clear-Host
|
Clear-Host
|
||||||
Write-Host "================ $Title ================"
|
Write-Host "================ $Title ================"
|
||||||
|
Write-Host "1: Download/Update Known-Hashes Database (KHDB)"
|
||||||
Write-Host "1: Update Known-Hashes Database (KHDB)"
|
|
||||||
Write-Host "2: Test Weak AD Passwords"
|
Write-Host "2: Test Weak AD Passwords"
|
||||||
Write-Host "3: Extract and Send Current Hashes for KHDB Update"
|
Write-Host "3: Extract and Send Current Hashes for KHDB Update"
|
||||||
Write-Host "4: Exit"
|
Write-Host "4: Uninstall"
|
||||||
|
Write-Host "5: Exit"
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Show-Menu
|
Show-Menu
|
||||||
$input = Read-Host "Please make a selection"
|
$userSelection = Read-Host "Please make a selection"
|
||||||
switch ($input) {
|
switch ($userSelection) {
|
||||||
'1' {
|
'1' {
|
||||||
Write-Host "Updating KHDB..."
|
Write-Host "Downloading KHDB..."
|
||||||
.\Update-KHDB.ps1
|
.\Update-KHDB.ps1
|
||||||
}
|
}
|
||||||
'2' {
|
'2' {
|
||||||
@@ -37,9 +77,13 @@ do {
|
|||||||
}
|
}
|
||||||
'3' {
|
'3' {
|
||||||
Write-Host "Extracting and Sending Current Hashes..."
|
Write-Host "Extracting and Sending Current Hashes..."
|
||||||
.\Send-CurrentHashes.ps1
|
.\Extract-NTHashes.ps1
|
||||||
}
|
}
|
||||||
'4' {
|
'4' {
|
||||||
|
Write-Host "Uninstalling..."
|
||||||
|
.\Uninstall.ps1
|
||||||
|
}
|
||||||
|
'5' {
|
||||||
Write-Host "Exiting..."
|
Write-Host "Exiting..."
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
@@ -48,4 +92,4 @@ do {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pause
|
pause
|
||||||
} while ($input -ne '4')
|
} while ($userSelection -ne '5')
|
||||||
|
@@ -14,15 +14,15 @@
|
|||||||
|
|
||||||
# KHDB Settings
|
# KHDB Settings
|
||||||
###############
|
###############
|
||||||
KHDBUrl=https://yourserver.com/khdb
|
storageAccountName = 'elysiumcqre'
|
||||||
SecureToken=YourSecureToken
|
containerName = 'hashes'
|
||||||
DataEndpoint=https://yourserver.com/dataendpoint
|
sasToken = '?sp=racwdl&st=2024-03-22T06:51:36Z&se=2024-12-31T14:51:36Z&spr=https&sv=2022-11-02&sr=c&sig=0xVI%2FevXFo0f27SLmci3%2F3e3zfQd7kDLLlkRDG0Os3M%3D'
|
||||||
WeakPasswordsDatabase=khdb.txt
|
|
||||||
|
|
||||||
# Application Settings
|
# Application Settings
|
||||||
######################
|
######################
|
||||||
InstallationPath=/Users/avedelphina/Documents/Work/CQRE.NET/Elysium-project/elysium
|
InstallationPath=/Users/avedelphina/Documents/Work/CQRE.NET/Elysium-project/elysium
|
||||||
ReportPathBase=/Users/avedelphina/Documents/Work/CQRE.NET/Elysium-project/elysium/Reports
|
ReportPathBase=/Users/avedelphina/Documents/Work/CQRE.NET/Elysium-project/elysium/Reports
|
||||||
|
WeakPasswordsDatabase=khdb.txt
|
||||||
# TODO CheckOnlyEnabledUsers=true
|
# TODO CheckOnlyEnabledUsers=true
|
||||||
|
|
||||||
# Domain Settings
|
# Domain Settings
|
||||||
@@ -30,17 +30,11 @@ ReportPathBase=/Users/avedelphina/Documents/Work/CQRE.NET/Elysium-project/elysiu
|
|||||||
# Domain 1 (rdm.cz)
|
# Domain 1 (rdm.cz)
|
||||||
Domain1Name=rdm.cz
|
Domain1Name=rdm.cz
|
||||||
Domain1DC=xxx.rdm.cz
|
Domain1DC=xxx.rdm.cz
|
||||||
Domain1DCIP=10.94.x.x
|
|
||||||
Domain1DA=elysium_adm@rdm.cz
|
|
||||||
|
|
||||||
# Domain 2 (st.sk)
|
# Domain 2 (st.sk)
|
||||||
Domain2Name=st.sk
|
Domain2Name=st.sk
|
||||||
Domain2DC=yyy.st.sk
|
Domain2DC=yyy.st.sk
|
||||||
Domain2DCIP=10.217.x.x
|
|
||||||
Domain2DA=elysium_adm@st.sk
|
|
||||||
|
|
||||||
# Domain 3 (blackmesaresearch.local)
|
# Domain 3 (blackmesaresearch.local)
|
||||||
Domain3Name=blackmesaresearch.local
|
Domain3Name=blackmesaresearch.local
|
||||||
Domain3DC=dc01-bmr
|
Domain3DC=dc01-bmr
|
||||||
Domain3DCIP=100.96.247.32
|
|
||||||
Domain3DA=BMR\elysium_adm
|
|
207
Extract-NTHashes.ps1
Normal file
207
Extract-NTHashes.ps1
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
##################################################
|
||||||
|
## ____ ___ ____ _____ _ _ _____ _____ ##
|
||||||
|
## / ___/ _ \| _ \| ____| | \ | | ____|_ _| ##
|
||||||
|
## | | | | | | |_) | _| | \| | _| | | ##
|
||||||
|
## | |__| |_| | _ <| |___ _| |\ | |___ | | ##
|
||||||
|
## \____\__\_\_| \_\_____(_)_| \_|_____| |_| ##
|
||||||
|
##################################################
|
||||||
|
## Project: Elysium ##
|
||||||
|
## File: Extract-NTLMHashes.ps1 ##
|
||||||
|
## Version: 1.0 ##
|
||||||
|
## Support: support@cqre.net ##
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Script for extracting NTLM hashes from live AD for further analysis.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This script will connect to selected domain (defined in ElysiumSettings.txt) using account with AD replication privileges and extract NTLM hashes from all active accounts. It will then compress and encrypt the resulting file, uploads it to designated Azure Storage account, checks for validity and then deletes everything. The hashes are extracted without usernames to minimise the sensitivity of the operation. Encryption is done with AES and passphrase that was defined in environment variable during first run.
|
||||||
|
#>
|
||||||
|
|
||||||
|
# Import settings
|
||||||
|
Write-Host "Loading settings..."
|
||||||
|
$ElysiumSettings = @{}
|
||||||
|
$settingsPath = "ElysiumSettings.txt"
|
||||||
|
|
||||||
|
if (-not (Test-Path $settingsPath)) {
|
||||||
|
Write-Error "Settings file not found at $settingsPath"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
Get-Content $settingsPath | ForEach-Object {
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($_) -and -not $_.StartsWith("#")) {
|
||||||
|
$keyValue = $_ -split '=', 2
|
||||||
|
if ($keyValue.Count -eq 2) {
|
||||||
|
$ElysiumSettings[$keyValue[0].Trim()] = $keyValue[1].Trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure DSInternals and Az.Storage are installed
|
||||||
|
$requiredModules = @('DSInternals', 'Az.Storage')
|
||||||
|
foreach ($module in $requiredModules) {
|
||||||
|
if (-not (Get-Module -ListAvailable -Name $module)) {
|
||||||
|
Write-Host "Installing $module module..."
|
||||||
|
Install-Module $module -Scope CurrentUser -Force
|
||||||
|
}
|
||||||
|
Import-Module $module
|
||||||
|
}
|
||||||
|
|
||||||
|
# Script variables
|
||||||
|
# External settings
|
||||||
|
$storageAccountName = $ElysiumSettings['storageAccountName']
|
||||||
|
$containerName = $ElysiumSettings['containerName']
|
||||||
|
$sasToken = $ElysiumSettings['sasToken']
|
||||||
|
|
||||||
|
# Retrieve the passphrase from a user environment variable
|
||||||
|
$passphrase = [System.Environment]::GetEnvironmentVariable("ELYSIUM_PASSPHRASE", [System.EnvironmentVariableTarget]::User)
|
||||||
|
|
||||||
|
# Dynamic variables
|
||||||
|
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||||
|
$domainPrefix = $selectedDomain.Name -replace "\W", "_" # Replace non-alphanumeric characters to ensure a valid file name
|
||||||
|
$exportPath = ".\${domainPrefix}_NTLM_Hashes_$timestamp.txt"
|
||||||
|
$compressedFilePath = ".\${domainPrefix}_NTLM_Hashes_$timestamp.zip"
|
||||||
|
$encryptedFilePath = ".\${domainPrefix}_NTLM_Hashes_$timestamp.enc"
|
||||||
|
$blobName = "${domainPrefix}_NTLM_Hashes_$timestamp.enc"
|
||||||
|
|
||||||
|
function Protect-FileWithAES {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$InputFile,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$OutputFile,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Passphrase
|
||||||
|
)
|
||||||
|
|
||||||
|
$aes = New-Object System.Security.Cryptography.AesManaged
|
||||||
|
$aes.KeySize = 256
|
||||||
|
$aes.BlockSize = 128
|
||||||
|
$aes.Mode = [System.Security.Cryptography.CipherMode]::CBC
|
||||||
|
|
||||||
|
# Generate key from passphrase
|
||||||
|
$passwordBytes = [System.Text.Encoding]::UTF8.GetBytes($Passphrase)
|
||||||
|
$aes.Key = [System.Security.Cryptography.SHA256]::Create().ComputeHash($passwordBytes)
|
||||||
|
|
||||||
|
# Generate a random IV
|
||||||
|
$aes.GenerateIV()
|
||||||
|
|
||||||
|
$encryptor = $aes.CreateEncryptor($aes.Key, $aes.IV)
|
||||||
|
|
||||||
|
$fileStream = [System.IO.File]::Open($InputFile, [System.IO.FileMode]::Open)
|
||||||
|
$outFileStream = [System.IO.File]::Create($OutputFile)
|
||||||
|
# Write the IV at the beginning of the output file
|
||||||
|
$outFileStream.Write($aes.IV, 0, $aes.IV.Length)
|
||||||
|
|
||||||
|
$cryptoStream = New-Object System.Security.Cryptography.CryptoStream($outFileStream, $encryptor, [System.Security.Cryptography.CryptoStreamMode]::Write)
|
||||||
|
|
||||||
|
try {
|
||||||
|
$buffer = New-Object Byte[] 8192
|
||||||
|
while (($read = $fileStream.Read($buffer, 0, $buffer.Length)) -gt 0) {
|
||||||
|
$cryptoStream.Write($buffer, 0, $read)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$cryptoStream.Close()
|
||||||
|
$outFileStream.Close()
|
||||||
|
$fileStream.Close()
|
||||||
|
$aes.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "File has been encrypted: $OutputFile"
|
||||||
|
}
|
||||||
|
function Get-FileChecksum {
|
||||||
|
param (
|
||||||
|
[string]$Path,
|
||||||
|
[string]$Algorithm = "SHA256"
|
||||||
|
)
|
||||||
|
$hasher = [System.Security.Cryptography.HashAlgorithm]::Create($Algorithm)
|
||||||
|
$stream = [System.IO.File]::OpenRead($Path)
|
||||||
|
try {
|
||||||
|
$hashBytes = $hasher.ComputeHash($stream)
|
||||||
|
return [BitConverter]::ToString($hashBytes) -replace '-', ''
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$stream.Close()
|
||||||
|
$hasher.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extract NTLM hashes
|
||||||
|
$exportPath = ".\NTLM_Hashes_$timestamp.txt"
|
||||||
|
$compressedFilePath = ".\NTLM_Hashes_$timestamp.zip"
|
||||||
|
|
||||||
|
# Build domain details from settings
|
||||||
|
$DomainDetails = @{}
|
||||||
|
for ($i = 1; $ElysiumSettings.ContainsKey("Domain${i}Name"); $i++) {
|
||||||
|
$DomainDetails["$i"] = @{
|
||||||
|
Name = $ElysiumSettings["Domain${i}Name"]
|
||||||
|
DC = $ElysiumSettings["Domain${i}DC"]
|
||||||
|
DA = $ElysiumSettings["Domain${i}DA"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# User selects a domain
|
||||||
|
Write-Host "Select a domain to extract NTLM hashes:"
|
||||||
|
$DomainDetails.GetEnumerator() | ForEach-Object { Write-Host "$($_.Key): $($_.Value.Name)" }
|
||||||
|
$selection = Read-Host "Enter the number of the domain"
|
||||||
|
$selectedDomain = $DomainDetails[$selection]
|
||||||
|
|
||||||
|
if (-not $selectedDomain) {
|
||||||
|
Write-Error "Invalid selection."
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update script variables based on selected domain
|
||||||
|
$domainController = $selectedDomain.DC
|
||||||
|
$credential = Get-Credential -Message "Enter AD credentials with replication rights for $($selectedDomain.Name)"
|
||||||
|
|
||||||
|
$ntlmHashes = Get-ADReplAccount -All -Server $domainController -Credential $credential |
|
||||||
|
Where-Object { $_.NTHash } |
|
||||||
|
ForEach-Object { [BitConverter]::ToString($_.NTHash).Replace("-", "") } |
|
||||||
|
Sort-Object -Unique
|
||||||
|
|
||||||
|
$ntlmHashes | Out-File -FilePath $exportPath
|
||||||
|
Write-Host "NTLM hashes have been extracted to: $exportPath"
|
||||||
|
|
||||||
|
# Compress extracted NTLM hashes
|
||||||
|
Compress-Archive -Path $exportPath -DestinationPath $compressedFilePath
|
||||||
|
Write-Host "File has been compressed: $compressedFilePath"
|
||||||
|
|
||||||
|
# Encrypt the compressed file
|
||||||
|
Protect-FileWithAES -InputFile $compressedFilePath -OutputFile $encryptedFilePath -Passphrase $passphrase
|
||||||
|
Write-Host "File has been encrypted: $encryptedFilePath"
|
||||||
|
|
||||||
|
# Calculate the local file checksum
|
||||||
|
$localFileChecksum = Get-FileChecksum -Path $encryptedFilePath
|
||||||
|
|
||||||
|
# Create the context for Azure Blob Storage with SAS token
|
||||||
|
$storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -SasToken $sasToken
|
||||||
|
|
||||||
|
# Upload the encrypted file to Azure Blob Storage
|
||||||
|
Set-AzStorageBlobContent -File $encryptedFilePath -Container $containerName -Blob $blobName -Context $storageContext
|
||||||
|
Write-Host "Encrypted file uploaded to Azure Blob Storage: $blobName"
|
||||||
|
|
||||||
|
# Download the blob to a temporary location to verify
|
||||||
|
$tempDownloadPath = [System.IO.Path]::GetTempFileName()
|
||||||
|
Get-AzStorageBlobContent -Blob $blobName -Container $containerName -Context $storageContext -Destination $tempDownloadPath -Force
|
||||||
|
|
||||||
|
# Calculate the downloaded file checksum
|
||||||
|
$downloadedFileChecksum = Get-FileChecksum -Path $tempDownloadPath
|
||||||
|
|
||||||
|
# Compare the checksums
|
||||||
|
if ($localFileChecksum -eq $downloadedFileChecksum) {
|
||||||
|
Write-Host "The file was correctly uploaded. Checksum verified."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "Checksum verification failed. The uploaded file may be corrupted."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean up local and temporary files
|
||||||
|
Remove-Item -Path $exportPath, $compressedFilePath, $encryptedFilePath, $tempDownloadPath -Force
|
||||||
|
Write-Host "Local and temporary files cleaned up after uploading to Azure Blob Storage."
|
||||||
|
|
||||||
|
Write-Host "Script execution completed."
|
@@ -18,11 +18,11 @@ Sensitive operations are confined only to the dedicated host. In the third step,
|
|||||||
## Operation
|
## Operation
|
||||||
### Install and update
|
### Install and update
|
||||||
This tool is provided in private git repository. Installation and updating is done with cloning and pulling from this repository.
|
This tool is provided in private git repository. Installation and updating is done with cloning and pulling from this repository.
|
||||||
|
During first run, the tool will ask for passphrase that will be used to encrypt/decrypt sensitive content.
|
||||||
|
After installation, edit ElysiumSettings.txt, check all variables and add domains to test.
|
||||||
### Update Known-Hashed Database (KHDB)
|
### Update Known-Hashed Database (KHDB)
|
||||||
Run script Elysium.ps1 as an administrator and choose option 1 (Update Known-Hashes Database).
|
Run script Elysium.ps1 as an administrator and choose option 1 (Update Known-Hashes Database).
|
||||||
The script will then check online for newer version and if found, downloads it.
|
The script will then download the database from dedicated Azure Storage, decompresses it and updates the current database.
|
||||||
As the KHDB content is encrypted, the script will then ask for decryption pasword.
|
|
||||||
With correct password provided, database is then updated.
|
|
||||||
### Test Weak AD passwords
|
### Test Weak AD passwords
|
||||||
Run script Elysium.ps1 as an administrator and choose option 2 (Test Weak AD Passwords).
|
Run script Elysium.ps1 as an administrator and choose option 2 (Test Weak AD Passwords).
|
||||||
The script will then ask for the domain to be tested and upon choice will ask for domain administrator password. The DA username is already provided in the script for each domain.
|
The script will then ask for the domain to be tested and upon choice will ask for domain administrator password. The DA username is already provided in the script for each domain.
|
||||||
@@ -31,7 +31,8 @@ The tool then connects to Domain Controller and tests all enabled users in the d
|
|||||||
Run script Elysium.ps1 as an administrator and choose option 3 (Extract and Send Hashes).
|
Run script Elysium.ps1 as an administrator and choose option 3 (Extract and Send Hashes).
|
||||||
The tool will then ask for domain and password of domain administrator. With correct credentials, the tool will then extract current hashes (no history) of non-disabled users, compresses and encrypts them and sends them to the tool provider.
|
The tool will then ask for domain and password of domain administrator. With correct credentials, the tool will then extract current hashes (no history) of non-disabled users, compresses and encrypts them and sends them to the tool provider.
|
||||||
### Uninstallation
|
### Uninstallation
|
||||||
Remove the cloned repository.
|
Run script Elysium.ps1 as an administrator and choose option 4 (Uninstall).
|
||||||
|
The script will then delete everything and remove the passphrase variable.
|
||||||
---
|
---
|
||||||
## FAQ
|
## FAQ
|
||||||
### What happens to the hashes we uploaded?
|
### What happens to the hashes we uploaded?
|
||||||
|
@@ -1,43 +0,0 @@
|
|||||||
param (
|
|
||||||
[string]$DataEndpoint = "https://yourserver.com/dataendpoint", # URL to send data
|
|
||||||
[string]$SecureToken = "YourSecureToken" # Secure token for sending data
|
|
||||||
)
|
|
||||||
|
|
||||||
function Send-CurrentHashes {
|
|
||||||
$domain = Read-Host "Enter the domain"
|
|
||||||
$domainAdminPassword = Read-Host "Enter the domain administrator password" -AsSecureString
|
|
||||||
|
|
||||||
# Extract hashes
|
|
||||||
$hashes = Get-CurrentHashes -Domain $domain -Password $domainAdminPassword
|
|
||||||
|
|
||||||
# Compress and encrypt data
|
|
||||||
$compressedEncryptedData = CompressAndEncrypt-Data -Data $hashes
|
|
||||||
|
|
||||||
# Send data
|
|
||||||
try {
|
|
||||||
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
|
|
||||||
$headers.Add("Authorization", "Bearer $SecureToken")
|
|
||||||
Invoke-WebRequest -Uri $DataEndpoint -Method 'POST' -Body $compressedEncryptedData -Headers $headers
|
|
||||||
Write-Host "Data sent successfully."
|
|
||||||
} catch {
|
|
||||||
Write-Error "Error sending data: $_"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-CurrentHashes {
|
|
||||||
param (
|
|
||||||
[Parameter(Mandatory = $true)][string]$Domain,
|
|
||||||
[Parameter(Mandatory = $true)][System.Security.SecureString]$Password
|
|
||||||
)
|
|
||||||
# Logic to extract current hashes from AD
|
|
||||||
}
|
|
||||||
|
|
||||||
function CompressAndEncrypt-Data {
|
|
||||||
param (
|
|
||||||
[Parameter(Mandatory = $true)][string]$Data
|
|
||||||
)
|
|
||||||
# Implement compression and encryption
|
|
||||||
# Return compressed and encrypted data
|
|
||||||
}
|
|
||||||
|
|
||||||
Send-CurrentHashes
|
|
@@ -12,6 +12,14 @@
|
|||||||
## Support: support@cqre.net ##
|
## Support: support@cqre.net ##
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Weak AD password finder component of Elysium tool.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This script will test the passwords of selected domain (defined in ElysiumSettings.txt) using DSInternal Test-PasswordQuality cmdlet. It writes it's output to a report file which is meant to be shared with internal security team.
|
||||||
|
#>
|
||||||
|
|
||||||
# Current timestamp for both report generation and header
|
# Current timestamp for both report generation and header
|
||||||
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||||
|
|
||||||
@@ -89,7 +97,8 @@ function Get-DomainDetailsFromSettings {
|
|||||||
DA = $Settings[$daKey]
|
DA = $Settings[$daKey]
|
||||||
}
|
}
|
||||||
$counter++
|
$counter++
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +133,7 @@ function Test-WeakADPasswords {
|
|||||||
# Performing the test
|
# Performing the test
|
||||||
Write-Host "Testing password quality for $($selectedDomain.Name)..."
|
Write-Host "Testing password quality for $($selectedDomain.Name)..."
|
||||||
$testResults = Get-ADReplAccount -All -Server $selectedDomain["DC"] -Credential $credentials |
|
$testResults = Get-ADReplAccount -All -Server $selectedDomain["DC"] -Credential $credentials |
|
||||||
Test-PasswordQuality -WeakPasswordHashesFile $FilePath -Verbose
|
Test-PasswordQuality -WeakPasswordHashesFile $FilePath -Verbose
|
||||||
|
|
||||||
# Report generation with dynamic content
|
# Report generation with dynamic content
|
||||||
$reportPath = Join-Path -Path $reportPathBase -ChildPath "$($selectedDomain.Name)_WeakPasswordReport_$timestamp.txt"
|
$reportPath = Join-Path -Path $reportPathBase -ChildPath "$($selectedDomain.Name)_WeakPasswordReport_$timestamp.txt"
|
||||||
|
@@ -1,24 +1,42 @@
|
|||||||
|
##################################################
|
||||||
|
## ____ ___ ____ _____ _ _ _____ _____ ##
|
||||||
|
## / ___/ _ \| _ \| ____| | \ | | ____|_ _| ##
|
||||||
|
## | | | | | | |_) | _| | \| | _| | | ##
|
||||||
|
## | |__| |_| | _ <| |___ _| |\ | |___ | | ##
|
||||||
|
## \____\__\_\_| \_\_____(_)_| \_|_____| |_| ##
|
||||||
|
##################################################
|
||||||
|
## Project: Elysium ##
|
||||||
|
## File: Uninstall.ps1 ##
|
||||||
|
## Version: 1.0 ##
|
||||||
|
## Support: support@cqre.net ##
|
||||||
|
##################################################
|
||||||
|
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Uninstall script for the Elysium AD password testing tool.
|
Uninstall script for the Elysium AD password testing tool.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
This script will remove the Elysium tool and its components (scripts, configurations, and any generated data) from the system.
|
This script will remove the Elysium tool and its components (scripts, configurations, and any generated data) from the system, and then delete itself.
|
||||||
#>
|
#>
|
||||||
|
|
||||||
# Define the path where the Elysium tool is installed
|
|
||||||
$ElysiumPath = "C:\Path\To\Elysium" # Update this with the actual installation path
|
|
||||||
|
|
||||||
function Uninstall-Elysium {
|
function Uninstall-Elysium {
|
||||||
Write-Host "Uninstalling Elysium tool..."
|
$ElysiumPath = Get-Location
|
||||||
|
|
||||||
|
Write-Host "Uninstalling Elysium tool from $ElysiumPath..."
|
||||||
|
|
||||||
# Check if the Elysium directory exists
|
# Check if the Elysium directory exists
|
||||||
if (Test-Path $ElysiumPath) {
|
if (Test-Path $ElysiumPath) {
|
||||||
|
# Schedule the script file for deletion
|
||||||
|
$scriptPath = $MyInvocation.MyCommand.Path
|
||||||
|
$deleteScript = { param($path) Remove-Item -Path $path -Force }
|
||||||
|
Start-Sleep -Seconds 3 # Delay to ensure the script finishes
|
||||||
|
Start-Process -FilePath "powershell.exe" -ArgumentList "-Command", $deleteScript, "-ArgumentList", $scriptPath -WindowStyle Hidden
|
||||||
|
|
||||||
# Remove the Elysium directory and all its contents
|
# Remove the Elysium directory and all its contents
|
||||||
Remove-Item -Path $ElysiumPath -Recurse -Force
|
Remove-Item -Path $ElysiumPath -Recurse -Force -Exclude $scriptPath
|
||||||
Write-Host "Elysium tool and all related files have been removed."
|
Write-Host "Elysium tool and all related files have been removed, excluding this script. This script will be deleted shortly."
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Elysium directory not found. It might have been removed already or the path is incorrect."
|
Write-Host "Elysium directory not found. It might have been removed already, or the path is incorrect."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Additional cleanup actions can be added here if needed
|
# Additional cleanup actions can be added here if needed
|
||||||
@@ -27,5 +45,16 @@ function Uninstall-Elysium {
|
|||||||
# Execute the uninstall function
|
# Execute the uninstall function
|
||||||
Uninstall-Elysium
|
Uninstall-Elysium
|
||||||
|
|
||||||
|
# Check if the Elysium passphrase environment variable exists
|
||||||
|
$passphraseEnvVar = [System.Environment]::GetEnvironmentVariable("ELYSIUM_PASSPHRASE", [System.EnvironmentVariableTarget]::User)
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($passphraseEnvVar)) {
|
||||||
|
Write-Host "No passphrase environment variable to remove."
|
||||||
|
} else {
|
||||||
|
# Remove the Elysium passphrase environment variable
|
||||||
|
[System.Environment]::SetEnvironmentVariable("ELYSIUM_PASSPHRASE", $null, [System.EnvironmentVariableTarget]::User)
|
||||||
|
Write-Host "Elysium passphrase environment variable has been removed."
|
||||||
|
}
|
||||||
|
|
||||||
# Confirm uninstallation
|
# Confirm uninstallation
|
||||||
Write-Host "Elysium tool has been successfully uninstalled." -ForegroundColor Green
|
Write-Host "Elysium tool has been successfully uninstalled. Exiting script." -ForegroundColor Green
|
||||||
|
@@ -1,3 +1,24 @@
|
|||||||
|
##################################################
|
||||||
|
## ____ ___ ____ _____ _ _ _____ _____ ##
|
||||||
|
## / ___/ _ \| _ \| ____| | \ | | ____|_ _| ##
|
||||||
|
## | | | | | | |_) | _| | \| | _| | | ##
|
||||||
|
## | |__| |_| | _ <| |___ _| |\ | |___ | | ##
|
||||||
|
## \____\__\_\_| \_\_____(_)_| \_|_____| |_| ##
|
||||||
|
##################################################
|
||||||
|
## Project: Elysium ##
|
||||||
|
## File: Update-KHDB.ps1 ##
|
||||||
|
## Version: 1.0 ##
|
||||||
|
## Support: support@cqre.net ##
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Known hashes database update script for the Elysium AD password testing tool.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This script download khdb.txt.zip from designated Azure Stroage account, decompress it and overwrite the current version.
|
||||||
|
#>
|
||||||
|
|
||||||
# Initialize an empty hashtable to store settings
|
# Initialize an empty hashtable to store settings
|
||||||
$ElysiumSettings = @{}
|
$ElysiumSettings = @{}
|
||||||
|
|
||||||
@@ -8,55 +29,40 @@ Get-Content $settingsPath | ForEach-Object {
|
|||||||
$ElysiumSettings[$keyValue[0]] = $keyValue[1]
|
$ElysiumSettings[$keyValue[0]] = $keyValue[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the variables
|
# Get variables related to Azure Blob storage
|
||||||
$KHDBUrl = $ElysiumSettings["KHDBUrl"]
|
$AzureBlobStorageUrl = $ElysiumSettings["AzureBlobStorageUrl"] # Ensure this is properly constructed in your settings
|
||||||
$SecureToken = $ElysiumSettings["SecureToken"]
|
$SecureToken = $ElysiumSettings["SecureToken"]
|
||||||
|
|
||||||
function Update-KHDB {
|
function Update-KHDB {
|
||||||
Write-Host "Checking for KHDB updates..."
|
Write-Host "Downloading KHDB..."
|
||||||
|
|
||||||
# Setting request headers
|
# Setting request headers
|
||||||
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
|
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
|
||||||
$headers.Add("Authorization", "Bearer $SecureToken")
|
$headers.Add("Authorization", "Bearer $SecureToken")
|
||||||
|
|
||||||
# Downloading KHDB
|
# Downloading KHDB.zip from Azure Blob Storage
|
||||||
|
$khdbZipPath = "khdb.zip"
|
||||||
try {
|
try {
|
||||||
$latestKHDB = Invoke-WebRequest -Uri $KHDBUrl -Headers $headers -UseBasicParsing
|
Invoke-WebRequest -Uri $AzureBlobStorageUrl -Headers $headers -OutFile $khdbZipPath
|
||||||
$encryptedKHDB = $latestKHDB.Content
|
Write-Host "KHDB.zip downloaded successfully."
|
||||||
Write-Host "KHDB downloaded successfully."
|
|
||||||
} catch {
|
} catch {
|
||||||
Write-Error "Error downloading KHDB: $_"
|
Write-Error "Error downloading KHDB.zip: $_"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Decrypting KHDB
|
# Decompressing KHDB.zip
|
||||||
try {
|
try {
|
||||||
$decryptionPassword = Read-Host "Enter decryption password" -AsSecureString
|
Expand-Archive -Path $khdbZipPath -DestinationPath . -Force
|
||||||
$decryptedKHDB = Unprotect-KHDB -EncryptedData $encryptedKHDB -Password $decryptionPassword
|
Remove-Item -Path $khdbZipPath -Force # Delete the zip file
|
||||||
Write-Host "KHDB decrypted successfully."
|
Write-Host "KHDB decompressed and cleaned up successfully."
|
||||||
} catch {
|
} catch {
|
||||||
Write-Error "Error decrypting KHDB: $_"
|
Write-Error "Error decompressing KHDB: $_"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Updating local KHDB (assuming a specific method to update your local database)
|
|
||||||
Update-LocalKHDB -Data $decryptedKHDB
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Unprotect-KHDB {
|
# Run the script
|
||||||
param (
|
|
||||||
[Parameter(Mandatory = $true)][string]$EncryptedData,
|
|
||||||
[Parameter(Mandatory = $true)][System.Security.SecureString]$Password
|
|
||||||
)
|
|
||||||
# Implement your decryption logic here
|
|
||||||
# Return decrypted data
|
|
||||||
}
|
|
||||||
|
|
||||||
function Update-LocalKHDB {
|
|
||||||
param (
|
|
||||||
[Parameter(Mandatory = $true)][string]$Data
|
|
||||||
)
|
|
||||||
# Implement your logic to update the local KHDB
|
|
||||||
}
|
|
||||||
|
|
||||||
Update-KHDB
|
Update-KHDB
|
||||||
|
|
||||||
|
Write-Host "Script execution completed."
|
56
decrypt.py
Normal file
56
decrypt.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
##################################################
|
||||||
|
## ____ ___ ____ _____ _ _ _____ _____ ##
|
||||||
|
## / ___/ _ \| _ \| ____| | \ | | ____|_ _| ##
|
||||||
|
## | | | | | | |_) | _| | \| | _| | | ##
|
||||||
|
## | |__| |_| | _ <| |___ _| |\ | |___ | | ##
|
||||||
|
## \____\__\_\_| \_\_____(_)_| \_|_____| |_| ##
|
||||||
|
##################################################
|
||||||
|
## Project: Elysium ##
|
||||||
|
## File: decrypt.py ##
|
||||||
|
## Version: 1.0 ##
|
||||||
|
## Support: support@cqre.net ##
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
# Installation notes:
|
||||||
|
# Install PyCryptodome with "pip install pycryptodome". Must be run with python3.
|
||||||
|
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Ask for the encrypted file's name
|
||||||
|
encrypted_file_name = input("Enter the name of the encrypted file (with .enc extension): ")
|
||||||
|
encrypted_file_path = f'path/to/your/encrypted/{encrypted_file_name}'
|
||||||
|
decrypted_file_path = encrypted_file_path.replace('.enc', '.zip')
|
||||||
|
|
||||||
|
# Try to retrieve the passphrase from the environment variable
|
||||||
|
passphrase = os.getenv('ELYSIUM_PASSPHRASE')
|
||||||
|
|
||||||
|
if passphrase is None:
|
||||||
|
passphrase = input("Passphrase not found in environment. Please enter the passphrase: ")
|
||||||
|
# Here, you might save the passphrase to a temporary session or file, but be cautious with security.
|
||||||
|
|
||||||
|
# Derive the AES key from the passphrase
|
||||||
|
key = hashlib.sha256(passphrase.encode()).digest()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Read the encrypted file
|
||||||
|
with open(encrypted_file_path, 'rb') as encrypted_file:
|
||||||
|
iv = encrypted_file.read(16) # The first 16 bytes are the IV
|
||||||
|
encrypted_data = encrypted_file.read()
|
||||||
|
|
||||||
|
# Decrypt the data
|
||||||
|
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||||
|
decrypted_data = cipher.decrypt(encrypted_data)
|
||||||
|
|
||||||
|
# Remove potential PKCS#7 padding
|
||||||
|
pad_len = decrypted_data[-1]
|
||||||
|
decrypted_data = decrypted_data[:-pad_len]
|
||||||
|
|
||||||
|
# Write the decrypted data to a file
|
||||||
|
with open(decrypted_file_path, 'wb') as decrypted_file:
|
||||||
|
decrypted_file.write(decrypted_data)
|
||||||
|
|
||||||
|
print(f"File has been decrypted: {decrypted_file_path}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {str(e)}")
|
Reference in New Issue
Block a user