### Validate Thread Start Address with CFG Bitmap Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt Checks if a thread start address is a valid indirect call target using the Control Flow Guard bitmap. Requires 16-byte alignment and applies to x64 system images. ```cpp // Check CFG (Control Flow Guard) bitmap for the start address // Only applies to x64 system images with 16-byte aligned addresses ULONG cfgBits; if (InSystemImageRange(thread.Win32StartAddress) && 0 == ((ULONG_PTR)thread.Win32StartAddress & 0xF) && GetCfgBitsForAddress(thread.Win32StartAddress, &cfgBits) && 0 == cfgBits) { // CFG bitmap indicates this is NOT a valid indirect call target // Attackers may use gadgets or suppressed exports detections.push_back("cfg_invalid"); } ``` -------------------------------- ### Analyze x64 Function Prolog Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt Uses the Zydis disassembler to validate function prologs at thread start addresses, detecting invalid patterns or proxy calls. ```cpp // x64 function prolog validation using Zydis disassembler // Valid prologs follow Windows x64 calling convention: // https://learn.microsoft.com/en-us/cpp/build/prolog-and-epilog ZydisDecoder decoder; ZydisDecodedInstruction instruction; ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64); // Read prolog bytes from target process std::string startBytes; startBytes.resize(MAX_PROLOG_SIZE); // 64 bytes ReadProcessMemorySafely(hProcess, thread.Win32StartAddress, startBytes, mbi); // Valid prolog instructions: // - PUSH nonvolatile registers (rbx, rbp, rdi, rsi, r12-r15) // - MOV [RSP+n], register (save to shadow space) // - LEA rbp, [rsp+n] (frame pointer setup) // - SUB rsp, n (stack allocation - prolog delimiter) // Detection: prolog(48b8deadbeef...) // Indicates the bytes don't form a valid function prolog // Could be a gadget or trampoline if (!bPrologFinished) { detections.push_back("prolog(" + ToHex(startBytes) + ")"); } // Detection: proxy_call(bytes) // Function that forwards execution to the thread parameter (RCX) // Used by attackers to proxy malicious code execution if (bCallThreadParameter) { detections.push_back("proxy_call(" + ToHex(startBytes) + ")"); } ``` -------------------------------- ### Analyze Thread Stack for Evasion Techniques (C++) Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt Performs stack walking to detect call stack spoofing, thread hijacking, and wrapper-based evasion techniques by validating return addresses. Reads TEB to get stack limits and checks for stack pivoting. ```cpp // Read thread stack and analyze for suspicious patterns // Expected stack: ntdll!RtlUserThreadStart -> kernel32!BaseThreadInitThunk -> Win32StartAddress // Read TEB to get stack limits NT_TIB64 tib; ReadProcessMemory(hProcess, thread.TebBaseAddress, &tib, sizeof(tib), NULL); // Check for stack pivoting (ROP indicator) const auto stackPointer = thread.ContextRecord ? thread.ContextRecord->Rsp : tib.StackLimit; if (stackPointer > tib.StackBase || stackPointer < tib.StackLimit) { detections.push_back("stack_pivot"); } // Read stack contents and climb looking for return addresses PVOID stackBuffer[0x1800 / sizeof(PVOID)]; const auto stackReadLength = std::min(sizeof(stackBuffer), (tib.StackBase - stackPointer) & ~0xF); ReadProcessMemory(hProcess, (PVOID)(tib.StackBase - stackReadLength), stackBuffer, stackReadLength, NULL); // StackClimb64 searches for valid return addresses std::vector callStackFrames; bool bCallStackDetection = false; StackClimb64(hProcess, stackBuffer, stackBufferCount, callStackFrames, &bCallStackDetection); // Detection types: // - "spoof(frames)" - Call stack appears spoofed (< 4 frames) // - "wrapper(frames)" - Indirect execution through wrapper function ``` -------------------------------- ### Detect Suspicious Modules and LoadLibrary Usage Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt Identifies threads starting in restricted system modules or pointing directly to LoadLibrary functions, which are common indicators of DLL injection. ```cpp // Modules that should never have thread entry points const std::array modulesWithoutThreadEntrypoints = { "kernel32", "kernelbase", "user32", "advapi32", "psapi", "dbghelp", "imagehlp", "powrprof", "verifier", "setupapi", "rpcrt4" }; // Check if start address is in a suspicious module const auto startModule = std::filesystem::path(mappedPath).stem().string(); for (const auto& module : modulesWithoutThreadEntrypoints) { if (startModule == module) { detections.push_back("unexpected(" + startModule + ")"); } } // LoadLibrary is always suspicious as a thread start address // (Used in classic DLL injection: CreateRemoteThread + LoadLibraryA) static auto pLoadLibraryW = GetProcAddress(hKernel32, "LoadLibraryW"); static auto pLoadLibraryA = GetProcAddress(hKernel32, "LoadLibraryA"); if (pLoadLibraryA == thread.Win32StartAddress || pLoadLibraryW == thread.Win32StartAddress) { detections.push_back("unexpected(LoadLibrary)"); } // Valid ntdll thread entry points (whitelist) static const std::array ntdllThreadEntryPoints = { GetSymbolAddress("ntdll!TppWorkerThread"), GetSymbolAddress("ntdll!EtwpLogger"), GetSymbolAddress("ntdll!DbgUiRemoteBreakin"), GetSymbolAddress("ntdll!RtlpQueryProcessDebugInformationRemote") }; ``` -------------------------------- ### Detect Memory Injection Types Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt Logic to identify threads starting in non-image memory or modified image pages, which are common indicators of shellcode injection or inline hooking. ```cpp MEMORY_BASIC_INFORMATION mbi{}; VirtualQueryEx(hProcess, thread.Win32StartAddress, &mbi, sizeof(mbi)); if (MEM_IMAGE != mbi.Type && MEM_COMMIT == mbi.State) { // This is a PRIVATE memory region with executable code // Indicates direct shellcode injection (classic injection) detections.push_back("PRIVATE"); } // Also detect modified MEM_IMAGE pages (hook detection) PSAPI_WORKING_SET_EX_INFORMATION pwsei{}; pwsei.VirtualAddress = thread.Win32StartAddress; if (K32QueryWorkingSetEx(hProcess, &pwsei, sizeof(pwsei)) && !pwsei.VirtualAttributes.Shared) { // The page has been modified (copy-on-write triggered) // Could indicate inline hooking or code patching detections.push_back("private_image"); } ``` -------------------------------- ### Get-InjectedThreadEx Build Configuration and Libraries Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt This C++ code specifies project dependencies, build settings, and required libraries for the Get-InjectedThreadEx project. Ensure Zydis is built statically with ZYDIS_STATIC_BUILD defined. ```cpp // Project dependencies: // - Windows SDK (for Win32 APIs) // - Zydis disassembler (https://github.com/zyantific/zydis) // - DbgHelp.lib (for symbol resolution) // - ntdll.lib (for native APIs) // Build configuration (Get-InjectedThreadEx.vcxproj): // - Platform: x64 // - Configuration: Release // - Zydis: Static build (ZYDIS_STATIC_BUILD) // Required libraries: #pragma comment(lib, "ntdll.lib") #pragma comment(lib, "DbgHelp.lib") #pragma comment(lib, "Zydis.lib") // Build steps: // 1. Clone repository with submodules: git clone --recursive // 2. Open Get-InjectedThreadEx.sln in Visual Studio // 3. Build Release x64 configuration // 4. Output: Get-InjectedThreadEx.exe ``` -------------------------------- ### Cross-Platform Windows Administration with PowerShell Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt Provides cross-platform Windows administration access with detailed process and thread information output. This PowerShell implementation is deprecated in favor of the C++ executable. ```powershell # Import and run the detection function # Note: PowerShell version is deprecated in favor of the C++ executable # Basic usage - scan all processes Get-InjectedThreadEx # Scan specific process Get-InjectedThreadEx -ProcessId 1234 # Enable aggressive detection (higher false positive rate) Get-InjectedThreadEx -Aggressive # Brief output mode Get-InjectedThreadEx -Brief # Example output object properties: # ProcessName, ProcessId, Wow64, Path, KernelPath, CommandLine # ThreadId, Win32StartAddress, Win32StartAddressModule # MemoryType, MemoryProtection, MemoryState # Detections (array of detection strings) # TailBytes, StartBytes (hex-encoded memory) # Detection types: # - MEM_PRIVATE: Thread starting in non-image memory # - prolog: Invalid x64 function prolog # - hooked: MEM_IMAGE page has been modified # - cfg: CFG bitmap violation # - cfg_export_suppressed: Using suppressed export # - cfg_modified: CFG bitmap page modified # - kernel32, kernelbase, etc.: Unexpected start module # - LoadLibrary: Classic DLL injection technique # - ntdll: Unknown ntdll entry point # - wrapper: Indirect execution detected # - hijacked: Call stack hijacking detected # - alignment: Suspicious address alignment # - tail: Invalid bytes before function # - SYSTEM impersonation: Thread impersonating SYSTEM # - sleep: Suspicious thread sleeping (obfuscate-and-sleep) ``` -------------------------------- ### Define Known False Positives (C++) Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt Defines a list of known false positives to filter out legitimate system processes from detection output. This structure holds process name, symbol, and count for filtering. ```cpp // Known false positives are filtered from output struct FalsePositive { const std::wstring ProcessName; const std::string Symbol; const size_t Count; }; static const std::array falsePositives = {{ { L"dwm.exe", "dwmcore.dll!CMit::RunInputThreadStatic", 1 }, { L"vctip.exe", "vctip.exe!CorExeMain", 1 } }}; // Check if detection matches known false positive BOOL IsKnownFalsePositive(const HANDLE hProcess, const PROCESSENTRY32 &processEntry, const PSS_THREAD_ENTRY thread, std::string &symbol, const std::vector &detections); ``` -------------------------------- ### ScanThread Function Signature Source: https://context7.com/jdu2600/get-injectedthreadex/llms.txt The core analysis function signature used to evaluate individual threads for injection indicators. ```cpp BOOL ScanThread(HANDLE hProcess, BOOL bIsDotNet, PSS_THREAD_ENTRY& thread, std::string& symbol, std::vector& detections); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.