Blog. Just Blog

Работа с Zone.Identifier на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Несколько лет назад я выкладывал пару статей на тему блокировки файлов с помощью альтернативных файловых потоков и Zone.Identifier. Там вся работа с ними выполнялась или средствами самой системы Windows, или сторонними приложениями. Настало время написать собственное приложение.

Сперва немного теории. За блокировку файлов отвечает COM-объект IZoneIdentifier для работы с которым нам потребуется несколько структур, GUID'ов и констант, про которые не знает FASM.
  1. ; GUID {0968E258-16C7-4DBA-AA86-462DD61E31A3}
  2. CLSID_PersistentZoneIdentifier \
  3.     dd 00968E258h
  4.     dw 016C7h
  5.     dw 04DBAh
  6.     db 0AAh, 086h, 046h, 02Dh, 0D6h, 01Eh, 031h, 0A3h
  7.  
  8. ; GUID {CD45F185-1B21-48E2-967B-EAD743A8914E}
  9. IID_IZoneIdentifier \
  10.     dd 0CD45F185h
  11.     dw 01B21h
  12.     dw 048E2h
  13.     db 096h, 07Bh, 0EAh, 0D7h, 043h, 0A8h, 091h, 04Eh
  14.  
  15. ; GUID {0000010B-0000-0000-C000-000000000046}
  16. IID_IPersistFile \
  17.     dd 00000010Bh
  18.     dw 00000h
  19.     dw 00000h
  20.     db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
  21.  
  22. ; IID_IZoneIdentifier Interface
  23. struct IZoneIdentifier
  24.     ; IUnknown
  25.     QueryInterface dd ?   ; 000h
  26.     AddRef         dd ?   ; 004h
  27.     Release        dd ?   ; 008h
  28.     ; IZoneIdentifier
  29.     GetId          dd ?   ; 00Ch
  30.     SetId          dd ?   ; 010h
  31.     Remove         dd ?   ; 014h
  32. ends
  33.  
  34. ; IID_IPersistFile Interface
  35. struct IPersistFile
  36.     ; IUnknown
  37.     QueryInterface dd ?   ; 000h
  38.     AddRef         dd ?   ; 004h
  39.     Release        dd ?   ; 008h
  40.     ; IPersistFile
  41.     GetClassID     dd ?   ; 00Ch
  42.     IsDirty        dd ?   ; 010h
  43.     Load           dd ?   ; 014h
  44.     Save           dd ?   ; 018h
  45.     SaveCompleted  dd ?   ; 01Ch
  46.     GetCurFile     dd ?   ; 020h
  47. ends
  48.  
  49. CLSCTX_INPROC_SERVER = 1
  50. S_OK                 = 0
  51. STGM_READ            = 0
Интерфейс IZoneIdentifier предоставляет три метода для работы с Zone.Identifier: получение текущего значения, установка или изменение идентификатора и его полное удаление.

Как вы знаете из предыдущих статей, идентификатор зоны не может существовать сам по себе, он должен быть привязан к файлу. Для связки интерфейса IZoneIdentifier с файлом на диске требуется сперва получить интерфейс IPersistFile. После этого для работы с методами GetId и Remove нужно попробовать загрузить файл при помощи метода Load. Почему именно "попробовать"? Дело в том, что если файл был ранее разблокирован или у него вообще не было альтернативного файлового потока Zone.Identifier, то при вызове метод загрузки вернет ошибку ERR_FILE_NOT_FOUND. Метод SetId предварительной загрузки файла не требует. Пути к файлам обязательно должны быть полными и записаны в юникоде.

