Диски под замкомКрис Касперски Хакер, номер #111, стр. 111-030-1 Как предотвратить непреднамеренный доступ к жестким дискамПриходилось ли тебе прятать диски в системе? Отключать их, чтобы не было видно? Или просто блокировать, чтобы ни одна программа и особенно вирусы не могли производить с ними никаких действий? Все это кажется простейшей задачей, но только до тех пор, пока не приступаешь к ее решению. Оказывается, что в инете распространяются какие-то левые утилиты, которые мало того, что платные – они ненадежны и сильно глючат. Но сегодня они нам и не потребуются! Эта история началась много лет назад, когда «Дятел» (винчестер типа IBM-DTLA-307015), используемый в качестве вспомогательного накопителя, в результате естественной выработки подшипника начал свистеть, шуметь и вибрировать всем корпусом. Недолго думая, автор установил в настройках электропитания отключение диска через 3 минуты. Основой диск («Барракуда» от Seagate) работал бесшумно и, поскольку к нему постоянно обращались, никогда не отключался, а вот «Дятел» (куда складировались редко используемые файлы) по замыслу должен был уснуть и долго не просыпаться (благо машина перезагружается раз в месяц, а то и реже). Однако положенные три минуты истекли, а «Дятел» все никак не мог угомониться. Еще добрых минут десять винчестер продолжал шуметь, пока не обнаружилось, что он конфликтует с Process Explorer'ом Марка Руссиновича. После его закрытия «Дятел», зевнув, отправился на покой: вибрации прекратились, и воцарилась долгожданная тишина. Ненадолго! Через некоторое время «Дятел» проснулся вновь, раскручивая свой шпиндель! Это агент Windows подсуетился и сообщил, что на таком-то диске осталось мало места и не мешало бы его почистить. Вместо этого разъяренный мыщъх завалил самого агента! :) Несколько часов благословенной тишины и… вновь грохот пробуждающегося «Дятла»! Какая служебная программа потревожила его на этот раз? Ах, MS Photo Editor, который при запуске зачем-то перечитывает все диски. A DVD-Decryptor при грабеже фильмов автоматически пытается записать их на диск с наибольшим количеством свободного пространства, сканируя все, включая спящие. Тысячи программ нахально лезут туда, куда их не просят, и далеко не каждую из них можно от этого отучить. Обозначенная проблема довольно актуальна (особенно на компьютерах, где воткнуто большое количество дисков, но основная нагрузка ложиться на один из них, а остальные используются в резервных целях). И чтобы ее решить, мыщъх стал искать пути блокировки дисковых томов, что, в конечном счете, оказалось полезным не только для усыпления дисков, но и защиты данных от вирусных/хакерских атак. Даже если злоумышленник захватит администратора (вместе со всеми правами), он все равно не сможет ни открывать файлы, ни даже просматривать содержимое заблокированного тома. В дебрях MSDNВсякий, кто стакивался с Windows, знает, что chkdsk.exe блокирует дисковый том на время его лечения. Еще бы! Попытка исправления ошибок, сопровождаемая записью на диск со стороны других приложений, рискует превратить базовые структуры данных в кашу! Весь вопрос в том — как именно chkdsk.exe осуществляет блокировку? Он же ведь, зараза такая, ничего не говорит и исходных текстов нет (сейчас сырцами Windows забиты все файлообменные сети, но на тот момент у мыщъх'а их не было, так что приходилось плясать от печки). Ну, нет исходных текстов — и не надо. Зато есть дизассемблер и MSDN. Распотрошив chkdsk.exe в IDA Pro и натравив на него монитор IOCTL-запросов, собранный на базе отладчика soft-ice (точка останова на API-функцию DeviveIoControl с записью всех аргументов в лог-файл), мыщъх определил, что блокировка дискового тома осуществляется путем посылки ему вполне документированной команды FSCTL_LOCK_VOLUME. Эта команда подробно описана в SDK вместе с другими, среди которых значится и FSCTL_DISMOUNT_VOLUME, ставшая предметом одной забавной и в тоже время поучительной истории. Название FSCTL_DISMOUNT_VOLUME свидетельствует, что команда предназначена для размонтирования дисков, а в мире UNIX это равносильно потере доступа к ним на логическом уровне вплоть до последующего монтирования. Вот только Windows — это вам не UNIX! Это совсем другой зверь. Вспомни, когда ты в Windows последний раз вручную монтировал дискету или CD-ROM. Не помнишь? Вот, и я не помню. Windows, в отличие от UNIX, всегда монтирует диски автоматически! А SDK полезно читать последовательно — от корки до корки. В описании команды FSCTL_DISMOUNT_VOLUME недвусмысленно сказано, что размонтированный том обладает следующими свойствами: а) на нем отсутствуют открытые файлы; б) операционная система о нем «забывает». Казалось бы, то, что нам нужно! Ан нет, ниже следует убийственная приписка (кстати, напечатанная тем же самым шрифтом), сообщающая, что операционная система попытается смонтировать демонтированный том при первой же попытке доступа к нему, в частности, вызов функции GetLogicalDrives заставит операционную систему смонтировать все демонтированные тома. Другими словами, как только мы нажмем <ALT-F1>/<ALT-F2> в FAR'е или попытаемся просмотреть содержимое тома, операционная система автоматически смонтирует его и никакой блокировки не получится! Обратимся к «голому» вызову FSCTL_LOCK_VOLUME, рекомендованному в описании команды FSCTL_DISMOUNT_VOLUME самой MS. Говорят, что использовать FSCTL_LOCK_VOLUME без FSCTL_DISMOUNT_VOLUME ни в коем случае нельзя! Дескать, при этом операционная система не сбрасывает дисковые буфера и если случайно забыть смонтировать том перед завершением работы Windows, диску придет капец. Что ж, открываем SDK и читаем: операционная система сбрасывает все дисковые буфера на том перед тем как заблокирует его, в частности, все данные, находящиеся в кэш'e «ленивой записи» выгружаются на том. Короче, насчет потенциальных разрушений можно не волноваться. Вызывать FSCTL_DISMOUNT_VOLUME до блокировки тома — бесполезно, а после — невозможно (DeviceIoControl возвратит ошибку, в полном соответствии со спецификациями Microsoft). Скелет программыВдоволь накурившись SDK, пишем следующий код. Обработка ошибок с прочими второстепенными деталями для упрощения понимания опущена: HANDLE hDevice; DWORD lpBytesReturned; hDevice = CreateFile (buf,GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0); DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME,NULL,0, NULL,0,&lpBytesReturned,0); Прежде чем отправлять тому команду FSCTL_LOCK_VOLUME, его необходимо открыть API-функцией CreateFile с флагами FILE_SHARE_READ|FILE_SHARE_WRITE, OPEN_EXISTING. Ну, с OPEN_EXISTING все понятно. Мы же не собираемся создавать новый дисковый том (имя которого, кстати говоря, записывается в формате «\\.\X:»), а открываем уже существующий. Флаги FILE_SHARE_READ|FILE_SHARE_WRITE способы легко ввести в заблуждение начинающих программистов, создавая впечатление, что заблокированный том будет доступен для совместной записи/чтения со стороны других приложений. Ничего подобного! Том будет заблокирован намертво! А эти флаги относятся к самому устройству, но не к команде FSCTL_LOCK_VOLUME. Перед блокировкой тома необходимо закрыть все открытые файлы и директории (не просматривать никакой каталог блокируемого тома в FAR'е), а также заручиться правами администратора (например, прибегнув к помощи службы «runas»). В противном случае DeviceIoControl возвратит ошибку. Заблокировать том заблокируем, а как его потом разблокировать обратно? Возвращаемся к MSDN и читаем: том будет оставаться заблокированным, пока не совершится одно из следующих действий: а) приложение, заблокировавшее том, не вызовет команду FSCTL_UNLOCK_VOLUME; б) дескриптор тома не будет закрыт вызовом CloseHandle или путем завершения процесса. Небольшое пояснение по поводу пункта (а). Подразумевается вполне определенное приложение (в данном случае, приложение, вызвавшее FSCTL_LOCK_VOLUME), никакое другое приложение не может разблокировать том посылкой команды FSCTL_LOCK_VOLUME. Эксперименты это полностью подтверждают. То есть, если мы блокируем том, то остальные приложения, даже обладающие правами администратора, не смогут до него добраться, во всяком случае на логическом уровне. В принципе, обладая правами администратора, нетрудно прочитать/записать содержимое диска на физическом уровне, например, открыв устройство \\.\PHYSICALDRIVE2, но это уже перебор. Нормальная малварь так не поступает, не говоря уже о пользователе типа «подружка». Теперь по поводу пункта (б). Как только наше приложение завершит работу, все заблокированные тома будут автоматически разблокированы и потому ничего другого не остается, кроме как резидентно болтаться в памяти, взаимодействуя с пользователем посредством командной строки или еще как. Обычно приложения, не создающие окон (то есть не имеющие пользовательского интерфейса) и работающие в фоновом режиме, оформляются в виде служб (они же системные сервисы). Мыщъх'у программировать службу было лень и он поступил проще: создал консольное приложение, а при его сборке указал линкеру, что это GUI, в результате чего удалось избежать создания консольного окна, загрязняющего своим присутствием «Рабочий стол». Уничтожение процесса через диспетчер задач приводит к автоматической разблокировке всех заблокированных томов. Но это некрасиво и потому было решено создать именованный семафор «nezumi_lock_mutex», дожидаясь его освобождения с помощью API-функции WaitForSingleObject, вгоняющей процесс в глубокий сон, чтобы он не кушал процессорное время. Повторный запуск программы с ключом «-release» освобождает семафор, передавая управление WaitForSingleObject – пробуждая процесс ото сна и тут же завершая его с закрытием дескрипторов всех заблокированных томов, что, как уже говорилось выше, приводит к их разблокировке. Достаточно простой, удобный и необычный способ блокировки дисков от (не)преднамеренного обращения, а главное — надежный! Поскольку большинство из нас хранит архивные копии прямо на жестком диске (это удобнее, чем стример или CD/DVD-R/RW), то имеет смысл заблокировать архивный том, снимая блокировку только на время обновления архивов. Как пользоваться программойПоскольку в комплект штатной поставки операционной системы не входит утилита для блокировки дисковых томов, мыщъх наскоро написал свою собственную, обозвав ее unmount.c. Исходные тексты прилагаются к статье (как видно из названия, она создавалась еще в те далекие времена, когда мыщъх верил в могущество команды FSCTL_DISMOUNT_VOLUME). Процедура сборки компилятором MS Visual C++ выглядит так: $cl.exe /c unmount.c $link unmount.obj /SUBSYSTEM:WINDOWS USER32.LIB Внимание: если просто скопировать исходный текст в окно IDE и сказать «Build», мы получим пулеметную очередь ошибок, а все потому, что по умолчанию IDE настроена на компиляцию С++ программ, а эта написана на чистом Си со всеми вольностями в преобразованиях типов. Для самых ленивых предлагается уже готовый к исполнению unmount.exe. Его следует запускать из командной строки со списком дисков, которые необходимо заблокировать, например: «unmount.exe \\.\X: \\.\Y: \\.\Z:», а разблокировать ранее заблокированные тома — «unmount.exe –release». Выборочная разблокировка отдельных томов в программе не предусмотрена (желающие могут добавить ее сами). Также, в некоторых оболочках типа FAR'а, во избежание возможной блокировки командой строки, ожидающей завершения приложения (которое в данном случае завершаться не собирается), рекомендуется использовать команду «start», поддерживаемую всеми версиями Windows, линейки NT. Примечание: программа содержит несколько некритичных ошибок, которые мыщъх так и не удосужился исправить. В частности, если запустить unmount не под администратором, то семафор будет успешно создан, а вот при попытке блокировки томов возникнет ошибка, но семафор останется цел и невредим. Повторный запуск утилиты под администратором ни к чему не приведет, пока пользователь (от имени которого создался семафор) не вызовет unmount.exe с ключом «-release». Впрочем, это все мелочи. Главное — руководящая идея! Размонтирование дисковых томовАльтернативный метод защиты дисков от (не)преднамеренных обращений к данным заключается в удалении точки монтирования, что легко сделать с помощью штатной утилиты MOUNTVOL, входящей в комплект поставки Windows, кажется, еще начиная с W2K. При запуске без ключей она выдает список точек монтирования, который выглядит приблизительно так: \\?\Volume{98fc8062-566a-11d9-82a2-806d6172696f}\ C:\ \\?\Volume{98fc8063-566a-11d9-82a2-806d6172696f}\ D:\ \\?\Volume{98fc8064-566a-11d9-82a2-806d6172696f}\ E:\ \\?\Volume{98fc8065-566a-11d9-82a2-806d6172696f}\ L:\ \\?\Volume{98fc8066-566a-11d9-82a2-806d6172696f}\ I:\ \\?\Volume{98fc8067-566a-11d9-82a2-806d6172696f}\ J:\ \\?\Volume{98fc8068-566a-11d9-82a2-806d6172696f}\ K:\ \\?\Volume{98fc8069-566a-11d9-82a2-806d6172696f}\ F:\ Длинная строка циферок, начинающаяся с «\\?\Volume» – это и есть имя тома (не путать с меткой диска!). Ниже идет точка монтирования, обычно представляющая собой букву, однако операционные системы семейства NT позволяют монтировать диски на каталоги любого другого тома (при условии, что этот каталог пустой), создавая файловые иерархии, характерные для UNIX-систем. Допустим, мы хотим размонтировать диск «A:\». Что мы должны для этого сделать? Во-первых, приобрести права администратора, а во-вторых, отдать команду: $MOUNTVOL.EXE A: /D Теперь диск «А:\» волшебным образом исчезает из системы и больше не отображается, создавая впечатление, что его вообще нет (а он ведь есть). И потому малвари или другому программному обеспечению до него теперь так просто не добраться. Хорошо, а как смонтировать диск обратно? Нет ничего проще! $REM вызываем MOUNTVOL без ключей, чтобы увидеть имена дисков $MOUNTVOL.EXE Возможные значения ИмениТома вместе с текущими точками подключения: \\?\Volume{98fc8062-566a-11d9-82a2-806d6172696f}\ C:\ \\?\Volume{98fc8063-566a-11d9-82a2-806d6172696f}\ D:\ … \\?\Volume{98fc8060-566a-11d9-82a2-806d6172696f}\ *** НЕТ ТОЧЕК ПОДКЛЮЧЕНИЯ *** \\?\Volume{e34f31c2-5654-11d9-9ec4-c140ca76d429}\ H:\ REM видим имя \\?\Volume{98fc8060-566a-11d9-82a2-806d6172696f}\ REM без точек подключения. Это и есть наш бывший диск A:\ REM сделаем из него диск B:\ $MOUNTVOL B: \\?\Volume{98fc8060-566a-11d9-82a2-806d6172696f}\ Кстати говоря, операции по удалению/восстановлению точки монтирования можно осуществлять и через «Менеджер Дисков» (панель «Администрирование»). Там, в графике, оно понагляднее будет, зато командная строка легко автоматизируется путем написания bat-файлов. Но тут на вкус и цвет все фломастеры разные. По надежности блокировка слегка выигрывает у операции удаления точки монтирования (восстановить точку монтирования может любое приложение, а не только то, которое ее удалило), однако программного обеспечения, умеющего работать с точками монтирования, мыщъх'у пока не встречалось. К тому же, заблокированные диски остаются «болтаться» в «Проводнике» и FAR'е, мозоля глаза своим присутствием, а вот удаление точек монтирования убирает их из системы, но это опять-таки вопрос вкуса. Вот так!Windows — мощная и интересная система, таящая под своим капотом огромные возможности. Пока остальные устанавливают сложные (и дорогостоящие) защитные комплексы, мы – хакеры – успешно обходимся своими лапами и хвостом, получая ничуть не худший, а зачастую даже лучший результат! DVDБинарный файл, а также исходник разработанной автором программы ты найдешь на диске WARNINGЭксперименты с жесткими дисками чреваты потерей данными. Будь бдителен! |