CFG Exception Utility

Тема в разделе "WASM.SOURCES & 2LZ", создана пользователем galenkane, 31 мар 2025 в 05:37.

  1. galenkane

    galenkane Active Member

    Публикаций:
    0
    Регистрация:
    13 янв 2017
    Сообщения:
    348
    Может кому пригодится в тестах.
    Не пропадать же кодесу)

    Код (C++):
    1. #include <iostream>
    2. #include <Windows.h>
    3. #include <psapi.h>
    4. #include <TlHelp32.h>
    5. #include <iomanip> // For std::setw and other formatting
    6. #include <string>
    7. #include "cfg_exception.h"
    8.  
    9. // Configuration settings
    10. // ======================================================================
    11. // Path to the target executable
    12. constexpr const char* TARGET_EXECUTABLE_PATH = "loader.exe";
    13.  
    14. // Wait times (in milliseconds)
    15. constexpr DWORD PROCESS_INIT_WAIT_TIME = 3000;     // Time to wait for process initialization
    16. constexpr DWORD PROCESS_OUTPUT_WAIT_TIME = 10000;  // Time to wait for process output
    17. constexpr DWORD PROGRESS_CHECK_INTERVAL = 1000;    // Interval to check process status
    18.  
    19. // Memory settings
    20. constexpr SIZE_T DEFAULT_PAGE_SIZE = 4096;         // Standard memory page size
    21. constexpr SIZE_T MIN_REGION_SIZE = 16;             // Minimum region size for CFG
    22.  
    23. // CFG Target settings
    24. constexpr const char* TARGET_FUNCTION = "NtSetContextThread"; // Function to add CFG exception for
    25. constexpr const char* TARGET_MODULE = "ntdll.dll";           // Module containing the function
    26. // ======================================================================
    27.  
    28. // Logger class to help with debug output
    29. class Logger
    30. {
    31. public:
    32.   enum LogLevel
    33.   {
    34.     INFO,
    35.     WARNING,
    36.     ERROR_CASE,
    37.     DEBUG
    38.   };
    39.  
    40.   static void Log(LogLevel level, const std::string &message)
    41.   {
    42.     std::string prefix;
    43.     switch (level)
    44.     {
    45.     case INFO:
    46.       prefix = "[INFO] ";
    47.       break;
    48.     case WARNING:
    49.       prefix = "[WARN] ";
    50.       break;
    51.     case ERROR_CASE:
    52.       prefix = "[ERROR] ";
    53.       break;
    54.     case DEBUG:
    55.       prefix = "[DEBUG] ";
    56.       break;
    57.     }
    58.  
    59.     std::cout << prefix << message << std::endl;
    60.   }
    61.  
    62.   static void LogError(const std::string &message, DWORD errorCode)
    63.   {
    64.     char errorBuffer[256];
    65.     FormatMessageA(
    66.         FORMAT_MESSAGE_FROM_SYSTEM,
    67.         NULL,
    68.         errorCode,
    69.         MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), // Use English locale
    70.         errorBuffer,
    71.         sizeof(errorBuffer),
    72.         NULL);
    73.  
    74.     std::string errorMsg = message + " Error code: " + std::to_string(errorCode) +
    75.                            " (" + std::string(errorBuffer) + ")";
    76.     Log(ERROR_CASE, errorMsg);
    77.   }
    78. };
    79.  
    80. // Check if the process is running with administrator privileges
    81. BOOL IsElevated()
    82. {
    83.   BOOL fIsElevated = FALSE;
    84.   HANDLE hToken = NULL;
    85.  
    86.   if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
    87.   {
    88.     TOKEN_ELEVATION elevation;
    89.     DWORD cbSize = sizeof(TOKEN_ELEVATION);
    90.  
    91.     if (GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &cbSize))
    92.     {
    93.       fIsElevated = elevation.TokenIsElevated;
    94.     }
    95.   }
    96.  
    97.   if (hToken)
    98.   {
    99.     CloseHandle(hToken);
    100.   }
    101.  
    102.   return fIsElevated;
    103. }
    104.  
    105. // Implementation of helper function
    106. BOOL GetMemoryAllocationBaseAndRegionSize(PVOID pvAddress, PVOID *ppvAllocationBase, PSIZE_T pstRegionSize)
    107. {
    108.   MEMORY_BASIC_INFORMATION tMemoryBasicInformation = {0};
    109.  
    110.   SIZE_T queryResult = VirtualQuery(pvAddress, &tMemoryBasicInformation, sizeof(tMemoryBasicInformation));
    111.   if (0 == queryResult)
    112.   {
    113.     return FALSE;
    114.   }
    115.  
    116.   *ppvAllocationBase = tMemoryBasicInformation.BaseAddress;
    117.   *pstRegionSize = tMemoryBasicInformation.RegionSize;
    118.  
    119.   return TRUE;
    120. }
    121.  
    122. // Get module base address in a process
    123. HMODULE GetRemoteModuleHandle(DWORD processId, const char *moduleName)
    124. {
    125.   MODULEENTRY32W moduleEntry = {0};
    126.   moduleEntry.dwSize = sizeof(MODULEENTRY32W);
    127.   HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processId);
    128.  
    129.   if (snapshot == INVALID_HANDLE_VALUE)
    130.   {
    131.     std::cerr << "Failed to create module snapshot. Error: " << GetLastError() << std::endl;
    132.     return NULL;
    133.   }
    134.  
    135.   BOOL result = Module32FirstW(snapshot, &moduleEntry);
    136.   while (result)
    137.   {
    138.     // Convert wide string to narrow string for comparison
    139.     char moduleNameA[MAX_PATH];
    140.     WideCharToMultiByte(CP_ACP, 0, moduleEntry.szModule, -1, moduleNameA, MAX_PATH, NULL, NULL);
    141.  
    142.     if (_stricmp(moduleNameA, moduleName) == 0)
    143.     {
    144.       CloseHandle(snapshot);
    145.       return moduleEntry.hModule;
    146.     }
    147.     result = Module32NextW(snapshot, &moduleEntry);
    148.   }
    149.  
    150.   CloseHandle(snapshot);
    151.   return NULL;
    152. }
    153.  
    154. // Two-step process creation and module enumeration
    155. LONG AddCfgExceptionToTestProcess()
    156. {
    157.   Logger::Log(Logger::INFO, "Starting CFG exception addition process...");
    158.  
    159.   STARTUPINFOA startupInfo = {0};
    160.   PROCESS_INFORMATION processInfo = {0};
    161.   LONG result = ERROR_SUCCESS;
    162.   HMODULE hNtdll = nullptr;
    163.   PVOID targetAddress = nullptr;
    164.   PVOID allocationBase = nullptr;
    165.   SIZE_T regionSize = 0;
    166.   SETPROCESSVALIDCALLTARGETS pSetProcessValidCallTargets = nullptr;
    167.   CFG_CALL_TARGET_INFO cfgCallTargetInfo = {0};
    168.  
    169.   // Get SetProcessValidCallTargets function pointer
    170.   Logger::Log(Logger::INFO, "Loading required system libraries...");
    171.   HMODULE hKernelbase = LoadLibraryW(L"Kernelbase.dll");
    172.   if (!hKernelbase)
    173.   {
    174.     DWORD error = GetLastError();
    175.     Logger::LogError("Failed to load Kernelbase.dll", error);
    176.     return ERROR_MOD_NOT_FOUND;
    177.   }
    178.  
    179.   pSetProcessValidCallTargets = reinterpret_cast<SETPROCESSVALIDCALLTARGETS>(
    180.       GetProcAddress(hKernelbase, "SetProcessValidCallTargets"));
    181.  
    182.   if (!pSetProcessValidCallTargets)
    183.   {
    184.     DWORD error = GetLastError();
    185.     Logger::LogError("Failed to get SetProcessValidCallTargets function pointer", error);
    186.     FreeLibrary(hKernelbase);
    187.     return ERROR_PROC_NOT_FOUND;
    188.   }
    189.   Logger::Log(Logger::INFO, "Successfully loaded required libraries and functions");
    190.  
    191.   // Step 1: First create the process normally to allow it to initialize
    192.   Logger::Log(Logger::INFO, "Creating process from specified path...");
    193.   startupInfo.cb = sizeof(startupInfo);
    194.  
    195.   // Create the process suspended to prevent it from terminating too quickly
    196.   if (!CreateProcessA(NULL, (LPSTR)TARGET_EXECUTABLE_PATH, NULL, NULL, FALSE,
    197.                     CREATE_SUSPENDED | CREATE_NEW_CONSOLE, // Start suspended
    198.                     NULL, NULL, &startupInfo, &processInfo))
    199.   {
    200.     DWORD error = GetLastError();
    201.     Logger::LogError("Failed to create process", error);
    202.     FreeLibrary(hKernelbase);
    203.     return error;
    204.   }
    205.  
    206.   Logger::Log(Logger::INFO, "Process created with PID: " + std::to_string(processInfo.dwProcessId));
    207.  
    208.   // Check if process is still active before continuing
    209.   DWORD waitResult = WaitForSingleObject(processInfo.hProcess, 0);
    210.   if (waitResult == WAIT_OBJECT_0) {
    211.     Logger::Log(Logger::ERROR_CASE, "Process terminated immediately after creation");
    212.     CloseHandle(processInfo.hThread);
    213.     CloseHandle(processInfo.hProcess);
    214.     FreeLibrary(hKernelbase);
    215.     return ERROR_PROCESS_ABORTED;
    216.   }
    217.  
    218.   // Resume the process from suspended state
    219.   ResumeThread(processInfo.hThread);
    220.  
    221.   // Give the process more time to initialize fully
    222.   Logger::Log(Logger::INFO, "Waiting for process to initialize (" + std::to_string(PROCESS_INIT_WAIT_TIME/1000) + " seconds)...");
    223.   Sleep(PROCESS_INIT_WAIT_TIME); // Wait for initialization
    224.  
    225.   // Check again if process is still running
    226.   waitResult = WaitForSingleObject(processInfo.hProcess, 0);
    227.   if (waitResult == WAIT_OBJECT_0) {
    228.     Logger::Log(Logger::WARNING, "Process terminated before we could analyze it");
    229.     CloseHandle(processInfo.hThread);
    230.     CloseHandle(processInfo.hProcess);
    231.     FreeLibrary(hKernelbase);
    232.     return ERROR_PROCESS_ABORTED;
    233.   }
    234.  
    235.   // Step 2: Now get module information
    236.   Logger::Log(Logger::INFO, "Attempting to create module snapshot...");
    237.   HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processInfo.dwProcessId);
    238.   if (snapshot == INVALID_HANDLE_VALUE)
    239.   {
    240.     DWORD error = GetLastError();
    241.     Logger::LogError("Failed to create module snapshot", error);
    242.     TerminateProcess(processInfo.hProcess, 0);
    243.     CloseHandle(processInfo.hThread);
    244.     CloseHandle(processInfo.hProcess);
    245.     FreeLibrary(hKernelbase);
    246.     return error;
    247.   }
    248.   Logger::Log(Logger::INFO, "Successfully created module snapshot");
    249.  
    250.   // Временно приостанавливаем процесс и даем возможность подключить отладчик
    251.   if (SuspendThread(processInfo.hThread) == -1)
    252.   {
    253.     DWORD error = GetLastError();
    254.     Logger::LogError("Failed to suspend process for debugging", error);
    255.   }
    256.   else
    257.   {
    258.     Logger::Log(Logger::INFO, "=================================================");
    259.     Logger::Log(Logger::INFO, "Process is now SUSPENDED and ready for debugging");
    260.     Logger::Log(Logger::INFO, "Process ID (PID): " + std::to_string(processInfo.dwProcessId));
    261.     Logger::Log(Logger::INFO, "You can now attach a debugger to this process");
    262.     Logger::Log(Logger::INFO, "For WinDbg: .attach " + std::to_string(processInfo.dwProcessId));
    263.     Logger::Log(Logger::INFO, "For Visual Studio: Debug > Attach to Process...");
    264.     Logger::Log(Logger::INFO, "=================================================");
    265.     Logger::Log(Logger::INFO, "Press Enter to continue execution...");
    266.     std::cin.get();
    267.  
    268.     // Возобновляем процесс после подключения отладчика
    269.     ResumeThread(processInfo.hThread);
    270.     Logger::Log(Logger::INFO, "Process resumed. Continuing with CFG exception setup...");
    271.   }
    272.  
    273.   // Step 3: Find ntdll.dll in the snapshot
    274.   Logger::Log(Logger::INFO, "Searching for ntdll.dll in process modules...");
    275.   MODULEENTRY32W moduleEntry = {0};
    276.   moduleEntry.dwSize = sizeof(MODULEENTRY32W);
    277.  
    278.   BOOL moduleResult = Module32FirstW(snapshot, &moduleEntry);
    279.   bool found = false;
    280.  
    281.   while (moduleResult)
    282.   {
    283.     // Convert wide string to narrow string for logging and comparison
    284.     char moduleNameA[MAX_PATH];
    285.     WideCharToMultiByte(CP_ACP, 0, moduleEntry.szModule, -1, moduleNameA, MAX_PATH, NULL, NULL);
    286.  
    287.     Logger::Log(Logger::DEBUG, "Found module: " + std::string(moduleNameA));
    288.  
    289.     if (_stricmp(moduleNameA, TARGET_MODULE) == 0)
    290.     {
    291.       Logger::Log(Logger::INFO, "Found ntdll.dll at address: " +
    292.                                     std::to_string(reinterpret_cast<uintptr_t>(moduleEntry.modBaseAddr)));
    293.       hNtdll = moduleEntry.hModule;
    294.       found = true;
    295.       break;
    296.     }
    297.     moduleResult = Module32NextW(snapshot, &moduleEntry);
    298.   }
    299.  
    300.   CloseHandle(snapshot);
    301.  
    302.   if (!found)
    303.   {
    304.     Logger::Log(Logger::ERROR_CASE, "Could not find ntdll.dll in the process modules");
    305.     TerminateProcess(processInfo.hProcess, 0);
    306.     CloseHandle(processInfo.hThread);
    307.     CloseHandle(processInfo.hProcess);
    308.     FreeLibrary(hKernelbase);
    309.     return ERROR_MOD_NOT_FOUND;
    310.   }
    311.  
    312.   // Step 4: Now suspend the process for our modifications
    313.   Logger::Log(Logger::INFO, "Suspending the process...");
    314.   if (SuspendThread(processInfo.hThread) == -1)
    315.   {
    316.     DWORD error = GetLastError();
    317.     Logger::LogError("Failed to suspend process", error);
    318.     TerminateProcess(processInfo.hProcess, 0);
    319.     CloseHandle(processInfo.hThread);
    320.     CloseHandle(processInfo.hProcess);
    321.     FreeLibrary(hKernelbase);
    322.     return error;
    323.   }
    324.  
    325.   // Check if CFG is enabled for the process
    326.   PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY cfgPolicy = { 0 };
    327.   BOOL isCfgEnabled = FALSE;
    328.  
    329.   if (GetProcessMitigationPolicy(processInfo.hProcess, ProcessControlFlowGuardPolicy,
    330.                                 &cfgPolicy, sizeof(cfgPolicy))) {
    331.       isCfgEnabled = cfgPolicy.EnableControlFlowGuard;
    332.       Logger::Log(Logger::INFO, "CFG status in target process: " +
    333.                   std::string(isCfgEnabled ? "ENABLED" : "DISABLED"));
    334.  
    335.       if (!isCfgEnabled) {
    336.           Logger::Log(Logger::WARNING, "CFG is not enabled in target process. Exceptions may not work.");
    337.       }
    338.   } else {
    339.       DWORD error = GetLastError();
    340.       Logger::LogError("Failed to query CFG status", error);
    341.   }
    342.  
    343.   // Get address of NtSetContextThread in our process to calculate offset
    344.   Logger::Log(Logger::INFO, "Loading ntdll.dll in the current process...");
    345.   HMODULE hLocalNtdll = LoadLibraryW(L"ntdll.dll");
    346.   if (!hLocalNtdll)
    347.   {
    348.     DWORD error = GetLastError();
    349.     Logger::LogError("Failed to load ntdll.dll locally", error);
    350.     ResumeThread(processInfo.hThread); // Resume before exiting
    351.     TerminateProcess(processInfo.hProcess, 0);
    352.     CloseHandle(processInfo.hThread);
    353.     CloseHandle(processInfo.hProcess);
    354.     FreeLibrary(hKernelbase);
    355.     return error;
    356.   }
    357.  
    358.   Logger::Log(Logger::INFO, "Getting address of NtSetContextThread...");
    359.   PVOID localFuncAddress = GetProcAddress(hLocalNtdll, TARGET_FUNCTION);
    360.   if (!localFuncAddress)
    361.   {
    362.     DWORD error = GetLastError();
    363.     Logger::LogError("Failed to get address of NtSetContextThread", error);
    364.     FreeLibrary(hLocalNtdll);
    365.     ResumeThread(processInfo.hThread);
    366.     TerminateProcess(processInfo.hProcess, 0);
    367.     CloseHandle(processInfo.hThread);
    368.     CloseHandle(processInfo.hProcess);
    369.     FreeLibrary(hKernelbase);
    370.     return ERROR_PROC_NOT_FOUND;
    371.   }
    372.  
    373.   // Calculate the offset from ntdll base
    374.   ULONG_PTR offset = (ULONG_PTR)localFuncAddress - (ULONG_PTR)hLocalNtdll;
    375.   Logger::Log(Logger::INFO, "Function offset from ntdll base: 0x" +
    376.                                 std::to_string(offset));
    377.  
    378.   // Calculate the target address in the target process
    379.   targetAddress = (PVOID)((ULONG_PTR)hNtdll + offset);
    380.   Logger::Log(Logger::INFO, "Target function address in target process: " +
    381.                                 std::to_string(reinterpret_cast<uintptr_t>(targetAddress)));
    382.  
    383.   // Get allocation base and region size with VirtualQueryEx
    384.   Logger::Log(Logger::INFO, "Getting memory information for target function...");
    385.   MEMORY_BASIC_INFORMATION memInfo = {0};
    386.   HANDLE hTargetProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_SET_INFORMATION,
    387.                                       FALSE, processInfo.dwProcessId);
    388.  
    389.   if (!hTargetProcess)
    390.   {
    391.     DWORD error = GetLastError();
    392.     Logger::LogError("Failed to open target process for memory operations", error);
    393.     FreeLibrary(hLocalNtdll);
    394.     ResumeThread(processInfo.hThread);
    395.     TerminateProcess(processInfo.hProcess, 0);
    396.     CloseHandle(processInfo.hThread);
    397.     CloseHandle(processInfo.hProcess);
    398.     FreeLibrary(hKernelbase);
    399.     return error;
    400.   }
    401.  
    402.   SIZE_T queryResult = VirtualQueryEx(hTargetProcess, targetAddress, &memInfo, sizeof(memInfo));
    403.   if (queryResult == 0)
    404.   {
    405.     DWORD error = GetLastError();
    406.     Logger::LogError("Failed to query remote memory", error);
    407.     CloseHandle(hTargetProcess);
    408.     FreeLibrary(hLocalNtdll);
    409.     ResumeThread(processInfo.hThread);
    410.     TerminateProcess(processInfo.hProcess, 0);
    411.     CloseHandle(processInfo.hThread);
    412.     CloseHandle(processInfo.hProcess);
    413.     FreeLibrary(hKernelbase);
    414.     return error;
    415.   }
    416.  
    417.   allocationBase = memInfo.AllocationBase;
    418.   regionSize = memInfo.RegionSize;
    419.  
    420.   // Additional validation for memory type and protection
    421.   if (!(memInfo.Type & MEM_IMAGE))
    422.   {
    423.     Logger::Log(Logger::ERROR_CASE, "Target memory is not an executable image (MEM_IMAGE)");
    424.     CloseHandle(hTargetProcess);
    425.     FreeLibrary(hLocalNtdll);
    426.     ResumeThread(processInfo.hThread);
    427.     TerminateProcess(processInfo.hProcess, 0);
    428.     CloseHandle(processInfo.hThread);
    429.     CloseHandle(processInfo.hProcess);
    430.     FreeLibrary(hKernelbase);
    431.     return ERROR_INVALID_ADDRESS;
    432.   }
    433.  
    434.   // Check if the memory region has execute permissions
    435.   BOOL hasExecutePermission = memInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ |
    436.                                                  PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
    437.   if (!hasExecutePermission)
    438.   {
    439.     Logger::Log(Logger::WARNING, "Target memory region does not have execute permissions");
    440.   }
    441.  
    442.   Logger::Log(Logger::INFO, "Memory information retrieved:");
    443.   Logger::Log(Logger::INFO, "  Allocation base: " + std::to_string(reinterpret_cast<uintptr_t>(allocationBase)));
    444.   Logger::Log(Logger::INFO, "  Region size: " + std::to_string(regionSize));
    445.   Logger::Log(Logger::INFO, "  Protection: 0x" + std::to_string(memInfo.Protect));
    446.   Logger::Log(Logger::INFO, "  Type: 0x" + std::to_string(memInfo.Type));
    447.  
    448.   // Configure CFG exception
    449.   Logger::Log(Logger::INFO, "Configuring CFG exception...");
    450.  
    451.   // Calculate the relative offset from allocation base
    452.   ULONG_PTR relativeOffset = static_cast<ULONG_PTR>(
    453.       reinterpret_cast<ULONG_PTR>(targetAddress) - reinterpret_cast<ULONG_PTR>(allocationBase));
    454.  
    455.   // Setup the call target info structure
    456.   cfgCallTargetInfo.Offset = relativeOffset;
    457.   cfgCallTargetInfo.Flags = CFG_CALL_TARGET_VALID; // Simplified flag usage
    458.  
    459.   Logger::Log(Logger::INFO, "Setting CFG exception with offset: 0x" +
    460.                                 std::to_string(cfgCallTargetInfo.Offset));
    461.   Logger::Log(Logger::INFO, "Target address: 0x" +
    462.                                 std::to_string(reinterpret_cast<uintptr_t>(targetAddress)));
    463.   Logger::Log(Logger::INFO, "Allocation base: 0x" +
    464.                                 std::to_string(reinterpret_cast<uintptr_t>(allocationBase)));
    465.  
    466.   // Try different approaches to add the CFG exception
    467.   Logger::Log(Logger::INFO, "Calling SetProcessValidCallTargets with allocation base...");
    468.  
    469.   // First approach: use allocation base with the full region size
    470.   if (!pSetProcessValidCallTargets(hTargetProcess, allocationBase, regionSize, 1, &cfgCallTargetInfo)) {
    471.       result = GetLastError();
    472.       Logger::LogError("First approach failed", result);
    473.  
    474.       // Second approach: Try with page size aligned region
    475.       SIZE_T pageSize = DEFAULT_PAGE_SIZE;
    476.       PVOID pageAlignedAddress = (PVOID)(((ULONG_PTR)targetAddress) & ~(pageSize - 1));
    477.       SIZE_T pageAlignedSize = pageSize;
    478.  
    479.       // Adjust offset for page aligned address
    480.       cfgCallTargetInfo.Offset = (ULONG_PTR)targetAddress - (ULONG_PTR)pageAlignedAddress;
    481.  
    482.       Logger::Log(Logger::INFO, "Trying with page aligned address: 0x" +
    483.                   std::to_string(reinterpret_cast<uintptr_t>(pageAlignedAddress)));
    484.       Logger::Log(Logger::INFO, "Adjusted offset: 0x" + std::to_string(cfgCallTargetInfo.Offset));
    485.  
    486.       if (!pSetProcessValidCallTargets(hTargetProcess, pageAlignedAddress, pageAlignedSize, 1, &cfgCallTargetInfo)) {
    487.           result = GetLastError();
    488.           Logger::LogError("Second approach failed", result);
    489.  
    490.           // Third approach: Try directly at target with minimal region and no offset
    491.           cfgCallTargetInfo.Offset = 0;
    492.  
    493.           Logger::Log(Logger::INFO, "Trying direct target approach...");
    494.           if (!pSetProcessValidCallTargets(hTargetProcess, targetAddress, MIN_REGION_SIZE, 1, &cfgCallTargetInfo)) {
    495.               result = GetLastError();
    496.               Logger::LogError("Third approach failed", result);
    497.  
    498.               // Fourth approach: Allocate our own memory and try setting CFG on that
    499.               Logger::Log(Logger::INFO, "Attempting to create our own allocation for CFG testing...");
    500.  
    501.               // Allocate executable memory in the target process
    502.               SIZE_T allocSize = pageSize;
    503.               PVOID testMemory = VirtualAllocEx(
    504.                   hTargetProcess,
    505.                   NULL,
    506.                   allocSize,
    507.                   MEM_COMMIT | MEM_RESERVE,
    508.                   PAGE_EXECUTE_READWRITE
    509.               );
    510.  
    511.               if (testMemory) {
    512.                   Logger::Log(Logger::INFO, "Created test allocation at: 0x" +
    513.                               std::to_string(reinterpret_cast<uintptr_t>(testMemory)));
    514.  
    515.                   // Write a simple RET instruction to the memory (0xC3)
    516.                   BYTE retInstr = 0xC3;
    517.                   SIZE_T bytesWritten;
    518.                   if (WriteProcessMemory(hTargetProcess, testMemory, &retInstr, sizeof(retInstr), &bytesWritten)) {
    519.                       Logger::Log(Logger::INFO, "Wrote RET instruction to test memory");
    520.  
    521.                       // Try setting CFG on our own allocation
    522.                       cfgCallTargetInfo.Offset = 0;  // Start of our allocation
    523.                       cfgCallTargetInfo.Flags = CFG_CALL_TARGET_VALID;
    524.  
    525.                       if (!pSetProcessValidCallTargets(hTargetProcess, testMemory, allocSize, 1, &cfgCallTargetInfo)) {
    526.                           result = GetLastError();
    527.                           Logger::LogError("Fourth approach failed on custom allocation", result);
    528.                       } else {
    529.                           result = ERROR_SUCCESS;
    530.                           Logger::Log(Logger::INFO, "Successfully set CFG exception on our custom allocation!");
    531.                       }
    532.                   } else {
    533.                       DWORD error = GetLastError();
    534.                       Logger::LogError("Failed to write to test memory", error);
    535.                   }
    536.               } else {
    537.                   DWORD error = GetLastError();
    538.                   Logger::LogError("Failed to allocate test memory", error);
    539.               }
    540.           } else {
    541.               result = ERROR_SUCCESS;
    542.               Logger::Log(Logger::INFO, "Successfully set CFG exception using third approach!");
    543.           }
    544.       } else {
    545.           result = ERROR_SUCCESS;
    546.           Logger::Log(Logger::INFO, "Successfully set CFG exception using second approach!");
    547.       }
    548.   } else {
    549.       result = ERROR_SUCCESS;
    550.       Logger::Log(Logger::INFO, "Successfully set CFG exception using first approach!");
    551.   }
    552.  
    553.   // Clean up
    554.   FreeLibrary(hLocalNtdll);
    555.   CloseHandle(hTargetProcess);
    556.  
    557.   // Resume and let the process run normally
    558.   if (result == ERROR_SUCCESS)
    559.   {
    560.     Logger::Log(Logger::INFO, "Resuming process and waiting for any output...");
    561.     ResumeThread(processInfo.hThread);
    562.  
    563.     // Подождите немного дольше, чтобы увидеть любую активность
    564.     DWORD waitTime = PROCESS_OUTPUT_WAIT_TIME;
    565.     Logger::Log(Logger::INFO, "Waiting up to 10 seconds for process to produce output...");
    566.  
    567.     // Периодически проверяйте, жив ли процесс
    568.     for (int i = 0; i < 10; i++) {
    569.         Sleep(PROGRESS_CHECK_INTERVAL);
    570.         DWORD exitCode = 0;
    571.         if (GetExitCodeProcess(processInfo.hProcess, &exitCode) && exitCode != STILL_ACTIVE) {
    572.             Logger::Log(Logger::INFO, "Process terminated with exit code: " + std::to_string(exitCode));
    573.             break;
    574.         }
    575.         Logger::Log(Logger::DEBUG, "Process still active: " + std::to_string(i+1) + " seconds elapsed");
    576.     }
    577.  
    578.     Logger::Log(Logger::INFO, "Press Enter to terminate the process and exit...");
    579.     std::cin.get();
    580.     TerminateProcess(processInfo.hProcess, 0);
    581.   }
    582.   else
    583.   {
    584.     Logger::Log(Logger::INFO, "Terminating process due to error...");
    585.     ResumeThread(processInfo.hThread); // Resume before terminating
    586.     TerminateProcess(processInfo.hProcess, 0);
    587.   }
    588.  
    589.   CloseHandle(processInfo.hThread);
    590.   CloseHandle(processInfo.hProcess);
    591.   FreeLibrary(hKernelbase);
    592.  
    593.   return result;
    594. }
    595.  
    596. int main()
    597. {
    598.   // Check for administrator privileges
    599.   if (!IsElevated())
    600.   {
    601.     std::cerr << "ERROR: This application requires administrator privileges." << std::endl;
    602.     std::cerr << "Please right-click and select 'Run as administrator'." << std::endl;
    603.     return ERROR_ACCESS_DENIED;
    604.   }
    605.  
    606.   Logger::Log(Logger::INFO, "Starting CFG Exception Utility...");
    607.   LONG result = AddCfgExceptionToTestProcess();
    608.  
    609.   if (result == ERROR_SUCCESS)
    610.   {
    611.     Logger::Log(Logger::INFO, "CFG exception operation completed successfully");
    612.   }
    613.   else
    614.   {
    615.     Logger::Log(Logger::ERROR_CASE, "Failed to add CFG exception. Error code: " + std::to_string(result));
    616.   }
    617.  
    618.   return result;
    619. }
    620.  
     

    Вложения:

    • app.zip
      Размер файла:
      7,6 КБ
      Просмотров:
      13
    Research нравится это.
  2. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    188
    Решил подождать немного, ничего не писать сюда не ходить, с головой были трудности :)

    А как это работает ?
     
  3. galenkane

    galenkane Active Member

    Публикаций:
    0
    Регистрация:
    13 янв 2017
    Сообщения:
    348
    Вы уже как Эминем в его прайм-тайм :) Утилита работает следующим образом: сначала создаётся целевой процесс (указанный как "loader.exe") в приостановленном состоянии, затем определяется адрес функции NtSetContextThread внутри этого процесса. После этого программа пробует несколько подходов для добавления исключения CFG для этого адреса, используя функцию Windows API SetProcessValidCallTargets.
    --- Сообщение объединено, 1 апр 2025 в 00:03 ---
    Это чисто для души потестить.
    --- Сообщение объединено, 1 апр 2025 в 00:34 ---
    этому парню пригодился бы кодес
    --- Сообщение объединено, 1 апр 2025 в 00:45 ---
    Из демки выходит, что смена eip для cfg безопасна. Если cfg чёто не понрав то вы точно узнаете.
     

    Вложения:

    Ahimov нравится это.
  4. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    188
    Тут что то довольно трудно найти, поиск весьма кривой. Если поискать гуглом, он находит это.

    Как тут ссылку найти я не знаю.

    Обход CFG посредством слим APC.

    Это было время срачей", виксов, покрытий и тп. Если тема сохранилась, то там должны сурки быть.
    --- Сообщение объединено, 1 апр 2025 в 01:19 ---
    Кстате а что с кл, чего он висит ?
     

    Вложения:

    • Slim (4).pdf
      Размер файла:
      59,2 КБ
      Просмотров:
      13
  5. galenkane

    galenkane Active Member

    Публикаций:
    0
    Регистрация:
    13 янв 2017
    Сообщения:
    348
    кл вроде норм работает. если тот который с домином тим.

    Набросал кодес под ваше описание из pdf, в RtlReleaseSRWLockExclusive
    не падает
    Код (C++):
    1.         SlimLock->Ptr = (PVOID)1; // Simple signaling for demo
    2.  
    код не претендует на конечную реализацию механизма)

    :scratch_one-s_head:
     

    Вложения:

    • SlimBloc.zip
      Размер файла:
      13,3 КБ
      Просмотров:
      11
    Последнее редактирование: 1 апр 2025 в 03:05
  6. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    188
    А да работает пингуется, под впн. Скоро походу вообще ничего без него не будет работать в рф.)