     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. 
 
 
3Virus3Date 3Code size3MEMORY_   3Infectable 3File  3Head3Stea-3Warm  3Memory3Tunne-3 
3     3     3,bytes   3SIZE, para3file size  3growth3size3lth  3reboot3slices3ling  3 
~A' 
3 #1  303/923   938   3   129    3>200,<=F4003 ~94F 3  3 3  -  3  -   3  0   3  -   3 
3 #2  304/923   8F6   3   120    3>200,<=EC003 ~91E 3  3 3  -  3  -   3  0   3  +   3 
3 #3  306/923   996   3   140    3>200,<=F4003 <A5E 3  3 3  -  3  -   3  0   3  +   3 
3 #4  307/923   A3D   3   155    3>200,<=F4003 <B05 3  3 3  -  3  -   3  0   3  +   3 
3 #5  308/923   FE5   3   20A    3>200,<=EC003 10AD 3  3 3  +  3  +   3  8   3  +   3 
3 #6  311/923  120F   3   252    3>200,<=E0003 130F 3 63h3  +  3  +   3  8   3  +   3 
3 #7  302/933  17B0   3   308    3>200,<=E0003 18C8 3 63h3  +  3  +   3  9   3  +   3 
3 #8  303/933  1876   3   321    3>200,<=D8003 <1C783 63h3  -  3  +   3 10   3  +   3 
3 #9  312/933  132A   3   27F    3>200,<=D8003 <172C3 63h3  -  3  -   3  7   3  +   3 
3#10  305/943  1812   3   35F    3>200,<=D0003 <22403 63h3  -  3  -   3 14   3  -   3 
 
 
 
 
Fig.2. Virus copyright messages for versions #1-#8. 
 
 
3 The BEATLEMANIA is alive!                                           3 
3 THE BEATLES, for ever, the best.                                    3 
3 John, Paul, George and Ringo, ladies and gentlemen, here they are!  3 
3 PLEASE, PLEASE ME. WITH THE BEATLES. A HARD DAY'S NIGHT.            3 
3 BEATLES FOR SALE. HELP. RUBBER SOUL. REVOLVER.                      3 
3 SGT.PEEPERS LONELY HEARTS CLUB BAND. THE BEATLES. YELLOW SUBMARINE. 3 
3 ABBEY ROAD. LET IT BE. MAGICAL MISTERY TOUR.                        3 
3 Other LP and singles available...                                   3 
3                                                                     3 
3 Virus 'Uruguay-#1'                                                  3 
3 Programmed in Montevideo (URUGUAY) by F3161. 03/92.                 3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#1 ' 
3                                                                     3 
3 I love ROXETTE !!!                                                  3 
3                                                                     3 
3 Virus 'Uruguay-#2'                                                  3 
3 Programmed in Montevideo (URUGUAY) by F3161. 04/92.                 3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#2 ' 
3                                                                     3 
3 'Uruguay-#3' Virus                                                  3 
3 Programmed in Montevideo (URUGUAY) by F3161. 06/92.                 3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#3 ' 
3                                                                     3 
3 'Uruguay-#4' Virus                                                  3 
3 Programmed in Montevideo (URUGUAY) by F3161. 07/92.                 3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#4 ' 
3                                                                     3 
3 'Uruguay-#5' Virus                                                  3 
3 Programmed in Montevideo (URUGUAY) by F3161. 08/92.                 3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#5 ' 
3                                                                     3 
3 'Uruguay-#6' Virus                                                  3 
3 Programmed in Montevideo (URUGUAY) by F3161. 11/92.                 3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#6 ' 
3                                                                     3 
3 Uruguay-#7 Virus                                                    3 
3 Programmed in Montevideo (URUGUAY). 02/93.                          3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#7 ' 
3                                                                     3 
3 Uruguay-#8 Virus                                                    3 
3 Programmed in Montevideo (URUGUAY). 03/93.                          3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#8 ' 
3                                                                     3 
3 Uruguay-#9 Virus                                                    3 
3 Programmed in Montevideo (URUGUAY). 12/93.                          3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
~A Uruguay-#9 ' 
3                                                                     3 
3 Uruguay-#10 Virus                                                   3 
3 Programmed in Montevideo (URUGUAY). 05/94.                          3 
3 This is a research virus - DO NOT DISTRIBUTE.                       3 
 Uruguay-#10  
 
 
 
 
 
