Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/post/meterpreter/extensions/bofloader/bofloader.rb
Views: 11791
# -*- coding: binary -*-12require 'rex/post/meterpreter/extensions/bofloader/tlv'3require 'rex/post/meterpreter/extensions/bofloader/command_ids'4require 'rexml/document'5require 'set'67module Rex8module Post9module Meterpreter10module Extensions11module Bofloader12###13#14# Bofloader extension - Executes a beacon object file in15# the current meterpreter session.16#17# Kevin Haubris (@kev169)18# Kevin Clark (@GuhnooPlusLinux)19# TrustedSec (@TrustedSec)20#21###2223class BofPackingError < RuntimeError24end2526# Code referenced from: https://github.com/trustedsec/COFFLoader/blob/main/beacon_generate.py27# Emulates the native Cobalt Strike bof_pack() function.28# Documented here: https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#bof_pack29#30# Type Description Unpack With (C)31# --------|---------------------------------------|------------------------------32# b | binary data | BeaconDataExtract33# i | 4-byte integer | BeaconDataInt34# s | 2-byte short integer | BeaconDataShort35# z | zero-terminated+encoded string | BeaconDataExtract36# Z | zero-terminated wide-char string | (wchar_t *)BeaconDataExtract37class BofPack38def initialize39reset40end4142def add_binary(binary)43# Add binary data to the buffer44binary = binary.bytes if binary.is_a? String45b_length = binary.length46binary = [b_length] + binary47buf = binary.pack("I<c#{b_length}")48@size += buf.length49@buffer << buf50end5152def add_int(dint)53@buffer << [dint.to_i].pack('I<')54@size += 455end5657def add_short(short)58@buffer << [short.to_i].pack('s<')59@size += 260end6162def add_str(str)63str = str.encode('utf-8').bytes64str << 0x00 # Null terminated strings...65s_length = str.length66str = [s_length] + str67buf = str.pack("I<c#{s_length}")68@size += buf.length69@buffer << buf70end7172def add_wstr(wstr)73wstr = wstr.encode('utf-16le').bytes74wstr << 0x00 << 0x00 # Null terminated wide string75s_length = wstr.length76wstr = [s_length] + wstr77buf = wstr.pack("I<c#{s_length}")78@size += buf.length79@buffer << buf80end8182def finalize_buffer83output = [@size].pack('I<') + @buffer84reset85output86end8788def reset89@buffer = ''90@size = 091end9293def bof_pack(fstring, args)94# Wrapper function to pack an entire bof command line into a buffer95if fstring.nil? || args.nil?96return finalize_buffer97end9899if fstring.length != args.length100raise BofPackingError, 'Mismatched format and argument lengths'101end102103fstring.chars.zip(args).each do |c, arg|104case c105when 'b'106add_binary(arg)107when 'i'108add_int(arg)109when 's'110add_short(arg)111when 'z'112add_str(arg)113when 'Z'114add_wstr(arg)115else116raise BofPackingError, "Invalid character in format string: #{c}. Must be one of \"b, i, s, z, Z\""117end118end119120# return the packed bof_string121finalize_buffer122end123end124125# Beacon object file (BOF) loader126class Bofloader < Extension127128def self.extension_id129EXTENSION_ID_BOFLOADER130end131132# Typical extension initialization routine.133#134# @param client (see Extension#initialize)135def initialize(client)136super(client, 'bofloader')137138client.register_extension_aliases(139[140{141'name' => 'bofloader',142'ext' => self143},144]145)146end147148def execute(bof_data, args_format: nil, args: nil, entry: 'go')149request = Packet.create_request(COMMAND_ID_BOFLOADER_EXECUTE)150151# Pack up beacon object file data and arguments into one single binary blob152# Hardcode the entrypoint to "go" (CobaltStrike approved)153bof = BofPack.new154packed_args = bof.bof_pack(args_format, args)155156# Send the meterpreter TLV packet and get the output back157request.add_tlv(TLV_TYPE_BOFLOADER_EXECUTE_BUFFER, bof_data)158request.add_tlv(TLV_TYPE_BOFLOADER_EXECUTE_BUFFER_ENTRY, entry)159request.add_tlv(TLV_TYPE_BOFLOADER_EXECUTE_ARGUMENTS, packed_args)160response = client.send_request(request)161return response.get_tlv_value(TLV_TYPE_BOFLOADER_EXECUTE_RESULT)162end163164end165end166end167end168end169end170171172