Blog. Just Blog

Отслеживание изменений в каталоге на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Отслеживание изменений в каталоге на Ассемблере
Отслеживание изменений в каталоге на Ассемблере

Одна из интересных задач, с которой рано или поздно сталкивается системный программист - это отслеживание изменений в определенном каталоге или на всем диске целиком. Это может быть что-то типа файлового монитора или какого-нибудь программного триггера, срабатывающего при появлении или изменении определенного файла. Не стоит забывать и борьбу со всякой хитрозакрученной шароварой, когда надо точно и быстро отследить, в какой файл записывается регистрационная информация или триальный счетчик. В этой статье я расскажу, как сделать подобный монитор изменений в каталогах на чистом Ассемблере.

Сперва надо определить целую пачку констант, которых по умолчанию нет в библиотеках FASM. Они представляют собой различные флаги событий и их комбинации, а также идентификаторы произошедших изменений.
  1. ; Флаги для отслеживания отдельных изменений
  2. FILE_NOTIFY_CHANGE_FILE_NAME   = 0x00000001
  3. FILE_NOTIFY_CHANGE_DIR_NAME    = 0x00000002
  4. FILE_NOTIFY_CHANGE_ATTRIBUTES  = 0x00000004
  5. FILE_NOTIFY_CHANGE_SIZE        = 0x00000008
  6. FILE_NOTIFY_CHANGE_LAST_WRITE  = 0x00000010
  7. FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020
  8. FILE_NOTIFY_CHANGE_CREATION    = 0x00000040
  9. FILE_NOTIFY_CHANGE_SECURITY    = 0x00000100
  10.  
  11. ; Сводный флаг для отслеживания всех изменений
  12. FILE_NOTIFY_CHANGE = FILE_NOTIFY_CHANGE_FILE_NAME or \
  13.         FILE_NOTIFY_CHANGE_DIR_NAME or \
  14.         FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or \
  15.         FILE_NOTIFY_CHANGE_LAST_WRITE or FILE_NOTIFY_CHANGE_LAST_ACCESS or \
  16.         FILE_NOTIFY_CHANGE_CREATION or FILE_NOTIFY_CHANGE_SECURITY
  17.  
  18. ; Флаги для идентификации произошедших изменений
  19. FILE_ACTION_ADDED                   = 0x00000001
  20. FILE_ACTION_REMOVED                 = 0x00000002
  21. FILE_ACTION_MODIFIED                = 0x00000003
  22. FILE_ACTION_RENAMED_OLD_NAME        = 0x00000004
  23. FILE_ACTION_RENAMED_NEW_NAME        = 0x00000005
Теперь сама функция обработки всех произошедших изменений. Очень важно, чтобы она обязательно запускалась в отдельном потоке. Дело в том, что используемая в ней функция ReadDirectoryChangesW останавливает выполнение программы до наступления очередного события, и, если ее использовать в основном потоке, то ничем хорошим это не закончится.
  1. ;-----------------------------------------
  2. ; Процедура наблюдателя за изменениями
  3. ;-----------------------------------------
  4. proc WatchProc hWnd:DWORD
  5.         ; Получить хэндл каталога для наблюдения
  6.         invoke  CreateFile,szFile,GENERIC_READ,FILE_SHARE_READ or\
  7.                 FILE_SHARE_WRITE or FILE_SHARE_DELETE, NULL, OPEN_EXISTING,\
  8.                 FILE_FLAG_BACKUP_SEMANTICS,0
  9.         mov     [hFile],eax
  10. .loc_watch:
  11.         ; Ожидать происходящие изменения
  12.         invoke  ReadDirectoryChangesW,[hFile], fni, MAX_PATH, TRUE,\
  13.                 FILE_NOTIFY_CHANGE,tmp,NULL,NULL
  14.         cmp     [tmp],0
  15.         je      .loc_watch
  16.  
  17.         mov     ebx,fni
  18.  
  19. .loc_process:
  20.         ; [ebx+FILE_NOTIFY_INFORMATION.FileName] - имя измененного файла
  21.         ; [ebx+FILE_NOTIFY_INFORMATION.FileNameLength] - длина имени файла
  22.  
  23.         ; Файл добавлен
  24.         cmp     [ebx+FILE_NOTIFY_INFORMATION.Action],FILE_ACTION_ADDED
  25.         je      .loc_added
  26.         ; Файл удален
  27.         cmp     [ebx+FILE_NOTIFY_INFORMATION.Action],FILE_ACTION_REMOVED
  28.         je      .loc_removed
  29.         ; Файл изменен
  30.         cmp     [ebx+FILE_NOTIFY_INFORMATION.Action],FILE_ACTION_MODIFIED
  31.         je      .loc_modified
  32.         ; Файл переименован - старое имя
  33.         cmp     [ebx+FILE_NOTIFY_INFORMATION.Action],FILE_ACTION_RENAMED_OLD_NAME
  34.         je      .loc_renamed_old
  35.         ; Файл переименован - новое имя
  36.         cmp     [ebx+FILE_NOTIFY_INFORMATION.Action],FILE_ACTION_RENAMED_NEW_NAME
  37.         je      .loc_renamed_new
  38.         ...
  39.         ...
  40.         ; Обработка событий
  41.         ...
  42.         ...
  43.         ; Произошло более одного изменения?
  44.         cmp     [ebx+FILE_NOTIFY_INFORMATION.NextEntryOffset],0
  45.         je      .loc_watch
  46.         ; Указатель на следующую структуру с информацией об изменении
  47.         add     ebx,[ebx+FILE_NOTIFY_INFORMATION.NextEntryOffset]
  48.  
  49.         jmp     .loc_process
  50. .loc_exit:
  51.         ret
  52. endp