Начнем программирование с получения идентификатора зоны файла. Тут все просто. Проверяем наличие альтернативного потока Zone.Identifier в момент загрузки файла, если он присутствует, то запрашиваем его значение.
  1.         ; Инициализировать COM-объект
  2.         invoke  CoInitialize,NULL
  3.  
  4.         ; Получить полный путь к файлу
  5.         invoke  GetFullPathName,fname,MAX_PATH,szPath,NULL
  6.         or      eax,eax
  7.         jz      loc_exit
  8.  
  9.         ; Создать объект
  10.         invoke  CoCreateInstance,CLSID_PersistentZoneIdentifier,NULL,\
  11.                 CLSCTX_INPROC_SERVER,IID_IZoneIdentifier,pZoneId
  12.         cmp     eax,S_OK
  13.         jne     loc_exit
  14.  
  15.         ; Получить интерфейс IPersistFile объекта
  16.         mov     eax,[pZoneId]
  17.         mov     eax,[eax]
  18.         stdcall dword [eax+IZoneIdentifier.QueryInterface],[pZoneId],\
  19.                 IID_IPersistFile,pPFile
  20.         or      eax,eax
  21.         jnz     loc_done2
  22.  
  23.         ; Попробовать загрузить файл
  24.         mov     eax,[pPFile]
  25.         mov     eax,[eax]
  26.         stdcall dword [eax+IPersistFile.Load],[pPFile],\
  27.                 szPath,STGM_READ
  28.         cmp     eax,S_OK
  29.         je      @f
  30.  
  31.         ; Идентификатора нет
  32.         jmp     loc_done1
  33. @@:
  34.         ; Получить значение идентификатора
  35.         mov     eax,[pZoneId]
  36.         mov     eax,[eax]
  37.         stdcall dword [eax+IZoneIdentifier.GetId],[pZoneId],\
  38.                 dZoneID
  39.         or      eax,eax
  40.         jnz     loc_done1
  41.  
  42.         ; [dZoneID] = значение идентификатора
  43.  
  44.         ; Прибраться за собой
  45. loc_done1:
  46.         mov     eax,[pPFile]
  47.         mov     eax,[eax]
  48.         stdcall [eax+IPersistFile.Release],[pPFile]
  49. loc_done2:
  50.         mov     eax,[pZoneId]
  51.         mov     eax,[eax]
  52.         stdcall [eax+IZoneIdentifier.Release],[pZoneId]
  53. loc_exit:
  54.         ; Удалить объект
  55.         invoke  CoUninitialize
Теперь установка или изменение имеющегося значения Zone.Identifier. Как я уже говорил, тут предварительная загрузка файла не требуется. Выбираем нужное значение идентификатора зоны из списка, устанавливаем это значение и затем сохраняем изменения. Если файловая система не поддерживает альтернативные потоки, родительский файл отсутствует или по какой-то причине диск недоступен для записи, то метод Save вернет ошибку.
  1.         ; Инициализировать COM-объект
  2.         invoke  CoInitialize,NULL
  3.  
  4.         ; Получить полный путь к файлу
  5.         invoke  GetFullPathName,fname,MAX_PATH,szPath,NULL
  6.         or      eax,eax
  7.         jz      loc_exit
  8.  
  9.         ; Создать объект
  10.         invoke  CoCreateInstance,CLSID_PersistentZoneIdentifier,NULL,\
  11.                 CLSCTX_INPROC_SERVER,IID_IZoneIdentifier,pZoneId
  12.         cmp     eax,S_OK
  13.         jne     loc_exit
  14.  
  15.         ; Получить интерфейс IPersistFile объекта
  16.         mov     eax,[pZoneId]
  17.         mov     eax,[eax]
  18.         stdcall dword [eax+IZoneIdentifier.QueryInterface],[pZoneId],\
  19.                 IID_IPersistFile,pPFile
  20.         or      eax,eax
  21.         jnz     loc_done2
  22.  
  23.         ; Установить идентификатор
  24.         mov     eax,[pZoneId]
  25.         mov     eax,[eax]
  26.         stdcall dword [eax+IZoneIdentifier.SetId],[pZoneId],\
  27.                 URLZONE_INTERNET
  28.         or      eax,eax
  29.         jnz     loc_done2
  30.  
  31.         ; Применить изменения
  32.         mov     eax,[pPFile]
  33.         mov     eax,[eax]
  34.         stdcall dword [eax+IPersistFile.Save],[pPFile],\
  35.                 szPath,TRUE
  36.         or      eax,eax
  37.         jnz     loc_done1
  38.  
  39.         ; Новое значение идентификатора установлено
  40.  
  41.         ; Прибраться за собой
  42. loc_done1:
  43.         mov     eax,[pPFile]
  44.         mov     eax,[eax]
  45.         stdcall [eax+IPersistFile.Release],[pPFile]
  46. loc_done2:
  47.         mov     eax,[pZoneId]
  48.         mov     eax,[eax]
  49.         stdcall [eax+IZoneIdentifier.Release],[pZoneId]
  50. loc_exit:
  51.         ; Удалить объект
  52.         invoke  CoUninitialize
