C# Code Injection

Did you ever want to expand your software’s abilities without having to recompile it? How can you give your software superhero like powers without the need to redistribute a new version to the customer?
You build a framework that is capable of running other things. I’ve built many a software that will run several other pieces of software using an XML or JSON file to hold the instructions for a predetermined number of steps. I’ve even written automated testing harnesses for things that would read dynamic data from a source such as an Excel spreadsheet or small database file. All of these things were nice and were huge time savers once they were operational. I wanted something that could grow beyond the preset boundries. I wanted to build a testing framework that was truely dynamic.
Captain America Super Soldier Serium

Code Injection

What I really needed was to be able to write some code and place it in a text file so that it can be scooped up later and processed by my framework. I needed a framework that would acomplish my task for me that would not require that I recompile it every time I needed to expand its capabilities. I needed to inject the code and have it run within my framework.
Let’s get started with this little sample bit here

using Microsoft.CSharp;
using System.CodeDom.Compiler;

var csc = new CSharpCodeProvider(
    new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } });
var parameters = new CompilerParameters(new[] {
    "mscorlib.dll",
    "System.Core.dll"
  });
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;

CompilerResults results = csc.CompileAssemblyFromSource(
parameters, @"
  using System;

  namespace Dynamic
  {
    class Program {
      public static void TestMethod(string name) {
          Console.WriteLine(""Hello "" + name);
          Console.WriteLine(""This message comes to you directly from some dynamically compiled code..."");
      }
    }
  }");

results.Errors.Cast<CompilerError>()
    .ToList()
    .ForEach(error =>
        Console.WriteLine(error.ErrorText)
    );

var instance = results.CompiledAssembly
                      .CreateInstance("Dynamic.Program");
instance.GetType()
        .GetMethod("TestMethod")
        .Invoke(instance, new [] { "Eric" });
 

Let’s examine this for a moment. This code is used compile in memory by the C# .NET compiler and then methods inside can be executed by using reflection. What would this look like if I’m building a basic testing framework? Let’s take a look at what a simple test framework might look like.

var csc = new CSharpCodeProvider(
    new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } });
var parameters = new CompilerParameters(new[] {
    "mscorlib.dll",
    "System.Core.dll"
  });
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;


soapEnvelope.Dump();

