Быть может вопрос в рубрику НОВИЧКИ, но т.к. драйвер, все же сюда напишу. Итак, веду перехват IoCreateFile в ядре. Схема: Переписываю первые 8 байт функции, FAR JUMP на свою naked функцию. Вид примерно такой (позаимствовал советы из ветки http://wasm.ru/forum/viewtopic.php?id=18923 ): Код (Text): __declspec(naked) new_IoCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength, IN CREATE_FILE_TYPE CreateFileType, IN PVOID ExtraCreateParameters, IN ULONG Options) { UNICODE_STRING unic; BOOLEAN notfound; notfound=FALSE; __asm { push ebp mov ebp, esp sub esp, 64 //make room for one local variable pushad } RtlInitUnicodeString(&unic, L"\\??\\C:\\file.txt"); if (0==RtlCompareUnicodeString(ObjectAttributes->ObjectName, &unic, TRUE)) { DPRINT("PID %ld IoCreate %S \n",PsGetCurrentProcessId() , ObjectAttributes->ObjectName->Buffer); // здесь мне надо возвратить в функцию STATUS_OBJECT_NAME_NOT_FOUND (типа чтобы файл не открылся) __asm { popad mov esp,ebp pop ebp // нужно ли это mov eax, 0xC0000034 // тут и не знаю что писать //leave ret } } __asm { popad mov esp,ebp pop ebp } __asm { _emit 0x8b // выполнение оригинальных команд _emit 0xff _emit 0x55 _emit 0x8b _emit 0xEC _emit 0x83 _emit 0xEC _emit 0x0C _emit 0xEA // джамп обратно на продолжение ориг. функции _emit 0xAA _emit 0xAA _emit 0xAA _emit 0xAA _emit 0x08 _emit 0x00 } } Т.е. после джампа на мою функцию проверяется, что за файл октрывается и выводится на печать, потом выполняются исходные инструкции и идет обратно джамп на следующие после этих 8 байт команды оригинальной функции. Я не могу сделать так, чтобы при успешном сравнении возвращялось ошибочное значение и дальше функция не шла.. Но не знаю как. Полистал справочник, статью "введение в машинный код" и другую литературу, но вот до такого момента не дошел.. Вроде в eax записал код ошибки, ret написал.. Инструкцию leave DDK не поддерживает (пока не пробовал делать спец. вставку).. Если "возвратить" состояние стека, то виснет при открытии нужного файла. Или синий экран. А если без этого (то есть просто отладочная печать и продолжение выполнения ориг. функции) то прекрасно работает (пока без синих экранов).. И еще вопрос, если у меня описана переменная - ну например булевА, то допустим при вызове одной программы CreateFile дело дойдет до этого обработчика, переменной установится значение -1.. Но перед тем как это значение будет использовано, другая программа успеет вызвать CreateFile и мой обработки запишет уже значение 0 в эту переменную, получится что в ту же самую переменную? И когда первая программа к ней обратиться, нарушиться логика программы? Правильно понимаю? Охотно почитаю документацию, но просто не знаю что искать и где...
Я читал статью (вообще читаю твой блог), допустим что фильтровать файловую систему еще можно, но нужно перехватывать и другие функции... В этом то и беда.. Например нужно защитить процесс от "убиения" - перехватом NtOpenProcess или NtTerminateProcess (в 95% этого хватит) и другие задачи.. так я бы жил с простой заменой адреса в таблице, но некоторые функции "перебивает" касперский, т.к. программа вполне законна, проблема пока не в сокрытии, а в том что перехват ставят другие продукты.
Напиши любую, правильную, на твой взгляд концовку, скомпилируй, засунь в иду, посмотри на указатель стека напротив каждой комманды(Options->general->disassembly->stack pointer), прикинь как он меняется, чтобы его корректно восстановить потом. Если не заработает -- запусти под сисером, протрассируй функцию, смотри на стек: запомни адрес возврата, регистры, сохраненные pushad и т.д., конечно муторно, но имхо так лучше всего прочувствовать что же происходит на самом деле, после одного такого разбора, больше подобных проблем не возникнет =)
Никакой беды покамест не вижу. Для фильтрации файловой системы используй файловые фильтры, для остального другие методы. Ты же сам потом рад не будешь, тебе же самому потом реально переписывать с нуля всё придётся. Не в этом так в другом проекте. Поверь мне, когда твоя квалификация уже позволит тебе принимать архитектурные решения, ты будешь в ужасе от этого. А вот это от незнания всё. Таблица SDT уже давно ни кем не используется для application-based защиты объектов ядра. Вместо этого используй хуки на методы типов. Касперский перемещает таблицу, поэтому стандартным способом ты ничего в ней не похукаешь. Я плотно это дело не копал, но там вроде адрес её надо из ETHREAD'а брать. Знающие люди поправят, если что.
Velheart, благодарю за совет. Сижу за сисером, но на данную минуту знаний не достаточно чтобы сходу разобраться в даресах возврата, т.е. нужно сидеть, разбираться, читать доку. Так и буду. Просто хотел урвать моментальное решение. Ну ладно. X64, прислушиваюсь ко всем советам, и так понимаю что нужно переходить на фильтры, но опять таки знаний не хватает. Вот только недавно перечитал осознанно книгу "рутикиты. Внедрение в ядро". там и про фильтры есть, но мало информации. А про касперский я сужу просто: запускаем AZV, он показывает что перехват ведется драйвером касперского, если я устанавливаю - то моим, соотв. так же сбивается мой перехватчик. Дело то в том, что именно сейчас нужно уже кое что заканчивать, и это самый короткий способ в моем случае.. Со временем конечно нужно развиваться, дойду и до фильтров и прочего... Ну а сейчас мне прийдется погрузиться в сисер или IDA.
test555 С кодом обработчика проблем быть не должно, там всё тривиально. Нельзя использовать модификацию инструкций длиной меньше ветвления, если это не синхронизировано с остальными процессорами. Можно это делать в IPI либо заменять ветвление на IopCreateFile(атомарно смещение на свой обработчик). Но изменение кода это очень не желательный способ.