Пример #1
0
        public void InjectFromCecilSecurityAttributeDefinitions()
        {
            var assembly = AssemblyCompiler.CompileTempAssembly(@"
			class Foo {
				public void CriticalMethod() {}
				public void Bar(int value) {}
				public void Bar(string value) {}
				public void SafeCriticalMethod() {}
				public Foo(string value) {}
			}

			class CriticalType {
			}
			"            );

            var finder             = new CecilDefinitionFinder(assembly);
            var safecriticalmethod = finder.FindMethod("System.Void Foo::SafeCriticalMethod()");
            var criticalmethod     = finder.FindMethod("System.Void Foo::CriticalMethod()");
            var criticaltype       = finder.FindType("CriticalType");

            var instructions = new List <CecilSecurityAttributeDescriptor>()
            {
                new CecilSecurityAttributeDescriptor(criticalmethod, SecurityAttributeType.Critical),
                new CecilSecurityAttributeDescriptor(safecriticalmethod, SecurityAttributeType.SafeCritical),
                new CecilSecurityAttributeDescriptor(criticaltype, SecurityAttributeType.Critical),
            };

            var injector = new Injector(assembly);

            injector.InjectAll(instructions);

            new AssemblySecurityVerifier(assembly.AssemblyPath()).Verify(instructions);
        }
Пример #2
0
        public void SetUp()
        {
            var executingAssemblyDefinition = CecilUtilsForTests.GetExecutingAssemblyDefinition();

            _finder  = new CecilDefinitionFinder(executingAssemblyDefinition);
            _subject = new MethodMap(_finder.FindType(GetType().FullName));
        }
Пример #3
0
        public void InjectFromCecilSecurityAttributeDefinitions()
        {
            var assembly = AssemblyCompiler.CompileTempAssembly(@"
            class Foo {
                public void CriticalMethod() {}
                public void Bar(int value) {}
                public void Bar(string value) {}
                public void SafeCriticalMethod() {}
                public Foo(string value) {}
            }

            class CriticalType {
            }
            ");

            var finder = new CecilDefinitionFinder(assembly);
            var safecriticalmethod = finder.FindMethod("System.Void Foo::SafeCriticalMethod()");
            var criticalmethod = finder.FindMethod("System.Void Foo::CriticalMethod()");
            var criticaltype = finder.FindType("CriticalType");

            var instructions = new List<CecilSecurityAttributeDescriptor>()
                                   {
                                       new CecilSecurityAttributeDescriptor(criticalmethod,SecurityAttributeType.Critical),
                                       new CecilSecurityAttributeDescriptor(safecriticalmethod,SecurityAttributeType.SafeCritical),
                                       new CecilSecurityAttributeDescriptor(criticaltype, SecurityAttributeType.Critical),
                                   };

            var injector = new Injector(assembly);
            injector.InjectAll(instructions);

            new AssemblySecurityVerifier(assembly.AssemblyPath()).Verify(instructions);
        }
Пример #4
0
        public void FindGenericMethod()
        {
            var assembly = CecilUtilsForTests.GetExecutingAssemblyDefinition();
            var finder   = new CecilDefinitionFinder(assembly);
            var found    = finder.FindMethod(string.Format("System.Void {0}::GenericMethod<T>(T&)", GetType().FullName));

            Assert.IsNotNull(found);
        }
Пример #5
0
        private static IEnumerable <TypeDefinition> CriticalTypesFor(AssemblyDefinition assemblyDefinition, string profileDirectory)
        {
            string assemblyName = assemblyDefinition.Name.Name;
            var    cdf          = new CecilDefinitionFinder(assemblyDefinition);

            var file = Files.CriticalTypesFileFor(assemblyName, profileDirectory);

            if (!File.Exists(file))
            {
                return(new TypeDefinition[0]);
            }
            return(File.ReadAllLines(file)
                   .Select(s => cdf.GetType(s)).Where(t => t != null));
        }
Пример #6
0
        private void AssertMethodRoundtrip(Func <int> func)
        {
            var method   = func.Method;
            var assembly = CecilUtilsForTests.GetExecutingAssemblyDefinition();
            var finder   = new CecilDefinitionFinder(assembly);

            // cecil uses / to introduce nested types, the runtime uses +
            var declaringTypeCecilName = method.DeclaringType.CecilTypeName();
            var type = finder.FindType(declaringTypeCecilName);

            Assert.IsNotNull(type, "Type {0} not found!", declaringTypeCecilName);

            var actualDefinition = type.Methods.GetMethod(method.Name)[0];
            var signature        = SignatureFor(actualDefinition);

            Assert.AreSame(actualDefinition, finder.FindMethod(signature));
        }
Пример #7
0
        private static IEnumerable <MethodToMethodCall> ReadMethodToMethodCallsFromFile(IEnumerable <AssemblyDefinition> assemblies, string file)
        {
            if (!File.Exists(file))
            {
                yield break;
            }
            foreach (var line in File.ReadAllLines(file))
            {
                if (line.StartsWith("#"))
                {
                    continue;
                }
                if (line.Trim().Length == 0)
                {
                    continue;
                }
                var splitter = "=>";
                int i        = line.IndexOf(splitter);
                if (i == -1)
                {
                    throw new ApplicationException("illegal line found in " + file + " was: " + line);
                }
                var caller = line.Substring(0, i).Trim();
                var callee = line.Substring(i + splitter.Length).Trim();

                var cecilDefinitionFinder = new CecilDefinitionFinder(assemblies);
                var mcaller = cecilDefinitionFinder.FindMethod(caller);
                if (mcaller == null)
                {
                    throw new ApplicationException("couldnt find method while parsing " + file + " signarture: " + caller);
                }
                var mcallee = cecilDefinitionFinder.FindMethod(callee);
                if (mcallee == null)
                {
                    throw new ApplicationException("couldnt find method while parsing " + file + " signarture: " + callee);
                }
                yield return(new MethodToMethodCall(mcaller, mcallee));
            }
        }
        private AssemblyDefinition PrepareTestForAssembly(string code, params string[] references)
        {
            _assembly = AssemblyCompiler.CompileTempAssembly(@"
            using System;
            using System.IO;
            using System.Runtime.CompilerServices;"

                                                             + code +

                                                             @"
            public static class Evil
            {
                [MethodImpl(MethodImplOptions.InternalCall)]
                public static void Do()
                {
                }
            }
", references);

            _cdf    = new CecilDefinitionFinder(_assembly);
            _evilDo = _cdf.FindMethod("System.Void Evil::Do()");
            return(_assembly);
        }
        public void TwoAssembliesWithCriticalType()
        {
            var assembly1 = AssemblyCompiler.CompileTempAssembly(@"
            public interface IMyEnumerator
            {
                void M1();
            }");

            var assembly2 = PrepareTestForAssembly(@"
            public class CriticalType : IMyEnumerator
            {
                public void M1()
                {
                    Evil.Do();
                }
            }
", assembly1.AssemblyPath());

            var finderForAssembly2 = new CecilDefinitionFinder(assembly2);
            var evilDo             = finderForAssembly2.FindMethod("System.Void Evil::Do()");
            var criticaltype       = finderForAssembly2.FindType("CriticalType");

            var assemblies = new[] { assembly1, assembly2 };

            var propagation = new MethodPrivilegePropagation(assemblies, new[] { evilDo }, new MethodDefinition[] { }, new[] { criticaltype }, new List <MethodToMethodCall>());
            var report      = propagation.CreateReportBuilder().Build();

            CollectionAssert.IsEmpty(report.GetInjectionsFor(assembly1));

            var injections = report.GetInjectionsFor(assembly2);
            var expected   = new[] {
                new CecilSecurityAttributeDescriptor(criticaltype, SecurityAttributeType.Critical),
                new CecilSecurityAttributeDescriptor(evilDo, SecurityAttributeType.Critical)
            };

            CollectionAssert.AreEquivalent(expected, injections);
        }
        private AssemblyDefinition PrepareTestForAssembly(string code, params string[] references)
        {
            _assembly = AssemblyCompiler.CompileTempAssembly(@"
            using System;
            using System.IO;
            using System.Runtime.CompilerServices;"

                +code+

            @"
            public static class Evil
            {
                [MethodImpl(MethodImplOptions.InternalCall)]
                public static void Do()
                {
                }
            }
            ", references);

            _cdf = new CecilDefinitionFinder(_assembly);
            _evilDo = _cdf.FindMethod("System.Void Evil::Do()");
            return _assembly;
        }
        public void TwoAssembliesWithCriticalType()
        {
            var assembly1 = AssemblyCompiler.CompileTempAssembly(@"
            public interface IMyEnumerator
            {
                void M1();
            }");

            var assembly2 = PrepareTestForAssembly(@"
            public class CriticalType : IMyEnumerator
            {
                public void M1()
                {
                    Evil.Do();
                }
            }
            ", assembly1.AssemblyPath());

            var finderForAssembly2 = new CecilDefinitionFinder(assembly2);
            var evilDo = finderForAssembly2.FindMethod("System.Void Evil::Do()");
            var criticaltype = finderForAssembly2.FindType("CriticalType");

            var assemblies = new[] { assembly1, assembly2 };

            var propagation = new MethodPrivilegePropagation(assemblies, new[] { evilDo }, new MethodDefinition[] { }, new[] { criticaltype }, new List<MethodToMethodCall>());
            var report = propagation.CreateReportBuilder().Build();

            CollectionAssert.IsEmpty(report.GetInjectionsFor(assembly1));

            var injections = report.GetInjectionsFor(assembly2);
            var expected = new[] {
                new CecilSecurityAttributeDescriptor(criticaltype, SecurityAttributeType.Critical),
                new CecilSecurityAttributeDescriptor(evilDo, SecurityAttributeType.Critical)
            };
            CollectionAssert.AreEquivalent(expected, injections);
        }
Пример #12
0
        public void Test()
        {
            // Step 1 - Step1: Detect methods that will fail at runtime if they're not [SC] or [SSC]

            const string requiresPrivilegesManual = @"
			System.Object Foo::Bar(System.Int32)
";

            var assembly1 = CompileTempAssembly(@"
			public class Foo {
				public static object Bar(int i) { return null; }
			}

			public class A {
				public unsafe void M1(int* i) {}
				public void M2() { Foo.Bar(0); }
				public void M3() { }
				public void M4() { M2(); }
				public unsafe void M5(int* i) { M1(i); }
			}

			unsafe public class CriticalType1 : I1
			{
				int* a;
				
				public void M6()
				{
					Foo.Bar(3);
				}
			}

			public interface I1 {
				void M6();
			}

			public interface I2 {
				void NotImplemented();
			}
");
            var assembly2 = CompileTempAssembly(@"

			using System.Runtime.CompilerServices;

			public class B : I1 {
				public void M1() {
					Foo.Bar(0);
				}

				[MethodImpl(MethodImplOptions.InternalCall)]
				public extern void M2();

				[MethodImpl(MethodImplOptions.InternalCall)]
				internal extern void M3();

				[MethodImpl(MethodImplOptions.InternalCall)]
				public extern void M4();

				public void M5() { M4(); }

				public void M6() { M1(); }
			}
", assembly1.MainModule.Image.FileInformation.FullName);

            var expectedRequiresPrivileges = new[]
            { @"# This file has a list of methods that were automatically detected to require privileges ([sc] or [ssc])
# in order to not generate an exception at runtime.

# using 'System.Int32*' as a parameter type
System.Void A::M1(System.Int32*)

# using 'System.Int32*' as a parameter type
System.Void A::M5(System.Int32*)",

              @"# This file has a list of methods that were automatically detected to require privileges ([sc] or [ssc])
# in order to not generate an exception at runtime.

# internal call
System.Void B::M2()

# internal call
System.Void B::M3()

# internal call
System.Void B::M4()".Replace("\n", "\r\n") };

            var assemblies = new[] { assembly1, assembly2 };

            AssemblySetResolver.SetUp(assemblies);

            var cdf           = new CecilDefinitionFinder(assembly1);
            var criticalTypes = new[] { cdf.GetType("CriticalType1") };

            var actualRequiresPrivileges = DetectMethodsRequiringPrivileges(criticalTypes, assemblies);

            Assert.AreEqual(expectedRequiresPrivileges, actualRequiresPrivileges.ToArray());


            // Step 2 - "Floodfill" requiredprivileges methods to all their callers, only being stopped by [SSC]
            var canBeSscManual = new[]
            {
                // assembly1
                Compatibility.ParseMoonlightAuditFormat(@"
!SSC-AA4CC9592C6775C5327AAA826B6693FF
System.Void A::M2()
	lucas - I checked this, it's totally safe"    ),

                // assembly2
                Compatibility.ParseMoonlightAuditFormat(@"
!SSC-AA4CC9592C6775C5327AAA826B6693FF
System.Void B::M2()
	lucas - I checked this, it's totally safe"    )
            };

            /*
             * publicApis  -> shows for each public entry point wether it's going to be [SC] or not.  for each [SC] method.
             * injectionInstructions -> all methods (public/nonpublic) that require decoration go in here.
             */

            actualRequiresPrivileges[0] += requiresPrivilegesManual;

            var propagationReport = PropagateRequiredPrivileges(criticalTypes, canBeSscManual, actualRequiresPrivileges.ToArray(), assembly1, assembly2);

            const string expectedInjectionInstructions = @"
SC-M: System.Object Foo::Bar(System.Int32)
SC-M: System.Void A::M1(System.Int32*)
SC-M: System.Void A::M5(System.Int32*)
SSC-M: System.Void A::M2()
SC-M: System.Void B::M1()
SSC-M: System.Void B::M2()
SC-M: System.Void B::M3()
SC-M: System.Void B::M4()
SC-M: System.Void B::M5()
SC-M: System.Void B::M6()
SC-M: System.Void I1::M6()
SC-T: CriticalType1
";

            StringAssert.AssertLinesAreEquivalent(expectedInjectionInstructions, propagationReport.InjectionInstructions);

            const string expectedPublicApis = @"
System.Void A::.ctor()    #available
System.Void A::M2()    #available
System.Void A::M3()    #available
System.Void A::M4()    #available
System.Void A::M5(System.Int32*)    #unavailable: method itself requires privileges
System.Void B::.ctor()    #available
System.Void B::M2()    #available
System.Void Foo::.ctor()    #available
System.Void I2::NotImplemented()    #available
System.Void A::M1(System.Int32*)    #unavailable: method itself requires privileges
System.Void B::M1()    #unavailable: calls System.Object Foo::Bar(System.Int32) which requires privileges itself
System.Void B::M4()    #unavailable: method itself requires privileges
System.Void B::M5()    #unavailable: calls System.Void B::M4() which requires privileges itself
System.Void B::M6()    #unavailable: calls System.Void B::M1() which calls System.Object Foo::Bar(System.Int32) which requires privileges itself
System.Object Foo::Bar(System.Int32)    #unavailable: method itself requires privileges
System.Void I1::M6()    #unavailable: is the base method of System.Void B::M6() which calls System.Void B::M1() which calls System.Object Foo::Bar(System.Int32) which requires privileges itself
System.Void CriticalType1::.ctor()    #unavailable: lives in a critical type
System.Void CriticalType1::M6()    #unavailable: lives in a critical type
";

            Console.WriteLine(propagationReport.PublicApis);
            StringAssert.AssertLinesAreEquivalent(expectedPublicApis, propagationReport.PublicApis);
        }
        public void Test()
        {
            var asssembly1src =
                @"
            using System;
            using System.Runtime.CompilerServices;

            public class A
            {
            public void Fine() {}
            unsafe public void NotFine(IntPtr* a) {}
            }

            unsafe public class B
            {
            IntPtr* bad;

            public void Fine() {}
            public void AlsoFine(IntPtr* a) {}

            [MethodImpl(MethodImplOptions.InternalCall)]
            public extern void AlsoFine2();
            }

            public class C
            {
            public void NotFine(B b) {}
            public void Fine() {}
            }

            public class SubB : B
            {
            }

            public class D
            {
            SubB b;
            }
            public class E
            {
            public void NotFine(D d) {}
            }

            ";

            var assembly = CSharpCompiler.CompileTempAssembly(asssembly1src);

            var ad = AssemblyFactory.GetAssembly(assembly);
            var cdf = new CecilDefinitionFinder(ad);
            MethodPrivilegeDetector.CriticalTypes = new[]
                                                        {
                                                            "B",
                                                            "SubB",
                                                            "D",
                                                        }.Select(s => cdf.FindType(s)).Cast<TypeReference>().ToList();
            var results = MethodPrivilegeDetector.MethodsRequiringPrivilegesThemselvesOn(ad).Select(kvp => kvp.Key);

            var expectedresults = new[]
                                  	{
                                  		"System.Void A::NotFine(System.IntPtr*)",
                                  		"System.Void C::NotFine(B)",
                                  		"System.Void E::NotFine(D)",
                                  	}.Select(s => cdf.FindMethod(s));

            CollectionAssert.AreEquivalent(expectedresults.ToArray(),results.ToArray());
        }
        public void Test()
        {
            // Step 1 - Step1: Detect methods that will fail at runtime if they're not [SC] or [SSC]

            const string requiresPrivilegesManual = @"
            System.Object Foo::Bar(System.Int32)
            ";

            var assembly1 = CompileTempAssembly(@"
            public class Foo {
                public static object Bar(int i) { return null; }
            }

            public class A {
                public unsafe void M1(int* i) {}
                public void M2() { Foo.Bar(0); }
                public void M3() { }
                public void M4() { M2(); }
                public unsafe void M5(int* i) { M1(i); }
            }

            unsafe public class CriticalType1 : I1
            {
                int* a;

                public void M6()
                {
                    Foo.Bar(3);
                }
            }

            public interface I1 {
                void M6();
            }

            public interface I2 {
                void NotImplemented();
            }
            ");
            var assembly2 = CompileTempAssembly(@"

            using System.Runtime.CompilerServices;

            public class B : I1 {
                public void M1() {
                    Foo.Bar(0);
                }

                [MethodImpl(MethodImplOptions.InternalCall)]
                public extern void M2();

                [MethodImpl(MethodImplOptions.InternalCall)]
                internal extern void M3();

                [MethodImpl(MethodImplOptions.InternalCall)]
                public extern void M4();

                public void M5() { M4(); }

                public void M6() { M1(); }
            }
            ", assembly1.MainModule.Image.FileInformation.FullName);

            var expectedRequiresPrivileges = new[]
            { @"# This file has a list of methods that were automatically detected to require privileges ([sc] or [ssc])
            # in order to not generate an exception at runtime.

            # using 'System.Int32*' as a parameter type
            System.Void A::M1(System.Int32*)

            # using 'System.Int32*' as a parameter type
            System.Void A::M5(System.Int32*)",

             @"# This file has a list of methods that were automatically detected to require privileges ([sc] or [ssc])
            # in order to not generate an exception at runtime.

            # internal call
            System.Void B::M2()

            # internal call
            System.Void B::M3()

            # internal call
            System.Void B::M4()".Replace("\n","\r\n")
            };

            var assemblies = new[] { assembly1, assembly2 };
            AssemblySetResolver.SetUp(assemblies);

            var cdf = new CecilDefinitionFinder(assembly1);
            var criticalTypes = new[] { cdf.GetType("CriticalType1") };

            var actualRequiresPrivileges = DetectMethodsRequiringPrivileges(criticalTypes, assemblies);

            Assert.AreEqual(expectedRequiresPrivileges, actualRequiresPrivileges.ToArray());

            // Step 2 - "Floodfill" requiredprivileges methods to all their callers, only being stopped by [SSC]
            var canBeSscManual = new[]
                                 	{
                                        // assembly1
                                 		Compatibility.ParseMoonlightAuditFormat(@"
            !SSC-AA4CC9592C6775C5327AAA826B6693FF
            System.Void A::M2()
            lucas - I checked this, it's totally safe"),

                                        // assembly2
                                        Compatibility.ParseMoonlightAuditFormat(@"
            !SSC-AA4CC9592C6775C5327AAA826B6693FF
            System.Void B::M2()
            lucas - I checked this, it's totally safe")

                                 	};

            /*
             * publicApis  -> shows for each public entry point wether it's going to be [SC] or not.  for each [SC] method.
             * injectionInstructions -> all methods (public/nonpublic) that require decoration go in here.
             */

            actualRequiresPrivileges[0] += requiresPrivilegesManual;

            var propagationReport = PropagateRequiredPrivileges(criticalTypes, canBeSscManual, actualRequiresPrivileges.ToArray(), assembly1, assembly2);

            const string expectedInjectionInstructions = @"
            SC-M: System.Object Foo::Bar(System.Int32)
            SC-M: System.Void A::M1(System.Int32*)
            SC-M: System.Void A::M5(System.Int32*)
            SSC-M: System.Void A::M2()
            SC-M: System.Void B::M1()
            SSC-M: System.Void B::M2()
            SC-M: System.Void B::M3()
            SC-M: System.Void B::M4()
            SC-M: System.Void B::M5()
            SC-M: System.Void B::M6()
            SC-M: System.Void I1::M6()
            SC-T: CriticalType1
            ";
            StringAssert.AssertLinesAreEquivalent(expectedInjectionInstructions, propagationReport.InjectionInstructions);

            const string expectedPublicApis = @"
            System.Void A::.ctor()    #available
            System.Void A::M2()    #available
            System.Void A::M3()    #available
            System.Void A::M4()    #available
            System.Void A::M5(System.Int32*)    #unavailable: method itself requires privileges
            System.Void B::.ctor()    #available
            System.Void B::M2()    #available
            System.Void Foo::.ctor()    #available
            System.Void I2::NotImplemented()    #available
            System.Void A::M1(System.Int32*)    #unavailable: method itself requires privileges
            System.Void B::M1()    #unavailable: calls System.Object Foo::Bar(System.Int32) which requires privileges itself
            System.Void B::M4()    #unavailable: method itself requires privileges
            System.Void B::M5()    #unavailable: calls System.Void B::M4() which requires privileges itself
            System.Void B::M6()    #unavailable: calls System.Void B::M1() which calls System.Object Foo::Bar(System.Int32) which requires privileges itself
            System.Object Foo::Bar(System.Int32)    #unavailable: method itself requires privileges
            System.Void I1::M6()    #unavailable: is the base method of System.Void B::M6() which calls System.Void B::M1() which calls System.Object Foo::Bar(System.Int32) which requires privileges itself
            System.Void CriticalType1::.ctor()    #unavailable: lives in a critical type
            System.Void CriticalType1::M6()    #unavailable: lives in a critical type
            ";
            Console.WriteLine(propagationReport.PublicApis);
            StringAssert.AssertLinesAreEquivalent(expectedPublicApis, propagationReport.PublicApis);
        }
Пример #15
0
        public void Test()
        {
            var asssembly1src =
                @"
using System;
using System.Runtime.CompilerServices;

public class A
{
	public void Fine() {}
	unsafe public void NotFine(IntPtr* a) {}
}

unsafe public class B
{
	IntPtr* bad;

	public void Fine() {}
	public void AlsoFine(IntPtr* a) {}

	[MethodImpl(MethodImplOptions.InternalCall)]
	public extern void AlsoFine2();
}

public class C
{
	public void NotFine(B b) {}
	public void Fine() {}
}

public class SubB : B
{
}

public class D
{
	SubB b;
}
public class E
{
	public void NotFine(D d) {}
}

";

            var assembly = CSharpCompiler.CompileTempAssembly(asssembly1src);

            var ad  = AssemblyFactory.GetAssembly(assembly);
            var cdf = new CecilDefinitionFinder(ad);

            MethodPrivilegeDetector.CriticalTypes = new[]
            {
                "B",
                "SubB",
                "D",
            }.Select(s => cdf.FindType(s)).Cast <TypeReference>().ToList();
            var results = MethodPrivilegeDetector.MethodsRequiringPrivilegesThemselvesOn(ad).Select(kvp => kvp.Key);


            var expectedresults = new[]
            {
                "System.Void A::NotFine(System.IntPtr*)",
                "System.Void C::NotFine(B)",
                "System.Void E::NotFine(D)",
            }.Select(s => cdf.FindMethod(s));

            CollectionAssert.AreEquivalent(expectedresults.ToArray(), results.ToArray());
        }