ARTeam Tutorial

Visit: http://cracking.accessroot.com | http://forum.accessroot.com

Solving a problem of Eudora on receiving mail with .ems attachments with viruses.


Information A little tutorial which shows how to solve some problems of the applications through ASM..
Target Qualcomm Eudora 6.2
Available http://www.eudora.com
Tools OllyDbg 1.10, ToPo 1.2 Fixed, Heavenstools Resource Tuner
Protection --
level Beginner
Category Fixing
Author(s) Shub-Nigurrath Nov 2004
Requirements Windows XP, IE 5.5 and above for best viewing


1. Introduction

Hi all today's target is Eudora 6.2. The purpose of this tutorial is not to crack the program indeed but to fix a little bug it has. It's not a common bug and doesn't happens to most of the people, but when happens it's gonna happens each time and quite frequently. So I thought a solution and then wrote this tutorial, a simple coockie-tutorial.

Even if you don't use Eudora or you never have had this particular bug I think the tutorial will be interesting because we'll discuss some general issues, so don't close it just now ^__^

During this tutorial I'll explain which is the bug, how it happens and how to solve with the instruments we have. The final result will be a patch of the program which will solve this erroneous behaviour.

There are three sections in the remaining of this tutorial:
1. Description of the bug
2. Studying the problem
3. Finding the right place and coding the solution
4. Conclusions
 



2. Description of the bug


The first step is to look to how the bug we have works.
Each time I check mail with Eudora I receive several mails with viruses, which contains all the types of trojans and strange attachments. Fortunately I have an antivirus installed (McAfee), but particularly one of these attachments's type gives problems to Eudora (and only this one, you'll understand why just few lines below): all the emails with an .ems attachment with viruses inside make Eudora to open a dialog with this message:

The problem arises because McAfee deletes the attachment before Eudora can handle the mail message thus making the program confused for an apparently missing file. Effectively McAfee acts correctly because .ems files are handled by the email clients as parts of the messages thus opening ports for infections (malicious html code or scripts); this is also the reason why this bug happens only for .ems attachments.

Anyway this bug is a little annoying because Eudora interrupts the automatic emails retrieving process to wait me for pressing the Ok button..and this might happens several times..grrr!

The solution would be to tell to Eudora developers about the problem, but I didn't have pay for this program ;-) or to solve on my own..obviously I chosen the second one!



3. Studying the problem

The solution consists of two parts:
1. finding the place where the dialog is created and shown
2. try to skip the visualization of the dialog and continue the email retrieving process.

The idea is to find the place where the dialog is shown, see how I can skip the visualization of the dialog and continue the mail checking process.

First of all let's open OllyDbg and attach it to the Eudora process (which is alrady stopped with the dialogbox shown).

Olly complains about the multithreading features of Eudora, well don't care and answer yes to its questions. Now the call stack of Eudora looks like the one below

Well, the program stopped at 0012D768 and the stack is quite clear: the application enters into the systems dlls calling the MFC42.#2514. if you like you can look at the code, but I directl ytell you that the interesting point where to look at is the one pointed by the arrow above, at 00434239.

Then you land into this place:

0043421A |. /75 04 JNZ SHORT Eudora.00434220    ; this jmp if taken skips the error message
0043421C |. |3918 CMP DWORD PTR DS:[EAX],EBX
0043421E |. |74 0D JE SHORT Eudora.0043422D     ; this jmp if not taken skip the error message
00434220 |> \8D8D F4FBFFFF LEA ECX,DWORD PTR SS:[EBP-40C]
00434226 |. 51 PUSH ECX
00434227 |. 50 PUSH EAX
00434228 |. FF50 0C CALL DWORD PTR DS:[EAX+C]
0043422B |. EB 11 JMP SHORT Eudora.0043423E     ; jmps away
0043422D |> 8D85 F4FBFFFF LEA EAX,DWORD PTR SS:[EBP-40C] ; copy a value pointed by [EBP-40C] into EAX
00434233 |. 50 PUSH EAX                         ; interesting push, which is the value of eax?
00434234 |. 68 0F010000 PUSH 10F                ; interesting push, 10f..remember this value!
00434239 |. E8 460C0100 CALL Eudora.00444E84    ; this call leads the error DialogBox
0043423E |> 59 POP ECX


