Перехват NtXxxFile в Windows 7
От: miksayer  
Дата: 14.09.10 21:07
Оценка:
Доброго времени суток!
Мне необходимо мониторить у некоторого процесса все его обращения к файловой системе. Для этого я решил перехватывать функции NtXxxFile. Я внедрил в этот процесс DLL-ку через CreateRemoteProcess(по Рихтеру). Тут проблем ничего не составило, а дальше они начались. Вот основные куски кода моей dll-ки(перехватываю заменой первых байт машинного кода функции):

void StopThreads()
{
    DWORD CurrTh, CurrPr;
    HANDLE h, ThrHandle;
    THREADENTRY32 Thread;
    
    CurrTh = GetCurrentThreadId();
    CurrPr = GetCurrentProcessId();
    h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (h != INVALID_HANDLE_VALUE)
    {
        Thread.dwSize = sizeof(THREADENTRY32);
        if (Thread32First(h, &Thread))
        do
        {
            if ((Thread.th32ThreadID != CurrTh) && (Thread.th32OwnerProcessID == CurrPr))
            {
                ThrHandle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, Thread.th32ThreadID);
                if (ThrHandle > 0)
                {
                    SuspendThread(ThrHandle);
                    CloseHandle(ThrHandle);
                }
            }
        } while (Thread32Next(h, &Thread));
        CloseHandle(h);
    }
}


void RunThreads()
{
    DWORD CurrTh, CurrPr;
    HANDLE h, ThrHandle;
    THREADENTRY32 Thread;
    
    CurrTh = GetCurrentThreadId();
    CurrPr = GetCurrentProcessId();
    h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (h != INVALID_HANDLE_VALUE)
    {
        Thread.dwSize = sizeof(THREADENTRY32);
        if (Thread32First(h, &Thread))
        do
        {
            if ((Thread.th32ThreadID != CurrTh) && (Thread.th32OwnerProcessID == CurrPr))
            {
                ThrHandle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, Thread.th32ThreadID);
                if (ThrHandle > 0)
                {
                    ResumeThread(ThrHandle);
                    CloseHandle(ThrHandle);
                }
            }
        } while (Thread32Next(h, &Thread));
        CloseHandle(h);
    }
}

NTSTATUS WINAPI NewNtOpenFile(PHANDLE FileHandle, 
                    ACCESS_MASK DesiredAccess,
                    POBJECT_ATTRIBUTES ObjectAttributes,
                    PIO_STATUS_BLOCK IoStatusBlock,
                    ULONG ShareAccess,
                    ULONG OpenOptions
                    )
{
    DWORD Written;
    WriteProcessMemory(GetCurrentProcess(), AdrNtOpenFile, &OldNtOpenFile, sizeof(far_jmp), &Written);
    MessageBox(0, L"NtOpenFile", 0, 0);
    WriteLogString(L"NtOpenFile\n");
    typedef NTSTATUS (WINAPI * NtOpenFileFuncType)(PHANDLE, 
                                    ACCESS_MASK, 
                                    POBJECT_ATTRIBUTES,
                                    PIO_STATUS_BLOCK,
                                    ULONG, ULONG);
    NtOpenFileFuncType NtOpenFileFunc = (NtOpenFileFuncType)AdrNtOpenFile;

    NTSTATUS ret = NtOpenFileFunc(FileHandle, DesiredAccess,
                                ObjectAttributes, IoStatusBlock,
                                ShareAccess, OpenOptions);
    WriteProcessMemory(GetCurrentProcess(), AdrNtOpenFile, &JmpNtOpenFile, sizeof(far_jmp), &Written);
    return ret;
}

