import rex powershell
parent
b453362a52
commit
29bf296b61
|
@ -30,11 +30,36 @@ module Powershell
|
|||
end
|
||||
|
||||
#
|
||||
# Return a Base64 encoded powershell code
|
||||
# Return a zlib compressed powershell code
|
||||
#
|
||||
def encode_code(eof = nil)
|
||||
def deflate_code(eof = nil)
|
||||
# Compress using the Deflate algorithm
|
||||
compressed_stream = ::Zlib::Deflate.deflate(code,
|
||||
::Zlib::BEST_COMPRESSION)
|
||||
|
||||
# Base64 encode the compressed file contents
|
||||
encoded_stream = Rex::Text.encode_base64(compressed_stream)
|
||||
|
||||
# Build the powershell expression
|
||||
# Decode base64 encoded command and create a stream object
|
||||
psh_expression = "$stream = New-Object IO.MemoryStream(,"
|
||||
psh_expression << "$([Convert]::FromBase64String('#{encoded_stream}')));"
|
||||
# Read & delete the first two bytes due to incompatibility with MS
|
||||
psh_expression << "$stream.ReadByte()|Out-Null;"
|
||||
psh_expression << "$stream.ReadByte()|Out-Null;"
|
||||
# Uncompress and invoke the expression (execute)
|
||||
psh_expression << "$(Invoke-Expression $(New-Object IO.StreamReader("
|
||||
psh_expression << "$(New-Object IO.Compression.DeflateStream("
|
||||
psh_expression << "$stream,"
|
||||
psh_expression << "[IO.Compression.CompressionMode]::Decompress)),"
|
||||
psh_expression << "[Text.Encoding]::ASCII)).ReadToEnd());"
|
||||
|
||||
# If eof is set, add a marker to signify end of code output
|
||||
#if (eof && eof.length == 8) then psh_expression += "'#{eof}'" end
|
||||
psh_expression << "echo '#{eof}';" if eof
|
||||
|
||||
# Convert expression to unicode
|
||||
unicode_expression = Rex::Text.to_unicode(code)
|
||||
unicode_expression = Rex::Text.to_unicode(psh_expression)
|
||||
|
||||
# Base64 encode the unicode expression
|
||||
@code = Rex::Text.encode_base64(unicode_expression)
|
||||
|
@ -42,10 +67,11 @@ module Powershell
|
|||
return code
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return a zlib compressed powershell code
|
||||
# Return a gzip compressed powershell code
|
||||
#
|
||||
def compress_code(eof = nil)
|
||||
def gzip_code(eof = nil)
|
||||
# Compress using the Deflate algorithm
|
||||
compressed_stream = Rex::Text.gzip(code)
|
||||
|
||||
|
@ -54,30 +80,51 @@ module Powershell
|
|||
|
||||
# Build the powershell expression
|
||||
# Decode base64 encoded command and create a stream object
|
||||
psh_expression = "IEX(New-Object IO.StreamReader("
|
||||
psh_expression << "(New-Object IO.Compression.GzipStream("
|
||||
psh_expression << "(New-Object IO.MemoryStream(,[Convert]::FromBase64String('#{encoded_stream}'))),"
|
||||
psh_expression = "$stream = New-Object IO.MemoryStream(,"
|
||||
psh_expression << "$([Convert]::FromBase64String('#{encoded_stream}')));"
|
||||
# Uncompress and invoke the expression (execute)
|
||||
psh_expression << "$(Invoke-Expression $(New-Object IO.StreamReader("
|
||||
psh_expression << "$(New-Object IO.Compression.GzipStream("
|
||||
psh_expression << "$stream,"
|
||||
psh_expression << "[IO.Compression.CompressionMode]::Decompress)),"
|
||||
psh_expression << "[Text.Encoding]::ASCII)).ReadToEnd();"
|
||||
psh_expression << "[Text.Encoding]::ASCII)).ReadToEnd());"
|
||||
|
||||
# If eof is set, add a marker to signify end of code output
|
||||
#if (eof && eof.length == 8) then psh_expression += "'#{eof}'" end
|
||||
psh_expression << "echo '#{eof}';" if eof
|
||||
|
||||
@code = psh_expression
|
||||
# Convert expression to unicode
|
||||
unicode_expression = Rex::Text.to_unicode(psh_expression)
|
||||
|
||||
return psh_expression
|
||||
# Base64 encode the unicode expression
|
||||
@code = Rex::Text.encode_base64(unicode_expression)
|
||||
|
||||
return code
|
||||
end
|
||||
|
||||
#
|
||||
# Compresses script contents with gzip or deflate
|
||||
#
|
||||
def compress_code(eof = nil, gzip = true, in_place = true)
|
||||
code = gzip ? gzip_code(eof) : deflate_code(eof)
|
||||
@code = code if in_place
|
||||
return code
|
||||
end
|
||||
|
||||
#
|
||||
# Reverse the compression process
|
||||
# Try gzip, inflate if that fails
|
||||
#
|
||||
def decompress_code
|
||||
# Decode base64 and convert to ascii
|
||||
raw = Rex::Text.decode_base64(code)
|
||||
ascii_expression = Rex::Text.to_ascii(raw)
|
||||
# Extract substring with payload
|
||||
encoded_stream = ascii_expression.scan(/FromBase64String\('(.*)'/).flatten.first
|
||||
# Decode and decompress the string
|
||||
return Rex::Text.ungzip( Rex::Text.decode_base64(encoded_stream) )
|
||||
# ::Zlib::Inflate.inflate( Rex::Text.decode_base64(encoded_stream) )
|
||||
@code = ( Rex::Text.ungzip( Rex::Text.decode_base64(encoded_stream) ) ||
|
||||
Rex::Text.zlib_inflate( Rex::Text.decode_base64(encoded_stream)) )
|
||||
return code
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -144,6 +191,7 @@ module Powershell
|
|||
'$WhatIfPreference'
|
||||
].map(&:downcase)
|
||||
|
||||
# return code.scan(/\$[a-zA-Z\-\_]+/).uniq.flatten - res_vars
|
||||
|
||||
our_vars = code.scan(/\$[a-zA-Z\-\_]+/).uniq.flatten.map(&:strip)
|
||||
return our_vars.select {|v| !res_vars.include?(v)}
|
||||
|
@ -243,7 +291,17 @@ module Powershell
|
|||
# Multi line
|
||||
code.gsub!(/<#(.*?)#>/m,'')
|
||||
# Single line
|
||||
code.gsub!(/^#.*$|^\s+#.*$/,'')
|
||||
code.gsub!(/^\s*#(?!.*region)(.*$)/i,'')
|
||||
end
|
||||
|
||||
#
|
||||
# Remove empty lines
|
||||
#
|
||||
def strip_empty_lines
|
||||
# Windows EOL
|
||||
code.gsub!(/[\r\n]+/,"\r\n")
|
||||
# UNIX EOL
|
||||
code.gsub!(/[\n]+/,"\n")
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -254,7 +312,6 @@ module Powershell
|
|||
code.gsub!(/\s+/,' ')
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Identify variables and replace them
|
||||
#
|
||||
|
@ -349,7 +406,21 @@ module Powershell
|
|||
# Pretend we are actually a string
|
||||
extend Forwardable
|
||||
# In case someone messes with String we delegate based on its instance methods
|
||||
eval %Q|def_delegators :@code, :#{::String.instance_methods[0..(String.instance_methods.index(:class)-1)].join(', :')}|
|
||||
#eval %Q|def_delegators :@code, :#{::String.instance_methods[0..(String.instance_methods.index(:class)-1)].join(', :')}|
|
||||
def_delegators :@code, :each_line, :strip, :chars, :intern, :chr, :casecmp, :ascii_only?, :<, :tr_s,
|
||||
:!=, :capitalize!, :ljust, :to_r, :sum, :private_methods, :gsub,:dump, :match, :to_sym,
|
||||
:enum_for, :display, :tr_s!, :freeze, :gsub, :split, :rindex, :<<, :<=>, :+, :lstrip!,
|
||||
:encoding, :start_with?, :swapcase, :lstrip!, :encoding, :start_with?, :swapcase,
|
||||
:each_byte, :lstrip, :codepoints, :insert, :getbyte, :swapcase!, :delete, :rjust, :>=,
|
||||
:!, :count, :slice, :clone, :chop!, :prepend, :succ!, :upcase, :include?, :frozen?,
|
||||
:delete!, :chop, :lines, :replace, :next, :=~, :==, :rstrip!, :%, :upcase!, :each_char,
|
||||
:hash, :rstrip, :length, :reverse, :setbyte, :bytesize, :squeeze, :>, :center, :[],
|
||||
:<=, :to_c, :slice!, :chomp!, :next!, :downcase, :unpack, :crypt, :partition,
|
||||
:between?, :squeeze!, :to_s, :chomp, :bytes, :clear, :!~, :to_i, :valid_encoding?, :===,
|
||||
:tr, :downcase!, :scan, :sub!, :each_codepoint, :reverse!, :class, :size, :empty?, :byteslice,
|
||||
:initialize_clone, :to_str, :to_enum,:tap, :tr!, :trust, :encode!, :sub, :oct, :succ, :index,
|
||||
:[]=, :encode, :*, :hex, :to_f, :strip!, :rpartition, :ord, :capitalize, :upto, :force_encoding,
|
||||
:end_with?
|
||||
|
||||
# def method_missing(meth, *args, &block)
|
||||
# code.send(meth,*args,&block) || (raise NoMethodError.new, meth)
|
||||
|
@ -379,12 +450,11 @@ module Powershell
|
|||
##
|
||||
|
||||
#
|
||||
# Convert binary to byte array, read from file if able
|
||||
# Build a byte array to load into powershell code
|
||||
#
|
||||
def self.to_byte_array(input_data,var_name="buf")
|
||||
return "[Byte[]]$#{name} = ''" if input_data.nil? or input_data.empty?
|
||||
|
||||
code = input_data.unpack('C*')
|
||||
def self.build_byte_array(input_data,var_name = Rex::Text.rand_text_alpha(rand(3)+3))
|
||||
code = ::File.file?(input_data) ? ::File.read(input_data) : input_data
|
||||
code = code.unpack('C*')
|
||||
psh = "[Byte[]] $#{var_name} = 0x#{code[0].to_s(16)}"
|
||||
lines = []
|
||||
1.upto(code.length-1) do |byte|
|
||||
|
@ -394,16 +464,7 @@ module Powershell
|
|||
lines.push ",0x#{code[byte].to_s(16)}"
|
||||
end
|
||||
end
|
||||
|
||||
return psh << lines.join("") + "\r\n"
|
||||
end
|
||||
|
||||
#
|
||||
# Build a byte array to load into powershell code
|
||||
#
|
||||
def self.build_byte_array(input_data,var_name = Rex::Text.rand_text_alpha(rand(3)+3))
|
||||
code = ::File.file?(input_data) ? ::File.read(input_data) : input_data
|
||||
return to_byte_array(input_data,var_name)
|
||||
psh << lines.join("") + "\r\n"
|
||||
end
|
||||
|
||||
def self.psp_funcs(dir)
|
||||
|
@ -423,3 +484,4 @@ module Powershell
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue