unknown 2 年 前
コミット
7ff035a06c

+ 21 - 0
KIT/EnumTaskScheduler/README.md

@@ -0,0 +1,21 @@
+# EnumTaskScheduler
+Enumerate and list all the scheduled tasks in the root folder.
+
+## Parameters
+* `hostName`: Specify `""` for the current system or the FQDN of the remote host: `DB01.example.local`. 
+
+
+## Usage
+* `enumtaskscheduler <(optional) hostName>`
+
+
+## Examples
+* `enumtaskscheduler`
+* `enumtaskscheduler DB01.example.local`
+
+
+## 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/EnumTaskScheduler/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/EnumTaskScheduler/bofcompile.bat

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

+ 326 - 0
KIT/EnumTaskScheduler/enumtaskscheduler.c

@@ -0,0 +1,326 @@
+#include <stdio.h>
+#include <windows.h>
+#include <taskschd.h>
+#include <combaseapi.h>
+#include "enumtaskscheduler.h"
+#include "beacon.h"
+
+
+
+
+//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)); // Clear print buffer.
+	}
+
+	va_end(argList);
+	return hr;
+}
+
+//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 EnumScheduledTasks(wchar_t * host) {
+    HRESULT hr = S_OK;
+
+    hr = OLE32$CoInitializeEx(NULL, COINIT_MULTITHREADED);
+    if (FAILED(hr)) return FALSE;
+
+    IID CTaskScheduler = {0x0f87369f, 0xa4e5, 0x4cfc, {0xbd,0x3e,0x73,0xe6,0x15,0x45,0x72,0xdd}};
+    IID IIDITaskService = {0x2faba4c7, 0x4da9, 0x4013, {0x96, 0x97, 0x20, 0xcc, 0x3f, 0xd4, 0x0f, 0x85}};
+    ITaskService *pTaskService = NULL;
+    hr = OLE32$CoCreateInstance(&CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, &IIDITaskService, (void**)&pTaskService);
+    if (FAILED(hr)) {
+        return FALSE;
+    }
+    
+	VARIANT Vhost;
+	VARIANT VNull;
+	OLEAUT32$VariantInit(&Vhost);
+	OLEAUT32$VariantInit(&VNull);
+    Vhost.vt = VT_BSTR;
+    Vhost.bstrVal = OLEAUT32$SysAllocString(host);
+    
+    hr = pTaskService->lpVtbl->Connect(pTaskService, Vhost, VNull, VNull, VNull); 
+    if (FAILED(hr)) {
+        goto cleanup;
+    }
+	
+    ITaskFolder* pRootFolder = NULL;
+    hr = pTaskService->lpVtbl->GetFolder(pTaskService, L"\\", &pRootFolder);
+    if (FAILED(hr)) {
+        goto cleanup;
+    }
+	
+    IRegisteredTaskCollection* pTaskCollection = NULL;
+    hr = pRootFolder->lpVtbl->GetTasks(pRootFolder, 0, &pTaskCollection);
+    if (FAILED(hr)) {
+        goto cleanup;
+    }
+
+
+    long numTasks = 0;
+    hr = pTaskCollection->lpVtbl->get_Count(pTaskCollection, &numTasks);
+
+	BeaconPrintToStreamW(L"[+] Scheduled tasks in root folder:\n");
+	BeaconPrintToStreamW(L"=======================================================\n\n");
+
+	for (long i = 1; i <= numTasks; i++) { 
+		IRegisteredTask* pRegisteredTask = NULL;
+		VARIANT index;
+		index.vt = VT_I4;
+		index.lVal = i;
+
+		hr = pTaskCollection->lpVtbl->get_Item(pTaskCollection, index, &pRegisteredTask);
+		if (SUCCEEDED(hr)) {
+			BSTR taskName = NULL;
+			hr = pRegisteredTask->lpVtbl->get_Name(pRegisteredTask, &taskName);
+			if (SUCCEEDED(hr)) {
+				BeaconPrintToStreamW(L"Task Name: %ls\n", taskName);
+				OLEAUT32$SysFreeString(taskName);
+			}
+			
+			
+			ITaskDefinition* pTaskDef = NULL;
+			hr = pRegisteredTask->lpVtbl->get_Definition(pRegisteredTask, &pTaskDef);
+			if (SUCCEEDED(hr)) {
+				
+				
+				// Fetching the Principal information and print the user account
+				IPrincipal* pPrincipal = NULL;
+				hr = pTaskDef->lpVtbl->get_Principal(pTaskDef, &pPrincipal);
+				if (SUCCEEDED(hr)) {
+					BSTR userId = NULL;
+					hr = pPrincipal->lpVtbl->get_UserId(pPrincipal, &userId);
+					if (SUCCEEDED(hr)) {
+						BeaconPrintToStreamW(L"- Task running as: %ls\n", userId);
+						OLEAUT32$SysFreeString(userId);
+					}
+					pPrincipal->lpVtbl->Release(pPrincipal);
+				}
+
+				// Fetching Action Information
+				ITaskDefinition* pTaskDef = NULL;
+				hr = pRegisteredTask->lpVtbl->get_Definition(pRegisteredTask, &pTaskDef);
+				if (SUCCEEDED(hr)) {
+					IActionCollection* pActionColl = NULL;
+					hr = pTaskDef->lpVtbl->get_Actions(pTaskDef, &pActionColl);
+					if (SUCCEEDED(hr)) {
+						long actionCount = 0;
+						hr = pActionColl->lpVtbl->get_Count(pActionColl, &actionCount);
+						if (SUCCEEDED(hr)) {
+							for (long j = 1; j <= actionCount; j++) {
+								IAction* pAction = NULL;
+								long actionIndex = j;
+
+								hr = pActionColl->lpVtbl->get_Item(pActionColl, actionIndex, &pAction);
+								if (SUCCEEDED(hr)) {
+									TASK_ACTION_TYPE actionType;
+									hr = pAction->lpVtbl->get_Type(pAction, &actionType);
+									if (SUCCEEDED(hr)) {
+										WCHAR* actionTypes[] = {
+											L"Start a program",
+											L"Send an e-mail (Deprecated)",
+											L"Display a message (Deprecated)"
+										};
+
+										WCHAR* actionTypeName = actionTypes[actionType];  // Using actionType as an index
+										BeaconPrintToStreamW(L"- Action type: %s\n", actionTypeName);
+
+										if (actionType == TASK_ACTION_EXEC) {
+											IExecAction* pExecAction = (IExecAction*) pAction;
+											BSTR execPath;
+											hr = pExecAction->lpVtbl->get_Path(pExecAction, &execPath);
+											if (SUCCEEDED(hr)) {
+												BeaconPrintToStreamW(L"- Executable path: %ls\n", execPath);
+												OLEAUT32$SysFreeString(execPath);
+											}
+										}
+									}
+
+									pAction->lpVtbl->Release(pAction);
+								}
+							}
+						}
+					}
+				}
+				
+				// Fetching Trigger Information
+				ITriggerCollection* pTriggerColl = NULL;
+				hr = pTaskDef->lpVtbl->get_Triggers(pTaskDef, &pTriggerColl);
+				if (SUCCEEDED(hr)) {
+					long triggerCount = 0;
+					hr = pTriggerColl->lpVtbl->get_Count(pTriggerColl, &triggerCount);
+					if (SUCCEEDED(hr)) {
+						for (long j = 1; j <= triggerCount; j++) {
+							ITrigger* pTrigger = NULL;
+							long triggerIndex = j;
+
+							hr = pTriggerColl->lpVtbl->get_Item(pTriggerColl, triggerIndex, &pTrigger);
+							if (SUCCEEDED(hr)) {
+								TASK_TRIGGER_TYPE2 triggerType;
+								hr = pTrigger->lpVtbl->get_Type(pTrigger, &triggerType);
+								if (SUCCEEDED(hr)) {
+									static const WCHAR* triggerTypeNames[] = {
+										L"On an event",    // 1
+										L"On a schedule",     // 2
+										L"Daily",    // 3
+										L"Weekly",   // 4
+										L"Monthly",  // 5
+										L"MonthlyDOW", // 6
+										L"On idle",       // 7
+										L"At task creation/modification", // 8
+										L"At startup",       // 9
+										L"At log on",      // 10
+										L"SessionStateChange (lock/unlock/connection)",  // 11
+										L"SessionStateChange (lock/unlock/connection)"  // 12
+									};
+
+									const WCHAR* triggerTypeName = (triggerType >= 0 && triggerType < sizeof(triggerTypeNames) / sizeof(triggerTypeNames[0])) 
+																  ? triggerTypeNames[triggerType] 
+																  : L"Unknown";
+
+									BeaconPrintToStreamW(L"- Trigger type: %s\n", triggerTypeName);
+								}
+
+								pTrigger->lpVtbl->Release(pTrigger);
+							}
+						}
+					}
+
+					pTriggerColl->lpVtbl->Release(pTriggerColl);
+				}
+
+				pTaskDef->lpVtbl->Release(pTaskDef);
+			}
+
+			if (pRegisteredTask) {
+				pRegisteredTask->lpVtbl->Release(pRegisteredTask);
+			}
+		}
+		BeaconPrintToStreamW(L"----------------------------------------------------\n\n");
+	}
+
+cleanup:
+    if (pTaskCollection) {
+        pTaskCollection->lpVtbl->Release(pTaskCollection);
+    }
+    if (pRootFolder) {
+        pRootFolder->lpVtbl->Release(pRootFolder);
+	}
+    if (pTaskService) {
+        pTaskService->lpVtbl->Release(pTaskService);
+    }
+
+    OLEAUT32$VariantClear(&Vhost);
+    OLE32$CoUninitialize();
+
+    return TRUE;
+}
+
+
+
+int go(char *args, int len) {
+	BOOL res = NULL;
+	datap parser;
+	WCHAR *hostName  = L""; 
+	
+	BeaconDataParse(&parser, args, len);
+	hostName = BeaconDataExtract(&parser, NULL);
+
+	res = EnumScheduledTasks(hostName);
+
+	if(!res) BeaconPrintf(CALLBACK_ERROR, "Failed to enumerate scheduled tasks.\n");
+	else  {
+		BeaconOutputStreamW();
+		BeaconPrintf(CALLBACK_OUTPUT, "[+] Done enumerating!\n");
+	}
+
+
+	return 0;
+}
+
+
+		
+		

