none
DCOM и авторизация RRS feed

  • Вопрос

  • Есть скрипт на PowerShell:

    $Code = @" using System; using System.Runtime.InteropServices; public class Impersonate { [DllImport("Ole32.dll", CharSet = CharSet.Auto)] static extern int CoSetProxyBlanket( IntPtr pProxy, uint dwAuthnSvc, uint dwAuthzSvc, [MarshalAs(UnmanagedType.LPWStr)] string pServerPrincName, uint dwAuthnLevel, uint dwImpLevel, IntPtr pAuthInfo, uint dwCapabilities ); public static int EnableImpersonation(object objDCOM) { return CoSetProxyBlanket( Marshal.GetIDispatchForObject(objDCOM), //pProxy 0xFFFFFFFFU, //dwAuthnSvc = RPC_C_AUTHN_DEFAULT 0xFFFFFFFFU, //dwAuthzSvc = RPC_C_AUTHZ_DEFAULT null, //pServerPrincName 0, //dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT 3, //dwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE IntPtr.Zero, //pAuthInfo 0x800U //dwCapabilities = EOAC_DEFAULT ); } } "@ Add-Type -TypeDefinition $Code; $Obj = New-Object -ComObject 'Test.TestObj'; "Impersonation: " + [Impersonate]::EnableImpersonation($Obj) | Out-Host; try { $Obj.Connect("localhost"); 'Success!' | Out-Host; $Obj.Disconnect(); } catch { $_ | Out-Host; }

    И есть программа на C#, которой в ссылки добавлена TestLib:

    using TestLib;
    using System;
    using System.Runtime.InteropServices;
    
    public class Impersonate
    {
        [DllImport("Ole32.dll", CharSet = CharSet.Auto)]
        static extern int CoSetProxyBlanket(
            IntPtr pProxy,
            uint dwAuthnSvc,
            uint dwAuthzSvc,
            [MarshalAs(UnmanagedType.LPWStr)] string pServerPrincName,
            uint dwAuthnLevel,
            uint dwImpLevel,
            IntPtr pAuthInfo,
            uint dwCapabilities
        );
    
        public static int EnableImpersonation(object objDCOM)
        {
            return CoSetProxyBlanket(
                Marshal.GetIDispatchForObject(objDCOM), //pProxy
                0xFFFFFFFFU, //dwAuthnSvc = RPC_C_AUTHN_DEFAULT
                0xFFFFFFFFU, //dwAuthzSvc = RPC_C_AUTHZ_DEFAULT
                null, //pServerPrincName
                0, //dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT
                3, //dwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE
                IntPtr.Zero, //pAuthInfo
                0x800U //dwCapabilities = EOAC_DEFAULT
            );
        }
    }
    
    namespace Test
    {
        class Program
        {
            static void Main(string[] args)
            {
                TestObj Obj = new TestObj();
                Console.WriteLine("Impersonation: " + Impersonate.EnableImpersonation(Obj));
                try
                {
                    Obj.Connect("localhost");
                    Console.WriteLine("Success!");
                    Obj.Disconnect();
                }
                catch (Exception err)
                { Console.WriteLine(err.Message); }
            }
        }
    }

    Как говорится, найдите 10 отличий.

    Одно я сейчас покажу.

    Вот это - результат запуска Script.ps1:

    PS C:\Windows\system32> & "Script.ps1"
    Impersonation: 0
    Success!

    А вот это - результат запуска Test.exe:

    C:\Windows\System32>"Test.exe"
    Impersonation: 0
    System error 0x8009030E (В пакете безопасности отсутствуют учетные данные)

    Возможно, у вас, уважаемые гении, есть мысли, что произошло и что надо докрутить в Visual Studio, чтобы Test.exe тоже показал Success?

    Подсказка: если в dcomcnfg уровень олицетворения по умолчанию переключить с "Определить" на "Олицетворение" - всё сразу заработает.


    Сквозь сиреневый дым...



    3 сентября 2016 г. 0:18

