gpt4 book ai didi

c# - 如何检测到 Windows VirtualStore 的文件重定向?

转载 作者:太空狗 更新时间:2023-10-29 17:36:55 25 4
gpt4 key购买 nike

自 Win Vista 发布以来,Microsoft 为以 32 位进程运行的遗留应用程序引入了文件虚拟化。作为 Microsoft 用户帐户控制 (UAC) 的一部分发布,任何试图写入任何被认为受操作系统保护的位置的旧应用程序都将重定向到 VirtualStore。

此时,已采取措施确保相关应用程序现在作为 UAC 感知的 64 位进程运行,但是,这对解决将用户数据迁移到被认为安全的位置的问题几乎没有作用来自虚拟化。

在解决此问题时,我发现在处理多个用户帐户时,已在位于 C:\Program Files(x86)\MyApp\Data 的旧路径中进行了一些更改,而同时,对位于 %localappdata%\VirtualStore\Programs\MyApp\Data 的 VirtualStore 进行了更改。问题是,我如何检测是否正在发生任何文件/文件夹虚拟化以及如何合并这两个位置?

编辑: 我找到了几个详细说明该问题以及如何重现该问题的网站,但没有任何网站包含解决该问题的方法。我确实找到了这个引用 FILE_ATTRIBUTE_VIRTUAL定义了一个看起来很有前途的文件属性——我在某处找到了另一个引用,虽然我不记得在哪里,它指出这是 Windows 用来指示文件虚拟化正在发生并标记重定向请求的属性。

这些链接描述了问题:

http://www.c-sharpcorner.com/uploadfile/GemingLeader/windows-file-and-registry-virtualization/

http://www.codeproject.com/Articles/66275/Windows-Vista-File-and-Registry-Virtualization

http://download.microsoftvirtuallabs.com/download/8/a/7/8a71365b-4c80-4e60-8185-8f12f59bf1d4/UACDataRedirection.pdf

最佳答案

这并不容易,但我找到了如何检测 UAC 虚拟化是否已启用。来电 GetTokenInformation()并传入 TokenVirtualizationEnabled 作为信息类将返回文件和注册表虚拟化是否启用。这是执行此操作的 C 函数:

// Gets whether the current process has UAC virtualization enabled.
// Returns TRUE on success and FALSE on failure.
BOOL GetVirtualizationEnabled(BOOL *enabled) {
HANDLE token;
DWORD tmpEnabled;
DWORD returnLen;
BOOL retVal = TRUE;

if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
return FALSE;

if(!GetTokenInformation(token, TokenVirtualizationEnabled,
&tmpEnabled, sizeof(tmpEnabled), &returnLen)) {
retVal = FALSE;
goto err;
}

*enabled = tmpEnabled;

err:
CloseHandle(token);

return retVal;
}

P/Invoke 有点难,但在这里,包括 P/Invoke header :

enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin,
TokenElevationType,
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
MaxTokenInfoClass
}

public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
public const UInt32 STANDARD_RIGHTS_READ = 0x00020000;
public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001;
public const UInt32 TOKEN_DUPLICATE = 0x0002;
public const UInt32 TOKEN_IMPERSONATE = 0x0004;
public const UInt32 TOKEN_QUERY = 0x0008;
public const UInt32 TOKEN_QUERY_SOURCE = 0x0010;
public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040;
public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080;
public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100;
public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
TOKEN_ADJUST_SESSIONID);

[DllImport("advapi32.dll", SetLastError=true)]
static extern bool GetTokenInformation(
IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
int TokenInformationLength,
out uint ReturnLength);

[DllImport("advapi32.dll", SetLastError = true)]
static extern bool SetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
ref uint TokenInformation, uint TokenInformationLength);

[DllImport("advapi32.dll", SetLastError=true)]
static extern bool OpenProcessToken(IntPtr ProcessHandle,
uint DesiredAccess, out IntPtr TokenHandle);

[DllImport("kernel32.dll", SetLastError=true)]
static extern bool CloseHandle(IntPtr hObject);

static bool TryGetVirtualizationEnabled(out bool enabled) {
IntPtr processHandle = Process.GetCurrentProcess().Handle;
IntPtr token;
uint returnLen;
object tmpEnabled = new uint();

enabled = false;
GCHandle handle = GCHandle.Alloc(tmpEnabled, GCHandleType.Pinned);

try {
if(!OpenProcessToken(processHandle, TOKEN_QUERY, out token))
return false;

try {
if(!GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TokenVirtualizationEnabled,
handle.AddrOfPinnedObject(), Marshal.SizeOf(typeof(uint)), out returnLen))
return false;

enabled = (uint)tmpEnabled != 0;
} finally {
CloseHandle(token);
}
} finally {
handle.Free();
}

return true;
}

我尝试使用任务管理器打开和关闭 UAC 虚拟化,并确认返回了正确的结果。可以通过调用 SetTokenInformation() 来启用和禁用虚拟化。 .

Microsoft 表示他们计划在未来的 Windows 版本中移除 UAC 虚拟化,并让程序不再依赖它。我看到有人建议制作一个 UAC 无法识别的单独程序,将文件从 VirtualStore 移动到 AppData,但我不知道这是否是一个好的解决方案。

关于c# - 如何检测到 Windows VirtualStore 的文件重定向?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14005081/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com