+ 29 - 0
KIT/EnumTaskScheduler/enumtaskscheduler.cna

@@ -0,0 +1,29 @@
+# author REDMED-X
+
+beacon_command_register(
+	"enumtaskscheduler", "Enumerate and list all the scheduled tasks in the root folder.",
+	"INFO:\nEnumerate and list all the scheduled tasks in the root folder.\n\n" .
+	"ARGUMENTS:\n[hostName]: The FQDN of the remote host or \"\" for the current system.\n\n" .
+	"USAGE:\nenumtaskscheduler <(optional) hostName>\n\n" .
+	"EXAMPLES:\nenumtaskscheduler \nenumtaskscheduler DB01.example.local\n\n");
+	
+alias enumtaskscheduler {
+    $bid = $1;
+	$host = $2; 
+
+
+    # Read in the right BOF file
+    $handle = openf(script_resource("enumtaskscheduler.o"));
+    $data   = readb($handle, -1);
+    closef($handle);
+
+
+	$arg_data  = bof_pack($bid, "Z", $host);
+
+	blog($bid, "Tasked to enumerate scheduled tasks in the root folder..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+
+}
+
+
+

+ 33 - 0
KIT/EnumTaskScheduler/enumtaskscheduler.h

@@ -0,0 +1,33 @@
+#include <windows.h>  
+
+//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);
+
+
+//CreateScheduledTask
+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);
+WINBASEAPI BSTR WINAPI OLEAUT32$SysAllocString(const OLECHAR *);
+WINBASEAPI void WINAPI OLEAUT32$SysFreeString(BSTR);
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...);
+WINBASEAPI int __cdecl MSVCRT$strcmp(const char *str1, const char *str2);
+WINBASEAPI int __cdecl MSVCRT$wcscmp(const wchar_t* str1, const wchar_t* str2);
+
+
+

BIN
KIT/EnumTaskScheduler/enumtaskscheduler.o