Здравствуйте! Возникла необходимость мониторить запуск файлов в системе. Сделал SDT перехваты. Нужно контролировать неизменность файлов. Для этого попытался считать хэш (функции рабочие). Код (Text): NTSTATUS HashFile(CHAR *hash,UNICODE_STRING *fname) { OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK iosb; NTSTATUS status; HANDLE SourceFileHandle; FILE_STANDARD_INFORMATION fsi; int i=0,BufferSize=32; CHAR Buffer[32]; sha256_context shctx; UCHAR dest[32]; strcpy(hash,""); InitializeObjectAttributes (&oa, fname, OBJ_CASE_INSENSITIVE , NULL, NULL); status = ZwCreateFile(&SourceFileHandle, FILE_READ_DATA, &oa, &iosb, 0, FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (status==STATUS_SUCCESS) { status=ZwQueryInformationFile(SourceFileHandle,&iosb,&fsi,sizeof(fsi),FileStandardInformation); if (status==STATUS_SUCCESS) { sha256_init(&shctx); do { memset(&Buffer, 0, sizeof(Buffer)); status = ZwReadFile(SourceFileHandle, NULL, NULL, NULL, &iosb, &Buffer, BufferSize, NULL, NULL); if (status == STATUS_SUCCESS) { sha256_write(&shctx, &Buffer[0],iosb.Information); } } while ( NT_SUCCESS(status) ); sha256_final(&shctx); memset(dest, 0, 32); memcpy(dest, &shctx.sha_out, 32); HashToHexStr(hash,dest); } ZwClose(SourceFileHandle); } return status; } Также - строка пишется в файл: Код (Text): void WriteDataToLog(CHAR *LogStr) { IO_STATUS_BLOCK iosb; CHAR s[1024]; if ((int)hLogFile!=-1) { strcpy(s,LogStr); strcat(s,"\n"); ZwWriteFile (hLogFile, 0, NULL, NULL, &iosb,s, strlen(s), NULL, NULL); } } Но, видимо из-за частых операций работы с файлами - возникает BSOD (думаю, что происходят несколько попыток открытия и чтения одного файла). Дамп: Код (Text): kd> !analyze -v ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* UNEXPECTED_KERNEL_MODE_TRAP (7f) This means a trap occurred in kernel mode, and it's a trap of a kind that the kernel isn't allowed to have/catch (bound trap) or that is always instant death (double fault). The first number in the bugcheck params is the number of the trap (8 = double fault, etc) Consult an Intel x86 family manual to learn more about what these traps are. Here is a *portion* of those codes: If kv shows a taskGate use .tss on the part before the colon, then kv. Else if kv shows a trapframe use .trap on that value Else .trap on the appropriate frame will show where the trap was taken (on x86, this will be the ebp that goes with the procedure KiTrap) Endif kb will then show the corrected stack. Arguments: Arg1: 00000008, EXCEPTION_DOUBLE_FAULT Arg2: 80042000 Arg3: 00000000 Arg4: 00000000 Debugging Details: ------------------ ***** Kernel symbols are WRONG. Please fix symbols to do analysis. MODULE_NAME: nt FAULTING_MODULE: 804d0000 nt DEBUG_FLR_IMAGE_TIMESTAMP: 3b7de38f BUGCHECK_STR: 0x7f_8 DEFAULT_BUCKET_ID: DRIVER_FAULT LAST_CONTROL_TRANSFER: from 804d6b8f to 804fc1bb STACK_TEXT: WARNING: Stack unwind information not available. Following frames may be wrong. 80539160 804d6b8f 0000007f 00000008 80042000 nt!KeBugCheckEx+0x19 00000000 00000000 00000000 00000000 00000000 nt!Kei386EoiHelper+0x14d5 STACK_COMMAND: .bugcheck ; kb FOLLOWUP_NAME: MachineOwner BUCKET_ID: WRONG_SYMBOLS Followup: MachineOwner --------- Кто сможет помочь разобраться? Буду благодарен.
Вот непонятно, из-за чего это... Если нет файловых операций - все работает. А нельзя ли проверить - открыт ли уже файл с помощью функций ZwCreateFile/ZwOpenFile, чтобы не открывать его повторно? Что-то я читал про синхронный и асинхронный режимы чтения в ядре - не совсем понял. Кто этим пользовался?
Нуда, как сказал tchunya возможно ты из хука вызываешь похуканную функцию в твоем случае ZwCreateFile и попадаешь опять же на хук и опять всё повторяется. Как вариант можно сделать проще: 1) В хуке ZwCreateFile вызывать оригинальный адрес функции, чтобы файл открылся. Затем смотреть на права доступа на открытие. в твоем случае должны быть хотя бы права на чтение. 2) Далее ты юзаешь полученный хендл для вычисления хеша файла 3) Далее ставишь позицию указателя опять на начало файла. 4) Принимаешь правильное действие в зависимости от полученного хеша и оригинального. 5) возвращаешь результат (хендл) 3 и 4 пункт могут поменяться местами, в зависимости от того что ты делаешь при проверке.
А чем простые нотификаторы не устраивают вроди PsSetCreateProcessNotifyRoutine, PsSetLoadImageNotifyRoutine?
Очевидно, он хочет иметь возможность _запрещать_ старт процесса при определенных условиях, а нотификаторы на то и нотификаторы - позволяют узнать о свершившемся факте и только.
Не совсем так. Во-первых, в нотификаторе о загрузке образа имеется возможность пропатчить образ так, чтобы его точка входа не была выполнена. Во-вторых, колбеки файловых фильтров совершенно легально позволяют запрещать создание исполняемых секций. Ну и, в конце концов, колбек на процессы в Vista SP1 и выше позволяет запрещать непосредственно создание процессов легко и непринуждённо.
x64 Патчить - это как-то криво, согласись Файловые фильтры это да, но я про нотификаторы PsSetXXXNotifyRoutine говорил. И не только для Vista+, а для всех)
Вобще наверное рулит: 1. нотификаторы от PsSetXXXNotifyRoutine 2. перехват в SSDT 3. файловые фильтры чем собственно аверы и владеют
tchunya slesh Именно их. Нет, так как писал не я и я теперь разбираюсь в проблеме. Я тоже подумал про рекурсивный вызов, спасибо за идеи, буду пробовать. Great Точно, это тоже надо. Всем большое спасибо, Вы подтвердили мои догадки - теперь мне проще будет думать, так как проблема локализована - буду пробовать.