void SetNtOpenFileHook()
{
    DWORD Written;

    AdrNtOpenFile = GetProcAddress(GetModuleHandle(L"Ntdll.dll"), "NtOpenFile");
    if (AdrNtOpenFile == 0)
    {
        MessageBox(NULL, L"Can't get NtOpenFile", L"Error!", 0);
        return;
    }
    
    JmpNtOpenFile.PushOp = 0x68;
    JmpNtOpenFile.PushArg = NewNtOpenFile;
    JmpNtOpenFile.RetOp = 0xC3;

    ReadProcessMemory(GetCurrentProcess(), AdrNtOpenFile, &OldNtOpenFile, sizeof(far_jmp), &Written);
    WriteProcessMemory(GetCurrentProcess(), AdrNtOpenFile, &JmpNtOpenFile, sizeof(far_jmp), &Written);

}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    DWORD Written;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        StopThreads();
        hLog = CreateFile(L"c:\\log.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        SetNtOpenFileHook();
        RunThreads();
        break;

    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        //WriteProcessMemory(GetCurrentProcess(), AdrNtOpenFile, &OldNtOpenFile, sizeof(far_jmp), &Written);
        break;
    }
    return TRUE;
}

Если внедрить эту дллку в процесс, который ВООБЩЕ не вызывает NtOpenFile(даже неявно, в моем случае это был просто стандартный шаблон win32 приложения из студии), то начинается нечто странное. При запуске вылетает мессаджбокс с надписью "NtOpenFile", т.е. будто бы эта АПИ-функция перхватилась, а при закрытии программы начинается бесконечный поток таких же месаджбоксов.
Если аналогично перехватывать NtCreateFile, то процесс вообще падает сразу после запуска.
Из-за чего может происходить такое веселье? Вроде все правильно. Аналогичный перехват, например, MessageBox работает нормально.
И еще: мне почему-то кажется, что тут дело в ОС. Возможно в Windows 7 запретили так перехватывать функции из Ntdll.dll?
Re: Перехват NtXxxFile в Windows 7
От: ononim  
Дата: 14.09.10 22:12
Оценка: +1
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, — при одновременном вызове перехваченной ф-ии из разных потоков будет плохо. Кроме того он может содержать и другие проблемы. И вообще — скачайте детурс, вроде он бесплатный еще.
Как много веселых ребят, и все делают велосипед...
Re: Перехват NtXxxFile в Windows 7
От: Were  
Дата: 14.09.10 23:19
Оценка:
Здравствуйте, miksayer, Вы писали:

Дополнительно к предыдущему оратору могу добавить, что не видно кода снятия защиты со страниц памяти ntdll. Не показано объявление JmpNtOpenFile, установлено-ли там выравнивание по 1 байту?
Re[2]: Перехват NtXxxFile в Windows 7
От: miksayer  
Дата: 15.09.10 05:47
Оценка:
Здравствуйте, ononim, Вы писали:

А какие меры надо предпринять против бесконечной рекурсии?
И еще: я веду лог-файл обращений к ФС. Т.е. вы хотите сказать, что надежнее будет писать посредством NtXxxFile функций?
Re[2]: Перехват NtXxxFile в Windows 7
От: miksayer  
Дата: 15.09.10 05:48
Оценка:
Здравствуйте, Were, Вы писали:

W>Здравствуйте, miksayer, Вы писали:


W>Дополнительно к предыдущему оратору могу добавить, что не видно кода снятия защиты со страниц памяти ntdll. Не показано объявление JmpNtOpenFile, установлено-ли там выравнивание по 1 байту?


Выравнивание стоит. А про снятие защиты со страниц памяти ntdll никогда не слышал. Как это делается?
Re[2]: Перехват NtXxxFile в Windows 7
От: miksayer  
Дата: 15.09.10 05:51
Оценка:
И по поводу thread-safe. Т.е. мне в принципе можно просто в начале функции-перехватчика вызывать StopThreads, а в конце RunThreads(их код я привел в первом сообщении)?
Re[3]: Перехват NtXxxFile в Windows 7
От: Were  
Дата: 15.09.10 06:33
Оценка:
Здравствуйте, miksayer, Вы писали:

M>Здравствуйте, Were, Вы писали:


W>>Здравствуйте, miksayer, Вы писали:


