├── .gitattributes ├── GetWebDAVStatus_BOF ├── GetWebDAVStatus.cna ├── GetWebDAVStatus.x64.o ├── GetWebDAVStatus.x86.o ├── GetWebDavStatus-Checksum.txt └── Source │ ├── GetWebDAVStatus.c │ ├── Makefile │ └── beacon.h ├── GetWebDAVStatus_DotNet ├── GetWebDAVStatus.sln └── GetWebDAVStatus │ ├── App.config │ ├── GetWebDAVStatus.csproj │ ├── Program.cs │ └── Properties │ └── AssemblyInfo.cs └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /GetWebDAVStatus_BOF/GetWebDAVStatus.cna: -------------------------------------------------------------------------------- 1 | #GetWebDAVStatus 2 | #CNA author @nickvourd 3 | 4 | beacon_command_register("GetWebDAVStatus", "Determine if the WebClient Service (WebDAV) is running on a remote system.", "Synopsis: GetWebDAVStatus \n\n"); 5 | 6 | alias GetWebDAVStatus { 7 | $bid = $1; 8 | 9 | $input = substr($0, 16); 10 | @args = split(' ', $input); 11 | 12 | $target = @args[0]; 13 | 14 | if ($target eq "") { 15 | berror($bid, "Specify an ip or hostname"); 16 | return; 17 | } 18 | 19 | # Read in the right BOF file 20 | $handle = openf(script_resource("GetWebDAVStatus." . barch($bid) . ".o")); 21 | $data = readb($handle, -1); 22 | closef($handle); 23 | 24 | # Pack our arguments 25 | $arg_data = bof_pack($bid, "Z", $target); 26 | btask($bid, "GetWebDAVStatus BOF by @G0ldenGunSec && @nickvourd"); 27 | 28 | beacon_inline_execute($bid, $data, "go", $arg_data); 29 | } 30 | -------------------------------------------------------------------------------- /GetWebDAVStatus_BOF/GetWebDAVStatus.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickvourd/GetWebDAVStatus/6917facf6cb8d475bea0a6ae392d4c4550c4f291/GetWebDAVStatus_BOF/GetWebDAVStatus.x64.o -------------------------------------------------------------------------------- /GetWebDAVStatus_BOF/GetWebDAVStatus.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickvourd/GetWebDAVStatus/6917facf6cb8d475bea0a6ae392d4c4550c4f291/GetWebDAVStatus_BOF/GetWebDAVStatus.x86.o -------------------------------------------------------------------------------- /GetWebDAVStatus_BOF/GetWebDavStatus-Checksum.txt: -------------------------------------------------------------------------------- 1 | GetWebDAVStatus.x64.o B8ED7B5C95EC7511D4CE307550BA0305 2 | GetWebDAVStatus.x86.o 49C859A3FF0D7E18E01576075A934899 -------------------------------------------------------------------------------- /GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "beacon.h" 4 | 5 | WINBASEAPI BOOL WINAPI KERNEL32$WaitNamedPipeW(LPCWSTR lpNamedPipeName, DWORD nTimeOut); 6 | WINBASEAPI void* WINAPI MSVCRT$malloc(size_t); 7 | WINBASEAPI size_t WINAPI MSVCRT$wcslen(const wchar_t* str); 8 | WINBASEAPI wchar_t* WINAPI MSVCRT$wcscpy(wchar_t* dest, const wchar_t* source); 9 | WINBASEAPI wchar_t* WINAPI MSVCRT$wcscat(wchar_t* dest, const wchar_t* source); 10 | WINBASEAPI void WINAPI MSVCRT$free(void*); 11 | 12 | void go(char* args, int length) 13 | { 14 | wchar_t* host; 15 | datap parser; 16 | BeaconDataParse(&parser, args, length); 17 | host = (wchar_t*)BeaconDataExtract(&parser, NULL); 18 | //BeaconPrintf(CALLBACK_OUTPUT, "Value of host: %S", host); 19 | 20 | wchar_t* pipeNameHead = L"\\\\"; 21 | wchar_t* pipeNameTail = L"\\pipe\\DAV RPC SERVICE"; 22 | BOOL pipeStatus = 0; 23 | 24 | wchar_t* fullPipeName = (wchar_t*)MSVCRT$malloc((MSVCRT$wcslen(host) + MSVCRT$wcslen(pipeNameHead) + MSVCRT$wcslen(pipeNameTail) + 1) * sizeof(wchar_t)); 25 | MSVCRT$wcscpy(fullPipeName, pipeNameHead); 26 | MSVCRT$wcscat(fullPipeName, host); 27 | MSVCRT$wcscat(fullPipeName, pipeNameTail); 28 | 29 | pipeStatus = KERNEL32$WaitNamedPipeW(fullPipeName, 3000); 30 | if (pipeStatus == 0) 31 | { 32 | BeaconPrintf(CALLBACK_ERROR, "[x] Unable to hit DAV pipe on %S, system is either unreachable or does not have WebClient service running", host); 33 | } 34 | else 35 | { 36 | BeaconPrintf(CALLBACK_OUTPUT, "[+] WebClient service is active on %S", host); 37 | } 38 | MSVCRT$free((void*)fullPipeName); 39 | } 40 | -------------------------------------------------------------------------------- /GetWebDAVStatus_BOF/Source/Makefile: -------------------------------------------------------------------------------- 1 | SRC = $(wildcard *.c) 2 | OBJS = $(patsubst %.c, %.o, $(SRC)) 3 | CC_x86 := i686-w64-mingw32-gcc 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | STRIP_x86 := i686-w64-mingw32-strip 6 | STRIP_x64 := x86_64-w64-mingw32-strip 7 | CFLAGS := -masm=intel 8 | 9 | all: $(OBJS) 10 | 11 | %.o: %.c 12 | $(CC_x64) $(CFLAGS) -o ../$*.x64.o -c $< 13 | $(STRIP_x64) --strip-unneeded ../$*.x64.o 14 | 15 | $(CC_x86) $(CFLAGS) -o ../$*.x86.o -DWOW64 -fno-leading-underscore -c $< 16 | $(STRIP_x86) --strip-unneeded ../$*.x86.o 17 | 18 | clean: 19 | rm ../*.o 20 | -------------------------------------------------------------------------------- /GetWebDAVStatus_BOF/Source/beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Cobalt Strike 4.1. 8 | */ 9 | 10 | /* data API */ 11 | typedef struct { 12 | char * original; /* the original buffer [so we can free it] */ 13 | char * buffer; /* current pointer into our buffer */ 14 | int length; /* remaining length of data */ 15 | int size; /* total size of this buffer */ 16 | } datap; 17 | 18 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 19 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 20 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 21 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 22 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 23 | 24 | /* format API */ 25 | typedef struct { 26 | char * original; /* the original buffer [so we can free it] */ 27 | char * buffer; /* current pointer into our buffer */ 28 | int length; /* remaining length of data */ 29 | int size; /* total size of this buffer */ 30 | } formatp; 31 | 32 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 33 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 34 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 35 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); 36 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); 37 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 38 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 39 | 40 | /* Output Functions */ 41 | #define CALLBACK_OUTPUT 0x0 42 | #define CALLBACK_OUTPUT_OEM 0x1e 43 | #define CALLBACK_ERROR 0x0d 44 | #define CALLBACK_OUTPUT_UTF8 0x20 45 | 46 | DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); 47 | DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); 48 | 49 | /* Token Functions */ 50 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 51 | DECLSPEC_IMPORT void BeaconRevertToken(); 52 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 53 | 54 | /* Spawn+Inject Functions */ 55 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 56 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 57 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 58 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 59 | 60 | /* Utility Functions */ 61 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 62 | -------------------------------------------------------------------------------- /GetWebDAVStatus_DotNet/GetWebDAVStatus.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31624.102 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GetWebDAVStatus", "GetWebDAVStatus\GetWebDAVStatus.csproj", "{89901571-47FB-4237-9ED7-DE025913641C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Release|Any CPU = Release|Any CPU 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {89901571-47FB-4237-9ED7-DE025913641C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {89901571-47FB-4237-9ED7-DE025913641C}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {89901571-47FB-4237-9ED7-DE025913641C}.Debug|x64.ActiveCfg = Debug|x64 19 | {89901571-47FB-4237-9ED7-DE025913641C}.Debug|x64.Build.0 = Debug|x64 20 | {89901571-47FB-4237-9ED7-DE025913641C}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {89901571-47FB-4237-9ED7-DE025913641C}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {89901571-47FB-4237-9ED7-DE025913641C}.Release|x64.ActiveCfg = Release|x64 23 | {89901571-47FB-4237-9ED7-DE025913641C}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {D08EC449-D284-4D38-A84F-8BB39A9BCAA7} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /GetWebDAVStatus_DotNet/GetWebDAVStatus/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /GetWebDAVStatus_DotNet/GetWebDAVStatus/GetWebDAVStatus.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {89901571-47FB-4237-9ED7-DE025913641C} 8 | Exe 9 | GetWebDAVStatus 10 | GetWebDAVStatus 11 | v4.5 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | true 36 | bin\x64\Debug\ 37 | DEBUG;TRACE 38 | full 39 | x64 40 | 7.3 41 | prompt 42 | true 43 | 44 | 45 | bin\x64\Release\ 46 | TRACE 47 | true 48 | pdbonly 49 | x64 50 | 7.3 51 | prompt 52 | true 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /GetWebDAVStatus_DotNet/GetWebDAVStatus/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Threading.Tasks; 6 | 7 | namespace GetWebDAVStatus 8 | { 9 | class Program 10 | { 11 | [DllImport("kernel32.dll", SetLastError = true)] 12 | [return: MarshalAs(UnmanagedType.Bool)] 13 | static extern bool WaitNamedPipeA(string lpNamedPipeName, uint nTimeOut); 14 | 15 | static void Main(string[] args) 16 | { 17 | int threadCount = 5; 18 | int targetIndex; 19 | List targetHosts; 20 | 21 | if (args.Length == 0) 22 | { 23 | Console.WriteLine("[X] Error: Provide target host(s) on the command line. If providing multiple targets, include as a comma seperated list"); 24 | return; 25 | } 26 | 27 | try 28 | { 29 | int tcIndex = Array.FindIndex(args, x => x.Equals("--tc", StringComparison.OrdinalIgnoreCase)); 30 | if (tcIndex >= 0) 31 | { 32 | threadCount = Int32.Parse(args[tcIndex + 1]); 33 | tcIndex = tcIndex * 2; 34 | } 35 | targetIndex = ((args.Length - 1) * args.Length / 2) - tcIndex - 1; 36 | targetHosts = args[targetIndex].Split(',').ToList(); 37 | } 38 | catch (Exception e) 39 | { 40 | Console.WriteLine("[X] Error parsing arguments, please check command line and try again"); 41 | Console.WriteLine(e.Message); 42 | return; 43 | } 44 | 45 | Parallel.ForEach(targetHosts, new ParallelOptions { MaxDegreeOfParallelism = threadCount }, singleTarget => 46 | { 47 | string pipename = @"\\" + singleTarget + @"\pipe\DAV RPC SERVICE"; 48 | //timeout is a somewhat arbitrary value, as if named pipe does not exist the function returns immediately. 49 | bool davActive = WaitNamedPipeA(pipename, 3000); 50 | if (davActive) 51 | { 52 | Console.WriteLine("[+] WebClient service is active on " + singleTarget); 53 | } 54 | else 55 | { 56 | Console.WriteLine("[x] Unable to reach DAV pipe on {0}, system is either unreachable or does not have WebClient service running", singleTarget); 57 | } 58 | }); 59 | return; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /GetWebDAVStatus_DotNet/GetWebDAVStatus/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GetWebDAVStatus")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GetWebDAVStatus")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("89901571-47fb-4237-9ed7-de025913641c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GetWebDAVStatus 2 | Small project to determine if the Web Client service (WebDAV) is running on a remote system by checking for the presence of the DAV RPC SERVICE named pipe. Does not require admin privileges on the remote system, but does require some form of valid credentials (no anonymous access). Both a BOF and C# version of the project are included, the C# version is multi-threaded so would be better suited for scanning a large number of systems. 3 | 4 | ## Usage 5 | The C# versions take a comma-seperated list of systems to scan. The C# version also has an optional arg of "--tc" that allows the operator to control the max amount of threads to be used (default: 5). The BOF vesrion take only one argument. 6 | 7 | BOF: `GetWebDAVStatus server01` 8 | 9 | C#: `execute-assembly C:\assemblies\GetWebDAVStatus.exe server01,server02 --tc 1` 10 | 11 | ## Building 12 | The C# project should be a pretty standard build, x64 + Release is the recommended build configuration. BOF can be built with the following command from the Makefile: 13 | 14 | `make` 15 | 16 | Prerequisites for compiling the BOF: 17 | - i686-w64-mingw32-gcc 18 | - x86_64-w64-mingw32-gcc 19 | 20 | ## Credits 21 | [@tifkin_](https://twitter.com/tifkin_) originally posted about this method of remotely identifying WebDAV [here](https://twitter.com/tifkin_/status/1419806476353298442). 22 | 23 | Special thanks to [@nickvourd](https://twitter.com/nickvourd) for his contributions. 24 | 25 | Originally heard about the above tweet on [@flangvik](https://twitter.com/Flangvik)'s [twitch stream](https://www.twitch.tv/flangvik). Would definitely recommend checking out. 26 | --------------------------------------------------------------------------------