Question Customize output in hosted CLR (.NET)

kosmosec

Member
Joined
Sep 16, 2021
Messages
18
Programming Experience
5-10
Hi, I'm hosting CLR in Golang program (but it doesn't matter where). Is the way to configure CLR to capture output from .NET assembly executed in my in-process CLR runtime straight into a file? I run .NET assembly in hosted CLR and I want to capture this output straight to the file (or some buffer).
 
Cool, but I assume I will have to make changes in the source code which I want to run from hosted CLR. Am I right? I would like to treat this .net source code as black-box and I would like to modify the behavior of CLR, because it is the only thing I can do from Golang (that's my assumption - I would like to treat .net source code as black-box).
 
No you don't have to modify the other managed code. You just need to have a stub where you do the output change.
 
Ok, so I should create a wrapper that creates app domain and a second app domain in the callback. The wrapper .NET program has an args which will be bytes of the target .NET assembly which I want to run. From Golang, I load CLR, run wrapper program with args - bytes of the target .NET. Looks good?
 
Ok, I don't know how to do it without a wrapper program. I've created something like this and looks like it works. Do you have something to add or doubt? Srr for shity C# coding from my side :D

wrapper:
public static void Main(string[] args)
        {
            Byte[] targetdotnet = StringToByteArray(args[0]);
            string fileName = args[1];
            List<string> listParameters = new List<string>();
            for (int i = 2; i < args.Length; i++)
            {
                listParameters.Add(args[i]);
            }
            string[] parameters = listParameters.ToArray();
            
            FileStream streamer;
            StreamWriter writer;
            TextWriter oldOut = Console.Out;
            TextWriter oldErr = Console.Error;
            try
            {
                streamer = new FileStream(fileName, FileMode.OpenOrCreate | FileMode.Append, FileAccess.Write);
                writer = new StreamWriter(streamer);
            }
            catch (Exception e)
            {
                return;
            }
            Console.SetOut(writer);
            Console.SetError(writer);
        
            try
            {
                Assembly assembly = Assembly.Load(targetdotnet);
                MethodInfo method = assembly.EntryPoint;
                object[] pp = new[] { parameters };
                object execute = method.Invoke(null, pp);
            } catch(Exception e)
            {
                return;
            } finally
            {
                writer.Close();
                streamer.Close();
                Console.SetOut(oldOut);
                Console.SetError(oldErr);
            }
          
            
            return;
        }
 
A couple things.

In general, it's bad to just eat exceptions without providing somekind of feedback unless you absolutely know that the exception can be ignored.

Next, it looks like StringToByteArray() is misnamed. By the name, I would expect it just to convert the Unicode args[0] string into a byte array, but based on your code, it looks like it actually reads the filename contained in the string and returns the bytes of the file. I would recommend skipping this entire process, and just use Assembly.LoadFile() and pass in the args[0].

Next, lines 5-10 looks like it can be collapsed to about 2 lines by simply allocating the right sized array, and then using Array.CopyTo().
 
Thanks Skydiver. Yes, I know about exceptions I will have to print what went wrong.

In case of StringToByteArray() - the first argument is hex string of .exe's bytes. I just need it because I load this wrapper from Golang and the golang program has bytes array of target .net assembly. So probably the name of method should has 'hex' somewhere :)

Just for curiosity. Is it the way that you wanted to solve my problem?
 
Back
Top Bottom