AppDomain.CreateInstanceFromAndUnwrap - Unable to cast transparent proxy

flukes1 picture flukes1 · Sep 17, 2009 · Viewed 13.9k times · Source

I'm writing a .NET library to inject managed DLLs into external processes. My current approach is:

  1. Use CreateRemoteThread to force the target process to call LoadLibrary on an unmanaged bootstrap DLL. From this point we're executing code in the target process.
  2. My bootstrap DLL then creates an instance of the CLR and calls ExecuteInDefaultAppDomain on it, which executes a method in a managed helper DLL.
  3. This method creates a new AppDomain and calls AppDomain.CreateInstanceFromAndUnwrap to pass execution into my payload DLL, casting the result as an IInjectionPayload.
  4. The idea is that my payload DLL exposes a class which implements IInjectionPayload, so the helper DLL can simply call payload.Run().

I'm doing it this way so that the payload code can be completely unloaded by simply calling AppDomain.Unload (after signalling it to clean up).

This approach works - the class in my payload DLL is getting instantiated in the target process, so code can be executed - but I can't cast the object returned by CreateInstanceFromAndUnwrap to an IInjectionPayload; it throws the following exception:

Unable to cast transparent proxy to type 'blah.Blah.IInjectionPayload'.

I've tried using CreateInstanceAndUnwrap, and Activator.CreateInstanceFrom followed by Object.Unwrap, but both of these methods also cause the same exception to be thrown.

The signature of my payload class is:

public class Program : MarshalByRefObject, IInjectionPayload

I'm stumped because the payload DLL is definitely getting loaded and the class is being instantiated, as intended. Any help would be much appreciated.

Answer

flukes1 picture flukes1 · Sep 17, 2009

Found the fix for this problem here: http://www.west-wind.com/WebLog/posts/601200.aspx

It looks like a bug in the .NET framework. The solution is to add a handler to AppDomain.CurrentDomain.AssemblyResolve which manually loads & returns the assembly at args.Name. Then you can call CreateInstanceFromAndUnwrap without it throwing an exception.