Удаление альтернативного потока Zone.Identifier также начинается с вызова метода загрузки файла. Если на этом этапе возникла ошибка, то и удалять дальше нечего. Если файл успешно загружен, то есть с ним связан идентификатор зоны, можно этот идентификатор удалить. После успешного удаления обязательно надо применить сделанные изменения.
  1.         ; Инициализировать COM-объект
  2.         invoke  CoInitialize,NULL
  3.  
  4.         ; Получить полный путь к файлу
  5.         invoke  GetFullPathName,fname,MAX_PATH,szPath,NULL
  6.         or      eax,eax
  7.         jz      loc_exit
  8.  
  9.         ; Создать объект
  10.         invoke  CoCreateInstance,CLSID_PersistentZoneIdentifier,NULL,\
  11.                 CLSCTX_INPROC_SERVER,IID_IZoneIdentifier,pZoneId
  12.         cmp     eax,S_OK
  13.         jne     loc_exit
  14.  
  15.         ; Получить интерфейс IPersistFile объекта
  16.         mov     eax,[pZoneId]
  17.         mov     eax,[eax]
  18.         stdcall dword [eax+IZoneIdentifier.QueryInterface],[pZoneId],\
  19.                 IID_IPersistFile,pPFile
  20.         or      eax,eax
  21.         jnz     loc_done2
  22.  
  23.         ; Попробовать загрузить файл
  24.         mov     eax,[pPFile]
  25.         mov     eax,[eax]
  26.         stdcall dword [eax+IPersistFile.Load],[pPFile],\
  27.                 szPath,STGM_READ
  28.         cmp     eax,S_OK
  29.         je      @f
  30.  
  31.         ; Идентификатора нет
  32.         jmp     loc_done1
  33. @@:
  34.         ; Удалить идентификатор
  35.         mov     eax,[pZoneId]
  36.         mov     eax,[eax]
  37.         stdcall dword [eax+IZoneIdentifier.Remove],[pZoneId]
  38.         or      eax,eax
  39.         jnz     loc_done1
  40.  
  41.         ; Применить изменения
  42.         mov     eax,[pPFile]
  43.         mov     eax,[eax]
  44.         stdcall dword [eax+IPersistFile.Save],[pPFile],\
  45.                 szPath,TRUE
  46.         or      eax,eax
  47.         jnz     loc_done1
  48.  
  49.         ; Идентификатор успешно удален
  50.  
  51.         ; Прибраться за собой
  52. loc_done1:
  53.         mov     eax,[pPFile]
  54.         mov     eax,[eax]
  55.         stdcall [eax+IPersistFile.Release],[pPFile]
  56. loc_done2:
  57.         mov     eax,[pZoneId]
  58.         mov     eax,[eax]
  59.         stdcall [eax+IZoneIdentifier.Release],[pZoneId]
  60. loc_exit:
  61.         ; Удалить объект
  62.         invoke  CoUninitialize
В приложение примеры программ с исходными текстами, которые получают, изменяют и удаляют Zone.Identifier у файла.

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

Zone.Identifier.Demo.zip (6,851 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (21.05.2023 в 20:49):
Зрители аплодируют, аплодируют, закончили аплодировать. Можно было бы упомянуть, что в Zone.Identifier кроме идентификатора содержится разная полезная информация типа ссылки на источник файла, но зачем? Только хардкор, только DeleteFile.
индеклерк (21.05.2023 в 18:59):
invoke DeleteFile, "c:\setup.exe:Zone.Identifier"
Vladimir (12.05.2023 в 15:19):
Знаю, можно и через PowerShell, просто нравится ваш софт за минималистичность и скорость работы. Я так ваши Total Exif Annihilator и Tiny Image Converter на кнопки приспособил, удобно.
ManHunter (12.05.2023 в 15:10):
Вряд ли. Получается ровно столько же движений, как если разблокировать файл через меню свойств в Проводнике. А для командной строки есть Streams от Марка Руссиновича.
Vladimir (12.05.2023 в 15:07):
Если бы вы сделали поддержку командной строки для remove_zone.exe, то было бы удобно повесить его на кнопку в Тотале. Вдруг вам захочется.

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

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

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