537dc6e218
When attempting to update cached payload sizes which utilize the Rex::Powershell functionality, the BRE block which appropriates initial code is called with the 'code' variable being a nil which results in: ``` lib/rex/powershell/script.rb:40:in `initialize': no implicit conversion of nil into String (TypeError) ``` This throws a conditional into the File.open call which presents an empty string instead of a nil. This still results in the rescue block having to catch the exception, but manages to keep the payload size updating script happy an retains consistent behavior.
98 lines
3.6 KiB
Ruby
98 lines
3.6 KiB
Ruby
# -*- coding: binary -*-
|
|
|
|
require 'rex'
|
|
require 'forwardable'
|
|
|
|
module Rex
|
|
module Powershell
|
|
class Script
|
|
attr_accessor :code
|
|
attr_reader :functions, :rig
|
|
|
|
include Output
|
|
include Parser
|
|
include Obfu
|
|
# 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(', :')}|
|
|
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 initialize(code)
|
|
@code = ''
|
|
@rig = Rex::RandomIdentifierGenerator.new
|
|
|
|
begin
|
|
# Open code file for reading
|
|
fd = ::File.new(code || '', 'rb')
|
|
while (line = fd.gets)
|
|
@code << line
|
|
end
|
|
|
|
# Close open file
|
|
fd.close
|
|
rescue Errno::ENAMETOOLONG, Errno::ENOENT
|
|
# Treat code as a... code
|
|
@code = code.to_s.dup # in case we're eating another script
|
|
end
|
|
@functions = get_func_names.map { |f| get_func(f) }
|
|
end
|
|
|
|
##
|
|
# Class methods
|
|
##
|
|
|
|
#
|
|
# Convert binary to byte array, read from file if able
|
|
#
|
|
# @param input_data [String] Path to powershell file or powershell
|
|
# code string
|
|
# @param var_name [String] Byte array variable name
|
|
#
|
|
# @return [String] input_data as a powershell byte array
|
|
def self.to_byte_array(input_data, var_name = Rex::Text.rand_text_alpha(rand(3) + 3))
|
|
# File will raise an exception if the path contains null byte
|
|
if input_data.include? "\x00"
|
|
code = input_data
|
|
else
|
|
code = ::File.file?(input_data) ? ::File.read(input_data) : input_data
|
|
end
|
|
|
|
code = code.unpack('C*')
|
|
psh = "[Byte[]] $#{var_name} = 0x#{code[0].to_s(16)}"
|
|
lines = []
|
|
1.upto(code.length - 1) do |byte|
|
|
if (byte % 10 == 0)
|
|
lines.push "\r\n$#{var_name} += 0x#{code[byte].to_s(16)}"
|
|
else
|
|
lines.push ",0x#{code[byte].to_s(16)}"
|
|
end
|
|
end
|
|
|
|
psh << lines.join('') + "\r\n"
|
|
end
|
|
|
|
#
|
|
# Return list of code modifier methods
|
|
#
|
|
# @return [Array] Code modifiers
|
|
def self.code_modifiers
|
|
instance_methods.select { |m| m =~ /^(strip|sub)/ }
|
|
end
|
|
end # class Script
|
|
end
|
|
end
|