unknown před 2 roky
rodič
revize
667ac51dcb

+ 22 - 0
KIT/EnumShares/README.md

@@ -0,0 +1,22 @@
+# EnumShares
+List remote shares and there access level using a list with predefined hostnames or IP addresses. The list is loaded from your own attacker system.
+
+>A valid list with hostnames is considered newline separated and ends with a newline. Furthermore, the following hostname notations are correct: `database`, `database.example.local`, `10.100.10.1`.  
+
+## Arguments
+* `<path to file>`: the path on your own attacker system to the file containing the list with predefined hostnames.
+
+
+## Usage
+* `enumshares <path to hostname file> `
+
+
+## Examples
+* `enumshares C:\Users\RTO\Documents\hostnames.txt`
+
+
+## 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/EnumShares/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/EnumShares/bofcompile.bat

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

+ 204 - 0
KIT/EnumShares/enumshares.c

@@ -0,0 +1,204 @@
+#include <stdio.h>
+#include <Windows.h>
+#include <Lm.h>
+#include "enumshares.h"
+#include "beacon.h"
+
+#pragma comment(lib, "Netapi32.lib")
+
+
+
+
+
+//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;
+}
+
+
+
+
+PSHARE_INFO_1 listShares(wchar_t *servername) {
+    PSHARE_INFO_1 pShareInfo = NULL;
+    DWORD dwEntriesRead = 0, dwTotalEntries = 0, dwResumeHandle = 0;
+    NET_API_STATUS nStatus;
+
+    BeaconPrintToStreamW(L"\nListing shares for: %ls\n", servername);
+    BeaconPrintToStreamW(L"=====================================================\n");
+	
+    do {
+        nStatus = NETAPI32$NetShareEnum(servername, 1, (LPBYTE*)&pShareInfo, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, &dwResumeHandle);
+		
+		
+        if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) {
+            for (DWORD i = 0; i < dwEntriesRead; i++) {
+                BeaconPrintToStreamW(L"Share Name: %-10ls <- ", pShareInfo[i].shi1_netname);
+				
+				if (KERNEL32$lstrcmpW(pShareInfo[i].shi1_netname, L"IPC$") == 0) {
+                    BeaconPrintToStreamW(L"[!] No file system access\n");
+                    continue;
+                }
+				
+                USE_INFO_2 useInfo = { 0 };
+                wchar_t fullPath[260];
+                MSVCRT$_snwprintf(fullPath, sizeof(fullPath) / sizeof(wchar_t) - 1, L"\\\\%s\\%s", servername ? servername : L"localhost", pShareInfo[i].shi1_netname);
+                
+                useInfo.ui2_remote = fullPath;
+                useInfo.ui2_asg_type = USE_DISKDEV; 
+                useInfo.ui2_username = NULL; // Use current user's credentials
+                useInfo.ui2_password = L"";
+				
+                nStatus = NETAPI32$NetUseAdd(NULL, 2, (LPBYTE)&useInfo, NULL);
+                if (nStatus == NERR_Success) {
+                    BeaconPrintToStreamW(L"[+] Accessible\n");
+                    NETAPI32$NetUseDel(NULL, fullPath, USE_LOTS_OF_FORCE);
+                } else {
+                    BeaconPrintToStreamW(L"[-] Error access denied\n");
+                }
+				
+            }
+			
+            NETAPI32$NetApiBufferFree(pShareInfo);
+            pShareInfo = NULL;
+        } else {
+            if (nStatus == ERROR_BAD_NETPATH) {
+                BeaconPrintToStreamW(L"Connection error: ERROR_BAD_NETPATH\n");
+			} else if (nStatus == ERROR_ACCESS_DENIED) {
+                BeaconPrintToStreamW(L"Connection error: ERROR_ACCESS_DENIED\n");
+            } else {
+                BeaconPrintToStreamW(L"Connection error code: %d\n", nStatus);
+            }
+            break;
+        }
+		
+    } while (nStatus == ERROR_MORE_DATA);
+	
+	return pShareInfo;
+}
+
+int go(char *args, int len) {
+	char* hostname;
+	char* nextHostname;
+    int iBytesLen = 0;
+    CHAR *hostFileBytes;
+	WCHAR wHostname[MAX_PATH];
+    datap parser;
+	
+    BeaconDataParse(&parser, args, len);
+    hostFileBytes = BeaconDataExtract(&parser, &iBytesLen);
+
+	if(iBytesLen != 0) {
+        BeaconPrintf(CALLBACK_OUTPUT, "[+] Loaded hostname file in memory with a size of %d bytes\n[*] Start share enumeration..\n", iBytesLen); 
+		
+        hostname = MSVCRT$strtok(hostFileBytes, "\r\n");
+        while (hostname != NULL) {
+			nextHostname = MSVCRT$strtok(NULL, "\r\n");
+            if (nextHostname == NULL) {
+                break;
+            }
+			
+			KERNEL32$MultiByteToWideChar(CP_ACP, 0, hostname, -1, wHostname, MAX_PATH);
+			PSHARE_INFO_1 pShareInfo = listShares(wHostname);
+            hostname = nextHostname;
+			
+			BeaconOutputStreamW();
+			NETAPI32$NetApiBufferFree(pShareInfo);
+			
+        }
+		
+		BeaconPrintf(CALLBACK_OUTPUT, "[+] Done!\n"); 
+		
+    } else {
+        BeaconPrintf(CALLBACK_ERROR, "Couldn't load the host file from disk.\n");
+    }
+	
+    return 0;
+}
+
+
+
+

