Wednesday, November 08, 1995

How to infect DOS32 protected mode .EXE files

How to infect DOS32 protected mode .EXE files
A pure research virus
Dark Fiber [NuKE] 8th November 1995

Whats DOS32
Who uses DOS32
Never heard of it!!
Where can I get DOS32
Basics of using PMODE
Slight differences to DOS 
DOS32
Simple DOS32 virus guidelines
Anti
-Virus strategies on DOS32 files
Some notes about DOS32
DOS32 File Header structure
Crash course in PMODE by Adam Seychell
A VERY detailed tech spec 
for PMODE by Yann Stephen

          [
*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]


Whats DOS32
        DOS32 is a DOS Extender
what that isis a really cool program
        designed to run in protected mode
, and it offers programs a flat
        memory layout
that isno 64kb segments 16bit code size,
        
its a pure 32bit enviromentwith some reflection in 16bit
        mode
.

        << 
Lifted from the DOS32 manual ^_^ >>
                
The 80386 has been around since 1987 and to this day DOS is
        still running in real mode
Since nobody has bothered to design a
        protected mode DOS
programs called 'DOS extenders' were writtenA
        DOS extender is basically a program that will 
switch the CPU into
        protected mode so that it can then execute a protected mode
        application under DOS
. If you don't know the difference between
        real mode and protected mode then have a go at reading the file
        PMODE.DOC or better still get a proper book before reading to much
        further. I think that it is much easier to program in protected
        mode than it is to on real mode ( Intel 8086 architecture ) because
        you can use only one big segment for the entire application.

                You could say a DOS extender is a separate program that
        handles all the setting up needed for protected mode under DOS. You
        let the DOS extender worry about all of the protected mode
        initialising. So you write programs in plain and pure protected
        mode.

                Since DOS runs in real mode ( or V86 mode ) a protected
        mode program can no longer execute DOS calls directly. The DOS
        extender should have services that allow protected mode programs to
        call real mode code and will either enter V86 mode or return to
        real mode when doing so. Usually a DOS extender has many more
        services than just real mode calls. For example, setting interrupt
        vectors, memory allocation, disk I/O routines and possibly a
        debugger.


Who uses DOS32? Never heard of it!!
        I'
m not surprised :) I've been using it for about a year.
        The only people who tend to use it are the demo coders,
        just like their they only people who use Trans PMODE.
        Your chances of finding DOS32 files are few and far between,
        but they do exist.


Where can I get DOS32
        ftp.cdrom.com /demos/code/pmode/dos32v33.zip


Basics of using PMODE
        ACK! Thats really too much to explain, if you dont know
        jack shit about pmode......  Theres lots of good .DOCS
        that comes with DOS32 zip.


Slight differences to using DOS32 and DOS

        File functions like

        DOS                             DOS32

        mov ds,segment                  mov  ah,040h
        mov ah,040h                     mov ecx,really big length
        mov cx,length                   mov edx,really long offset
        mov dx,offset code              int  21h
        int 21h

        The main differences are for things such as offsets.
        You use extended 32bit registers, not pissy little 16bit ones.

        And ofcourse, it uses selectors instead of segments....


Simple DOS32 virus guidelines
        This will just be a step by step thing

           total_executable_size  is the size of the executable code
                                  as well as the size of all the relocations

           executable_code_size   this is the size of the executable code
                                  only.

           stubloader_size        this is the size of the

        1. You need to find the DOS32 header.
           Because DOS32 files are just standard overlays,
           tacked onto the extender stub or a loader stub,
           the standard overlay technique still works,

           Assume there is an .EXE file header in BUFFER

           ;; Calculate the overlay offset using the MZ header file size
           movzx eax,word ptr [BUFFER + 4]
           movzx edx,word ptr [BUFFER + 2]
           or dx,dx
           je $+3
           dec ax
           shl eax,9
           add edx,eax

           EDX now points to the overlay offset within the .EXE file.
           This address needs to be saved in order to make modifications
           here later onwards.

        2. Read in and check for a valid DOS32 header
        3. Check to see if the DOS32 exec is compressed
        4. Check to see if the DOS32 file contains an overlay.
           Formula for calculating a DOS32 overlay length is

           total_file_size - stubloader_size - total_executable_size == 0
           or
           total_file_size - stubloader_size == total_executable_size

           the total_executable_size is at offset 08h within the DOS32
           header.

           eg:
                mov     ax,04202h
                xor     edx,edx
                int     21h
                ;eax = total size
                sub     eax,dword ptr [stubloader_size]
                cmp     eax,dword ptr [BUFFER + 08h]
                je      no_overlay_present

        5. Remove the relocations from the end of the file
           To find the offset to the relocations the formula is
           executable_code_size - stubloader_size - header_size = reloc_offset

                eg:
                   mov  ax,04200h
                   mov  edx,dword ptr [BUFFER + 010h]
                   add  edx,dword ptr [stubloader_size]
                   add  edx,header_size
                   int  21h

        6. Append the virus

        7. Append the relocations

        8. Calculate the new header values
           To calculate a new EIP, its equal to the current
                       executable_code_size
           ESP must be > than your (EIP + total_virus size)

           the new stack MUST be on a DWORD boundary.

           You now need to patch in the amount of memory required to
           run the program, the total_executable_size, and the
           executable_code_size.
           This is as easy as adding the total virus size onto them.

        9. Write the new header back


