Обнаружение виртуализации реестра - PullRequest
20 голосов
/ 16 июня 2009

У меня есть набор приложений на C # (v2), и я борюсь с виртуализацией реестра в Win7 (и в меньшей степени в Vista).

У меня есть область конфигурации общего реестра, к которой мои приложения должны обращаться в HKLM \ Software \ Company ... До Vista все просто записывалось и считывалось из этого места по мере необходимости.

Код надлежащим образом обнаружил сбои записи в этот раздел реестра и откатился соответствующим образом (вместо этого он записал в HKCU и уведомил пользователя о том, что примененные ими настройки будут влиять только на текущего пользователя).

В Vista виртуализация реестра прервала все это, потому что проверка доступа, которую мы использовали для записи HKLM, "молча" прошла бы успешно и вместо этого виртуализировалась бы в HKCR \ VirtualStore \ Machine .... В этом случае пользователь будет думать, что он сохранил конфигурацию всей машины, а вместо этого записал только в виртуальное хранилище.

К сожалению, даже попытка перечислить разрешения для ключа HKLM reg в явном виде возвращает результаты, указывающие, что у пользователя есть доступ, независимо от того, есть он или нет.

Когда мы добавили поддержку Vista, мы использовали обходной путь, чтобы выполнить пробную запись в HKLM ... и затем проверить в HKCR \ VirtualStore \ Machine ... то же значение и заметить, что виртуализация произошла, если значение было найдено.

Похоже, что в Win7 это (опять же) нарушено, поскольку запросы к явному виртуальному расположению (HKCR) теперь показывают объединенные результаты из местоположения HKLM, даже если запись не была виртуализирована.

У кого-нибудь есть какие-либо предложения по поводу этого?

Ограничения: - Мне нужно решение, которое работает, не требуя повышения прав (когда у меня нет разрешений на уровне администратора, я получу откат к конфигурации для каждого пользователя в HKCU, но мне нужно иметь возможность надежно обнаруживать этот случай).

  • Это должно работать с приложением C2 v2 (я видел вариант для кода C ++ - встроить манифест, который отключает виртуализацию для .exe, но я не смог сделать это в C # V2, см. отключить виртуализацию папок в windows ).

  • Он должен работать без «установщика» (это исключает возможность отключить виртуализацию для ключа реестра, который нам нужен, а именно команда REG FLAGS ...).

Ответы [ 4 ]

10 голосов
/ 24 августа 2009

Это превосходно поставленный вопрос, +1 (Почему это вики сообщества, оно заслуживает очков!)

В общем, существует набор правил (которые [с которыми вы столкнетесь] будут меняться с течением времени), которые контролируют, будет ли задействована виртуализация UAC [и, следовательно, неявно Registry].

Некоторые существенные части документации Наборы правил виртуализации реестра в MSDN :

  1. [как говорит джеффамафон], если у манифеста есть набор запрашиваемых атрибутов / запрашиваемого уровня выполнения, он отключается. Похоже, вы не исключили возможность добавления манифеста, поэтому не могли бы вы указать, почему это не сработает для вас? (Вы говорите: «Я не смог сделать это в C # V2» - есть опция «Добавить элемент» для добавления файла манифеста приложения, которая доступна в VS2005)
  2. если исполняемый файл работает на 64-разрядной версии, по умолчанию он выключен
  3. если это не интерактивный процесс (например, служба, не размещен в IIS и т. Д.), Он отключен

Если вы не в состоянии повлиять на что-либо из вышеперечисленного, что является идеальным, и, таким образом, вы хотите определить, применима ли виртуализация UAC в текущем контексте, используйте этот ответ на вопрос, что может сначала не представляется связанным вопросом . (Очевидно, что вам все равно нужно решить, относится ли он к конкретному ключу, с которым вы работаете, что является движущейся целью, и вы, очевидно, не захотите реализовывать код, который должен отслеживать изменения, если его вообще можно избежать - но в в большинстве случаев это должно быть относительно ясно.)

2 голосов
/ 16 июня 2009

Вы можете включить / отключить виртуализацию для каждого ключа в соответствии с this , но он говорит вам об использовании инструмента командной строки. Но должен быть способ сделать это программно.

Возможно, будет проще всего полностью отключить виртуализацию в вашем приложении, установив требуемое значение ExectionLevel в своем манифесте. Вы можете попробовать самый высокий доступный, но это может означать, что ваше приложение всегда запускается от имени администратора. Похоже, что установка asInvoker отключит виртуализацию. См. также .

0 голосов
/ 21 декабря 2011

У меня была похожая проблема, и введение манифеста решило ее.

Я полагался на безопасность реестра, чтобы приложение (Win32) не создавало ключи в HKLM / Software / Wow6432Node при работе от имени обычного пользователя, и был очень удивлен, увидев, что это происходит независимо, но ключ отсутствует и он был создан вместо этого в этой новой области VirtualStore.

Виртуализация реестра отключается, когда обнаруживается, что манифест PE содержит информацию, связанную с безопасностью. Чтобы не требовать повышения прав, мой манифест содержит следующий узел:

<trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
   <security>
      <requestedPrivileges>
         <requestedExecutionLevel level="asInvoker">
         </requestedExecutionLevel>
      </requestedPrivileges>
   </security>
</trustInfo>

Чтобы исполняемый файл был совместим с Vista и XP, очевидно, что каждый узел в разделе TrustInfo должен содержать пространство имен:

<ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
   <ms_asmv2:security>
      <ms_asmv2:requestedPrivileges>
         <ms_asmv2:requestedExecutionLevel level="asInvoker">
         </ms_asmv2:requestedExecutionLevel>
      </ms_asmv2:requestedPrivileges>
   </ms_asmv2:security>
</ms_asmv2:trustInfo>

Как только манифест был правильно встроен в мой .exe (мне потребовалось несколько попыток, изменив соответствующие свойства проекта), программа, наконец, завершилась сбоем, как я и ожидал.

Для управляемого кода манифест можно включить в качестве шага после сборки, запустив инструмент mt.exe. Например, как сообщается в статье MSDN

mt.exe –manifest YourFile.manifest –outputresource:YourApp.exe;#1

Я предпочитаю использовать манифестный подход, а не изменять флаги узлов реестра с помощью reg.exe, как описано в этой статье , поскольку это делает поведение согласованным на всех машинах.

Надеюсь, это поможет (даже если после прочтения даты первоначальной публикации я почти уверен, что проблема давно решена !!)

Альберто

0 голосов
/ 17 июня 2009

Обратите внимание, что HKCR - это само виртуальное хранилище, комбинация HKLM\Software\Classes и HKCU\Software\Classes.

Наилучшим подходом было бы не допустить виртуализации реестра. Сначала проверьте, повышен ли уровень пользователя во время выполнения, а затем вы можете уведомить пользователя, что изменения будут применены только к текущему пользователю, прежде чем они даже начнут вносить изменения.

Обнаружив, что вы в первую очередь являетесь администратором с повышенными правами, вы можете просто избежать записи в HKLM, когда он будет виртуализирован.

Пример:

private bool IsAdministrator
{
    get
    {
        WindowsIdentity wi = WindowsIdentity.GetCurrent();
        WindowsPrincipal wp = new WindowsPrincipal(wi);

        return wp.IsInRole(WindowsBuiltInRole.Administrator);
    }
}

Примечание: Я не пишу код на C #, пример взят из вопроса Как я могу определить, работает ли мой процесс с повышенными правами UAC или нет?

...