Перехват 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?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.