Anti Virus strategies for DOS32 files.
        Whats to say.  NO anti virus programs scan dos32 files,
        proably because there so few and far between, and secondly
        probably because its an OMF format.


Some notes about DOS32
        Ummm, well, DOS32 files can be compressed, and this virus
        cant infect those ones.....

        DOS32 is an OMF format, and has its own linker, DLINK.
        You can TASM the code, but TLINK will just barf.



DOS32 File Header structure
        File format of a DOS32 executable (.EXE file produced from DLINK)

        Offset    Size           Description

        ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
        0         n    A stub loader or DOS32.EXE of n bytes {no stub in DLL}
        n+0       4    Signature "Adam"     { ="DLL " for DLL files }
        n+4       2    Minimum DOS32 version required (packed BCD)
        n+6       2    DLINK version in packed BCD format
        n+8       4    Number of bytes remaining after the stub file. The
                       entire .EXE file size (after linking) will be equal
                       to this value plus the stub file size.
        n+0Ch     4    Start of 32bit executable image relative to the
                       '
Adam' signature.
        n+10h     4    Length of executable image ( see below ).
        n+14h     4    Initial memory required for application. This value
                       must be larger than the size of the 32bit executable
                       image.
        n+18h     4    Initial EIP  { public varible address for DLL file }
        n+1Ch     4    Initial ESP  { ignored in DLL header }
        n+20h     4    Number of entries in fixup table. Each entry in the
                       table contains a 32bit offset relative to the start
                       of the executable image of a 16bit WORD that must be
                       set to the programs data selector at load time. The
                       table immediately follows the executable image.
        n+24h     4    Flags  ( function active when bit is set )
                       bit 0 = executable image is compressed
                       bit 1 = display DOS32 logo when executed
                       bits 2..31 reseved.

        The 32bit executable image (application binary data) can start
        anywhere after this point (i.e >= offset n+28h in the .EXE file).


A Crash course in PMODE by Adam Seychell

                      A CRASH COURSE IN PROTECTED MODE


                                                          By Adam Seychell


                After my release of DOS32 V1.2 a lot of people were asking
        for basic help in protected mode programming. If you already know
        what a selector is then there is probably no need for you to read
        this file.

                Ok you know all about the 8086 ( or a 386 in real mode )
        architecture and what to know about this fantastic protected mode
        stuff. I'
ll start off saying that I think real mode on the 386 is
        like driving a car that is stuck in first gear
There is the
        potential of a lot of power but it is not being used
It really
        degrades the 386 processor 
and was not designed to normally operate
        in this mode
Even the Intel data book states  "Real mode is
        required primarily to set up the processor for Protected Mode
        operation"
.


                      
SEGMENTATION OF THE INTEL 80x86

                A segment is a block of memory that starts at a fixed base
        address 
and has a set length.  As you should already know that
        
*everymemory reference by the CPU requires both a SEGMENT value
        
and a OFFSET value to be specifiedThe OFFSET value is the
        location relative to the base address of the segment
The SEGMENT
        value contains the information 
for the segmentI am going to
        explain very basically how this SEGMENT value is interpreted by the
        80386 to give the parameters of segments
.


                
In protected mode this SEGMENT value is interpreted
        completely different than in real mode 
and/or Virtual 86 modeThe
        SEGMENT values are now called 
