运行 没有以管理员身份弹出 UAC 的可执行文件

Run Executable File Without UAC Popup as Administrator

我正在 运行进行一项大型研究,我们在不同国家/地区的工作人员收集有关平板电脑的信息 运行宁 Windows 10 家企业。每个员工都被分配到一台平板电脑,他们使用标准用户名和密码登录平板电脑。这些用户在机器上没有本地管理员权限,但所有平板电脑都有一个我知道的管理员用户名和密码,并且这些在平板电脑上是统一的。

每天晚上,用户都会在他们的平板电脑上调用一个程序,将数据上传到我们的服务器,然后我们在此同步过程中将信息传回平板电脑。否则,它们将与互联网断开连接。在同步过程结束时,将执行一个程序,允许我 运行 我喜欢的任何脚本,但脚本在标准用户帐户下执行(即没有提升的权限)。

我需要为所有平板电脑更新他们在平板电脑上使用的软件的错误修复,我想在同步过程中执行此操作。错误修复包含在一个简单的可执行文件中,可以很容易地将它与我在同步期间喜欢的任何代码一起推送到员工的平板电脑上。如果用户 运行 以管理员身份运行同步程序,这就不是问题,因为我可以在同步结束时通过脚本 运行 简单地 运行 可执行文件。但他们不是,所以我试图找到一种方法,我可以 运行 一个脚本(我真的不在乎它是什么。它可能是一个 windows 批处理文件,一个 vbs脚本、VB.NET、powershell 等)并让该脚本以管理权限执行并且 运行 安装没有 UAC 提示干扰。

老实说,我什至不介意以明文形式提供管理员密码,因为这些用户都是我们的员工,他们不能用它做任何真正与我们有关的事情(而且我总是可以部署后续的通过同步过程删除文件中有密码的程序)。我意识到这听起来有些复杂,但简而言之,我想执行以下步骤:

  1. 将错误更新可执行文件发送到平板电脑(我现在可以这样做)
  2. 开发自定义代码,将管理员凭据传递给平板电脑并在 1 中安装可执行文件而不显示 UAC(我可以在同步期间将脚本发送到平板电脑但不知道如何以管理员身份执行它没有得到 UAC 提示)。

有什么办法可以做到这一点吗?我已经使用 PowerShell 脚本(如 here and here 中描述的脚本)探索了一整天,但收效甚微。这是我在 $cred 中存储凭据后得到的最接近的,但它继续给我 UAC 提示:

Start-Process PowerShell.exe -Cred $cred -ArgumentList '-command &{Start-Process -FilePath C:\MySyncPath\BugFix32.exe -Verb runas}]

更新

经过一些额外的工作后,我想我可以将其设置为 运行,如果我能以某种方式使用可以在普通用户帐户下 运行 的脚本禁用 UAC 控制,并且将管理员凭据传递给它。知道我怎样才能做到这一点吗?如果我能让它工作,即使重新启动,我也能完成我需要的。

这不是 PowerShell 的东西,而是一般的 windows 10 的东西。您需要为此禁用 UAC。不过 Windows 10 还没有使用它的经验。

您可以尝试将 EnableLUA 注册表项设置为 0。密钥可以在以下位置找到: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System

不过这可能需要重启才能生效。

此问题属于 "when people ask for security holes as features" 的类别。

您不能绕过(或者,如果您更喜欢这种措辞,"programmatically accept")UAC 提示并在没有交互式确认的情况下自动提升。 UAC 是专门为防止这种情况而设计的。 (如果这是可能的,所有的恶意软件都会这样做。)

您遇到的实际问题是您想要更新您的应用程序,但该应用程序位于 Program Files 文件夹(或标准用户不在的其他位置)允许修改)。

为了允许任何用户更新您的程序,您必须授予所有用户对您的文件夹的完全控制。理想情况下,您的应用程序的安装程序会在安装期间对 DACL 进行此调整(当安装程序 运行 作为管理员时)。

现在您将不得不接受最终的一次性要求,即用户提升为管理员。然后您可以禁用您应用程序的所有安全性 - 允许任何用户(恶意或非恶意)随意修改您的应用程序。

GrantEveryoneFullControlToFileOrFolder("C:\Program Files\Contoso");

伪代码实现:

void  GrantAllUsersFullControlToFileOrFolder(String path)
{
    PACL oldDACL;
    PACL newDACL;    
    PSECURITY_DESCRIPTOR sd;

    //Get the current DALC (Discretionary Access Control List) and Security Descriptor
    GetNamedSecurityInfo(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, 
          nil, nil, ref oldDACL, nil, ref sd);

    //Create an SID for the "Users" group
    PSID usersSid = StringToSid("S-1-5-32-545");

    // Initialize an EXPLICIT_ACCESS structure for the new Access Control Entry (ACE)
    EXPLICIT_ACCESS ea;
    ZeroMemory(@ea, SizeOf(EXPLICIT_ACCESS));
    ea.grfAccessPermissions  = GENERIC_ALL;
    ea.grfAccessMode         = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE;
    ea.grfInheritance        = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
    ea.Trustee.TrusteeForm   = TRUSTEE_IS_SID;
    ea.Trustee.TrusteeType   = TRUSTEE_IS_GROUP;
    ea.Trustee.ptstrName     = PChar(usersSID);

    // Create a new ACL that merges the new ACE into the existing ACL.
    // SetEntriesInAcl takes care of adding the ACE in the correct order in the list
    SetEntriesInAcl(1, @ea, oldDACL, ref newDACL); //use LocalFree to free returned newDACL

    //Attach the new ACL as the object's new DACL
    SetNamedSecurityInfo(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
          nil, nil, newDACL, nil);

    LocalFree(HLOCAL(sd));
    LocalFree(HLOCAL(newDACL));
    FreeSid(usersSID);
}

任何用户都可以修改应用程序并非完全闻所未闻:大多数 MMO 都会在您玩游戏时安装更新。 MMOs usually have a shim applied by Microsoft that gives 应用程序文件夹的所有用户控制。

运行 脚本作为域管理员帐户...并在脚本之前设置执行策略 运行,然后 运行 作为管理员...有些应用程序很挑剔UAC 仍然存在,但 Set-ExecutionPolicy [bypass/remotesigned] 将确保您不会收到提示。但是,如果域管理员帐户无权访问共享,则共享和权限可能仍然是个问题。 psexec 执行此操作,但这实际上是执行我刚才提到的操作,而 psexec 文件实质上是在脚本末尾写出权限。目的是确保密码不是以明文形式编写的,它会散列密码值。无论哪种方式,如果您希望安全地完成此操作,使用 GPO 并确保您的文件 permissions/share 处于最高级别可能会重复提示。这就是为什么你会看到一些批处理文件使用 %1 %2 %3 %4 %5 %6 %7 %8 %9 ....这是因为它会自动请求提升并将在迭代循环中循环直到出现 UAC 提示没必要。

我知道我遇到了一个旧线程,但这是我发现的,试图将旧的 cmd 批处理与 powershell 混合和匹配......很多关于导致调用的执行策略与期间的考虑电话...