/* * SectionHeader.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.util.BinaryInputBuffer; import org.jakstab.util.Logger; /** * This is the structure used to parse a PE/COFF Section Header. * Sections must appear in ascending order of virtual address, * and must be consecutive in the virtual address space. * Their virtual addresses must be multiples of SectionAlignment * in the PE header. * Also, the PointerToRawData and SizeOfRawData fields must be multiples of * FileAlignment in the PE header. * If (SectionAlignment < PageSize) then * PointerToRawData == VirtualAddress * @author Michael Stepp */ class SectionHeader { private final static Logger logger = Logger.getLogger(SectionHeader.class); public static final int STRUCT_SIZE = 40; ///// Flags for 'Characteristics' field ////////////////////////////// public static final int IMAGE_SCN_SCALE_INDEX = 0x00000001; public static final int IMAGE_SCN_CNT_CODE = 0x00000020; public static final int IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040; public static final int IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080; public static final int IMAGE_SCN_LNK_INFO = 0x00000200; public static final int IMAGE_SCN_LNK_REMOVE = 0x00000800; public static final int IMAGE_SCN_LNK_COMDAT = 0x00001000; public static final int IMAGE_SCN_GPREL = 0x00008000; public static final int IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000; public static final int IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000; public static final int IMAGE_SCN_MEM_DISCARDABLE = 0x02000000; public static final int IMAGE_SCN_MEM_NOT_CACHED = 0x04000000; public static final int IMAGE_SCN_MEM_NOT_PAGED = 0x08000000; public static final int IMAGE_SCN_MEM_SHARED = 0x10000000; public static final int IMAGE_SCN_MEM_EXECUTE = 0x20000000; public static final int IMAGE_SCN_MEM_READ = 0x40000000; public static final int IMAGE_SCN_MEM_WRITE = 0x80000000; ////////////////////////////////////////////////////////////////////// private final byte NameArray[]; // 8bytes private final String name; // Virtual size and address are not final to allow relocation of sections in objs public long VirtualSize; // 4bytes public long VirtualAddress; // 4bytes (really an RVA) public final long SizeOfRawData; // 4bytes public final long PointerToRawData; // 4bytes public final long PointerToRelocations; // 4bytes (file pointer) (object only) public final long PointerToLinenumbers; // 4bytes (file pointer) public final int NumberOfRelocations; // 2bytes public final int NumberOfLinenumbers; // 2bytes public final long Characteristics; // 4bytes public final long startFP; /** * Parses a Section Header from an input stream */ public SectionHeader(BinaryInputBuffer in) throws java.io.IOException{ startFP = in.getCurrent(); NameArray = new byte[8]; in.read(NameArray); StringBuilder nBuilder = new StringBuilder(); for (int i=0;i<8;i++){ if ((NameArray[i]&0xFF)>32 && (NameArray[i]&0xFF)<128) nBuilder.append((char)(NameArray[i]&0xFF)); } name = nBuilder.toString(); VirtualSize = in.readDWORD(); VirtualAddress = in.readDWORD(); SizeOfRawData = in.readDWORD(); PointerToRawData = in.readDWORD(); PointerToRelocations = in.readDWORD(); PointerToLinenumbers = in.readDWORD(); NumberOfRelocations = in.readWORD(); NumberOfLinenumbers = in.readWORD(); Characteristics = in.readDWORD(); //output(); } public boolean isCodeSection() { return (Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE)) > 0; } public boolean isReadOnlySection() { return (Characteristics & IMAGE_SCN_MEM_READ) > 0 && (Characteristics & IMAGE_SCN_MEM_WRITE) == 0; } public boolean hasComdat() { return (Characteristics & IMAGE_SCN_LNK_COMDAT) > 0; } public boolean isRemovedByLinker() { return (Characteristics & IMAGE_SCN_LNK_REMOVE) > 0; } public boolean isDiscardable() { return (Characteristics & IMAGE_SCN_MEM_DISCARDABLE) > 0; } public String getName() { return name; } public void output(){ logger.debug("SectionHeader: {"); logger.debug(" Name = '" + getName() + "'"); logger.debug(" VirtualSize = " + "0x" + Long.toHexString(VirtualSize)); logger.debug(" VirtualAddress = 0x" + Long.toHexString(VirtualAddress)); logger.debug(" SizeOfRawData = 0x" + Long.toHexString(SizeOfRawData)); logger.debug(" PointerToRawData = " + "0x" + Long.toHexString(PointerToRawData)); logger.debug(" PointerToRelocations = " + "0x" + Long.toHexString(PointerToRelocations)); logger.debug(" PointerToLinenumbers = " + "0x" + Long.toHexString(PointerToLinenumbers)); logger.debug(" NumberOfRelocations = " + NumberOfRelocations); logger.debug(" NumberOfLinenumbers = " + NumberOfLinenumbers); logger.debug(" Characteristics = 0x" + Long.toHexString(Characteristics)); logger.debug("}"); } }