Ответы

  • Использовать CoInitializeSecurity:

    public class Unmanaged
    {
        [DllImport("ole32.dll")]
        public static extern int CoInitializeSecurity(IntPtr pVoid, int
            cAuthSvc, IntPtr asAuthSvc, IntPtr pReserved1, RpcAuthnLevel level,
            RpcImpLevel impers, IntPtr pAuthList, EoAuthnCap dwCapabilities, IntPtr
            pReserved3);
    
        public enum RpcAuthnLevel
        {
            Default = 0,
            None = 1,
            Connect = 2,
            Call = 3,
            Pkt = 4,
            PktIntegrity = 5,
            PktPrivacy = 6
        }
    
        public enum RpcImpLevel
        {
            Default = 0,
            Anonymous = 1,
            Identify = 2,
            Impersonate = 3,
            Delegate = 4
        }
    
        public enum EoAuthnCap
        {
            None = 0x00,
            MutualAuth = 0x01,
            StaticCloaking = 0x20,
            DynamicCloaking = 0x40,
            AnyAuthority = 0x80,
            MakeFullSIC = 0x100,
            Default = 0x800,
            SecureRefs = 0x02,
            AccessControl = 0x04,
            AppID = 0x08,
            Dynamic = 0x10,
            RequireFullSIC = 0x200,
            AutoImpersonate = 0x400,
            NoCustomMarshal = 0x2000,
            DisableAAA = 0x1000
        }
    }

    Перед вызовом new TestObj()

    Unmanaged.CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero,
                                               Unmanaged.RpcAuthnLevel.Connect,
                                               Unmanaged.RpcImpLevel.Impersonate, IntPtr.Zero,
                                               Unmanaged.EoAuthnCap.None, IntPtr.Zero);

    Я так понимаю, все борьба с KSC:

    using System;
    using System.Runtime.InteropServices;
    
    
    namespace Test
    {
    
    public class Unmanaged
    {
        [DllImport("ole32.dll")]
        public static extern int CoInitializeSecurity(IntPtr pVoid, int
            cAuthSvc, IntPtr asAuthSvc, IntPtr pReserved1, RpcAuthnLevel level,
            RpcImpLevel impers, IntPtr pAuthList, EoAuthnCap dwCapabilities, IntPtr
            pReserved3);
    
        public enum RpcAuthnLevel
        {
            Default = 0,
            None = 1,
            Connect = 2,
            Call = 3,
            Pkt = 4,
            PktIntegrity = 5,
            PktPrivacy = 6
        }
    
        public enum RpcImpLevel
        {
            Default = 0,
            Anonymous = 1,
            Identify = 2,
            Impersonate = 3,
            Delegate = 4
        }
    
        public enum EoAuthnCap
        {
            None = 0x00,
            MutualAuth = 0x01,
            StaticCloaking = 0x20,
            DynamicCloaking = 0x40,
            AnyAuthority = 0x80,
            MakeFullSIC = 0x100,
            Default = 0x800,
            SecureRefs = 0x02,
            AccessControl = 0x04,
            AppID = 0x08,
            Dynamic = 0x10,
            RequireFullSIC = 0x200,
            AutoImpersonate = 0x400,
            NoCustomMarshal = 0x2000,
            DisableAAA = 0x1000
        }
    }
    
        class Program
        {
            static void Main(string[] args)
            {
    			 Unmanaged.CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero,
                                               Unmanaged.RpcAuthnLevel.Connect,
                                               Unmanaged.RpcImpLevel.Impersonate, IntPtr.Zero,
                                               Unmanaged.EoAuthnCap.None, IntPtr.Zero);
    										   
                Type type1 = Type.GetTypeFromProgID("klakaut.KlAkProxy", true);
    			dynamic Obj = (dynamic)Activator.CreateInstance(type1);
    			
    			Type type2 = Type.GetTypeFromProgID("klakaut.KlAkParams", true);
    			dynamic Params = (dynamic)Activator.CreateInstance(type2);
    			Params.Add("Address", "1localhost:14000");
    			Params.Add("UseSSL", false);
    			
                try
                {
                    Obj.Connect(Params);
                    Console.WriteLine("Success!{0}",Obj.VersionId);
                    Obj.Disconnect();
                }
                catch (Exception err)
                { Console.WriteLine(err.Message); }
            }
        }
    }
    

    4 сентября 2016 г. 11:05