"selectors"You'll see why when
        finished reading this file. So whenever you load a segment register
        you are loading it with a selector.



        The Selector is word length and contains three different fields.

        Bits  0..1       Request Privilege level        ( just set this to
                                                        zero )

        Bit   2          Table Indicator        0 = Global Descriptor Table
                                                1 = Local Descriptor Table

        Bits 3..15      The INDEX field value of the desired descriptor in
                        the GDT This index value points to a descriptor in
                        the table.



                    The  GLOBAL DESCRIPTOR TABLE  (GDT)

                The Global Descriptor Table ( GDT ) is a table of
        DESCRIPTORS and it is stored in memory. The address of this table
        is given in a special 386 register called the global descriptor
        table register. There always must be a GDT when in protected mode
        because it is in this table where all of the segments are defined.
        Each DESCRIPTOR ( stored in the GDT ) contains the complete
        information about a segment. It is a description of the segment.
        Each Descriptor is 64 bits long and contains many different fields.
        I'
ll explain the fields laterThe INDEX field  stored in bits
        3..15 of any segment register 
selects a descriptor to use for the
        type of segment wanted
So the only segments the programmer can use
        
are the available descriptors in the GDT.


        
ExampleSuppose you what to access location 012345h in your data
                segment 
and you were told that the descriptor for your data
                segment is descriptor number 6 in the 
Global Descriptor
                Table
.  Assume that the Global Descriptor Table has already
                been set up 
and built for you  example, as in DOS32).

        
SolutionWe need to load a segment register (SS,DS,FS,GS,ES)  with
                a value so that it will select 
(or index descriptor
                number 6 of the GDT
Then reference the address with a
                instruction that will 
use this loaded segment register.

        
One of the segment registers (FS,DS,GS,SS,CS or ESmust be loaded
        with the following three fields
,

                
Request Privilege level Bits 0..1 ) = 0  (always)
                
Table Indicator bit 2 )  = 0
                Index  
bits 3..15 ) = 6


             mov  ax
,0000000110000b      ;load DS with the selector value
             mov  ds
,ax
             mov  byte ptr DS
:[ 012345h ],0     Using the DS
             segment register



                The 386 has hardware 
for a complete multitasking system.
        
There are several different types of descriptors available in the
        GDT 
for managing multitaskingYou don't need to know about all the
        different descriptors just to program in protected mode. Just the
        info above is enough.  All you need to know to program in protected
        mode is what descriptors are available to you and what are the
        selector values to these descriptors.  The base address of the
        segment may also be known. See the file DOS32.DOC for obtaining the
        selector values.

            There are two groups of descriptors 1) CODE/DATA descriptors
        which are used for any code and data segments.

        2) SYSTEM descriptors are used for the multitasking system of the
        386. These type of descriptors will never need to be used for
        programming applications.



                  Format of a code and data descriptor

        BITS             description if the field
        ------------------------------------------------------------
        0..15            SEGMENT LIMIT 0...15
        16..39           SEGMENT BASE 0..23
        40              (A)   accessed bit
        41..43          (TYPE) 0 = SEE BELOW
        44              (0)  0 = code/data descriptor 1 = system descriptor
        45..46          (DPL) Descriptor Privilege level
        47              (P)  Segment Present bit
        48..50          SEGMENT LIMIT 16..19
        51..52          (AVL)   2 bits available for the OS
        53              zero for future processors
        54              Default Operation size used by code descriptors only
        55              Granularly:  1 = segment limit = limit field *1000h
                                    0 = segment limit = limit field
        56..63          SEGMENT BASE 24..31

        format of TYPE field
            bit  2    Executable (E)     0 = Descriptor is data type
                 1    Expansion Direction (ED) 0 = Expand up
                                               1 = Expand up
                 0    Writeable (W)       W = 0 data segment is read only
                                          W = 1 data segment is R/W

            bit  2    Executable (E)  1 = Descriptor is code type
                 1    Conforming (C)   ( I don'
t understand )
                 
0    Readable (R)        0 Code segment execute only
                                          R 
1 Code segment is Readable

           I
'd better stop here, I am confusing myself. As you can see
        there is more to a segment that just it'
s base address and limit.
        
The three descriptors that are available in DOS32  all have limits
        of 0ffffffffh 
(4GB). This means that the offsets can be any value.
        For 
examplethe instruction    XOR EAX,ES:[0FFFFFFFFh]  is
        allowed
. If you happen to load an invalid selector value into one
        of the segment registers then the 386 will report an General
        Protection exception 
interrupt 13 ).  In protected mode this
        exception is also used 
for many other illegal operations.



                           
The LINEAR ADDRESS and PHYSICAL ADDRESS

             All the address translations described above is done by the
        386 segmentation unit
