Skip to content

MishaProductions/DotNetParser

Repository files navigation

DotNetParser

This project allows you to run .NET executables inside of C#. Discord server: http://discord.gg/SeDrYk79W8

Will this execute my .NET Project?

Yes, it will. However, only a limited subset of .NET Features are working.

What is working/implemented?

  • if/while/for statements
  • Console.Write/Writeline
  • Classes
  • Fields
  • sbyte/byte/ushort/short/int/uint/long/ulong/float/double
  • Adding/Subtracting/Multiplying/Dividing/Remainder
  • Bitwise Operations (and, or, xor, not, shift left, shift right)
  • string.Length
  • Loading separate DLLS
  • Actions
  • Basic generic support
  • Really basic reflection
  • Sub-classes
  • Arrays

Building

Set the DotNetParserRunner or TesterKernel project as the startup project in Visual Studio and click on Run.

How to use?

Basics

Setting up

First you need to create an instance of DotNetFile and pass the byte array with the contents of your C# executable. Starting from some .NET core version, the EXE file was made into a stub which just runs dotnet app.dll. You need to use that dll file for it to work.

var fl = new DotNetFile(@"c:\app.dll");

You can access all of the classes from the Types property in the fl variable.

Next, create an instance of DotNetClr. This runs the .NET code.

var clr = new DotNetClr(fl, @"c:\framework\");

C:\framework points to a folder where a basic corlib is made. You can find one under the releases.

Executing

RegisterResolveCallBack is used to load dlls such as System.Private.Corlib. You can run the Start method to begin executing the code.

clr.RegisterResolveCallBack(callback);
clr.Start();

Example of the callback:

  private static byte[] AssemblyCallback(string dll)
        {
            if(dll == "System.Private.CoreLib")
            {
                return File.ReadAllBytes("framework/System.Private.CoreLib.dll");
            }
            else
            {
                return null;
            }
        }

Marshaling

Calling methods

"CLR" side

You can register an "internal" method which can be called from your application which you want to run.

clr.RegisterCustomInternalMethod("TestsComplete", TestsComplete);
private static void TestsComplete(MethodArgStack[] Stack, ref MethodArgStack returnValue, DotNetMethod method)
{
    Console.WriteLine("All Tests Completed.");
}

Inside of the function, the Stack variable represents all of the parameters. returnValue represents the return value of the internal method. Ignore it if the return type is void.

Application side

To invoke this newly created method, add this code:

TestsComplete();

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

Passing objects from the CLR to the application

"CLR" side

 clr.RegisterCustomInternalMethod("TestsRxObject", TestRxObject);

Now the method:

private static void TestRxObject(MethodArgStack[] Stack, ref MethodArgStack returnValue, DotNetMethod method)
{
  var cctor = m.GetMethod("DotNetparserTester", "TestObject", ".ctor");
  if (cctor == null)
      throw new NullReferenceException();
  var s = new CustomList<MethodArgStack>();
  s.Add(MethodArgStack.String("value"));
  returnValue = clr.CreateObject(cctor, s);
}

First we get the constructor method (normally named .ctor). Then we build the list of parameters and call clr.CreateObject();

Application side

  public class TestObject
    {
        public string TestProperty;

        public TestObject(string prop)
        {
            TestProperty = prop;
        }
    }
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern TestObject TestsRxObject();
var m = TestsRxObject();