Дело о невидимых файлах

Как вы думаете, какой сообщение выведет нижеследующая программа, в случае если её запустить на Windows Vista 64 с правами обычного пользователя, т.е. пользователя, у которого нет прав на запись в каталог “C:\Program Files”?

#include <memory.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    FILE* f = NULL;
    char cookie[] = { 'b', 'a', 'r', ' ' };
    char data[sizeof(cookie)] = { 'f', 'o', 'o', ' ' };

    f = fopen("C:\\Program Files\\foo.txt", "w");
    if (f)
    {
        fwrite(cookie, sizeof(cookie), 1, f);
        fclose(f);
    }

    f = fopen("C:\\Program Files\\foo.txt", "r");
    if (f)
    {
        fread(data, sizeof(data), 1, f);
        fclose(f);
    }

    if (0 == memcmp(data, cookie, sizeof(cookie)))
    {
        printf("Success!\n");
    }
    else
    {
        printf("Something went wrong!\n");
    }

    return 0;
}

Как это не странно ответ зависит от типа процессора, для которого скомпилирована программа. Если это 64-х битный процессор, то создание файла “C:\Program Files\foo.txt” завершиться неудачей из-за недостатка прав и программа выведет, как и положено, “Something went wrong!”. Однако если ту же программу скомпилировать как 32-х разрядное приложение, она напечатает “Success!”. Т.е. файл создастся, не смотря на то, что пользователь не имеет права создавать файлы в каталоге “C:\Program Files”! Как это возможно?

Ответ – Least-privilege User Account (LUA) Virtualization. Microsoft уже довольно долго пытается убедить пользователей не использовать учетную запись администратора для повседневной работы. Появление LUA в Vista тоже имеет к этому отношение. В частности LUA Virtualization решает проблему старых приложений, которые непременно хотят создавать файлы в системных каталогах.

С помощью отладчика можно посмотреть, что происходит при запуске программы на самом деле.

Если поставить точку останова сразу после создания файла, то в списке описателей в Process Explorer видно, что в реальности файл создается не в “C:\Program Files”, а в каталоге “C:\Users<user name>\AppData\Local\VirtualStore\Program Files\foo.txt”.

Механизм LUA Virtualization просто перенаправляет файловые операции в пользовательский каталог, если обнаруживает, что программа пытается создать файл, либо открыть существующий файл на запись. Само собой каждый пользователь получит свой набор перенаправленных файлов.

Однако почему же 64-х битная версия не ведет себя подобным образом? Дело в том, что механизм LUA Virtualization нужен только для обеспечения совместимости со старыми приложениями. Все 64-х разрядные приложения по умолчанию считаются достаточно новыми, чтобы корректно работать с системными каталогами.

Полный список условий необходимых для включения LUA Virtualization достаточно обширен:

  1. Процесс должен быть запущен от имени интерактивного пользователя;

  2. Процесс должен быть 32-х битным;

  3. Манифест приложения не должен использовать директиву “requestedExecutionLevel”;

  4. Системный вызов, например NtWriteFile, должен исходить от потока, находящегося выполняющегося в пользовательском режиме. Кроме того, поток не должен имперсонировать другого пользователя;

  5. Виртуализируемый файл должен находиться в одном из системных каталогов. По-умолчанию этот список включает в себя: “%SystemRoot%”, “%ProgramFiles%” и “%ProgramData%”, исключая некоторые поддиректории;

  6. Многие расширения файлов, такие как “.exe”, “.dll”, “.sys” и т.д. входят в довольно обширный список невиртуализируемых расширений. Если файл имен расширение из этого списка, он не будет виртуализирован;

  7. Администратор должен иметь права на запись в файл, иначе файл также не будет виртуализирован.

Столь длинный список условий ещё раз говорит о том, что механизм LUA Virtualization предназначен только для обеспечения совместимости со старыми приложениями.

По аналогии с файловой системой виртуализируется системный реестр, вернее ветвь “HKEY_LOCAL_MACHINE\SOFTWARE”. Для каждого ключа можно установить флаг, контролирующий виртуализацию. Сам я этого не пробовал, однако утверждается, что это можно сделать с помощью команды “reg flags”.

Кроме того, появление LUA Virtualization затронуло Windows Explorer и Task Manager. Windows Explorer показывает линк “Compatibility Files”, если хотя бы один из файлов текущего каталога был виртуализирован для активного пользователя. Нажатие на этот линк открывает каталог, куда были помещены виртуализированные файлы из текущего каталога. Task Manager показывает статус процесса: “виртуализирован”/”не виртуализирован” (колонка “Virtualization” во вкладке “Processes”).

Ссылки по теме: Developer Best Practices and Guidelines for Applications in a Least Privileged Environment, LUA Virtualization.

Upd: поправил символы ‘<’ и ‘>’.

comments powered by Disqus