Injecting Code into Silverlight Applications

Introduction

If you haven't seen the tool yet, get a hand on it. It's a real timesaver - especially because Silverlight - though it's v3 - is still quite buggy. I wondered how it's actually possible to peek into a Silverlight app the way Silverlight spy does and this is how I guess it's working. I did not in any way reverse engineer Silverlight Spy. Everything you are going to see will be easy to understand and no deeper knowledge is necessary to do something similar. I attached the Source code to this post, so you can play around with it and perhaps create some real application that does something useful :P

Tools Used

Hosting the Injector

The first question was, how to host the injector. For Silverlight Spy, the application process hosts a browser instance using the open source .NET wrapper control csEXWEB which wraps an Internet Explorer instance and provides the plumbing to reach into events without having the hassle of interop yourself.

Since I'm doing a proof of concept here, this is more than what I need. I decided to create a Fiddler plugin that handles the injection. Fiddler offers a very comfortable way to intercept and modify httop requests and responses. In a nutshell you provide an assembly with a class implementing a specific interface. At various points of the http message request/response lifecycle your methods are called and they can modify the request/response.

Intercepting Silverlight Http Requests

Since I want to work with the original Silverlight application that was returned by the webserver, I decided to use the AutoTamperResponseBefore method if the fiddler interface. It provides access to the server response and allows for modifications to it.

To concentrate just on Silverlight applications, I look at the mimetype of the response and only do anything when it's a Silverlight app. Silverlight applications come in XAP files. A XAP file is a ZIP archive, that contains assemblies and other resources of the application. To prove this, navigate to a silverlight application using fiddler as a proxy, activate the inspector and switch to Hex View in the response panel.

To get to the contents, mark the complete file in HexView and save it to disk, then change the extension to .zip and open it with your favorite archiver. In the interceptor, we open these Zips in memory using the .NETZipLibrary. We open the zip as an input, scan through the individual files, optionally modify them and then return a new Zip that contains the changed output.

Injecting code

This is the most interesting part - it uses the Mono Project Cecil. Cecil allows you to modify .NET assemblies the way we want. Interestingly Silverlight Spy also makes use of it ;P In this example my aim was to provide debug output from a Silverlight application using Debug.WriteLine. If you want to have a good example of how to work with Cecil, check out this sample. I used most of the code because it's quite similar to what I need. However there is one major difference: Silverlight applications do not use the .NET 2.0 framework but got their own scaled down version. This is why this won't work:

The Debug class would point to the .NET 2.0 framework and not the Silverlight one - which will create a non working assembly.

To be able to get to the right type, I manually loaded the silverlight core dll and got a reference to it's debug type. Then I loop over all methods in a defined assembly like this sample above does injecting code that does a Debug.WriteLine.

After tha the modified assembly is packaged to the XAP that is returned to the browser.

Conclusion

So there is no real magic behind what Silverlight Spy does. It injects a small code packet into the Silverlight application that allows communication with the host. I guess the application uses some kind of browser mechanism here (e.g. calling Javascript functions or DOM storage) since Silverlight applications are quite limited in what they are allowed to do for security reasons. Still it's a cool tool and really inexpensive for what you can do with it.

The project attached to this post is aimed torwards the Silverlight Spy start page.

I decided only to hijack "FirstFloor.SilverlightSpy.StartPage.dll" for this example. To get it working for you, you probably have to change the path to the Silverlight system dll and the fiddler path in the post build event:

xcopy /Y "$(TargetDir)*.dll" C:\Programme\Fiddler2\Scripts\

When launching fidler with the interceptor in place and navigating to the page above, you will notice, that DebugView shows the injected messages.

To inspect the output of the injector, go to the request in fiddler and save it to disk as shown before. You will see that all methods have been called with Debug.WriteLine statements.

I hope you found this article somehow interesting. Be free to use the code provided, perhaps give me a mention if you found it useful.