+ 36 - 0
KIT/EnumShares/enumshares.cna

@@ -0,0 +1,36 @@
+# author REDMED-X
+
+beacon_command_register(
+	"enumshares", "List remote shares and there access level using a predefined list with hostnames.",
+	"INFO:\nList remote shares and there access level based on a list with predefined hostnames or IP addresses. The list is loaded from your own attacker system.\n\n" .
+	"ARGUMENTS:\n[<path to file>]: the path on your own attacker system to the file containing the list with predefined hostnames. Each hostname must be newline separated.\n\n" .
+	"USAGE:\nenumshares <path to hostname file>\n\n" .
+	"EXAMPLES:\nenumshares C:\\Users\\RTO\\Documents\\hostnames.txt\n\n");
+	
+alias enumshares {
+    $bid = $1;
+	$path = $2;
+	
+	if ($path eq "") {
+		berror($bid, "Please specify the path on your own attacker system to the file containing the list with newline separated hostnames.\n");
+		return;
+	}
+
+	# read in the .txt file
+	$handle = openf("$path");
+	$file = readb($handle, -1);
+	closef($handle);
+	
+	blog($bid, "path: $+  $path");
+	
+    # Read in the right BOF file
+    $handle = openf(script_resource("enumshares.o"));
+    $data = readb($handle, -1);
+    closef($handle);
+
+	# Pack our arguments
+    $arg_data = bof_pack($bid, "b", $file);
+
+	blog($bid, "Tasked to enumerate remote shares..");
+    beacon_inline_execute($bid, $data, "go", $arg_data);
+}

+ 34 - 0
KIT/EnumShares/enumshares.h

@@ -0,0 +1,34 @@
+#include <windows.h>  
+
+//Go
+DECLSPEC_IMPORT char* __cdecl MSVCRT$strtok(char* _String, const char* _Delimiters);
+
+//listShares
+WINBASEAPI int __cdecl MSVCRT$printf(const char * _Format,...);
+DECLSPEC_IMPORT NET_API_STATUS NET_API_FUNCTION NETAPI32$NetShareEnum(LMSTR servername, DWORD level, LPBYTE *bufptr, DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle);
+DECLSPEC_IMPORT NET_API_STATUS NET_API_FUNCTION NETAPI32$NetUseAdd(LMSTR uncname, DWORD level, LPBYTE buf, LPDWORD parm_err);
+DECLSPEC_IMPORT NET_API_STATUS NET_API_FUNCTION NETAPI32$NetApiBufferFree(LPVOID Buffer);
+DECLSPEC_IMPORT NET_API_STATUS NET_API_FUNCTION NETAPI32$NetUseDel(LMSTR uncname, LMSTR use_name, DWORD force_cond);
+WINBASEAPI int __cdecl MSVCRT$_snwprintf(wchar_t *buffer, size_t count, const wchar_t *format, ...);
+WINBASEAPI int WINAPI KERNEL32$lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2);
+
+
+//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);
+
+
+
+

binární
KIT/EnumShares/enumshares.o


+ 3 - 3
KIT/FindWebClient/README.md

@@ -1,5 +1,5 @@
 # FindWebClient
-Find hosts with the WebClient service running based on a list with predefined hostnames or IP addresses. The list is loaded from your own attacker system.
+Find hosts with the WebClient service running using a list with predefined hostnames or IP addresses. The list is loaded from your own attacker system.
 
 >A valid list with hostnames is considered newline separated and ends with a newline. Furthermore, the following hostname notations are correct: `database`, `database.example.local`, `10.100.10.1`.  
 
@@ -13,8 +13,8 @@ Find hosts with the WebClient service running based on a list with predefined ho
 
 
 ## Examples
-* `findwebclient C:\Users\redmed\Documents\hostnames.txt`
-* `findwebclient C:\\Users\\redmed\\Documents\\hostnames.txt debug`
+* `findwebclient C:\Users\RTO\Documents\hostnames.txt`
+* `findwebclient C:\\Users\RTO\Documents\hostnames.txt debug`
 
 
 ## Compile

+ 1 - 0
README.md

@@ -16,6 +16,7 @@ The following tools are currently in the operators' kit:
 |**[DllEnvHijacking](KIT/DllEnvHijacking)**|BOF implementation of DLL environment hijacking published by [Wietze](https://www.wietzebeukema.nl/blog/save-the-environment-variables).|
 |**[EnumLocalCert](KIT/EnumLocalCert)**|List all local computer certificates from a specific store.|
 |**[EnumSecProducts](KIT/EnumSecProducts)**|List security products (like AV/EDR) that are running on the system.|
+|**[EnumShares](KIT/EnumShares)**|List remote shares and there access level using a predefined list with hostnames.|
 |**[EnumTaskScheduler](KIT/EnumTaskScheduler)**|Enumerate and list all the scheduled tasks in the root folder.|
 |**[FindDotnet](KIT/FindDotnet)**|Find processes that most likely have .NET loaded.|
 |**[FindHandle](KIT/FindHandle)**|Find "process" and "thread" handle types between processes.|