W>>Дополнительно к предыдущему оратору могу добавить, что не видно кода снятия защиты со страниц памяти ntdll. Не показано объявление JmpNtOpenFile, установлено-ли там выравнивание по 1 байту?


M>Выравнивание стоит. А про снятие защиты со страниц памяти ntdll никогда не слышал. Как это делается?


Нужно использовать VirtualProtect, чтобы убрать атрибут "только чтение" со страницы памяти ntdll, в которой находится нужная функции. Странно, если модификация работает без этого.
Re[4]: Перехват NtXxxFile в Windows 7
От: Pavel Dvorkin Россия  
Дата: 15.09.10 07:28
Оценка:
Здравствуйте, Were, Вы писали:

W>Нужно использовать VirtualProtect, чтобы убрать атрибут "только чтение" со страницы памяти ntdll, в которой находится нужная функции. Странно, если модификация работает без этого.


Ничего странного, если дело идет под отладчиком, он мог снять, ему же брекпойнты ставить.
With best regards
Pavel Dvorkin
Re: Перехват NtXxxFile в Windows 7
От: Jolly Roger  
Дата: 15.09.10 08:50
Оценка:
Здравствуйте, miksayer, Вы писали:

M> ReadProcessMemory(GetCurrentProcess(), AdrNtOpenFile, &OldNtOpenFile, sizeof(far_jmp), &Written);

M> WriteProcessMemory(GetCurrentProcess(), AdrNtOpenFile, &JmpNtOpenFile, sizeof(far_jmp), &Written);

Любопытный "ход конём" А почему-бы просто не memcpy?
"Нормальные герои всегда идут в обход!"
Re: Перехват NtXxxFile в Windows 7
От: De-Bugger  
Дата: 15.09.10 08:56
Оценка: +1
Здравствуйте, miksayer, Вы писали:

M>Доброго времени суток!

M>Мне необходимо мониторить у некоторого процесса все его обращения к файловой системе.

Драйвер-фильтр ФС. Все остальные способы — гемор на свою задницу, вечно падающие костыли и лучи поноса от благодарных пользователей в вашу сторону.
Re[2]: Перехват NtXxxFile в Windows 7
От: miksayer  
Дата: 15.09.10 13:25
Оценка: -1
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, miksayer, Вы писали:


JR>Любопытный "ход конём" А почему-бы просто не memcpy?


Потому что так у Рихтера было
Re[2]: Перехват NtXxxFile в Windows 7
От: miksayer  
Дата: 15.09.10 13:25
Оценка:
Здравствуйте, De-Bugger, Вы писали:

DB>Здравствуйте, miksayer, Вы писали:


DB>Драйвер-фильтр ФС. Все остальные способы — гемор на свою задницу, вечно падающие костыли и лучи поноса от благодарных пользователей в вашу сторону.


блин, нету никакого желания пока что учиться писать драйверы
Re[3]: Перехват NtXxxFile в Windows 7
От: x64 Россия  
Дата: 15.09.10 13:52
Оценка: 1 (1)
M>блин, нету никакого желания пока что учиться писать драйверы

Это единственно правильное решение данной задачи. Если сам не можешь, ну обратись к начальству, пусть закажут на стороне.
Re[4]: Перехват NtXxxFile в Windows 7
От: miksayer  
Дата: 15.09.10 14:40
Оценка:
Здравствуйте, x64, Вы писали:

M>>блин, нету никакого желания пока что учиться писать драйверы


x64>Это единственно правильное решение данной задачи. Если сам не можешь, ну обратись к начальству, пусть закажут на стороне.

это лаба вообще-то Вот задание:

5. Разработать программу, которая запускает приложение, переданное программе
на вход. После запуска приложения должна выполняться журнализация всех
обращений приложения к реестру и файловой системе. Для этого в запущенное
приложение должна подгружаться DLL-библиотека, перехватывающая функции
работы с файловой системой (NtXxxx). Перехват обращений к реестру можно
осуществить любым известным способом.

