Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Перехват NtOpenFile

445
04 ноября 2011 года
Charley
176 / / 16.08.2011
Драйвер перехватывает системные вызовы NtCreateFile и NtOpenFile.
Перехват осуществляется методом подмены адресов в таблице системных вызовов.
Для добавления имени файла необходимо передать символ 'a' и имя файла (без пробела)
> wrd.exe \\.\Driver
afile_name
Т.е. если я создаю какую-нибудь папку и пытаюсь ее открыть, то выскакивает ошибка.
Но препод приказал изменить прогу таким образом, чтобы сначала она запрещала доступ ко всем папкам в проводнике, а я мог той же wrd-командой разблокировать папку на открытие.
Код:
#include <ntddk.h>

#define SYM_LINK_NAME   L"\\Global??\\Driver"
#define DEVICE_NAME     L"\\Device\\DDriver"

UNICODE_STRING  DevName;        // имя устройства
UNICODE_STRING  SymLinkName;    // имя символьной ссылки

...
// номер вызова NtOpenFile в таблице системных вызовов
#define NUMBER_NT_OPEN_FILE   0x74

// номер вызова NtCreateFile в таблице системных вызовов
#define NUMBER_NT_CREATE_FILE   0x25

...

// адрес функции NtOpenFile
NT_OPEN_FILE glRealNtOpenFile;

// адрес функции NtCreateFile
NT_CREATE_FILE glRealNtCreateFile;

// таблица системных вызовов
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;

//структура, содержащая имена всех файлов
typedef struct _FileList
{
    UNICODE_STRING FileName;
    struct _FileList* next;
} FileList;

FileList* first = NULL;
FileList* cur = NULL;
int GeneralLen = 0;

//функции для работы со структурой

void AddToList(char* name);
int FindAtList(PUNICODE_STRING name);
int FindAtListForSysCall(PUNICODE_STRING name);
void RemoveList();

int AnalysisString(char* buffer, int* BufLen);
void CharToUnicodeString(PUNICODE_STRING unistr, char* buffer);
BOOLEAN CreateReadBuffer(char* buffer);
PCHAR GetSZFromUnicodeString(PUNICODE_STRING us, int* TempLen);
void GetFullName(PUNICODE_STRING name, PUNICODE_STRING FullName);
void GetRelativeName(PUNICODE_STRING name, PUNICODE_STRING RelativeName);

//*************************************************************
// описание функций


// функция инициализации драйвера
NTSTATUS DriverEntry (
...
...
    // запоминаем адрес реального обработчика вызова NtOpenFile
    glRealNtOpenFile = (NT_OPEN_FILE)KeServiceDescriptorTable->Base[NUMBER_NT_OPEN_FILE];

     // запоминаем адрес реального обработчика вызова NtCreateFile
    glRealNtCreateFile = (NT_CREATE_FILE)KeServiceDescriptorTable->Base[NUMBER_NT_CREATE_FILE];

    // подставляем адрес нового обработчика
    KeServiceDescriptorTable->Base[NUMBER_NT_OPEN_FILE] = (ULONG) HookNtOpenFile;

    // подставляем адрес нового обработчика
    KeServiceDescriptorTable->Base[NUMBER_NT_CREATE_FILE] = (ULONG) HookNtCreateFile;

    return status;
}

// функция выгрузки драйвера
VOID DriverUnload (IN PDRIVER_OBJECT DriverObject){

    // удаление символьной ссылки и объекта устройства

    IoDeleteSymbolicLink(&SymLinkName);
    IoDeleteDevice(DriverObject->DeviceObject);
    RemoveList();

    KeServiceDescriptorTable->Base[NUMBER_NT_OPEN_FILE] = (ULONG) glRealNtOpenFile;
    KeServiceDescriptorTable->Base[NUMBER_NT_CREATE_FILE] = (ULONG) glRealNtCreateFile;

    return;    
}

//функция добавления звена в список файлов
void AddToList(char* name)
{
    FileList *tmp;
    UNICODE_STRING UniName;

    CharToUnicodeString(&UniName, name);

    if(first == NULL)
    {
        first = ExAllocatePool(PagedPool, sizeof(FileList));

        first->FileName.Length = UniName.Length;
        first->FileName.MaximumLength = UniName.MaximumLength;
        first->FileName.Buffer = ExAllocatePool(NonPagedPool, UniName.MaximumLength);
        RtlCopyMemory(first->FileName.Buffer, UniName.Buffer, UniName.Length);

        first->next = NULL;

        GeneralLen += strlen(name) + 1;

        return;
    }

    if(!FindAtList(&UniName))
    {
        tmp = ExAllocatePool(PagedPool, sizeof(FileList));

        tmp->FileName.Length = UniName.Length;
        tmp->FileName.MaximumLength = UniName.MaximumLength;
        tmp->FileName.Buffer = ExAllocatePool(NonPagedPool, UniName.MaximumLength);
        RtlCopyMemory(tmp->FileName.Buffer, UniName.Buffer, UniName.Length);

        tmp->next = cur->next;
        cur->next = tmp;

        GeneralLen += strlen(name) + 1;
    }
}

