unknown 2 lat temu
rodzic
commit
b6c61186d6

+ 8 - 8
KIT/AddTaskScheduler/README.md

@@ -1,5 +1,5 @@
 # AddTaskScheduler
-This tool can be used to create a scheduled task on the current system or a remote host. It supports multiple trigger options. 
+This tool can be used to create a scheduled task on the current system or a remote host. It supports multiple trigger options. If the tool is running with elevated privileges, it will automatically set the `Run whether user is logged on or not` security option as `NT AUTHORITY\SYSTEM`. 
 
 >As a rule of thumb, setting a scheduled task for any user but yourself, requires elevated privileges. Furthermore, the tool returns error codes if the operation fails. The most common error codes are: 80070005 (not enough privileges), 80041318/80041319 (most likely you made a typo in one of the input fields), and 80070002 (scheduled task doesn't exist). 
 
@@ -13,10 +13,10 @@ This tool can be used to create a scheduled task on the current system or a remo
 ## Supported trigger options
 * `onetime`: Create task with trigger "On a schedule: one time".
 * `daily`: Create task with trigger "On a schedule: daily."
-* `logon`: Create task with trigger "At log on" (requires admin privs if set for another user or all users).
-* `startup`: Create task with trigger "At startup" (requires admin privs).
-* `lock`: Create task with trigger "On workstation lock" (requires admin privs if set for another user or all users).
-* `unlock`: Create task with trigger "On workstation unlock" (requires admin privs if set for another user or all users).
+* `logon`: Create task with trigger "At log on" (requires elevated privileges if set for another user or all users).
+* `startup`: Create task with trigger "At startup" (requires elevated privileges).
+* `lock`: Create task with trigger "On workstation lock" (requires elevated privileges if set for another user or all users).
+* `unlock`: Create task with trigger "On workstation unlock" (requires elevated privileges if set for another user or all users).
 
 ## Trigger specific parameters
 * `startTime`: Start time of the trigger in format: `2023-03-24T12:08:00`.
@@ -35,9 +35,9 @@ This tool can be used to create a scheduled task on the current system or a remo
 * `addtaskscheduler <taskName> <(optional) hostName> <programPath> "<(optional) programArguments>" unlock <(optional) userID> <(optional) delay>`
 
 ## Examples
-* `addtaskscheduler TestTask "" C:\Windows\System32\cmd.exe "/c C:\Windows\System32\calc.exe" daily 2023-03-24T12:08:00 2023-03-28T12:14:00 1 PT2H`
-* `addtaskscheduler NewTask DB01.example.local C:\Users\Public\Downloads\legit.exe "" logon Testdomain\Administrator`
-* `addtaskscheduler OneDrive "" C:\Data\OneDrive.exe "" unlock "" PT5M`
+* `addtaskscheduler ExampleTask "" C:\Users\Public\Downloads\payload.exe "" onetime 2023-03-24T12:08:00 PT3H`
+* `addtaskscheduler ExampleTask "" C:\Windows\System32\cmd.exe "/c C:\Windows\System32\calc.exe" daily 2023-03-24T12:08:00 2023-03-28T12:14:00 1 PT2H`
+* `addtaskscheduler ExampleTask DB01.example.local C:\Users\Public\Downloads\payload.exe "" startup PT1M`
 
 ## Compile
 - 1\. Make sure Visual Studio is installed and supports C/C++.

+ 4 - 9
KIT/AddTaskScheduler/addtaskscheduler.c

@@ -221,7 +221,6 @@ BOOL CreateScheduledTask(char* triggerType, wchar_t* taskName, wchar_t * host, w
 	ITaskService *pTaskService = NULL;
     hr = OLE32$CoCreateInstance(&CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, &IIDITaskService, (void**)&pTaskService);
     if (FAILED(hr)) {
-		//MSVCRT$printf("Failed to create ITaskService: %x\n", hr); //DEBUG
         return actionResult;
     }
 	
@@ -234,7 +233,6 @@ BOOL CreateScheduledTask(char* triggerType, wchar_t* taskName, wchar_t * host, w
 	
 	hr = pTaskService->lpVtbl->Connect(pTaskService, Vhost, VNull, VNull, VNull); 
     if (FAILED(hr)) {
-        //MSVCRT$printf("ITaskService::Connect failed: %x\n", hr); //DEBUG
 		goto cleanup;
     }
 	
@@ -242,7 +240,6 @@ BOOL CreateScheduledTask(char* triggerType, wchar_t* taskName, wchar_t * host, w
 	BSTR folderPathBstr = OLEAUT32$SysAllocString(L"\\");
 	hr = pTaskService->lpVtbl->GetFolder(pTaskService, folderPathBstr, &pTaskFolder);
 	if (FAILED(hr)) {
-		//MSVCRT$printf("ITaskService::GetFolder failed: %x\n", hr); //DEBUG
 		goto cleanup;
 	}
 	OLEAUT32$SysFreeString(folderPathBstr);
@@ -253,15 +250,15 @@ BOOL CreateScheduledTask(char* triggerType, wchar_t* taskName, wchar_t * host, w
 		goto cleanup;
     }
 	
+	BOOL isRemoteHost = (Vhost.bstrVal && *Vhost.bstrVal);
 	IPrincipal* pPrincipal = NULL;
 	hr = pTaskDefinition->lpVtbl->get_Principal(pTaskDefinition, &pPrincipal);
 	if (SUCCEEDED(hr)) {
-		if (IsElevated()) {
-			BeaconPrintf(CALLBACK_OUTPUT, "[*] Running in elevated context and setting \"Run whether user is logged on or not\" security option!\n"); 
+		if (IsElevated() || isRemoteHost) {
+			BeaconPrintf(CALLBACK_OUTPUT, "[*] Running in elevated context and setting \"Run whether user is logged on or not\" security option as SYSTEM!\n"); 
 			BSTR systemUser = OLEAUT32$SysAllocString(L"SYSTEM");
 			pPrincipal->lpVtbl->put_UserId(pPrincipal, systemUser);
 			OLEAUT32$SysFreeString(systemUser);
-			
 		}else {
 			pPrincipal->lpVtbl->put_LogonType(pPrincipal, TASK_LOGON_INTERACTIVE_TOKEN);
 		}
@@ -272,7 +269,6 @@ BOOL CreateScheduledTask(char* triggerType, wchar_t* taskName, wchar_t * host, w
     ITriggerCollection* pTriggerCollection = NULL;
     hr = pTaskDefinition->lpVtbl->get_Triggers(pTaskDefinition, &pTriggerCollection);
     if (FAILED(hr)) {
-        //MSVCRT$printf("ITaskDefinition::get_Triggers failed: %x\n", hr); //DEBUG
 		goto cleanup;
     }
 
@@ -291,7 +287,6 @@ BOOL CreateScheduledTask(char* triggerType, wchar_t* taskName, wchar_t * host, w
 		hr = SetUnlockTask(hr, pTriggerCollection, userID, delay); 
 	} 
 	else {
-		//MSVCRT$printf("[-] [%ls] is not a supported trigger type\n", triggerType); //DEBUG
 		goto cleanup;
 	}
 	
@@ -376,7 +371,7 @@ int go(char *args, int len) {
 	WCHAR *hostName  = L""; 
     WCHAR *programPath; 
     WCHAR *programArguments  = L""; 
-	CHAR *triggerType; //onetime, daily, logon , startup, lock, unlock
+	CHAR *triggerType; 
 	WCHAR *startTime; 
     WCHAR *expireTime = L""; 
 	int daysInterval = 0; 

BIN
KIT/AddTaskScheduler/addtaskscheduler.o


+ 7 - 2
KIT/EnumSecProducts/README.md

@@ -1,10 +1,15 @@
 # EnumSecProducts
-Get a list of security products (like AV/EDR) that are running on the system. This is done by comparing running processes against a hardcoded list of 130 security products.
+Get a list of security products like AV/EDR that are running on the current- or remote host. This is done by comparing running processes against a hardcoded list of 130 security products.
 
+## Arguments
+* `[hostname]`: The hostname/FQDN/IP of the remote host OR leave empty for the current system.\n\n" .
 
 ## Usage
-* `enumsecproducts`
+* `enumsecproducts <(optional) hostname>`
 
+## Examples
+* `enumsecproducts`
+* `enumsecproducts WS01.example.local`
 
 ## Compile
 - 1\. Make sure Visual Studio is installed and supports C/C++.

+ 57 - 48
KIT/EnumSecProducts/enumsecproducts.c

@@ -1,9 +1,7 @@
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-#include <ctype.h>
 #include <windows.h>
-#include <tlhelp32.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <wtsapi32.h>
 #include "enumsecproducts.h"
 #include "beacon.h"
 
@@ -15,7 +13,6 @@ typedef struct {
 } SoftwareData;
 
 
-
 //https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
 HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
 	HRESULT hr = S_FALSE;
@@ -29,7 +26,7 @@ HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
 		}
 	}
 
-	if (g_lpwPrintBuffer <= (LPWSTR)1) { 
+	if (g_lpwPrintBuffer <= (LPWSTR)1) {  
 		g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
 		if (g_lpwPrintBuffer == NULL) {
 			hr = E_FAIL;
@@ -89,6 +86,7 @@ VOID BeaconOutputStreamW() {
 	}
 
 CleanUp:
+
 	if (g_lpStream != NULL) {
 		g_lpStream->lpVtbl->Release(g_lpStream);
 		g_lpStream = NULL;
@@ -102,22 +100,32 @@ CleanUp:
 	if (lpwOutput != NULL) {
 		KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
 	}
+
 	return;
 }
 
 
 
-bool CheckSecProc() {
-    bool foundSecProduct = false;
-    HANDLE procHandle;
-    PROCESSENTRY32 pe32;
+
+void go(char *args, int len) {
+	CHAR *hostName = "";
+	HANDLE handleHost = NULL;
+    datap parser;
+	DWORD argSize = NULL;
+	WTS_PROCESS_INFOA * proc_info;
+	DWORD pi_count = 0;
+	LPSTR procName; 
+	bool foundSecProduct = false;
 	
+    BeaconDataParse(&parser, args, len);
+    hostName = BeaconDataExtract(&parser, &argSize);
+
 	//allocate memory for list
 	size_t numSoftware = 130; //130
     SoftwareData *softwareList = (SoftwareData *)KERNEL32$VirtualAlloc(NULL, numSoftware * sizeof(SoftwareData), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
-
     if (softwareList == NULL) {
-        return 1;
+		BeaconPrintf(CALLBACK_ERROR, "Failed to allocate memory for softwareList.\n");
+        return -1;
     }
 
     //Start security product list
@@ -642,51 +650,52 @@ bool CheckSecProc() {
 	softwareList[129].category = L"AV";
 	//End security product list
 
+	
+	//get handle to specified host
+	handleHost = WTSAPI32$WTSOpenServerA(hostName);
 
 	//get list of running processes 
-	procHandle = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
-    if (procHandle == INVALID_HANDLE_VALUE) {
-        return false;
-    }
-
-    pe32.dwSize = sizeof(PROCESSENTRY32);
-    if (!KERNEL32$Process32First(procHandle, &pe32)) {
-        KERNEL32$CloseHandle(procHandle);
-        return false;
-    }
+	if (!WTSAPI32$WTSEnumerateProcessesA(handleHost, 0, 1, &proc_info, &pi_count)) {
+		BeaconPrintf(CALLBACK_ERROR, "Failed to get a valid handle to the specified host.\n");
+		return -1;
+	}
 	
+	if(pi_count == 0) {
+		BeaconPrintf(CALLBACK_ERROR, "Couldn't list remote processes. Do you have enough privileges on the remote host?\n");
+		return -1;
+	}
+
 	//compare list with running processes
-	BeaconPrintToStreamW(L"\nDescription\t\t\t\t\tCategory\n");
-	BeaconPrintToStreamW(L"===============================================================\n");
-    do {
-        char procName[MAX_PATH];
-        MSVCRT$strcpy(procName, pe32.szExeFile);
-        for (size_t i = 0; procName[i]; i++) {
+	BeaconPrintToStreamW(L"Description\t\t\t\t\tCategory\n--------------------------------------------------------------\n");
+	for (int i = 0 ; i < pi_count ; i++ ) {
+		procName = proc_info[i].pProcessName;
+		
+		for (size_t i = 0; procName[i]; i++) {
             procName[i] = MSVCRT$tolower(procName[i]); 
         }
-
-        for (size_t i = 0; i < numSoftware; i++) {
-            if (MSVCRT$strcmp(procName, softwareList[i].filename) == 0) {
-                foundSecProduct = true;
-                BeaconPrintToStreamW(L"%-50ls\t%ls\n", softwareList[i].description, softwareList[i].category);
+		
+		for (size_t i = 0; i < numSoftware; i++) {
+			if (MSVCRT$strcmp(procName, softwareList[i].filename) == 0) {
+				BeaconPrintToStreamW(L"%-50ls\t%ls\n", softwareList[i].description, softwareList[i].category);
+				foundSecProduct = true;
                 break;
             }
-        }
-    } while (KERNEL32$Process32Next(procHandle, &pe32));
-
-    KERNEL32$CloseHandle(procHandle);
+		}
+		procName = NULL;
+	}
+	
+	if (foundSecProduct) {
+        BeaconOutputStreamW();
+		BeaconPrintf(CALLBACK_OUTPUT, "[+] Finished enumerating.\n");
+    } else {
+        BeaconPrintf(CALLBACK_ERROR, "No running security processes were found.\n");
+    }
+	
+	WTSAPI32$WTSCloseServer(handleHost);
 	KERNEL32$VirtualFree(softwareList, 0, MEM_RELEASE);
 
-    return foundSecProduct;
+    return 0;
 }
 
 
-int go() {
-    if (CheckSecProc()) {
-		BeaconOutputStreamW();
-        BeaconPrintf(CALLBACK_OUTPUT,"\n[+] Finished enumerating security products.\n");
-    } else {
-        BeaconPrintf(CALLBACK_OUTPUT,"\n[+] No security products from the list were found on the system!\n");
-    }
-    return 0;
-}
+

+ 15 - 7
KIT/EnumSecProducts/enumsecproducts.cna

@@ -1,18 +1,26 @@
 # author REDMED-X
 
 beacon_command_register(
-	"enumsecproducts", "List security products running on the system.",
-	"INFO:\nGet a list of security products (like AV/EDR) that are running on the system. This is done by comparing running processes against a hardcoded list of 130 security products.\n\n" .
-	"USAGE:\nenumsecproducts\n\n");
-	
+    "enumsecproducts", "List security products running on the current- or remote host.",
+    "INFO:\nGet a list of security products like AV/EDR that are running on the current- or remote host. This is done by comparing running processes against a hardcoded list of 130 security products.\n\n" .
+	"ARGUMENTS:\n[hostname]: The FQDN or IP of the remote host OR leave empty for the current system.\n\n" .
+    "USAGE:\nenumsecproducts <(optional) hostname>\n\n" .
+	"EXAMPLES:\nenumsecproducts \nenumsecproducts WS01.example.local\n\n");
+
+
 alias enumsecproducts {
     $bid = $1;
+    $remotehost = $2;
 
-    # Read in the right BOF file
+    # read in the right BOF file
     $handle = openf(script_resource("enumsecproducts.o"));
     $data = readb($handle, -1);
     closef($handle);
 
-	blog($bid, "Tasked to list running security products..");
-    beacon_inline_execute($bid, $data, "go", $null);
+    # pack our arguments
+    $arg_data = bof_pack($bid, "z", $remotehost);
+
+    blog($bid, "Tasked to list running security products..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
 }
+

+ 8 - 10
KIT/EnumSecProducts/enumsecproducts.h

@@ -1,16 +1,17 @@
-#include <windows.h>  
+#include <windows.h>
 
 //CheckSecProc
 DECLSPEC_IMPORT void * WINAPI KERNEL32$VirtualAlloc (LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
 DECLSPEC_IMPORT int WINAPI KERNEL32$VirtualFree (LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
-DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateToolhelp32Snapshot(DWORD, DWORD th32ProcessID);
-DECLSPEC_IMPORT BOOL WINAPI KERNEL32$Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
-DECLSPEC_IMPORT BOOL WINAPI KERNEL32$Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
-DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject);
-DECLSPEC_IMPORT char* __cdecl MSVCRT$strcpy(char* _Dest, const char* _Source);
-DECLSPEC_IMPORT int __cdecl MSVCRT$tolower(int _C);
+WINBASEAPI char* __cdecl MSVCRT$strcpy(char* _Dest, const char* _Source);
+WINBASEAPI int __cdecl MSVCRT$tolower(int _C);
 WINBASEAPI int __cdecl MSVCRT$strcmp(const char *str1, const char *str2);
 WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...);
+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 DWORD WINAPI KERNEL32$GetLastError(void);
+
 
 //BeaconPrintToStreamW + BeaconOutputStreamW
 #define MAX_STRING 8192
@@ -26,8 +27,5 @@ 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);
-
-
 
 

BIN
KIT/EnumSecProducts/enumsecproducts.o


+ 6 - 6
KIT/PSremote/bofcompile.bat

@@ -1,6 +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
-
+@ECHO OFF
+
+cl.exe /nologo /c /Od /MT /W0 /GS- /Tc psremote.c
+move /y psremote.obj psremote.o
+
+

+ 149 - 149
KIT/PSremote/psremote.c

@@ -1,150 +1,150 @@
-#include <windows.h>
-#include <stdio.h>
-#include <wtsapi32.h>
-#include "beacon.h"
-#include "psremote.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)); 
-	}
-
-	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 ListProcesses(HANDLE handleTargetHost) {
-
-	WTS_PROCESS_INFOA * proc_info;
-	DWORD pi_count = 0;
-	LPSTR procName; 
-	WCHAR WCprocName[256];
-	BOOL RemoteProc = FALSE;
-	
-	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 RemoteProc;
-	}
-	
-	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);
-		RemoteProc = TRUE;
-	}
-	WTSAPI32$WTSCloseServer(handleTargetHost);
-	return RemoteProc;
-}
-
-void go(char *args, int len) {
-	
-	CHAR *hostName;
-	datap parser;
-	DWORD argSize = NULL;
-	HANDLE handleTargetHost = NULL;
-	BOOL res = NULL;
-
-	BeaconDataParse(&parser, args, len);
-    hostName = BeaconDataExtract(&parser, &argSize);
-
-	handleTargetHost = WTSAPI32$WTSOpenServerA(hostName);
-	res = ListProcesses(handleTargetHost);
-	
-	if(!res) {
-		BeaconPrintf(CALLBACK_ERROR, "[-] Couldn't list remote processes. Do you have enough privileges on the remote host?\n");
-		return 0;
-	}
-	else  {
-		BeaconOutputStreamW();
-		BeaconPrintf(CALLBACK_OUTPUT, "[+] DONE");
-	}
-
-	return 0;
+#include <windows.h>
+#include <stdio.h>
+#include <wtsapi32.h>
+#include "beacon.h"
+#include "psremote.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)); 
+	}
+
+	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 ListProcesses(HANDLE handleTargetHost) {
+
+	WTS_PROCESS_INFOA * proc_info;
+	DWORD pi_count = 0;
+	LPSTR procName; 
+	WCHAR WCprocName[256];
+	BOOL RemoteProc = FALSE;
+	
+	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 RemoteProc;
+	}
+	
+	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);
+		RemoteProc = TRUE;
+	}
+	WTSAPI32$WTSCloseServer(handleTargetHost);
+	return RemoteProc;
+}
+
+void go(char *args, int len) {
+	
+	CHAR *hostName;
+	datap parser;
+	DWORD argSize = NULL;
+	HANDLE handleTargetHost = NULL;
+	BOOL res = NULL;
+
+	BeaconDataParse(&parser, args, len);
+    hostName = BeaconDataExtract(&parser, &argSize);
+
+	handleTargetHost = WTSAPI32$WTSOpenServerA(hostName);
+	res = ListProcesses(handleTargetHost);
+	
+	if(!res) {
+		BeaconPrintf(CALLBACK_ERROR, "[-] Couldn't list remote processes. Do you have enough privileges on the remote host?\n");
+		return 0;
+	}
+	else  {
+		BeaconOutputStreamW();
+		BeaconPrintf(CALLBACK_OUTPUT, "[+] Finished enumerating.");
+	}
+
+	return 0;
 }

+ 24 - 29
KIT/PSremote/psremote.cna

@@ -1,29 +1,24 @@
-# author REDMED-X
-
-beacon_command_register(
-    "psremote", "List all running processes on a remote host.",
-    "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 {
-    $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($bid, "z", $remotehost);
-
-    blog($bid, "Tasked to list processes of host: $+  $remotehost");
-    beacon_inline_execute($bid, $data, "go", $arg_data);
-}
-
+# author REDMED-X
+
+beacon_command_register(
+    "psremote", "List all running processes on a remote host.",
+    "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 {
+    $bid = $1;
+    $remotehost = $2;
+
+    # 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($bid, "z", $remotehost);
+
+    blog($bid, "Tasked to list running processes..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}
+

BIN
KIT/PSremote/psremote.o