Как я понимаю, тут идет речь о том способе, которым я пытаюсь сделать.
Re[5]: Перехват NtXxxFile в Windows 7
От: x64 Россия  
Дата: 15.09.10 15:03
Оценка: +1 -2
M>это лаба вообще-то... Вот задание:

Ёлки, я вообще поражаюсь, как только наглости хватает в сраных универах давать задачи, которые люди решают в коммерческих компаниях за вполне приличные деньги, между прочим. Ну ты объясни преподу, что если он тебе заплатит пару тыщ зелени, то ты с радостью выполнишь это задание. А если нет, тогда не стоит, наверное, тратить на него время, учитывая что в соседней конторе (ну или во всяком случае в Москве точно) тебе будут за этот гемор ещё и приплачивать, и это будет явно не стипендия. Ну слов нет.
Re[5]: Перехват NtXxxFile в Windows 7
От: Pavel Dvorkin Россия  
Дата: 15.09.10 15:07
Оценка:
Здравствуйте, 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.
With best regards
Pavel Dvorkin
Re[6]: Перехват NtXxxFile в Windows 7
От: -prus-  
Дата: 16.09.10 07:16
Оценка:
Здравствуйте, x64, Вы писали:

x64>Ну ты объясни преподу, что если он тебе заплатит пару тыщ зелени, то ты с радостью выполнишь это задание.


Боюсь, как бы после этого препод у него не попросил пару тыщ зелени потом за экзамен или зачет .
С уважением,
Евгений
Re[7]: Перехват NtXxxFile в Windows 7
От: x64 Россия  
Дата: 16.09.10 07:32
Оценка:
P>Боюсь, как бы после этого препод у него не попросил пару тыщ зелени потом за экзамен или зачет :).

Ну так расставаться надо с такими учебными заведениями. Это, правда, моё скромное мнение. Сам-то я без высшего.
Re[8]: Перехват NtXxxFile в Windows 7
От: -prus-  
Дата: 16.09.10 07:43
Оценка:
Здравствуйте, x64, Вы писали:

x64>Ну так расставаться надо с такими учебными заведениями. Это, правда, моё скромное мнение. Сам-то я без высшего.


Да не, я к тому, что просто не поставят зачет или экзамен, если начнет выпендриваться. Задание есть задание и его нужно выполнять.
Тем более такая непростая задача откроет ему много нового. Это имхо все.
С уважением,
Евгений
Re[6]: Перехват NtXxxFile в Windows 7
От: Pavel Dvorkin Россия  
Дата: 16.09.10 09:45
Оценка:
Здравствуйте, x64, Вы писали:

M>>это лаба вообще-то... Вот задание:


x64>Ёлки, я вообще поражаюсь, как только наглости хватает в сраных универах давать задачи, которые люди решают в коммерческих компаниях за вполне приличные деньги, между прочим. Ну ты объясни преподу, что если он тебе заплатит пару тыщ зелени, то ты с радостью выполнишь это задание. А если нет, тогда не стоит, наверное, тратить на него время, учитывая что в соседней конторе (ну или во всяком случае в Москве точно) тебе будут за этот гемор ещё и приплачивать, и это будет явно не стипендия. Ну слов нет.


Категорически не согласен.

Сразу скажу — не обсуждаю конкретную ситуацию в вузе, так как не знаю деталей. Так что только по задаче.

А что тут, собственно, плохого ? Нормальная задача по системному программированию. Даже если студент не напишет полностью корректное решение, то по крайней мере познакомится с перехватом АПИ-функций, поймет, как импорт-экспорт устроены. А на каких тогда примерах их системному программированию обучать ? Или же вообще вуз должен ограничиться классом class Person и всеми его наследниками с Hibernate? Так ведь и за это в соседних конторах тоже платят.
Кстати, а где те, что в соседних конторах за деньги это делают, учились это делать ?
With best regards
Pavel Dvorkin
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.