The segmentation unit looks up the
        descriptor tables
segment selectorsoffsets and then outputs a
        32bit linear address
This linear address is calculated by the
        segmentation unit in the following manner
.

        
Linear address base address of segment offsetThe segment base
        address is found in the Base address field 
bits 16..39 56..63 )
        
of a descriptor which is located in the Global Descriptor Table.
        
The index field bits 3..15of the segment register selects the
        descriptor to 
use.


        
An example of the linear address of the instruction.

                  
MOV       EAXES:[EDX*8+012345678h]

        where EDX 
100h and ES equals a selector wich points to a
        descriptor with the base field equal to 02000000h
.

        
The linear address 2000000h + ( 100h*012345678h ) = 014345E78h


             Just to make things even more complicated the 386 has an
        second memory managing unit called the Paging Unit
The linear
        address calculated above may still not be the physical RAM location
        the 386 is addressing
This linear address has yet to go through
        another stage
the paging unit. If you are having trouble with what
        I
've said so far then you may want to take a coffee break before
        continuing because this is even worse.

             The 32bit linear address is directed to the paging unit. The
        paging unit divides the linear address into three sections.

        bits 0..12    Offset in a page
        bits 13..23   Points to the page entry in the page table
        bits 24..31   Points to the directory entry in the page directory table

        The page table contains 1024 double word entires. In each of these
        entries is the physical address of a 4KB page. The page directory
        also contains 1024 double word entries. Each of these directory
        entries hold a physical address of a page table. See intel
        Documentation for the exact format of the page table entries and
        directory table entries.  The physical base address of the
        DIRECTORY TABLE is in control register 3 ( CR3 )

          This means if every entry in the directory table is used then
        there would be 1024 page tables available. Because each page table
        hold 1024 page addresses then there would be a total of 1024*1024
        4KB pages. The addresses in the page tables are all physical
        addresses. i.e the output of the CPU address bus pins. The paging
        unit can be enabled or disabled depending on wether bit 31 of CR0
        is set. If the paging in disabled then the linear address simply
        equals the physical address. If paging is enabled the the linear
        address is translated by the paging unit to form a physical
        address.  Please note that it is possible to set up the page tables
        and directory such that the linear address equals the physical
        address. This is what DOS32 does for the first 1MB of linear
        address space. If you can not understand my hopeless attempt of
        describing the paging unit then the diagram below might help.

            The 32 bit linear address from the segmentation unit
  -------------------------------------------------------------------------
  |   BITS  0..12             |    BITS  13..23       |    BITS 24..31     |
  |                           |                       |                    |
  -------------------------------------------------------------------------
               |                                  |                   |
               |------------------------          |                   |
                                        |         |                   |
                                        |         |                   |
                                        |         |                   |
        A Page in memory (4KB)          |         |                   |
     --------------------------         |         |                   |
     |                        |         |         |                   |
     |                        |         |         |                   |
     |                        |         |         |                   |
     |                        |         |         |                   |
     |                        |         |         |                   |
     |                        |         |         |                   |
     |                        |         |         |                   |
     |                        | <-------          |                   |
     |                        |                   |                   |
     |                        |                   |                   |
     |                        |                   |                   |
|---> -------------------------                   |                   |
|                                                 |                   |
|                                                 |                   |
|                                                 |                   |
|            PAGE  TABLE          Offset          |                   |
|    --------------------------                   |                   |
|    |                        |    4092           |                   |
|    --------------------------                   |                   |
|    .                        .                   |                   |
|    .                        .                   |                   |
|    .                        .                   |                   |
|    --------------------------                   |                   |
|    |                        |     12            |                   |
|    --------------------------                   |                   |
|---<|   address of page      |     8   <---------                    |
     --------------------------                                       |
     |                        |     4                                 |
     --------------------------                                       |
     |                        |     0                                 |
|--> --------------------------                                       |
|                                                                     |
|                                                                     |
|                                                                     |
|                                                                     |
|                                                                     |
|         DIRECTORY TABLE          Offset                             |
|    --------------------------                                       |
|    |                        |    4092                               |
|    --------------------------                                       |
|    .                        .                                       |
|    .                        .                                       |
|    .                        .                                       |
|    --------------------------                                       |
|---<| address of page table  |     12  <-----------------------------
     --------------------------
     |                        |     8
     --------------------------
     |                        |     4
     --------------------------
     |                        |     0
