#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;
}
Перехват NtOpenFile
Перехват осуществляется методом подмены адресов в таблице системных вызовов.
Для добавления имени файла необходимо передать символ 'a' и имя файла (без пробела)
> wrd.exe \\.\Driver
afile_name
Т.е. если я создаю какую-нибудь папку и пытаюсь ее открыть, то выскакивает ошибка.
Но препод приказал изменить прогу таким образом, чтобы сначала она запрещала доступ ко всем папкам в проводнике, а я мог той же wrd-командой разблокировать папку на открытие.
Код:
Я думаю что надо делать со структурой ObjectAttributes, текст сильно сократил. Сразу говорю писал не я, надеюсь на помощь профессионалов:)