/* * PE_Header.java - This file is part of the Jakstab project. * * Copyright 2007-2015 Johannes Kinder <jk@jakstab.org> * Copyright (C) 2003 The University of Arizona * * The original code for this class was taken from "MBEL: The Microsoft * Bytecode Engineering Library" and modified for use with Jakstab. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, see <http://www.gnu.org/licenses/>. */ package org.jakstab.loader.pe; import org.jakstab.loader.BinaryParseException; import org.jakstab.util.BinaryInputBuffer; import org.jakstab.util.Logger; /** * This class parses the PE header of a PE/COFF file * * @author Michael Stepp * @author Johannes Kinder */ @SuppressWarnings("unused") class PE_Header{ private final static Logger logger = Logger.getLogger(PE_Header.class); public static final byte[] PE_TAG = new byte[]{80, 69, 0, 0}; // "PE\0\0" private static final int PE_SUBSYSTEM_NATIVE = 1; private static final int PE_SUBSYSTEM_WINDOWS_GUI = 2; private static final int PE_SUBSYSTEM_WINDOWS_CUI = 3; private static final int PE_SUBSYSTEM_OS2_CUI = 5; private static final int PE_SUBSYSTEM_POSIX_CUI = 7; private static final int PE_SUBSYSTEM_NATIVE_WINDOWS = 8; private static final int PE_SUBSYSTEM_WINDOWS_CE_GUI = 9; // constants for the 'Subsystem' field private static final int PE32_MAGIC = 0x10b; private static final int PE32_PLUS_MAGIC = 0x20b; private int Magic; // 2bytes private int MajorLinkerVersion; // 1byte private int MinorLinkerVersion; // 1byte private long SizeOfCode; // 4bytes private long SizeOfInitializedData; // 4bytes private long SizeOfUninitializedData; // 4bytes private long AddressOfEntryPoint; // 4byte RVA private long BaseOfCode; // 4byte RVA // end of same format for PE32/PE32+ private long BaseOfData; // 4byte RVA // absent in PE32+ // NT additional fields private long ImageBase; // 4byte VA private long SectionAlignment; // 4bytes private long FileAlignment; // 4bytes private int MajorOperatingSystemVersion; // 2bytes private int MinorOperatingSystemVersion; // 2bytes private int MajorImageVersion; // 2bytes private int MinorImageVersion; // 2bytes private int MajorSubsystemVersion; // 2bytes private int MinorSubsystemVersion; // 2bytes private long Win32VersionValue; // 4bytes private long SizeOfImage; // 4bytes private long SizeOfHeaders; // 4bytes private long CheckSum; // 4bytes private int Subsystem; // 2bytes private int DllCharacteristics; // 2bytes private long SizeOfStackReserve; // 4bytes private long SizeOfStackCommit; // 4bytes private long SizeOfHeapReserve; // 4bytes private long SizeOfHeapCommit; // 4bytes private long LoaderFlags; // 4bytes private long NumberOfRvaAndSizes; // 4bytes private ImageDataDirectory[] DataDirectory;// usually [16] /** * Parses a PE_Header from an input stream */ public PE_Header(BinaryInputBuffer in) throws java.io.IOException, BinaryParseException{ Magic = in.readWORD(); MajorLinkerVersion = in.readBYTE(); MinorLinkerVersion = in.readBYTE(); SizeOfCode = in.readDWORD(); SizeOfInitializedData = in.readDWORD(); SizeOfUninitializedData = in.readDWORD(); AddressOfEntryPoint = in.readDWORD(); BaseOfCode = in.readDWORD(); if (Magic == PE32_MAGIC){ // PE32 (normal) BaseOfData = in.readDWORD(); ImageBase = in.readDWORD(); SectionAlignment = in.readDWORD(); FileAlignment = in.readDWORD(); MajorOperatingSystemVersion = in.readWORD(); MinorOperatingSystemVersion = in.readWORD(); MajorImageVersion = in.readWORD(); MinorImageVersion = in.readWORD(); MajorSubsystemVersion = in.readWORD(); MinorSubsystemVersion = in.readWORD(); Win32VersionValue = in.readDWORD(); SizeOfImage = in.readDWORD(); SizeOfHeaders = in.readDWORD(); CheckSum = in.readDWORD(); Subsystem = in.readWORD(); DllCharacteristics = in.readWORD(); // obsolete, ==0 SizeOfStackReserve = in.readDWORD(); SizeOfStackCommit = in.readDWORD(); SizeOfHeapReserve = in.readDWORD(); SizeOfHeapCommit = in.readDWORD(); LoaderFlags = in.readDWORD(); // obsolete, ==0 NumberOfRvaAndSizes = in.readDWORD(); } else if (Magic == PE32_PLUS_MAGIC){ // PE32+ ImageBase = in.readDDWORD(); SectionAlignment = in.readDWORD(); FileAlignment = in.readDWORD(); MajorOperatingSystemVersion = in.readWORD(); MinorOperatingSystemVersion = in.readWORD(); MajorImageVersion = in.readWORD(); MinorImageVersion = in.readWORD(); MajorSubsystemVersion = in.readWORD(); MinorSubsystemVersion = in.readWORD(); Win32VersionValue = in.readDWORD(); SizeOfImage = in.readDWORD(); SizeOfHeaders = in.readDWORD(); CheckSum = in.readDWORD(); Subsystem = in.readWORD(); DllCharacteristics = in.readWORD(); // obsolete, ==0 SizeOfStackReserve = in.readDDWORD(); SizeOfStackCommit = in.readDDWORD(); SizeOfHeapReserve = in.readDDWORD(); SizeOfHeapCommit = in.readDDWORD(); LoaderFlags = in.readDWORD(); // obsolete, ==0 NumberOfRvaAndSizes = in.readDWORD(); } else throw new BinaryParseException("PE_Header: Invalid magic number"); DataDirectory = new ImageDataDirectory[(int)NumberOfRvaAndSizes]; for (int i=0;i<NumberOfRvaAndSizes;i++) DataDirectory[i] = new ImageDataDirectory(in); } public void output(){ logger.debug("PE Header:{"); logger.debug(" Magic = " + "0x" + Integer.toHexString(Magic)); logger.debug(" MajorLinkerVersion = " + MajorLinkerVersion); logger.debug(" MinorLinkerVersion = " + MinorLinkerVersion); logger.debug(" SizeOfCode = " + SizeOfCode); logger.debug(" SizeOfInitializedData = " + SizeOfInitializedData); logger.debug(" SizeOfUninitializedData = " + SizeOfUninitializedData); logger.debug(" AddressOfEntryPoint = " + "0x" + Long.toHexString(AddressOfEntryPoint)); logger.debug(" BaseOfCode = " + "0x" + Long.toHexString(BaseOfCode)); logger.debug(" BaseOfData = " + "0x" + Long.toHexString(BaseOfData)); logger.debug(" /// NT Additional fields ////////"); logger.debug(" ImageBase = " + "0x" + Long.toHexString(ImageBase)); logger.debug(" SectionAlignment = " + "0x" + Long.toHexString(SectionAlignment)); logger.debug(" FileAlignment = " + "0x" + Long.toHexString(FileAlignment)); logger.debug(" MajorOperatingSystemVersion = " + MajorOperatingSystemVersion); logger.debug(" MinorOperatingSystemVersion = " + MinorOperatingSystemVersion); logger.debug(" MajorImageVersion = " + MajorImageVersion); logger.debug(" MinorImageVersion = " + MinorImageVersion); logger.debug(" MajorSubsystemVersion = " + MajorSubsystemVersion); logger.debug(" MinorSubsystemVersion = " + MinorSubsystemVersion); logger.debug(" Win32VersionValue = " + Win32VersionValue); logger.debug(" SizeOfImage = " + SizeOfImage); logger.debug(" SizeOfHeaders = " + SizeOfHeaders); logger.debug(" CheckSum = " + "0x" + Long.toHexString(CheckSum)); logger.debug(" Subsystem = " + Subsystem); logger.debug(" DllCharacteristics = " + "0x" + Integer.toBinaryString(DllCharacteristics)); logger.debug(" SizeOfStackReserve = " + SizeOfStackReserve); logger.debug(" SizeOfStackCommit = " + SizeOfStackCommit); logger.debug(" SizeOfHeapReserve = " + SizeOfHeapReserve); logger.debug(" SizeOfHeapCommit = " + SizeOfHeapCommit); logger.debug(" LoaderFlags = " + "0x" + Long.toBinaryString(LoaderFlags)); logger.debug(" NumberOfRvaAndSizes = " + NumberOfRvaAndSizes); logger.debug(" DataDirectory[" + NumberOfRvaAndSizes + "] = \n {"); for (int i=0;i<NumberOfRvaAndSizes;i++){ logger.debug(" {\n VirtualAddress = " + "0x" + Long.toHexString(DataDirectory[i].VirtualAddress) + "\n Size = " + DataDirectory[i].Size + "\n }"); if (i<16) logger.debug(ImageDataDirectory.STRINGS[i]); } logger.debug(" }\n}"); } public long getAddressOfEntryPoint() { return AddressOfEntryPoint; } /** * @return the imageBase */ public long getImageBase() { return ImageBase; } /** * @return the dataDirectory */ public ImageDataDirectory[] getDataDirectory() { return DataDirectory; } }