|--> --------------------------
|
|
|
|         ----------------------------------------------
--------<-|               CR3                          |
          ----------------------------------------------


           This was only meant to be a rough introduction to the protected
        mode segmentation mechanism of the 80386+. I hope I did not make
        this sound too complicated so that you have been put off with the
        whole idea of protected mode programming. If you want to know more
        then I suggest you buy a book on the 80386. The "Intel Programmers
        Reference guide" is the most detailed book around. The info here is
        only meant to give you an idea of how protected mode works. Please
        note that DOS32 does *ALL* of the setting up needed for protected
        mode.  Don'
t worry if you couldn't understand half the stuff I was
        talking about. You don'
t have to know about any stupid things like
        the descriptor format
selector index fieldsprivilege levels
        
,pagingtablesect ectWhat you do need to know are the
        selector values 
for all the descriptors that are available to your
        program
Then the segment registers can simply be loaded with these
        known selector values
DOS32 uses only 3 descriptors ( or segments
        
) as described in DOS32.DOC.




A VERY detailed tech spec for PMODE by Yann Stephen

                PROTECTED MODE  
A more detailed approch )
                          
Written by Yann Stephen


        
Global Descriptor Table Register (GDTR) :

        
The contents of the global table register define a table in the
        80386DX
's physical memory address space called the Global
        Descriptor Table (GDT). This global descriptor table is one
        important element of the 80386DX'
s memory management system.

        
GDTR is a 48-bit register that is located inside the 80386DXThe
        lower two bytes of this register
which are identified as LIMIT,
        
specify the size in byte of the GDTThe decimal value of LIMIT is
        one less than the actual size of the table
. For instance, if LIMIT
        equals 00FFh the table is 256 bytes in length
Since LIMIT has 16
        bits
the GDT can be up to 65,536 bytes longThe upper four bytes
        of the GDTR
which are labelled BASElocate the beginning of the
        GDT in physical memory
This 32-bit base address allows the table
        to be positioned anywhere in the 80386DX
's address space.

        The GDT provides a mechanism for defining the characteristics of
        the 80386DX'
global memory address space. Global memory is a
        general system resource that is shared by many 
or all software
        tasks
That isstorage locations in global memory are accessible
        by any task that runs on the microprocessor
This table contains
        what are called system segment descriptors
It is these descriptors
        that identify the characteristics of the segments of 
global memory.
        For 
instancea segment descriptor provides information about the
        size
starting point, and access rights of a global memory segment.
        
Each descriptor is eight bytes longthus our earlier example of a
        256
-byte table provides enough storage space for just 32
        descriptors
Remember that the size of the global descriptor table
        can be expanded simply by changing the value of LIMIT in the GDTR
        under software control
. If the table is increased to its maximum
        size of 65
,563 bytesit can hold up to 8,192 descriptors.

        
Question 1.1 How many descriptors can be stored the global
        
descriptor table when the size of LIMIT is 0FFFh.

        
The value of the BASE and LIMIT must be loaded into the GDTR before
        the 80386DX is switched from real mode of operation to the
        protected mode
Special instruction are provided for this purpose
        in the system control instruction set of the 80386 DX
Once the
        80386DX is in protected mode
the location of the table is
        typically not changed
.


        
Interrupt Descriptor Table Register (IDTR) :

        
Just like the global descriptor table registerthe interrupt
        descriptor table register 
(IDTRdefines a table in physical
        memory
Howeverthis table contains what are called interrupt
        descriptors
not segment descriptors. For this reason  it is known
        
as the Interrupt Descriptor Table (IDT).This register and table of
        descriptors provide the mechanism by which the microprocessor
        passes program control to interrupt 
and exception routines.

                
Just like the GDTRthe IDTR is 48 bits in lengthAgain,
        
the lower two bytes of the register (LIMITdefine the table size.
        
That isthe size of the table equals LIMIT+1 bytesSince two
        bytes define the size
the IDT can also be up to 65,536 bytes long.
        
But the 80386DX only supports up to 256 interrupts and exceptions;
        
thereforethe size of the IDT should not be set to support more
        than 256 interrupts
The upper three bytes of IDTR (BASEidentify
        the starting address of the IDT in  physical memory
The type of
        descriptor used in the IDT are what are called interrupt gates
.
        
These gates provide a means for passing program control to the
        beginning of an interrupt service routine
Each gate is eight bytes
        long 
and contains both attributes and a starting address for the
        service routine
.

        
Question 1.2 What is the maximum value that should be assigned to
        the limit in the IDTR
?


        
This table can also be located anywhere in the linear address space
        address