Подтвердить что ты не робот

Обнаружение виртуализации реестра

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

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

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

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

  • [как говорит jeffamaphone], если манифест имеет запрошенный Privileges/requestedExecutionLevel, он отключен. Вы, похоже, не исключали добавления манифеста, так что вы можете указать, почему это не сработает для вас? (Вы говорите: "Я не смог сделать это в С# V2" - есть опция "Добавить элемент", чтобы добавить файл манифеста приложения и доступный в VS2005)
  • если exe работает на 64 бит, по умолчанию он выключен
  • если это не интерактивный процесс (например, служба или размещение в IIS и т.д.), он отключен

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

Ответ 2

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

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

Ответ 3

Обратите внимание, что 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);
    }
}

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

Ответ 4

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

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

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

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

Чтобы исполняемый файл совместим с Vista и XP, по-видимому, каждый node в разделе 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, как описано в этой статье, поскольку это делает поведение, согласованное на всех машинах.

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

Альберто