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

#initialize ⇒ ParsedProfile

Returns a new instance of ParsedProfile.



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

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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object



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

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

Instance Attribute Details

#sections ⇒ Object

Returns the value of attribute sections.



146
147
148
# File 'lib/msf/core/payload/malleable_c2.rb', line 146

def sections
  @sections
end

#sets ⇒ Object

Returns the value of attribute sets.



146
147
148
# File 'lib/msf/core/payload/malleable_c2.rb', line 146

def sets
  @sets
end

Instance Method Details

#get_section(name) ⇒ Object



166
167
168
169
170
171
172
# File 'lib/msf/core/payload/malleable_c2.rb', line 166

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



158
159
160
161
162
163
164
# File 'lib/msf/core/payload/malleable_c2.rb', line 158

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

#to_tlv ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/msf/core/payload/malleable_c2.rb', line 238

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



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/msf/core/payload/malleable_c2.rb', line 214

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

#uris ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/msf/core/payload/malleable_c2.rb', line 174

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



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/msf/core/payload/malleable_c2.rb', line 194

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