Can you hack this out?
I recently had to take a really deep look into how to cheat the CLR, that brought about some interesting discoveries, including the fact that it is, surprisingly, possible to do so.
Let us say that you have this code in some 3rd party assembly that you cannot modify:
internal interface IRunner
{
void Execute();
}
public sealed class AssemblyRunner : IRunner
{
void IRunner.Execute()
{
Console.WriteLine("executing");
}
}
public class CompositeRunner<T> where T : new()
{
public void Execute()
{
if(!typeof(IRunner).IsAssignableFrom(typeof(T)))
throw new InvalidOperationException("invalid type");
var runner = (IRunner)new T();
Console.WriteLine("starting");
runner.Execute();
Console.WriteLine("done");
}
}
Can you get the CompositeRunner to output:
- starting
- before executing
- executing
- after executing
- done
The real problem was a bit harder, but this is a good start.
Comments
Hi,
I think that
if(typeof(IRunner).IsAssignableFrom(typeof(T)))
should be
if( ! typeof(IRunner).IsAssignableFrom(typeof(T)))
Using Aspect Oriented Programming?
For instance you can write Aspects that get injected into this assembly during PostCompilation, although this is not CLR hacking.
Eti,
Yes, it should, fixed, thanks :-)
Pierre,
You can't modify the original assembly in any way.
I have no idea on how you did it. You, Sir, are a machine!
Is this something that could be used for mocking unmockable classes? (Sealed, non-virtual, etc)
Hi again,
Well i'm sure you are thinking about something else but this code outputs the expected values:
class Test : IRunner {
CompositeRunner <test c = new CompositeRunner <test();
c.Execute();
You probably are asking about CompositeRunner <assemblyrunner.
Use reflection to find the interface that AssemblyRunner implements, and implement it yourself in your own emitted class?
public class MyRunner : IRunner
{
private readonly AssemblyRunner _inner = new AssemblyRunner();
public void Execute()
{
}
}
new CompositeRunner <myrunner().Execute();
How about that?
<myrunner();
Sorry, did not notice IRunner is internal.
You could probably 'TypeMock' it, and use Profiler API to hook the method...?
Ralf wont your call to inner.Execute() be in accessible as its private?
Well this could be done quite easily with dynamic dispatch in .net 4.0. Something tells me we cant use that however. :-)
Eti,
IRunner is an internal interface in another assembly, you cannot inherit from it.
Configurator,
Try it :-)
I can tell you it... isn't easy
Van & Ralf,
IRunner is an internal interface in another assembly, your code won't compile
Igal,
Show me working code to make this work.
The profiling API are... possible, but they are a bigger cheat than I would consider.
David,
Try solving this using 4.0, it would be interesting to see where it trips you
Ignore the rules specified. Use Mono.Cecil. Rewrite the assembly.
OK, time for a hint. Did you find a way to implement an internal interface using reflection.emit? To derive from a sealed class? Make the CLR think your type implemented an interface while it did not ... quite? Something else altogether?
Ah, yes, I see the problem.
Type 'Implementation' from assembly 'NewAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is attempting to implement an inaccessible interface.
The solution is to use the Remoting RealProxy class and "implement" the interface with some magic.
blogs.msdn.com/.../...linq-to-sql-datacontext.aspx
... just when I was going to say: if the solution involves in-proc remoting, then I don't want to know it ;-) bah!
The problem with using C# 4's dynamic is that you can't cast it to the interface (I think)
Chris,
You can't, assume this is a framework assembly
Stefan,
I will give you a hint, remoting...
Hristo,
That is a good first step, but it won't solve this particular problem.
I am not asking you to replace a live instance, I am asking you to change the way it works when I create a new instance.
Is transparent proxy near the mark? :-)
Dave,
Yes & no.
Try to get a working sample, you'll see what I mean.
I haven't tried solving this puzzle yet, but it seems more complicated than I thought.
Closed generic type complicates things significantly...
Krzysztof,
That is more or less the point :-)
Ayende, Are you looking for a hack or do you really have one, because
the code you posted does not compile:
public sealed class AssemblyRunner : IRunner
{
}
Compile Error 1 The modifier 'private' is not valid for this item
The core of the problem is the line:
if(!typeof(IRunner).IsAssignableFrom(typeof(T)))
the call to IsAssignableFrom
Looking into Type.IsAssignableFrom code, it maybe a path to implement a TypeBuilder ...
liviu,
I have a hack, and thanks for catching that issue, fixed that.
And a type builder wouldn't quite work here.
So I was thinking something similar to this approach.
stackoverflow.com/.../is-there-a-way-to-call-a-...
Dave,
You can't modify the assembly, and try it with proxies, see where it gets you
Is something related to ContextBoundObject?
Alk.
Why not:
public class MyCompositeRunner <t : CompositeRunner <t
{
public new void Execute()
{
// bla bla
}
}
?
Alkampfer,
That is related, in some way, yes
Pixel,
That won't work, when you pass CompositeRunner to something that will call its Execute method, your method won't get called.
public class WrapperRunner <t : IRunner where T : IRunner, new()
{
}
var composite = new CompositeRunner <wrapperrunner<assemblyrunner>();
its a bit weird but should work
composite.Execute();
Marc,
IRunner is internal, you can't inherit it.
You should escape the brackets. It prevents us from posting code with generics and it could allow cross-site scripting.
The solution must use ContextBoundObjects, message sinks, and transparent proxies. Although, it's been a while since I've dug into those internals, I think you just need to find a way to get the CompositeRunner participating in the sink chain?
I can't picture the code, but it doesn't feel impossible. I don't have time to experiment right now, but it's a nice puzzle. Looking forward to your solution.
Actually I have no time to try a solution, but the right direction can be trying to load the sealed object in another AppDomain, since communication between AppDomains always happens with a proxy. When you create object in another Appdomain all communication happens with a remoting proxy.
The only problem is that the creation of the sealed object happens inside the CompositeRunner, that directly called
var runner = (IRunner)new T();
You probably found a way to make this code creates T object in another appDomain?
Alk.
I should not call the execute method directly, but have to wrap it in a proxy, or put the method in a delegate and pass the delegate into a execute method, in the execute method to add your decoration before and after running the delegate
It seems like there should be a way of doing this by deriving from Type. I'm just not sure offhand how to implement it in such a way that it would do that. Reflecting on IsAssignableFrom doesn't really seem to help as much as I'd hoped it would (or I'm too dense to see the right way to work it based on that).
No, I can't hack this out. Enlighten us, Ayende.
Something around latent typing? Can't recall I f I'll need to reference the internal interface, though.
Maybe getting down to pointer/memory level?
If all else fails, remoting, as Ayende said. I remember seeing some ORM using that technique.
Al,
Try it :-)
Alkampfer,
No second app domain is required.
And yes, there is a trick here.
Fred,
Show me the code
Kyle,
You are in the right direction, now take it to the illogical conclusion.
Paulo,
Latent typing? I can't see a solution to that here, but maybe you can educate me.
I thought about doing pointers here, but it is not needed.
Remoting would work,but _how_?
Al,
You are close, but not quite.
I saw an article the other day about hooking into the JIT and hijacking the jump table. But I cannot find the reference again :(
http://netasm.codeplex.com/
Atleast similar
I remember your tweets about AppDomain.AssemblyResolve and hacking LINQ2SQL IProvider.
The best was "how to override System.RuntimeType at runtime using Reflection.Emit "
I guess this is it :-)
Hmm. I'm guessing that now, you know also the way to mock static methoda with Rhino Mocks :-)
If you do not use another appDomain, probably a possibility is to inherit from Type, override the ISAssignableFrom(Type) method and return true, this fools the Runner and makes the following test pass
if(!typeof(IRunner).IsAssignableFrom(typeof(T)))
then maybe it is possible with reflection.emit, to create a new class, and use your custom Type as type, so when the runner call typeof(T) it gets your MyType that return true when it ask for IsAssignableFrom, and it gets fooled.
But actually you still have another problem, because the IRunner is internal interface, and even with reflection Emit you cannot create a class that implements it, so you can make this class inherits from ContextBoundObject and use the standard IMessage AOP technique to intercept calls and redirect to a real AsseemblyRunner object, and now you can inject code before and after the call :)
I wish to have some time to check this path and verify where it leads :)
Alk.
I haven't done any remoting or COM, so I'm just fooling around.
I'm trying to use proxy of Type class and using it as generic argument to CompositeRunner, but I can't just cast transparent proxy to Type;)
@Whut Transparent proxy is an object not a type. If you want its type, use GetType(), but I do not see what it gives you.
So, you're not gonna tell us?
No clue how :)
But, can this somehow be used to provide a undo/redo facility that is transparent to the objects? Somehow catching the get/set of a property and also enhancing any property in a object with Undo() and Redo() methods?
Found 2 links about something like this. Sorry for polluting your comments section :)
stackoverflow.com/.../how-do-i-intercept-a-meth...
www.developerfusion.com/.../3/
msdn.microsoft.com/en-us/magazine/cc164165.aspx
Again, sorry for pollution, but I can't edit the comment previous.
Care to post the solution?
I think, the story comes from here ..
gyrate.wordpress.com/.../context-bound-object-p...
I spent this morning 30 minutes thinking to a solution, it is really a thought question :).
Ayende, it is somewhat related to creating a dynamic class with reflection.Emit and changing manually the TypeToken, setting with reflection the m_tdType field of the TypeBuilder? when the compositeRunner checks if T implements IRunner uses typeof(T) that in MSIL generates a call to GetTypeFromHandle using the TypeToken of T...
Alk
Using remoting, message sinks and some reflection hacks I'm able to run those lines:
var runner = (IRunner)new T();
runner.Execute();
Still I can't crack this
if(!typeof(IRunner).IsAssignableFrom(typeof(T)))
But I will find it;)
@ayende
will you unveil the answer???
@olcay şeker
Apparently we didn't ask kindly enough.
Please Don't give the answer, maybe some hints so we can try to figure it out. (I might be the only fool asking for this though)
I think the solution can be found by using resharper on L2S Profiler :--))
I agree with Anthony, can we have some more hints, at work we are having fun in our lunch break on this one ;)
@ Whut, how does you code look right now?
I think to get round the IsAssignableFrom, you have to Inherit off the Type Class, override this function to return true and then use the System.Reflection.Emit to force the code to use your Type class. thing is I have yet to figure out how to do that
@ Ayende, the class type you pass into the CompositeRunner does not inherit of IRunner? its just a class that has an execute function, and you make it always return true on the IsAssignableFrom?
@liviu
"resharper on L2S Profiler :--))"
Did that, understand how he solved the task at hand, still cannot solve this one.
David:
if you do override IsAssignableFrom you still have to get past the cast on the next line.
Ayende:
Do you need to some how push the IRunner interface that you get using reflection into the RuntimeTypeCache for the new object or am I heading in the wrong direction?
Anthony Dewhirst:
I think the cast can be handled with explicit operator.
I still cannot figure out how to trick the typeof(T) to return the Type that I wanted.
Ayende:
You said "The real problem was a bit harder" And by far no one has manage to solve the "easier one"
Can you please enlighten us with at list some hints. Also I am very curious about the real challenge you had.
I said resharper, i ment reflector...
I think the challange is related either to EF or to L2S profiling...
Change the System.Console.WriteLine() function in mscorlib, and do with it what you want.
www.blackhat.com/.../...agedCodeRootkits-PAPER.pdf
Arielr,
That is pretty much cheating.
Maybe something like this:
var irunner = typeof(AssemblyRunner).GetInterface("IRunner");
....
TypeBuilder myType = myModule.DefineType("MyRunner",
MethodBuilder exMethod =
ILGenerator ilgen = exMethod.GetILGenerator();
ilgen.EmitWriteLine("before executing");
// call to AssemblyRunner.Execute
ilgen.EmitWriteLine("after executing");
Type finished = myType.CreateType();
Type[] typeArgs = {finished};
Type constructed = typeof(CompositeRunner<>).MakeGenericType(typeArgs);
MethodInfo mi = constructed.GetMethod("Execute");
mi.Invoke(Activator.CreateInstance(constructed, null, null), null);
It's allready passing through
typeof(IRunner).IsAssignableFrom(typeof(T))
but failing on
var runner = (IRunner)new T();
Oren,
Yeah, I know.
Fun, ain't it? :)
Hmmm.... If this is possible, then I'm hoping that there are some pretty ground breaking improvements to Rhino Mocks in the near future :)
Comment preview