以用户身份运行程序,但具有更高的特权

时间:2018-12-31 06:45:17

标签: c# .net console-application administrator

场景:

管理员将安装该应用程序。该应用程序具有一些内核级别的操作,因此,它必须以特权模式运行。但是用户没有管理员凭据才能以提升模式运行应用程序。

那么,解决上述情况的最佳可能性是什么?

解决方案一(尝试): 通过管理员安装应用程序时,我们将创建一个管理员,在此我们可以知道他的用户名和密码。因此,当用户尝试执行任何操作时,我们将使用c#中的processstartinfo()和process.start()函数以提升模式运行应用程序。但是,该应用程序以管理员名称运行,因此该用户的映射驱动器不可见,因为该管理员不在ACL列表中。因此,这种方法正在被排除。

在使用c#应用程序完成操作之前,可以提升用户自己作为管理员的解决方案吗?

我被困住了,没有找到任何值得阅读的文章。

编辑: 在企业级别,Windows不会要求使用Bitlocker的管理员身份。因此,我们希望实现相同类型的功能。

有可能吗?

有人可以帮忙吗?

谢谢。

4 个答案:

答案 0 :(得分:3)

我所做的解决方案是将程序分为两部分。一部分作为使用管理员特权运行的服务运行,另一部分使用普通特权运行。 这两个程序之间的通信可以通过以太网或共享内存运行。

答案 1 :(得分:0)

我认为您可能会陷入困境,因为您要处理具有权限功能的两个功能,并且这两个功能都必须正确运行您的应用程序。

我注意到您有以下两个:

  • 文件系统路径。。只有登录的用户有权访问此文件(管理员帐户则无此权限)。
  • 申请流程。。只有管理员帐户可以运行这些流程(登录的用户将被提示具有用户权限)。

为了说明这一点...

        |  File System Path   |  Application Process
User    |        OK           |          --
Admin   |        --           |          OK

解决方案需要看起来像这样...

        |  File System Path   |  Application Process
Service |        OK           |          OK

如果可能的话,我想这是最简单的方法,您可以通过该方法创建一个具有执行这两项权限的服务帐户

答案 2 :(得分:0)

您可以尝试创建具有管理员权限的并行线程以执行内核操作。这样,您的整个程序就包含在一个可执行文件中。

答案 3 :(得分:0)

您可以使用COM+ Component Services。使用.NET,最简单的方法是使用Enterprise Services's ServicedComponent,它具有各种包装程序和实用程序类,可以与COM +组件服务进行互操作。

因此,请按以下步骤操作:

1)创建一个.NET Framework类库。

2)为它添加一个强名称并用它签名

3)例如为它添加一个这样的类(我还添加了一些实用的方法来诊断问题)

[ComVisible(true)]
public class AdminClass : ServicedComponent
{
    public int DoSomethingAsAdmin()
    {
        // test something that a normal user shouldn't see
        return Directory.GetFiles(Path.Combine(Environment.SystemDirectory, "config")).Length;
    }

    public string WindowsIdentityCurrentName => WindowsIdentity.GetCurrent().Name;
    public string CurrentProcessFilePath => Process.GetCurrentProcess().MainModule.FileName;

    // depending on how you call regsvcs, you can run as a 32 or 64 bit surrogate dllhost.exe
    public bool Is64BitProcess => Environment.Is64BitProcess;
}

4)将以下内容添加到AssemblyInfo.cs

[assembly: ApplicationName("AdminApp")]
[assembly: SecurityRole("AdminAppUser")]
[assembly: ApplicationActivation(ActivationOption.Server)]

这是定义一个名为“ AdminApp”的COM +应用程序,向其中添加一个名为“ AdminAppUser”的角色,然后声明该应用程序将作为“服务器”运行,这意味着“进程外”。

5)进行编译并以admin身份运行此命令

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regsvcs.exe AdminApp.dll

或此命令:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe AdminApp.dll

这两个命令都将创建COM +应用程序,并将.NET库DLL托管在代理.exe(dllhost.exe)中。如果选择第一个,则托管进程将以x64运行,如果选择第二个,则托管进程将以x86运行。

如果您运行组件服务(从Windows / Run),则可以检查此注册的结果:

enter image description here

