Pre-release cleanup: cross-platform installers, remove env leaks

- Install-AllModules.ps1: rewrite as additive + cross-platform. No longer
  force-uninstalls existing Azure modules or clones external repos into the
  repo. Windows-only modules (AzureAD, winget tools) guarded by platform.
- install-dependencies.sh: drop unused qt6-websockets-dev, add libqt6svg6,
  replace snap-only pwsh install with a .deb-first fallback, stop wiping the
  apt cache.
- Remove hardcoded operator environment: absolute home path in
  WHfBAttackWindow, LAN IPs + password in gdb-attach-server.sh, and LAN IPs
  baked into GrabTokenAzureAD/webhook helper defaults (now loopback/placeholder).
- .gitignore: exclude loot/ and repo-root runtime state.
- README: Windows build steps, platform column on module table, Related
  Tooling list for the previously auto-cloned repos.
This commit is contained in:
David Garcia
2026-07-31 07:31:17 -06:00
parent e11a5b0d9d
commit 37a82e5827
12 changed files with 434 additions and 283 deletions
+8
View File
@@ -33,6 +33,14 @@ error.log.*
*.animosession
*.animosessions
# Engagement output - never commit captured data
loot/
# Runtime state that lands at the repo root depending on the launch dir
saved_sessions.dat
device_certs.dat
history_*.txt
# IDE / Editor
.vscode/
.idea/
+223 -230
View File
@@ -1,230 +1,223 @@
$ErrorActionPreference = 'Stop'
Write-Host "`n--- Azure Tool Setup ---`n"
function Remove-AllAzureModules {
Write-Host "`n--- Starting removal of all Azure-related modules ---`n"
Write-Host "Removing AzureRM modules..."
Get-Module -ListAvailable AzureRM* | ForEach-Object {
Write-Host "Removing: $($_.Name)"
Uninstall-Module -Name $_.Name -AllVersions -Force -ErrorAction SilentlyContinue
}
Write-Host "`nRemoving Az modules..."
Get-Module -ListAvailable Az* | ForEach-Object {
Write-Host "Removing: $($_.Name)"
Uninstall-Module -Name $_.Name -AllVersions -Force -ErrorAction SilentlyContinue
}
Write-Host "`nRemoving any modules starting with 'Azure'..."
Get-Module -ListAvailable Azure* | ForEach-Object {
Write-Host "Removing: $($_.Name)"
Uninstall-Module -Name $_.Name -AllVersions -Force -ErrorAction SilentlyContinue
}
Write-Host "`nRemoving AzureAD modules..."
Get-Module -ListAvailable AzureAD | ForEach-Object {
Write-Host "Removing: AzureAD"
Uninstall-Module -Name AzureAD -AllVersions -Force -ErrorAction SilentlyContinue
}
Write-Host "`nRemoving Microsoft Graph modules..."
Get-Module -ListAvailable Microsoft.Graph | ForEach-Object {
Write-Host "Removing: $($_.Name)"
Uninstall-Module -Name $_.Name -AllVersions -Force -ErrorAction SilentlyContinue
}
Write-Host "`nRemoving AADInternals modules..."
Get-Module -ListAvailable AADInternals | ForEach-Object {
Write-Host "Removing: $($_.Name)"
Uninstall-Module -Name $_.Name -AllVersions -Force -ErrorAction SilentlyContinue
}
Write-Host "`n--- All specified Azure modules have been removed ---`n"
}
Remove-AllAzureModules
Start-Sleep -Seconds 2
# Verify module removals
Write-Host "`n--- Verifying module removals ---`n"
$modulesToCheck = @("AzureRM", "Az", "AzureAD", "AzureADPreview", "Microsoft.Graph")
foreach ($mod in $modulesToCheck) {
if (Get-Module -ListAvailable $mod) {
Write-Warning "$mod modules still exist."
} else {
Write-Host "$mod modules removed."
}
}
Write-Host "`n--- Reinstalling stable Azure modules ---`n"
# Install stable Az and AzureAD modules
Install-Module -Name Az -Scope CurrentUser -Force
Install-Module -Name AzureAD -Scope CurrentUser -Force
# AADInternals
# Install the module
Install-Module -Name "AADInternals" -Scope CurrentUser -Force
Install-Module -Name "AADInternals-Endpoints" -Scope CurrentUser -Force
# Import modules
Import-Module -Name "AADInternals"
Import-Module -Name "AADInternals-Endpoints"
# SQL
Install-Module -Name SqlServer -Scope CurrentUser -Force
Import-Module -Name SqlServer
# AzTable I needed it for PWNDLabs
Install-Module AzTable -Scope CurrentUser -Force
# Microsoft Graph
Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force
# New function: Ensure additional Azure sub-modules (including Microsoft Graph) are installed.
function Ensure-AzureModules {
param(
[Parameter(Mandatory=$true)]
[string[]]$ModuleNames
)
foreach ($mod in $ModuleNames) {
if (-not (Get-Module -ListAvailable $mod)) {
Write-Host "$mod not found. Installing..."
Install-Module -Name $mod -Scope CurrentUser -Force -ErrorAction Stop
Write-Host "$mod installed successfully."
} else {
Write-Host "$mod is already installed."
}
}
}
# List of additional Azure sub-modules to ensure are installed (Microsoft.Graph included)
$additionalModules = @(
"Az.Accounts",
"Az.Compute",
"Az.Network",
"Az.Resources",
"Az.Storage",
"Az.KeyVault",
"Az.Monitor",
"Az.Security",
"Az.Automation",
"Az.Functions",
"Microsoft.Graph"
)
Ensure-AzureModules -ModuleNames $additionalModules
# Function to ensure that winget (Windows Package Manager) is installed
function Ensure-Winget {
if (-not (Get-Command winget -ErrorAction SilentlyContinue)) {
Write-Host "winget not found. Downloading and installing the official winget MSIX bundle..."
# Download the official winget MSIX bundle from Microsoft's GitHub release page.
$installerUrl = "https://github.com/microsoft/winget-cli/releases/latest/download/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
$installerPath = "$env:TEMP\winget.msixbundle"
Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath
Write-Host "Installing winget package..."
# Install the downloaded MSIX bundle. Note that Add-AppxPackage may require administrator privileges.
Add-AppxPackage -Path $installerPath
Remove-Item $installerPath
}
else {
Write-Host "winget is already installed."
}
}
Ensure-Winget
# Azure CLI check/install function using winget
function Ensure-AzCLI {
if (-not (Get-Command az -ErrorAction SilentlyContinue)) {
Write-Host "Azure CLI not found. Installing via winget..."
winget install -e --id Microsoft.AzureCLI --accept-source-agreements --accept-package-agreements
} else {
Write-Host "Azure CLI is already installed. Updating via winget..."
winget upgrade -e --id Microsoft.AzureCLI --accept-source-agreements --accept-package-agreements
}
}
# Azure Function Core Tools check/install function using winget
function Ensure-FuncTools {
if (-not (Get-Command func -ErrorAction SilentlyContinue)) {
Write-Host "Azure Function Core Tools not found. Installing via winget..."
winget install -e --id Microsoft.Azure.FunctionsCoreTools --accept-source-agreements --accept-package-agreements
} else {
Write-Host "Azure Function Core Tools already installed. Updating via winget..."
winget upgrade -e --id Microsoft.Azure.FunctionsCoreTools --accept-source-agreements --accept-package-agreements
}
}
#Install Git Module from winget
function Ensure-Git {
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
Write-Host "Git not found. Installing via winget..."
winget install --id Git.Git --accept-source-agreements --accept-package-agreements
} else {
Write-Host "Git is already installed. Updating via winget..."
winget upgrade -e --id Git.Git --accept-source-agreements --accept-package-agreements
}
}
# Call installers for CLI and Function Tools
Ensure-AzCLI
Ensure-FuncTools
Ensure-Git
# Function to clone GitHub repositories
function Clone-GitHubTools {
param(
[Parameter(Mandatory = $true)]
[string[]]$RepoURLs,
[string]$DestinationPath = "."
)
# Create destination folder if it doesn't exist
if (-not (Test-Path $DestinationPath)) {
New-Item -ItemType Directory -Path $DestinationPath | Out-Null
}
foreach ($url in $RepoURLs) {
Write-Host "Cloning repository from $url"
# Extract repository name from URL (assumes URL ends with .git)
$repoName = ($url.Split("/")[-1]).Replace(".git", "")
$targetFolder = Join-Path $DestinationPath $repoName
if (Test-Path $targetFolder) {
Write-Host "Repository '$repoName' already exists in $DestinationPath, skipping clone."
} else {
git clone $url $targetFolder
if ($LASTEXITCODE -eq 0) {
Write-Host "Successfully cloned '$repoName'."
} else {
Write-Warning "Failed to clone '$repoName' from $url."
}
}
}
}
# Clone the specified GitHub repositories
$repos = @(
"https://github.com/LuemmelSec/APEX.git",
"https://github.com/hausec/PowerZure.git",
"https://github.com/f-bader/TokenTacticsV2.git",
"https://github.com/dirkjanm/ROADtools.git",
"https://github.com/Azure/Stormspotter.git",
"https://github.com/NetSPI/MicroBurst.git",
"https://gist.github.com/xpn/f12b145dba16c2eebdd1c6829267b90c",
"https://github.com/dafthack/MFASweep.git",
"https://github.com/dafthack/MSOLSpray.git",
"https://github.com/Gerenios/AADInternals.git",
"https://github.com/YasserREED/Office365Hacker.git",
"https://github.com/lutzenfried/OffensiveCloud.git"
)
Clone-GitHubTools -RepoURLs $repos -DestinationPath "."
Write-Host "`n Environment cleaned, Azure modules (including Microsoft Graph) reinstalled, sub-modules ensured, and tools updated successfully.`n" -ForegroundColor Green
<#
.SYNOPSIS
Installs the PowerShell modules and CLI tools ANIMO drives.
.DESCRIPTION
Runs on Windows PowerShell 5.1, and on PowerShell 7 on Windows, Linux and
macOS. Modules that only exist on Windows (AzureAD, and the winget-installed
CLI tools) are skipped with a message on other platforms rather than failing.
This script is additive. It never uninstalls modules you already have.
.EXAMPLE
pwsh -File Install-AllModules.ps1
.EXAMPLE
# Skip the ~2 GB umbrella Az module and install only the submodules ANIMO uses
pwsh -File Install-AllModules.ps1 -SkipUmbrellaAz
#>
[CmdletBinding()]
param(
# Install only the Az.* submodules ANIMO calls, not the full Az meta-module.
[switch]$SkipUmbrellaAz
)
# Continue, not Stop: one unavailable module should not abort the whole install.
$ErrorActionPreference = 'Continue'
# $IsWindows is a PowerShell 6+ automatic variable. On Windows PowerShell 5.1 it
# is undefined, and that edition only ever runs on Windows.
$onWindows = $IsWindows -or ($PSVersionTable.PSEdition -eq 'Desktop')
Write-Host ""
Write-Host "--- ANIMO module setup ---" -ForegroundColor Cyan
Write-Host "PowerShell $($PSVersionTable.PSVersion) ($($PSVersionTable.PSEdition)) on $(if ($onWindows) { 'Windows' } else { 'Unix' })"
Write-Host ""
# ---------------------------------------------------------------------------
# Gallery bootstrap
# ---------------------------------------------------------------------------
function Initialize-Gallery {
# Windows PowerShell 5.1 ships without the NuGet provider and defaults to
# TLS 1.0, both of which break Install-Module against the gallery.
if ($PSVersionTable.PSEdition -eq 'Desktop') {
try {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
} catch {
Write-Warning "Could not force TLS 1.2: $($_.Exception.Message)"
}
if (-not (Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction SilentlyContinue)) {
Write-Host "Installing NuGet package provider..."
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser | Out-Null
}
}
$gallery = Get-PSRepository -Name PSGallery -ErrorAction SilentlyContinue
if ($gallery -and $gallery.InstallationPolicy -ne 'Trusted') {
Write-Host "Trusting PSGallery for this user..."
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted -ErrorAction SilentlyContinue
}
}
# ---------------------------------------------------------------------------
# Module installation
# ---------------------------------------------------------------------------
function Ensure-Module {
param(
[Parameter(Mandatory)][string]$Name,
[string]$Note
)
if (Get-Module -ListAvailable -Name $Name -ErrorAction SilentlyContinue) {
Write-Host (" {0,-26} already installed" -f $Name) -ForegroundColor DarkGray
return
}
Write-Host (" {0,-26} installing..." -f $Name)
try {
# -AllowClobber: Az command names collide with leftover AzureRM installs.
Install-Module -Name $Name -Scope CurrentUser -Force -AllowClobber -ErrorAction Stop
Write-Host (" {0,-26} OK" -f $Name) -ForegroundColor Green
} catch {
Write-Warning ("{0}: {1}" -f $Name, $_.Exception.Message)
if ($Note) { Write-Host " $Note" -ForegroundColor Yellow }
}
}
Initialize-Gallery
# Az submodules ANIMO actually calls. Installing these individually is far
# smaller than the umbrella Az module and covers every Az cmdlet in the codebase.
$azSubmodules = @(
'Az.Accounts' # Connect-AzAccount, Get-AzAccessToken, Get-AzContext
'Az.Resources' # Get-AzResource, Get-AzRoleAssignment, Get-AzADServicePrincipal
'Az.Compute' # Get-AzVM, Get-AzVMImage, Get-AzVMSize
'Az.Network' # Get-AzVirtualNetwork, Get-AzNetworkSecurityGroup
'Az.Storage' # Get-AzStorageAccount, Get-AzStorageBlob, SAS tokens
'Az.KeyVault' # Get-AzKeyVaultSecret, Get-AzKeyVaultKey
'Az.Monitor'
)
# Modules that install and load on every platform.
$crossPlatform = @(
@{ Name = 'Microsoft.Graph' }
@{ Name = 'SqlServer' } # Invoke-SqlCmd, used by SqlDatabaseWindow
@{ Name = 'AADInternals'; Note = 'Some AADInternals cmdlets are Windows-only.' }
@{ Name = 'AADInternals-Endpoints'; Note = 'Some cmdlets are Windows-only.' }
@{ Name = 'AzTable' }
)
Write-Host "Az submodules:" -ForegroundColor Cyan
foreach ($m in $azSubmodules) { Ensure-Module -Name $m }
if (-not $SkipUmbrellaAz) {
Write-Host ""
Write-Host "Umbrella Az module (large - use -SkipUmbrellaAz to omit):" -ForegroundColor Cyan
Ensure-Module -Name 'Az'
}
Write-Host ""
Write-Host "Cross-platform modules:" -ForegroundColor Cyan
foreach ($m in $crossPlatform) { Ensure-Module -Name $m.Name -Note $m.Note }
# ---------------------------------------------------------------------------
# Windows-only: AzureAD module and the winget-installed CLI tools
# ---------------------------------------------------------------------------
function Ensure-Winget {
if (Get-Command winget -ErrorAction SilentlyContinue) {
Write-Host " winget already installed" -ForegroundColor DarkGray
return $true
}
Write-Host " winget installing App Installer bundle..."
try {
$installerUrl = 'https://github.com/microsoft/winget-cli/releases/latest/download/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle'
$installerPath = Join-Path $env:TEMP 'winget.msixbundle'
Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath -ErrorAction Stop
# May require elevation.
Add-AppxPackage -Path $installerPath -ErrorAction Stop
Remove-Item $installerPath -ErrorAction SilentlyContinue
return [bool](Get-Command winget -ErrorAction SilentlyContinue)
} catch {
Write-Warning "winget install failed: $($_.Exception.Message)"
return $false
}
}
function Ensure-WingetPackage {
param(
[Parameter(Mandatory)][string]$Id,
[Parameter(Mandatory)][string]$Command,
[Parameter(Mandatory)][string]$Label
)
if (Get-Command $Command -ErrorAction SilentlyContinue) {
Write-Host (" {0,-26} already installed" -f $Label) -ForegroundColor DarkGray
return
}
Write-Host (" {0,-26} installing via winget..." -f $Label)
winget install -e --id $Id --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
Write-Warning "$Label install returned exit code $LASTEXITCODE."
}
}
Write-Host ""
if ($onWindows) {
Write-Host "Windows-only modules:" -ForegroundColor Cyan
# AzureAD targets .NET Framework and cannot be imported by PowerShell 7.
# It installs fine, but only Windows PowerShell 5.1 can load it.
Ensure-Module -Name 'AzureAD' `
-Note 'AzureAD loads only under Windows PowerShell 5.1, not pwsh 7.'
if ($PSVersionTable.PSEdition -ne 'Desktop') {
Write-Host " Note: import AzureAD from Windows PowerShell 5.1, or use" -ForegroundColor Yellow
Write-Host " Import-Module AzureAD -UseWindowsPowerShell from pwsh 7." -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Windows CLI tools:" -ForegroundColor Cyan
if (Ensure-Winget) {
Ensure-WingetPackage -Id 'Microsoft.AzureCLI' -Command 'az' -Label 'Azure CLI'
Ensure-WingetPackage -Id 'Microsoft.Azure.FunctionsCoreTools' -Command 'func' -Label 'Functions Core Tools'
Ensure-WingetPackage -Id 'Git.Git' -Command 'git' -Label 'Git'
} else {
Write-Host " winget unavailable - install az, func and git manually." -ForegroundColor Yellow
}
} else {
Write-Host "Skipping Windows-only components on this platform:" -ForegroundColor Cyan
Write-Host " AzureAD - .NET Framework only; cannot load on pwsh 7."
Write-Host " ANIMO panels that need it degrade rather than break."
Write-Host " winget - Windows package manager."
Write-Host " az / func / git - install via ./install-dependencies.sh or your"
Write-Host " distro package manager."
}
# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
Write-Host ""
Write-Host "--- Verifying ---" -ForegroundColor Cyan
$check = $azSubmodules + $crossPlatform.Name
if (-not $SkipUmbrellaAz) { $check += 'Az' }
if ($onWindows) { $check += 'AzureAD' }
foreach ($m in $check) {
$found = Get-Module -ListAvailable -Name $m -ErrorAction SilentlyContinue
if ($found) {
$ver = ($found.Version | Select-Object -Unique | Sort-Object -Descending | Select-Object -First 1)
Write-Host (" {0,-26} {1}" -f $m, $ver) -ForegroundColor Green
} else {
Write-Host (" {0,-26} MISSING" -f $m) -ForegroundColor Red
}
}
Write-Host ""
Write-Host "Done. No modules were removed and nothing was cloned into this directory." -ForegroundColor Green
Write-Host "Third-party tooling ANIMO pairs well with is listed under 'Related Tooling'"
Write-Host "in README.md - clone those outside this repository."
Write-Host ""
+77 -13
View File
@@ -56,21 +56,21 @@ ANIMO is a comprehensive Azure AD / Entra ID assessment platform that combines *
| Requirement | Version |
|:------------|:--------|
| OS | Linux (Kali recommended), macOS, or Windows with WSL2 |
| Qt6 | 6.2+ (Widgets, Network, WebEngineWidgets, Sql) |
| OS | Linux (Kali recommended, build verified), macOS, or Windows — natively or via WSL2 |
| Qt6 | 6.2+ (Widgets, Network, WebEngineWidgets, Sql; plus the Svg image plugin for the app icon) |
| CMake | 3.16+ |
| PowerShell | 7.x (`pwsh`) |
| Azure CLI | 2.x (`az`) — optional but recommended for parity |
| Python | 3.8+ with `msal`, `requests` |
### Install & Build
### Install & Build (Linux)
```bash
# Clone the repository
git clone https://github.com/dmcxblue/ANIMO.git
cd ANIMO
# Install system dependencies (Linux/Kali)
# Install system dependencies (Debian / Ubuntu / Kali)
./install-dependencies.sh
# Install PowerShell modules
@@ -80,6 +80,34 @@ pwsh -File Install-AllModules.ps1
./build.sh
```
### Build on Windows
The CMake project is cross-platform and `Install-AllModules.ps1` runs on both
platforms, but the build itself is currently only verified on Linux. On Windows,
install the prerequisites yourself and invoke CMake directly:
```powershell
# Prerequisites (via winget, or the Qt Online Installer for Qt itself)
winget install -e --id Kitware.CMake
winget install -e --id Ninja-build.Ninja
winget install -e --id ShiningLight.OpenSSL.Light
# Qt 6.2+ with the Qt WebEngine and Qt SQL modules, plus MSVC (Visual Studio
# Build Tools with the C++ workload). Note the Qt install prefix.
# PowerShell modules
pwsh -File Install-AllModules.ps1
# Configure and build - point CMAKE_PREFIX_PATH at your Qt6 install
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release `
-DCMAKE_PREFIX_PATH="C:/Qt/6.7.2/msvc2019_64"
cmake --build build
```
Binaries land in `build\server\AnimoServer.exe` and `build\client\AnimoClient.exe`.
The hardening flags in the top-level `CMakeLists.txt` are GCC/Clang-only and are
skipped under MSVC. `build.sh` and `clean.sh` are bash scripts — use the CMake
commands above, or run them from WSL2.
### Launch
```bash
@@ -540,16 +568,52 @@ AnimoServer [options]
### Required PowerShell Modules
Installed automatically by `Install-AllModules.ps1`:
Installed by `Install-AllModules.ps1`. The script is additive — it never removes
modules you already have — and skips Windows-only components on Linux and macOS
with a message rather than failing.
| Module | Purpose |
|:-------|:--------|
| `Az` | Azure Resource Manager |
| `AzureAD` | Azure Active Directory |
| `AADInternals` | Azure AD internals & token operations |
| `Microsoft.Graph` | Microsoft Graph SDK |
| `SqlServer` | Azure SQL operations |
| `AzTable` | Azure Table Storage |
| Module | Purpose | Platform |
|:-------|:--------|:---------|
| `Az.Accounts`, `Az.Resources`, `Az.Compute`, `Az.Network`, `Az.Storage`, `Az.KeyVault`, `Az.Monitor` | The Az cmdlets ANIMO actually calls | Any |
| `Az` | Umbrella meta-module (~2 GB; skip with `-SkipUmbrellaAz`) | Any |
| `Microsoft.Graph` | Microsoft Graph SDK | Any |
| `SqlServer` | `Invoke-SqlCmd` for the SQL Database module | Any |
| `AADInternals` | Azure AD internals & token operations | Any (some cmdlets Windows-only) |
| `AADInternals-Endpoints` | AADInternals endpoint helpers | Any (some cmdlets Windows-only) |
| `AzTable` | Azure Table Storage | Any |
| `AzureAD` | Azure Active Directory (legacy) | **Windows only** |
`AzureAD` targets .NET Framework and cannot be imported by PowerShell 7 — use
Windows PowerShell 5.1, or `Import-Module AzureAD -UseWindowsPowerShell` from
pwsh 7 on Windows. On Linux the `Get-AzureAD*` terminal autocompletions remain
available but the cmdlets will not resolve; every ANIMO panel has an Az or Graph
code path, so nothing depends on `AzureAD` being present.
On Windows the script also installs `az`, `func`, and `git` via winget. On Linux,
`az` comes from `install-dependencies.sh`.
### Related Tooling
ANIMO pairs well with these projects. Clone them **outside** this repository:
```bash
mkdir -p ~/tools && cd ~/tools
```
| Project | Purpose |
|:--------|:--------|
| [AADInternals](https://github.com/Gerenios/AADInternals) | Azure AD internals research toolkit |
| [ROADtools](https://github.com/dirkjanm/ROADtools) | Azure AD exploration and enumeration |
| [TokenTacticsV2](https://github.com/f-bader/TokenTacticsV2) | Token manipulation and family refresh abuse |
| [APEX](https://github.com/LuemmelSec/APEX) | Azure privilege escalation toolkit |
| [PowerZure](https://github.com/hausec/PowerZure) | Azure post-exploitation framework |
| [MicroBurst](https://github.com/NetSPI/MicroBurst) | Azure enumeration and privesc scripts |
| [Stormspotter](https://github.com/Azure/Stormspotter) | Azure attack-graph visualisation |
| [MFASweep](https://github.com/dafthack/MFASweep) | MFA coverage gap discovery |
| [MSOLSpray](https://github.com/dafthack/MSOLSpray) | Password spraying against Microsoft Online |
| [Office365Hacker](https://github.com/YasserREED/Office365Hacker) | Office 365 attack tooling |
| [OffensiveCloud](https://github.com/lutzenfried/OffensiveCloud) | Multi-cloud offensive references |
| [ROADtoken gist](https://gist.github.com/xpn/f12b145dba16c2eebdd1c6829267b90c) | PRT cookie retrieval via browsercore |
---
+10 -4
View File
@@ -167,16 +167,22 @@ void WHfBAttackWindow::setLoading(bool loading) {
}
QString WHfBAttackWindow::findPythonScript() {
QString appDir = QCoreApplication::applicationDirPath();
QStringList searchPaths = {
QCoreApplication::applicationDirPath() + "/../helpers/DeviceCode2WFH.py",
QCoreApplication::applicationDirPath() + "/../../helpers/DeviceCode2WFH.py",
appDir + "/../../helpers/DeviceCode2WFH.py",
appDir + "/../helpers/DeviceCode2WFH.py",
appDir + "/helpers/DeviceCode2WFH.py",
appDir + "/DeviceCode2WFH.py",
QDir::currentPath() + "/helpers/DeviceCode2WFH.py",
"/home/dmcxblue/Documents/OffensiveTools/Azure/ANIMO/helpers/DeviceCode2WFH.py"
"../../helpers/DeviceCode2WFH.py",
"../helpers/DeviceCode2WFH.py",
"helpers/DeviceCode2WFH.py",
"DeviceCode2WFH.py"
};
for (const QString &path : searchPaths) {
QFileInfo fi(path);
if (fi.exists()) {
if (fi.exists() && fi.isFile()) {
return fi.absoluteFilePath();
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ function Get-PRTToken {
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[string]$WebhookUrl # Example: http://192.168.1.61:8000/
[string]$WebhookUrl # Example: http://<LISTENER_IP>:8000/
)
process {
+1 -1
View File
@@ -2,7 +2,7 @@ function Get-UserPRTToken {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$WebhookUrl # Example: http://192.168.1.61:8000/
[string]$WebhookUrl # Example: http://<LISTENER_IP>:8000/
)
process {
@@ -5,7 +5,7 @@ namespace GrabTokenAzureAD
class CombinedGrabber
{
// ========== HARDCODED CONFIGURATION ==========
private const string CALLBACK_URL = "http://192.168.1.21:8000/capture";
private const string CALLBACK_URL = "http://127.0.0.1:8000/capture";
private const string CLIENT_ID = "1950a258-227b-4e31-a9cf-717495945fc2"; // Azure PowerShell
private const string TENANT = "common";
private const string REDIRECT_URI = "http://localhost:8400";
+1 -1
View File
@@ -137,7 +137,7 @@ Options:
Default: http://localhost:8400
-u, --callback <url> ANIMO webhook URL to send captured tokens
Default: http://192.168.1.21:8000/capture
Default: http://127.0.0.1:8000/capture
--no-callback Disable sending tokens to callback URL
@@ -150,7 +150,7 @@ namespace GrabTokenAzureAD
public string RedirectUri { get; set; } = "http://localhost:8400";
public string GraphScope { get; set; } = "offline_access https://graph.microsoft.com/.default";
public string ManagementScope { get; set; } = "https://management.azure.com/.default";
public string CallbackUrl { get; set; } = "http://192.168.1.21:8000/capture";
public string CallbackUrl { get; set; } = "http://127.0.0.1:8000/capture";
public int ListenerTimeoutSeconds { get; set; } = 300;
public string Authority => $"https://login.microsoftonline.com/{Tenant}/oauth2/v2.0";
+1 -1
View File
@@ -213,7 +213,7 @@ Examples:
python3 webhook_capture.py -p 9000
# Start server on specific interface
python3 webhook_capture.py -i 192.168.1.61 -p 8000
python3 webhook_capture.py -i <LISTENER_IP> -p 8000
# Auto-save captured data
python3 webhook_capture.py -o captured_prt.json
+92 -19
View File
@@ -1,39 +1,112 @@
#!/usr/bin/env bash
#
# install-dependencies.sh - Debian/Ubuntu/Kali build and runtime dependencies.
#
# Installs the Qt6 + CMake toolchain ANIMO builds against, PowerShell 7, and
# (optionally) the Azure CLI. For the PowerShell modules themselves, run
# `pwsh -File Install-AllModules.ps1` afterwards.
#
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
# Update package lists
echo "[*] Updating package lists..."
sudo apt-get update
# Install toolchain + Qt6 deps
echo "[*] Installing toolchain and Qt6 development packages..."
sudo apt-get install -y --no-install-recommends \
build-essential \
cmake \
ninja-build \
curl \
ca-certificates \
qt6-base-dev \
qt6-tools-dev \
qt6-tools-dev-tools \
qt6-base-dev-tools \
qt6-webengine-dev \
qt6-webengine-dev-tools \
qt6-websockets-dev \
libqt6svg6 \
libqt6sql6 \
libqt6sql6-sqlite \
libssl-dev \
snapd
libssl-dev
sudo snap install powershell --classic
# ---------------------------------------------------------------------------
# PowerShell 7
#
# Kali does not ship snapd and enabling it there is unreliable, so prefer the
# .deb Microsoft publishes on GitHub and fall back to snap only if that fails.
# ---------------------------------------------------------------------------
# Azure CLI - login scripts opportunistically call `az login` alongside
# Connect-AzAccount so operators can run `az` one-liners in the session
# terminal. If az isn't on PATH the login scripts skip it cleanly, so
# this install is optional but recommended.
if ! command -v az >/dev/null 2>&1; then
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash || {
echo "[!] az cli install failed - continuing without it. Login scripts will skip az login."
}
install_powershell_deb() {
local arch deb_arch url tmp
arch="$(dpkg --print-architecture)"
case "$arch" in
amd64) deb_arch="x64" ;;
arm64) deb_arch="arm64" ;;
*) echo "[!] No PowerShell .deb for architecture '$arch'."; return 1 ;;
esac
echo "[*] Resolving latest PowerShell release..."
local version
version="$(curl -fsSL https://api.github.com/repos/PowerShell/PowerShell/releases/latest \
| grep -oP '"tag_name":\s*"v\K[^"]+' || true)"
if [ -z "$version" ]; then
echo "[!] Could not determine the latest PowerShell version."
return 1
fi
url="https://github.com/PowerShell/PowerShell/releases/download/v${version}/powershell_${version}-1.deb_${deb_arch}.deb"
tmp="$(mktemp -d)"
echo "[*] Downloading PowerShell ${version} (${deb_arch})..."
if ! curl -fsSL -o "$tmp/powershell.deb" "$url"; then
echo "[!] Download failed: $url"
rm -rf "$tmp"
return 1
fi
# apt-get install on a local .deb pulls its dependencies; dpkg alone would not.
sudo apt-get install -y "$tmp/powershell.deb"
rm -rf "$tmp"
}
install_powershell_snap() {
command -v snap >/dev/null 2>&1 || sudo apt-get install -y snapd
sudo snap install powershell --classic
}
if command -v pwsh >/dev/null 2>&1; then
echo "[+] PowerShell already installed: $(pwsh --version)"
else
echo "[*] Installing PowerShell 7..."
if install_powershell_deb; then
echo "[+] PowerShell installed from .deb."
elif install_powershell_snap; then
echo "[+] PowerShell installed from snap."
else
echo "[!] PowerShell install failed. ANIMO needs pwsh for its session"
echo " terminal - install it manually before running the server:"
echo " https://learn.microsoft.com/powershell/scripting/install/installing-powershell-on-linux"
fi
fi
# Optional: reduce layer size in containers/CI
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
# ---------------------------------------------------------------------------
# Azure CLI (optional)
#
# The login scripts opportunistically call `az login` alongside Connect-AzAccount
# so operators can run `az` one-liners in the session terminal. If az is missing
# the login scripts skip it cleanly, so this is recommended but not required.
# ---------------------------------------------------------------------------
if command -v az >/dev/null 2>&1; then
echo "[+] Azure CLI already installed."
else
echo "[*] Installing Azure CLI..."
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash || {
echo "[!] az cli install failed - continuing without it."
echo " Login scripts will skip az login."
}
fi
echo
echo "[+] Dependencies installed."
echo " Next: pwsh -File Install-AllModules.ps1"
echo " Then: ./build.sh"
+18 -11
View File
@@ -10,10 +10,11 @@
# 2) If AnimoServer is not running, spawns it under gdb in batch mode with
# the passed CLI args. Any crash dumps full backtrace before gdb exits.
#
# Server args:
# Server args (spawn mode only):
# Pass everything after `--` and it's forwarded verbatim to AnimoServer.
# Or set env: ANIMO_IP, ANIMO_PORT, ANIMO_PASSWORD.
# Defaults: -i 192.168.1.27 -p 50500 -P rt2025
# Defaults: -i 127.0.0.1 -p 7777. ANIMO_PASSWORD has no default - either
# export it or pass -P yourself after `--`.
#
# Output goes to:
# /tmp/animo-srv-gdb.log (this script's snapshot / crash output)
@@ -32,10 +33,11 @@ REPO_ROOT="$(cd "$SELF_DIR/.." && pwd)"
SERVER_BIN="$REPO_ROOT/build/server/AnimoServer"
LOG="/tmp/animo-srv-gdb.log"
# Defaults, overridable via env or CLI passthrough.
IP="${ANIMO_IP:-192.168.1.27}"
PORT="${ANIMO_PORT:-50500}"
PASSWORD="${ANIMO_PASSWORD:-rt2025}"
# Defaults, overridable via env or CLI passthrough. No password default on
# purpose - it would end up committed and reused across engagements.
IP="${ANIMO_IP:-127.0.0.1}"
PORT="${ANIMO_PORT:-7777}"
PASSWORD="${ANIMO_PASSWORD:-}"
MODE="auto"
PASSTHROUGH=()
@@ -49,11 +51,6 @@ while [[ $# -gt 0 ]]; do
esac
done
# If nothing passed after `--`, build default arg list.
if [ ${#PASSTHROUGH[@]} -eq 0 ]; then
PASSTHROUGH=(-i "$IP" -p "$PORT" -P "$PASSWORD")
fi
require_gdb() {
command -v gdb >/dev/null || { echo "gdb not on PATH"; exit 1; }
}
@@ -83,6 +80,16 @@ snapshot() {
spawn_under_gdb() {
[ -x "$SERVER_BIN" ] || { echo "Server binary not found: $SERVER_BIN"; exit 1; }
# Only spawn mode needs server args; snapshot mode attaches to a live process.
if [ ${#PASSTHROUGH[@]} -eq 0 ]; then
if [ -z "$PASSWORD" ]; then
echo "No server password set. Either:" >&2
echo " export ANIMO_PASSWORD=<pass>" >&2
echo " or: $0 --spawn -- -i $IP -p $PORT -P <pass>" >&2
exit 1
fi
PASSTHROUGH=(-i "$IP" -p "$PORT" -P "$PASSWORD")
fi
# Kill only the server matching our port; leave unrelated instances alone.
local existing
existing=$(find_running)