Le'ts concentrate to the CALL Eudora.00444E84, it leads you directly to the error message, thus could be interesting to have a look at the pushed parameters right before the call. Moreover there are some interesting conditional jumps before which exactly skip this call and his pushes.

So we can consider this call as something like following.

ShowErrorDialog(char* message, 10F);

now try to retrieve the actual parameters passed to this call. Olly's stack view already has all we need.

First of all configure the Olly's stack view as following

now you are ready to analyze Eudora's application stack. You should know that the returning addresses of the subprocedures in ASm are placed into the stack, so you can rebuild the calling tree simply reading the stack. If you scroll a little down the stack's window you should see something like

0012D80C |00444EBC RETURN to Eudora.00444EBC from <JMP.&MFC42.#2514>

Double click on it and you land at 0043423E, which is the instruction right after the call around which we are working!
Interesting, so the following subroutine in the stack's windows is our subroutine. One word before: Olly clearly tells you, when possible, which is the stack of a particular call (local context), so you can easily move to the stack of the call inside which Eudora was when it executed the instruction at 00434234.

The most interesting thing there is:

0012D8DC |0043423E RETURN to Eudora.0043423E from Eudora.00444E84
0012D8E0 |0000010F
0012D8E4 |0012D8F0 ASCII "Could not open the file :\Eudora\Attach\warning.ems for reading. Cause: No such file or directory exists. (2)"
0012D8E8 |00000002
0012D8EC |00000000

Bingo, we have the final confirm that the EAX contained the error message!

 

But what is 10F about? Well, the first idea is to check if it's a dialog resource...follow this idea.

What we now have to understand is: "who uses this dialog?". We have two different possibilities and solutions:

  1. it's a dialog only for the .ems problem: we can skip it totally (NOPping it or modifying the jmps above)
  2. it's a generic dialog used for all the errors: in this case the solution becomes more complex...

Well, fire up a resource editor to find which is the dialog box which has been used by Eudora to show the dialog. I used Resource Tuner, but anyother is good too (e.g. Resource Hacker which is free).

Resource Tuner reports that Eudora doesn't have any dialog inside, so the dialog resources must be on another file, a Dll loaded by Eudora. Among the Dlls which have been loaded (in Olly use ALT-E ot see the executable module list) we see one named Eudora32.dll .. sounds interesting, let's see if there's something useful inside.

Resource Tuner reports this: dialog resource ID 271 which is equal to 10F..Bingo, this is what we saw in Olly.

Then try to reasum what we did till now: I found the correct dialog which is shown by Eudora, but the problem is that it's used to show any error message, thus will not be enough to skip the dialog, otherwise we wouldn't get any error at all. What we need indeed is a more clever skipping method which will skip the dialog only when the error message is about an .ems missing file..

What we would code in the next section can be described, using a pseudo-code, as following:

if (message_to_be_shown contains ".ems") then
   skip dialog();
else
   show dialog();
process_next_message();

more precisely the idea I had is to give to the ShowErrorDialog() we identified before, a non existent resourceID when the error message is about .ems files, otherwise give the correct resourceID (10F).

The reasoning behind this conclusion is simple: the involved MFC APIs (you can browse the stack to see which are) simply do not do anything at all if the given resource isn't found in the application.

So we can write the final patch we want to do as following.

if (message_to_be_shown contains ".ems") then
   ShowErrorDialog(message, 7D0);                     //skips the dialog giving a non existend resourceID (7D0)
else
   ShowErrorDialog(message, 10F);                     //show the dialog() normally
continue Eudora execution from address 0043423E       //processes next message

or better:

ShowErrorDialog(message, MyNewCall(message));
continue Eudora execution from address 0043423E

int MyNewCall(char *message) {
  if (message contains ".ems") then
     return 7D0;
  else
     return 10F; 
}

This last one will be the one we'll implement!
 



4. Finding the right place and coding the solution

The steps of this part of the tutorial are:
  1. Do a call because all the required things don't fit in place.
  2. Find a free space in the .code section of Eudora big enough to fit the new call
  3. Write the call paying attention to keep stack and registries' consistency (the call must not modify registry and stack), patch the place where the call should be called.

