- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
环境:Windows XP SP3、C#、.Net 4.0
问题:
我试图在模拟类中添加对模拟用户注册表配置单元的访问权限,但我遇到了基于被模拟用户类型的问题(或者更准确地说,限制似乎是模拟用户)。
我原来是在关注 an impersonation example from CodeProject其中显示了对 LoadUserProfile()
的调用使用通过调用 DuplcateToken()
生成的重复 token 开始模拟后发生来自 LogonUser()
获得的原始 token .我无法在我的环境中使用管理员帐户模拟受限用户的示例(从示例中包含的屏幕截图来看,它似乎是在 Windows Vista\7 系统上完成的,并且没有提供有关涉及的帐户类型)。
调用 LoadUserProfile()
抛出“拒绝访问”的错误。查看 userenv.log 显示“LoadUserProfile: failed to enable the restore privilege.error c0000022”这一行。 MSDN 上的 LoadUserProfile 文档显示调用进程必须拥有 SE_RESTORE_NAME 和 SE_BACKUP_NAME 权限,默认情况下只有 Administrators 和 Backup Operators 组的成员拥有这些权限。 (作为旁注,当我稍后尝试将这两个权限添加到用户组时,我仍然收到拒绝访问,但 userenv.log 显示“DropClientContext:客户端 [编号] 没有足够的权限。错误 5”,我不能' t 找到任何信息)
鉴于我模拟的用户没有这些权限,我将调用移至 LoadUserProfile()
在开始模拟之前,这次加载没有问题,我能够在这个测试中读写它。以为我已经找到了我的答案,我为帐户类型创建了一个条件检查,以便 LoadUserProfile()
如果当前用户是管理员的成员,则在模拟之前调用,或者如果成员不是管理员的成员,则等到模拟之后调用(在后面的实例中,我将依赖具有这些权限的模拟用户)。不幸的是我错了;我还没有发现我的答案。当我测试角色颠倒(用户 > 管理员)的调用时,调用 LoadUserProfile()
仍然再次失败,出现拒绝访问错误,并且 userenv.log 显示相同的“LoadUserProfile: failed to enable the restore privilege.error c0000061”,但这次有不同的错误号。
认为对LogonUser()
返回的token默认可能没有开启权限和\或 DuplicateToken()
我给 AdjustTokenPrivilege()
添加了两个电话在从 WindowsIdentity.GetCurrent(TokenAccessLevels.AdjustPrivileges | TokenAccessLevels.Query).Token
获得的当前用户 token (发生在模拟之后)上.TokenAccessLevels.AdjustPrivileges
和 TokenAccessLevels.Query
之所以被指定,是因为 MSDN 上的 AdjustTokenPrivilege 文档指定正在调整的 token 上需要它们(我还尝试使用从 OpenProcessToken()
检索到的句柄通过调用 System.Diagnostics.Process.GetCurrentProcess().Handle
获取 token ,但是当从用户调用时失败了模拟的内部和外部,GetCurrentProcess()
是抛出访问被拒绝的函数)AdjustTokenPrivilege()
与 WindowsIdentity...Token
一起使用时成功返回但是 LoadUserProfile()
仍然导致拒绝访问(恢复特权)。
在这一点上我不相信 AdjustTokenPrivilege()
正在做它的工作,所以我开始使用 GetTokenInformation()
确定特定 token 的可用权限以及它们处于什么状态。这导致了它自己的一小袋乐趣。在学习了一些新东西后,我可以拨打 GetTokenInformation()
并打印出权限列表及其当前状态,但结果有些不确定,因为在调用 AdjustTokenPrivilege()
之前和之后,还原和备份都显示属性为 0。作为管理员和冒充管理员(奇怪的是,当调用 AdjustTokenPrivilege()
时, token 上的其他三个权限从 2 变为 1,但实际上没有被调整,其值仍为 0)
我取消了对 DuplicateToken()
的调用并用从 LogonUser()
返回的 token 替换它正在使用的所有地方看看这是否有助于测试 token 的特权LogonUser()
和 DuplicateToken()
token 是相同的。当我最初编写模拟类时,我一直在调用 WindowsImpersonationContext.Impersonate()
时使用主要 token 。没有任何问题,并认为值得一试。
在我在下面提供的代码示例中,我可以在以管理员身份运行时模拟和访问用户的注册表,但反过来不行。任何帮助将不胜感激。
事前编辑:
我也试过使用 RegOpenCurrentUser()
API 代替 LoadUserProfile()
并成功使用管理员 > 自我和管理员 > 用户模拟,但是当从另一个管理员帐户或用户模拟管理员时 RegOpenCurrentUser()
返回一个指向 HKEY_USERS\S-1-5-18(无论是什么)而不是实际帐户配置单元的指针。我猜是因为它实际上并没有加载,这让我回到了需要使用的地方 LoadUserProfile()
来自 RegOpenCurrentUser 文档 (MSDN):
RegOpenCurrentUser uses the thread's token to access the appropriate key, or the default if the profile is not loaded.
// Private variables used by class
private IntPtr tokenHandle;
private PROFILEINFO pInfo;
private WindowsImpersonationContext thisUser;
private string sDomain = string.Empty;
private string sUsername = string.Empty;
private string sPassword = string.Empty;
private bool bDisposed = false;
private RegistryKey rCurrentUser = null;
private SafeRegistryHandle safeHandle = null;
//Constants used for privilege adjustment
private const string SE_RESTORE_NAME = "SeRestorePrivilege";
private const string SE_BACKUP_NAME = "SeBackupPrivilege";
private const UInt32 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
private const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
private const UInt32 SE_PRIVILEGE_REMOVED = 0x00000004;
private const UInt32 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;
[StructLayout(LayoutKind.Sequential)]
protected struct PROFILEINFO {
public int dwSize;
public int dwFlags;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpUserName;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpProfilePath;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpDefaultPath;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpServerName;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpPolicyPath;
public IntPtr hProfile;
}
protected struct TOKEN_PRIVILEGES {
public UInt32 PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public LUID_AND_ATTRIBUTES[] Privileges;
}
[StructLayout(LayoutKind.Sequential)]
protected struct LUID_AND_ATTRIBUTES {
public LUID Luid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential)]
protected struct LUID {
public uint LowPart;
public int HighPart;
}
// Private API calls used by class
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
protected static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("userenv.dll", SetLastError = true, CharSet = CharSet.Auto)]
protected static extern bool LoadUserProfile(IntPtr hToken, ref PROFILEINFO lpProfileInfo);
[DllImport("userenv.dll", SetLastError = true, CharSet = CharSet.Auto)]
protected static extern bool UnloadUserProfile(IntPtr hToken, IntPtr hProfile);
[DllImport("kernel32.dll", SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]
protected static extern bool CloseHandle(IntPtr hObject);
[DllImport("advapi32.dll", SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]
protected static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, UInt32 Zero, IntPtr Null1, IntPtr Null2);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)][return: MarshalAs(UnmanagedType.Bool)]
protected static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref LUID lpLuid);
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void Start() {
tokenHandle = IntPtr.Zero; // set the pointer to nothing
if (!LogonUser(sUsername, sDomain, sPassword, 2, 0, ref tokenHandle)) {
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
} // end if !LogonUser returned false
try { //All of this is for loading the registry and is not required for impersonation to start
LUID LuidRestore = new LUID();
LUID LuidBackup = new LUID();
if(LookupPrivilegeValue(null, SE_RESTORE_NAME, ref LuidRestore) && LookupPrivilegeValue(null, SE_BACKUP_NAME, ref LuidBackup)) {
//Create the TokenPrivileges array to pass to AdjustTokenPrivileges
LUID_AND_ATTRIBUTES[] LuidAndAttributes = new LUID_AND_ATTRIBUTES[2];
LuidAndAttributes[0].Luid = LuidRestore;
LuidAndAttributes[0].Attributes = SE_PRIVILEGE_ENABLED;
LuidAndAttributes[1].Luid = LuidBackup;
LuidAndAttributes[1].Attributes = SE_PRIVILEGE_ENABLED;
TOKEN_PRIVILEGES TokenPrivileges = new TOKEN_PRIVILEGES();
TokenPrivileges.PrivilegeCount = 2;
TokenPrivileges.Privileges = LuidAndAttributes;
IntPtr procHandle = WindowsIdentity.GetCurrent(TokenAccessLevels.AdjustPrivileges | TokenAccessLevels.Query).Token;
if(AdjustTokenPrivileges(procHandle, false, ref TokenPrivileges, 0, IntPtr.Zero, IntPtr.Zero)) {
pInfo = new PROFILEINFO();
pInfo.dwSize = Marshal.SizeOf(pInfo);
pInfo.lpUserName = sUsername;
pInfo.dwFlags = 1;
LoadUserProfile(tokenHandle, ref pInfo); //this is not required to take place
if(pInfo.hProfile != IntPtr.Zero) {
safeHandle = new SafeRegistryHandle(pInfo.hProfile, true);
rCurrentUser = RegistryKey.FromHandle(safeHandle);
}//end if pInfo.hProfile
}//end if AdjustTokenPrivileges
}//end if LookupPrivilegeValue 1 & 2
}catch{
//We don't really care that this didn't work but we don't want to throw any errors at this point as it would stop impersonation
}//end try
WindowsIdentity thisId = new WindowsIdentity(tokenHandle);
thisUser = thisId.Impersonate();
} // end function Start
最佳答案
来自 LoadUserProfile docs :
Starting with Windows XP Service Pack 2 (SP2) and Windows Server 2003, the caller must be an administrator or the LocalSystem account. It is not sufficient for the caller to merely impersonate the administrator or LocalSystem account.
关于c# - 模拟和 CurrentUser 注册表访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4392221/
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 4 年前。 Improv
PowerShell Web Access 允许您通过 Web 浏览器运行 PowerShell cmdlet。它显示了一个基于 Web 的控制台窗口。 有没有办法运行 cmdlet 而无需在控制台窗
我尝试在无需用户登录的情况下访问 Sharepoint 文件。 我可以通过以下任一方式获取访问 token 方法一: var client = new RestClient("https://logi
我目前正在尝试通过 Chrome 扩展程序访问 Google 服务。我的理解是,对于 JS 应用程序,Google 首选的身份验证机制是 OAuth。我的应用目前已成功通过 OAuth 向服务进行身份
假设我有纯抽象类 IHandler 和派生自它的类: class IHandler { public: virtual int process_input(char input) = 0; };
我有一个带有 ThymeLeaf 和 Dojo 的 Spring 应用程序,这给我带来了问题。当我从我的 HTML 文件中引用 CSS 文件时,它们在 Firebug 中显示为中止。但是,当我通过在地
这个问题已经有答案了: JavaScript property access: dot notation vs. brackets? (17 个回答) 已关闭 6 年前。 为什么这不起作用? func
我想将所有流量重定向到 https,只有 robot.txt 应该可以通过 http 访问。 是否可以为 robot.txt 文件创建异常(exception)? 我的 .htaccess 文件: R
我遇到了 LinkedIn OAuth2: "Unable to verify access token" 中描述的相同问题;但是,那里描述的解决方案并不能解决我的问题。 我能够成功请求访问 toke
问题 我有一个暴露给 *:8080 的 Docker 服务容器. 我无法通过 localhost:8080 访问容器. Chrome /curl无限期挂断。 但是如果我使用任何其他本地IP,我就可以访
我正在使用 Google 的 Oauth 2.0 来获取用户的 access_token,但我不知道如何将它与 imaplib 一起使用来访问收件箱。 最佳答案 下面是带有 oauth 2.0 的 I
我正在做 docker 入门指南:https://docs.docker.com/get-started/part3/#recap-and-cheat-sheet-optional docker-co
我正在尝试使用静态 IP 在 AKS 上创建一个 Web 应用程序,自然找到了一个带有 Nginx ingress controller in Azure's documentation 的解决方案。
这是我在名为 foo.js 的文件中的代码。 console.log('module.exports:', module.exports) console.log('module.id:', modu
我试图理解访问键。我读过https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-se
我正在使用 MGTwitterEngine"将 twitter 集成到我的应用程序中。它在 iOS 4.2 上运行良好。当我尝试从任何 iOS 5 设备访问 twitter 时,我遇到了身份验证 to
我试图理解访问键。我读过https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-se
我正在使用以下 API 列出我的 Facebook 好友。 https://graph.facebook.com/me/friends?access_token= ??? 我想知道访问 token 过
401 Unauthorized - Show headers - { "error": { "errors": [ { "domain": "global", "reas
我已经将我的 django 应用程序部署到 heroku 并使用 Amazon s3 存储桶存储静态文件,我发现从 s3 存储桶到 heroku 获取数据没有问题。但是,当我测试查看内容存储位置时,除
我是一名优秀的程序员,十分优秀!