Files
elysium/AGENTS.md
T
tomas.kracmar ad1db86232 Release v2.2.0: unified versioning and replication permission pre-check
- Unified project versioning (v2.2.0) across all scripts, settings template,
  and documentation. All components now share a single version number.
- Added Test-ReplicationPermissions to Test-WeakADPasswords.ps1 to validate
  the three required AD replication extended rights before DCSync, providing
  clear fail-fast errors when permissions are missing.
- Updated CHANGELOG.md with unified versioning strategy and release history.
- Updated README.md with versioning section and improved troubleshooting docs.
2026-06-09 09:43:43 +02:00

126 lines
8.1 KiB
Markdown

# Elysium — Agent Context
> This file is written for AI coding agents. The project language is English; all code comments, documentation, and settings are in English.
## Project Overview
Elysium is a Windows-focused Active Directory weak-password assessment toolkit. It is implemented entirely in PowerShell (with one Python decryption helper) and is designed to be run from a dedicated, trusted Windows host by an operator with replication-equivalent rights on the target AD domain.
The tool performs three core workflows:
1. **Update Known-Hashes Database (KHDB)** — Download an incremental, sharded hash database from remote storage (Azure Blob or S3-compatible).
2. **Test Weak AD Passwords** — Use DSInternals to replicate account data and test passwords against the local KHDB, producing timestamped text reports.
3. **Extract and Send Current Hashes** — Pull NTLM hashes (without usernames) from live AD, compress, encrypt, and upload them back to the tool provider to improve the KHDB. This step is optional.
4. **Update Lithnet Password Protection Store** — Populate a local Lithnet Password Protection store with compromised hashes, plaintext passwords, and banned words.
## Technology Stack
- **Runtime:** Windows PowerShell 5.1 or PowerShell 7 (`pwsh`).
- **Required PowerShell modules:** `DSInternals`, `ActiveDirectory` (RSAT).
- **Optional PowerShell modules:** `Az.Storage`, `AWS.Tools.S3` / `AWSPowerShell.NetCore`, `LithnetPasswordProtection`.
- **Python 3:** `decrypt.py` requires `pycryptodome` for decrypting uploaded payload files.
- **Network:** TLS 1.2+ enforced; native S3 SigV4 signing implemented in pure PowerShell/.NET (no AWS Tools required).
## Project Structure
```
Elysium.ps1 # Main menu / orchestrator script
Elysium.Common.ps1 # Shared helpers: pwsh relauncher, Windows PS fallback
ElysiumSettings.txt # Live configuration (key=value format, # comments)
ElysiumSettings.txt.sample # Documented template for operators
Update-KHDB.ps1 # KHDB downloader: manifest + shard incremental update
Prepare-KHDBStorage.ps1 # KHDB publisher: split source into shards, build manifest, upload
Test-WeakADPasswords.ps1 # AD password-quality test with DSInternals
Extract-NTHashes.ps1 # Hash extraction, compression, encryption, upload
Update-LithnetStore.ps1 # Lithnet Password Protection store importer
Uninstall.ps1 # Self-removal script
decrypt.py # Python 3 decryptor for .enc payloads
Settings.ps1 # Legacy settings file (superseded by ElysiumSettings.txt)
khdb.txt # Local merged KHDB file (generated by Update-KHDB.ps1)
Reports/ # Generated reports and transcript logs
```
## Configuration Format
`ElysiumSettings.txt` uses a simple `Key=value` format. Lines starting with `#` are comments. Values are **not** quoted by default; if quotes are used they are stripped by some parsers.
Key sections:
- `StorageProvider``Azure` or `S3`
- Azure: `storageAccountName`, `containerName`, `sasToken`
- S3: `s3EndpointUrl`, `s3Region`, `s3BucketName`, `s3AccessKeyId`, `s3SecretAccessKey`, `s3ForcePathStyle`, `s3UseAwsTools`
- KHDB layout: `KhdbManifestPath`, `KhdbShardPrefix`, `KhdbLocalShardDir`
- App: `InstallationPath`, `ReportPathBase`, `WeakPasswordsDatabase`, `CheckOnlyEnabledUsers`
- Lithnet: `LithnetStorePath`, `LithnetSyncHibp`, `LithnetHashSources`, `LithnetPlaintextSources`, `LithnetBannedWordSources`
- Telemetry (optional): `UsageBeaconUrl`, `UsageBeaconMethod`, `UsageBeaconInstanceId`, `UsageBeaconTimeoutSeconds`
- Domains: `Domain1Name`, `Domain1DC`, `Domain2Name`, `Domain2DC`, ...
## PowerShell Edition Handling
This project has nuanced PowerShell edition rules that must be preserved:
- **Scripts that benefit from parallelism** (`Update-KHDB.ps1`, `Prepare-KHDBStorage.ps1`, `Update-LithnetStore.ps1`, `Uninstall.ps1`) auto-relaunch under `pwsh` (PowerShell 7+) via `Restart-WithPwshIfAvailable` in `Elysium.Common.ps1`.
- **Scripts that require legacy modules** (`Test-WeakADPasswords.ps1`, `Extract-NTHashes.ps1`) auto-relaunch under `Windows PowerShell` (`powershell.exe`) via `Restart-WithWindowsPowerShellIfAvailable`, because `DSInternals` and `ActiveDirectory` often need the Desktop edition.
- `Elysium.ps1` (the menu) checks `$PSVersionTable.PSEdition` and invokes the appropriate child process for options 2 and 3.
When modifying any script, keep the `. $commonHelper` import and the corresponding `Restart-With*IfAvailable` call at the top.
## Code Style Guidelines
- Strict mode and error handling are mandatory at the top of every script:
```powershell
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
```
- Every operational script starts a **transcript** into `Reports/logs/` (or `%TEMP%` for uninstall) and stops it in a `finally` block.
- Functions use `Verb-Noun` naming. Private helpers are also `Verb-Noun`.
- Settings parsing is done manually via `Get-Content` and string splitting on `=`, not `ConvertFrom-StringData`.
- Paths are resolved relative to `$PSScriptRoot` whenever possible.
- Large file operations use `StreamReader` / `StreamWriter` with explicit `UTF8Encoding($false)` (no BOM) and large buffers (1 MiB preferred).
- S3-native functions (SigV4) are duplicated in scripts that need them because they run in parallel `ForEach-Object -Parallel` scopes where module imports are not preserved.
## Build / Run Commands
There is no package manager or build system. The tool is run directly:
```powershell
# Main menu
.\Elysium.ps1
# Direct invocation (respects auto-relaunch behavior)
.\Update-KHDB.ps1
.\Update-KHDB.ps1 -MaxParallelTransfers 8
.\Test-WeakADPasswords.ps1
.\Extract-NTHashes.ps1
.\Update-LithnetStore.ps1
.\Prepare-KHDBStorage.ps1 -SourcePath .\khdb.txt -OutputRoot .\publish -StorageProvider S3 -SkipUpload
.\Uninstall.ps1
```
No tests or CI pipelines exist in this repository.
## Testing & Validation
- **KHDB validation:** `Validate-KHDBFile` in `Update-KHDB.ps1` checks 32-hex format, sorting, and duplicates.
- **DSInternals compatibility:** `Resolve-DSInternalsWeakHashFile` in `Test-WeakADPasswords.ps1` normalizes legacy `HASH:count` lines into a temporary hash-only file.
- **Upload integrity:** After every upload, the script downloads the blob back and compares SHA256 checksums before deleting local artifacts.
- **Credential pre-check:** `Test-WeakADPasswords.ps1` validates credentials against the chosen DC with `Get-ADDomain` and checks the three replication extended rights before attempting DCSync.
## Security Considerations
- The operator passphrase is stored in the **user-level** environment variable `ELYSIUM_PASSPHRASE`. Do not log or serialize it.
- `Test-WeakADPasswords.ps1` refuses to run when Windows FIPS policy is enabled (`HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy\Enabled = 1`) because DSInternals operations may fail or be limited.
- The extract-and-send workflow uploads **hashes only** (no usernames). Encryption uses PBKDF2 (SHA-256, 100k iterations, random 16-byte salt) + AES-256-CBC with a 4-byte magic header `ELY1`.
- S3 requests are signed with native SigV4 via `System.Net.Http.HttpClient` so no AWS credentials file or third-party module is required. If AWS Tools are used (`s3UseAwsTools = true`), the native path is still available as a fallback.
- Reports contain sensitive AD data. They are written to `Reports/` under the script root by default.
- All network operations enforce TLS 1.2+ (`[System.Net.ServicePointManager]::SecurityProtocol`).
## Notes for Agents
- Do **not** introduce new package-manager files (e.g., `package.json`, `pyproject.toml`, `Cargo.toml`). This project is intentionally dependency-light and script-driven.
- When adding new settings, keep the `key=value` flat format and update both `ElysiumSettings.txt.sample` and any parser that reads the file.
- If you add a new operational script, include the standard banner, strict mode, transcript logging, and the `Elysium.Common.ps1` relauncher pattern.
- The `.gitignore` excludes `khdb.txt`, `ElysiumSettings.txt`, `Reports/`, `khdb-shards/`, and `khdb-manifest.json`.