Как уже отмечалось, идея перехвата состоит в перезаписи обработчиков IRP- пакетов. Для этого необходимо иметь возможность изменять поля структуры DRIVER. К счастью, существует функция Io. Get. Device. Pointer, которая возвращает указатель на объект вершины стека именованных устройств и указатель на соответствующий файловый объект.
Вот фрагмент кода функции, устанавливающей ловушку: NTSTATUS Hook. Device(LPWSTR lp. Device)UNICODE. Теперь заменим адреса обработчиков и функций выгрузки драйвера на свои: NTSTATUS Hook. Device(LPWSTR lp. Device)g. Driver.
Object = Device. Object- > Driver. Object; g. Device. Марес Мини Стен 58 Инструкция. Control = g. Driver. Object- > Major.
Function. Это необходимо делать для корректной выгрузки драйвера, чтобы не было утечки ресурсов и аналогичных ошибок. Так как указатель на объект драйвера защиты сохранeн, то чтобы снять ловушку, нужно просто восстановить прежние обработчики IRP- пакетов: void Unhook. Device(void)g. Driver. Object- > Major. Function. Так как система защиты по каким- либо причинам может закончить свою работу раньше нашего драйвера, то чтобы избежать краха системы из- за неверных указателей, обработаем это событие в функции Hook. Unload: void Hook. Unload(PDRIVER. Только нужно высвободить захваченные ресурсы и не вызывать сохранeнный g.
Cemu - Эмулятор Wii U для операционной системы Windows.
Hook. Unload. Принцип работы эмулятора. Перехватчик. Зная основные принципы простейшего перехвата IRP- пакетов, приступим к реализации пока только самого перехватчика для дальнейшего анализа.
Для этого создадим объект драйвера, который содержит символьное имя (например Dos. Devices. Hook) и точки входа CREATE, CLOSE, READ. Io. Create. Device(Driver. Object, 0, & us.
Device. Name, FILE. При такой реализации обмена данными между приложением и перехватчиком невозможно сразу же отправить их пользовательской программе, поэтому необходимо создать некоторую структуру для хранения необходимых данных о пойманном пакете. Например односвязный список, как это реализовано мной. Теперь следует определиться, какую информацию нужно буферизировать.
Это общая информация о пакете (тип, флаги, прочее) и, конечно, буферы. Также можно добавить время перехвата. При копировании содержимого буферов нужно помнить об их типе, иначе — крах. Забегая вперед, отмечу, что драйвер защиты использует буферизированный ввод- вывод, это немного упрощает код. Код Hook. Dispatchif (idl. Tail- > Irp. Data. Input. Length). Так как пакет содержит буферы, чье содержимое представляет интерес, то размер сообщений заранее не известен.
Поэтому поступим следующим образом: при первом чтении получаем общую информацию о пакете и размере буферов; при повторном читаем содержимое, удаляем звено из списка пакетов и не забываем про спиновые блокировки для последовательной работы с данными: Код Driver. Dispatch. Length = Io. SL- > Parameters. Read. Length; if (Length == sizeof(IRP. Из полученных логов становится видно, какие управляющие коды посылаются и их результаты. Также можно видеть, что запросы и ответы на два различных кода (9c. Казалось бы, можно построить табличный эмулятор, но после серии запусков убеждаемся, что это невозможно, так как содержимое буферов различно, и неизвестно, как оно образуется.
Перехваченные пакеты без ключа. Перехваченные пакеты с ключом.
Затем возможны несколько вариантов дальнейших действий: изучать дебри драйвера защиты; воспользоваться информацией самих разработчиков системы. Оба варианта дают необходимую информацию.
Итак, оказывается, содержимое пакетов шифруется публичным симметричным алгоритмом AES (Advanced Encryption Standard). Логичной целью является получение ключа шифрования. Но если еще больше углубиться в изучение устройства системы защиты, то окажется, что аппаратный ключ имеет уникальный номер и содержит всю необходимую информацию, но для доступа к нему требуются программные ключи. Пример дампа ключа. Поэтому первое, что нужно сделать, это получить ключ. Поставленную задачу может решить обычный брутфорс: unsigned short Key; unsigned char Ref.
Key. Для этого есть функции, определенные разработчиками. Функции HL. Это прототипы старых версий HASP SDK, но работают они и с новыми типами ключей, так как разработчики обеспечили обратную совместимость. Новый API мало отличается от старого, и это никак не сказывается на принципе работы брутфорса. Подробную документацию Hasp API, готовые реализации брутфорса и дампера ключей можно найти на диске.