Windows Live Messenger Addons Internals
2008 February 12th | By Ismael | Comments (0) | Permalink
Under: programming
Introduction
In this article we analyze Windows Live Messenger 8.5, that is the last version of MSN Messenger.Windows Live Messenger does provide a plugin api (Messenger, Add-ins, and more…) but the features exposed are a very limited subset. Also, this plugin support is not enabled by default and requires the user intervention.Moreover, as of January 3rd 2008 Windows Live Messenger Add-In API this interface is no longer supported.
Hooking
As messenger lacks of a public api we need a way to inject our code in it. There several way to do this, we will be reviewing only two of them.
System wide Hook
We need a hook dll injected in every process of the system. This can be achieved using a CBTProc that creates a system wide window hook. This proc has to check if we are inside Messenger and if it is true, load our dll that contains the code that we want to inject. The advantages of this method are that we are not modifying the installation of Messenger and we are using documented functions, so this approach is likely to work on every version of Windows. On the other hand, our hook dll will be injected in every process and updating requires a reboot that may look suspicious to Anti-Virus software.
Proxy DLL
The idea is to create a proxy dll that will have the same name that other dll used by Messenger. This proxy dll will load our dll when is loaded and will forward all the calls to the original one. In order to avoid renaming or moving system dlls, we can use the trick of placing our dll in the folder where msnmsgr.exe is located so according to Dynamic-Link Library Search Order it will be loaded before the original one placed in system32 folder. The advantage of this method is that affects only Messenger and does not requires to load a dll in every process. The disvantage is that it is associated to a specific version of Messenger.This trick is used by MsgPlus and its dll name is msimg32.dll How was Plus! done?.
Inside MSN Messenger
UI Controls
Previous version of Messenger used standard windows controls to display its UI, but in the latest versions they are using custom controls. Using Spy++ we can see that there is only one window with class name “DirectUIHWND”.
We can see in the picture that this windows lacks of any child window. There was some speculation about they were using windowless controls. These type of controls implement IAccessible interface so if we can obtain such interface we can query the object to look for other interfaces implemented. Unfortunately, most of the interfaces required by the windowless controls are not implemented here. The only interesting interface exported is IOleWindow, but instances of this interface return always the same DirectUIHWND window that is useless.Using Dependency Walker we can check what dlls are used and what is used of each one. One of them is msncore.dll that exports a bunch of C++ functions like DirectUI::NativeHWNDHost::NativeHWNDHost(void). This seems to be the dll used by messenger to display its UI. Further inspection of this dll reveals that it exports DllRegisterServer function. It looks as a COM server, but luckless executing ‘regsvr32 msncore.dll’ from the command line throws an error. After verifying in its resources, we did not find any TLB, so it will require much more research to see if we can get any useful interface from this ’server’.
Resources
The only known way to customize messenger UI is modifying the resources that it uses. These resources are placed in msgsres.dll, that is located in messenger folder. There are lots of sources of information about this type of solution such as How to skin WLM 8.1.This approach can be implemented in two ways: modifing the original file or changing the resource in memory. The first method is easier but has some problems: if the file is updated our changes are lost and antivirus software may warm the user about this modified file. The other method is more complex but lacks of these problems. Resources are usually loaded using LoadResource, LoadImage, etc.; if we can make Messenger get our modified resources instead of the original ones we have reached our goal.
Messenger Plugin Demo
Hooking with Deviare
In order to make Messenger load our modified resources we need to hook the following functions calls: FindResource, LoadResource, LockResource, SizeofResource. We are going to use Deviare API to easily install our hooks.We must know that UI resources are loaded the first time Messenger is loaded. So we need Deviare to notify whenever a new program is started. After creating our SpyManager instance, we can specify that we want to be notified of process creation in this way:
_spyManager->PutReportProcessCreation(_create_process_hook_and_polling, 0)
When OnProcessStarted event is triggered we check if msnmgr.exe was started. If the new process is messenger, we initialize our ResourceManager that installs our hooks. The code that install our hooks is in FunctionHook::Init in the file FunctionHook.h. Only function’s name and function’s module are needed (these are customized using template parameters, in our demo look at DECLARE_FUNCTION_HOOKED).
Managing Resources
ResourceManager receives the events of the hooked functions and modifies the resources we want to customize. It is very simple, it keeps a state of each resource we have to modify, and when requested we return our modified copy.The following call order FindResource → LoadResource → LockResource → SizeofResource is expected for each customized resource.
Adding a Button
We need to add our button to resource 4004:923 (resource type:resource id). This is done when we insert our string.
<Button cmdid=123 id=atom(nktbtn) AccRole=57 Class="TransparentButton" Layout=flowlayout(0,2,0,2) Active=MouseandKeyboard|NoSyncFocus Padding=rect(5,4,5,4)> <element class="ToolbarIcon" ID=Atom(ai402)/> </Button>
To customize the aspect of our button we need to modify resource 4005:923.
Button[id=atom(nktbtn)]
{
accdesc:rcstr(3488);
ShortcutString:rcstr(3489);
AccName:rcstr(3490);
}
element[ID=Atom(ai402)]
{
content:rcimg(3000);
}
Customizing Resources
While customizing resources 4004:923 and 4005:923 is simple because they already exists, returning resources that do not exist is much trickier. Also, strings resources are grouped in 16 strings, check The format of string resources for more info.We customize these resources allocating memory inside Messenger using VirtualAllocEx and returning this address whenever our custom resources are requested. Our hook handler is called after the function fails trying to get invalid resource ids (that are the customized resource addresses). A more robust implementation should place the hook handler before the original function and skip calls when we detect our custom resources are requested.
Enhancements
- Resources are initialized multiple times, when only once will be enough.
Final Result
Demo source code
Requirements
- Visual Studio 2005.
- Windows Live Messenger 8.5.
Source code
Services
Nektra offers development services focused in Windows MSN Messenger add-on development




