Реферат: Методы перехвата API-вызовов в Win32
RtlCopyMemory(GDT, &Patch, 5); //jmp MGetDriveType
IsHook = true;
KeLowerIrql(oldirql); //Вернём IRQL обратно
return status;
}
Если функция GetDriveTypeA ещё не перехвачена (IsHook=false), то:
Определяется адрес функции GetDriveTypeA (он присылается в качестве параметра);
По адресу NewGetDriveType копируются 5 байт из начала GetDriveTypeA;
За ними вставляется байт 0xE9 (код команды jmp) и смещение до точки GetDriveTypeA + 5;
По адресу GetDriveTypeA вставляется 0xE9 и смещение до точки MGetDriveType;
Флаг перехвата IsHook устанавливается в true.
Функция снятия перехвата возвращает всё на свои места:
NTSTATUS DTDrvDev::DTDRV_IOCTL_UNHOOK_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; I.Information() = 0; if (!IsHook) return status; KIRQL oldirql; KeRaiseIrql(DISPATCH_LEVEL, &oldirql); //Поднимем IRQL до DISPATCH_LEVEL RtlCopyMemory(GDT, NewGetDriveType, 5); //Вернёмзаголовок GetDriveTypeA наместо IsHook = false; KeLowerIrql(oldirql); //Вернём IRQL обратно return status; } |
Данный метод – компромисс между гибкостью (перехват через таблицу импорта не требует написания драйвера), и мощью (по мощи он практически не уступает подмене кода в DLL), однако он реализуется только в Win9X.
Заключение
Итак, перехват API-вызовов – вещь, хотя и достаточно сложная, но все-таки реализуемая (причём различными способами). Методы перехвата различны и часто не переносимы из одной версии Windows в другую.
Microsoft старается сохранять совместимость программного обеспечения со старыми версиями Windows, но получается это далеко не всегда, и аспекты программирования, настолько приближённые к низкоуровневому системному программированию, очень сильно различаются для разных версий Windows. Поэтому часто приходится жертвовать эффективностью в ущерб универсальности – и наоборот.