Class: Msf::Payload::MalleableC2::ParsedProfile

Inherits:
Object
  • Object
show all
Defined in:
lib/msf/core/payload/malleable_c2.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeParsedProfile

Returns a new instance of ParsedProfile.



143
144
145
146
# File 'lib/msf/core/payload/malleable_c2.rb', line 143

def initialize
  @sets = []
  @sections = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object



148
149
150
151
# File 'lib/msf/core/payload/malleable_c2.rb', line 148

def method_missing(name, *args)
  name = name.to_s.gsub('_', '-')
  get_section(name) || get_set(name)
end

Instance Attribute Details

#sectionsObject

Returns the value of attribute sections.



141
142
143
# File 'lib/msf/core/payload/malleable_c2.rb', line 141

def sections
  @sections
end

#setsObject

Returns the value of attribute sets.



141
142
143
# File 'lib/msf/core/payload/malleable_c2.rb', line 141

def sets
  @sets
end

Instance Method Details

#get_section(name) ⇒ Object



161
162
163
164
165
166
167
# File 'lib/msf/core/payload/malleable_c2.rb', line 161

def get_section(name)
  sec = @sections.find {|s| s.name == name.downcase}
  if block_given? && !sec.nil?
    yield(sec)
  end
  sec
end

#get_set(key) ⇒ Object



153
154
155
156
157
158
159
# File 'lib/msf/core/payload/malleable_c2.rb', line 153

def get_set(key)
  val = @sets.find {|s| s.key == key.downcase}&.value
  if block_given? && !val.nil?
    yield(val)
  end
  val
end

#to_tlvObject



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/msf/core/payload/malleable_c2.rb', line 233

def to_tlv
  tlv = MET::GroupTlv.new(MET::TLV_TYPE_C2)

  self.get_set('useragent') {|ua| tlv.add_tlv(MET::TLV_TYPE_C2_UA, ua)}
  c2_uri = self.get_set('uri')

  self.get_section('http-get') {|http_get|
    tlv.tlvs << build_get_tlv(http_get, c2_uri)
  }

  self.get_section('http-post') {|http_post|
    tlv.tlvs << build_post_tlv(http_post, c2_uri)
  }

  tlv
end

#unwrap_inbound_post(raw_bytes) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/msf/core/payload/malleable_c2.rb', line 209

def unwrap_inbound_post(raw_bytes)
  prepends = self.http_post&.client&.output&.prepend || []
  prefix = prepends.map {|p| p.args[0]}.join('')
  if !prefix.empty? && raw_bytes.start_with?(prefix)
    raw_bytes = raw_bytes[prefix.length, raw_bytes.length]
  end

  appends = self.http_post&.client&.output&.append || []
  suffix = appends.map {|p| p.args[0]}.join('')
  if !suffix.empty? && raw_bytes.end_with?(suffix)
    raw_bytes = raw_bytes[0, raw_bytes.length - suffix.length]
  end

  # do any decoding necessary
  if raw_bytes.length > 0
    if self.http_post&.client&.output&.has_directive('base64')
      raw_bytes = Rex::Text.decode_base64(raw_bytes)
    elsif self.http_post&.client&.output&.has_directive('base64url')
      raw_bytes = Rex::Text.decode_base64url(raw_bytes)
    end
  end
  raw_bytes
end

#urisObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/msf/core/payload/malleable_c2.rb', line 169

def uris
  base_uri = self.get_set('uri')
  get_uri = nil
  post_uri = nil

  self.get_section('http-get') {|http_get|
    get_uri = http_get.get_set('uri')
  }
  self.get_section('http-post') {|http_post|
    post_uri = http_post.get_set('uri')
  }

  # A `set uri` value may list several space-separated candidate URIs
  # (Cobalt Strike picks one at random per request). Split them out so
  # the handler registers a mount for each candidate, otherwise the
  # literal "uri-a uri-b" string is registered as a single unmatchable
  # resource.
  [base_uri, get_uri, post_uri].compact.flat_map {|u| u.split(/\s+/) }.reject(&:empty?).uniq
end

#wrap_outbound_get(raw_bytes) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/msf/core/payload/malleable_c2.rb', line 189

def wrap_outbound_get(raw_bytes)
  prepends = self.http_get&.server&.output&.prepend || []
  prefix = prepends.map {|p| p.args[0]}.join('')
  appends = self.http_get&.server&.output&.append || []
  suffix = appends.map {|p| p.args[0]}.join('')

  # do any encoding necessary
  if raw_bytes.length > 0
    if self.http_get&.server&.output&.has_directive('base64')
      raw_bytes = Rex::Text.encode_base64(raw_bytes)
    elsif self.http_get&.server&.output&.has_directive('base64url')
      raw_bytes = Rex::Text.encode_base64url(raw_bytes)
    end
  end

  result = prefix + raw_bytes + suffix

  result
end