Что вы можете сделать, это использовать COM + Component Services .В .NET проще всего использовать ServicedComponent Enterprise Services , который имеет всевозможные обертки и служебные классы для взаимодействия со службами компонентов COM +.
Итак, вот шаги для этого:
1) Создайте библиотеку классов .NET Framework.
2) Добавьте строгое имя и подпишите его
3) Добавьте, например, такой класс (I ')мы также добавили некоторый служебный метод для диагностики вещей)
[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)]
Для этого нужно определить приложение COM + с именем "AdminApp",добавьте к нему роль с именем «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 + и разместят DLL-библиотеку .NET в суррогатном .exe (dllhost.exe).Если вы выберете первый, размещенный процесс будет работать как x64, а если вы запустите второй, размещенный процесс будет работать как x86.
Вы можете проверить результат этой регистрации, если вы запустите службы компонентов (изWindows / Run):
6) Щелкните правой кнопкой мыши приложение, и вы увидите целую кучу интересных вещей, которые можно настроить.Обратите внимание, что вы даже можете запустить это как службу (на вкладке «Активация») и т. Д. То, что вы должны сделать, это настроить удостоверение, которое будет запускать этот процесс, примерно так:
Здесь я использовал собственную учетную запись администратора.Вы не хотите, чтобы использовал любой другой встроенный выбор.
7) Теперь, когда включена защита по умолчанию, в принципе никто не может вызвать этот компонент.Поэтому нам просто нужно добавить пользователя к роли «AdminAppUser», которую мы создали ранее.Конечно, вы можете сделать это с помощью пользовательского интерфейса, как показано здесь:
, но вот фрагмент кода, который делает это программно (мы используем COM + объекты администрирования ):
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;
}
Результат должен быть таким:
8) Сейчасдля клиентского приложения использовать средства AdminApp очень просто.Не ссылайтесь на .DLL как на стандартную ссылку .NET, но используйте его как любой другой внешний COM-компонент.Вы можете сослаться на файл .TLB, который был создан regsvcs, или просто использовать магическое динамическое ключевое слово, как я продемонстрировал здесь (недостаток в том, что вы не получаете автозаполнение):
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 для легкого развертывания и т. Д.