Shoutbox

How was Plus! done? - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: WLM Plus! General (/forumdisplay.php?fid=23)
+----- Thread: How was Plus! done? (/showthread.php?tid=71839)

How was Plus! done? by muttantegg on 02-17-2007 at 12:41 AM

Hi! I just installed Plus! and was curious about how it worked.

I don't know much about windows programming... I was wondering if someone could explain to me how is it that Plus! attaches itself to Messenger when I run it. I looked at the original Messenger files and they didnt look changed after I installed Plus. :huh:

Thanks for your time.

(Oh, and if you answer this one Im sure more will follow... :$ Hope you don't mind me being curious)


RE: How was Plus! done? by ShawnZ on 02-17-2007 at 12:47 AM

it creates a "proxy" to the real msimg32.dll by placing a fake one in messenger's directory. along with, naturally, providing msimg32's functions, it also sneaks in a little load for msgpluslive.dll without messenger knowing any better.


RE: How was Plus! done? by muttantegg on 02-17-2007 at 11:28 AM

That explains it! ^^ And the detoured.dll too I suppose :)

Well, I guess I have one more question :D

How did Patchou ( ? ) figure out where he needed to attach Plus! and which calls to detour to make Messenger do all those shiny things like coloured nicks and voice clips? I look at it and it's a black box :S I have no idea what it's inner workings are.

Is there a manual for Messenger Live on the net for people doing mods? I don't think Microsoft would make it's source code available :P

Thank you for your answers, it's not often someone gives good replies to newbies...


RE: How was Plus! done? by Baggins on 02-17-2007 at 12:26 PM

If you google 'messenger API' you might find some interesting information.

Some things that Plus! does can be done with this, but the rest need to be done using hooks.

Plus! hooks the windows and menus of Messenger to add the script menu and color thing.


RE: How was Plus! done? by muttantegg on 02-17-2007 at 02:50 PM

Right! I think I'm starting to understand :)

I'll do some research and find out how to add cool buttons and menus to a program window before I nag you with more questions :D

A big 'Thank you' to ShawnZ and Baggins!


RE: How was Plus! done? by hmaster on 02-17-2007 at 03:03 PM

How To Hook Msn Messenger In Visual Basic -> http://forum.mess.be/index.php?showtopic=52
VB6 intro to the Messenger API -> http://forum.mess.be/index.php?showtopic=55
C# Examples -> http://forum.mess.be/index.php?showtopic=36

Most of them haven't been updated but they can give you a good start.


RE: How was Plus! done? by vikke on 02-17-2007 at 03:52 PM

He's using API Hooking, using the Detours library. For example, it could change the IAT table to fake Messenger call CreateWindow, while it calls Patchous CreateWindow instead. There are sereval other methods, check CodeProject.com for samples. I recommend HookImportedFunction API.
He's also made his own RichEdit interface for the color codes etc.
It's also done by normal Windows Message hooks.

Oh, yeah, he added the button by intercepting LoadResource, FindResourceW, SizeofResource. Then he fakes Messenger to load another/modifed copy of the window resources with a button added.

Hope this helps :).


RE: How was Plus! done? by matty on 02-17-2007 at 03:56 PM

quote:
Originally posted by vikke
Oh, yeah, he added the button by intercepting LoadResource, FindResourceW, SizeofResource. Then he fakes Messenger to load another/modifed copy of the window resources with a button added.
If you mean the Toolbar buttons he patches the UFile in memory to add his own buttons.
RE: RE: How was Plus! done? by vikke on 02-17-2007 at 04:00 PM

quote:
Originally posted by Matty
quote:
Originally posted by vikke
Oh, yeah, he added the button by intercepting LoadResource, FindResourceW, SizeofResource. Then he fakes Messenger to load another/modifed copy of the window resources with a button added.
If you mean the Toolbar buttons he patches the UFile in memory to add his own buttons.

How do you define "patches"?
I'm like 80% sure he's intercepting LoadResource APIs. However thats a working way. My theory would be: Patchou patches the LoadResource APIs to pass the modified XML UIFILE which handles the windows, and from there he could write to memory, but he still needs to hook SizeofResource, so Messenger would allocate the right spaces, so we wont have a crash.

-vikke
RE: How was Plus! done? by muttantegg on 02-17-2007 at 04:24 PM

So if I understood this correctly :

Plus!, using a proxy msimg32.dll and the detoured.dll library attaches itself to Messenger. It then intercepts Messenger's API calls by changing the code in memory (not the file in the hard drive) to include some extra code. This way new menus and buttons are added (during CreateWindow or LoadResource), with code attached to them and present in MsgPlusLive.dll

Next it adds functionality to the SendMessage and ReceiveMessage events by hooking this functions (and by doing so, allowing Plus! to parse commands like /ping).

