进程启动作为域pipe理员从用户启动进程与UAC在域networking中激活

我正试图做一些事情,现在我的头撞在屏幕上后,我不确定是否可以做到。

情况如下:

  • 一个带有域控制器的Windowsnetworking,PC的普通用户没有pipe理权限。
  • 在networking(UNCpath)共享中find更新(MSI)的程序将运行更新。
  • 因为用户不能进行安装。 更新必须与其他具有pipe理员权限的用户一起运行。

理论是有道理的,但是:

  • 它只适用于pipe理员用户是给定PC中的本地pipe理员。 我无法使它与在PC中没有本地帐户的域pipe理员一起工作。

我曾尝试过:

  • 使用advapi32.dll LogonUser中的令牌进行用户模拟。
  • 处理 – >开始()安装提供域pipe理员用户凭证。
  • 处理 – >开始()广告与域pipe理员,然后处理 – >开始()安装与普通用户。

如上所述,如果pipe理员用户在PC中有一个本地帐户,它将工作。 但是,如果我使用域pipe理员,则PC将提示UAC屏幕询问有效的pipe理员凭据。

如果我使用任务pipe理器进行检查,则进程将使用给定的凭证启动。 它只是没有安装的权利。

是否有可能做我在这里尝试的? 如果没有,任何方式?

问题是networking是从一个域进行pipe理的,PC不一定有本地创build的pipe理员用户帐户。

如上所述,如果管理员用户在PC中有一个本地帐户,它将工作。 但是,如果我使用域管理员,则PC将提示UAC屏幕询问有效的管理员凭据。

你想要发生什么? 为了模仿一个用户,你必须知道他们的密码。

用户需要知道域管理员的密码,所以他们将其输入到“同意”对话框中,然后安装即可继续。

您是否想象一个系统,可以以管理员身份运行应用程序,而无需任何人输入域管理员凭据? 这是根本不允许的。


有可能做我在这里尝试的吗?

我不确定你想在这里发生什么。 这就是为什么我问你到底想要发生什么。

我知道你想要启动一个具有管理权限的帐户的流程; 所以这个单独的过程可以执行更新。 我收集的问题是登录的用户不是管理员。

我无法使它与在PC中没有本地帐户的域管理员一起工作。

特别是在使用域管理员时,你想要做些什么? 什么,你想看到发生? 你是否认为,通过代码,你可以启动一个升级过程作为域用户没有UAC提示出现? 这不会发生。

但是这是可能的

所有这些话,你所描述的是可能的。 正如克里斯·杰克逊在博客中指出的那样 :

  1. 使用CreateProcessWithLogonW作为域管理员启动程序
  2. 从该应用程序中,使用带有runas谓词的ShellExecute提升为管理员
  3. 执行你的更新

我用一个快速的Delphi应用程序来模拟它。

最初,测试应用程序是以标准用户身份运行的(名为Forest Gump )。 我检测到他不是管理员,并在“ 更新软件”按钮上显示UAC屏蔽:

在这里输入图像说明

点击按钮会导致软件启动自己的副本,但使用域管理员帐户(我, 伊恩 )的凭据。 这是使用CreateProcessWithLogonW完成的:

 if IsUserAdmin then begin //No need for hoops, we're already an admin. Do the update. PerformUpdate(); Exit; end; //Relaunch ourselves as a particular domain admin user. username := 'ian@redacted.com'; password := 'correct battery horse staple'; applicationName := ParamStr(0); commandLine := applicationName+' /performUpdates'; ZeroMemory(@si, SizeOf(si)); si.cb := SizeOf(si); CreateProcessWithLogonW(PWideChar(username), nil, PWideChar(password), 0, PWideChar(applicationName), PWideChar(commandLine), 0, nil, nil, si, {var} pi) 

诀窍是我们传递/performUpdates选项。 当我们的应用程序启动时,它会检测是否被指示执行更新。 如果是这样,我们使用ShellExecuterunas谓词来启动自己的升级副本:

 procedure TForm1.FormActivate(Sender: TObject); begin if FindCmdLineSwitch('performUpdates', True) then begin //If we're not an admin, then use ShellExecute to launch ourselves as one if not IsUserAdmin then begin //Relaunch ourselves as an admin Toolkit.RunAsAdmin(0, ParamStr(0), '/performUpdates'); //don't forget to pass the command option Application.Terminate; Exit; end; //We are an admin; do the updates. PerformUpdates; MessageDlg('Update complete.', mtINformation, [mbOk], 0); Application.Terminate; Exit; end; end; 