1. Do a call because all the required things don't fit in place.

We don't have space enough to do what we decided: we have to substitute the PUSH 10F with a proper call to my new subrotine (what I called in the other section MyNewCall).


0043422D |> 8D85 F4FBFFFF LEA EAX,DWORD PTR SS:[EBP-40C]
00434233 |. 50 PUSH EAX
00434234 |. 68 0F010000 PUSH 10F                ; interesting push, 10f..remember this value!
00434239 |. E8 460C0100 CALL Eudora.00444E84
0043423E |> 59 POP ECX

First of all he problem is to find a place into the .code section of Eudora which enough free space (unused bytes) to fit our needs.

Note: compilers usually do not pack tight the soubroutines one beside the other. Usually they insert a lot of padding unused bytes among subroutines (00 or 90), these bytes are used to allign the code and to make the linker process easier. These bytes are what we are going to use.

2. Find a free space in the .code section of Eudora big enough to fit the new call

First of all we have to use a proper tool which will find the required space for us. I used ToPo 1.2 from MrCrimson, the version fixed by Ricardo Narvajo, which works on XP systems also (included with this tutorial).

Fire up ToPo and meanwhile Close Eudora Process, which is now nomore useful. ToPo requires Olly to close the process before opening. Follow the steps below, being the first picture how the program opens.

  1. open Eudora.exe using Open Button

  2. Select "Use an existing section

  3. unselect "backup file" and insert a "Bytes to be added" of 100 in the "Exec only" section

  4. press Do It!


We now have and address where to code our call.

Note: the address returned by ToPo is each time different, thus from now on there will a little discrepance with the above picture. When I wrote the code ToPo returned to me as a result the address 005FEDF8 so the following code is consistent with this value.

3. Write the call ...

We now have and address where to code our call. Fire up again Olly and restart Eudora from beginning.

0043422D |> 8D85 F4FBFFFF LEA EAX,DWORD PTR SS:[EBP-40C]
00434233 |. 50 PUSH EAX
00434234 |. E8 BFAB1C00 CALL Eudora.005FEDF8 ; our new call to MyNewCall()
00434239 |. E8 460C0100 CALL Eudora.00444E84
0043423E |> 59 POP ECX

Our new call is instead the following one.

005FEDF8 /$ 55 PUSH EBP                                    ; save the stack pointer
005FEDF9 |. 51 PUSH ECX                                    ; save ecx on the stack
005FEDFA |. 52 PUSH EDX                                    ; save edx on the stack
005FEDFB |. 50 PUSH EAX                                    ; save eax on the stack
005FEDFC |. 33C9 XOR ECX,ECX                               ; zeroes ecx
005FEDFE |. 33D2 XOR EDX,EDX                               ; zeroes edx
005FEE00 |. 8B45 38 MOV EAX,DWORD PTR SS:[EBP+38]          ; get the pointer to the filename from stack
005FEE03 |> 83C2 01 /ADD EDX,1                             ; string lenght loop (till is 0)
005FEE06 |. 36:8D0C10 |LEA ECX,DWORD PTR SS:[EAX+EDX] 
005FEE0A |. 81FA 00010000 |CMP EDX,100                    ; check if edx>=256 avoid infinite loops (not pointing to a string?)

005FEE10 |. 7D 35 |JGE SHORT Eudora.005FEE47
005FEE12 |. 8039 00 |CMP BYTE PTR DS:[ECX],0               ; string terminator
005FEE15 |.^ 75 EC \JNZ SHORT Eudora.005FEE03
005FEE17 |. 90 NOP
005FEE18 |. 36:8D4C10 FD LEA ECX,DWORD PTR SS:[EAX+EDX-3] ; edx is the strlen, eax is the first char, -3 is the extension lenght, ECX will contains the first char of "ems"

