mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-4881_ryanmkurtz_pe--SQUASHED'
(Closes #6864)
This commit is contained in:
commit
1b9507e12d
6 changed files with 906 additions and 1038 deletions
|
@ -150,8 +150,8 @@ public class DOSHeader extends OldDOSHeader {
|
|||
if (e_lfanew >= 0 && e_lfanew <= 0x1000000) {
|
||||
try {
|
||||
NTHeader ntHeader =
|
||||
new NTHeader(reader, e_lfanew, SectionLayout.FILE, false, false);
|
||||
if (ntHeader != null && ntHeader.getOptionalHeader() != null) {
|
||||
new NTHeader(reader, e_lfanew, SectionLayout.FILE, false);
|
||||
if (ntHeader.getOptionalHeader() != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ import ghidra.program.model.data.*;
|
|||
import ghidra.util.DataConverter;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.NotYetImplementedException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A class to represent the <b><code>IMAGE_NT_HEADERS32</code></b> and
|
||||
|
@ -54,7 +52,6 @@ public class NTHeader implements StructConverter, OffsetValidator {
|
|||
private OptionalHeader optionalHeader;
|
||||
private BinaryReader reader;
|
||||
private int index;
|
||||
private boolean advancedProcess = true;
|
||||
private boolean parseCliHeaders = false;
|
||||
|
||||
private SectionLayout layout = SectionLayout.FILE;
|
||||
|
@ -64,18 +61,16 @@ public class NTHeader implements StructConverter, OffsetValidator {
|
|||
* @param reader the binary reader
|
||||
* @param index the index into the reader to the start of the NT header
|
||||
* @param layout The {@link SectionLayout}
|
||||
* @param advancedProcess if true, information outside of the base header will be processed
|
||||
* @param parseCliHeaders if true, CLI headers are parsed (if present)
|
||||
* @throws InvalidNTHeaderException if the bytes the specified index
|
||||
* @throws IOException if an IO-related exception occurred
|
||||
* do not constitute an accurate NT header.
|
||||
*/
|
||||
public NTHeader(BinaryReader reader, int index, SectionLayout layout, boolean advancedProcess,
|
||||
boolean parseCliHeaders) throws InvalidNTHeaderException, IOException {
|
||||
public NTHeader(BinaryReader reader, int index, SectionLayout layout, boolean parseCliHeaders)
|
||||
throws InvalidNTHeaderException, IOException {
|
||||
this.reader = reader;
|
||||
this.index = index;
|
||||
this.layout = layout;
|
||||
this.advancedProcess = advancedProcess;
|
||||
this.parseCliHeaders = parseCliHeaders;
|
||||
|
||||
parse();
|
||||
|
@ -264,14 +259,7 @@ public class NTHeader implements StructConverter, OffsetValidator {
|
|||
}
|
||||
tmpIndex += FileHeader.IMAGE_SIZEOF_FILE_HEADER;
|
||||
|
||||
// Process Optional Header. Abort load on failure.
|
||||
try {
|
||||
optionalHeader = new OptionalHeaderImpl(this, reader, tmpIndex);
|
||||
}
|
||||
catch (NotYetImplementedException e) {//TODO
|
||||
Msg.error(this, "Unexpected Exception: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
optionalHeader = new OptionalHeader(this, reader, tmpIndex);
|
||||
|
||||
// Process symbols. Allow parsing to continue on failure.
|
||||
boolean symbolsProcessed = false;
|
||||
|
@ -286,12 +274,6 @@ public class NTHeader implements StructConverter, OffsetValidator {
|
|||
// Process sections. Resolving some sections names (i.e., "/21") requires symbols to have
|
||||
// been successfully processed. Resolving is optional though.
|
||||
fileHeader.processSections(optionalHeader, symbolsProcessed);
|
||||
|
||||
// Perform advanced processing. If advanced processing is disabled, these things may be
|
||||
// independently parsed later in the load if they are needed.
|
||||
if (advancedProcess) {
|
||||
optionalHeader.processDataDirectories(TaskMonitor.DUMMY);
|
||||
}
|
||||
}
|
||||
|
||||
void writeHeader(RandomAccessFile raf, DataConverter dc) throws IOException {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,812 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.app.util.bin.format.pe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.pe.ImageCor20Header.ImageCor20Flags;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressOutOfBoundsException;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.DataConverter;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* typedef struct _IMAGE_OPTIONAL_HEADER {
|
||||
* WORD Magic; // MANDATORY
|
||||
* BYTE MajorLinkerVersion;
|
||||
* BYTE MinorLinkerVersion;
|
||||
* DWORD SizeOfCode;
|
||||
* DWORD SizeOfInitializedData;
|
||||
* DWORD SizeOfUninitializedData;
|
||||
* DWORD AddressOfEntryPoint; // MANDATORY
|
||||
* DWORD BaseOfCode;
|
||||
* DWORD BaseOfData;
|
||||
* DWORD ImageBase; // MANDATORY
|
||||
* DWORD SectionAlignment; // MANDATORY
|
||||
* DWORD FileAlignment; // MANDATORY
|
||||
* WORD MajorOperatingSystemVersion; // MANDATORY
|
||||
* WORD MinorOperatingSystemVersion;
|
||||
* WORD MajorImageVersion;
|
||||
* WORD MinorImageVersion;
|
||||
* WORD MajorSubsystemVersion;
|
||||
* WORD MinorSubsystemVersion;
|
||||
* DWORD Win32VersionValue;
|
||||
* DWORD SizeOfImage; // MANDATORY
|
||||
* DWORD SizeOfHeaders; // MANDATORY
|
||||
* DWORD CheckSum;
|
||||
* WORD Subsystem; // MANDATORY
|
||||
* WORD DllCharacteristics;
|
||||
* DWORD SizeOfStackReserve;
|
||||
* DWORD SizeOfStackCommit;
|
||||
* DWORD SizeOfHeapReserve;
|
||||
* DWORD SizeOfHeapCommit;
|
||||
* DWORD LoaderFlags;
|
||||
* DWORD NumberOfRvaAndSizes; // USED
|
||||
* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* <pre>
|
||||
* typedef struct _IMAGE_OPTIONAL_HEADER64 {
|
||||
* WORD Magic;
|
||||
* BYTE MajorLinkerVersion;
|
||||
* BYTE MinorLinkerVersion;
|
||||
* DWORD SizeOfCode;
|
||||
* DWORD SizeOfInitializedData;
|
||||
* DWORD SizeOfUninitializedData;
|
||||
* DWORD AddressOfEntryPoint;
|
||||
* DWORD BaseOfCode;
|
||||
* ULONGLONG ImageBase;
|
||||
* DWORD SectionAlignment;
|
||||
* DWORD FileAlignment;
|
||||
* WORD MajorOperatingSystemVersion;
|
||||
* WORD MinorOperatingSystemVersion;
|
||||
* WORD MajorImageVersion;
|
||||
* WORD MinorImageVersion;
|
||||
* WORD MajorSubsystemVersion;
|
||||
* WORD MinorSubsystemVersion;
|
||||
* DWORD Win32VersionValue;
|
||||
* DWORD SizeOfImage;
|
||||
* DWORD SizeOfHeaders;
|
||||
* DWORD CheckSum;
|
||||
* WORD Subsystem;
|
||||
* WORD DllCharacteristics;
|
||||
* ULONGLONG SizeOfStackReserve;
|
||||
* ULONGLONG SizeOfStackCommit;
|
||||
* ULONGLONG SizeOfHeapReserve;
|
||||
* ULONGLONG SizeOfHeapCommit;
|
||||
* DWORD LoaderFlags;
|
||||
* DWORD NumberOfRvaAndSizes;
|
||||
* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class OptionalHeaderImpl implements OptionalHeader {
|
||||
protected short magic;
|
||||
protected byte majorLinkerVersion;
|
||||
protected byte minorLinkerVersion;
|
||||
protected int sizeOfCode;
|
||||
protected int sizeOfInitializedData;
|
||||
protected int sizeOfUninitializedData;
|
||||
protected int addressOfEntryPoint;
|
||||
protected int baseOfCode;
|
||||
protected int baseOfData;
|
||||
protected long imageBase;
|
||||
protected int sectionAlignment;
|
||||
protected int fileAlignment;
|
||||
protected short majorOperatingSystemVersion;
|
||||
protected short minorOperatingSystemVersion;
|
||||
protected short majorImageVersion;
|
||||
protected short minorImageVersion;
|
||||
protected short majorSubsystemVersion;
|
||||
protected short minorSubsystemVersion;
|
||||
protected int win32VersionValue;
|
||||
protected int sizeOfImage;
|
||||
protected int sizeOfHeaders;
|
||||
protected int checkSum;
|
||||
protected short subsystem;
|
||||
protected short dllCharacteristics;
|
||||
protected long sizeOfStackReserve;
|
||||
protected long sizeOfStackCommit;
|
||||
protected long sizeOfHeapReserve;
|
||||
protected long sizeOfHeapCommit;
|
||||
protected int loaderFlags;
|
||||
protected int numberOfRvaAndSizes;
|
||||
protected DataDirectory[] dataDirectory;
|
||||
|
||||
protected NTHeader ntHeader;
|
||||
protected BinaryReader reader;
|
||||
protected int startIndex;
|
||||
private long startOfDataDirs;
|
||||
|
||||
OptionalHeaderImpl(NTHeader ntHeader, BinaryReader reader, int startIndex) throws IOException {
|
||||
this.ntHeader = ntHeader;
|
||||
this.reader = reader;
|
||||
this.startIndex = startIndex;
|
||||
|
||||
parse();
|
||||
}
|
||||
|
||||
private String getName() {
|
||||
return "IMAGE_OPTIONAL_HEADER" + (is64bit() ? "64" : "32");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is64bit() {
|
||||
return magic == Constants.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getImageBase() {
|
||||
return imageBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAddressOfEntryPoint() {
|
||||
return Integer.toUnsignedLong(addressOfEntryPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfCode() {
|
||||
return sizeOfCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSizeOfCode(long size) {
|
||||
this.sizeOfCode = (int) size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfInitializedData() {
|
||||
return Integer.toUnsignedLong(sizeOfInitializedData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSizeOfInitializedData(long size) {
|
||||
this.sizeOfInitializedData = (int) size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfUninitializedData() {
|
||||
return Integer.toUnsignedLong(sizeOfUninitializedData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSizeOfUninitializedData(long size) {
|
||||
this.sizeOfUninitializedData = (int) size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseOfCode() {
|
||||
return Integer.toUnsignedLong(baseOfCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseOfData() {
|
||||
return Integer.toUnsignedLong(baseOfData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfImage() {
|
||||
return Integer.toUnsignedLong(sizeOfImage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSizeOfImage(long size) {
|
||||
this.sizeOfImage = (int) size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfHeaders() {
|
||||
return Integer.toUnsignedLong(sizeOfHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSizeOfHeaders(long size) {
|
||||
this.sizeOfHeaders = (int) size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNumberOfRvaAndSizes() {
|
||||
return Integer.toUnsignedLong(numberOfRvaAndSizes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getMajorOperatingSystemVersion() {
|
||||
return majorOperatingSystemVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getMinorOperatingSystemVersion() {
|
||||
return minorOperatingSystemVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processDataDirectories(TaskMonitor monitor) throws IOException {
|
||||
reader.setPointerIndex(startOfDataDirs);
|
||||
|
||||
dataDirectory = new DataDirectory[numberOfRvaAndSizes];
|
||||
if (numberOfRvaAndSizes == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ndata = 0;
|
||||
monitor.setMessage("Parsing exports...");
|
||||
try {
|
||||
dataDirectory[ndata] = new ExportDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing imports...");
|
||||
try {
|
||||
dataDirectory[ndata] = new ImportDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing resources...");
|
||||
try {
|
||||
dataDirectory[ndata] = new ResourceDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing exceptions...");
|
||||
try {
|
||||
dataDirectory[ndata] = new ExceptionDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing security...");
|
||||
try {
|
||||
dataDirectory[ndata] = new SecurityDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing relocations...");
|
||||
try {
|
||||
dataDirectory[ndata] = new BaseRelocationDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing debug information...");
|
||||
try {
|
||||
dataDirectory[ndata] = new DebugDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing architecture...");
|
||||
try {
|
||||
dataDirectory[ndata] = new ArchitectureDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing global pointer...");
|
||||
try {
|
||||
dataDirectory[ndata] = new GlobalPointerDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing TLS data...");
|
||||
try {
|
||||
dataDirectory[ndata] = new TLSDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing load config data...");
|
||||
try {
|
||||
dataDirectory[ndata] = new LoadConfigDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing bound imports...");
|
||||
try {
|
||||
dataDirectory[ndata] = new BoundImportDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing import address table...");
|
||||
try {
|
||||
dataDirectory[ndata] = new ImportAddressTableDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing delay imports...");
|
||||
try {
|
||||
dataDirectory[ndata] = new DelayImportDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Parsing COM descriptors...");
|
||||
try {
|
||||
dataDirectory[ndata] = new COMDescriptorDataDirectory(ntHeader, reader);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
if (PortableExecutable.DEBUG) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
if (++ndata == numberOfRvaAndSizes) {
|
||||
return;
|
||||
}
|
||||
|
||||
dataDirectory[ndata] = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataDirectory[] getDataDirectories() {
|
||||
return dataDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSectionAlignment() {
|
||||
return sectionAlignment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFileAlignment() {
|
||||
return fileAlignment;
|
||||
}
|
||||
|
||||
protected void parse() throws IOException {
|
||||
reader.setPointerIndex(startIndex);
|
||||
|
||||
magic = reader.readNextShort();
|
||||
if (magic != Constants.IMAGE_ROM_OPTIONAL_HDR_MAGIC &&
|
||||
magic != Constants.IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
|
||||
magic != Constants.IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||
Msg.warn(this, "Unsupported magic value: 0x%x. Assuming 32-bit.".formatted(magic));
|
||||
}
|
||||
majorLinkerVersion = reader.readNextByte();
|
||||
minorLinkerVersion = reader.readNextByte();
|
||||
sizeOfCode = reader.readNextInt();
|
||||
sizeOfInitializedData = reader.readNextInt();
|
||||
sizeOfUninitializedData = reader.readNextInt();
|
||||
addressOfEntryPoint = reader.readNextInt();
|
||||
// NB: 0 or negative addressOfEntryPoint is legal
|
||||
if (addressOfEntryPoint < 0) {
|
||||
Msg.warn(this, "Negative entry point " + Integer.toHexString(addressOfEntryPoint));
|
||||
}
|
||||
if (addressOfEntryPoint == 0) {
|
||||
int characteristics = ntHeader.getFileHeader().getCharacteristics();
|
||||
if ((characteristics & FileHeader.IMAGE_FILE_DLL) == 0) {
|
||||
Msg.warn(this, "Zero entry point for non-DLL");
|
||||
}
|
||||
}
|
||||
baseOfCode = reader.readNextInt();
|
||||
|
||||
if (is64bit()) {
|
||||
baseOfData = -1;//not used
|
||||
imageBase = reader.readNextLong();
|
||||
}
|
||||
else {
|
||||
baseOfData = reader.readNextInt();
|
||||
imageBase = Integer.toUnsignedLong(reader.readNextInt());
|
||||
}
|
||||
|
||||
sectionAlignment = reader.readNextInt();
|
||||
fileAlignment = reader.readNextInt();
|
||||
if (fileAlignment < 0x200) {
|
||||
Msg.warn(this, "Unusual file alignment: 0x" + Integer.toHexString(fileAlignment));
|
||||
}
|
||||
majorOperatingSystemVersion = reader.readNextShort();
|
||||
minorOperatingSystemVersion = reader.readNextShort();
|
||||
majorImageVersion = reader.readNextShort();
|
||||
minorImageVersion = reader.readNextShort();
|
||||
majorSubsystemVersion = reader.readNextShort();
|
||||
minorSubsystemVersion = reader.readNextShort();
|
||||
win32VersionValue = reader.readNextInt();
|
||||
sizeOfImage = reader.readNextInt();
|
||||
sizeOfHeaders = reader.readNextInt();
|
||||
if (sizeOfHeaders >= sizeOfImage) {
|
||||
Msg.warn(this, "Size of headers >= size of image: forced load");
|
||||
}
|
||||
checkSum = reader.readNextInt();
|
||||
subsystem = reader.readNextShort();
|
||||
dllCharacteristics = reader.readNextShort();
|
||||
|
||||
if (is64bit()) {
|
||||
sizeOfStackReserve = reader.readNextLong();
|
||||
sizeOfStackCommit = reader.readNextLong();
|
||||
sizeOfHeapReserve = reader.readNextLong();
|
||||
sizeOfHeapCommit = reader.readNextLong();
|
||||
}
|
||||
else {
|
||||
sizeOfStackReserve = reader.readNextUnsignedInt();
|
||||
sizeOfStackCommit = reader.readNextUnsignedInt();
|
||||
sizeOfHeapReserve = reader.readNextUnsignedInt();
|
||||
sizeOfHeapCommit = reader.readNextUnsignedInt();
|
||||
}
|
||||
|
||||
loaderFlags = reader.readNextInt();
|
||||
numberOfRvaAndSizes = reader.readNextInt();
|
||||
|
||||
if (numberOfRvaAndSizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) {
|
||||
Msg.warn(this, "Non-standard # of data directories: " + numberOfRvaAndSizes);
|
||||
if (numberOfRvaAndSizes > IMAGE_NUMBEROF_DIRECTORY_ENTRIES || numberOfRvaAndSizes < 0) {
|
||||
Msg.warn(this,
|
||||
"Forcing # of data directories to: " + IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
|
||||
numberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
|
||||
}
|
||||
}
|
||||
|
||||
startOfDataDirs = reader.getPointerIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.util.bin.StructConverter#toDataType()
|
||||
*/
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException {
|
||||
StructureDataType ddstruct = new StructureDataType(DataDirectory.TITLE, 0);
|
||||
ddstruct.add(IBO32, "VirtualAddress", null);
|
||||
ddstruct.add(DWORD, "Size", null);
|
||||
ddstruct.setCategoryPath(new CategoryPath("/PE"));
|
||||
|
||||
StructureDataType struct = new StructureDataType(getName(), 0);
|
||||
|
||||
struct.add(WORD, "Magic", null);
|
||||
struct.add(BYTE, "MajorLinkerVersion", null);
|
||||
struct.add(BYTE, "MinorLinkerVersion", null);
|
||||
struct.add(DWORD, "SizeOfCode", null);
|
||||
struct.add(DWORD, "SizeOfInitializedData", null);
|
||||
struct.add(DWORD, "SizeOfUninitializedData", null);
|
||||
struct.add(IBO32, "AddressOfEntryPoint", null);
|
||||
struct.add(IBO32, "BaseOfCode", null);
|
||||
if (is64bit()) {
|
||||
//BaseOfData does not exist in 64 bit
|
||||
struct.add(new Pointer64DataType(), "ImageBase", null);
|
||||
}
|
||||
else {
|
||||
struct.add(IBO32, "BaseOfData", null);
|
||||
struct.add(new Pointer32DataType(), "ImageBase", null);
|
||||
}
|
||||
struct.add(DWORD, "SectionAlignment", null);
|
||||
struct.add(DWORD, "FileAlignment", null);
|
||||
struct.add(WORD, "MajorOperatingSystemVersion", null);
|
||||
struct.add(WORD, "MinorOperatingSystemVersion", null);
|
||||
struct.add(WORD, "MajorImageVersion", null);
|
||||
struct.add(WORD, "MinorImageVersion", null);
|
||||
struct.add(WORD, "MajorSubsystemVersion", null);
|
||||
struct.add(WORD, "MinorSubsystemVersion", null);
|
||||
struct.add(DWORD, "Win32VersionValue", null);
|
||||
struct.add(DWORD, "SizeOfImage", null);
|
||||
struct.add(DWORD, "SizeOfHeaders", null);
|
||||
struct.add(DWORD, "CheckSum", null);
|
||||
struct.add(WORD, "Subsystem", null);
|
||||
struct.add(WORD, "DllCharacteristics", null);
|
||||
if (is64bit()) {
|
||||
struct.add(QWORD, "SizeOfStackReserve", null);
|
||||
struct.add(QWORD, "SizeOfStackCommit", null);
|
||||
struct.add(QWORD, "SizeOfHeapReserve", null);
|
||||
struct.add(QWORD, "SizeOfHeapCommit", null);
|
||||
}
|
||||
else {
|
||||
struct.add(DWORD, "SizeOfStackReserve", null);
|
||||
struct.add(DWORD, "SizeOfStackCommit", null);
|
||||
struct.add(DWORD, "SizeOfHeapReserve", null);
|
||||
struct.add(DWORD, "SizeOfHeapCommit", null);
|
||||
}
|
||||
struct.add(DWORD, "LoaderFlags", null);
|
||||
struct.add(DWORD, "NumberOfRvaAndSizes", null);
|
||||
struct.add(
|
||||
new ArrayDataType(ddstruct, numberOfRvaAndSizes, ddstruct.getLength()),
|
||||
"DataDirectory", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath("/PE"));
|
||||
return struct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeHeader(RandomAccessFile raf, DataConverter dc) throws IOException {
|
||||
raf.write(dc.getBytes(magic));
|
||||
raf.write(new byte[] { majorLinkerVersion });
|
||||
raf.write(new byte[] { minorLinkerVersion });
|
||||
raf.write(dc.getBytes(sizeOfCode));
|
||||
raf.write(dc.getBytes(sizeOfInitializedData));
|
||||
raf.write(dc.getBytes(sizeOfUninitializedData));
|
||||
raf.write(dc.getBytes(addressOfEntryPoint));
|
||||
raf.write(dc.getBytes(baseOfCode));
|
||||
if (is64bit()) {
|
||||
//BaseOfData does not exist in 64 bit
|
||||
raf.write(dc.getBytes(imageBase));
|
||||
}
|
||||
else {
|
||||
raf.write(dc.getBytes(baseOfData));
|
||||
raf.write(dc.getBytes((int) imageBase));
|
||||
}
|
||||
raf.write(dc.getBytes(sectionAlignment));
|
||||
raf.write(dc.getBytes(fileAlignment));
|
||||
raf.write(dc.getBytes(majorOperatingSystemVersion));
|
||||
raf.write(dc.getBytes(minorOperatingSystemVersion));
|
||||
raf.write(dc.getBytes(majorImageVersion));
|
||||
raf.write(dc.getBytes(minorImageVersion));
|
||||
raf.write(dc.getBytes(majorSubsystemVersion));
|
||||
raf.write(dc.getBytes(minorSubsystemVersion));
|
||||
raf.write(dc.getBytes(win32VersionValue));
|
||||
raf.write(dc.getBytes(sizeOfImage));
|
||||
raf.write(dc.getBytes(sizeOfHeaders));
|
||||
raf.write(dc.getBytes(checkSum));
|
||||
raf.write(dc.getBytes(subsystem));
|
||||
raf.write(dc.getBytes(dllCharacteristics));
|
||||
if (is64bit()) {
|
||||
raf.write(dc.getBytes(sizeOfStackReserve));
|
||||
raf.write(dc.getBytes(sizeOfStackCommit));
|
||||
raf.write(dc.getBytes(sizeOfHeapReserve));
|
||||
raf.write(dc.getBytes(sizeOfHeapCommit));
|
||||
}
|
||||
else {
|
||||
raf.write(dc.getBytes((int) sizeOfStackReserve));
|
||||
raf.write(dc.getBytes((int) sizeOfStackCommit));
|
||||
raf.write(dc.getBytes((int) sizeOfHeapReserve));
|
||||
raf.write(dc.getBytes((int) sizeOfHeapCommit));
|
||||
}
|
||||
raf.write(dc.getBytes(loaderFlags));
|
||||
raf.write(dc.getBytes(numberOfRvaAndSizes));
|
||||
|
||||
//the last one is null ...
|
||||
for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i) {
|
||||
if (dataDirectory[i] != null) {
|
||||
raf.write(dc.getBytes(dataDirectory[i].getVirtualAddress()));
|
||||
raf.write(dc.getBytes(dataDirectory[i].getSize()));
|
||||
}
|
||||
else {
|
||||
raf.write(dc.getBytes(0));
|
||||
raf.write(dc.getBytes(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateDataDirectories(Program program) {
|
||||
Memory memory = program.getMemory();
|
||||
int sizeint = Integer.SIZE / 8;
|
||||
Address addr = program.getImageBase().add(startOfDataDirs);
|
||||
for (int i = 0; i < numberOfRvaAndSizes; i++) {
|
||||
try {
|
||||
int virtualAddress = memory.getInt(addr, false);
|
||||
addr = addr.add(sizeint);
|
||||
int size = memory.getInt(addr, false);
|
||||
addr = addr.add(sizeint);
|
||||
if (dataDirectory[i] != null && dataDirectory[i].hasParsedCorrectly()) {
|
||||
if (dataDirectory[i].getVirtualAddress() != virtualAddress) {
|
||||
Msg.warn(this,
|
||||
"Correcting dataDirectory[" + i + "] va:" +
|
||||
Integer.toHexString(dataDirectory[i].getVirtualAddress()) + "->" +
|
||||
Integer.toHexString(virtualAddress));
|
||||
dataDirectory[i].setVirtualAddress(virtualAddress);
|
||||
}
|
||||
if (dataDirectory[i].getSize() != size) {
|
||||
Msg.warn(this,
|
||||
"Correcting dataDirectory[" + i + "] sz:" +
|
||||
Integer.toHexString(dataDirectory[i].getSize()) + "->" +
|
||||
Integer.toHexString(size));
|
||||
dataDirectory[i].setSize(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCLI() throws IOException {
|
||||
long origPointerIndex = reader.getPointerIndex();
|
||||
|
||||
reader.setPointerIndex(startOfDataDirs + (DataDirectory.IMAGE_SIZEOF_IMAGE_DIRECTORY_ENTRY *
|
||||
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR));
|
||||
|
||||
ImageCor20Header cor20 = new COMDescriptorDataDirectory(ntHeader, reader).getHeader();
|
||||
|
||||
reader.setPointerIndex(origPointerIndex);
|
||||
|
||||
if (cor20 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean intermediateLanguageOnly = (cor20.getFlags() &
|
||||
ImageCor20Flags.COMIMAGE_FLAGS_ILONLY) == ImageCor20Flags.COMIMAGE_FLAGS_ILONLY;
|
||||
|
||||
return intermediateLanguageOnly && cor20.getManagedNativeHeader().getVirtualAddress() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getMajorLinkerVersion() {
|
||||
return majorLinkerVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getMinorLinkerVersion() {
|
||||
return minorLinkerVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getMajorImageVersion() {
|
||||
return majorImageVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getMinorImageVersion() {
|
||||
return minorImageVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getMajorSubsystemVersion() {
|
||||
return majorSubsystemVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getMinorSubsystemVersion() {
|
||||
return minorSubsystemVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWin32VersionValue() {
|
||||
return win32VersionValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChecksum() {
|
||||
return checkSum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSubsystem() {
|
||||
return subsystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getDllCharacteristics() {
|
||||
return dllCharacteristics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfStackReserve() {
|
||||
return sizeOfStackReserve;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfStackCommit() {
|
||||
return sizeOfStackCommit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfHeapReserve() {
|
||||
return sizeOfHeapReserve;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSizeOfHeapCommit() {
|
||||
return sizeOfHeapCommit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLoaderFlags() {
|
||||
return loaderFlags;
|
||||
}
|
||||
}
|
|
@ -21,9 +21,10 @@ import java.io.RandomAccessFile;
|
|||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.format.mz.DOSHeader;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.util.DataConverter;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.NotYetImplementedException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A class to manage loading Portable Executables (PE).
|
||||
|
@ -86,15 +87,15 @@ public class PortableExecutable {
|
|||
}
|
||||
|
||||
try {
|
||||
ntHeader = new NTHeader(reader, dosHeader.e_lfanew(), layout, advancedProcess,
|
||||
parseCliHeaders);
|
||||
ntHeader = new NTHeader(reader, dosHeader.e_lfanew(), layout, parseCliHeaders);
|
||||
if (advancedProcess) {
|
||||
ntHeader.getOptionalHeader()
|
||||
.processDataDirectories(new MessageLog(), TaskMonitor.DUMMY);
|
||||
}
|
||||
}
|
||||
catch (InvalidNTHeaderException e) {
|
||||
Msg.debug(this, "Expected InvalidNTHeaderException, ignoring");
|
||||
}
|
||||
catch (NotYetImplementedException e) {
|
||||
Msg.debug(this, "Expected NotYetImplementedException, ignoring");
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e) {
|
||||
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
processMemoryBlocks(pe, program, fileBytes, monitor, log);
|
||||
|
||||
monitor.setCancelEnabled(false);
|
||||
optionalHeader.processDataDirectories(monitor);
|
||||
optionalHeader.processDataDirectories(log, monitor);
|
||||
monitor.setCancelEnabled(true);
|
||||
optionalHeader.validateDataDirectories(program);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue