Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Вопрос Bootkit Hooking — BSOD при вызове MmCopyMemory через ntoskrnl

Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
429
Реакции
10
Народ, кто плотно ковыряет UEFI буткиты, нужна помощь по логике проброса хуков в ядро. Ситуация следующая: пытаюсь захукать MmCopyMemory через цепочку перехватов в winload.

Что уже сделано:
  1. Хукаю ExitBootServices.
  2. Выцепляю базу winload.efi.
  3. Ставлю хук на OslArchTransferToKernel.
  4. Внутри этого хука пытаюсь патчить ntoskrnl.exe.

Код хука выглядит примерно так:
Код:
Expand Collapse Copy
EFI_STATUS osl_arch_transfer_to_kernel_hook(uint64_t loader_block, uint64_t entry)
{
    uint64_t cr0 = AsmReadCr0();
    AsmWriteCr0(cr0 & ~0x10000ull);
    copy_memory((uint8_t*)g_osl_arch_transfer_to_kernel, g_osl_arch_transfer_to_kernel_bytes, 12);
    AsmWriteCr0(cr0);

    switch_ctx(0);
    KLDR_DATA_TABLE_ENTRY ntoskrnl = get_module_base(&lpb->LoadOrderListHead, L"ntoskrnl.exe");

    g_mm_copy_memory = (uint64_t)ntoskrnl.DllBase + 0x030C030;
    copy_memory(g_mm_copy_memory_bytes, (uint8_t*)g_mm_copy_memory, 12);

    uint64_t hook_address = (uint64_t)mm_copy_memory_hook;
    uint8_t shellcode[12] = {0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
    copy_memory(shellcode + 2, (uint8_t*)&hook_address, 8);

    cr0 = AsmReadCr0();
    AsmWriteCr0(cr0 & ~0x10000ull);
    copy_memory((uint8_t*)g_mm_copy_memory, shellcode, 12);
    AsmWriteCr0(cr0);

    return ((osl_arch_transfer_to_kernel_t)g_osl_arch_transfer_to_kernel)(loader_block, entry);
}

Суть проблемы:
Винда грузится нормально, но как только доходит до вызова MmCopyMemory, вылетает SYSTEM_SERVICE_EXCEPTION bugcheck.

Подозрение на то, что шеллкод делает прыжок по физическому адресу, который в контексте ядра уже невалиден. Пробовал делать ConvertPointer для адреса хука, но на выходе получаю честный 0x0. Если вместо прыжка вставлять просто xor rax, rax; ret, то патч отрабатывает и система не падает, но мне нужен полноценный трамплин.

Код:
Expand Collapse Copy
#include <stdint.h>
#include "tools.h"

typedef void(__stdcall* blp_arch_switch_context_t)(int);
EFI_SYSTEM_TABLE* g_system_table;
static EFI_EXIT_BOOT_SERVICES original_exit_boot_services = NULL;
static uint64_t g_osl_arch_transfer_to_kernel = 0;
static uint8_t g_osl_arch_transfer_to_kernel_bytes[12] = {0};
blp_arch_switch_context_t switch_ctx = 0;
typedef EFI_STATUS (*osl_arch_transfer_to_kernel_t)(uint64_t loader_block, uint64_t entry);
LOADER_PARAMETER_BLOCK* lpb = 0;

// ... helper functions ...

EFI_STATUS EFIAPI exit_boot_services_hook(EFI_HANDLE image_handle, uint64_t ebs_map_key)
{
    uint64_t return_address = (uint64_t)_ReturnAddress();
    gBS->ExitBootServices = original_exit_boot_services;
    uint64_t winload_efi = get_module_base_from_address(return_address);
    
    // Pattern matching winload for OslExecuteTransition and BlpArchSwitchContext
    // Setting up the hook for OslArchTransferToKernel
    
    return original_exit_boot_services(image_handle, ebs_map_key);
}

Явно где-то косячу с маппингом адресов при переходе из окружения EFI в ядро. Кто уже сталкивался с таким поведением при попытке захукать ntoskrnl на этапе загрузки?

Отпишитесь, кто фиксил подобные краши.
 
Назад
Сверху Снизу