All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dorkbox.peParser.headers.OptionalHeader Maven / Gradle / Ivy

There is a newer version: 3.3
Show newest version
/*
 * Copyright 2012 dorkbox, llc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dorkbox.peParser.headers;

import java.util.ArrayList;
import java.util.List;

import dorkbox.peParser.misc.DirEntry;
import dorkbox.peParser.ByteArray;
import dorkbox.peParser.misc.MagicNumberType;
import dorkbox.peParser.types.ByteDefinition;
import dorkbox.peParser.types.DWORD;
import dorkbox.peParser.types.HeaderDefinition;
import dorkbox.peParser.types.ImageBase;
import dorkbox.peParser.types.ImageBase_Wide;
import dorkbox.peParser.types.ImageDataDir;
import dorkbox.peParser.types.ImageDataDirExtra;
import dorkbox.peParser.types.MagicNumber;
import dorkbox.peParser.types.DWORD_WIDE;
import dorkbox.peParser.types.RVA;
import dorkbox.peParser.types.DllCharacteristics;
import dorkbox.peParser.types.Subsystem;
import dorkbox.peParser.types.WORD;

public class OptionalHeader extends Header {

    // see: http://msdn.microsoft.com/en-us/library/ms809762.aspx

    public List tables = new ArrayList(0);

    //
    // Standard fields.
    //
    public final MagicNumber MAGIC_NUMBER;
    public final WORD MAJOR_LINKER_VERSION;
    public final WORD MINOR_LINKER_VERSION;
    public final DWORD SIZE_OF_CODE;
    public final DWORD SIZE_OF_INIT_DATA;
    public final DWORD SIZE_OF_UNINIT_DATA;
    public final DWORD ADDR_OF_ENTRY_POINT;
    public final DWORD BASE_OF_CODE;
    public final DWORD BASE_OF_DATA;

    private boolean IS_32_BIT;

    //
    // NT additional fields.
    //
    @SuppressWarnings("rawtypes")
    public final ByteDefinition IMAGE_BASE;
    public final DWORD SECTION_ALIGNMENT;
    public final DWORD FILE_ALIGNMENT;
    public final WORD MAJOR_OS_VERSION;
    public final WORD MINOR_OS_VERSION;
    public final WORD MAJOR_IMAGE_VERSION;
    public final WORD MINOR_IMAGE_VERSION;
    public final WORD MAJOR_SUBSYSTEM_VERSION;
    public final WORD MINOR_SUBSYSTEM_VERSION;
    public final DWORD WIN32_VERSION_VALUE;
    public final DWORD SIZE_OF_IMAGE;
    public final DWORD SIZE_OF_HEADERS;
    public final DWORD CHECKSUM;
    public final Subsystem SUBSYSTEM;
    public final DllCharacteristics DLL_CHARACTERISTICS;
    @SuppressWarnings("rawtypes")
    public final ByteDefinition SIZE_OF_STACK_RESERVE;
    @SuppressWarnings("rawtypes")
    public final ByteDefinition SIZE_OF_STACK_COMMIT;
    @SuppressWarnings("rawtypes")
    public final ByteDefinition SIZE_OF_HEAP_RESERVE;
    @SuppressWarnings("rawtypes")
    public final ByteDefinition SIZE_OF_HEAP_COMMIT;
    public final DWORD LOADER_FLAGS;
    public final RVA NUMBER_OF_RVA_AND_SIZES;


    public final ImageDataDir EXPORT_TABLE;
    public final ImageDataDir IMPORT_TABLE;
    public final ImageDataDir RESOURCE_TABLE;
    public final ImageDataDir EXCEPTION_TABLE;
    public final ImageDataDir CERTIFICATE_TABLE;
    public final ImageDataDir BASE_RELOCATION_TABLE;

    public final ImageDataDir DEBUG;
    public final ImageDataDir COPYRIGHT;
    public final ImageDataDir GLOBAL_PTR;
    public final ImageDataDir TLS_TABLE;
    public final ImageDataDir LOAD_CONFIG_TABLE;

    public final ImageDataDirExtra BOUND_IMPORT;
    public final ImageDataDirExtra IAT;
    public final ImageDataDirExtra DELAY_IMPORT_DESCRIPTOR;
    public final ImageDataDirExtra CLR_RUNTIME_HEADER;

    public OptionalHeader(ByteArray bytes) {
        // the header length is variable.

        //
        // Standard fields.
        //
        h(new HeaderDefinition("Standard fields"));
        bytes.mark();

        this.MAGIC_NUMBER = h(new MagicNumber(bytes.readUShort(2), "magic number"));
        this.MAJOR_LINKER_VERSION = h(new WORD(bytes.readUShort(1), "major linker version"));
        this.MINOR_LINKER_VERSION = h(new WORD(bytes.readUShort(1), "minor linker version"));
        this.SIZE_OF_CODE = h(new DWORD(bytes.readUInt(4), "size of code"));
        this.SIZE_OF_INIT_DATA = h(new DWORD(bytes.readUInt(4), "size of initialized data"));
        this.SIZE_OF_UNINIT_DATA = h(new DWORD(bytes.readUInt(4), "size of unitialized data"));
        this.ADDR_OF_ENTRY_POINT = h(new DWORD(bytes.readUInt(4), "address of entry point"));
        this.BASE_OF_CODE = h(new DWORD(bytes.readUInt(4), "address of base of code"));
        this.BASE_OF_DATA = h(new DWORD(bytes.readUInt(4), "address of base of data"));

        this.IS_32_BIT = this.MAGIC_NUMBER.get() == MagicNumberType.PE32;

        bytes.reset();
        if (this.IS_32_BIT) {
            bytes.skip(28);
        } else {
            bytes.skip(24);
        }


        //
        // Standard fields.
        //
        h(new HeaderDefinition("Windows specific fields"));

        if (this.IS_32_BIT) {
            this.IMAGE_BASE = h(new ImageBase(bytes.readUInt(4), "image base"));
        } else {
            this.IMAGE_BASE = h(new ImageBase_Wide(bytes.readULong(8), "image base"));
        }

        this.SECTION_ALIGNMENT = h(new DWORD(bytes.readUInt(4), "section alignment in bytes"));
        this.FILE_ALIGNMENT = h(new DWORD(bytes.readUInt(4), "file alignment in bytes"));

        this.MAJOR_OS_VERSION = h(new WORD(bytes.readUShort(2), "major operating system version"));
        this.MINOR_OS_VERSION = h(new WORD(bytes.readUShort(2), "minor operating system version"));
        this.MAJOR_IMAGE_VERSION = h(new WORD(bytes.readUShort(2), "major image version"));
        this.MINOR_IMAGE_VERSION = h(new WORD(bytes.readUShort(2), "minor image version"));
        this.MAJOR_SUBSYSTEM_VERSION = h(new WORD(bytes.readUShort(2), "major subsystem version"));
        this.MINOR_SUBSYSTEM_VERSION = h(new WORD(bytes.readUShort(2), "minor subsystem version"));

        this.WIN32_VERSION_VALUE = h(new DWORD(bytes.readUInt(4), "win32 version value (reserved, must be zero)"));
        this.SIZE_OF_IMAGE = h(new DWORD(bytes.readUInt(4), "size of image in bytes"));
        this.SIZE_OF_HEADERS = h(new DWORD(bytes.readUInt(4), "size of headers (MS DOS stub, PE header, and section headers)"));
        this.CHECKSUM = h(new DWORD(bytes.readUInt(4), "checksum"));
        this.SUBSYSTEM = h(new Subsystem(bytes.readUShort(2), "subsystem"));
        this.DLL_CHARACTERISTICS = h(new DllCharacteristics(bytes.readUShort(2), "dll characteristics"));

        if (this.IS_32_BIT) {
            this.SIZE_OF_STACK_RESERVE = h(new DWORD(bytes.readUInt(4), "size of stack reserve"));
            this.SIZE_OF_STACK_COMMIT = h(new DWORD(bytes.readUInt(4), "size of stack commit"));
            this.SIZE_OF_HEAP_RESERVE = h(new DWORD(bytes.readUInt(4), "size of heap reserve"));
            this.SIZE_OF_HEAP_COMMIT = h(new DWORD(bytes.readUInt(4), "size of heap commit"));
        } else {
            this.SIZE_OF_STACK_RESERVE = h(new DWORD_WIDE(bytes.readULong(8), "size of stack reserve"));
            this.SIZE_OF_STACK_COMMIT = h(new DWORD_WIDE(bytes.readULong(8), "size of stack commit"));
            this.SIZE_OF_HEAP_RESERVE = h(new DWORD_WIDE(bytes.readULong(8), "size of heap reserve"));
            this.SIZE_OF_HEAP_COMMIT = h(new DWORD_WIDE(bytes.readULong(8), "size of heap commit"));
        }

        this.LOADER_FLAGS = h(new DWORD(bytes.readUInt(4), "loader flags (reserved, must be zero)"));
        this.NUMBER_OF_RVA_AND_SIZES = h(new RVA(bytes.readUInt(4), "number of rva and sizes"));


        bytes.reset();
        if (this.IS_32_BIT) {
            bytes.skip(96);
        } else {
            bytes.skip(112);
        }

        //
        // Data directories
        //
        h(new HeaderDefinition("Data Directories"));
        this.EXPORT_TABLE = table(h(new ImageDataDir(bytes, DirEntry.EXPORT)));
        this.IMPORT_TABLE = table(h(new ImageDataDir(bytes, DirEntry.IMPORT)));
        this.RESOURCE_TABLE = table(h(new ImageDataDir(bytes, DirEntry.RESOURCE)));
        this.EXCEPTION_TABLE = table(h(new ImageDataDir(bytes, DirEntry.EXCEPTION)));
        this.CERTIFICATE_TABLE = table(h(new ImageDataDir(bytes, DirEntry.SECURITY)));
        this.BASE_RELOCATION_TABLE = table(h(new ImageDataDir(bytes, DirEntry.BASERELOC)));

        this.DEBUG = table(h(new ImageDataDir(bytes, DirEntry.DEBUG)));
        this.COPYRIGHT = table(h(new ImageDataDir(bytes, DirEntry.COPYRIGHT)));
        this.GLOBAL_PTR = table(h(new ImageDataDir(bytes, DirEntry.GLOBALPTR)));
        this.TLS_TABLE = table(h(new ImageDataDir(bytes, DirEntry.TLS)));
        this.LOAD_CONFIG_TABLE = table(h(new ImageDataDir(bytes, DirEntry.LOAD_CONFIG)));

        this.BOUND_IMPORT = h(new ImageDataDirExtra(bytes, "bound import"));
        this.IAT = h(new ImageDataDirExtra(bytes, "IAT"));
        this.DELAY_IMPORT_DESCRIPTOR = h(new ImageDataDirExtra(bytes, "delay import descriptor"));
        this.CLR_RUNTIME_HEADER = h(new ImageDataDirExtra(bytes, "COM+ runtime header"));

        // reserved 8 bytes!!
        bytes.skip(8);
    }

    private  T table(T object) {
        this.tables.add(object);
        return object;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy