diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/OptionalHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/OptionalHeader.java index 5fa440ba2d..e3fce6e82c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/OptionalHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/OptionalHeader.java @@ -24,6 +24,62 @@ import ghidra.util.DataConverter; import ghidra.util.task.TaskMonitor; public interface OptionalHeader extends StructConverter { + + /** + * ASLR with 64 bit address space. + */ + public final static int IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020; + + /** + * The DLL can be relocated at load time. + */ + public final static int IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040; + + /** + * Code integrity checks are forced. + */ + public final static int IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080; + + /** + * The image is compatible with data execution prevention (DEP) + */ + public final static int IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100; + + /** + * The image is isolation aware, but should not be isolated. + */ + public final static int IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200; + + /** + * The image does not use structured exception handling (SEH). + */ + public final static int IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400; + + /** + * Do not bind the image. + */ + public final static int IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800; + + /** + * Image should execute in an AppContainer. + */ + public final static int IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000; + + /** + * A WDM driver. + */ + public final static int IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000; + + /** + * Image supports Control Flow Guard. + */ + public final static int IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000; + + /** + * The image is terminal server aware. + */ + public final static int IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000; + /** * The count of data directories in the optional header. */ @@ -262,7 +318,7 @@ public interface OptionalHeader extends StructConverter { public void setSizeOfInitializedData(long size); /** - * Returns the size of all sections with the uninitialized + * Returns the size of all sections with the uninitialized * data attributes. * @return the size of all sections with the uninitialized data attributes */ @@ -307,10 +363,10 @@ public interface OptionalHeader extends StructConverter { /** * Writes this optional header to the specified random access file. - * + * * @param raf the random access file * @param dc the data converter - * + * * @throws IOException */ public void writeHeader(RandomAccessFile raf, DataConverter dc) throws IOException; diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedProcedureSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedProcedureSymbolApplier.java index 34ac56f640..d6e9e796bc 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedProcedureSymbolApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedProcedureSymbolApplier.java @@ -168,11 +168,13 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier { @Override void apply() throws PdbException, CancelledException { - boolean result = applyTo(applicator.getCancelOnlyWrappingMonitor()); - if (result == false) { - throw new PdbException(this.getClass().getSimpleName() + ": failure at " + address + - " applying " + getName()); - } + // TODO. Investigate more. This is not working for at least one CLI dll in that we are + // not getting correct addresses. There is no omap and the one section is unnamed. +// boolean result = applyTo(applicator.getCancelOnlyWrappingMonitor()); +// if (result == false) { +// throw new PdbException(this.getClass().getSimpleName() + ": failure at " + address + +// " applying " + getName()); +// } } boolean applyTo(TaskMonitor monitor) throws PdbException, CancelledException { @@ -291,6 +293,8 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier { } // Rest presumes procedureSymbol. long token = procedureSymbol.getToken(); + // TODO: once GP-328 is merged, use static methods to get table and row. + // CliIndexUtils.getTableIdUnencoded(token) and .getRowIdUnencoded(token). int table = (int) (token >> 24) & 0xff; int row = (int) (token & 0xffffff); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbAddressManager.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbAddressManager.java index c4444f979a..bd38adcff2 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbAddressManager.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbAddressManager.java @@ -99,7 +99,7 @@ public class PdbAddressManager { /** * Returns the Address for the given symbol. If the {@link PdbApplicatorOptions} * Address Remap option is turned on is turned on, it will attempt to map the address to a - * new address in the current program. + * new address in the current program. * @param symbol The {@link AddressMsSymbol} * @return The Address, which can be {@code Address.NO_ADDRESS} if invalid or * {@code Address.EXTERNAL_ADDRESS} if the address is external to the program. @@ -111,7 +111,7 @@ public class PdbAddressManager { /** * Returns the Address for the given section and offset. If the {@link PdbApplicatorOptions} * Address Remap option is turned on is turned on, it will attempt to map the address to a - * new address in the current program. + * new address in the current program. * @param segment The segment * @param offset The offset * @return The Address, which can be {@code Address.NO_ADDRESS} if invalid or @@ -128,7 +128,7 @@ public class PdbAddressManager { /** * Returns the Address for the given section and offset. If the {@link PdbApplicatorOptions} * Address Remap option is turned on is turned on, it will attempt to map the address to a - * new address in the current program. + * new address in the current program. * @param symbol The {@link AddressMsSymbol} * @return The Address, which can be {@code Address.NO_ADDRESS} if invalid or * {@code Address.EXTERNAL_ADDRESS} if the address is external to the program. @@ -298,7 +298,7 @@ public class PdbAddressManager { // // Set section/segment 0 to image base. (should be what is header), but what is its size? // // TODO... made up size for now... is there something else? We could put null instead. // // For now, the method that reads this information might report EXTERNAL instead of -// // trying to use this. +// // trying to use this. // long segmentZeroLength = 0x7fffffff; // allSegmentsInfo.add(new SegmentInfo(imageBase, segmentZeroLength)); // PdbDebugInfo dbi = applicator.getPdb().getDebugInfo(); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java index 2f21b31ed5..12c07e17ac 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java @@ -928,6 +928,16 @@ public class PdbApplicator { //============================================================================================== // CLI-Managed infor methods. //============================================================================================== + // Currently in CLI, but could move. + boolean isDll() { + return pdbCliManagedInfoManager.isDll(); + } + + // Currently in CLI, but could move. + boolean isAslr() { + return pdbCliManagedInfoManager.isAslr(); + } + CliAbstractTableRow getCliTableRow(int tableNum, int rowNum) throws PdbException { return pdbCliManagedInfoManager.getCliTableRow(tableNum, rowNum); } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbCliInfoManager.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbCliInfoManager.java index d058a9d251..e03f590034 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbCliInfoManager.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbCliInfoManager.java @@ -16,11 +16,12 @@ package ghidra.app.util.pdb.pdbapplicator; import java.io.IOException; +import java.util.List; import java.util.Objects; import generic.continues.GenericFactory; import ghidra.app.util.bin.ByteProvider; -import ghidra.app.util.bin.MemoryByteProvider; +import ghidra.app.util.bin.FileBytesProvider; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; import ghidra.app.util.bin.format.pe.*; import ghidra.app.util.bin.format.pe.PortableExecutable.SectionLayout; @@ -28,6 +29,7 @@ import ghidra.app.util.bin.format.pe.cli.streams.CliStreamMetadata; import ghidra.app.util.bin.format.pe.cli.tables.CliAbstractTable; import ghidra.app.util.bin.format.pe.cli.tables.CliAbstractTableRow; import ghidra.app.util.importer.MessageLogContinuesFactory; +import ghidra.program.database.mem.FileBytes; import ghidra.program.model.listing.Program; /** @@ -37,6 +39,11 @@ public class PdbCliInfoManager { private CliStreamMetadata metadataStream; + // TODO: May move these out from this class to a higher level. Would mean passing in + // the appropriate header to this constructor if we want to reuse that code. + private boolean isDll = false; + private boolean isAslr = false; + /** * Manager of CLI-related tables that we might need access to for PDB processing. * @param applicator {@link PdbApplicator} for which this class is working. @@ -46,7 +53,15 @@ public class PdbCliInfoManager { metadataStream = getCliStreamMetadata(applicator); } - public CliAbstractTableRow getCliTableRow(int tableNum, int rowNum) throws PdbException { + boolean isDll() { + return isDll; + } + + boolean isAslr() { + return isAslr; + } + + CliAbstractTableRow getCliTableRow(int tableNum, int rowNum) throws PdbException { if (metadataStream == null) { throw new PdbException("CliStreamMetadata is null"); } @@ -63,18 +78,28 @@ public class PdbCliInfoManager { return null; } - ByteProvider provider = new MemoryByteProvider(program.getMemory(), program.getImageBase()); + List allFileBytes = program.getMemory().getAllFileBytes(); + FileBytes fileBytes = allFileBytes.get(0); // Should be that of main imported file + ByteProvider provider = new FileBytesProvider(fileBytes); PortableExecutable pe = null; try { GenericFactory factory = MessageLogContinuesFactory.create(applicator.getMessageLog()); - pe = PortableExecutable.createPortableExecutable(factory, provider, - SectionLayout.MEMORY, true, true); + pe = PortableExecutable.createPortableExecutable(factory, provider, SectionLayout.FILE, + true, true); NTHeader ntHeader = pe.getNTHeader(); OptionalHeader optionalHeader = ntHeader.getOptionalHeader(); + int characteristics = ntHeader.getFileHeader().getCharacteristics(); + isDll = (characteristics & FileHeader.IMAGE_FILE_DLL) == FileHeader.IMAGE_FILE_DLL; DataDirectory[] dataDirectory = optionalHeader.getDataDirectories(); + int optionalHeaderCharaceristics = optionalHeader.getDllCharacteristics(); + isAslr = (optionalHeaderCharaceristics & + OptionalHeader.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == OptionalHeader.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA; COMDescriptorDataDirectory comDir = (COMDescriptorDataDirectory) dataDirectory[OptionalHeader.IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]; ImageCor20Header header = comDir.getHeader(); + if (header == null) { + return null; + } return header.getMetadata().getMetadataRoot().getMetadataStream(); } catch (Exception e) {