Вдогонку к предыдущей статье
А текущая статья посвящена вот такому вопросу: Допустим, есть некая программа для компьютера, которой вы хотите пользоваться, но не очень доверяете, заметили что она лазит по каким-то файлам без разрешения, читает их, или ещё хуже, записывает излишнее, разбрасывает свои файлы, "сорит".
Будет рассказано о многих совершенно разных способах урезонить софт и обезопаситься. Перечислю как банальные общеизвестные даже начинающим пользователям способы, так и способы интересные для любопытных интересующихся, желающих больше понимать, быть продвинутыми, экспериментировать, модифицировать, контролировать, а не довольствоваться тем, что есть. Думаю, кроме сухого технического языка описания, наверное, кому-нибудь что-то покажется и волшебным, удивительным! 🎆 Здесь не в том смысле, что "техника кажется дикарям магией", а в том смысле, что уже знающим на базовом уровне покажутся интересными "хакерские" фишки с большим контролем, углублением в детали, раньше не замечаемые.
Итак, поехали.
Начну с самых простых общеизвестных способов.
💥 Поиск в настройках.
Посмотреть все настройки программы явные, затем искать скрытые. Может что не заметили, а вдруг есть возможность отключения "нежелательной деятельности", в частности сбора данных и записи ненужных файлов.
💥 Почитать справку к программе.
💥 Искать в интернете как вообще в поиске, так и спросить на форумах и в темах посвящённых именно такой программе, если есть такие темы. Знатоки практики могут подсказать скрытые настройки и неочевидные способы.
💥 Найти и просмотреть в компьютере: если есть, конфигурационные файлы программы, в которые она сохраняет настройки. Такие файлы могут быть любыми, с любым названием и расширением, но разработчики обычно называют их понятно, что это и есть настройки.
Найти и просмотреть разделы реестра, если программа хранит настройки в реестре. Просмотреть всё что связано с программой, ключи реестра и файлы настроек. А вдруг где-то открытым текстом будет имя параметра, что-то похожее на искомое. Например, Logging=1 или Telemetry enable, DataCollection:true Или ещё что-то эдакое, множество вариантов. Очень наивно надеяться, что легко по названию будет очевидно что это оно и что простое изменение параметров на противоположные 0, disable, false раз и отключит нежелательное поведение программы. Но попробовать можно, а вдруг разработчики сделали такую возможность и вот она. Но может и не быть никаких параметров для отключения.
💡 Примечание. Как можно облегчить поиск папок, файлов на диске, разделов и ключей в реестре, в которые программа вносит изменения? Как найти, куда она вносит изменения. О этом будет рассказано позже, в пункте о виртуализации.
💥 Виртуальные машины.
Радикальный, надёжный но громоздкий способ обезопаситься, запускать подозрительную программу в виртуальной машине. Программа пусть будет читать и писать файлы на виртуальном диске, а не на всём основном, взаимодействовать с операционной системой поставленной в виртуальной машине, а не основной.
Если программа нашпионит, напакостит, намусорит в системе просто лишними бесполезными файлами или даже вредными, это останется в рамках виртуального диска. (если не подключили доступ к реальному)
В общем, если не доверяете новой, ещё малоизвестной программе, то запускать её в виртуалке. ✅Виртуальная машина также выручит, если есть программа которой доверяете, но она излишне много взаимодействует с системой (вмешивается в систему, вносит от себя файлы и записи в реестре), а вам не желательно чтоб ваша чистенькая основная система была "замусорена" нерадивыми и расточительными программами. Просто пользоваться. И заодно, возможно, хотите разобраться и выяснить, поэкспериментировать - а так ли нужны программе все её файлы, или работает без некоторых и можно сделать программу компактнее, портабельнее.
☝️❗ Предостережение - допустим, посмотрели что программа по-видимости не вредит в виртуальной машине, ведёт себя в рамках приличий, глянули поверхностно, полагаете что она безопасна и решили смело запустить программу уже в основной системе. Но изменения (в том числе нежелательные и даже вредные) могут быть скрытыми, не заметными невооружённому глазу! А антивирусы если не реагируют, это ещё не значит что программа точно безопасная.
Невооружённым глазом нельзя отследить все изменения, что же программа произвела, что и где скрытно отредактировала. Надо вооружиться софтом для сравнения каталогов или т.н. "слепков" (сделанных списков файлов и реестра). Сделать слепок виртуального диска до первого запуска новой программы, затем запустить её и проверять, пользоваться ей, а затем создать второй слепок, сравнить оба. Так выявить различия, что изменилось после установки и запуска программы, что она скрыто сделала.
Плюсы виртуальной машины - изоляция системы поставленной в ней от основной системы, безопасность, простор для экспериментов. Минусы - виртуальная машина(эмуляция компьютера) имеет меньшую производительность чем основная, нужно ждать когда виртуальная запустится, она занимает оперативную память и другие ресурсы.
💥 Портабелизированный софт. Виртуализация окружения для программ.
💡 А что, если хочется способ легковесный, не запускать громоздкую виртуальную машину с своей отдельной операционной системой, а делать виртуальными только лишь изменения в обычной системе. Запускать как обычно программу, но запретить ей вносить нежелательные изменения в окружающую среду, файловую систему и операционную защитить.
Это давно изобретено, виртуализация окружения для программ. Принцип такой, как правило - настраивается, какие папки для программы будут совсем не видимы - она не сможет в них зайти и читать данные, а какие доступны для чтения, но запрещено внесение изменений. Когда программа будет запрашивать запись в запрещённых для неё папках, то запись будет перенаправлена в т.н. "песочницу", временную папку. Программа если станет создавать файл в запретной папке, то ей покажется(!), что файл успешно создан там, а на самом деле запретная папка будет защищена от действий программы, файл создастся в песочнице, либо в оперативной памяти. Тот же принцип для реестра, он тоже защищён от вмешательств программы.
Существует разный специальный софт, инструменты для портабелизации и виртуализации. 💡Подсказка - например, ThinApp, Turbo Studio, InstallAware Virtualization, Enigma, Cameyo, и другие. Они способны упаковать все файлы программы в один.
✅ Это очень удобно, иметь один файл .exe вместо большой кучки всяких файлов и папок которые обильно наплодили нерадивые разработчики и некоторые мало того что насоздавали файлов, так и норовят помещать их не только лишь в папку программы, а ещё в много папок и куда-то в систему размещать и регистрировать.
А портабельная программа так не должна поступать, не должна сорить и распихивать свои файлы по многим разным папкам. Она содержит всё своё нужноё в себе и не пакостит. Ей может быть выдана папка - "песочница", где позволено "сорить".
Очень удобно иметь портабельную программу, её не надо ни устанавливать, ни деинсталлировать и чистить после неё остатки, она и места меньше занимает. В идеальном случае - программа не "мусорит", не оставляет следов в системе, не вносит изменений в файлы и реестр. Но практически встречаются неполностью портабелизированные программы, а также такие, которые затруднительно полностью портабелизировать.
Портабельными называют программы, которые легко перенести на любой диск в любую папку и запустить, они не требуют процедур установки и деинсталляции и, как правило, за очень редким исключением, не пишут в систему, не "мусорят".
Примечание - программа может быть создана портабельной изначально разработчиками, и это самый лучший вариант, молодцы что не напихали в неё лишнее. А может быть упакована, портабелизирована кем то ещё, не теми кто её создал. Что встроили туда "репакеры"? В идеале... идеальные добросовестные, альтруистичные, тщательно проводят ревизию, чистят набор файлов от излишних, вырезают избыточные, неиспользуемые и нежелательные функции программы, рекламу, слежку и т.п., а от себя не добавляют ничего плохого.
В портабелизированную программу можно добавить работоспособные настройки. Например, исходная программа при первом запуске требует от пользователя произвести настройки, а в портабелизированную можно встроить настройки, чтоб она была сразу готова к использованию, очень удобно. А если удалить "песочницу" то настройки, разумеется, не сбросятся совсем, а вернутся к тем что встроены. Что опять же удобно.
❓ Как упаковать программу? В общем принципе это делается так: сначала в инструменте для портабелизации-виртуализации программ создать слепок системы. Затем поставить программу, настроить и попользоваться, закрыть чтоб сохранились настройки. Создать второй слепок системы, затем будет автоматическое сравнение слепков и выявление что поменялось, где именно программа намусорила, куда поместила всякие свои файлы и настройки. Затем вся куча файлов копируется в проект, в нём можно внести изменения, удалить из проекта явно лишние файлы, если считаете что они не нужны программе или ошибочно причислены к ней.
Можно настроить в проекте доступ к папкам - например, запретить вносить изменения в всю файловую систему вообще на всех дисках. Разрешить запись только лишь в временной папке. При желании можно скрыть от программы, на всякий случай, папки с личными документами, она их не увидит. В общем, можно настраивать доступ к папкам и к реестру как угодно, ещё и интернет можно отключить для программы на всякий случай(если она и без доступа к нему работает). Программа станет значительно безопаснее, будет работать, но не сорить и не шпионить, не лазить в сеть.
Примечание - нельзя скрывать от программы системные папки, иначе программа вероятно не будет работать. Системные папки должны быть видимы программе, но запрещено вносить изменения в них.
Далее проект собирается в итоговый файл. Готово, теперь портабельная программа содержит в себе в одном файле упакованные все свои файлы и настройки, плюс к ней добавлены библиотеки виртуализации, запрещающие сорить в системе.
💥 Windows Sandbox
Это средство виртуализации, встроенное в саму операционную систему, но не во все версии. Похоже на виртуальную машину, принцип работы несколько отличается от полноценных виртуальных машин (аж целую отдельную систему запускающими) и от обычных песочниц виртуализирующих окружение программ. Это некий гибрид таких методов. Операционная система запускается та же, копия основной системы, но с настройками по умолчанию и пустая. Нужно будет скопировать программу(например через буфер обмена) и запустить внутри песочницы. (Пишут, что она изолирована от основной системы. Но я считаю это средство сомнительным, не очень надёжным)
А после закрытия такой песочницы все данные внутри неё удаляются.
💥 Фаерволы для доступа к сети и аналогичные прослойки-защитники для доступа к файлам.
Упомянем совсем другие средства как можно настроить доступ для программ.
Т.н. фаервол - с помощью него можно настроить доступ к сети, доступ как вообще всей системы, так и избирательно доступ для отдельных программ. Доступ как вообще в сеть, так и к отдельным адресам, портам, протоколам, именам, ... Фаервол является прослойкой, через него проходят сетевые запросы и он фильтрует их соответственно настройкам доступов.
☝ Идея совершенно очевидна, чтоб был аналогичный функционал не для сети а для файловой системы - на всякий случай запретить запись куда попало, настроить доступ к папкам. По умолчанию сомнительным программам установить строгие ограничения.
❓ Есть ли такой софт, как фаерволы с очень детальной подробной настройкой и полным контролем доступа, но только не для сети, а специально для файловой системы? Теоретически конечно возможно такое. К сожалению не подскажу такого софта, только слышал, что в антивирусах бывает что-то подобное, они следят, и если программа проявляет активность в файловой системе, и, особенно если пытается изменить что-то в особо охраняемых(системных) папках, антивирус заблокирует программу.
Следующие способы ручной настройки доступов.
💥 Доступы в файловой системе
Встроенный функционал в операционную систему. Например, в Виндовс в проводнике в контекстном меню выбрать "Свойства", затем "Безопасность", откроется окно настройки доступов для пользователей или групп. По моему сложновато для настройки и не очень надёжно...
Можно задать доступы, например, запретить запись и изменение для обычного пользователя, и разрешить для администратора. Тогда в такой папке сможет произвести изменения программа запущенная "от администратора" но не просто от пользователя. А можно попробовать запретить вносить изменения вообще всем пользователям - папка с содержимым останется неизменной, никто не исказит информацию, не удалит имеющиеся и не добавит новые файлы туда. Если вообще верно работают права доступа, то возможно так настроить.
Примечание - не рекомендуется менять права доступа у системных папок.
А что можно делать? Например, если есть папка, которой пользуется только конкретная программа, она часто всё пишет и пишет туда излишние файлы, можно попробовать запретить запись в эту папку. Возможно, что программа будет работать как ни в чём не бывало и успокоится, будет поменьше грузить диск и процессор. Но возможно, что выдаст ошибку.
💥 Запрет записи с помощью замены папки на файл и наоборот.
Старинный способ, считается, что так делали ещё в давние времена. Просто заменяли папку на одноимённый файл или наоборот. Например, программа при своей работе создаёт папку и пишет, и пишет туда файлы. А пользователь считает, что эта активность явно излишняя и не нужная, удаляет папку и создаёт файл с тем же именем. Затем программа хочет как обычно создать себе папку, а система ей отказывает в этом - ведь есть уже файл с тем же именем. В этом случае тоже не с каждой программой сработает, некоторые проигнорируют это и будут работать, а другие посчитают ошибку критичной.
💥 Перенаправление с помощью ссылок в файловой системе
А вот этот способ эффективный и безопасный, но не всем очевидный. Не запретить, но направить в другое место. Простые пользователи не все слышали о таком, но будет очень интересно узнать. А продвинутые знают и применяют.
Что такое жёсткая ссылка (HardLink) - это как специальный ярлык, ссылающийся на файл в пределах того же раздела. Если программы обращаются к хардлинку, то система направляет их обращения к файлу.
Как это можно применять? Например, если есть несколько одинаковых файлов, или нужно чтоб они были одинаковыми и синхронизировались. Оставляем только один настоящий файл, а остальные меняем на ссылки на него, получается экономия места на диске. Ещё как можно применять - если программа обращается к файлу в определённой папке, а хотите перенести файл в другое место. Тогда переносите, а чтоб программа не потеряла файл по прежнему адресу, на прошлом месте оставляете ссылку на новое.
Что такое точка соединения (Junction) - а это ссылка на папку, она может располагаться в пределах компьютера на любом диске. Символическая ссылка (SymbolicLink) - это более современная разновидность, а по сути поддерживает всё то же самое что обозначено выше, можно ссылаться на файлы или на папки. В Проводнике симлинк выглядит так же как обычная папка, но со стрелочкой. Если зайти в такую "папку", то Проводник отобразит содержимое точно так же, как если бы это была самая настоящая папка на этом месте. Но папки там нету, есть ссылка на папку находящуюся в другом месте.
🔥 Кто-то уже смекнул и загорелся идеями, как это применять. Например, перенести некоторые интенсивно используемые папки на более скоростной диск, защитить обычный.
Допустим, есть на рамдиске раздел R и на обычном диске на D стоит софт. Одна из программ интенсивно пишет в свою подпапку log какие-то временные файлы, логи и прочую кучу лишней мелочи. Команда mklink создаёт перенаправления:
mklink /D D:\ProgramFiles\YourProgram\log R:\Temp
- Где первый путь это сам создаваемый ярлык, а второй это путь на который он ссылается. Такая команда создаст на месте D:\ProgramFiles\YourProgram\log линк, который ссылается на папку R:\Temp - эта папка должна существовать. Теперь программа будет как обычно ничего не подозревая обращаться к своей подпапке с логами, а на самом деле будет писать их в папку Temp на диске R.
Способы с файловой системой перечислены, далее можно упомянуть другие способы, как можно перенаправить или совсем отключить некие нежелательные действия программы.
💥 Просмотр исходников и модификация
Если есть исходные файлы с кодом программы, то, теоретически, возможно разобраться и переделать как угодно, изменить, удалить из программы те функции которые считаете лишними, ненужными, нежелательными. Будь то излишнее создание каких-то папок и файлов, сбор данных, или ещё чего-то.
В случае простых программ может повезёт и только глянув, вскоре увидите где конкретно те функции и как отключить. А может и нет, окажется очень сложно и даже имея код, не всё ясно, запутано, после долгих попыток решите сдаться и бросить это занятие.
💥 Дизассемблирование, декомпиляция и патчи, не обладая исходниками.
Тоже способ, но ещё сложнее. Опять же как повезёт. Или, как наглядно сделано. Нет гарантий. Можете внести правки в программу, а она откажется работать и нужно будет опять искать в чём причина. В общем, это способы для тех у кого очень много усидчивости и свободного времени.
💥 Прослойки, промежуточные библиотеки с функциями фильтрации
В завершении статьи бонус для энтузиастов, ещё идеи.
А что, если не изменять программу, но попросту фильтровать её вызовы функций из библиотек, в том числе, системных функций?
💡🔥 О, да, это блестящая идея, озаряющая догадкой и манящая перспективами, но очевидная не всем, кто-то даже ещё не рассматривал в таком ракурсе. Начинающим исследователям будет очень интересно и увлекательно.
Краткая справка - программы, даже если обладают нативными бинарными файлами (где код выполняется на настоящем процессоре, без эмуляции и виртуальных машин), почти ничего не делают сами, совершенно не способны! Они обращаются к системным библиотекам, в которых расположены стандартные функции API. Либо обращаются к своим библиотекам или неким сторонним фреймворкам, а они являются посредниками, и в итоге опять же обращаются к функциям системных библиотек и вызывают их.
Прикладной софт НЕ занимается уровнями оборудования, то есть, когда приложение хочет открыть файл, оно не отправляет команды самому диску. Ведь это очень сложно и не нужно, всю работу с дисками и файловыми системами делает операционная система с драйверами, а чтобы просто создать файл, не нужно в это всё вникать, следует лишь вызвать системную функцию.
Приложение, само через главный исполняемый файл или через промежуточные библиотеки, вызывает стандартную, частоупотребляемую, общеизвестную системную функцию пользовательского уровня, например функцию CreateFile.
И только некоторые редкие приложения сами вызывают функцию ядра NtCreateFile или ещё менее известные, менее документированные функции. Только редкие приложения работающие с диском вызывают DeviceIoControl или NtDeviceIoControlFile или что-то ещё более таинственное из глубины системы.
Другими словами, обычное приложение как правило, нехитрым образом вызывает самые обычные функции API предоставляемые системой. Может оказаться так, что достаточно перехватить всего одну или несколько функций, например тот пресловутый CreateFile, чтоб отфильтровать файловую активность приложения (запретить программе писать лишние файлы или перенаправить запись в другую папку). Но может оказаться посложнее и потребуется перехватить и фильтровать не одну функцию а некоторое множество...
✅ Значит схема в общих чертах такова: Нужно написать и внедрить библиотеку прослойку между программой и системной библиотекой. Программа которая вызывает системную функцию открытия файла будет обращаться к функции в нашей промежуточной библиотеке, а та будет фильтровать запросы по имени файла. Отклонять, либо разрешать как есть, либо перенаправлять в другую папку, на ваше усмотрение.
Как отклонить? Не вызывать функцию открытия файла и вернуть вместо неё результат гласящий о ошибке (INVALID_HANDLE_VALUE или попросту -1)
Как перенаправить? Элементарно заменить путь файла в параметре функции. В рассматриваемом случае, параметр lpFileName у функций CreateFileA - Ansi и CreateFileW - Unicode текст. Приложение может пользоваться только одним вариантом функции или двумя.
❓ Как именно добавить библиотеку? Есть несколько вариантов.
Вариант для простых программ - статический импорт. В таблице импорта в исполняемом файле программы заменить имя библиотеки содержащей интересующую функцию (функция CreateFileW находится в KERNEL32.dll) на имя нашей промежуточной библиотеки, имя может быть любым не совпадающим с системными файлами, имя должно быть такой же длины или короче. Например 1.dll 💡Лайфхак: Имя библиотеки можно найти и заменить с помощью обычного хекс редактора, специальный софт не обязателен, но было бы удобнее если создать\найти утилиту (какой нибудь dependency viewer, то есть просмотрщик зависимостей для исполняемых файлов) в которой можно наглядно просматривать таблицы импорта и экспорта функций из библиотек. (На скриншоте самодельная утилита для просмотра такой информации)
В 1.dll должен быть набор импортируемых программой функций. 💡Совет: Вовсе не обязательно делать все функции внутри библиотеки. Достаточно сделать только те, что нас интересуют, чтоб программа вызывала наши вместо системных. А остальные импортируемые функции можно перенаправить на оригинальную библиотеку. Вот как это делается, при компиляции библиотеки нужно передать компилятору или линкеру файл .def, в котором содержится декларация экспорта (приведено в пример только несколько строк, а далеко не весь список функций):
EXPORTS
CreateFileW = CreateFileW_ @207
CloseHandle = KERNEL32.CloseHandle @136
Это означает что CreateFileW - имя в библиотеке, а CreateFileW_ - это имя нашей промежуточной функции которая должна быть внутри в самом коде библиотеки (внутри неё мы будем фильтровать запросы и вызывать оригинал с именем без подчёркивания), а CloseHandle вообще не фильтруется прослойкой, вызов этой функции сразу перенаправляется на системную библиотеку.
Статический импорт достаточен для простых программ. А непростые динамически вызывают множество библиотек, а те в свою очередь вызывают системные функции. ❓ Как быть в таком случае, как ещё можно поставить перехват и фильтр?
✨ Более сложный способ, описан упрощённо в общем принципе: При загрузке нашей библиотеки будет выполняться код, он в начале оригинальной функции поставит прыжок, переход на нашу функцию (В ассемблере команда перехода - jmp и смещение, то есть расстояние прыжка, разница с адресом на который процессор "прыгнет", перейдёт и продолжит исполнение кода), а перед тем нужно сохранить данные с того места, на которое запишем jmp.
Когда программа вызовет перехваченную функцию, то произойдёт переход на нашу фильтрующую функцию. Фильтруем, а если пропускаем, то нужно восстановить данные(убрать прыжок из начала) и вызвать оригинальную функцию, а затем вновь поставить в её начале jmp на адрес нашей функции.
☝ Примечание. Это для энтузиастов, это очень примитивное "создание\переизобретение велосипедов". Просто для понимания базовых принципов и каких-то фишек. На таких принципах (перехват вызовов функций), но только сложнее, работающие с массой более глубоких и малоизвестных системных функций, работают не только всякие хакерские и исследовательские, а обычные средства для отладки, а также средства для виртуализации окружения приложений. Средства запуска программ, защищающие от них систему, перенаправляющие запись в "песочницу" и вообще, делающие программы портабельными.
Если нужно не мучаться изобретать простые самоделки, а найти готовые сложные и надёжные инструменты для придания портабельности и безопасности программам, то подсказки уже даны выше в пункте "💥 Портабелизированный софт. Виртуализация окружения для программ", а вдобавок к тому, очевидно, следует иметь вообще в системе защитников, фаервол и антивирус, в них могут иметься функции настройки доступов.
Интересно, а есть ещё какие-то способы? Можно ли не вмешиваться ни в программы, ни перехватывать функции библиотек, а как-то иначе фильтровать действия процессов? Да, есть способы.
💥 Драйвер фильтра файловой системы
Все выше упомянутые способы я немного опробовал и поэкспериментировал, но только этот способ ещё не делал, не писал драйвер, непривычно там разбираться, нет опыта. Оказывается, предусмотрены мини-фильтры, особый тип драйверов. Помню что когда-то поинтересовался и читал где-то о том, что такой драйвер в принципе возможен. Но сейчас совсем не до этого. (Неужели лень? Да как-то не нужно стало)
И всё же упоминаю о такой замечательной возможности. Теоретически, энтузиасты могут на практике реализовать эту идею, написать фильтр файловой системы, то есть получить почти полный контроль🔥, сделать "фаервол для доступа к файлам", знать какой процесс обращается к каким файлам и если надо, то защищать файлы от нежелательных действий программ, запрещать доступ к личным файлам и так далее, настроить доступы как угодно на своё усмотрение, если не доверяют что обычные система и антивирусы надёжно защитят, хотят сами проконтролировать.
***
А ещё какие-нибудь способы есть?
Перечислил все способы которые знаю. Но есть ещё некоторые способы как защитить файлы, впрочем, это уже другое и не совсем в тему.
Например, чтоб защитить от просмотра, можно зашифровать файлы, их содержимое будет не читаемое, если нет пароля и способа дешифровки. Но этот способ не защищает от искажения, замены, удаления файлов. А в статье рассматривались различные способы, когда файлы остаются оригинальными, не шифруются, но ограничивается доступ программ к ним.
Ещё можно упомянуть способ - разграничение устройств, иметь реальные разные устройства - на одном личные файлы и надёжные программы, а на другом - эксперименты с сомнительными программами, которые если что-то сломают, испортят, напакостят, то это не нанесёт большого ущерба. И всё же, это другое.