It's a little simple but I think it's what's going on. Did I forget something?


RE: How was Plus! done? by vikke on 02-17-2007 at 04:27 PM

No that's probably all for the core..


RE: How was Plus! done? by Patchou on 02-18-2007 at 08:06 AM

Actually, msimg32.dll is the only thing that loads Messenger Plus! into Messenger. Detours is used after, to hook a couple of API functions (using Detours gives better results than patching the IAT like older versions of Messenger Plus! used to do, but you can achieve similar results with both methods). You could also use a CBT hook, check the documentation of SetWindowsHookEx, it's probably easier to start with that.

Then it's all a matter of intercepting the creation of each window and sending the proiper messages to send their behaviours, add stuff to the various menus, etc... changing the Messenger UI involves hooking some of the resource APIs like LoadResource yes.

Good luck :)


RE: RE: How was Plus! done? by vikke on 02-18-2007 at 03:34 PM

quote:
Originally posted by Patchou
Actually, msimg32.dll is the only thing that loads Messenger Plus! into Messenger. Detours is used after, to hook a couple of API functions (using Detours gives better results than patching the IAT like older versions of Messenger Plus! used to do, but you can achieve similar results with both methods). You could also use a CBT hook, check the documentation of SetWindowsHookEx, it's probably easier to start with that.

Then it's all a matter of intercepting the creation of each window and sending the proiper messages to send their behaviours, add stuff to the various menus, etc... changing the Messenger UI involves hooking some of the resource APIs like LoadResource yes.

Good luck :)

That was what I tried to say. And CreateWindow was just an example. CBT hook is better for window creations, but even best is a RET Hook, with the WM_CREATE interception, because thats after the window is created :P (when the Message is handled by Messenger.
RE: How was Plus! done? by muttantegg on 02-18-2007 at 04:22 PM

Hehe. Hooking windows sounds fun :grin: Can't wait to add my own menus to Messenger!

That will have to wait though. All the examples I've seen so far are a bit outdated and/or won't compile in VS 2005. When I get some free time I'll play around with it a bit :)

A big 'Thank you' to all who replied and especially to Patchou for making Plus!


RE: How was Plus! done? by vikke on 02-18-2007 at 04:40 PM

Sure! If you need any help, PM me, I've done this.


RE: How was Plus! done? by muttantegg on 02-19-2007 at 12:49 PM

Hi guys! It's me again :)

quote:
Originally posted by Patchou
Actually, msimg32.dll is the only thing that loads Messenger Plus! into Messenger.

Okay. I've been reading the MSDN pages refering to Dlls (and DllMain) and came across this :

quote:
The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order.

So, if you shouldn't load libraries in msimg32.dll's DllMain, where do you do it? You have to load MsgPlusLive.dll somewhere...  Is this one of those times when you do it, even though is dangerous?
RE: How was Plus! done? by vikke on 02-19-2007 at 04:37 PM

I did, Patchou too I guess. Not a problem.

Or write it using MFC; I think you can put it in InitInstace (the MFC DllMain) without any problemos :).


RE: How was Plus! done? by Patchou on 02-19-2007 at 07:45 PM

Although the rule must be generally respected, this depends on each particuliar scenario and situation. If you create a dll file to be loaded in a particular process and it works, then it will simply always work. Jsut make sure you do the strict minimum in DllMain (don't start calling functions from other dlls except to put in place basic hooking, delay your initialisation for later).


RE: How was Plus! done? by TheSteve on 02-20-2007 at 02:32 AM

Here is a pretty good list of what you should and shouldn't do when you are creating DllMain. See the document for more details.

quote:
Originally posted by http://www.microsoft.com/whdc/driver/kernel/dll_bestprac.mspx

You should never perform the following tasks from within DllMain:
  • Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash.
  • Synchronize with other threads. This can cause a deadlock.
  • Acquire a synchronization object that is owned by code that is waiting to acquire the loader lock. This can cause a deadlock.
  • Initialize COM threads by using CoInitializeEx. Under certain conditions, this function can call LoadLibraryEx.
  • Call the registry functions. These functions are implemented in Advapi32.dll. If Advapi32.dll is not initialized before your DLL, the DLL can access uninitialized memory and cause the process to crash.
  • Call CreateProces. Creating a process can load another DLL.
  • Call ExitThread. Exiting a thread during DLL detach can cause the loader lock to be acquired again, causing a deadlock or a crash.
  • Call CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky.
  • Create a named pipe or other named object (Windows 2000 only). In Windows 2000, named objects are provided by the Terminal Services DLL. If this DLL is not initialized, calls to the DLL can cause the process to crash.
  • Use the memory management function from the dynamic C Run-Time (CRT). If the CRT DLL is not initialized, calls to these functions can cause the process to crash.
  • Call functions in User32.dll or Gdi32.dll. Some functions load another DLL, which may not be initialized.
  • Use managed code.

The following tasks are safe to perform within DllMain:
  • Initialize static data structures and members at compile time.
  • Create and initialize synchronization objects.
  • Allocate memory and initialize dynamic data structures (avoiding the functions listed above.)
  • Set up thread local storage (TLS).
  • Open, read from, and write to files.
  • Call functions in Kernel32.dll (except the functions that are listed above).
  • Set global pointers to NULL, putting off the initialization of dynamic members. In Microsoft Windows Vista™, you can use the one-time initialization functions to ensure that a block of code is executed only once in a multithreaded environment.


RE: How was Plus! done? by muttantegg on 02-20-2007 at 04:35 AM

Hey guys! I got my fake Dll working :)

