C++ 如何从更高级别在用户级别启动Exe

C++ 如何从更高级别在用户级别启动Exe,c++,winapi,uac,C++,Winapi,Uac,我希望流程始终在用户级别运行。当安装程序(自定义,而不是msi)启动它时(以管理员级别运行),或者当用户登录时。环顾四周,我不确定这是否可行。每个人都在寻找另一条路。总之,这应该会有帮助。假设您知道要以哪个用户的身份运行,并且有他们的密码,则会这样做。有很多黑客方法可以做到这一点(使用taskscheduler,注入explorer.exe等) 获得正确用户的唯一方法(UAC提升之前启动程序的用户(可能与shell/“登录”/“会话所有者”的用户不同)是让安装程序运行自身的两个实例,一个未提升的

我希望流程始终在用户级别运行。当安装程序(自定义,而不是msi)启动它时(以管理员级别运行),或者当用户登录时。环顾四周,我不确定这是否可行。

每个人都在寻找另一条路。总之,这应该会有帮助。

假设您知道要以哪个用户的身份运行,并且有他们的密码,则会这样做。

有很多黑客方法可以做到这一点(使用taskscheduler,注入explorer.exe等)

获得正确用户的唯一方法(UAC提升之前启动程序的用户(可能与shell/“登录”/“会话所有者”的用户不同)是让安装程序运行自身的两个实例,一个未提升的“外部”实例,它主要通过使用ShellExecute[Ex]启动自身来启动另一个实例用runas动词。当需要启动中/低级进程时,通过某种形式的IPC提升的实例会通知外部实例启动新进程


实现起来很麻烦,我建议不要在安装程序的末尾设置run复选框。

与Bill所说的类似,您也可以使用CreateProcessAsUser()API来实现

  • 首先使用LogonUser()并获取进程需要作为其运行的用户的访问令牌。此处,如果用户属于administrators组(如果您将LOGON\u标志传递为LOGON32\u LOGON\u INTERACTIVE,那么您将获得一个分割令牌)。因此,如果需要提升的管理员令牌,请将标志作为LOGON32\u LOGON\u批传递
  • 使用上面获得的令牌,您可以通过命令行和参数调用CreateProcessAsUser()

  • 最简单的方法是有两个进程。一个是普通用户,它启动提升/管理进程。然后,管理进程可以使用IPC来请求正常的用户进程做一些事情

    如果没有正常的用户流程,则文档:

    从一个不相关的过程到一个提升的过程是很容易的。您可以运行一个进程,该进程的提升方式为Shell-Execute或Shell-Execute-Ex

    走另一条路更难。首先,很难通过咀嚼你的标识来正确地移除提升属性。还有一件事,即使你能做到,这也不是正确的做法,因为未提升的用户可能与提升的用户不同

    这里的解决方案是返回到Explorer,让Explorer为您启动程序。由于Explorer是以原始未关联用户的身份运行的,因此程序(在本例中为Web浏览器)将以Bob的身份运行。如果要打开的文件的处理程序作为进程内扩展而不是单独的进程运行,这一点也很重要,因为在这种情况下,取消关联的尝试将毫无意义,因为首先没有创建新进程。(如果文件的处理程序尝试与自身的现有不相关副本通信,则可能会因为UIPI而失败。)

    好吧,我知道小节目不应该有动机,但我无法控制自己。别说了。让我们编写代码。(请记住,小程序很少或根本不进行错误检查,因为它们就是这样运行的。)

    #定义严格的
    #包括
    #包括
    #包括
    #包括
    #包括
    在用户的默认Web浏览器中打开不相关的网页
  • scratch cmd.exe“C:\Users”3
    在C:\Users(最大化)处打开一个不相关的命令提示符
  • 划痕C:\Path\To\Image.bmp“”编辑
    在未提升的图像编辑器中编辑位图

  • 这很好,但不是“唯一”(正确)的方式。您可以调用IShell-Dispatch2::Shell-Execute而无需注入。@Alexander:IShell-Dispatch2将以与Explorer.exe相同的用户身份执行,这可能不是“正确”的用户,并且在使用cmd.exe Shell的服务器核心上根本无法工作……非常有用。谢谢它工作得很好。不幸的是,你必须小心不要过早地给FindWindowSW打电话。如果在桌面启动之前调用,它将返回带有空指针的S_FALSE。当一个新用户在Windows10机器上安装时,我们经常看到这种情况。我们的代码在完成之前启动。
    #define STRICT
    #include <windows.h>
    #include <shldisp.h>
    #include <shlobj.h>
    #include <exdisp.h>
    #include <atlbase.h>
    #include <stdlib.h>
    
    void FindDesktopFolderView(REFIID riid, void **ppv)
    {
     CComPtr<IShellWindows> spShellWindows;
     spShellWindows.CoCreateInstance(CLSID_ShellWindows);
    
     CComVariant vtLoc(CSIDL_DESKTOP);
     CComVariant vtEmpty;
     long lhwnd;
     CComPtr<IDispatch> spdisp;
     spShellWindows->FindWindowSW(
         &vtLoc, &vtEmpty,
         SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp);
    
     CComPtr<IShellBrowser> spBrowser;
     CComQIPtr<IServiceProvider>(spdisp)->
         QueryService(SID_STopLevelBrowser,
                      IID_PPV_ARGS(&spBrowser));
    
     CComPtr<IShellView> spView;
     spBrowser->QueryActiveShellView(&spView);
    
     spView->QueryInterface(riid, ppv);
    }    
    
    void GetDesktopAutomationObject(REFIID riid, void **ppv)
    {
     CComPtr<IShellView> spsv;
     FindDesktopFolderView(IID_PPV_ARGS(&spsv));
     CComPtr<IDispatch> spdispView;
     spsv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&spdispView));
     spdispView->QueryInterface(riid, ppv);
    }
    
    void ShellExecuteFromExplorer(
        PCWSTR pszFile,
        PCWSTR pszParameters = nullptr,
        PCWSTR pszDirectory  = nullptr,
        PCWSTR pszOperation  = nullptr,
        int nShowCmd         = SW_SHOWNORMAL)
    {
     CComPtr<IShellFolderViewDual> spFolderView;
     GetDesktopAutomationObject(IID_PPV_ARGS(&spFolderView));
     CComPtr<IDispatch> spdispShell;
     spFolderView->get_Application(&spdispShell);
    
     CComQIPtr<IShellDispatch2>(spdispShell)
        ->ShellExecute(CComBSTR(pszFile),
                       CComVariant(pszParameters ? pszParameters : L""),
                       CComVariant(pszDirectory ? pszDirectory : L""),
                       CComVariant(pszOperation ? pszOperation : L""),
                       CComVariant(nShowCmd));
    }
    
    int __cdecl wmain(int argc, wchar_t **argv)
    {
     if (argc < 2) return 0;
    
     CCoInitialize init;
     ShellExecuteFromExplorer(
        argv[1],
        argc >= 3 ? argv[2] : L"",
        argc >= 4 ? argv[3] : L"",
        argc >= 5 ? argv[4] : L"",
        argc >= 6 ? _wtoi(argv[5]) : SW_SHOWNORMAL);
    
     return 0;
    }