Fig.3. Layout of Uruguay-#7 virus (was selected as a typical example). 
 
 
3                                  3 Relative 3 Absolute 3   Address  3 
3    Virus routines and data       3   size   3  size    3    zone    3 
3                                  3    (%)   3 (bytes)  3    (hex)   3 
~A' 
3 Data buffer & victim file start  3     3    3    176   3    0....B0 3 
3 Startup code                     3     8    3    459   3   B1...27C 3 
3 Copyright string                 3     2    3    115   3  27D...2F0 3 
3 Tunneling trace routines         3     9    3    548   3  2F1...515 3 
3 Warm reboot routines (Int 8,9)   3     9    3    518   3  516...71B 3 
3 Interrupt (13h,21h) handlers     3    14    3    874   3  71C...A86 3 
3 Infection routines               3     6    3    374   3  A87...BFD 3 
3 EXE header relocator routine     3     2    3    132   3  BFE...C82 3 
3 Memory decode/encode routines    3     2    3    127   3  C83...D02 3 
3 Polymorphic engine data & tables 3     5    3    330   3  D03...E4D 3 
3 Polymorphic engine code          3    38    3   2295   3  E4E..1745 3 
3 Random number generator          3     2    3    106   3 1746..17AF 3 
~A' 
3 Total:                           3   100    3   6064   3    17B0    3 
 
 
 
 
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. 
 
3           ...                       3           ...                       3 
3 IP >  MOV DI,POINTER            3           MOV DI,POINTER            3 
3           ...                       3           ...                       3 
3           MOV CX,COUNTER            3           MOV CX,COUNTER            3 
3           ...                       3           ...                       3 
3 DECRYPT:  XOR word ptr [DI],MASK  3 DECRYPT:  XOR word ptr [DI],MASK 3 
3           ...                     3 3           ...                      33 
3           ADD DI,2                3 3           ADD DI,2                 33 
3           ...                     3 3 IP >  ...                      33 
3 POINTER:  xxxx < 3 POINTER:  LOOP DECRYPT             33 
3           xxxx                      3           xxxx <3 
3           xxxx                      3           xxxx                      3 
3           ...                       3           ...                       3 
3                                     3                                     3 
3 a) simple case (before running)     3 b) simple case (after running)      3 
 
 
 
 
Fig.5. Virus head and tail. 
 
 
3                                               3 
3      3                             V                                         3 
3  3 
3 3 JMP 3     victim file body      3 virus decryptor 3 encrypted virus body 3 3 
3  3 
3                             3 
3  virus                                                virus                  3 
3  head                                                 tail                   3 
3 (3-bytes)                                                                    3 
3                                                                              3 
3                a) simple 3-byte head (JMP=E9 offset)                         3 
~A 
3                                                         3 
3                3                             V                                         3 
3  3 
3 3 ...PUSH...RET 3     victim file body      3 virus decryptor 3 encrypted virus body 3 3 
3  3 
3                             3 
3      virus                                                virus                        3 
3      head                                                 tail                         3 
3   (99-bytes)                                                                           3 
3                                                                                        3 
3  b) extended virus head uses 3 types of control transfer to the virus                  3 
3     tail: 1. JMP offset; 2. MOV reg, offset/JMP reg; 3. PUSH offset/RET.               3 
3     Dots denote do-nothing and register modification commands commands.                3 
 
 
 
Fig.6. Do-nothing instructions of Uruguay polymorphic engine (#7, #8), 
       used in the decryptor of virus body. 
 
 
3  clc         3   adc   dx,ax        neg   dx       inc   dl             3 
3  cld         3   adc   dx,bx        neg   bp       inc   dh             3 
3  cmc         3   adc   dx,cx        neg   dl       dec   dl             3 
3  stc         3   adc   dx,dx        neg   dh       dec   dh             3 
3  sti         3   adc   dx,si        not   dl       xor   dh,dh          3 
3  nop         3   adc   dx,bp        not   dh       xor   dl,dl          3 
3  inc     dx  3   adc   bp,dx        rcl   dx,1     xchg  bp,dx          3 
3  inc     bp  3   jmp   short $+2    rcl   bp,1     xchg  dh,dl          3 
3  dec     dx  3   jc    $+2          rcr   dx,1     xchg  dl,dh          3 
3  dec     bp  3   jz    $+2          rcr   bp,1     push  bp / pop  dx   3 
3              3   jnz   $+2          shl   dl,1     push  dx / pop  bp   3 
3              3   jbe   $+2          shl   dh,1                          3 
3              3   jl    $+2          shr   dl,1                          3 
3              3                      shr   dh,1                          3 
3  a)one-byte  3                                                          3 
3    commands  3                 b)two-byte commands                      3 
 
 
 