//функция поиска звена по имени файла
int FindAtList(PUNICODE_STRING name)
{
    FileList* tmp;
    cur = first;

    if(first == NULL)
        return 0;

    do
    {
        if(!RtlCompareUnicodeString(&cur->FileName, name, TRUE))
            return 1;
       
        tmp = cur;
        cur = cur->next;
    }
    while(cur != NULL);

    cur = tmp;

    return 0;
}

//функция удаления списка имён файлов
void RemoveList()
{
    FileList* tmp;

    if(first == NULL)
        return;

    do
    {
        tmp = first->next;
        ExFreePool(first->FileName.Buffer);
        first = tmp;
    }
    while(first != NULL);

    GeneralLen = 0;
}

//поиск в списке имени файла
int FindAtListForSysCall(PUNICODE_STRING name)
{
    UNICODE_STRING FullName;
    UNICODE_STRING RelativeName;
    FileList* tmp;

    tmp = first;

    if(first == NULL)
        return 0;

    GetFullName(name, &FullName);
    GetRelativeName(name, &RelativeName);

    do
    {
        if(!RtlCompareUnicodeString(&tmp->FileName, &FullName, TRUE))
            return 1;

        if(!RtlCompareUnicodeString(&tmp->FileName, &RelativeName, TRUE))
            return 1;
       
        tmp = tmp->next;
    }
    while(tmp != NULL);

    return 0;
}

// функция-обработчик системного вызова NtOpenFile
NTSTATUS HookNtOpenFile(
    OUT PHANDLE FileHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN ULONG ShareAccess,
    IN ULONG OpenOptions
    )
{
FILE_OBJECT *file;
NTSTATUS status;
NTSTATUS retstatus;
KPROCESSOR_MODE mode;

    // получаем режим процессора (пользовательский или ядра) из которого пришёл запрос
    mode = ExGetPreviousMode();
    if(mode == KernelMode)
        mode = 'K';
    else
        mode = 'U';

    if(!FindAtListForSysCall(ObjectAttributes->ObjectName))
    {
        DbgPrint("NtOpenFile. FileName:%wZ\n", ObjectAttributes->ObjectName);

        return STATUS_OPEN_FAILED;
    }

    // вызываем NtOpenFile
    retstatus = glRealNtOpenFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,
        ShareAccess,OpenOptions);

    return retstatus;
}

// функция-обработчик системного вызова NtCreateFile
NTSTATUS HookNtCreateFile(
    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
    )
{
NTSTATUS status;
NTSTATUS retstatus;
KPROCESSOR_MODE mode;
FILE_NAME_INFORMATION *fni;
IO_STATUS_BLOCK isb;
UNICODE_STRING name;
char *TmpName;
char* CharName;
int NameLen = 0;

    // получаем режим процессора (пользовательский или ядра) из которого пришёл запрос
    mode = ExGetPreviousMode();
    if(mode == KernelMode)
        mode = 'K';
    else
        mode = 'U';

    // проверяем наличие корневой директории для файла
    // если есть, значит имя файла относительно этой директории
    if(ObjectAttributes->RootDirectory){
        // выделения памяти для информации о файле
        fni = (FILE_NAME_INFORMATION*) ExAllocatePool(PagedPool,0x1000);

        if(fni){
            // получение информации о файле
            status = ZwQueryInformationFile(
                     ObjectAttributes->RootDirectory,   // описатель файла
                     &isb,                              // адрес структуры IO_STATUS_BLOCK
                     fni,                               // буфер для сохранения информации
                     0x1000,                            // размер буфера
                     FileNameInformation                // тип информации - имя файла
                     );

            if(NT_SUCCESS(status))
            {
                fni->FileName[(isb.Information - 4) / 2] = 0;
                name.Length = isb.Information;
                name.MaximumLength = isb.Information;
                name.Buffer = ExAllocatePool(PagedPool, name.MaximumLength);

                RtlCopyMemory(name.Buffer, &fni->FileName, name.Length);

                TmpName = GetSZFromUnicodeString(&name, &NameLen);
                NameLen -= 2;
                TmpName[NameLen] = 0;
               
                CharName = ExAllocatePool(PagedPool, NameLen + 6);
                strncpy(CharName, "\\??\\C:", 6);
                CharName[6] = 0;
                strncat(CharName, TmpName, NameLen);
                CharToUnicodeString(&name, CharName);
               
                ExFreePool(TmpName);
                ExFreePool(CharName);

                if(FindAtListForSysCall(&name))
                {
                    DbgPrint("NtCreateFile_RootDir. FileName: %wZ\n", &name);
                    ExFreePool(name.Buffer);
                    ExFreePool(fni);

                    return STATUS_CANNOT_MAKE;                 
                }

                ExFreePool(name.Buffer);
            }
           
            ExFreePool(fni);
            }
    }
    else
    {
        if(FindAtListForSysCall(ObjectAttributes->ObjectName))
        {
            DbgPrint("NtCreateFile. FileName: %wZ\n", ObjectAttributes->ObjectName);

            return STATUS_CANNOT_MAKE; 
        }
    }
   
   
    // вызываем NtCreateFile
    retstatus = glRealNtCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,
        AllocationSize,FileAttributes,ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);

    return retstatus;
}

Я думаю что надо делать со структурой ObjectAttributes, текст сильно сократил. Сразу говорю писал не я, надеюсь на помощь профессионалов:)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог