是否可以在Vista/Windows 7
中冒充管理员在代码中设置用户名、登录名和密码?
我的场景:很多用户(没有本地管理员权限)将执行c#程序;c#程序复制一个文件到C:Windows
。我希望程序使用管理员的凭据进行复制,而不会得到"拒绝访问"消息,也不会在UAC提示符中键入凭据。
我试过这两种方法:
- 包含
requireAdministrator
或highestAvailable
舱单。用户将被提示输入凭据,所以这不起作用。 - 从
advapi32.dll API
使用旧的LogonUser
进行模拟。我试过了,效果很好……
这可能吗?
编辑
很多人对我为什么做这么可怕的事情感兴趣。我正在编辑,包括一些我的评论,解释为什么我需要这个。
我们不能在每个用户计算机上创建一个计划任务。这是1时间问题:给所有用户发一封邮件,要求他们执行。exe文件网络文件夹中的文件(或附加.exe)。这就是全部要点:避免一台接一台地做。
来吧!我知道这是不对的,但情况就是这样。的正常和正确的方法将花费我们2个月的时间过程。总经理让我们想个办法在短时间内完成那件事一周的工作原因。这不是什么病毒或攻击…这是一个愚蠢的任务,更换过时的壁纸与新的用漂亮的新销售"咒语"。
正如其他人所说,您的解决方案打破了几个最佳实践,而"现在只需要完成它"并不是打破最佳实践的好时机,历史已经证明了这一点。所以你首先应该做的一些建议:
- 为这个 创建一个全新的帐户
- 为该帐户提供所需的最低权限
- 给该帐户一个非常短的(<1周)超时
这至少可以保证从现在起一年后不会有人偶然发现这个程序,并在任何地方拥有管理员权限。像这样的程序可能只需要一天的时间,但已经有人指出,这样做的安全性是徒劳的。
考虑到这一点,我发现了一个关于LogonUser突破性变化的帖子。它要求更改您的DllImport
代码从:
[DllImport("advapi32.dll", SetLastError = true)]
private extern static bool LogonUser(
string pszUsername, string pszDomain, string pszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
:
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain,
String lpszPassword, int dwLogonType, int dwLogonProvider,
out SafeTokenHandle phToken);
看看这是否能解决你的"只适用于Windows XP"的问题。
既然你有了编程问题的解决方案,你真的需要和你的公司谈谈,弄清楚为什么你的公司政策让你的IT部门失去了优势,以至于部署一个新的壁纸需要2个月的时间。这类问题可能会恶化到无法再修复的地步,因为修复的时间太长了。(哦,那个服务帐户的密码是三年前的,而且是一个域管理员,修复它需要大量的文书工作…)
你说你只是在改变用户的壁纸,正确的方法应该是两步的过程,这可以完全通过组策略来完成。
步骤1:有一个每台机器一次的启动脚本,将背景从网络共享复制到本地windows目录。
步骤2:将用户壁纸更新为新的公司壁纸。(你需要更新的reg键在HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionPolicies
,特别是Wallpaper
和WallpaperStyle
)
如果新壁纸的名称与旧壁纸相同,可以删除步骤2。
如果你真的必须按照你的方式去做,这里有一个基于我在自己的任务中使用的这个问题的答案的解决方案。
在你的代码中添加以下的native emethods类。
using System;
using System.Runtime.InteropServices;
/// <summary>
/// Implements P/Invoke Interop calls to the operating system.
/// </summary>
internal static class NativeMethods
{
/// <summary>
/// The type of logon operation to perform.
/// </summary>
internal enum LogonType : int
{
/// <summary>
/// This logon type is intended for users who will be interactively
/// using the computer, such as a user being logged on by a
/// terminal server, remote shell, or similar process.
/// This logon type has the additional expense of caching logon
/// information for disconnected operations; therefore, it is
/// inappropriate for some client/server applications, such as a
/// mail server.
/// </summary>
Interactive = 2,
/// <summary>
/// This logon type is intended for high performance servers to
/// authenticate plaintext passwords.
/// The LogonUser function does not cache credentials for this
/// logon type.
/// </summary>
Network = 3,
/// <summary>
/// This logon type is intended for batch servers, where processes
/// may be executing on behalf of a user without their direct
/// intervention. This type is also for higher performance servers
/// that process many plaintext authentication attempts at a time,
/// such as mail or Web servers.
/// The LogonUser function does not cache credentials for this
/// logon type.
/// </summary>
Batch = 4,
/// <summary>
/// Indicates a service-type logon. The account provided must have
/// the service privilege enabled.
/// </summary>
Service = 5,
/// <summary>
/// This logon type is for GINA DLLs that log on users who will be
/// interactively using the computer.
/// This logon type can generate a unique audit record that shows
/// when the workstation was unlocked.
/// </summary>
Unlock = 7,
/// <summary>
/// This logon type preserves the name and password in the
/// authentication package, which allows the server to make
/// connections to other network servers while impersonating the
/// client. A server can accept plaintext credentials from a
/// client, call LogonUser, verify that the user can access the
/// system across the network, and still communicate with other
/// servers.
/// NOTE: Windows NT: This value is not supported.
/// </summary>
NetworkCleartext = 8,
/// <summary>
/// This logon type allows the caller to clone its current token
/// and specify new credentials for outbound connections. The new
/// logon session has the same local identifier but uses different
/// credentials for other network connections.
/// NOTE: This logon type is supported only by the
/// LOGON32_PROVIDER_WINNT50 logon provider.
/// NOTE: Windows NT: This value is not supported.
/// </summary>
NewCredentials = 9
}
/// <summary>
/// Specifies the logon provider.
/// </summary>
internal enum LogonProvider : int
{
/// <summary>
/// Use the standard logon provider for the system.
/// The default security provider is negotiate, unless you pass
/// NULL for the domain name and the user name is not in UPN format.
/// In this case, the default provider is NTLM.
/// NOTE: Windows 2000/NT: The default security provider is NTLM.
/// </summary>
Default = 0,
/// <summary>
/// Use this provider if you'll be authenticating against a Windows
/// NT 3.51 domain controller (uses the NT 3.51 logon provider).
/// </summary>
WinNT35 = 1,
/// <summary>
/// Use the NTLM logon provider.
/// </summary>
WinNT40 = 2,
/// <summary>
/// Use the negotiate logon provider.
/// </summary>
WinNT50 = 3
}
/// <summary>
/// The type of logon operation to perform.
/// </summary>
internal enum SecurityImpersonationLevel : int
{
/// <summary>
/// The server process cannot obtain identification information
/// about the client, and it cannot impersonate the client. It is
/// defined with no value given, and thus, by ANSI C rules,
/// defaults to a value of zero.
/// </summary>
Anonymous = 0,
/// <summary>
/// The server process can obtain information about the client,
/// such as security identifiers and privileges, but it cannot
/// impersonate the client. This is useful for servers that export
/// their own objects, for example, database products that export
/// tables and views. Using the retrieved client-security
/// information, the server can make access-validation decisions
/// without being able to use other services that are using the
/// client's security context.
/// </summary>
Identification = 1,
/// <summary>
/// The server process can impersonate the client's security
/// context on its local system. The server cannot impersonate the
/// client on remote systems.
/// </summary>
Impersonation = 2,
/// <summary>
/// The server process can impersonate the client's security
/// context on remote systems.
/// NOTE: Windows NT: This impersonation level is not supported.
/// </summary>
Delegation = 3
}
/// <summary>
/// Logs on the user.
/// </summary>
/// <param name="userName">Name of the user.</param>
/// <param name="domain">The domain.</param>
/// <param name="password">The password.</param>
/// <param name="logonType">Type of the logon.</param>
/// <param name="logonProvider">The logon provider.</param>
/// <param name="token">The token.</param>
/// <returns>True if the function succeeds, false if the function fails.
/// To get extended error information, call GetLastError.</returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LogonUser(
string userName,
string domain,
string password,
LogonType logonType,
LogonProvider logonProvider,
out IntPtr token);
/// <summary>
/// Duplicates the token.
/// </summary>
/// <param name="existingTokenHandle">The existing token
/// handle.</param>
/// <param name="securityImpersonationLevel">The security impersonation
/// level.</param>
/// <param name="duplicateTokenHandle">The duplicate token
/// handle.</param>
/// <returns>True if the function succeeds, false if the function fails.
/// To get extended error information, call GetLastError.</returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DuplicateToken(
IntPtr existingTokenHandle,
SecurityImpersonationLevel securityImpersonationLevel,
out IntPtr duplicateTokenHandle);
/// <summary>
/// Closes the handle.
/// </summary>
/// <param name="handle">The handle.</param>
/// <returns>True if the function succeeds, false if the function fails.
/// To get extended error information, call GetLastError.</returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr handle);
}
这是在代码中使用的实现。
IntPtr token;
if (!NativeMethods.LogonUser(
this.userName,
this.domain,
this.password,
NativeMethods.LogonType.NewCredentials,
NativeMethods.LogonProvider.Default,
out token))
{
throw new Win32Exception();
}
try
{
IntPtr tokenDuplicate;
if (!NativeMethods.DuplicateToken(
token,
NativeMethods.SecurityImpersonationLevel.Impersonation,
out tokenDuplicate))
{
throw new Win32Exception();
}
try
{
using (WindowsImpersonationContext impersonationContext =
new WindowsIdentity(tokenDuplicate).Impersonate())
{
//Copy your file to the windows directory here.
impersonationContext.Undo();
return;
}
}
finally
{
if (tokenDuplicate != IntPtr.Zero)
{
if (!NativeMethods.CloseHandle(tokenDuplicate))
{
// Uncomment if you need to know this case.
////throw new Win32Exception();
}
}
}
}
finally
{
if (token != IntPtr.Zero)
{
if (!NativeMethods.CloseHandle(token))
{
// Uncomment if you need to know this case.
////throw new Win32Exception();
}
}
}