Execute .NET IL code in C#

后端 未结 1 1499
自闭症患者
自闭症患者 2021-02-07 05:41

Is there any way to execute an array of IL codes in C# like shell codes in C/C++?

I want to create a method, convert it to IL code, obfuscate it and store in an array of

1条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-07 06:03

    You will need to use the infrastructure in the System.Reflection.Emit namespace. Specifically, you should look at the docs for MethodBuilder.CreateMethodBody which takes an array of bytes representing MSIL instructions. There is a full example there, but below is short snippet of its use. Here, I will create a delegate to the dynamic method as well.

    I will note that this is only supported in a very limited way, which is called out in the docs:

    This is currently not fully supported. The user cannot supply the location of token fix ups and exception handlers.

    The issue is that metadata tokens used in IL to reference types, methods, string literals, etc are resolved at the module level. Thus IL is not completely portable in the sense that you can't take arbitrary, raw IL from a method in one module and just drop it into another method in another module. You need the proper metadata tokens in the new module. However, if you know that your IL contains no metadata tokens you can do it, but this severely limits what you can do with this. (HT: svick, Simon Svensson)

    class Program
    {
        static void Main(string[] args)
        {
            // opcodes for pushing two arguments to the stack, adding, and returning the result.
            byte[] ilcodes = { 0x02, 0x03, 0x58, 0x2A };
            var method = CreateFromILBytes(ilcodes);
            Console.WriteLine(method(2, 3));
        }
    
        private static Func CreateFromILBytes(byte[] bytes)
        {
            var asmName = new AssemblyName("DynamicAssembly");
            var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
            var module = asmBuilder.DefineDynamicModule("DynamicModule");
            var typeBuilder = module.DefineType("DynamicType");
            var method = typeBuilder.DefineMethod("DynamicMethod", 
                MethodAttributes.Public | MethodAttributes.Static, 
                typeof(int), 
                new[] { typeof(int), typeof(int) });
            method.CreateMethodBody(bytes, bytes.Length);
            var type = typeBuilder.CreateType();
            return (Func)type.GetMethod("DynamicMethod").CreateDelegate(typeof(Func));
        }
    }
    

    Note the use of the RunAndSave option. This will save the dynamic assembly to disk in a temporary location. It may be more desirable to use RunAndCollect which will generate the assembly in memory only and allow it to be collected later when all references to it are dead. However, there are some caveats to so called collectible assemblies, detailed here.

    0 讨论(0)
提交回复
热议问题