├── .gitignore ├── Modules └── Empire │ ├── BlueCommandData.psm1 │ └── BlueCommandEmpire.psm1 ├── Pages ├── AgentLogs.ps1 ├── Configuration.ps1 ├── Downloads.ps1 ├── Execution.ps1 └── home.ps1 ├── README.md ├── bluecommand.psd1 ├── bluecommand.psm1 ├── img ├── AgentDownload.gif ├── Credential_Manager.png ├── ExecuteModule.gif ├── HomePage.png └── empire_rest.png └── start.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | Tools/DomainPasswordSpray.ps1 2 | Tools/DomainPasswordSpray/DomainPasswordSpay.psd1 3 | Tools/DomainPasswordSpray/DomainPasswordSpray.psm1 4 | scan.json 5 | scratch.ps1 6 | Data/EmpireAgents.json 7 | Data/EmpireConfig.json 8 | Data/EmpireModules.json 9 | Data/NetworkScan.json 10 | Data/AuditLog.log 11 | test.ps1 12 | Data/Downloads/8BYZEAXN/screenshot/LEE-NUC1_2019-01-21_02-59-58.png 13 | Data/Downloads/ -------------------------------------------------------------------------------- /Modules/Empire/BlueCommandData.psm1: -------------------------------------------------------------------------------- 1 | #### All functions need to have proper function params, synopsis, help, etc.... 2 | #### Also where my psd1 file at 3 | 4 | Function Get-BSJSONObject 5 | { 6 | Param( 7 | [Parameter(Mandatory=$true)] $BSFile 8 | ) 9 | 10 | if(Test-Path($BSFile)) 11 | { 12 | $FileContents = Get-Childitem -file $BSFile 13 | $Length = $FileContents.Length 14 | 15 | iF($Length -ne 0) 16 | { 17 | $JsonObject = ConvertFrom-Json -InputObject (Get-Content $BSFile -raw) 18 | return $JsonObject 19 | } 20 | else 21 | { 22 | # Empty File 23 | return $null 24 | } 25 | 26 | 27 | } 28 | else 29 | { 30 | # Does not Exist 31 | return $null 32 | } 33 | } 34 | 35 | Function Get-BSEmpireAgentData() 36 | { 37 | 38 | $Data = @() 39 | $ResourcesJsonContent = Get-BSJSONObject -BSFile $Cache:EmpireAgentFilePath 40 | 41 | #### Data Stuff 42 | foreach($Resource in $ResourcesJsonContent) 43 | { 44 | $Data = $Data +[PSCustomObject]@{ 45 | id=($Resource.id); 46 | name=($Resource.name); 47 | checkin_time=($Resource.checkin_time); 48 | external_ip=($Resource.external_ip); 49 | hostname=($Resource.hostname); 50 | internal_ip=($Resource.internal_ip); 51 | langauge=($Resource.langauge); 52 | langauge_version=($Resource.langauge_version); 53 | lastseen_time=($Resource.lastseen_time); 54 | listener=($Resource.listener); 55 | os_details=($Resource.os_details); 56 | username=($Resource.username); 57 | } 58 | } 59 | 60 | return $Data 61 | } 62 | 63 | 64 | 65 | Function Get-BSEmpireConfigData() 66 | { 67 | 68 | $Data = @() 69 | $ResourcesJsonContent = Get-BSJSONObject -BSFile $Cache:EmpireConfigFilePath 70 | 71 | #### Data Stuff 72 | foreach($Resource in $ResourcesJsonContent) 73 | { 74 | $Data = $Data +[PSCustomObject]@{ 75 | empire_host=($Resource.empire_host); 76 | empire_port=($Resource.empire_port); 77 | empire_token=($Resource.empire_token); 78 | api_username=($Resource.api_username); 79 | install_path=($Resource.install_path); 80 | version=($Resource.version); 81 | sync_time=($Resource.sync_time) 82 | } 83 | } 84 | 85 | return $Data 86 | 87 | 88 | } 89 | 90 | 91 | Function Get-BSEmpireModuleData() 92 | { 93 | 94 | $Data = @() 95 | $Options = @() 96 | $FirstPartOfDefinition = '^.*=@{Description=' 97 | $SecondPartOfDefinition = ';.*;.*Value=.*}' 98 | 99 | $ResourcesJsonContent = Get-BSJSONObject -BSFile $Cache:EmpireModuleFilePath 100 | 101 | #### Data Stuff 102 | foreach($Module in $ResourcesJsonContent) 103 | { 104 | 105 | #Propertize the Module Objects 106 | $ModuleOptionsObject = @() 107 | $ModuleOptions = $Module.options 108 | 109 | $ModuleOptionsNotes = $ModuleOptions | Get-Member -MemberType NoteProperty 110 | ForEach($Note in $ModuleOptionsNotes) 111 | { 112 | 113 | $OptionDefinitionFormatted = $Note.Definition 114 | $OptionDefinitionFormatted = $OptionDefinitionFormatted -replace $FirstPartOfDefinition," " 115 | $OptionDefinitionFormatted = $OptionDefinitionFormatted -replace $SecondPartOfDefinition,"" 116 | 117 | $ModuleOptionsObject = $ModuleOptionsObject +[PSCustomObject]@{ 118 | Name=($Note.Name); 119 | Definition=($OptionDefinitionFormatted); 120 | } 121 | } 122 | 123 | 124 | $Data = $Data +[PSCustomObject]@{ 125 | Name=($Module.name); 126 | Author=($Module.Author); 127 | Description=($Module.Description); 128 | Language=($Module.Language); 129 | NeedsAdmin=($Module.NeedsAdmin); 130 | OpsecSafe=($Module.OpsecSafe); 131 | Options=($ModuleOptionsObject); 132 | } 133 | } 134 | 135 | 136 | 137 | return $Data 138 | 139 | 140 | } 141 | 142 | Function Get-BSDownloadsCount 143 | { 144 | $Count = 0 145 | $BSDownloadsPath = $Cache:BSDownloadsPath 146 | $AgentFiles = ($BSDownloadsPath + '\') | Get-ChildItem -Recurse | where {! $_.PSIsContainer } 147 | $Count = $AgentFiles.Count 148 | 149 | return $Count 150 | } 151 | 152 | 153 | Function Get-BSDownloads 154 | { 155 | param( 156 | $AgentName = $null 157 | ) 158 | 159 | $BSDownloadsPath = $Cache:BSDownloadsPath 160 | 161 | $DownloadedFiles = @() 162 | 163 | if($AgentName -ne $null) 164 | { 165 | $AgentFolderName = $Folder.Name 166 | $AgentFolderPath = $BSDownloadsPath + '\'+ $AgentName 167 | $AgentFiles = ($AgentFolderPath + '\') | Get-ChildItem -Recurse | where { ! $_.PSIsContainer } 168 | ForEach($File in $AgentFiles) 169 | { 170 | $FullPath = $File.FullName 171 | $ParentDirectory = $AgentFolderName 172 | $Directory = $File.Directory.FullName 173 | $DownloadedFiles += $File | Select-Object -Property Name, FullName, CreationTime, @{Name="Agent"; Expression = {$ParentDirectory}}, @{Name="Directory"; Expression = {$Directory}}, @{Name="FullPath"; Expression = {$FullPath}} 174 | } 175 | 176 | } 177 | else 178 | { 179 | $AgentFolders = ($Cache:BSDownloadsPath + '\') | Get-ChildItem | ?{ $_.PSIsContainer } 180 | 181 | Foreach($Folder in $AgentFolders) 182 | { 183 | $AgentFolderName = $Folder.Name 184 | $AgentFolderPath = $Folder.FullName 185 | $AgentFiles = ($AgentFolderPath + '\') | Get-ChildItem -Recurse | where { ! $_.PSIsContainer } 186 | ForEach($File in $AgentFiles) 187 | { 188 | $FullPath = $File.FullName 189 | $ParentDirectory = $AgentFolderName 190 | $Directory = $File.Directory.FullName 191 | $DownloadedFiles += $File | Select-Object -Property Name, FullName, CreationTime, @{Name="Agent"; Expression = {$ParentDirectory}},@{Name="Directory"; Expression = {$Directory}}, @{Name="FullPath"; Expression = {$FullPath}} 192 | } 193 | } 194 | } 195 | 196 | return ($DownloadedFiles) 197 | 198 | } 199 | 200 | 201 | 202 | Function Get-BSNetworkScanData() 203 | { 204 | 205 | $Data = @() 206 | $ResourcesJsonContent = Get-BSJSONObject -BSFile $Cache:NetworkScanFilePath 207 | 208 | #### Data Stuff 209 | foreach($Resource in $ResourcesJsonContent) 210 | { 211 | $Data = $Data +[PSCustomObject]@{ 212 | HostName=($Resource.Hostname); 213 | IPv4=($Resource.IPv4); 214 | Status=($Resource.Status); 215 | Computer=(New-UDLink -Text "RDP" -Url "remotedesktop://$Resource.IPv4"); 216 | Note=""; 217 | LastScan=($Resource.ScanTime.DateTime); 218 | isEmpire=($Resource.EmpireServer); 219 | } 220 | } 221 | 222 | return $Data 223 | 224 | } 225 | 226 | 227 | 228 | Function Clear-BSJON 229 | { 230 | Param( 231 | [Parameter(Mandatory=$true)] $BSFile 232 | ) 233 | if(Test-Path($BSFile)) 234 | { 235 | # Clear Existings 236 | Clear-Content $BSFile -Force 237 | } 238 | else 239 | { 240 | # Does not Exist 241 | } 242 | } 243 | 244 | 245 | Function Write-BSJSON 246 | { 247 | Param ( 248 | [Parameter(Mandatory=$true)] $BSFile = '', 249 | [Parameter(Mandatory=$true)] $BSObjectData 250 | ) 251 | 252 | $BSObjectData | ConvertTo-Json | Out-File $BSFile -Append 253 | 254 | 255 | } 256 | 257 | 258 | Function Write-BSObjectToJSON 259 | { 260 | Param ( 261 | [Parameter(Mandatory=$true)] $BSFile = '', 262 | [Parameter(Mandatory=$true)] $BSObjectData 263 | ) 264 | 265 | $BSObjectData | ConvertTo-Json | Out-File $BSFile -Append 266 | 267 | 268 | } 269 | 270 | 271 | 272 | 273 | Function Write-BSEmpireAgentData 274 | { 275 | Param ( 276 | [Parameter(Mandatory=$true)] $BSObjectData 277 | ) 278 | 279 | Clear-BSJON -BSFile $Cache:EmpireAgentFilePath 280 | Write-BSJSON -BSFile $Cache:EmpireAgentFilePath -BSObjectData $BSObjectData 281 | 282 | } 283 | 284 | 285 | Function Write-BSEmpireConfigData 286 | { 287 | Param ( 288 | [Parameter(Mandatory=$true)] $BSObjectData 289 | ) 290 | Clear-BSJON -BSFile $Cache:EmpireConfigFilePath 291 | Write-BSJSON -BSFile $Cache:EmpireConfigFilePath -BSObjectData $BSObjectData 292 | 293 | 294 | } 295 | 296 | Function Write-BSEmpireModuleData 297 | { 298 | Param ( 299 | [Parameter(Mandatory=$true)] $BSObjectData 300 | ) 301 | Clear-BSJON -BSFile $Cache:EmpireModuleFilePath 302 | Write-BSJSON -BSFile $Cache:EmpireModuleFilePath -BSObjectData $BSObjectData 303 | 304 | 305 | } 306 | 307 | 308 | 309 | Function Write-BSNetworkScanData 310 | { 311 | Param ( 312 | [Parameter(Mandatory=$true)] $BSObjectData 313 | ) 314 | Clear-BSJON -BSFile $Cache:NetworkScanFilePath 315 | Write-BSJSON -BSFile $Cache:NetworkScanFilePath -BSObjectData $BSObjectData 316 | 317 | } 318 | 319 | Function Write-BSAuditLog 320 | { 321 | Param ( 322 | [Parameter(Mandatory=$true)] $BSLogContent 323 | ) 324 | $BSLogContentFormatted = ($(Get-Date -Format 'yyyy-MM-dd hh:mm:ss') + ' : ' + $BSLogContent) 325 | $BSLogContentFormatted | Out-File $Cache:BSLogFilePath -Append 326 | } -------------------------------------------------------------------------------- /Modules/Empire/BlueCommandEmpire.psm1: -------------------------------------------------------------------------------- 1 | #### All functions need to have proper function params, synopsis, help, etc.... 2 | #### Also where my psd1 file at 3 | 4 | Import-Module CredentialManager -force 5 | 6 | #[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } 7 | add-type @" 8 | using System.Net; 9 | using System.Security.Cryptography.X509Certificates; 10 | public class TrustAllCertsPolicy : ICertificatePolicy { 11 | public bool CheckValidationResult( 12 | ServicePoint srvPoint, X509Certificate certificate, 13 | WebRequest request, int certificateProblem) { 14 | return true; 15 | } 16 | } 17 | "@ 18 | 19 | [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy 20 | 21 | 22 | function Get-EmpireModules 23 | { 24 | param( 25 | [Parameter(Mandatory=$true)] $EmpireBox, 26 | [Parameter(Mandatory=$true)] $EmpireToken, 27 | $EmpirePort = '1337' 28 | ) 29 | 30 | #Get Agents 31 | $Modules = Invoke-WebRequest -Method Get -uri "https://$EmpireBox`:$EmpirePort/api/modules?token=$EmpireToken" 32 | $Modules = $Modules.Content | ConvertFrom-Json 33 | 34 | $ModuleObjects = @() 35 | ForEach($Module in $Modules.modules) 36 | { 37 | 38 | $ModuleObject = [PSCustomObject]@{ 39 | Name = $Module.Name 40 | Author = $Module.Author 41 | Comments = $Module.Comments 42 | Description = $Module.Description 43 | Language = $Module.Language 44 | NeedsAdmin = $Module.NeedsAdmin 45 | OpsecSafe = $Module.OpsecSafe 46 | options = $Module.options 47 | } 48 | $ModuleObjects = $ModuleObjects + $ModuleObject 49 | 50 | } 51 | 52 | return $ModuleObjects 53 | 54 | } 55 | 56 | 57 | 58 | function Start-BSEmpireModuleOnAgent 59 | { 60 | Param( 61 | [Parameter(Mandatory=$true)] $EmpireBox, 62 | [Parameter(Mandatory=$true)] $EmpireToken, 63 | $EmpirePort = '1337', 64 | [Parameter(Mandatory=$true)] $AgentName, 65 | [Parameter(Mandatory=$true)] $ModuleName, 66 | $Options = $null 67 | ) 68 | 69 | $moduleURI = "https://$EmpireBox`:$EmpirePort/api/modules/"+$ModuleName+"?token=$EmpireToken" 70 | $PostBody = '{"Agent":"'+$AgentName+'"}' 71 | 72 | if($Options) 73 | { 74 | $PostBodyWithOptions = '{"Agent":"'+$AgentName+'",'+$Options+'}' 75 | $PostBody = $PostBodyWithOptions 76 | } 77 | 78 | Write-BSAuditLog -BSLogContent ("Module URI: " + $moduleURI) 79 | Write-BSAuditLog -BSLogContent ("Post Body: " + $PostBody) 80 | 81 | # TODO : MODULE OPTIONS IMPLEMENTATION 82 | <# 83 | # Guessing this is like... 84 | # { 85 | "Agent": "WTN1LHHRYHFWHXU3", 86 | "OPtion1": "Test", 87 | "Option2": "Test2" 88 | } 89 | #> 90 | 91 | #Get Agents 92 | $ModuleExecution = Invoke-WebRequest -Method Post -uri $moduleURI -Body $PostBody -ContentType 'application/json' 93 | 94 | $ModuleExecutionStatusCode = $ModuleExecution.StatusCode 95 | 96 | Write-BSAuditLog -BSLogContent ("Execution Code: " + $ModuleExecutionStatusCode) 97 | 98 | if($ModuleExecutionStatusCode -eq '200') 99 | { 100 | $ModuleExecution = $ModuleExecution.Content | ConvertFrom-Json 101 | $Return = (($ModuleExecution.msg) + " - Execution Status: " + ($ModuleExecution.success)) 102 | $ReturnTitleCase = (Get-Culture).textinfo.totitlecase($Return.tolower()) 103 | 104 | return $ReturnTitleCase 105 | } 106 | else 107 | { 108 | return ("Execution Status: FAILED") 109 | } 110 | 111 | } 112 | 113 | 114 | function Get-AgentDownloads 115 | { 116 | Param( 117 | [Parameter(Mandatory=$true)] $CredentialName, 118 | [Parameter(Mandatory=$true)] $EmpireServer, 119 | [Parameter(Mandatory=$true)] $EmpireDirectory, 120 | [Parameter(Mandatory=$true)] $EmpireAgentName, 121 | [Parameter(Mandatory=$true)] $DownloadFolder 122 | 123 | ) 124 | 125 | 126 | ### USER "CREDENTIAL MANAGER" TO CONNECT TO CRED MANAGER IN WINDERS 127 | $StoredCredential = Get-StoredCredential -Target $CredentialName 128 | 129 | $Credential = $StoredCredential 130 | 131 | $LocalDownloadFolder = ($DownloadFolder + $EmpireAgentName) 132 | $ExecutionResult = "" 133 | 134 | Try{ 135 | Get-SCPFolder -LocalFolder $LocalDownloadFolder -RemoteFolder ($EmpireDirectory +'/downloads/'+$EmpireAgentName) -ComputerName $EmpireServer -Credential $Credential -Force 136 | $ExecutionResult = "OK" 137 | } 138 | Catch 139 | { 140 | $ExecutionResult = "FAIL" 141 | } 142 | 143 | return $ExecutionResult 144 | } 145 | 146 | Function Get-LocalAgentLogDetails 147 | { 148 | 149 | Param( 150 | [Parameter(Mandatory=$true)] $DownloadFolder, 151 | [Parameter(Mandatory=$true)] $EmpireAgentName 152 | ) 153 | 154 | $LocalAgentDownloadFolder = $DownloadFolder + $EmpireAgentName 155 | 156 | $TimeStampRegex = '\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d :' #LOL - TODO wtf is this? 157 | 158 | 159 | IF(Test-Path $LocalAgentDownloadFolder) 160 | { 161 | $AgentLogContent = Get-Content -Path ($LocalAgentDownloadFolder + '\agent.log') 162 | $AgentResultObjects = @() 163 | $ObjectData = ""; 164 | ForEach($Line in $AgentLogContent) 165 | { 166 | if($Line -match $TimeStampRegex) 167 | { 168 | 169 | IF($ObjectData -ne "") 170 | { 171 | $CompleteObjectData = $ObjectData 172 | $ResultObject.Message = $CompleteObjectData; 173 | $AgentResultObjects = $AgentResultObjects + $ResultObject 174 | $ObjectData = "" 175 | } 176 | 177 | $ResultObject = [PSCustomObject]@{ 178 | TimeStamp = ($Line.ToString().Replace(' :','')) 179 | Message = "test" 180 | } 181 | 182 | } 183 | else 184 | { 185 | $ObjectData = $ObjectData + $Line; 186 | 187 | } 188 | 189 | } 190 | 191 | 192 | 193 | } 194 | 195 | 196 | 197 | Return $AgentResultObjects 198 | 199 | 200 | 201 | 202 | 203 | } 204 | 205 | Function Get-EmpireInformation 206 | { 207 | Param( 208 | [Parameter(Mandatory=$true)]$EmpireBox, 209 | [Parameter(Mandatory=$true)]$EmpireToken, 210 | $EmpirePort = '1337' 211 | ) 212 | 213 | 214 | #Get Version 215 | $Verison = Invoke-WebRequest -Method Get -uri "https://$EmpireBox`:$EmpirePort/api/version?token=$EmpireToken" 216 | $Verison = $Verison.Content | ConvertFrom-Json 217 | $Verison = $Verison.version 218 | 219 | #Get Listeners 220 | $Listeners = Invoke-WebRequest -Method Get -uri "https://$EmpireBox`:$EmpirePort/api/listeners?token=$EmpireToken" 221 | $Listeners = $Listeners.Content | ConvertFrom-Json 222 | 223 | #Get Agents 224 | $Agents = Invoke-WebRequest -Method Get -uri "https://$EmpireBox`:$EmpirePort/api/agents?token=$EmpireToken" 225 | $Agents = $Agents.Content | ConvertFrom-Json 226 | ForEach($Agent in $Agents.agents) 227 | { 228 | #Write-Host $Agent. 229 | } 230 | 231 | 232 | #Start-Command 233 | 234 | #& "curl --insecure -i https://$EmpireBox`:$EmpirePort/api/version?token=$EmpireToken" 235 | 236 | 237 | } 238 | 239 | Function Get-EmpireAgentResults 240 | { 241 | 242 | Param( 243 | [Parameter(Mandatory=$true)]$EmpireBox, 244 | [Parameter(Mandatory=$true)]$EmpireToken, 245 | $EmpirePort = '1337', 246 | [Parameter(Mandatory=$true)]$AgentName 247 | ) 248 | 249 | $uri = 'https://'+$EmpireBox+':'+$EmpirePort+'/api/agents/'+$AgentName+'/results?token='+$EmpireToken 250 | 251 | $AgentResults = Invoke-WebRequest -Method Get -uri $uri 252 | $AgentResults = $AgentResults.Content | ConvertFrom-Json 253 | $AgentResultObjects = @() 254 | ForEach($Result in $AgentResults.results.AgentResults) 255 | { 256 | 257 | $ResultObject = [PSCustomObject]@{ 258 | agentname = $AgentName 259 | command = $Result.command 260 | results = $Result.results 261 | } 262 | $AgentResultObjects = $AgentResultObjects + $ResultObject 263 | 264 | } 265 | 266 | return $AgentResultObjects 267 | } 268 | 269 | Function Get-EmpireAgents 270 | { 271 | Param( 272 | [Parameter(Mandatory=$true)]$EmpireBox, 273 | [Parameter(Mandatory=$true)]$EmpireToken, 274 | $EmpirePort = '1337' 275 | ) 276 | 277 | 278 | #Get Agents 279 | $Agents = Invoke-WebRequest -Method Get -uri "https://$EmpireBox`:$EmpirePort/api/agents?token=$EmpireToken" 280 | $Agents = $Agents.Content | ConvertFrom-Json 281 | 282 | $AgentObjects = @() 283 | ForEach($Agent in $Agents.agents) 284 | { 285 | 286 | $AgentObject = [PSCustomObject]@{ 287 | id = $Agent.ID 288 | checkin_time = $Agent.checkin_time 289 | external_ip = $Agent.external_ip 290 | hostname = $Agent.hostname 291 | internal_ip = $Agent.internal_ip 292 | langauge = $Agent.language 293 | langauge_version = $Agent.language_version 294 | lastseen_time = $Agent.lastseen_time 295 | listener = $Agent.listener 296 | name = $Agent.name 297 | os_details = $Agent.os_details 298 | username = $Agent.username 299 | } 300 | $AgentObjects = $AgentObjects + $AgentObject 301 | 302 | } 303 | 304 | return $AgentObjects 305 | } 306 | 307 | 308 | 309 | Function Get-EmpireModules{ 310 | 311 | Param( 312 | [Parameter(Mandatory=$true)] $EmpireBox, 313 | [Parameter(Mandatory=$true)] $EmpireToken, 314 | $EmpirePort = '1337' 315 | ) 316 | 317 | #Get Agents 318 | $Modules = Invoke-WebRequest -Method Get -uri "https://$EmpireBox`:$EmpirePort/api/modules?token=$EmpireToken" 319 | $Modules = $Modules.Content | ConvertFrom-Json 320 | 321 | $ModuleObjects = @() 322 | ForEach($Module in $Modules.modules) 323 | { 324 | 325 | $ModuleObject = [PSCustomObject]@{ 326 | Name = $Module.Name 327 | Author = $Module.Author 328 | Comments = $Module.Comments 329 | Description = $Module.Description 330 | Language = $Module.Language 331 | NeedsAdmin = $Module.NeedsAdmin 332 | OpsecSafe = $Module.OpsecSafe 333 | options = $Module.options 334 | } 335 | $ModuleObjects = $ModuleObjects + $ModuleObject 336 | 337 | } 338 | 339 | return $ModuleObjects 340 | 341 | 342 | } 343 | 344 | 345 | Function Get-EmpireStatus 346 | { 347 | Param( 348 | [Parameter(Mandatory=$true)] $EmpireBox, 349 | [Parameter(Mandatory=$true)] $EmpireToken, 350 | $EmpirePort = '1337' 351 | ) 352 | 353 | #Get Configuration 354 | try{ 355 | $ConfigurationInformation = Invoke-WebRequest -Method Get -uri "https://$EmpireBox`:$EmpirePort/api/config?token=$EmpireToken" 356 | $ConfigurationInformation = $ConfigurationInformation.Content | ConvertFrom-Json 357 | $ConfigurationInformation = $ConfigurationInformation.config 358 | 359 | 360 | $ConfigurationInformationObject = [PSCustomObject]@{ 361 | empire_host = $EmpireBox 362 | empire_port = $EmpirePort 363 | empire_token = $EmpireToken 364 | api_username = $ConfigurationInformation.api_username 365 | install_path = $ConfigurationInformation.install_path 366 | version = $ConfigurationInformation.version 367 | sync_time = ($(Get-Date -Format 'yyyy-MM-dd hh:mm:ss')) 368 | } 369 | 370 | } 371 | catch 372 | { 373 | $ConfigurationInformationObject = $null 374 | } 375 | 376 | return $ConfigurationInformationObject 377 | } 378 | 379 | Function Get-EmpireReports 380 | { 381 | #https://github.com/EmpireProject/Empire/wiki/RESTful-API 382 | 383 | Param( 384 | [Parameter(Mandatory=$true)] $EmpireBox, 385 | [Parameter(Mandatory=$true)] $EmpireToken, 386 | $EmpirePort = '1337', 387 | [Parameter(Mandatory=$true)] $AgentName, 388 | $Options = "", 389 | $ReportType = "result" #task, result, checkin 390 | ) 391 | 392 | ### AGENT - NOT WORKING 393 | $uri = 'https://'+$EmpireBox+':'+$EmpirePort+'/api/reporting/agent/'+$AgentName+'?token='+$EmpireToken 394 | 395 | ### ALL - WORKING 396 | #$uri = "https://$EmpireBox`:$EmpirePort/api/reporting?token="+$EmpireToken 397 | 398 | ### TYPE 399 | $uri = 'https://'+$EmpireBox+':'+$EmpirePort+'/api/reporting/type/'+$ReportType+'?token='+$EmpireToken 400 | 401 | 402 | $uri 403 | $Reports = Invoke-WebRequest -Method Get -uri $uri 404 | $Reports = $Reports.Content | ConvertFrom-Json 405 | $ReportObjects = @() 406 | ForEach($Report in $Reports.reporting) 407 | { 408 | 409 | $ReportObject = [PSCustomObject]@{ 410 | id = $Report.ID 411 | agentname = $Report.agentname 412 | event_type = $Report.event_type 413 | message = $Report.message 414 | timestamp = $Report.timestamp 415 | 416 | } 417 | $ReportObjects = $ReportObjects + $ReportObject 418 | 419 | } 420 | 421 | return $ReportObjects 422 | } -------------------------------------------------------------------------------- /Pages/AgentLogs.ps1: -------------------------------------------------------------------------------- 1 | New-UDPage -Name "EmpireAgentLogs" -Icon file -Endpoint { 2 | 3 | $EmpireAgents = Get-BSEmpireAgentData 4 | $EmpireModules = Get-BSEmpireModuleData 5 | $EmpireConfiguration = Get-BSEmpireConfigData 6 | 7 | $EmpireBox = $EmpireConfiguration.empire_host 8 | $EmpirePort = $EmpireConfiguration.empire_port 9 | $EmpireToken = $EmpireConfiguration.empire_token 10 | 11 | 12 | New-UDInput -Title "Retrieve Logs" -Id "AgentResultsRetrieval" -Content { 13 | 14 | New-UDInputField -Type 'select' -Name 'EmpireAgentName' -Values $EmpireAgents.name -DefaultValue (($EmpireAgents | Select-Object -First 1).Name) -Placeholder "Select an Agent" 15 | New-UDInputField -Type 'textbox' -Name 'WindowsCredentialName' -DefaultValue ($Cache:WindowsCredentialName) -Placeholder 'Name of Generic Windows Credential to Connect to Empire Server' 16 | 17 | } -Endpoint { 18 | param($EmpireAgentName, $WindowsCredentialName) 19 | 20 | $DownloadFolder = $Cache:BSDownloadsPath 21 | 22 | if($DownloadFolder -notlike '*\') 23 | { 24 | $DownloadFolder = $DownloadFolder + '\' 25 | } 26 | 27 | $LocalAgentDownloadFolder = $DownloadFolder + $EmpireAgentName 28 | 29 | New-UDInputAction -Toast "Getting Results for Agent: $EmpireAgentName" 30 | Write-BSAuditLog -BSLogContent "Empire Results: Getting Results for Agent: $EmpireAgentName" 31 | 32 | # EXECUTE DOWNLOAD LOGS FOR AGENT 33 | Write-BSAuditLog -BSLogContent "Empire Results: Attempting to Download Data from Agent: $EmpireAgentName to $DownloadFolder" 34 | $AgentLogDownloadStatus = Get-AgentDownloads -EmpireServer $Cache:EmpireServer -EmpireDirectory $Cache:EmpireDirectory -EmpireAgentName $EmpireAgentName -DownloadFolder $DownloadFolder -CredentialName $WindowsCredentialName 35 | 36 | Write-BSAuditLog -BSLogContent "Empire Results: Attempting to Read Downloaded Data from Agent: $EmpireAgentName" 37 | $AgentLogDetails = Get-LocalAgentLogDetails -EmpireAgentName $EmpireAgentName -DownloadFolder $DownloadFolder 38 | 39 | 40 | 41 | Show-UDModal -Content { 42 | New-UDHeading -Size 4 -Text "Agent Results Download" 43 | New-UDHeading -Size 6 -Text "Agent: $EmpireAgentName Results downloaded to: $LocalAgentDownloadFolder" 44 | New-UDGrid -Title "Agent Logs" -Headers @("TimeStamp", "Message") -Properties @("TimeStamp","Message") -Endpoint { 45 | 46 | #TODO - THIS IS BUG! TABLE WORKS FINE 47 | $AgentLogDetails | Out-UDGridData 48 | } 49 | 50 | 51 | } 52 | 53 | 54 | 55 | Write-BSAuditLog -BSLogContent "Empire Results: Retrieval and Display Completed" 56 | 57 | } 58 | 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Pages/Configuration.ps1: -------------------------------------------------------------------------------- 1 | New-UDPage -Name "EmpireConfiguration" -Icon empire -Endpoint { 2 | 3 | 4 | $NetworkResources = Get-BSNetworkScanData 5 | $ValidEmpireNetworkResources = @() 6 | 7 | ForEach($Resource in $NetworkResources) 8 | { 9 | if($Resource.isEmpire -eq 'YES') 10 | { 11 | $ValidEmpireNetworkResources = $ValidEmpireNetworkResources + $Resource 12 | 13 | } 14 | else 15 | { 16 | #NOT EMPIRE SERVER 17 | } 18 | } 19 | $EmpireConfig = Get-BSEmpireConfigData 20 | 21 | 22 | 23 | New-UDInput -Title "Connect to New Empire Server" -Id "EmpireConfiguration" -SubmitText "Connect" -Content { 24 | New-UDInputField -Type 'textarea' -Name 'EmpireIP' -DefaultValue $Cache:EmpireServer 25 | New-UDInputField -Type 'textarea' -Name 'EmpirePort' -DefaultValue '1337' 26 | New-UDInputField -Type 'textarea' -Name 'EmpireToken' -DefaultValue $EmpireConfig.empire_token 27 | } -Endpoint { 28 | param($EmpireIP, $EmpirePort, $EmpireToken) 29 | New-UDInputAction -Toast "Retrieving Empire Configurations!" 30 | 31 | $EmpireComputer = $EmpireIP 32 | 33 | Write-BSAuditLog -BSLogContent "Empire Configuration: Attempting to Retrieve Configuration from: $EmpireComputer" 34 | 35 | 36 | $EmpireConfiguration = Get-EmpireStatus -EmpireBox $EmpireComputer -EmpireToken $EmpireToken -EmpirePort $EmpirePort 37 | Write-BSEmpireConfigData -BSObject $EmpireConfiguration 38 | 39 | $EmpireAgents = Get-EmpireAgents -EmpireBox $EmpireComputer -EmpireToken $EmpireToken -EmpirePort $EmpirePort 40 | Write-BSEmpireAgentData -BSObject $EmpireAgents 41 | 42 | $EmpireModules = Get-EmpireModules -EmpireBox $EmpireComputer -EmpireToken $EmpireToken -EmpirePort $EmpirePort 43 | Write-BSEmpireModuleData -BSObject $EmpireModules 44 | 45 | #Update Other Elements 46 | Sync-UDElement -Id "ExistingEmpireInstance" -Broadcast 47 | Sync-UDElement -Id "EmpireAgents" -Broadcast 48 | Sync-UDElement -Id "EmpireModules" -Broadcast 49 | 50 | Write-BSAuditLog -BSLogContent "Empire Configuration: Configuration Retrieval Complete" 51 | 52 | } 53 | 54 | 55 | 56 | 57 | New-UDGrid -Title "Existing Empire Instance" -Id "ExistingEmpireInstance" -Headers @("empire_host","version", "api_username", "install_path", "sync_time") -Properties @("empire_host","version", "api_username", "install_path", "sync_time") -Endpoint { 58 | $JsonData = Get-BSEmpireConfigData 59 | If ($JsonData.version) 60 | { 61 | $Text = 'Empire - Version: ' + ($JsonData.version) +' - User: ' + ($JsonData.api_username) + ' - Installed: ' + ($JsonData.install_path) 62 | } 63 | else 64 | { 65 | $Text = "No Empire Found - Run Config!" 66 | } 67 | $JsonData | Out-UDGridData 68 | } 69 | 70 | 71 | New-UDGrid -Title "Empire Agents" -Id "EmpireAgents" -Headers @("id", "name", "checkin_time","external_ip","hostname","langauge", "langauge_version", "lastseen_time","listener","os_details","username") -Properties @("id", "name", "checkin_time","external_ip","hostname","langauge", "langauge_version", "lastseen_time","listener","os_details","username") -AutoRefresh -Endpoint { 72 | $JsonData = Get-BSEmpireAgentData 73 | $JsonData | Out-UDGridData 74 | } 75 | 76 | New-UDGrid -Title "Empire Modules" -Id "EmpireModules" -Headers @("Name", "Description", "Author","Language","NeedsAdmin","OpsecSafe") -Properties @("Name", "Description", "Author","Language","NeedsAdmin","OpsecSafe") -AutoRefresh -Endpoint { 77 | $JsonData = Get-BSEmpireModuleData 78 | $JsonData | Out-UDGridData 79 | } 80 | 81 | 82 | } -------------------------------------------------------------------------------- /Pages/Downloads.ps1: -------------------------------------------------------------------------------- 1 | New-UDPage -Name "EmpireDownloads" -Icon download -Endpoint { 2 | 3 | $EmpireAgents = Get-BSEmpireAgentData 4 | $EmpireModules = Get-BSEmpireModuleData 5 | $EmpireConfiguration = Get-BSEmpireConfigData 6 | 7 | $EmpireBox = $EmpireConfiguration.empire_host 8 | $EmpirePort = $EmpireConfiguration.empire_port 9 | $EmpireToken = $EmpireConfiguration.empire_token 10 | 11 | 12 | 13 | New-UDInput -Title "Retrieve Files" -Id "AgentResultsRetrieval" -Content { 14 | 15 | New-UDInputField -Type 'select' -Name 'EmpireAgentName' -Values $EmpireAgents.name -DefaultValue (($EmpireAgents | Select-Object -First 1).Name) -Placeholder "Select an Agent" 16 | New-UDInputField -Type 'textbox' -Name 'WindowsCredentialName' -DefaultValue 'empireserver' -Placeholder 'Name of Generic Windows Credential to Connect to Empire Server' 17 | 18 | } -Endpoint { 19 | param($EmpireAgentName, $WindowsCredentialName) 20 | 21 | $DownloadFolder = $Cache:BSDownloadsPath 22 | 23 | if($DownloadFolder -notlike '*\') 24 | { 25 | $DownloadFolder = $DownloadFolder + '\' 26 | } 27 | 28 | New-UDInputAction -Toast "Getting Results for Agent: $EmpireAgentName" 29 | Write-BSAuditLog -BSLogContent "Empire Results: Getting Results for Agent: $EmpireAgentName" 30 | 31 | # EXECUTE DOWNLOAD LOGS FOR AGENT 32 | Write-BSAuditLog -BSLogContent "Empire Results: Attempting to Download Data from Agent: $EmpireAgentName to $DownloadFolder" 33 | $AgentLogDownloadStatus = Get-AgentDownloads -EmpireServer $Cache:EmpireServer -EmpireDirectory $Cache:EmpireDirectory -EmpireAgentName $EmpireAgentName -DownloadFolder $DownloadFolder -CredentialName $WindowsCredentialName 34 | 35 | Sync-UDElement -Id 'DownloadedFilesGrid' -Broadcast 36 | 37 | Write-BSAuditLog -BSLogContent "Empire Results: Retrieval Completed" 38 | 39 | } 40 | 41 | 42 | New-UDGrid -Title "Downloaded Files" -Id "DownloadedFilesGrid" -Headers @("Name", "CreationTime", "Agent", "Download") -Properties @("Name", "CreationTime", "Agent","Download") -Endpoint { 43 | Get-BSDownloads | ForEach-Object { 44 | 45 | [PSCustomObject]@{ 46 | Name = $_.Name 47 | CreationTime = $_.CreationTime 48 | Agent = $_.Agent 49 | Download = New-UDButton -Text "Download" -OnClick (New-UDEndpoint -Endpoint{ 50 | 51 | $FileName = $ArgumentList[0] 52 | $AgentFolder = $ArgumentList[1] 53 | $FullPath = $ArgumentList[2] 54 | 55 | $FullPathWeb = $FullPath.Replace(($Cache:BlueCommandDataFolder+'\'),"") 56 | $FullPathWeb = $FullPathWeb.Replace('\',"/") 57 | 58 | $WebFileURL = 'http://localhost:'+ $Cache:BlueCommandPort + '/' + $FullPathWeb 59 | #Invoke-WebRequest $WebFileURL 60 | Invoke-UDRedirect -Url $WebFileURL -OpenInNewWindow 61 | 62 | 63 | } -ArgumentList $_.Name, $_.Agent, $_.FullPath) 64 | } 65 | } | Out-UDGridData 66 | } 67 | 68 | 69 | New-UDElement -Tag "ul" -Id "ExecutionResults2" -Content { 70 | 71 | } 72 | 73 | New-UDElement -Tag "ul" -Id "ButtonOpenLoot" -Content { 74 | 75 | } 76 | 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /Pages/Execution.ps1: -------------------------------------------------------------------------------- 1 | New-UDPage -Name "EmpireExecution" -Icon plane -Endpoint { 2 | 3 | 4 | $Session:CurrentlySelectedAgent = "NULL" 5 | $Session:EmpireModules = Get-BSEmpireModuleData 6 | 7 | ## If Only ONE Agent Availible Just Select the First Agent 8 | $Session:EmpireAgents = Get-BSEmpireAgentData 9 | if($Session:EmpireAgents) 10 | { 11 | $Session:CurrentlySelectedAgent = ($Session:EmpireAgents | Select-Object -First 1).name 12 | } 13 | 14 | 15 | #### Module "Package" Selection Box - With Boxes! 16 | New-UDGrid -Title "Package Selection" -Headers @("Name", "Description", " ") -Properties @("Name", "Description", "Execute") -Endpoint { 17 | $Session:EmpireModules | ForEach-Object { 18 | 19 | [PSCustomObject]@{ 20 | Name = $_.Name 21 | Description = $_.Description 22 | Execute = New-UDButton -Text "Execute" -OnClick (New-UDEndpoint -Endpoint { 23 | 24 | $EmpireAgentName = $ArgumentList[0] 25 | $ModuleName = $ArgumentList[1] 26 | $ModuleDescription = $ArgumentList[2] 27 | $ModuleOptions = $ArgumentList[3] 28 | 29 | Write-BSAuditLog -BSLogContent "Empire Operations: Planning Execution for $ModuleName on Agent $EmpireAgentName" 30 | 31 | if ($EmpireAgentName -ne $null) 32 | { 33 | 34 | Show-UDModal -Content { 35 | New-UDTable -Title "Strike Package Details" -Headers @("Name", "Description") -Endpoint { 36 | @{ 37 | 'Name' = $ModuleName 38 | 'Description' = $ModuleDescription 39 | } | Out-UDTableData -Property @("Name", "Description") 40 | 41 | } 42 | 43 | New-UDTable -Title "Module Options" -Headers @("Option Name", "Definition") -Endpoint { 44 | $ModuleOptions | Out-UDTableData -Property @("Name", "Definition") 45 | } 46 | 47 | New-UDInput -Title "Execute Strike Package" -Id "AgentModuleOperations" -SubmitText "Execute" -Content { 48 | New-UDInputField -Type 'select' -Name 'EmpireAgentName' -Values $Session:EmpireAgents.name -DefaultValue $Session:CurrentlySelectedAgent -Placeholder "Select an Agent" 49 | New-UDInputField -Type 'textbox' -Name 'OptionsJSON' -DefaultValue $null 50 | } -Endpoint { 51 | 52 | ## GET EMPIRE CONFIGO 53 | 54 | $EmpireConfiguration = Get-BSEmpireConfigData 55 | 56 | $EmpireBox = $EmpireConfiguration.empire_host 57 | $EmpirePort = $EmpireConfiguration.empire_port 58 | $EmpireToken = $EmpireConfiguration.empire_token 59 | 60 | ## TODO OPtions Parsing? 61 | If($OptionsJSON) 62 | { 63 | $ExecutuionLog = 'Empire Operations: Executing Action: ' + $ModuleName +' on: ' + $EmpireAgentName + " which lives on $EmpireBox" 64 | Write-BSAuditLog -BSLogContent $ExecutuionLog 65 | $EmpireModuleExecution = Start-BSEmpireModuleOnAgent -EmpireBox $EmpireBox -EmpireToken $EmpireToken -EmpirePort $EmpirePort -AgentName $EmpireAgentName -ModuleName $ModuleName 66 | } 67 | else 68 | { 69 | $ExecutuionLog = 'Empire Operations: Executing Action: ' + $ModuleName +' WITH OPTIONS: ' + $OptionsJSON + ' on: ' + $EmpireAgentName + " which lives on $EmpireBox" 70 | Write-BSAuditLog -BSLogContent $ExecutuionLog 71 | $EmpireModuleExecution = Start-BSEmpireModuleOnAgent -EmpireBox $EmpireBox -EmpireToken $EmpireToken -EmpirePort $EmpirePort -AgentName $EmpireAgentName -ModuleName $ModuleName -Options $OptionsJSON 72 | } 73 | 74 | 75 | Write-BSAuditLog -BSLogContent $EmpireModuleExecution 76 | 77 | 78 | Clear-UDElement -Id "StrikePackageExecution" 79 | Add-UDElement -ParentId "StrikePackageExecution" -Content { 80 | New-UDHtml -Markup ('STRIKE STATUS: EXECUTED
' + '' + $EmpireModuleExecution + '') 81 | } 82 | 83 | } 84 | 85 | New-UDElement -Id "StrikePackageExecution" -Tag "b" -Content { 86 | New-UDHtml -Markup ('STRIKE STATUS: DEPLOYMENT READY') 87 | } 88 | 89 | 90 | } 91 | 92 | } 93 | else{ 94 | 95 | Show-UDModal -Content { 96 | New-UDHeading -Size 4 -Text "Invalid Selection!" 97 | New-UDHeading -Size 6 -Text "You must Select a VALID Agent First!" 98 | } 99 | } 100 | 101 | } -ArgumentList $Session:CurrentlySelectedAgent, $_.Name, $_.Description, $_.Options) 102 | } 103 | 104 | } | Out-UDGridData 105 | 106 | 107 | } 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /Pages/home.ps1: -------------------------------------------------------------------------------- 1 | New-UDPage -Name "Home" -Icon home -Endpoint { 2 | 3 | ### CARD COUNTS 4 | $EmpireAgentsJsonData = Get-BSEmpireAgentData 5 | $EmpireModulesJsonData = Get-BSEmpireModuleData 6 | $NetworkResourcesJsonData = Get-BSNetworkScanData 7 | 8 | $NetworkResourcesCount = ($NetworkResourcesJsonData | Measure | Select-Object Count).Count 9 | $EmpireAgentsCount = ($EmpireAgentsJsonData | Measure | Select-Object Count).Count 10 | $EmpireModuleCount = $EmpireModulesJsonData.Count 11 | 12 | New-UDRow -Columns { 13 | 14 | 15 | New-UDColumn -Size 2 { 16 | 17 | New-UDCounter -Title "Empire Modules" -BackgroundColor '#4C9BF3' -FontColor '#FFFFFF' -Endpoint { 18 | $EmpireModuleCount | ConvertTo-Json 19 | } 20 | 21 | } 22 | 23 | New-UDColumn -Size 2 { 24 | 25 | New-UDCounter -Title "Active Agents" -BackgroundColor '#4CC6DB' -FontColor '#FFFFFF' -Endpoint { 26 | $EmpireAgentsCount | ConvertTo-Json 27 | } 28 | 29 | } 30 | 31 | New-UDColumn -Size 2 { 32 | 33 | New-UDCounter -Title "Agent Files" -BackgroundColor '#7561F1' -FontColor '#FFFFFF' -Endpoint { 34 | Get-BSDownloadsCount | ConvertTo-Json 35 | } 36 | 37 | } 38 | <# 39 | New-UDColumn -Size 2 { 40 | 41 | New-UDCounter -Title "Agent Files Downloaded" -BackgroundColor '#F2496A' -FontColor '#FFFFFF' -Endpoint { 42 | Get-BSDownloadsCount | ConvertTo-Json 43 | } 44 | 45 | } 46 | #> 47 | 48 | 49 | } 50 | 51 | New-UDTable -Title "Existing Empire Instance" -Id "ExistingEmpireInstance" -Headers @("Empire IP","Version", "Path", "Sync Time") -Endpoint { 52 | $JsonData = Get-BSEmpireConfigData 53 | $JsonData | Out-UDTableData -Property @("empire_host","version", "install_path", "sync_time") 54 | } 55 | 56 | 57 | $JsonData = Get-BSEmpireAgentData 58 | New-UDGrid -Title "Empire Agents" -Headers @("Name", "Created", "Last Seen","External IP","Hostname","Listener","OS","Username") -Properties @("name", "checkin_time","lastseen_time","external_ip","hostname","listener","os_details","username") -AutoRefresh -Endpoint { 59 | 60 | $JsonData | Out-UDGridData 61 | } 62 | 63 | 64 | 65 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BlueCommand 🌌 2 | ================== 3 | 4 | **BlueCommand** is a dashboard and tooling front-end for [PowerShell Empire](https://github.com/EmpireProject/Empire) using [PowerShell Universal Dashboard](https://universaldashboard.io/) from [Adam Driscoll](https://github.com/adamdriscoll) 5 | 6 | ![](./img/HomePage.png) 7 | 8 | 9 | **WARNING**: This project does not nearly scratch the surface of interacting with all the capababilites of PowerShell Empire. This was a project to help my learn / play around with PowerShell Empire and its' REST API. You will be much better served in life but actually learning how to use PowerShell Empire :) 10 | 11 | # Features 12 | * Web Dashboard / Controller for PowerShell Empire! 13 | * Utilizes the Empire REST API and [PowerShell Universal Dashboard](https://universaldashboard.io/) 14 | * [PowerShell Empire](https://www.powershellempire.com/) Integration 15 | * Rest Integration to retrieve Empire Instance Information (Agents, Modules Downloads) 16 | * Rest Integration to Execute Modules on Agents. 17 | * SCP to Download Agent Results / Downloads 18 | 19 | **Searching and Executing Modules on Empire Agents** 20 | ![](./img/ExecuteModule.gif) 21 | 22 | **Retrieving Agent Downloads** 23 | ![](./img/AgentDownload.gif) 24 | 25 | # Getting Started 26 | 27 | ## Prereqs 28 | 1. Install [Universal Dashboard](https://universaldashboard.io/) ``Install-Module UniversalDashboard -AccecptLicense`` 29 | 2. Install [PoshSSH](https://github.com/darkoperator/Posh-SSH) ``Install-Module -Name Posh-SSH`` 30 | * PoshSSH is used to run SCP commands to extract agent artifacts. 31 | 3. Install [PowerShell Credential Manager](https://github.com/davotronic5000/PowerShell_Credential_Manager) ``Install-Module -Name CredentialManager`` 32 | * Credential Manager allows use to easily use Windows Credential Manager to auth to our Empire Server 33 | 4. Setup [PowerShell Empire](https://www.powershellempire.com/) 34 | + Run Empire with --rest command 35 | + Generate a Listener / Stager 36 | + Deploy Agents 37 | + Make a Note of Rest Key and Empire Server IP. 38 | 39 | ## Usage 40 | 1. Populate your environment variables in the ``start.ps1`` Script 41 | 2. Run the Start Script 42 | 3. Connect to your Empire Server on the Empire Configuration Page using your Empire Server IP, and Rest API Key. 43 | * ![](./img/empire_rest.png) 44 | 4. BlueCommand will try and utilze POSH-SSH to SCP Download the Empire Agents Downloads/Logs - This requires a stored a "Generic Credential" in your windows credential manager to facilitate this. ![](./img/credential_manager.png) 45 | -------------------------------------------------------------------------------- /bluecommand.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | 3 | # Script module or binary module file associated with this manifest. 4 | RootModule = '.\BlueCommand.psm1' 5 | 6 | # Version number of this module. 7 | ModuleVersion = '1.0' 8 | 9 | # Supported PSEditions 10 | # CompatiblePSEditions = @() 11 | 12 | # ID used to uniquely identify this module 13 | GUID = '7d9d3976-88eb-4c1c-af84-b8bf54cf3153' 14 | 15 | # Author of this module 16 | Author = 'Lee Berg' 17 | 18 | # Company or vendor of this module 19 | CompanyName = 'Berg Studios' 20 | 21 | # Copyright statement for this module 22 | Copyright = '(c) 2019 Lee Berg. All rights reserved.' 23 | 24 | # Description of the functionality provided by this module 25 | Description = 'A sec tool built on Universal Dashboard.' 26 | 27 | # Minimum version of the Windows PowerShell engine required by this module 28 | # PowerShellVersion = '' 29 | 30 | # Name of the Windows PowerShell host required by this module 31 | # PowerShellHostName = '' 32 | 33 | # Minimum version of the Windows PowerShell host required by this module 34 | # PowerShellHostVersion = '' 35 | 36 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 37 | # DotNetFrameworkVersion = '' 38 | 39 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 40 | # CLRVersion = '' 41 | 42 | # Processor architecture (None, X86, Amd64) required by this module 43 | # ProcessorArchitecture = '' 44 | 45 | # Modules that must be imported into the global environment prior to importing this module 46 | #RequiredModules = @() 47 | 48 | # Assemblies that must be loaded prior to importing this module 49 | # RequiredAssemblies = @() 50 | 51 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 52 | # ScriptsToProcess = @() 53 | 54 | # Type files (.ps1xml) to be loaded when importing this module 55 | # TypesToProcess = @() 56 | 57 | # Format files (.ps1xml) to be loaded when importing this module 58 | # FormatsToProcess = @() 59 | 60 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 61 | # NestedModules = @() 62 | 63 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 64 | FunctionsToExport = '*' 65 | 66 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 67 | CmdletsToExport = '*' 68 | 69 | # Variables to export from this module 70 | VariablesToExport = '*' 71 | 72 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 73 | AliasesToExport = '*' 74 | 75 | # DSC resources to export from this module 76 | # DscResourcesToExport = @() 77 | 78 | # List of all modules packaged with this module 79 | # ModuleList = @() 80 | 81 | # List of all files packaged with this module 82 | # FileList = @() 83 | 84 | 85 | # HelpInfo URI of this module 86 | # HelpInfoURI = '' 87 | 88 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 89 | # DefaultCommandPrefix = '' 90 | 91 | } 92 | -------------------------------------------------------------------------------- /bluecommand.psm1: -------------------------------------------------------------------------------- 1 | function Start-BSDash { 2 | param( 3 | [Parameter(Mandatory=$true)] $EmpireServer, 4 | [Parameter(Mandatory=$true)] $EmpireDirectory, 5 | [Parameter(Mandatory=$true)] $EmpirePort, 6 | [Parameter(Mandatory=$true)] $BlueCommandFolder, 7 | [Parameter(Mandatory=$true)] $BlueCommandPort, 8 | [Parameter(Mandatory=$false)] $WindowsCredentialName 9 | ) 10 | 11 | # This Caches the Connection Info so the other components and modules can utilze them 12 | $Cache:ConnectionInfo = @{ 13 | Server = $EmpireServer 14 | Credential = $Credential 15 | } 16 | 17 | #Dashboard Port 18 | $Cache:BlueCommandPort = $BlueCommandPort 19 | 20 | # Empire Server 21 | $Cache:EmpireServer = $EmpireServer 22 | $Cache:EmpireDirectory = $EmpireDirectory 23 | $Cache:EmpirePort = $EmpirePort 24 | 25 | $Cache:WindowsCredentialName = $WindowsCredentialName 26 | 27 | $Pages = @() 28 | $Pages += . (Join-Path $PSScriptRoot "pages\home.ps1") 29 | 30 | Get-ChildItem (Join-Path $PSScriptRoot "pages") -Exclude "home.ps1" | ForEach-Object { 31 | $Pages += . $_.FullName 32 | } 33 | 34 | 35 | #### DATA FOLDER SETUP 36 | 37 | #Folder Pathes 38 | $Cache:BlueCommandFolder = $BlueCommandFolder 39 | $Cache:BlueCommandDataFolder = $Cache:BlueCommandFolder + '\Data' 40 | 41 | #File Paths 42 | $Cache:EmpireConfigFilePath = $Cache:BlueCommandFolder + '\Data\EmpireConfig.json' 43 | $Cache:EmpireModuleFilePath = $Cache:BlueCommandFolder + '\Data\EmpireModules.json' 44 | $Cache:EmpireAgentFilePath = $Cache:BlueCommandFolder + '\Data\EmpireAgents.json' 45 | $Cache:NetworkScanFilePath = $Cache:BlueCommandFolder + '\Data\NetworkScan.json' 46 | $Cache:BSLogFilePath = $Cache:BlueCommandFolder + '\Data\AuditLog.log' 47 | $Cache:BSDownloadsPath = $Cache:BlueCommandFolder + '\Data\Downloads' 48 | 49 | 50 | 51 | if((Test-Path -Path $Cache:BlueCommandFolder) -eq $false){throw 'The BlueCommand Data Folder does not exist!'} 52 | if((Test-Path -Path $Cache:BlueCommandDataFolder) -eq $false){New-Item -Path $Cache:BlueCommandDataFolder -ItemType Directory} 53 | if((Test-Path -Path $Cache:BSDownloadsPath) -eq $false){New-Item -Path $Cache:BSDownloadsPath -ItemType Directory} 54 | if((Test-Path -Path $Cache:BSLogFilePath) -eq $false){New-Item -Path $Cache:BSLogFilePath -ItemType File} 55 | 56 | #Downloads Folder 57 | $DownloadsFolder = Publish-UDFolder -Path ($Cache:BSDownloadsPath+'\') -RequestPath '/Downloads' 58 | 59 | 60 | #### THEME 61 | 62 | $DarkDefault = New-UDTheme -Name "Basic" -Definition @{ 63 | UDDashboard = @{ 64 | BackgroundColor = "#393F47" 65 | FontColor = "#FFFFFF" 66 | } 67 | UDNavBar = @{ 68 | BackgroundColor = "#272C33" 69 | FontColor = "#FFFFFF" 70 | } 71 | UDFooter = @{ 72 | BackgroundColor = "#272C33" 73 | FontColor = "#FFFFFF" 74 | } 75 | UDCard = @{ 76 | BackgroundColor = "#272C33" 77 | FontColor = "#FFFFFF" 78 | } 79 | UDChart = @{ 80 | BackgroundColor = "#272C33" 81 | FontColor = "#FFFFFF" 82 | } 83 | UDMonitor = @{ 84 | BackgroundColor = "#272C33" 85 | FontColor = "#FFFFFF" 86 | } 87 | UDTable = @{ 88 | BackgroundColor = "#272C33" 89 | FontColor = "#FFFFFF" 90 | } 91 | UDGrid = @{ 92 | BackgroundColor = "#272C33" 93 | FontColor = "#FFFFFF" 94 | } 95 | UDCounter = @{ 96 | BackgroundColor = "#272C33" 97 | FontColor = "#FFFFFF" 98 | } 99 | UDInput = @{ 100 | BackgroundColor = "#272C33" 101 | FontColor = "#FFFFFF" 102 | } 103 | } 104 | 105 | $BSEndpoints = New-UDEndpointInitialization -Module @("Modules\Empire\BlueCommandData.psm1", "Modules\Empire\BlueCommandEmpire.psm1") 106 | $Dashboard = New-UDDashboard -Title "BlueCommand 🌌" -Pages $Pages -EndpointInitialization $BSEndpoints -Theme $DarkDefault 107 | 108 | Try{ 109 | Start-UDDashboard -Dashboard $Dashboard -Port $Cache:BlueCommandPort -PublishedFolder $DownloadsFolder 110 | } 111 | Catch 112 | { 113 | Write-Error($_.Exception) 114 | } 115 | 116 | 117 | 118 | 119 | } 120 | -------------------------------------------------------------------------------- /img/AgentDownload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeberg/BlueCommand/086e14687f96b30eaa0e337b59d7c49a5492c482/img/AgentDownload.gif -------------------------------------------------------------------------------- /img/Credential_Manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeberg/BlueCommand/086e14687f96b30eaa0e337b59d7c49a5492c482/img/Credential_Manager.png -------------------------------------------------------------------------------- /img/ExecuteModule.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeberg/BlueCommand/086e14687f96b30eaa0e337b59d7c49a5492c482/img/ExecuteModule.gif -------------------------------------------------------------------------------- /img/HomePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeberg/BlueCommand/086e14687f96b30eaa0e337b59d7c49a5492c482/img/HomePage.png -------------------------------------------------------------------------------- /img/empire_rest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeberg/BlueCommand/086e14687f96b30eaa0e337b59d7c49a5492c482/img/empire_rest.png -------------------------------------------------------------------------------- /start.ps1: -------------------------------------------------------------------------------- 1 | # BlueCommand Start Script 2 | 3 | # Set These Variables - and populate the Credential Object 4 | $BlueCommandFolder = 'C:\Users\lee\git\BlueCommand' 5 | $EmpireServerIP = '192.168.200.106' 6 | $WindowsCredentialName = 'empireserver' 7 | $EmpireDirectory = '/home/lee/Empire' 8 | $EmpirePort = '1337' 9 | 10 | 11 | Import-Module .\BlueCommand.psd1 -Force 12 | 13 | Get-UDDashboard | Stop-UDDashboard 14 | Get-UDRestApi | Stop-UDRestAPI 15 | Start-BSDash -EmpireServer $EmpireServerIP -EmpireDirectory $EmpireDirectory -EmpirePort $EmpirePort -BlueCommandFolder $BlueCommandFolder -BlueCommandPort 10001 -WindowsCredentialName $WindowsCredentialName --------------------------------------------------------------------------------