带有runas动词的ShellExecute触发UAC提升提示,然后升级的应用程序作为我( Ian )运行,出现具有管理权限的不同管理员用户:

在这里输入图像说明

RunAsAdmin函数是ShellExecute的简单包装:

 function RunAsAdmin(hWnd: HWND; filename: string; Parameters: string): Boolean; { See Step 3: Redesign for UAC Compatibility (UAC) http://msdn.microsoft.com/en-us/library/bb756922.aspx } var sei: TShellExecuteInfo; begin ZeroMemory(@sei, SizeOf(sei)); sei.cbSize := SizeOf(TShellExecuteInfo); sei.Wnd := hwnd; sei.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_FLAG_NO_UI; sei.lpVerb := PChar('runas'); sei.lpFile := PChar(Filename); // PAnsiChar; if parameters <> '' then sei.lpParameters := PChar(parameters); // PAnsiChar; sei.nShow := SW_SHOWNORMAL; //Integer; Result := ShellExecuteEx(@sei); end; 

在语法上稍微简单一些,但UseShellExecuteVerb =“runas”是关键点。

.NET中的函数IsUserAdmin要容易得多:

 //helper function that tells us if we're already running with administrative rights private Boolean IsUserAnAdmin() { //A user can be a member of the Administrator group, but not an administrator. //Conversely, the user can be an administrator and not a member of the administrators group. //Check if the current user has administrative privelages var identity = WindowsIdentity.GetCurrent(); return (null != identity && new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator)); } 

比原生代码还要多:

 function IsUserAdmin: Boolean; var b: BOOL; AdministratorsGroup: PSID; begin { This function returns true if you are currently running with admin privelages. In Vista and later, if you are non-elevated, this function will return false (you are not running with administrative privelages). If you *are* running elevated, then IsUserAdmin will return true, as you are running with admin privelages. Windows provides this similar function in Shell32.IsUserAnAdmin. But the function is depricated, and this code is lifted from the docs for CheckTokenMembership: http://msdn.microsoft.com/en-us/library/aa376389.aspx } { Routine Description: This routine returns TRUE if the callers process is a member of the Administrators local group. Caller is NOT expected to be impersonating anyone and is expected to be able to open its own process and process token. Arguments: None. Return Value: TRUE - Caller has Administrators local group. FALSE - Caller does not have Administrators local group. } b := AllocateAndInitializeSid( SECURITY_NT_AUTHORITY, 2, //2 sub-authorities SECURITY_BUILTIN_DOMAIN_RID, //sub-authority 0 DOMAIN_ALIAS_RID_ADMINS, //sub-authority 1 0, 0, 0, 0, 0, 0, //sub-authorities 2-7 not passed AdministratorsGroup); if (b) then begin if not CheckTokenMembership(0, AdministratorsGroup, b) then b := False; FreeSid(AdministratorsGroup); end; Result := b; end; 

所以,所有的工作,并做你所需要的。 但用户仍然会被提交一个UAC 同意对话框; 尽管他们只会继续下去。 我收集这对你不合适。 即使是这样:

不要这样做

上面的代码中的关键问题,克里斯·杰克逊在他的博客中提到:

最常见的要求是编写自制软件部署软件的人,他们希望将凭证直接编码到应用程序中,并提升自己的流程。 这里真正的问题不在于API的缺乏,而在于您的应用程序中已有管理员凭据编码,供全世界阅读 。 如果你有这个想法,你想要的就是尽快到达一个你没有的地方,而不是让这个设计更容易。

可怕的,可怕的,违规的代码是:

 //Relaunch ourselves as a particular domain admin user. username := 'ian@redacted.com'; password := 'correct battery horse staple'; 

你已经硬编码了用户的密码。 这不好。 你不要那个。

希望管理员实际需要走到机器并输入他的凭据。

更简单的选择

您正处于允许任何用户更新应用程序的世界。 如果这是真的,如果所有的用户都被允许修改文件和注册表项,那就让他们

在应用程序安装过程中,更改您的应用程序的文件夹的NTFS权限,以便所有用户具有完全控制

在这里输入图像说明

这是解决您的问题的正确方法。

即使上面没有回答你的问题。

你要看什么?

现在我们来了整整一圈。 你要看什么?

注意 :任何代码都被释放到公共领域。 不需要归属