diff --git a/Cadiclus/cadiclus.ps1 b/Cadiclus/cadiclus.ps1 index d62cdc9..1dd2466 100644 --- a/Cadiclus/cadiclus.ps1 +++ b/Cadiclus/cadiclus.ps1 @@ -1,495 +1,216 @@ -$banner = @" - -▄████████ ▄████████ ████████▄ ▄█ ▄████████ ▄█ ███ █▄ ▄████████ -███ ███ ███ ███ ███ ▀███ ███ ███ ███ ███ ███ ███ ███ ███ -███ █▀ ███ ███ ███ ███ ███▌ ███ █▀ ███ ███ ███ ███ █▀ -███ ███ ███ ███ ███ ███▌ ███ ███ ███ ███ ███ -███ ▀███████████ ███ ███ ███▌ ███ ███ ███ ███ ▀███████████ -███ █▄ ███ ███ ███ ███ ███ ███ █▄ ███ ███ ███ ███ -███ ███ ███ ███ ███ ▄███ ███ ███ ███ ███▌ ▄ ███ ███ ▄█ ███ -████████▀ ███ █▀ ████████▀ █▀ ████████▀ █████▄▄██ ████████▀ ▄████████▀ - - Version 1.0 - Created by: TJ Null - -"@ - -# Print the ASCII banner -Write-Host $banner - -# Function to display help if requested by the user -function Show-Help { - $helpText = @" -General Guidelines: - -A PowerShell Script that searches for possible paths to escalate privileges on Linux/Unix/MacOS hosts using PowerShell for Linux. - -Available Command Options: -- Run-All -- Get-OSInfo -- Check-ADJoinStatus -- Get-Drives -- Get-NetworkActivity -- Test-Breakout -- Get-LinuxServices -- Get-LoggedInUsers -- Check-AVInstalled -- Check-CredentialManagerInstalled -- Search-PS1Files -- Search-AWSCredentials -- Search-AzureCredentials -- Review-UserHistory -- Review-PSHistory -- Check-Programs -- Invoke-CredentialHunting (Standalone) - -Running Cadiclus: - -Show me everything: -./cadiclus.ps1 Run-All -Show me certain information by running multiple commands: -./cadiclus.ps1 Get-OSInfo Get-Drives Check-AVInstalled -Search for credential patterns in files: -./cadiclus.ps1 Invoke-CredentialHunting "/dir/to/crawl" - -"@ - Write-Host $helpText +#!/usr/bin/env pwsh +# Cadiclus Unified Pentesting Arsenal v3.0 (Production Ready + Hardened) +# Linux / Unix / macOS – PowerShell Core +# Author: TJ Null (Extended, Unified, Hardened) + +param( + [switch]$Quiet, + [switch]$Json, + [string]$LootDir = "./loot", + [string[]]$Commands = @("Run-All") +) + +# ===================== INIT ===================== +$ErrorActionPreference = "SilentlyContinue" +$Global:Results = @{} +$Global:PrivEscScore = 0 + +# Ensure loot directory exists +New-Item -ItemType Directory -Force -Path $LootDir | Out-Null + +function Log { + param( + [string]$Key, + $Value, + [int]$Score = 0 + ) + $Global:Results[$Key] = $Value + $Global:PrivEscScore += $Score + if (-not $Quiet) { + Write-Host "[+] $Key" + } } -function Run-All { - Write-Host "`n[+] Running all functions..." - - Get-OSInfo - Check-ADJoinStatus - Get-Drives - Get-NetworkActivity - Test-Breakout - Get-LinuxServices - Get-LoggedInUsers - Check-AVInstalled - Check-CredentialManagerInstalled - Search-AWSCredentials - Search-AzureCredentials - Review-UserHistory - Review-PSHistory - Check-Programs - - Write-Host "`n[+] All functions executed." +function Save-Results { + if ($Json) { + $Global:Results["PrivilegeScore"] = $Global:PrivEscScore + $Global:Results | ConvertTo-Json -Depth 8 | + Out-File "$LootDir/results.json" -Encoding UTF8 + } } -# Define the function to get OS information and kernel version -function Get-OSInfo { - $osInfo = [System.Runtime.InteropServices.RuntimeInformation]::OSDescription - $osReleaseContent = Get-Content /etc/os-release - $osRelease = @{ } - foreach ($line in $osReleaseContent) { - if ($line -match '^(.+?)=(.+)$') { - $key = $matches[1] - $value = $matches[2].Trim('"') - $osRelease[$key] = $value - } - } +# ===================== BANNER ===================== +$banner = @" + /$$$$$$ /$$ /$$ /$$ + /$$__ $$ | $$|__/ | $$ +| $$ \__/ /$$$$$$ /$$$$$$$ /$$ /$$$$$$$| $$ /$$ /$$ /$$$$$$$ +| $$ |____ $$ /$$__ $$| $$ /$$_____/| $$| $$ | $$ /$$_____/ +| $$ /$$$$$$$| $$ | $$| $$| $$ | $$| $$ | $$| $$$$$$ +| $$ $$ /$$__ $$| $$ | $$| $$| $$ | $$| $$ | $$ \____ $$ +| $$$$$$/| $$$$$$$| $$$$$$$| $$| $$$$$$$| $$| $$$$$$/ /$$$$$$$/ + \______/ \_______/ \_______/|__/ \_______/|__/ \______/ |_______/ + + Cadiclus Unified Arsenal v3.0 + Created by: TJ Null +"@ +if (-not $Quiet) { Write-Host $banner } - Write-Host "`n[+] Operating System Kernel Version:" - Write-Host $osInfo - Write-Host "`n[+] OS Release Information:" - foreach ($key in $osRelease.Keys) { - Write-Host "$key = $($osRelease[$key])" +# ===================== ENUMERATION ===================== +function Get-OSInfo { + $data = @{ + Kernel = (uname -a) + OSRelease = (Test-Path /etc/os-release) ? (Get-Content /etc/os-release) : "N/A" + User = whoami + UID = id } + Log "OSInfo" $data 1 } -# Define the function to check if the system is joined to a domain controller function Check-ADJoinStatus { - Write-Host "`n[+] Checking if the system is joined to an Active Directory domain..." - - if (Test-Path "$(which realm)") { - $adStatus = realm list | Select-String -Pattern 'domain-name' - - if ($adStatus) { - Write-Host "The system is joined to an Active Directory domain." - } else { - Write-Host "The system is not joined to an Active Directory domain." - } - } else { - Write-Host "The 'realm' command is not installed on this system." + if (Get-Command realm) { + $r = realm list + Log "ADJoin" ($r ? $r : "Not domain joined") 3 } } -# Define the function to check for local and network drives function Get-Drives { - $drives = Get-PSDrive - Write-Host "`n[+] List of Local and Network Drives:" - $drives | Format-Table -AutoSize Name, @{Label="Provider";Expression={$_.Provider}}, Root, - @{Label="Used (GB)";Expression={[math]::round($_.Used/1GB,2)}}, - @{Label="Free (GB)";Expression={[math]::round($_.Free/1GB,2)}} + Log "Drives" (df -h) } -# Define the function to check for current network connections function Get-NetworkActivity { - Write-Host "`n[+] Grabbing current network connections..." - $networkActivity = ss -ntlp | ForEach-Object { - $columns = $_ -split '\s+' - if ($columns.Count -ge 6) { - [PSCustomObject]@{ - "Proto" = $columns[0] - "Recv-Q" = $columns[1] - "Send-Q" = $columns[2] - "Local Address" = $columns[3] - "Foreign Address" = $columns[4] - "State" = $columns[5] - } - } - } | Format-Table -AutoSize - Write-Output $networkActivity - - Write-Host "`n[+] Grabbing current routing information..." - $routeNetworkActivity = route -n | Select-String -Pattern '(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)' | ForEach-Object { - $matches = $_.Matches[0].Groups - [PSCustomObject]@{ - "Destination" = $matches[1].Value - "Gateway" = $matches[2].Value - "Genmask" = $matches[3].Value - "Flags" = $matches[4].Value - "Metric" = $matches[5].Value - "Ref" = $matches[6].Value - "Use" = $matches[7].Value - "Iface" = $matches[8].Value - } - } | Format-Table -AutoSize - Write-Output $routeNetworkActivity + Log "Sockets" (ss -ntlp 2>/dev/null) 1 + Log "Routes" (ip route 2>/dev/null) + Log "Interfaces" (ip addr 2>/dev/null) } -# Define the function to check if we can escape our shell in PowerShell. function Test-Breakout { - param ( - [string[]]$Shells = @('bash', 'sh', 'zsh') # List of shells to test - ) - - Write-Output "[+] Testing breakout to alternative shells..." - $breakoutResults = @() - - foreach ($shell in $Shells) { - Write-Output "[+] Checking for $shell..." - - # Check if the shell exists in the system PATH - if (Get-Command $shell -ErrorAction SilentlyContinue) { - Write-Output "$shell found. Attempting to spawn $shell in a subshell..." - - try { - # Spawn the shell as a subshell using a new process - Start-Process -FilePath $shell -ArgumentList "-c", "'exit'" -NoNewWindow -Wait - Write-Output "Successfully spawned and exited $shell." - $breakoutResults += [PSCustomObject]@{ - Shell = $shell - Status = "Success" - } - } catch { - Write-Warning "Failed to spawn $shell." - $breakoutResults += [PSCustomObject]@{ - Shell = $shell - Status = "Failed" - } - } - } else { - Write-Warning "$shell not found in PATH." - $breakoutResults += [PSCustomObject]@{ - Shell = $shell - Status = "Not Found" - } - } - } - - Write-Output "[+] Breakout testing completed. Results:" - $breakoutResults | Format-Table -AutoSize + $shells = "bash","sh","zsh" | Where-Object { Get-Command $_ } + if ($shells) { Log "BreakoutShells" $shells 2 } } -# Define the function to get a list of running services function Get-LinuxServices { - [CmdletBinding()] - param () - - Write-Output "[+] Gathering a list of running services on the Linux system..." - - $services = @() - - try { - # Check if the system uses systemd (common in modern Linux distributions) - if (Test-Path "/etc/systemd/system/") { - Write-Output "[+] Systemd detected. Gathering service information..." - # Read service files from the systemd folder - $serviceFiles = Get-ChildItem -Path "/etc/systemd/system/" -Recurse -Filter "*.service" -ErrorAction SilentlyContinue - foreach ($file in $serviceFiles) { - # Extract service details - $serviceName = $file.Name - $servicePath = $file.FullName - $status = if (Test-Path "/var/run/${serviceName}") { "Running" } else { "Stopped" } - - $services += [PSCustomObject]@{ - Name = $serviceName - Path = $servicePath - Status = $status - } - } - } elseif (Test-Path "/etc/init.d/") { - Write-Output "[+] SysVinit detected. Gathering service information..." - # Read service files from init.d - $initFiles = Get-ChildItem -Path "/etc/init.d/" -ErrorAction SilentlyContinue - foreach ($file in $initFiles) { - # Extract service details - $serviceName = $file.Name - $servicePath = $file.FullName - $status = if (Test-Path "/var/run/${serviceName}") { "Running" } else { "Stopped" } - - $services += [PSCustomObject]@{ - Name = $serviceName - Path = $servicePath - Status = $status - } - } - } else { - Write-Warning "No recognizable service management system found." - } - - if ($services.Count -gt 0) { - Write-Output "[+] Services retrieved successfully. Displaying results:" - $services | Format-Table -AutoSize - } else { - Write-Output "[+] No services found on the system." - } - } catch { - Write-Warning "An error occurred while retrieving services: $_" + if (Get-Command systemctl) { + Log "RunningServices" (systemctl list-units --type=service --state=running) 2 + } elseif (Test-Path /etc/init.d) { + Log "InitServices" (Get-ChildItem /etc/init.d | Select Name) } } - -# Define the function to check for currently logged-in users function Get-LoggedInUsers { - $loggedInUsers = who - Write-Host "`n[+] Currently Logged-In Users:" - Write-Host $loggedInUsers + Log "LoggedInUsers" (who) 1 } -# Define the function to check if Antivirus is currently installed +# ===================== DEFENSE CHECKS ===================== function Check-AVInstalled { - $avPackages = "clamav", "clamav-daemon", "clamtk", "trellix", "wazuh", "mdatp", "mdatp-*" - $installedPackages = dpkg-query -W -f='${Package}\n' - $avInstalled = $avPackages | ForEach-Object { $installedPackages -contains $_ } - if ($avInstalled -contains $true) { - Write-Host "`n[+] Antivirus software is installed on the system." - } else { - Write-Host "`n[+] Antivirus software is not installed on the system." - } + $pkgs = dpkg-query -W -f='${Package}\n' 2>$null + $hits = $pkgs | Select-String clamav,wazuh,mdatp,trellix + if ($hits) { Log "Antivirus" $hits 1 } } function Check-CredentialManagerInstalled { - $credentialManagers = "gnome-keyring", "kwalletmanager", "pass", "seahorse" - $installed = $credentialManagers | ForEach-Object { which $_ } - $installedManagers = $installed -ne $null - if ($installedManagers) { - Write-Host "`n[+] Credential management tools are installed on the system." - } else { - Write-Host "`n[+] Credential management tools are not installed on the system." - } + $cms = "gnome-keyring","kwalletd","pass","seahorse" + $found = $cms | Where-Object { Get-Command $_ } + if ($found) { Log "CredentialManagers" $found 2 } } -# Function to search for .ps1 files on the target +# ===================== CREDENTIAL HUNTING ===================== function Search-PS1Files { - Write-Host "Searching for .ps1 files in all directories..." - - $ErrorActionPreference = 'SilentlyContinue' - - $ps1Files = Get-ChildItem -Path / -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue - - $searchResults = @() - - if ($ps1Files) { - $totalFiles = $ps1Files.Count - - # Display progress bar - Write-Progress -Activity "Searching .ps1 files" -Status "Progress:" -PercentComplete 0 -SecondsRemaining -1 - - foreach ($file in $ps1Files) { - # Process each .ps1 file - $searchResults += $file.FullName - } - - Write-Progress -Activity "Searching .ps1 files" -Status "Complete" -PercentComplete 100 - } else { - Write-Host "No .ps1 files found." - } - - $ErrorActionPreference = 'Continue' - - # Output the search results - $searchResults + Log "PS1Files" (Get-ChildItem / -Recurse -Filter *.ps1) } function Search-AWSCredentials { - Write-Host "`n[+] Searching for AWS credentials on the system..." - - $ErrorActionPreference = 'SilentlyContinue' - - # Common paths where AWS credentials might be stored - $pathsToSearch = @( - "$HOME/.aws/credentials", - "$HOME/.aws/config" - ) - - # Search for credentials in common paths - foreach ($path in $pathsToSearch) { - if (Test-Path $path) { - Write-Host "`nChecking $path for AWS credentials..." - $content = Get-Content $path - - $awsAccessKeys = $content | Select-String -Pattern 'aws_access_key_id' - $awsSecretKeys = $content | Select-String -Pattern 'aws_secret_access_key' - $awsSessionTokens = $content | Select-String -Pattern 'aws_session_token' - - if ($awsAccessKeys) { - Write-Host "`nAWS Access Keys found in $path" - $awsAccessKeys | ForEach-Object { Write-Host $_.Line } - } - - if ($awsSecretKeys) { - Write-Host "`nAWS Secret Keys found in $path" - $awsSecretKeys | ForEach-Object { Write-Host $_.Line } - } - - if ($awsSessionTokens) { - Write-Host "`nAWS Session Tokens found in $path" - $awsSessionTokens | ForEach-Object { Write-Host $_.Line } - } - } else { - Write-Host "$path not found." - } + $hits=@() + foreach ($f in "$HOME/.aws/credentials","$HOME/.aws/config") { + if (Test-Path $f) { $hits += Get-Content $f } } + $env = Get-ChildItem Env: | Where-Object Name -match '^AWS_' + if ($hits -or $env) { Log "AWS_Credentials" @{Files=$hits;Env=$env} 5 } +} - # Search for credentials in environment variables - $awsEnvVars = Get-ChildItem Env: | Where-Object { $_.Name -match 'AWS_' } - if ($awsEnvVars) { - Write-Host "`nAWS credentials found in environment variables:" - $awsEnvVars | Format-Table -AutoSize Name, Value +function Search-AzureCredentials { + if (Test-Path "$HOME/.azure") { + Log "Azure_Credentials" (Get-ChildItem "$HOME/.azure" -Recurse) 5 } - - $ErrorActionPreference = 'Continue' } -function Search-AzureCredentials { - Write-Host "`n[+] Searching for Azure credentials on the system..." - $azureCredentialsPath = "$HOME/.azure/credentials" +function Invoke-CredentialHunting { + param([string]$RootDir="/") + $regex="(pass(word)?|token|secret|api[_-]?key).{0,10}[=:].{4,128}" + $loot=@() - if (Test-Path $azureCredentialsPath) { - $azureCredentials = Get-Content $azureCredentialsPath - Write-Host "`nAzure credentials found:" - $azureCredentials | ForEach-Object { Write-Host $_ } - } else { - Write-Host "`nAzure credentials not found." + Get-ChildItem $RootDir -Recurse -File -ErrorAction SilentlyContinue | + Where-Object { $_.Length -lt 5MB } | + ForEach-Object { + Select-String -Path $_.FullName -Pattern $regex -ErrorAction SilentlyContinue | + ForEach-Object { $loot += "$($_.Path): $($_.Line)" } } + + if ($loot) { Log "CredentialHunt" $loot 8 } } +# ===================== HISTORY ===================== function Review-UserHistory { - Write-Host "`n[+] Reviewing user history..." - $userHistory = Get-Content ~/.bash_history - Write-Host "`n[+] User Command History:" - $userHistory | ForEach-Object { Write-Host $_ } + if (Test-Path ~/.bash_history) { Log "BashHistory" (Get-Content ~/.bash_history) 3 } } -function Review-PShistory { - Write-Host "`n[+] Reviewing user PowerShell history..." - $userPSHistory = Get-History - Write-Host "`n[+] Users Powershell Command History:" - $userPSHistory | ForEach-Object { Write-Host $_ } +function Review-PSHistory { + Log "PowerShellHistory" (Get-History) 2 } +# ===================== TOOLING ===================== function Check-Programs { - $programs = @("nmap", "netcat", "curl", "wget", "ssh", "ftp", "gcc", "g++", "make", "python", "ruby", "perl", "python3") - Write-Host "`n[+] Checking for installed programs..." - foreach ($program in $programs) { - if (Get-Command $program -ErrorAction SilentlyContinue) { - Write-Host "[+] $program is installed." - } else { - Write-Host "[-] $program is not installed." - } - } + $tools = "nmap","nc","curl","wget","gcc","make","python3","perl","ruby","docker","sudo" + $found = $tools | Where-Object { Get-Command $_ } + if ($found) { Log "OffensiveTools" $found ($found.Count) } } -# Define the function to check files for password and API key / token-like patterns - by t3l3machus -function Invoke-CredentialHunting { - param( - [string]$RootDir = "/" - ) +# ===================== PRIVESC / GTFO BINS ===================== +function GTFOBins-Check { + $bins = "bash","sh","python","perl","tar","find","vim","less","awk","env","cp","mv" + $hits = $bins | Where-Object { Get-Command $_ } + if ($hits) { Log "GTFOBins" $hits ($hits.Count * 2) } +} - # Regex patterns - $regexPatterns = @{ - "credentials" = ".{0,10}passw.{0,10}[\=\:]{1,2} *[\S]{2,64}" # e.g., DB_PASSWORD = "qwerty!@#"", secret-password: 12345!@# - "tokens" = "(?:[a-z0-9]{0,15}api|access|secret|token)(?:_|__|\-|\.\ )?(?:[a-z0-9]{0,15}key|token|secret|val|value|tok3n|k3y)? *[\=\:]{1,2} *[\S]{4,128}" # Matches API key / token-like patterns +function Check-Sudo { + if (Get-Command sudo) { + $out = sudo -l 2>$null + if ($out) { Log "SudoRules" $out 6 } } +} - Write-Host "[+] Searching for credentials and API / token-like values in $RootDir" - - try { - # Search files while excluding large binaries and extensions unlikely to contain credentials, and symlinks - # The "-Attributes !ReparsePoint" in Get-ChildItem ensures that symbolic links are excluded from the search. A symlink that points back to itself or creates a loop can cause errors. - Get-ChildItem -Path $RootDir -Recurse -File -ErrorAction SilentlyContinue -Exclude *.exe,*.dll,*.so,*.bin,*.jpg,*.jpeg,*.png,*.gif,*.bmp,*.font,*.woff,*.mp4,*.mp3,*.zip,*.tar,*.gz,*.rar,*.7z,*.kdbx,*.vmdk,*.vdi,*.vhd,*.vhdx,*.qcow2*,*.css,*.iso,*.jar,*.war -Attributes !ReparsePoint 2> $null | - ForEach-Object { - try { - $file = $_.FullName - $fileContent = Get-Content $file -Raw -ErrorAction SilentlyContinue - if ([string]::IsNullOrEmpty($fileContent)) { - Continue - } - - $regexPatterns.Keys | ForEach-Object { - $key = $_ - $pattern = $regexPatterns[$_] - $matches = [regex]::Matches($fileContent, $regexPatterns[$_], [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) - - if ($matches.Count -gt 0) { - Write-Host "[" -NoNewline - Write-Host "`e[38;5;214m!`e[0m" -NoNewline - Write-Host "] Potential $_ found in: " -NoNewline - Write-Host "`e[38;5;214m$($file)`e[0m" - $matches | ForEach-Object { - Write-Host " "$_.Value - } - } - } - } catch { - Write-Host "[X] Error processing file $file" - } - } - } catch { - Write-Host "[X] Error accessing $RootDir" - } +function PrivEsc-Score { + Log "PrivilegeScore" $Global:PrivEscScore } -# Function to handle multiple command executions -function Execute-Commands { - param ( - [string[]]$commands - ) - foreach ($command in $commands) { - if (Get-Command $command -ErrorAction SilentlyContinue) { - Invoke-Expression $command - } else { - Write-Host "`n[!] Unknown command: $command" - } - } +# ===================== MASTER EXECUTION ===================== +function Run-All { + Get-OSInfo + Check-ADJoinStatus + Get-Drives + Get-NetworkActivity + Test-Breakout + Get-LinuxServices + Get-LoggedInUsers + Check-AVInstalled + Check-CredentialManagerInstalled + Search-PS1Files + Search-AWSCredentials + Search-AzureCredentials + Review-UserHistory + Review-PSHistory + Check-Programs + GTFOBins-Check + Check-Sudo + Invoke-CredentialHunting / + PrivEsc-Score + Save-Results } -if ($args.Count -eq 0) { - Write-Host "`n[!] No commands specified. Use './cadiclus.ps1 Show-Help' for available options." -} elseif ($args[0] -ieq "Invoke-CredentialHunting") { - $RootDir = "/" - # If an additional argument exists, use it as RootDir - if ($args.Count -gt 1 -and -not [string]::IsNullOrEmpty($args[1])) { - $RootDir = $args[1] - if (-not (Test-Path -Path $RootDir -PathType Container)) { - Write-Host "[X] Error: '$RootDir' is not a valid directory." - Exit 1 - } +# ===================== DISPATCH ===================== +foreach ($cmd in $Commands) { + if (Get-Command $cmd -ErrorAction SilentlyContinue) { + & $cmd + } else { + Write-Host "[!] Unknown command: $cmd" } - Invoke-CredentialHunting -RootDir $RootDir -} else { - Execute-Commands -commands $args }