Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 05-12-2006, 07:27
Fade
 
Posts: n/a
Modifying programs to use more than one copy at a time.

Some programs like for example MSN only allow you to run one instance of itself at a time. I wanted to try and crack MSN for practice to see if I could run more than one instance of it.

I assumed it would create a mutex and when I load MSN into Olly and search for all intermodular calls I see that there are several calls to CreateMutexA, I thought maybe by NOP'ing out the correct one it wouldn't create the mutex and then I could run as many instances as I like. Firstly I don't know which is the correct mutex, or what the other mutex's are for. Also if I NOP them all msn doesn't run, I thought that it would cause some problem but I wanted to try it anyway

So I was looking at some source and I saw that when you create a mutex you call GetLastError() and look to see what it returns so you know if it is currently running or not. But when I looked through the intermodular calls I couldn't see any references to GetLastError :P
I thought if I could find it maybe I could look at where it checks the return and compares it and maybe edit the je/jz to jne/jnz but as I said I couldn't find the GetLastError so I couldn't find where it checks the return :P

I am not asking for somebody to give me the answer, because I want to learn for myself, but I am stuck and have no idea what to do so if anybody can give me some hints that would be great

-------------------------------------------------
Okay I was just about to post this and decided to compile my own code with GetLastError() it seems that the intermodular call for it is RtlGetLastWin32Error the reason I couldn't see it is because I was looking for the wrong thing. After looking now I see that a lot in Olly.

Well from here I am stuck again. Out of all the CreateMutex's there is one which is right above a GetLastError so I think that may be the one I have tried a few things but have had no luck.

If anybody can help that would be great.
Reply With Quote
  #2  
Old 05-12-2006, 16:36
MarkusO
 
Posts: n/a
No help at this point, but only Win9x used GetLastError from KERNEL32.DLL. On Windows NT/2K/XP/... GetLastError ist only a redirection to RtlGetLastWin32Error in NTDLL.DLL. (to keep compatibility with Win9x programs)

Programs might also use "FindWindow" in different versions to check if they are already running.
Reply With Quote
  #3  
Old 05-12-2006, 22:35
Fade
 
Posts: n/a
Thanks MarkusO, I set breakpoints on the mutex's and would run the program to see where the code would stop. The program would just run through though and if MSN was not open it would open it and if it was open it would display the MSN which was already open.
I checked intermodular calls for FindWindow and found some, so I put some breakpoints and run the program, but the code stopped at the breakpoints without either opening MSN or displaying the current MSN. So I knew the code was either there or somewhere before it. I checked the MSDN for FindWindow(), I found out that if the function fails it returns NULL. So I thought I'd look for a JZ or JNZ under the FindWindow, I couldn't see one I could only see a JE.

I tried several things like NOP'ing the JE, changing the JE to JNE but none of this worked. Up above the FindWindow (well actually it is FindWindowA) there was a CreateEventA and then a GetLastError. I checked the MSDN for CreateEventA and it said:

Quote:
If the function succeeds, the return value is a handle to the event object. 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.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.
Under the CreateEventA there is a JE which I assume checks the return to see if the event was created successfully. Then underneath that the GetLastError has a JNZ to make sure it did not return NULL (0). If it did return NULL then it knows it is already open, and continues down the code to the FindWindow so it can find the MSN which is already open.

So what I did was change the JE under CreateEventA to a JMP which goes straight to the code which it would execute if no other MSN is open. Jumping over the GetLastError and FindWindow etc.

Here is the original code