6)右键单击该应用程序,您会看到一大堆可以配置的很棒的东西。请注意,您甚至可以将其作为服务运行(在“激活”标签中),等等。您必须做的是配置将运行此过程的身份,如下所示:

enter image description here

在这里,我使用了自定义管理员帐户。您不想使用其他任何内置选项。

7)现在,由于已启用默认安全性,因此基本上没有人可以调用此组件。因此,我们只需要向先前创建的角色“ AdminAppUser”添加用户即可。您当然可以使用如下所示的UI进行此操作:

enter image description here

但这是一段以编程方式执行此操作的代码(我们使用COM+ administration objects):

AddUserInRole("AdminApp", "AdminAppUser", @"SMO01\simon");

....

static void AddUserInRole(string appName, string roleName, string userName)
{
    dynamic catalog = Activator.CreateInstance(Type.GetTypeFromProgID("COMAdmin.COMAdminCatalog"));

    // the list of collection hierarchy : https://docs.microsoft.com/en-us/windows/desktop/cossdk/com--administration-collections
    var apps = catalog.GetCollection("Applications");
    var app = GetCollectionItem(apps, appName);
    if (app == null)
        throw new Exception("Application '" + appName + "' was not found.");

    var roles = apps.GetCollection("Roles", app.Key);
    var role = GetCollectionItem(roles, roleName);
    if (role == null)
        throw new Exception("Role '" + roleName + "' was not found.");

    // UsersInRole collection
    // https://docs.microsoft.com/en-us/windows/desktop/cossdk/usersinrole
    var users = roles.GetCollection("UsersInRole", role.Key);
    var user = GetCollectionItem(users, userName);
    if (user == null)
    {
        user = users.Add();
        user.Value["User"] = userName;
        users.SaveChanges();
    }
}

static dynamic GetCollectionItem(dynamic collection, string name)
{
    collection.Populate();
    for (int i = 0; i < collection.Count; i++)
    {
        var item = collection.Item(i);
        if (item.Name == name)
            return item;
    }
    return null;
}

结果应该是这样的:

enter image description here

8)现在,对于客户端应用程序,使用AdminApp工具很容易。不要将.DLL引用为标准.NET引用,而应将其用作任何其他外部COM组件。您可以引用由regsvcs创建的.TLB文件,或者仅使用我在此处演示的magic动态关键字(缺点是您无法自动完成):

using System;
using System.Security.Principal;

namespace UserApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Is64BitProcess " + Environment.Is64BitProcess);
            Console.WriteLine("Running As " + WindowsIdentity.GetCurrent().Name);

            var type = Type.GetTypeFromProgID("AdminApp.AdminClass");
            dynamic trustedClass = Activator.CreateInstance(type);

            Console.WriteLine("Admin App Process Path: " + trustedClass.CurrentProcessFilePath);
            Console.WriteLine("Admin App Running As: " + trustedClass.WindowsIdentityCurrentName);
            Console.WriteLine("Admin App Is64BitProcess: " + trustedClass.Is64BitProcess);
            Console.WriteLine("Admin App DoSomethingAsAdmin: " + trustedClass.DoSomethingAsAdmin());
        }
    }
}

现在,当您将其作为“ simon”运行时,您应该会看到类似的内容,它可以正常工作:

Is64BitProcess False
Running As SMO01\simon
Admin App Process Path: C:\WINDOWS\system32\dllhost.exe
Admin App Running As: SMO01\myAdmin
Admin App Is64BitProcess: True
Admin App DoSomethingAsAdmin: 71

例如,当您以未配置角色的“ bob”身份运行它时,您应该看到类似这样的内容,但访问被拒绝,这是预期的:

Is64BitProcess False
Running As SMO01\bob

Unhandled Exception: System.UnauthorizedAccessException: Retrieving the COM class factory for component with CLSID {0DC1F11A-A187-3B6D-9888-17E635DB0974} failed due to the following error: 80070005 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at UserApp.Program.Main(String[] args) in C:\Users\simon\source\repos\TrustedSystem\UserApp\Program.cs:line 14

请注意,我们创建了一个受信任的系统,而没有在任何地方设置任何密码。而且,我只是简单介绍了COM +组件的功能。例如,您可以将应用程序导出为.MSI,以便于部署等。