Multiple MSN

Monday, March 13 2006 @ 09:28 AM CET

Contributed by: Devoney

Level : newbie

Victim: MSN Messenger
Goal: Patching it so we can run multiple sessions at once instead of just one.
Tools: A Debugger (I use Ollydbg)
Author: Devoney

When you already have a MSN running you can not launch another MSN at the same time of the same version. When creating your own program you have to build in some security if you want people to be able to run only one session at the same time. So MSN has a moment where it checks if there is a previous version running. We need to find out where that is!

Get to work:
Ok, open msnmsgr.exe with your favorite debugger. Normally its localized in this dir: C:Program FilesMSN Messenger. Now set a breakpoint on every reference on th CreateEvent API. Maybe you will notice that its CreateEventA in MSN. The A only stand for 32-bit. Now run the program tru the debugger (in ollydbg press F9 or the play button). The debugger probarly breaks a couple of times, not much. In my case it breaks 3 times. Now we are not interested in all those CreateEventA moments. We are only interested in this piece of code:

005575E3 |> 68 4C4A4100 PUSH msnmsgr.00414A4C ; /EventName = "MSNMSGR"
005575E8 |. 53 PUSH EBX ; |InitiallySignaled
005575E9 |. 6A 01 PUSH 1 ; |ManualReset = TRUE
005575EB |. 53 PUSH EBX ; |pSecurity
005575EC |. FF15 58134000 CALL DWORD PTR DS:[; CreateEventA

The addresses might differ from yours but the way the security is coded is the same in every MSN so far. Take a look at the EventName (the first parameter pushed). Its MSNMSGR.

Now read this:
"Return Values
A handle to the event object indicates success. If the named event object existed before the function call, the function returns a handle to the existing object and GetLastError returns ERROR_ALREADY_EXISTS. NULL indicates failure. To get extended error information, call GetLastError."

Now scroll a couple of lines down in the code of the debugger and notice this piece:
00557600 |. FF15 74144000 CALL DWORD PTR DS:[; [GetLastError
00557606 |. 3D B7000000 CMP EAX,0B7
0055760B |. 0F85 B5010000 JNZ msnmsgr.005577C6

So GetLastError api checks the value which was returned from CreateEventA. It compares it with 0B7. 0B7 probarly is the hex value for constant which says SUCCES or somekind. When there is no SUCCES (so there is already a version running) the API CreateEvent does not return SUCCES. And EAX wont be 0B7. So this jump isn't made when there is already a version running. So we have to be sure the jump is made no mather what! SO change the JNZ (which is a conditional jump) to a unconditional jump JMP. (still to the same address ofcourse). Now save the modifcations. In Ollydbg you do that by right mouse click in the screen -> Copy to executable -> All Modifications -> Copy All -> Right mouse button in the new screen -> Save file. (this is not exactly the same for older versions of ollydbg.)

Now start the app as many times if you like and you see that it does not terminated itself anymore when there is another session running.

We could also speed up the code little. This jump can be made earlier because CreateEvent is not neccesary because the result of the checkup isn't important anymore. So go back to the CreateEventA api. Replace the first Parameter pushed "PUSH 414A4C" by "JMP " (in my case the address is "005577C6").

Hopefully you have understood what I was trying to explain and that you have learned out of this! How did I know it was all about this CreateEvent? I started to set a breakpoint on ExitProcess and worked my way back to see where it came from when there was already a version of msn running. Then I compared the code when there was no MSN running so that I knew I was not too far already. Finally after 2 hours I ended up with CreateEvent.