Add compiler support when mingw is available

This commit is contained in:
Spencer McIntyre 2022-09-09 16:33:23 -04:00
parent 4e0111f119
commit 37d3c296ad
3 changed files with 116 additions and 3 deletions

View File

@ -15,6 +15,10 @@ License: BSD-3-clause
# Last updated: 2013-Nov-04
#
Files: data/headers/windows/c_payload_util/beacon.h
Copyright: 2022, Copyright Help/Systems LLC and its group of companies.
License: Apache 2.0
Files: data/exploits/mysql/lib_mysqludf_sys_*.so
Copyright: 2007 Roland Bouman
2008-2010 Roland Bouman and Bernardo Damele A. G.

View File

@ -0,0 +1,69 @@
/*
* Beacon Object Files (BOF)
* -------------------------
* A Beacon Object File is a light-weight post exploitation tool that runs
* with Beacon's inline-execute command.
*
* Additional BOF resources are available here:
* - https://github.com/Cobalt-Strike/bof_template
*
* Cobalt Strike 4.x
* ChangeLog:
* 1/25/2022: updated for 4.5
*/
/* data API */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} datap;
DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size);
DECLSPEC_IMPORT char * BeaconDataPtr(datap * parser, int size);
DECLSPEC_IMPORT int BeaconDataInt(datap * parser);
DECLSPEC_IMPORT short BeaconDataShort(datap * parser);
DECLSPEC_IMPORT int BeaconDataLength(datap * parser);
DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size);
/* format API */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} formatp;
DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz);
DECLSPEC_IMPORT void BeaconFormatReset(formatp * format);
DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len);
DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...);
DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size);
DECLSPEC_IMPORT void BeaconFormatFree(formatp * format);
DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);
/* Output Functions */
#define CALLBACK_OUTPUT 0x0
#define CALLBACK_OUTPUT_OEM 0x1e
#define CALLBACK_OUTPUT_UTF8 0x20
#define CALLBACK_ERROR 0x0d
DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len);
DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...);
/* Token Functions */
DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token);
DECLSPEC_IMPORT void BeaconRevertToken();
DECLSPEC_IMPORT BOOL BeaconIsAdmin();
/* Spawn+Inject Functions */
DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length);
DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo);
DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);
/* Utility Functions */
DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max);

View File

@ -24,10 +24,11 @@ module Rex
'Beacon Object File Loader'
end
DEFAULT_ENTRY = 'go'
DEFAULT_ENTRY = 'go'.freeze
@@execute_bof_opts = Rex::Parser::Arguments.new(
['-h', '--help'] => [ false, 'Help Banner' ],
['-c', '--compile'] => [ true, 'Compile the input file (requires mingw).' ],
['-e', '--entry'] => [ true, "The entry point (default: #{DEFAULT_ENTRY})." ],
['-f', '--format-string'] => [ true, 'bof_pack compatible format-string. Choose combination of: b, i, s, z, Z' ]
)
@ -54,6 +55,8 @@ module Rex
return tab_complete_filenames(str, words) if words.length == 1
fmt = {
'-c' => [ nil ],
'--compile' => [ nil ],
'-e' => [ true ],
'--entry' => [ true ],
'-f' => [ true ],
@ -63,7 +66,7 @@ module Rex
end
def cmd_execute_bof(*args)
if args.length == 0 || args.include?('-h') || args.include?('--help')
if args.empty? || args.include?('-h') || args.include?('--help')
cmd_execute_bof_help
return false
end
@ -72,9 +75,12 @@ module Rex
bof_args_format = nil
bof_cmdline = []
entry = DEFAULT_ENTRY
compile = false
@@execute_bof_opts.parse(args) do |opt, _idx, val|
case opt
when '-c', '--compile'
compile = true
when '-f', '--format-string'
bof_args_format = val
when '-e', '--entry'
@ -104,7 +110,12 @@ module Rex
print_status('No argument format specified, executing bof with no arguments.')
end
bof_data = ::File.binread(bof_filename)
if compile
bof_data = compile_c(bof_filename)
return unless bof_data
else
bof_data = ::File.binread(bof_filename)
end
# loading all data will hang on invalid files like DLLs, so only parse the 20-byte header at first
parsed = Metasm::COFF.decode_header(bof_data[0...20])
@ -145,6 +156,35 @@ module Rex
private
def compile_c(source)
if client.arch == ARCH_X86
mingw = Metasploit::Framework::Compiler::Mingw::X86.new
elsif client.arch == ARCH_X64
mingw = Metasploit::Framework::Compiler::Mingw::X64.new
else
print_error("Unsupported client architecture: #{client.arch}")
return
end
unless mingw.class.available?
print_error("#{mingw.mingw_bin} is unavailable, can not compile source code")
return
end
::Dir::Tmpname.create([::File.basename(source, '.c'), '.o']) do |destination|
output, status = Open3.capture2e(mingw.mingw_bin, '-c', source, '-I', Metasploit::Framework::Compiler::Mingw::INCLUDE_DIR, '-o', destination)
unless status.exitstatus == 0
print_error("Compilation exited with error code: #{status.exitstatus}")
print_line(output) unless output.blank?
return
end
bof_data = ::File.binread(destination)
::File.delete(destination)
return bof_data
end
end
def get_executable_symbols(coff)
executable_symbols = []
coff.symbols.each do |sym|