From 3b4c37d852eba6b9ac04a884d58f4b22ed8af4ae Mon Sep 17 00:00:00 2001 From: Nikos Vourdas <32869078+nickvourd@users.noreply.github.com> Date: Tue, 20 Feb 2024 00:07:51 +0200 Subject: [PATCH 01/12] Create Makefile --- GetWebDAVStatus_BOF/src/Makefile | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 GetWebDAVStatus_BOF/src/Makefile diff --git a/GetWebDAVStatus_BOF/src/Makefile b/GetWebDAVStatus_BOF/src/Makefile new file mode 100644 index 0000000..6bc9e4a --- /dev/null +++ b/GetWebDAVStatus_BOF/src/Makefile @@ -0,0 +1,19 @@ +SRC = $(wildcard *.c) +OBJS = $(patsubst %.c, %.o, $(SRC)) +CC_x86 := i686-w64-mingw32-gcc +CC_x64 := x86_64-w64-mingw32-gcc +STRIP_x86 := i686-w64-mingw32-strip +STRIP_x64 := x86_64-w64-mingw32-strip +CFLAGS := -masm=intel + +all: $(OBJS) + +%.o: %.c + $(CC_x64) $(CFLAGS) -o ../$*.x64.o -c $< + $(STRIP_x64) --strip-unneeded ../$*.x64.o + + $(CC_x86) $(CFLAGS) -o ../$*.x86.o -DWOW64 -fno-leading-underscore -c $< + $(STRIP_x86) --strip-unneeded ../$*.x86.o + +clean: + rm ../*.o From 0e6bf5486c2c622df1285eeb3e36ab07a070c7f6 Mon Sep 17 00:00:00 2001 From: Nikos Vourdas <32869078+nickvourd@users.noreply.github.com> Date: Tue, 20 Feb 2024 00:08:20 +0200 Subject: [PATCH 02/12] Rename Source.c to GetWebDAVStatus.c --- GetWebDAVStatus_BOF/src/{Source.c => GetWebDAVStatus.c} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename GetWebDAVStatus_BOF/src/{Source.c => GetWebDAVStatus.c} (99%) diff --git a/GetWebDAVStatus_BOF/src/Source.c b/GetWebDAVStatus_BOF/src/GetWebDAVStatus.c similarity index 99% rename from GetWebDAVStatus_BOF/src/Source.c rename to GetWebDAVStatus_BOF/src/GetWebDAVStatus.c index a75517e..e5e8451 100644 --- a/GetWebDAVStatus_BOF/src/Source.c +++ b/GetWebDAVStatus_BOF/src/GetWebDAVStatus.c @@ -35,4 +35,4 @@ void go(char* args, int length) MSVCRT$free((void*)fullPipeName); singleHost = MSVCRT$strtok(NULL, ","); } -} \ No newline at end of file +} From e56293515003fe9380138b28dd818d5fee50b60c Mon Sep 17 00:00:00 2001 From: Nikos Vourdas <32869078+nickvourd@users.noreply.github.com> Date: Tue, 20 Feb 2024 00:10:12 +0200 Subject: [PATCH 03/12] Create GetWebDAVStatus.cna --- GetWebDAVStatus_BOF/GetWebDAVStatus.cna | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 GetWebDAVStatus_BOF/GetWebDAVStatus.cna diff --git a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna new file mode 100644 index 0000000..b2b4014 --- /dev/null +++ b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna @@ -0,0 +1,28 @@ +#GetWebDAVStatus +#CNA author @nickvourd + +beacon_command_register("GetWebDAVStatus", "Determine if the WebClient Service (WebDAV) is running on a remote system.", "Synopsis: GetWebDAVStatus \n\n"); + +alias GetWebDAVStatus { + $bid = $1; + + $input = substr($0, 16); + @args = split(' ', $input); + + $target = @args[0]; + + if ($target eq "") { + berror($bid, "Specify an ip or hostname"); + return; + } + + # Read in the right BOF file + $handle = openf(script_resource("GetWebDAVStatus." . barch($bid) . ".o")); + $data = readb($handle, -1); + closef($handle); + + # Pack our arguments + $arg_data = bof_pack($bid, "Z", $target); + + beacon_inline_execute($bid, $data, "go", $arg_data); +} From 9dba98003e5db79c70e5155c3a9135363b18bd1e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Feb 2024 00:14:55 +0200 Subject: [PATCH 04/12] Rename src to Source --- GetWebDAVStatus_BOF/{src => Source}/GetWebDAVStatus.c | 0 GetWebDAVStatus_BOF/{src => Source}/Makefile | 0 GetWebDAVStatus_BOF/{src => Source}/beacon.h | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename GetWebDAVStatus_BOF/{src => Source}/GetWebDAVStatus.c (100%) rename GetWebDAVStatus_BOF/{src => Source}/Makefile (100%) rename GetWebDAVStatus_BOF/{src => Source}/beacon.h (100%) diff --git a/GetWebDAVStatus_BOF/src/GetWebDAVStatus.c b/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c similarity index 100% rename from GetWebDAVStatus_BOF/src/GetWebDAVStatus.c rename to GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c diff --git a/GetWebDAVStatus_BOF/src/Makefile b/GetWebDAVStatus_BOF/Source/Makefile similarity index 100% rename from GetWebDAVStatus_BOF/src/Makefile rename to GetWebDAVStatus_BOF/Source/Makefile diff --git a/GetWebDAVStatus_BOF/src/beacon.h b/GetWebDAVStatus_BOF/Source/beacon.h similarity index 100% rename from GetWebDAVStatus_BOF/src/beacon.h rename to GetWebDAVStatus_BOF/Source/beacon.h From fe5b719a3ceaf50120f42a5ebde481e4f9aab31c Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 10 Mar 2024 00:28:33 +0200 Subject: [PATCH 05/12] Edit SOURCE and CNA --- GetWebDAVStatus_BOF/GetWebDAVStatus.cna | 1 + GetWebDAVStatus_BOF/GetWebDAVStatus_x64.o | Bin 2185 -> 0 bytes GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c | 59 ++++++++++--------- 3 files changed, 31 insertions(+), 29 deletions(-) delete mode 100644 GetWebDAVStatus_BOF/GetWebDAVStatus_x64.o diff --git a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna index b2b4014..a0421b8 100644 --- a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna +++ b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna @@ -23,6 +23,7 @@ alias GetWebDAVStatus { # Pack our arguments $arg_data = bof_pack($bid, "Z", $target); + btask($bid, "GetWebDAVStatus BOF by @G0ldenGunSec & @nickvourd"); beacon_inline_execute($bid, $data, "go", $arg_data); } diff --git a/GetWebDAVStatus_BOF/GetWebDAVStatus_x64.o b/GetWebDAVStatus_BOF/GetWebDAVStatus_x64.o deleted file mode 100644 index f61b00464135b180d5b1cfb5e9c97bc4d343b93d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2185 zcma)7O>7%Q6n@)vnovlc(jO#B%TN}{RU_jzB}qdBPHdBna1twa52Z}yN>^Q;7L34&G)`} z^JeGIxZDjtS94mn3*brcEowMi7aKfi!Xkoxsoo0eeSHu$_;O`c$<{reBG_)z#i4IJ zD)^>QN>*Jrikj1V07|mY9K?!2=0bGS(1cc30rVg|6>78z#UU1tmRofXAwPh+=L0Q; z^>nQ=_!9ZWj(C|HQN6J44xUA?Z^Kv}#sAS_`!Gkwo=&D-7@JGy(v#yOCn^=wh!)M| z6aS0GE{UmJn|3ChoF1D>Wlu25>u>x%#P1c54$$CtRg;_FRH?38cuuEmL$Q{_uDShg8TIo@@{w%0F-fvR3lge-tj^9cuj3%J&9QLYe zS}E6jh|-9<^@b9G@Y}zU1bvZ)Po?&7&_<}L@@=*H6^)P~SG?iMs5?nXQmeNcy<=)M zhnb)*R@dclxYl;OseS$0gMJEu9*1F=9D~Y{bd@soCou4>AMTGs_hXylwdpDC$nU+i zT20;hrtozi&i5#OA$SZ+`a%%H@|cI7#WL)n1uSV(hhTLVy|s(pM}%3U_cJVeJ#-z* z{T}*m7u`dIyB2k{ua0}@A1oj6P&XdJ$2}BAyvmsz%81r6hNj_Fh^3%9$M+pWR1kKVi&{%JjY{M;vN6Y8DtowY7w z;U)L#%X7WofBfUjmj2hJyGNe;cYo&452Np13nl|`9nVVCG_F)aQmsb+A-=*j5sk&( z1L;!0Y}mzU$pHF|KGS^Z5-Uq|?Y3I;g}Vn`vP4&It2JM?bP>uDtrcCdG5#wpcwo)< zAjJZBB=At>GtYD|lO0TRmVU2SJ2dZfFdwuqt9GL)1H;jk^z=}jqgm{Q=Es3@mnGU~ zWId4!dwoRZ=K=II(EL<%p+}bJTv5c!Q-?($#p-GRJq7gMv-sr0}ZWkEB=v{vFq1`o|x;GN3OCuVa>Nh=m@y_Iu?Q{+|$rJiguUL%tvH;6Qn6k$EknU&SG=d3(0@d>mIeR- diff --git a/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c b/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c index e5e8451..77dab4a 100644 --- a/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c +++ b/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c @@ -2,37 +2,38 @@ #include #include "beacon.h" -WINBASEAPI BOOL WINAPI KERNEL32$WaitNamedPipeA(LPCSTR lpNamedPipeName, DWORD nTimeOut); -WINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T); -WINBASEAPI SIZE_T WINAPI MSVCRT$strlen(const char* str); -WINBASEAPI void* WINAPI MSVCRT$strcpy(const char* dest, const char* source); -WINBASEAPI void* WINAPI MSVCRT$strcat(const char* dest, const char* source); -WINBASEAPI void* WINAPI MSVCRT$strtok(char* str, const char* delim); -WINBASEAPI void* WINAPI MSVCRT$free(void*); +WINBASEAPI BOOL WINAPI KERNEL32$WaitNamedPipeW(LPCWSTR lpNamedPipeName, DWORD nTimeOut); +WINBASEAPI void* WINAPI MSVCRT$malloc(size_t); +WINBASEAPI size_t WINAPI MSVCRT$wcslen(const wchar_t* str); +WINBASEAPI wchar_t* WINAPI MSVCRT$wcscpy(wchar_t* dest, const wchar_t* source); +WINBASEAPI wchar_t* WINAPI MSVCRT$wcscat(wchar_t* dest, const wchar_t* source); +WINBASEAPI void WINAPI MSVCRT$free(void*); void go(char* args, int length) { - char* pipeNameHead = "\\\\"; - char* pipeNameTail = "\\pipe\\DAV RPC SERVICE"; - BOOL pipeStatus = 0; - char* singleHost = MSVCRT$strtok(args, ","); + wchar_t* host; + datap parser; + BeaconDataParse(&parser, args, length); + host = (wchar_t*)BeaconDataExtract(&parser, NULL); + //BeaconPrintf(CALLBACK_OUTPUT, "Value of host: %S", host); + + wchar_t* pipeNameHead = L"\\\\"; + wchar_t* pipeNameTail = L"\\pipe\\DAV RPC SERVICE"; + BOOL pipeStatus = 0; - while (singleHost != NULL) - { - char* fullPipeName = MSVCRT$malloc(MSVCRT$strlen(singleHost) + MSVCRT$strlen(pipeNameHead) + MSVCRT$strlen(pipeNameTail) + 1); - MSVCRT$strcpy(fullPipeName, pipeNameHead); - MSVCRT$strcat(fullPipeName, singleHost); - MSVCRT$strcat(fullPipeName, pipeNameTail); - pipeStatus = KERNEL32$WaitNamedPipeA(fullPipeName, 3000); - if (pipeStatus == 0) - { - BeaconPrintf(CALLBACK_OUTPUT, "[x] Unable to hit DAV pipe on %s, system is either unreachable or does not have WebClient service running", singleHost); - } - else - { - BeaconPrintf(CALLBACK_OUTPUT, "[+] WebClient service is active on %s", singleHost); - } - MSVCRT$free((void*)fullPipeName); - singleHost = MSVCRT$strtok(NULL, ","); - } + wchar_t* fullPipeName = (wchar_t*)MSVCRT$malloc((MSVCRT$wcslen(host) + MSVCRT$wcslen(pipeNameHead) + MSVCRT$wcslen(pipeNameTail) + 1) * sizeof(wchar_t)); + MSVCRT$wcscpy(fullPipeName, pipeNameHead); + MSVCRT$wcscat(fullPipeName, host); + MSVCRT$wcscat(fullPipeName, pipeNameTail); + + pipeStatus = KERNEL32$WaitNamedPipeW(fullPipeName, 3000); + if (pipeStatus == 0) + { + BeaconPrintf(CALLBACK_ERROR, "[x] Unable to hit DAV pipe on %S, system is either unreachable or does not have WebClient service running", host); + } + else + { + BeaconPrintf(CALLBACK_OUTPUT, "[+] WebClient service is active on %S", host); + } + MSVCRT$free((void*)fullPipeName); } From 529c3fb93cb3f1565ff46a5f10755e385410714d Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 10 Mar 2024 00:39:02 +0200 Subject: [PATCH 06/12] Edit SOURCE and CNA and README --- GetWebDAVStatus_BOF/GetWebDAVStatus.cna | 2 +- GetWebDAVStatus_BOF/GetWebDAVStatus.x64.o | Bin 0 -> 1646 bytes GetWebDAVStatus_BOF/GetWebDAVStatus.x86.o | Bin 0 -> 1560 bytes GetWebDAVStatus_BOF/GetWebDavStatus-Checksum.txt | 2 ++ README.md | 8 ++++---- 5 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 GetWebDAVStatus_BOF/GetWebDAVStatus.x64.o create mode 100644 GetWebDAVStatus_BOF/GetWebDAVStatus.x86.o create mode 100644 GetWebDAVStatus_BOF/GetWebDavStatus-Checksum.txt diff --git a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna index a0421b8..34df5c2 100644 --- a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna +++ b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna @@ -23,7 +23,7 @@ alias GetWebDAVStatus { # Pack our arguments $arg_data = bof_pack($bid, "Z", $target); - btask($bid, "GetWebDAVStatus BOF by @G0ldenGunSec & @nickvourd"); + btask($bid, "GetWebDAVStatus BOF by @G0ldenGunSec && @nickvourd"); beacon_inline_execute($bid, $data, "go", $arg_data); } diff --git a/GetWebDAVStatus_BOF/GetWebDAVStatus.x64.o b/GetWebDAVStatus_BOF/GetWebDAVStatus.x64.o new file mode 100644 index 0000000000000000000000000000000000000000..6ebf0bede0ae858dadaabb4ccb1112b98f3a1773 GIT binary patch literal 1646 zcmZux&ui2`6n^Q(`lJ55cy)xWRIF=l1w|3IZevrlOYFMaLtEN(ciIhPlO;*pZ9x=P zgs?0W&mKJp{sY>BtgWCY>A}PP0X;0}!DBC?Zzh|VH2WZLzWL^RFYhHYQ+jnAnCT+G z1&%~WIke_*?76A{FpSUJgg0k80?JaVq&jLy*9)dWX{DBJyVqKnd%<*8G~qr9-t>i4 z0GKbGszr6DQKENi^VMk>NvEoDT@7_v?3Eb{VY(Z)_%v_?(aTsqC7sX7^-8TaYWN^%Zgt!1xIFq;MeBr6&%?{ z5#b*ClN`z1GcFe(9nmR1dmfuu+Id>83V@E}V zK}6>`x*c#21FnGRJYPiz?7${?oQGKD{hV7hap;-=1o|-UsD}EG}x5>f!_3sirZ3cdw#aHjS}T&9QLjb@}OBAv5zdxly!rYDBq;s_SMk%Au}U s-HdappYM@0la(HijV5PR&B>}2T2k;}&2}Ta+7wGOoRw&j6^l~%2b=~%J^%m! literal 0 HcmV?d00001 diff --git a/GetWebDAVStatus_BOF/GetWebDAVStatus.x86.o b/GetWebDAVStatus_BOF/GetWebDAVStatus.x86.o new file mode 100644 index 0000000000000000000000000000000000000000..5171e2c5587de234ace582746cf22759acffffc7 GIT binary patch literal 1560 zcmZuxTWb?R6h51*G1`j=1@VUS5W#DDRYVlhCPPtc2}zp@HpFc@Z5EQ^lAy+7Z;9!nIPvB{}(~?VsstBT?hsb|Mn4@i0311^;Ht zkvF9K_oa>mAs=b;-8$bPy3QM6$8A%u#&`EeRvWUtS>roCMnb0HXMR*SBx%FP*?fxz z;?y<1<&9v8yPfGqCz^_X*F|;tv)FvQ`eYlH&bjHrq@$g!%aI;*drSX)))Rj1hS4^| z2a?L`wd~)|o9pYdFiR@5Wl-@Gh!QXg8DNltB*f9Dfg{eq9qe(`K3vVRX-%0c3TEl7 zpjs?3nqg(NESRpb^XV(hTr(|EVyel6Y88aRmNY{s`GPY>H`u%`Os44;D=5o?&4{^p zQ5BlSOkpgmdBKb&O;fc+n(K15LmU$;c}vBy&V;BNkH>Ga3*(d17un#@)fH769s)XV z)TBxZq{m_Dbhj)&m*`FaoWYNdN(%ch+8cfr80$Hds0M>~r4O5^qd48T5DcO{?4a9d zX-o)rsEIO&=uCy6&_b0KdWq zw=v^wOty{jK00n5yG`?|jiG&PHh0w5W*2<`exY?&5~)-w5EX^of}xZI Date: Sun, 10 Mar 2024 00:48:06 +0200 Subject: [PATCH 07/12] Edit README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e866e44..9b14ca0 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,13 @@ The C# project should be a pretty standard build, x64 + Release is the recommend `make` +Prerequisites for compiling the BOF: +- i686-w64-mingw32-gcc +- x86_64-w64-mingw32-gcc + ## Credits [@tifkin_](https://twitter.com/tifkin_) originally posted about this method of remotely identifying WebDAV [here](https://twitter.com/tifkin_/status/1419806476353298442). +Special thanks to [@nickvourd](https://twitter.com/nickvourd) for his contributions. + 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. From 6a71824300fa8ccaa401cd8567af8434e71dcb71 Mon Sep 17 00:00:00 2001 From: Nikos Vourdas <32869078+nickvourd@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:35:57 -0600 Subject: [PATCH 08/12] Improve GetWebDAVStatus command documentation and error handling Enhanced the GetWebDAVStatus command with usage instructions and improved error handling. --- GetWebDAVStatus_BOF/GetWebDAVStatus.cna | 39 ++++++++++++++++++------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna index 34df5c2..633006e 100644 --- a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna +++ b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna @@ -1,29 +1,46 @@ -#GetWebDAVStatus -#CNA author @nickvourd - -beacon_command_register("GetWebDAVStatus", "Determine if the WebClient Service (WebDAV) is running on a remote system.", "Synopsis: GetWebDAVStatus \n\n"); +# GetWebDAVStatus.cna +# CNA author @nickvourd + +beacon_command_register( + "GetWebDAVStatus", + "Determine if the WebClient Service (WebDAV) is running on a remote system", + "Synopsis: GetWebDAVStatus \n\n" . + "Usage: GetWebDAVStatus \n\n" . + "Arguments:\n" . + " target IP address or hostname of the remote system\n\n" . + "Examples:\n" . + " GetWebDAVStatus 192.168.1.100\n" . + " GetWebDAVStatus dc01.domain.local", + "bof" +); alias GetWebDAVStatus { - $bid = $1; + local('$bid $input @args $target $handle $data $arg_data'); + $bid = $1; $input = substr($0, 16); @args = split(' ', $input); - $target = @args[0]; if ($target eq "") { - berror($bid, "Specify an ip or hostname"); - return; + berror($bid, "Specify an ip or hostname"); + berror($bid, "Usage: GetWebDAVStatus "); + return; } # Read in the right BOF file $handle = openf(script_resource("GetWebDAVStatus." . barch($bid) . ".o")); - $data = readb($handle, -1); + $data = readb($handle, -1); closef($handle); + if (strlen($data) == 0) { + berror($bid, "Could not load BOF file: GetWebDAVStatus." . barch($bid) . ".o"); + return; + } + # Pack our arguments - $arg_data = bof_pack($bid, "Z", $target); - btask($bid, "GetWebDAVStatus BOF by @G0ldenGunSec && @nickvourd"); + $arg_data = bof_pack($bid, "Z", $target); + btask($bid, "GetWebDAVStatus BOF by @G0ldenGunSec && @nickvourd"); beacon_inline_execute($bid, $data, "go", $arg_data); } From d183fedfd1e9c5b04d410a5b9e9bd6344230865b Mon Sep 17 00:00:00 2001 From: Nikos Vourdas <32869078+nickvourd@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:46:52 -0600 Subject: [PATCH 09/12] Update GetWebDAVStatus.c --- GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c b/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c index 77dab4a..832d131 100644 --- a/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c +++ b/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c @@ -29,11 +29,11 @@ void go(char* args, int length) pipeStatus = KERNEL32$WaitNamedPipeW(fullPipeName, 3000); if (pipeStatus == 0) { - BeaconPrintf(CALLBACK_ERROR, "[x] Unable to hit DAV pipe on %S, system is either unreachable or does not have WebClient service running", host); + BeaconPrintf(CALLBACK_ERROR, "Unable to hit DAV pipe on %S, system is either unreachable or does not have WebClient service running", host); } else { - BeaconPrintf(CALLBACK_OUTPUT, "[+] WebClient service is active on %S", host); + BeaconPrintf(CALLBACK_OUTPUT, "WebClient service is active on %S", host); } MSVCRT$free((void*)fullPipeName); } From 1728b10be220ad6487cd682f93e3a59b7e5b1148 Mon Sep 17 00:00:00 2001 From: Nikos Vourdas <32869078+nickvourd@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:56:52 -0600 Subject: [PATCH 10/12] Improve WebDAV status checking logic Refactor memory allocation and pipe name handling for WebDAV status check. --- GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c | 124 +++++++++++++++---- 1 file changed, 101 insertions(+), 23 deletions(-) diff --git a/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c b/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c index 832d131..f39f5f9 100644 --- a/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c +++ b/GetWebDAVStatus_BOF/Source/GetWebDAVStatus.c @@ -1,39 +1,117 @@ #include -#include #include "beacon.h" WINBASEAPI BOOL WINAPI KERNEL32$WaitNamedPipeW(LPCWSTR lpNamedPipeName, DWORD nTimeOut); -WINBASEAPI void* WINAPI MSVCRT$malloc(size_t); -WINBASEAPI size_t WINAPI MSVCRT$wcslen(const wchar_t* str); -WINBASEAPI wchar_t* WINAPI MSVCRT$wcscpy(wchar_t* dest, const wchar_t* source); -WINBASEAPI wchar_t* WINAPI MSVCRT$wcscat(wchar_t* dest, const wchar_t* source); -WINBASEAPI void WINAPI MSVCRT$free(void*); +WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap(void); +WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); +WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); void go(char* args, int length) { - wchar_t* host; datap parser; - BeaconDataParse(&parser, args, length); - host = (wchar_t*)BeaconDataExtract(&parser, NULL); - //BeaconPrintf(CALLBACK_OUTPUT, "Value of host: %S", host); - - wchar_t* pipeNameHead = L"\\\\"; - wchar_t* pipeNameTail = L"\\pipe\\DAV RPC SERVICE"; + wchar_t* host = NULL; + wchar_t* fullPipeName = NULL; BOOL pipeStatus = 0; + HANDLE hHeap = NULL; + int totalHosts = 0; + int enabledCount = 0; + int disabledCount = 0; + int hostLen = 0; + int i = 0; + int numHosts = 0; + + BeaconDataParse(&parser, args, length); + hHeap = KERNEL32$GetProcessHeap(); - wchar_t* fullPipeName = (wchar_t*)MSVCRT$malloc((MSVCRT$wcslen(host) + MSVCRT$wcslen(pipeNameHead) + MSVCRT$wcslen(pipeNameTail) + 1) * sizeof(wchar_t)); - MSVCRT$wcscpy(fullPipeName, pipeNameHead); - MSVCRT$wcscat(fullPipeName, host); - MSVCRT$wcscat(fullPipeName, pipeNameTail); + // First argument is the number of hosts + numHosts = BeaconDataInt(&parser); - pipeStatus = KERNEL32$WaitNamedPipeW(fullPipeName, 3000); - if (pipeStatus == 0) + if (numHosts <= 0) { - BeaconPrintf(CALLBACK_ERROR, "Unable to hit DAV pipe on %S, system is either unreachable or does not have WebClient service running", host); + BeaconPrintf(CALLBACK_ERROR, "[!] No targets specified"); + return; } - else + + BeaconPrintf(CALLBACK_OUTPUT, "=== GetWebDAVStatus Check ===\n"); + + for (totalHosts = 0; totalHosts < numHosts; totalHosts++) { - BeaconPrintf(CALLBACK_OUTPUT, "WebClient service is active on %S", host); + host = (wchar_t*)BeaconDataExtract(&parser, NULL); + + if (host == NULL || host[0] == L'\0') + { + break; + } + + // Calculate length manually + hostLen = 0; + while (host[hostLen] != L'\0') + { + hostLen++; + } + + // Allocate buffer for full pipe name + // \\host\pipe\DAV RPC SERVICE = 2 + hostLen + 21 + 1 + fullPipeName = (wchar_t*)KERNEL32$HeapAlloc(hHeap, HEAP_ZERO_MEMORY, (2 + hostLen + 21 + 1) * sizeof(wchar_t)); + + if (fullPipeName == NULL) + { + BeaconPrintf(CALLBACK_ERROR, "[!] Memory allocation failed for %S", host); + continue; + } + + // Build pipe name manually + // Copy "\\\\" + fullPipeName[0] = L'\\'; + fullPipeName[1] = L'\\'; + + // Copy host + for (i = 0; i < hostLen; i++) + { + fullPipeName[2 + i] = host[i]; + } + + // Copy "\\pipe\\DAV RPC SERVICE" + fullPipeName[2 + hostLen] = L'\\'; + fullPipeName[3 + hostLen] = L'p'; + fullPipeName[4 + hostLen] = L'i'; + fullPipeName[5 + hostLen] = L'p'; + fullPipeName[6 + hostLen] = L'e'; + fullPipeName[7 + hostLen] = L'\\'; + fullPipeName[8 + hostLen] = L'D'; + fullPipeName[9 + hostLen] = L'A'; + fullPipeName[10 + hostLen] = L'V'; + fullPipeName[11 + hostLen] = L' '; + fullPipeName[12 + hostLen] = L'R'; + fullPipeName[13 + hostLen] = L'P'; + fullPipeName[14 + hostLen] = L'C'; + fullPipeName[15 + hostLen] = L' '; + fullPipeName[16 + hostLen] = L'S'; + fullPipeName[17 + hostLen] = L'E'; + fullPipeName[18 + hostLen] = L'R'; + fullPipeName[19 + hostLen] = L'V'; + fullPipeName[20 + hostLen] = L'I'; + fullPipeName[21 + hostLen] = L'C'; + fullPipeName[22 + hostLen] = L'E'; + fullPipeName[23 + hostLen] = L'\0'; + + pipeStatus = KERNEL32$WaitNamedPipeW(fullPipeName, 3000); + + if (pipeStatus == 0) + { + BeaconPrintf(CALLBACK_OUTPUT, "[-] %S - WebClient NOT running or unreachable", host); + disabledCount++; + } + else + { + BeaconPrintf(CALLBACK_OUTPUT, "[+] %S - WebClient ENABLED", host); + enabledCount++; + } + + KERNEL32$HeapFree(hHeap, 0, fullPipeName); + fullPipeName = NULL; } - MSVCRT$free((void*)fullPipeName); + + BeaconPrintf(CALLBACK_OUTPUT, "\n[*] Summary: %d hosts checked, %d enabled, %d disabled/unreachable", + totalHosts, enabledCount, disabledCount); } From 950a9cc449cbb5cc3555b0527ab47178f3bd2f95 Mon Sep 17 00:00:00 2001 From: Nikos Vourdas <32869078+nickvourd@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:57:23 -0600 Subject: [PATCH 11/12] Enhance GetWebDAVStatus for multiple targets Updated command to support multiple target inputs and improved usage instructions. --- GetWebDAVStatus_BOF/GetWebDAVStatus.cna | 44 +++++++++++++++++-------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna index 633006e..7ee2c84 100644 --- a/GetWebDAVStatus_BOF/GetWebDAVStatus.cna +++ b/GetWebDAVStatus_BOF/GetWebDAVStatus.cna @@ -3,28 +3,32 @@ beacon_command_register( "GetWebDAVStatus", - "Determine if the WebClient Service (WebDAV) is running on a remote system", - "Synopsis: GetWebDAVStatus \n\n" . - "Usage: GetWebDAVStatus \n\n" . + "Determine if the WebClient Service (WebDAV) is running on remote systems", + "Synopsis: GetWebDAVStatus [target2] [target3] ...\n\n" . + "Usage: GetWebDAVStatus [additional targets...]\n\n" . + "Description:\n" . + " Checks if the WebClient service (WebDAV) is running on one or more\n" . + " remote systems by attempting to connect to the DAV RPC SERVICE pipe.\n\n" . "Arguments:\n" . - " target IP address or hostname of the remote system\n\n" . + " target IP address or hostname of the remote system(s)\n" . + " Multiple targets can be specified separated by spaces\n\n" . "Examples:\n" . " GetWebDAVStatus 192.168.1.100\n" . - " GetWebDAVStatus dc01.domain.local", + " GetWebDAVStatus dc01.domain.local\n" . + " GetWebDAVStatus dc01 ws01 srv01\n" . + " GetWebDAVStatus 192.168.1.10 192.168.1.20 192.168.1.30", "bof" ); alias GetWebDAVStatus { - local('$bid $input @args $target $handle $data $arg_data'); + local('$bid $handle $data $arg_data $i $target $numTargets'); $bid = $1; - $input = substr($0, 16); - @args = split(' ', $input); - $target = @args[0]; - if ($target eq "") { - berror($bid, "Specify an ip or hostname"); - berror($bid, "Usage: GetWebDAVStatus "); + # Check if we have at least one target + if (size(@_) < 2) { + berror($bid, "Specify at least one ip or hostname"); + berror($bid, "Usage: GetWebDAVStatus [target2] [target3] ..."); return; } @@ -38,9 +42,21 @@ alias GetWebDAVStatus { return; } - # Pack our arguments - $arg_data = bof_pack($bid, "Z", $target); + # Calculate number of targets + $numTargets = size(@_) - 1; + + # Pack: first the count (i), then each target as wide string (Z) + $arg_data = bof_pack($bid, "i", $numTargets); + + for ($i = 1; $i < size(@_); $i++) { + $target = @_[$i]; + if ($target ne "") { + $arg_data = $arg_data . bof_pack($bid, "Z", $target); + } + } btask($bid, "GetWebDAVStatus BOF by @G0ldenGunSec && @nickvourd"); + btask($bid, "Checking WebDAV status on $numTargets host(s)..."); + beacon_inline_execute($bid, $data, "go", $arg_data); } From fb0fb5ca830b13902c08cd1bfcc4c91378e2ed2a Mon Sep 17 00:00:00 2001 From: Nikos Vourdas <32869078+nickvourd@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:58:07 -0600 Subject: [PATCH 12/12] Enhance BOF usage example in README Updated BOF usage example to include multiple servers. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b14ca0..36ac380 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Small project to determine if the Web Client service (WebDAV) is running on a re ## Usage 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. -BOF: `GetWebDAVStatus server01` +BOF: `GetWebDAVStatus server01 dc01 ws01 192.168.1.55 ca.domain.local` C#: `execute-assembly C:\assemblies\GetWebDAVStatus.exe server01,server02 --tc 1`