Code:
005580C9  |> 68 FC494100    PUSH MSN.004149FC                      ; /EventName = "MSNMSGR"
005580CE  |. 53             PUSH EBX                                 ; |InitiallySignaled
005580CF  |. 6A 01          PUSH 1                                   ; |ManualReset = TRUE
005580D1  |. 53             PUSH EBX                                 ; |pSecurity
005580D2  |. FF15 58134000  CALL DWORD PTR DS:[<&KERNEL32.CreateEven>; \CreateEventA
005580D8  |. 3BC3           CMP EAX,EBX
005580DA  |. 8B7D F0        MOV EDI,DWORD PTR SS:[EBP-10]
005580DD  |. 8947 28        MOV DWORD PTR DS:[EDI+28],EAX
005580E0     0F84 CD010000  JE MSN.005582B3
005580E6  |. FF15 74144000  CALL DWORD PTR DS:[<&KERNEL32.GetLastErr>; [GetLastError
005580EC  |. 3D B7000000    CMP EAX,0B7
005580F1     0F85 B5010000  JNZ MSN.005582AC
005580F7  |. 6A FF          PUSH -1                                  ; /Timeout = INFINITE
005580F9  |. FF77 28        PUSH DWORD PTR DS:[EDI+28]               ; |hObject
005580FC  |. FF15 54144000  CALL DWORD PTR DS:[<&KERNEL32.WaitForSin>; \WaitForSingleObject
00558102  |. 83F8 FF        CMP EAX,-1
00558105  |. 0F84 A8010000  JE MSN.005582B3
0055810B  |. 53             PUSH EBX                                 ; /Title
0055810C  |. 68 A8474100    PUSH MSN.004147A8                      ; |Class = "MSNMSGRBlObj"
00558111  |. FF15 40164000  CALL DWORD PTR DS:[<&USER32.FindWindowA>>; \FindWindowA
Here is the code after I changed the JE to a JMP.

Code:
005580C9   > 68 FC494100    PUSH MSN.004149FC                   ; /EventName = "MSNMSGR"
005580CE   . 53             PUSH EBX                                 ; |InitiallySignaled
005580CF   . 6A 01          PUSH 1                                   ; |ManualReset = TRUE
005580D1   . 53             PUSH EBX                                 ; |pSecurity
005580D2   . FF15 58134000  CALL DWORD PTR DS:[<&KERNEL32.CreateEven>; \CreateEventA
005580D8   . 3BC3           CMP EAX,EBX
005580DA   . 8B7D F0        MOV EDI,DWORD PTR SS:[EBP-10]
005580DD   . 8947 28        MOV DWORD PTR DS:[EDI+28],EAX
005580E0   . E9 C7010000    JMP MSN.005582AC
005580E5     90             NOP
005580E6   . FF15 74144000  CALL DWORD PTR DS:[<&KERNEL32.GetLastErr>; [GetLastError
005580EC   . 3D B7000000    CMP EAX,0B7
005580F1   . 0F85 B5010000  JNZ MSN.005582AC
005580F7   . 6A FF          PUSH -1                                  ; /Timeout = INFINITE
005580F9   . FF77 28        PUSH DWORD PTR DS:[EDI+28]               ; |hObject
005580FC   . FF15 54144000  CALL DWORD PTR DS:[<&KERNEL32.WaitForSin>; \WaitForSingleObject
00558102   . 83F8 FF        CMP EAX,-1
00558105   . 0F84 A8010000  JE MSN.005582B3
0055810B   . 53             PUSH EBX                                 ; /Title
0055810C   . 68 A8474100    PUSH MSN.004147A8                   ; |Class = "MSNMSGRBlObj"
00558111   . FF15 40164000  CALL DWORD PTR DS:[<&USER32.FindWindowA>>; \FindWindowA
Reply With Quote
  #4  
Old 05-12-2006, 22:56
Knight
 
Posts: n/a
Here's tutorial about the same subject:
_http://www.reversing.be/article.php?story=20060313092818514

Regards,
Knight
Reply With Quote
  #5  
Old 05-13-2006, 03:26
TmC TmC is offline
VIP
 
Join Date: Aug 2004
Posts: 328
Rept. Given: 1
Rept. Rcvd 15 Times in 9 Posts
Thanks Given: 2
Thanks Rcvd at 22 Times in 16 Posts
TmC Reputation: 15
msn does not use mutex to check if already running. it checks in the process list if a msnmsgr.exe is running and if not it runs itself.

Try to create another msnmsgr.exe with another name (ex. msnmsgr2.exe) and it runs like a baby as many times as you want, provided that you rename it each time to another name.
Reply With Quote
  #6  
Old 05-13-2006, 08:18
Harding
 
Posts: n/a
Sometimes it not always the process search you want to look for. Think further, if it finds the MSN is already running, what will it do?... call ExitProcess() maybe? Just stop on ExitProcess() and check where it was called from. That would give you something to work with.
Reply With Quote
  #7  
Old 05-13-2006, 09:35
Fade
 
Posts: n/a
Quote:
Originally Posted by Knight
Here's tutorial about the same subject:
_http://www.reversing.be/article.php?story=20060313092818514

Regards,
Knight
It is practically the same as the way I did it except he says to put an unconditional JMP at the first PUSH but I just replace the JE. I didn't copy that tutorial honestly guys, because for me this was just about the knowledge and learning.

Quote:
Originally Posted by TmC
msn does not use mutex to check if already running. it checks in the process list if a msnmsgr.exe is running and if not it runs itself.

Try to create another msnmsgr.exe with another name (ex. msnmsgr2.exe) and it runs like a baby as many times as you want, provided that you rename it each time to another name.
I think this goes to show that sometimes we do things too complicated and the way we think is too complicated. If we look for simpler techniques we may find easier ways of doing things. But I didn't waste my time anyway because I learnt some stuff.

Quote:
Originally Posted by Harding
Sometimes it not always the process search you want to look for. Think further, if it finds the MSN is already running, what will it do?... call ExitProcess() maybe? Just stop on ExitProcess() and check where it was called from. That would give you something to work with.
Working your way backwards through the code is a good method. though I think it would not have been a high priority of mine, more than likely a last resort. But I guess for each problem comes a different method, and alsong as you solve the problem the method you use doesn't matter. Aslong as it works for you

I think from the perspective of a reverser I have seen some different ways that people will try and stop 2 instances of an application from running, the first 2 were Mutex's and FindWindow, but the 2 other methods were CreateEvent and by checking the name of running processes.

From a software developers perspective I think maybe adding something simple like an extra check of the same method. It wouldn't be too difficult to bypass I don't think, but it may cause a little confusion. Like having the FindWindow code which someone might try to NOP or JMP past. But then after that have another FindWindow code, so it checks first and if it doesn't find the window it checks again incase the first check was altered. So really they would have to NOP both FindWindow's. I don't think this would be very difficult like I said but it may cause a little confusion. It is always interesting to look at things from the view of the reverser and then look at it from the view of a software developer.

Anyway thank you for your reply guys.
Reply With Quote
  #8  
Old 05-13-2006, 14:12
TQN TQN is offline
VIP
 
Join Date: Apr 2003
Location: Vietnam
Posts: 343
Rept. Given: 142
Rept. Rcvd 20 Times in 12 Posts
Thanks Given: 169
Thanks Rcvd at 130 Times in 43 Posts
TQN Reputation: 20
As I see in the ASM code, I think we only need to patch at 005580F1, from JNZ MSN.005582AC to JMP MSN.005582AC.
The C pesudo-code can be:
Code:
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, "MSNMSGR");
if (NULL == hEvent)
    goto Error; // At addr 005582B3
else
{ 
    if (ERROR_ALREADY_EXISTS /* = 0xB7 */ != GetLastError())
        goto StartNewInstance; // At addr 005582AC
    else
    {
        // Wait until the first instance of MSN exited
        if (WAIT_FAILED /* = -1 */ == WaitForSingleObject(hEvent, INFINITE /* = -1 */))
            goto Error; // addr 005582B3
        FindWindow("MSNMSGRBlObj", NULL);
        // ..............
        // ..............
    }
}
Regards,
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Highly self modifying code chants General Discussion 1 09-21-2016 17:46
Modifying Assembly Attributes (.NET) The Old Pirate General Discussion 7 05-11-2015 00:15
Modifying resources of self-checking exe c4p0ne General Discussion 8 09-17-2004 21:32


All times are GMT +8. The time now is 00:22.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( 1998 - 2024 )