CompilerResults results = csc.CompileAssemblyFromSource(
parameters, @"
  using System;

  namespace WebService
  {
    class TestFramework {
          //  THIS METHOD MOST LIKELY WILL NOT BE DYNAMIC BUT IT WILL BE BUILT INTO YOUR FRAMEWORK
	  public static string Authentication(string userName, string Password) {
	  	XNamespace soapNs = ""http://schemas.xmlsoap.org/soap/envelope/"";
		XNamespace topNs = ""YourCompany.WebService.Integration"";
		var soapEnvelope = new XElement(soapNs + ""Envelope"",
						new XAttribute(XNamespace.Xmlns + ""soapenv"", ""http://schemas.xmlsoap.org/soap/envelope/""),
						new XAttribute(XNamespace.Xmlns + ""top"", ""YourCompany.WebService.Integration""),
					new XElement(soapNs + ""Header"", null),
					new XElement(soapNs + ""Body"", 
						new XElement(topNs + ""Authenticate"", 
							new XElement(topNs + ""username"", userName),
							new XElement(topNs + ""password"", Password)
					)));
		var webResp = ExecutePost(webServiceUrl, soapAction, soapEnvelope.ToString());	
		if (webResp.StatusCode != HttpStatusCode.OK) 
			throw new Exception(""Unable To Get Ticket Information"");
		
		var sr = new StreamReader(webResp.GetResponseStream());
		var xDoc = XDocument.Parse(sr.ReadToEnd());	
		var authResult = xDoc.Descendants(topNs + ""AuthenticateResult"");	
		if (authResult != null)
			""Thank you..."".Dump();
		
		return authResult.First().Value;
	  }

      public static string BuildSoapRequest(string ticket) {
         // Build the soap request method.
         // Could be built from C# code or read in from a text file
      }	

      public static string ExecuteCall(string method, string request) {
         // MAY BE DYNAMIC BUT MORE THAN LIKELY BUILT INTO YOUR FRAMEWORK.
      }
	
      public static bool TestResponse(string soapResponse) {
          // Test the response
	  // Place your custom code here to look for 
	  // individual response information.
      }
    }
  }");

results.Errors.Cast<CompilerError>()
    .ToList()
    .ForEach(error =>
        Console.WriteLine(error.ErrorText)
    );

var instance = results.CompiledAssembly
                      .CreateInstance("WebService.TestFramework");
var ticket = instance.GetType()
                     .GetMethod("Authenticate")
                     .Invoke(instance, new [] { "Eric", "P@$$w0rd" });

var request = instance.GetType()
                      .GetMethod("BuildSoapRequest")
                      .Invoke(instance, new [] { ticket });

var response = instance.GetType()
                       .GetMethod("ExecuteCall")
                       .Invoke(instance, new [] { request });
					   
var isSuccess = instance.GetType()
                        .GetMethod("TestResponse")
                        .Invoke(instance, new [] { response });					   
  

As you can see, the authentication mechanism might not change for each call it could be changed here. Now the code to dynamically create my soap request is in the ExecuteCall method. The response custom code can be called that will test the response for errors. While this example is very rudimentary, it illustrates the concept nicely.

Authenticate

This method is used to authenticate with the web service. I’ve illustrated here the authentication method could be passed in as a string, built by the compiler and then called upon to login. I wouldn’t do this in practice because your authentication mechanism is unlikely to change between web service calls. Rather I would build this into the testing framework and just assume that it will be called prior to each of your web service calls.

BuildSoapRequest

This method will allow you to build your request that you want to send to the web service. It could be built in code that might look something like this:

private void BuildSoapRequest(string ticket) {
  var soapEnvelope = new XElement(soapNs + "Envelope",
      new XAttribute(XNamespace.Xmlns + "soapenv", "http://schemas.xmlsoap.org/soap/envelope/"),
      new XAttribute(XNamespace.Xmlns + "top", "YourCompany.WebService.Integration"),
    new XElement(soapNs + "Header", 
      new XElement(topNs + "ticket", ticket)),
    new XElement(soapNs + "Body", 
      new XElement(topNs + "GetInfo", 
        new XElement(topNs + "command", 
          new XElement(topNs + "LastUpdateFromDate", "2015-10-13"),
          new XElement(topNs + "LastUpdateToDate", "2015-11-13")
    ))));

}
  

Now the quality engineers who may not be ready to write C# code can also fashion requests that they want to test against the web service. I built my request using XElement but the quality engineers could just pass back a string to the caller.

ExecuteCall

This is where the actual execution of the post happens. This method should be a part of your testing framework but it could be injected as well. Lets take a look at the sample below on how to accomplish this.

private System.Net.HttpWebResponse ExecutePost(string webserviceUrl, string soapAction, string postData) {
    var webReq = (HttpWebRequest)WebRequest.Create(webserviceUrl);
    webReq.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;  
    webReq.ContentType = "text/xml;charset=UTF-8";	
    webReq.UserAgent = "Opera/12.02 (Android 4.1; Linux; Opera Mobi/ADR-1111101157; U; en-US) Presto/2.9.201 Version/12.02";
    webReq.Referer = "http://www.yourcompany.com";
    webReq.Headers.Add("SOAPAction", soapAction);
    webReq.Method = "POST";
		
    var encoded = Encoding.UTF8.GetBytes(postData);
    webReq.ContentLength = encoded.Length;
    var dataStream = webReq.GetRequestStream();
    dataStream.Write(encoded, 0, encoded.Length);
    dataStream.Close();
	
  return webReq.GetResponse() as System.Net.HttpWebResponse;	
}
 
TestResponse

Checking the response could be as easy as checking the response code or as complex as inspecting individual elements in the response. Here is some sample code that will get you started on the way to parsing your XML response.

var webResp = ExecutePost(webServiceUrl, soapAction, soapEnvelope.ToString());	
if (webResp.StatusCode != HttpStatusCode.OK) 
  throw new Exception("Unable To Get The Requested Information");
		
var sr = new StreamReader(webResp.GetResponseStream());
var xDoc = XDocument.Parse(sr.ReadToEnd());

//  DO CUSTOM CHECKING HERE
 

Security Concerns

I’m going to be honest with you here for a moment. This could be extremely dangerous or even disastrous for you in the wrong hands. I’m only advocating the use of this as part of a larger internal framework. More than likely on the inside of your corporate firewall. Since your framework doesn’t really do any kind of code checking this can be made to do anything! But as I was once told, with great power comes great responsibility… Until next time.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s