And thanks to

code:
#pragma warning( disable:4273 )
it even compiles nicely!

Now comes the fun part... Anyone knows the signature of Initialize in MsgPlusLive.dll ?
RE: How was Plus! done? by Patchou on 02-20-2007 at 06:26 AM

lol.. and why would you want to know something like that hum? :p


RE: RE: How was Plus! done? by vikke on 02-20-2007 at 07:41 AM

quote:
Originally posted by Patchou
lol.. and why would you want to know something like that hum? :p

Load Plus! or maybe replace Plus! ;) ?

Edit: I tried load using no params (void), and that seemed to work fine. The DLL is loaded, and confirmed by GetModuleHandle API. But I loaded it into my own program, not Messenger.
Here's my stupid VB6 code: :@
code:
Private Declare Function Initialize Lib "MsgPlusLive" ()
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" _
  (ByVal lpModuleName As String) As Long
 
Private Sub Form_Load()
    Initialize
    MsgBox "Plus Loaded?"
    If GetModuleHandle("MsgPlusLive.dll") > 0 Then
        MsgBox "Plus is loaded!"
    End If
End Sub

I wrote it in VB6 because I'm using Visual Studio 2005 for C++, which takes like an half hour to start :|
RE: How was Plus! done? by muttantegg on 02-20-2007 at 10:15 AM

quote:
Originally posted by Patchou
lol.. and why would you want to know something like that hum? :p

Wel... It's part of my evil plan to dominate the world through hipnotizing rays coming out of Msn Messenger. (6)

LOL, no really... I figure if I can load it I'll get Plus! :D (Well... again :)) Because right now I load the Dll's but Plus!'s stuff doesnt appear :(

I suppose I could load Plus!'s msimg32.dll and that would get it to work. *-)
RE: How was Plus! done? by vikke on 02-20-2007 at 10:18 AM

Did you try LoadLibrary API? That would probably not work either :(. But it's worth a try :).

I don't think Patchou will give you the signature :).


RE: How was Plus! done? by muttantegg on 02-20-2007 at 10:26 AM

I got it! I got it!

Thanks vikke! I owe you a million! Now I can rest :)

