Доброго времени суток!
Мне необходимо мониторить у некоторого процесса все его обращения к файловой системе. Для этого я решил перехватывать функции NtXxxFile. Я внедрил в этот процесс DLL-ку через CreateRemoteProcess(по Рихтеру). Тут проблем ничего не составило, а дальше они начались. Вот основные куски кода моей dll-ки(перехватываю заменой первых байт машинного кода функции):
Если внедрить эту дллку в процесс, который ВООБЩЕ не вызывает NtOpenFile(даже неявно, в моем случае это был просто стандартный шаблон win32 приложения из студии), то начинается нечто странное. При запуске вылетает мессаджбокс с надписью "NtOpenFile", т.е. будто бы эта АПИ-функция перхватилась, а при закрытии программы начинается бесконечный поток таких же месаджбоксов.
Если аналогично перехватывать NtCreateFile, то процесс вообще падает сразу после запуска.
Из-за чего может происходить такое веселье? Вроде все правильно. Аналогичный перехват, например, MessageBox работает нормально.
И еще: мне почему-то кажется, что тут дело в ОС. Возможно в Windows 7 запретили так перехватывать функции из Ntdll.dll?
M>[/ccode] M>Если внедрить эту дллку в процесс, который ВООБЩЕ не вызывает NtOpenFile(даже неявно, в моем случае это был просто стандартный шаблон win32 приложения из студии), то начинается нечто странное. При запуске вылетает мессаджбокс с надписью "NtOpenFile", т.е. будто бы эта АПИ-функция перхватилась, а при закрытии программы начинается бесконечный поток таких же месаджбоксов.
NtOpenFile/NtCreateFile вызываются не только если ваше приложение вызвало ее. Ваше приложение — это не только код который вы написали, но еще и туева хуча системных длл который могут работать с файлами, драйверами, пайпами etc — все это ходит через Nt***File. Даже загрузка длл, то бишь LoadLibrary — это прежде всего открытие файла этой длл с последующим его мапингом в память. То есть LoadLibrary "внутри" вызывает как минимум — NtCreateFile/NtCreateSection/NtMapViewOfSection.
M>Если аналогично перехватывать NtCreateFile, то процесс вообще падает сразу после запуска. M>Из-за чего может происходить такое веселье? Вроде все правильно. Аналогичный перехват, например, MessageBox работает нормально. M>И еще: мне почему-то кажется, что тут дело в ОС. Возможно в Windows 7 запретили так перехватывать функции из Ntdll.dll?
Показывать MessageBox да и ваще пользоваться высокоуровневым по отношению к NT kernel services функционалом — надо как минимум очень, очень осторожно. MessageBox — это ведь создание диалога. А значит может быть открытие файла с ресурсами. Потом — user32 может начать подгружать разные длл с хуками, а это LoadLibrary, а LoadLibrary — это см выше, а это — бесконечная рекурсия, а вы против нее никаких мер не предприняли. Кроме того MessageBox как и другие win32 API может менять результат GetLastError, в то время как Nt* вызовы этим не занимаются что так же может поломать логику приложения. Вобщем с хуками на ntdll надо быть как ежикам с сексом.
PS кроме того ваш код не thread-safe, — при одновременном вызове перехваченной ф-ии из разных потоков будет плохо. Кроме того он может содержать и другие проблемы. И вообще — скачайте детурс, вроде он бесплатный еще.
Как много веселых ребят, и все делают велосипед...
Дополнительно к предыдущему оратору могу добавить, что не видно кода снятия защиты со страниц памяти ntdll. Не показано объявление JmpNtOpenFile, установлено-ли там выравнивание по 1 байту?
А какие меры надо предпринять против бесконечной рекурсии?
И еще: я веду лог-файл обращений к ФС. Т.е. вы хотите сказать, что надежнее будет писать посредством NtXxxFile функций?
Здравствуйте, Were, Вы писали:
W>Здравствуйте, miksayer, Вы писали:
W>Дополнительно к предыдущему оратору могу добавить, что не видно кода снятия защиты со страниц памяти ntdll. Не показано объявление JmpNtOpenFile, установлено-ли там выравнивание по 1 байту?
Выравнивание стоит. А про снятие защиты со страниц памяти ntdll никогда не слышал. Как это делается?
И по поводу thread-safe. Т.е. мне в принципе можно просто в начале функции-перехватчика вызывать StopThreads, а в конце RunThreads(их код я привел в первом сообщении)?
Здравствуйте, miksayer, Вы писали:
M>Здравствуйте, Were, Вы писали:
W>>Здравствуйте, miksayer, Вы писали:
W>>Дополнительно к предыдущему оратору могу добавить, что не видно кода снятия защиты со страниц памяти ntdll. Не показано объявление JmpNtOpenFile, установлено-ли там выравнивание по 1 байту?
M>Выравнивание стоит. А про снятие защиты со страниц памяти ntdll никогда не слышал. Как это делается?
Нужно использовать VirtualProtect, чтобы убрать атрибут "только чтение" со страницы памяти ntdll, в которой находится нужная функции. Странно, если модификация работает без этого.
Здравствуйте, Were, Вы писали:
W>Нужно использовать VirtualProtect, чтобы убрать атрибут "только чтение" со страницы памяти ntdll, в которой находится нужная функции. Странно, если модификация работает без этого.
Ничего странного, если дело идет под отладчиком, он мог снять, ему же брекпойнты ставить.
Здравствуйте, De-Bugger, Вы писали:
DB>Здравствуйте, miksayer, Вы писали:
DB>Драйвер-фильтр ФС. Все остальные способы — гемор на свою задницу, вечно падающие костыли и лучи поноса от благодарных пользователей в вашу сторону.
блин, нету никакого желания пока что учиться писать драйверы
Здравствуйте, x64, Вы писали:
M>>блин, нету никакого желания пока что учиться писать драйверы
x64>Это единственно правильное решение данной задачи. Если сам не можешь, ну обратись к начальству, пусть закажут на стороне.
это лаба вообще-то Вот задание:
5. Разработать программу, которая запускает приложение, переданное программе
на вход. После запуска приложения должна выполняться журнализация всех
обращений приложения к реестру и файловой системе. Для этого в запущенное
приложение должна подгружаться DLL-библиотека, перехватывающая функции
работы с файловой системой (NtXxxx). Перехват обращений к реестру можно
осуществить любым известным способом.
Как я понимаю, тут идет речь о том способе, которым я пытаюсь сделать.
Ёлки, я вообще поражаюсь, как только наглости хватает в сраных универах давать задачи, которые люди решают в коммерческих компаниях за вполне приличные деньги, между прочим. Ну ты объясни преподу, что если он тебе заплатит пару тыщ зелени, то ты с радостью выполнишь это задание. А если нет, тогда не стоит, наверное, тратить на него время, учитывая что в соседней конторе (ну или во всяком случае в Москве точно) тебе будут за этот гемор ещё и приплачивать, и это будет явно не стипендия. Ну слов нет.
Здравствуйте, miksayer, Вы писали:
M>5. Разработать программу, которая запускает приложение, переданное программе M>на вход. После запуска приложения должна выполняться журнализация всех M>обращений приложения к реестру и файловой системе.
Хм. Напрашивается флаг DEBUG_ONLY_THIS_PROCESS в CreateProcess и WaitForDebugEvent
case CREATE_PROCESS_DEBUG_EVENT:
// As needed, examine or change the registers of the
// process's initial thread with the GetThreadContext and
// SetThreadContext functions; read from and write to the
// process's virtual memory with the ReadProcessMemory and
// WriteProcessMemory functions; and suspend and resume
// thread execution with the SuspendThread and ResumeThread
// functions. Be sure to close the handle to the process image
// file with CloseHandle.
Здравствуйте, x64, Вы писали:
x64>Ну так расставаться надо с такими учебными заведениями. Это, правда, моё скромное мнение. Сам-то я без высшего.
Да не, я к тому, что просто не поставят зачет или экзамен, если начнет выпендриваться. Задание есть задание и его нужно выполнять.
Тем более такая непростая задача откроет ему много нового. Это имхо все.
Здравствуйте, x64, Вы писали:
M>>это лаба вообще-то... Вот задание:
x64>Ёлки, я вообще поражаюсь, как только наглости хватает в сраных универах давать задачи, которые люди решают в коммерческих компаниях за вполне приличные деньги, между прочим. Ну ты объясни преподу, что если он тебе заплатит пару тыщ зелени, то ты с радостью выполнишь это задание. А если нет, тогда не стоит, наверное, тратить на него время, учитывая что в соседней конторе (ну или во всяком случае в Москве точно) тебе будут за этот гемор ещё и приплачивать, и это будет явно не стипендия. Ну слов нет.
Категорически не согласен.
Сразу скажу — не обсуждаю конкретную ситуацию в вузе, так как не знаю деталей. Так что только по задаче.
А что тут, собственно, плохого ? Нормальная задача по системному программированию. Даже если студент не напишет полностью корректное решение, то по крайней мере познакомится с перехватом АПИ-функций, поймет, как импорт-экспорт устроены. А на каких тогда примерах их системному программированию обучать ? Или же вообще вуз должен ограничиться классом class Person и всеми его наследниками с Hibernate? Так ведь и за это в соседних конторах тоже платят.
Кстати, а где те, что в соседних конторах за деньги это делают, учились это делать ?