005FEE1D |. 8039 65 CMP BYTE PTR DS:[ECX],65                ; compare with 'e'
005FEE20 |. 75 25 JNZ SHORT Eudora.005FEE47                 ; jmp out, it's not an ".ems" error, so show it
005FEE22 |. 90 NOP
005FEE23 |. 90 NOP
005FEE24 |. 83C1 01 ADD ECX,1                               ; move to the next char
005FEE27 |. 8039 6D CMP BYTE PTR DS:[ECX],6D                ; compare with 'm'
005FEE2A |. 75 1B JNZ SHORT Eudora.005FEE47                 ; jmp out, it's not an ".ems" error, so show it
005FEE2C |. 90 NOP
005FEE2D |. 90 NOP
005FEE2E |. 83C1 01 ADD ECX,1
005FEE31 |. 8039 73 CMP BYTE PTR DS:[ECX],73                ; compare with 's'
005FEE34 |. 75 11 JNZ SHORT Eudora.005FEE47                 ; jmp out, it's not an ".ems" error, so show it
005FEE36 |. 90 NOP
005FEE37 |. 90 NOP
005FEE38 |. 58 POP EAX                                      ; replace original register values
005FEE39 |. 5A POP EDX                                      ; replace original register values
005FEE3A |. 59 POP ECX
005FEE3B |. 5D POP EBP
005FEE3C |. 5B POP EBX                                      ; EBX contains return value, so is important
005FEE3D |. 68 D0070000 PUSH 7D0                            ; push a fake dialogID used to not show the messagebox
005FEE42 |. 53 PUSH EBX                                    ; I must swap the return value and the dialogID, so as to return to caller with a stack how Eudora expect to be

005FEE43 |. 33DB XOR EBX,EBX                                ; zeroes EBX
005FEE45 |. C3 RETN
005FEE46 | 90 NOP
005FEE47 |> 58 POP EAX
005FEE48 |. 5A POP EDX
005FEE49 |. 59 POP ECX
005FEE4A |. 5D POP EBP
005FEE4B |. 5B POP EBX
005FEE4C |. 68 0F010000 PUSH 10F                            ; real dialogID to show the messagebox
005FEE51 |. 53 PUSH EBX
005FEE52 |. 33DB XOR EBX,EBX
005FEE54 \. C3 RETN

Here also how it looks into Olly..

Some comments about what I did.

  1. I choose to push and then pop each registry on the stack one by one, you can also use PUSHAD and POPAD which does the same for all the registry in just one step.

  2. At 005FEE00 I used the value pointed by [EBP+38], which I found with Olly to be the filename path of the missing file; the value at [EBP+40C] is instead the message shown by the messagebox.

Now you can write all the modifications made to Eudora, save and then execute with Olly to see how the program works, remember to place a BP at 00434234 before.

The stack of Eudora right after executing our routine is like the following

EBP-41C > 000007D0
E
BP-418 > 0012D8F0 ASCII "Could not open the file :\Eudora\Attach\=GB2312Q=D3=CA=B2=A1=B6=BE=B.ems for reading Cause: No such file or directory exists. (2)"

Go to section 3 of this tutorial and read again what Eudora had before on the stack at this exact point, a value of 10F and the error message, now there's instead our 7D0..Good we finished!

 


5. Conclusions

Lesson Learnt

Still awake?!? As usual we try to summarize what we learnt during this tutorial..hope at least one of the points were new for you :)

1. play a little with program's resources and windows' APIs
2. Coding a subroutine in assembler
3. Finding the free space where to insert your code into an application



 
6. Greetingz

[MAIN TEAM]
| Nilrem | Enforcer | Ferrari | Pompeyfan(ex-member) | MaDMAn_H3rCuL3s | EJ12N | Kruger |
Shub-Nigurrath | Jdog45 | R@adier | Teerayoot | ThunderPwr | Eggi | Bone Enterprise

*****************************

Exetools | Woodmann | VCT | TSRh | Sir JMI | SatyricOn | LaBBa | FEUERRADER | Britedream | MarKuS-DJM | Hacnho | cl0ud (Mephisto) | Zest | Hobgoblin | Peroquin | Nullz | Everyone I missed & you


(.|.)
 ).( (¯`·._.·[¯¨´*·~-.¸¸,.-~*´¨&8~) Ŝħůβ¬Ňïĝµŕřāŧħ ¨´*·~-.¸¸,.-~*´¨]·._.·´¯)
( v )
 \|/