Принцип ее работы простой. Сперва получаем хэндл каталога, в котором требуется отслеживать изменения, затем в цикле ожидаем наступление события. Подробности события передаются в структуре FILE_NOTIFY_INFORMATION. Также обратите внимание, что в одном событии может быть несколько изменений, в этом случае в структуре FILE_NOTIFY_INFORMATION будет заполнен указатель на структуру с описанием следующего события. Например, при переименовании файла приходят два события с информацией о старом и новом имени файла. Меняя комбинацию флагов, можно настроить обработчик на обработку только конкретных событий, а также на отслеживание изменений не только в выбранном каталоге, но и в его подкаталогах.

В приложении пример программы с исходным текстом, которая мониторит все изменения на диске C: и вложенных каталогах, и выводит полученные данные в окно лога.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Folder.Watch.Demo.zip (3,409 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 5499 | Комментариев: 10

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (03.10.2020 в 14:46):
Просто взять и ручками дописать в импорт ReadDirectoryChangesW, вот и все решение. Нельзя же во всем полагаться на инклуды, в FASM они остановились в развитии на поддержке Win2000.
Олег (03.10.2020 в 14:29):
Скачал FASM, хочу скомпилировать для корня другого диска - не хочет.
Оказалось что в "INCLUDE" нету под-директории "\apiw\", только "\api\".
Изменил исходник, всё равно не компилирует - теперь не знает 'ReadDirectoryChangesW'.
У вас какие-то свои "INCLUDE"? Где бы их взять? Спасибо!
FFFF (14.09.2020 в 20:44):
Неплохо! Осталось то же для регистра - и прокмон мона в мусор.
ManHunter (10.04.2017 в 01:34):
А что, недостаточно чистый? Или WinAPI не труЪ, нужен уровень драйвера диска?
Nobody4all (10.04.2017 в 01:27):
писал что на чистом ассемблере )))
Рысь (01.10.2015 в 15:56):
Здорово, спасибо! Узнал что некий "USBModem-MegaFon", который не подключался и не включался (и был удалён из автозагрузки) уже года два как постоянно что-то пишет в свой лог.
Ещё бы сохранение в файл и возможность указывать папку для мониторинга через параметр командной строки...
ManHunter (25.08.2015 в 23:18):
Отслеживает, но обозначает только как модификацию файла \system32
Sergey (25.08.2015 в 23:02):
А запись в файловый поток таким образом отслеживается? Например в \system32:blablabla
ManHunter (17.08.2015 в 13:28):
Ага, особенно когда прога пишет свой триал куда-нибудь в \system32\kernel33.dll
user (17.08.2015 в 12:34):
Короче, это логгер, в отличие от ревизора наподобие AdInf'a.
Тоже нужная штука.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0045 сек.) / Память: 4.5 Mb
Наверх