diff --git a/red-teaming/README.md b/red-teaming/README.md index 3dffab1..4698417 100755 --- a/red-teaming/README.md +++ b/red-teaming/README.md @@ -57,6 +57,8 @@ cmstp.exe /ni /s cmstp.inf - **`cobalt-arsenal`** - A set of my published Cobalt Strike 4.0+ compatible aggressor scripts. That includes couple of my handy utils I've used on various engagements. +- **`cobalt-udrl-hasher`** - A handy utility used to recalculate hashes needed for Cobalt Strike _User Defined Reflective Loaders_ + - **`CobaltSplunk`** - Originally devised by [Vincent Yiu](https://github.com/vysecurity/CobaltSplunk), heavily reworked by me: a Splunk application that ingests, indexes and exposes several search operators to work with Cobalt Strike logs from within of a Splunk interface. Supports Cobalt Strike 4.3+ log files syntax. Gives a lot of flexibility to work with Teamserver log files, search through them, generate insightful reports/dashboards/pivot tables and much more. - [**`code-exec-templates`**](https://github.com/mgeeky/Penetration-Testing-Tools/tree/master/red-teaming/code-exec-templates) - a small collection of template/backbone files for various code-execution techniques (VBScript/JScript embedded in HTA/SCT/XSL/VBS/JS) diff --git a/red-teaming/cobalt-udrl-hasher/README.md b/red-teaming/cobalt-udrl-hasher/README.md new file mode 100644 index 0000000..845ef99 --- /dev/null +++ b/red-teaming/cobalt-udrl-hasher/README.md @@ -0,0 +1,45 @@ +## Cobalt Strike UDRL Hasher + +Simple helper utility recomputing `DLL Reflective Loader` hashes, for offensive engineering needs whenever we want to recompile [User Defined Reflective Loaders](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/malleable-c2-extend_user-defined-rdll.htm) and such. + +Ever came across [such hashes](https://github.com/stephenfewer/ReflectiveDLLInjection/blob/master/dll/src/ReflectiveLoader.h#L43) before? + +``` +#define KERNEL32DLL_HASH 0x6A4ABC5B +#define NTDLLDLL_HASH 0x3CFA685D + +#define LOADLIBRARYA_HASH 0xEC0E4E8E +#define GETPROCADDRESS_HASH 0x7C0DFCAA +#define VIRTUALALLOC_HASH 0x91AFCA54 +#define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8 + +[...] + +#define HASH_KEY 13 +``` + +These can be used for a straightforward signaturing. + +We can regenerate them easily with utility included here: + +``` +cmd> hash 55 + +#define KERNEL32DLL_HASH 0xA6154C3A // kernel32.dll +#define NTDLLDLL_HASH 0x0521447A // ntdll.dll + +#define LOADLIBRARYA_HASH 0xE0D79FEB // LoadLibraryA +#define GETPROCADDRESS_HASH 0x6BAC2F89 // GetProcAddress +#define VIRTUALALLOC_HASH 0x9EE2D962 // VirtualAlloc +#define VIRTUALPROTECT_HASH 0x9154022F // VirtualProtect +#define NTFLUSHINSTRUCTIONCACHE_HASH 0x7353E65D // NtFlushInstructionCache + +#define HASH_KEY 55 + +``` + +**Notice** - if you want to get hash for a DLL, be sure to include its extension: + +``` +hash 55 kernel32.dll +``` diff --git a/red-teaming/cobalt-udrl-hasher/hash.c b/red-teaming/cobalt-udrl-hasher/hash.c new file mode 100644 index 0000000..a052cb1 --- /dev/null +++ b/red-teaming/cobalt-udrl-hasher/hash.c @@ -0,0 +1,123 @@ +// +// Simple utility aimed to help regenerating UDRL hashes +// +// cmd> gcc hash.c -o hash.exe +// +// Mariusz Banach / mgeeky, '23 +// binary-offensive.com +// + +#include +#include +#include + +BYTE hashKey = 13; + +__forceinline DWORD ror( DWORD d ) { + return _rotr( d, hashKey ); +} + +__forceinline DWORD hash( const char * c ) { + register DWORD h = 0; + do + { + h = ror( h ); + h += *c; + } while( *++c ); + + return h; +} + +__forceinline DWORD hashModule( const char * c ) { + register DWORD h = 0; + + size_t counter = strlen(c) * 2; + wchar_t * wstr = (wchar_t*)malloc(counter + 2); + char * ptr = (char*)wstr; + + mbstowcs(wstr, c, counter); + + do + { + h = ror( (DWORD)h ); + + // normalize to uppercase if the module name is in lowercase + if( *((BYTE *)ptr) >= 'a' ) + h += *((BYTE *)ptr) - 0x20; + else + h += *((BYTE *)ptr); + + ptr++; + + } while( --counter ); + + free(wstr); + return h; +} + +int endswith(const char *str, const char *suffix) +{ + if (!str || !suffix) + return 0; + size_t lenstr = strlen(str); + size_t lensuffix = strlen(suffix); + if (lensuffix > lenstr) + return 0; + return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; +} + +void print(char* str) { + DWORD val = 0; + + if(endswith(str, ".dll")) { + val = hashModule(str); + } + else { + val = hash(str); + } + + char str2[256] = ""; + char *s = str2; + + for(int i = 0; i < strlen(str); i++) { + if(isalnum(str[i])) { + *(s++) = str[i]; + } + } + + s = str2; + while (*s) *(s++) = toupper(*s); + + strncat(str2, "_HASH", sizeof(str2)-1); + + printf("#define %-30s 0x%08X\t// %s\n", str2, val, str); +} + +int main(int argc, char** argv) { + if (argc < 2) { + printf("Usage: hash.exe [string]\n"); + return 0; + } + + hashKey = atoi(argv[1]); + + printf("\n"); + + if (argc == 3) { + print(argv[2]); + } + else { + print("kernel32.dll"); + print("ntdll.dll"); + printf("\n"); + print("LoadLibraryA"); + print("GetProcAddress"); + print("VirtualAlloc"); + print("VirtualProtect"); + print("NtFlushInstructionCache"); + } + + printf("\n#define HASH_KEY %d\n", hashKey); + + return 0; +} \ No newline at end of file diff --git a/red-teaming/cobalt-udrl-hasher/hash.exe b/red-teaming/cobalt-udrl-hasher/hash.exe new file mode 100644 index 0000000..0b45022 Binary files /dev/null and b/red-teaming/cobalt-udrl-hasher/hash.exe differ