Code injection in Silverlight
In my free time, I develop Snoop . This is a great help for WPF developers, which has no good free counterparts in the world of Silverlight. Snoop embeds its build in the WPF process and puts it in order. I was curious: is it possible to embed an arbitrary assembly into the running silverlight process from outside the browser?
As far as I know, all existing programs that embed code in silverlight do this by intercepting and modifying the .xap file before loading the application. This is a good way, but it has several disadvantages:
1. You cannot connect to an already running application without reloading the page
2. Intercepting the .xap file often limits the plug-in runtime of Internet Explorer. For a universal interceptor, you need to use / write an http sniffer.
I want to offer a way that allows you to connect to an already running application and infiltrate it without reloading the page, without modifying the .xap file and without restrictions on the browser. Before we get started, let me introduce today's open-source guest:
slinject
This console program is the fruit of programming curiosity. It allows you to select a running Silverlight process and embed the Silverlight assembly in it (click for a larger resolution):

Binaries can be downloaded here , and C # source code is available on github . Before you begin to deploy, the program must be installed by running the command:
slinject --installThis is a one-time operation that requires administrator rights. After installing the injector can be implemented under any user.
Wait, don’t leave! Or how it works
As often happens, the idea is very simple. Connect the debugger to the Silverlight process and execute the Assembly.Load () command. It could always be done from the Visual Studio debugger, but can it be done from your program?
Silverlight is installed with a number of interesting libraries and tools, which, unfortunately, have either disgusting documentation or none. One of these libraries is dbgshim.dll . It is through this door that debuggers go into the world of Silverlight. Visual Studio uses it, so why don't we take advantage of the loophole? True, why not? A lack of good documentation is not a good argument. But a good challenge for the curious - you can.
So, after several nights wandering around the
Problem
It was necessary to find a method in Silverlight that would be guaranteed to be called in any Silverlight process in order to put a breakpoint in it. In the case of WPF / WinForms, applications are simple. We take the processor of the Windows message queue and set a breakpoint in it. But in Silverlight, there is no Windows message queue. Fortunately, it has a close counterpart: the JoltHelper.FireEvent () method. This method is called even in an empty Silverlight application, just move the mouse.
Remember, I said that the console debugger was able to do expression evaluation ... sometimes? In fact, in order to execute code during a breakpoint, the debugging infrastructure requires a number of conditions . If the method is optimized, there can be no question of any funceval. JoltHelper.FireEvent () is, of course, optimized:

Decision
It turns out that Silverlight jitter, like his big brother from the .NET world, listens to .ini recommendations for optimizing the generated code. It is enough to create the following .INI file next to the assembly: Save it as "Assembly_name_without_dll.ini", and the next time during JIT compilation the generated code will be more friendly to the debugger. The biggest catch is the encoding of the .ini file. If it differs from UTF-16 Little Endian, the file will be simply ignored. To improve performance, Silverlight, during installation, generates images in machine codes for standard assemblies. Essentially the same ngen
[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0, only the utility is called coregen, and the result of the generation is placed in the Silverlight folder. Coregen also takes into account the existence of .ini recommendations, and can generate debugging machine code.
When you say:
slinject --installThe program creates a System.Windows.ini file with the necessary recommendations to jitter. removes the old precompiled System.Windows.ni.dll image, and asks coregen to create a debugged image. And of course, to undo all these changes, it’s enough to do
slinject --uninstall
Finally
So, we got a universal assembly implementer in Silverlight? Unfortunately no. Even killing a stream looks more harmless than interrupting it in a random place asking to execute random code. Mike Stall on his blog talks about why FuncEval is evil , but useful evil. In the end, that’s how Watches / Locals / Immediate windows work in Visual Studio. Armed with this knowledge, using slinject, be prepared for Silverlight process crashes, browser crashes, and politician tricks.
Moreover, I am not an expert in COM'e / ICorDebug'e. Surely I made a bunch of mistakes in the code , but it's open source - I will be glad if you show / correct errors.
I hope you enjoyed this walk into the world of the Silverlight debugger - I will be glad to hear reviews :).