Fig.7. Register-modification instructions of Uruguay polymorphic 
        engine (#7, #8), used in the decryptor of virus body. 
 
 
3 ADD REG, word         INC REG         MOV REG, REG 3 
3 SUB REG, word         DEC REG         AND REG, REG 3 
3 XOR REG, word         NOT REG         XOR REG, REG 3 
3 MOV REG, word         SHR REG,1       OR REG, REG  3 
3 OR REG, word          SHL REG,1       ADD REG, REG 3 
3 AND REG, word         ROR REG,1       SUB REG, REG 3 
3                       ROL REG,1                    3 
3                                                    3 
3           REG=AX/CX/DX/BP/BX/SI/DI                 3 
 
 
 
Fig.8. Encryption methods used by Uruguay-#7 and #8. 
 
 
3  # 3  Method sequence       3 Comment                       3 
~A' 
3  1 3 XOR [word],CONSTANT    3 CONSTANT is global            3 
3  2 3 SUB [word],CONSTANT    3 CONSTANT is global            3 
3  3 3 ADD [word],CONSTANT    3 CONSTANT is global            3 
3  4 3 ROR [word],1           3                               3 
3  5 3 ROL [word],1           3                               3 
3  6 3 NOT [word]             3                               3 
3  7 3 NEG [word]             3                               3 
3  8 3 XOR [word],CX          3 LOOP counter is used as MASK  3 
3    3                        3 (CX is modified by LOOP)      3 
3  9 3 SUB [word],CX          3 LOOP counter is used as MASK  3 
3    3                        3 (CX is modified by LOOP)      3 
3 10 3 ADD [word],CX          3 LOOP counter is used as MASK  3 
3    3                        3 (CX is modified by LOOP)      3 
3 11 3 XOR [word],DI          3 POINTER is used as mask       3 
3    3 ADD DI,2               3 (DI is modified as in Fig.9)  3 
3 12 3 SUB [word],DI          3 POINTER is used as mask       3 
3    3 ADD DI,2               3 (DI is modified as in Fig.9)  3 
3 13 3 ADD [word],DI          3 POINTER is used as mask       3 
3    3 ADD DI,2               3 (DI is modified as in Fig.9)  3 
3 14 3 XOR [word],MASK        3 MASK is for this method only  3 
3 15 3 SUB [word],MASK        3 MASK is for this method only  3 
3 16 3 ADD [word],MASK        3 MASK is for this method only  3 
 
 
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. 
 
 
3           ...                         3           ...                         3 
3 IP >  MOV DI,POINTER              3           MOV DI,POINTER              3 
3           ...                         3           ...                         3 
3           MOV CX,COUNTER              3           MOV CX,COUNTER              3 
3           ...                         3           ...                         3 
3 DECRYPT:  XOR word ptr [DI],MASK1  3 DECRYPT:  XOR word ptr [DI],MASK1  3 
3           ...                       3 3           ...                       3 3 
3           SUB word ptr [DI],MASK2 ' 3           SUB word ptr [DI],MASK2 ' 3 
3           ...                       3 3           ...                       3 3 
3           ADD word ptr [DI],MASK3 ' 3           ADD word ptr [DI],MASK3 ' 3 
3           ...                       3 3           ...                       3 3 
3           ADD DI,2                  3 3           ADD DI,2                  3 3 
3           ...                       3 3 IP >  ...                       3 3 
3 POINTER:  xxxx < 3 POINTER:  LOOP DECRYPT              3 3 
3           xxxx                        3           xxxx < 3 
3           xxxx                        3           xxxx                        3 
3           ...                         3           ...                         3 
3                                       3                                       3 
3    a) nested case (before running)    3     b) nested case (after running)    3 
 
 
 
Fig.10. Code synonyms used to modify pointer -- DI=DI+2 
        (modification of BX and SI is the same). RND 
        denotes any random word. 
 
 
3 # 3    Modification method     3     Processor opcodes     3 
3   ~A' 
3   3    First    3    Second    3    First    3    Second   3 
3   3 instruction 3  instruction 3 instruction 3 instruction 3 
~A' 
3 1 3 INC DI      3 INC DI       3      47     3      47     3 
3 2 3 ADD DI,+2   3              3  83,C7,02   3             3 
3 3 3 SUB DI,FFFE 3              3 81,EF,FE,FF 3             3 
3 4 3 SUB DI,-2   3              3  83,EF,FE   3             3 
3 5 3 ADD DI,2    3              3 81,C7,02,00 3             3 
3 6 3 ADD DI,RND  3 SUB DI,RND-2 3 81,C7,xx,yy 3 81,EF,zz,yy 3 
 
 
                                         