Все ответы

  • Использовать CoInitializeSecurity:

    public class Unmanaged
    {
        [DllImport("ole32.dll")]
        public static extern int CoInitializeSecurity(IntPtr pVoid, int
            cAuthSvc, IntPtr asAuthSvc, IntPtr pReserved1, RpcAuthnLevel level,
            RpcImpLevel impers, IntPtr pAuthList, EoAuthnCap dwCapabilities, IntPtr
            pReserved3);
    
        public enum RpcAuthnLevel
        {
            Default = 0,
            None = 1,
            Connect = 2,
            Call = 3,
            Pkt = 4,
            PktIntegrity = 5,
            PktPrivacy = 6
        }
    
        public enum RpcImpLevel
        {
            Default = 0,
            Anonymous = 1,
            Identify = 2,
            Impersonate = 3,
            Delegate = 4
        }
    
        public enum EoAuthnCap
        {
            None = 0x00,
            MutualAuth = 0x01,
            StaticCloaking = 0x20,
            DynamicCloaking = 0x40,
            AnyAuthority = 0x80,
            MakeFullSIC = 0x100,
            Default = 0x800,
            SecureRefs = 0x02,
            AccessControl = 0x04,
            AppID = 0x08,
            Dynamic = 0x10,
            RequireFullSIC = 0x200,
            AutoImpersonate = 0x400,
            NoCustomMarshal = 0x2000,
            DisableAAA = 0x1000
        }
    }

    Перед вызовом new TestObj()

    Unmanaged.CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero,
                                               Unmanaged.RpcAuthnLevel.Connect,
                                               Unmanaged.RpcImpLevel.Impersonate, IntPtr.Zero,
                                               Unmanaged.EoAuthnCap.None, IntPtr.Zero);

    Я так понимаю, все борьба с KSC:

    using System;
    using System.Runtime.InteropServices;
    
    
    namespace Test
    {
    
    public class Unmanaged
    {
        [DllImport("ole32.dll")]
        public static extern int CoInitializeSecurity(IntPtr pVoid, int
            cAuthSvc, IntPtr asAuthSvc, IntPtr pReserved1, RpcAuthnLevel level,
            RpcImpLevel impers, IntPtr pAuthList, EoAuthnCap dwCapabilities, IntPtr
            pReserved3);
    
        public enum RpcAuthnLevel
        {
            Default = 0,
            None = 1,
            Connect = 2,
            Call = 3,
            Pkt = 4,
            PktIntegrity = 5,
            PktPrivacy = 6
        }
    
        public enum RpcImpLevel
        {
            Default = 0,
            Anonymous = 1,
            Identify = 2,
            Impersonate = 3,
            Delegate = 4
        }
    
        public enum EoAuthnCap
        {
            None = 0x00,
            MutualAuth = 0x01,
            StaticCloaking = 0x20,
            DynamicCloaking = 0x40,
            AnyAuthority = 0x80,
            MakeFullSIC = 0x100,
            Default = 0x800,
            SecureRefs = 0x02,
            AccessControl = 0x04,
            AppID = 0x08,
            Dynamic = 0x10,
            RequireFullSIC = 0x200,
            AutoImpersonate = 0x400,
            NoCustomMarshal = 0x2000,
            DisableAAA = 0x1000
        }
    }
    
        class Program
        {
            static void Main(string[] args)
            {
    			 Unmanaged.CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero,
                                               Unmanaged.RpcAuthnLevel.Connect,
                                               Unmanaged.RpcImpLevel.Impersonate, IntPtr.Zero,
                                               Unmanaged.EoAuthnCap.None, IntPtr.Zero);
    										   
                Type type1 = Type.GetTypeFromProgID("klakaut.KlAkProxy", true);
    			dynamic Obj = (dynamic)Activator.CreateInstance(type1);
    			
    			Type type2 = Type.GetTypeFromProgID("klakaut.KlAkParams", true);
    			dynamic Params = (dynamic)Activator.CreateInstance(type2);
    			Params.Add("Address", "1localhost:14000");
    			Params.Add("UseSSL", false);
    			
                try
                {
                    Obj.Connect(Params);
                    Console.WriteLine("Success!{0}",Obj.VersionId);
                    Obj.Disconnect();
                }
                catch (Exception err)
                { Console.WriteLine(err.Message); }
            }
        }
    }
    

    4 сентября 2016 г. 11:05
  • Она, родимая. Хотя у меня сейчас больше борьба не с KSC, а с программированием.

    Не посоветуете чего умного почитать про DCOM, что там после чего и зачем вызывать? А то я уже в этих бланкетах и секуритях немножко заблудился. Напрочь.

    Ага. Ещё один внезапный момент для меня. Оказывается, если создать в проекте ссылку на библиотеку типов COM, Visual Studio добавляет вызов CoInitializeSecurity с дефолтными значениями при запуске программы. Соответственно, любой запуск CoInitializeSecurity в теле Main возвращает RPC_E_TOO_LATE и фатальное отсутствие результата.

    Так и живём.

    7 сентября 2016 г. 2:13