Wow... this had really been nagging me. Back to real life now :(


quote:
Originally posted by vikke
Did you try LoadLibrary API? That would probably not work either :(. But it's worth a try :).

I don't think Patchou will give you the signature :).

What's so special about the signature?:huh: (guess I could always look at the assembly, take a few classes in reverse engineering lol)

Aaaanyway... Plus loads, menus, icons, everything :) I did as you suggested and tried calling Initialize() :

code:
// Initialize Plus (hopefully)
typedef VOID (* PLUS_Type)(VOID);
PLUS_Type Initialize_fn = (PLUS_Type) GetProcAddress( _PlusDll, "Initialize");
Initialize_fn();


Maybe I got it right by accident, who knows :P Oh, and sorry about the messy code, I'm still new to all this strange typedef's (and already started to hate LPCWSTR's)
RE: RE: How was Plus! done? by vikke on 02-20-2007 at 01:54 PM

quote:
Originally posted by muttantegg
quote:
Originally posted by vikke
Did you try LoadLibrary API? That would probably not work either :(. But it's worth a try :).

I don't think Patchou will give you the signature :).

What's so special about the signature?:huh: (guess I could always look at the assembly, take a few classes in reverse engineering lol)

You asked for it ? :)
quote:
Originally posted by muttantegg
code:
// Initialize Plus (hopefully)
typedef VOID (* PLUS_Type)(VOID);
PLUS_Type Initialize_fn = (PLUS_Type) GetProcAddress( _PlusDll, "Initialize");
Initialize_fn();


Good job, function pointers are not that hard :P, it's only about learning the technique! ;)
RE: How was Plus! done? by muttantegg on 02-20-2007 at 11:47 PM

:( All went well, until I tried hooking the resources.

If I "DetourAttach" FindResource, LoadResource or SizeOfResource Plus! stops working. I still get the menu bar, but the only item on Plus!'s menu is "Software not loaded..."

I can't hook things that Plus! also hooks? :^)


RE: How was Plus! done? by vikke on 02-21-2007 at 09:50 AM

Yes, you can. But you'll need to buy Detours, as that's one of their premium features :(.

Use another method, like IAT, EAT, Code Overwrite, Extended Code Overwrite, there are some librarys floating around the net :)

Edit: I've heard you'll need to pass some handle somewhere to get Plus! to apply it's changes. ^o)


RE: How was Plus! done? by muttantegg on 02-21-2007 at 05:26 PM

Please excuse the sarcastic tone of this post. It's meant to be joyful and amusing (maybe even comic).

quote:
Originally posted by vikke
Yes, you can. But you'll need to buy Detours, as that's one of their premium features :(.


Yes, THAT is going to happen. In which pocket did I put those $10.000 I had set aside to purchase a license from Microsoft?

quote:
Originally posted by vikke

Use another method, like IAT, EAT, Code Overwrite, Extended Code Overwrite, there are some librarys floating around the net :)


Erm... Nice! Apparently ECO is what Detours uses in the first place.

Well, for my part I'm satisfied. I believe further questions would not belong in this thread. "How was Plus! made" has been described and I am happy.

DllInjection and API Hooking for those interested. :)
RE: How was Plus! done? by Patchou on 02-22-2007 at 05:43 AM

Just to make sure you don't corrupt the memory with invalid signatures:

int WINAPI Initialize(void)

:p


RE: How was Plus! done? by shlomifr on 08-10-2009 at 12:00 PM

Hi all,

I've heard that "Plus!" is using some proxy system dll to get it's code started in the msnmsgr process (detour). Isn't that a very version dependant method? Why not using a hook or CreateRemoteThread to get the code injected into the process?

I'm trying to write a Messenger plugin myself and would like to know what was the logic behind that decision.

Thanks,
Shlomi Fruchter


RE: How was Plus! done? by ShawnZ on 08-10-2009 at 03:06 PM

quote:
Originally posted by shlomifr
Why not using a hook or CreateRemoteThread to get the code injected into the process?

because with that method you need another thread to call CreateRemoteThread from :p e.g., another process running in the background constantly that must start before messenger starts, etc.

however, it may be fairly reliable if such a binary started itself before messenger using the same trick Process Explorer uses to start itself before taskmgr... (that is, setting itself as taskmgr's Debugger in Image File Execution Options... although i don't know the details of how this works or if it would even work at all)
RE: How was Plus! done? by shlomifr on 08-10-2009 at 03:58 PM

So how does "Plus!" make sure it is supported for all Messenger's versions? Microsoft probably change the dlls they use from time to time.

Another problem is that some other Messenger plugin might replace the same dll and override the proxy used by my plugin.

Anyone has an idea for how to solve this? :)

Thanks,
Shlomi.


RE: How was Plus! done? by ShawnZ on 08-10-2009 at 04:05 PM

quote:
Originally posted by shlomifr
So how does "Plus!" make sure it is supported for all Messenger's versions?

it checks the version number of messenger before doing anything else :p
quote:
Originally posted by shlomifr
nother problem is that some other Messenger plugin might replace the same dll and override the proxy used by my plugin.

well that's the disadvantage to this method :p
RE: How was Plus! done? by shlomifr on 08-11-2009 at 09:51 AM

Ok thanks ShawnZ, I managed to get into the Messenger process using a proxy dll.

One more question though, I noticed that "Plus!" is manipulating the in-memory resources of the Messenger to get UI elements into the application. Is there any tutorial about that? It seems that the recent version of WLM is not compatibe with most of the articles I found on the net.

Thanks a lot again :)
Shlomi.


RE: How was Plus! done? by Patchou on 08-11-2009 at 09:01 PM

UI files in the latest version of Messenger are all encoded. There is no tutorial to decode them but you can use MPTools.exe distributed with Plus! to decode them, easily and for free.

Changing the resources in memory can be done in several ways, I suggest you read in the MSDN Library about that :).


RE: How was Plus! done? by shlomifr on 08-12-2009 at 06:11 AM

Well, I kinda know how to do that by hooking the resource loading api calls, the encoding part is the question for me.

Can you give me a hint? :)

Thanks,
Shlomi


RE: How was Plus! done? by Patchou on 08-14-2009 at 05:59 PM

as I said, MPTools.exe already does all of that for you. If you want to do it yourself, you'll ahve to do like I did: spend two weeks in a room, looking at your computer screen, with an hex editor and notepad to write some notes of what you find ;).

To start, you should know that the uib files have a proper header and a couple of separated sections referenced from the header. Teh first sections define data used by the last one to reconstitute the decoded text file.