From cf1739b4b5dab9ca44573b2722c9eb018cb9a09c Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Fri, 18 Sep 2020 17:03:45 -0400 Subject: [PATCH] GP-182 Fixing unknown resource blowup --- .../app/util/bin/format/ne/Resource.java | 39 ++-- .../app/util/bin/format/ne/ResourceType.java | 201 ++++++++++-------- .../ghidra/app/util/opinion/NeLoader.java | 7 +- 3 files changed, 140 insertions(+), 107 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Resource.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Resource.java index 2dc2eb5c24..91eda63926 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Resource.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Resource.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +15,11 @@ */ package ghidra.app.util.bin.format.ne; -import ghidra.app.util.bin.format.*; -import ghidra.util.Conv; - import java.io.IOException; +import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; +import ghidra.util.Conv; + /** * An implementation of the new-executable TNAMEINFO structure. * @@ -61,6 +60,7 @@ public class Resource { public short getFileOffset() { return fileOffset; } + /** * Returns the file length of this resource. * @return the file length of this resource @@ -68,6 +68,7 @@ public class Resource { public short getFileLength() { return fileLength; } + /** * Returns the flag word of this resource. * @return the flag word of this resource @@ -75,6 +76,7 @@ public class Resource { public short getFlagword() { return flagword; } + /** * Returns the resource ID of this resource. * @return the resource ID of this resource @@ -82,6 +84,7 @@ public class Resource { public short getResourceID() { return resourceID; } + /** * Returns the handle of this resource. * @return the handle of this resource @@ -89,6 +92,7 @@ public class Resource { public short getHandle() { return handle; } + /** * Returns the usage of this resource. * @return the usage of this resource @@ -96,6 +100,7 @@ public class Resource { public short getUsage() { return usage; } + /** * Returns true if this resource is moveable. * @return true if this resource is moveable @@ -103,6 +108,7 @@ public class Resource { public boolean isMoveable() { return (flagword & FLAG_MOVEABLE) != 0; } + /** * Returns true if this resource is pure. * @return true if this resource is pure @@ -110,13 +116,15 @@ public class Resource { public boolean isPure() { return (flagword & FLAG_PURE) != 0; } + /** * Returns true if this resource is preloaded. * @return true if this resource is preloaded - */ + */ public boolean isPreload() { return (flagword & FLAG_PRELOAD) != 0; } + /** * Returns the shifted file offset of this resource. * this.getFileOffset() << ResourceTable.getAlignmentShiftCount() @@ -127,6 +135,7 @@ public class Resource { int offset_int = Conv.shortToInt(fileOffset); return offset_int << shift_int; } + /** * Returns the shifted file length of this resource. * this.getFileLength() << ResourceTable.getAlignmentShiftCount() @@ -137,20 +146,20 @@ public class Resource { int length_int = Conv.shortToInt(fileLength); return length_int << shift_int; } + /** * Returns the actual bytes for this resource. * @return the actual bytes for this resource */ public byte[] getBytes() throws IOException { - return reader.readByteArray( - getFileOffsetShifted(), - getFileLengthShifted()); + return reader.readByteArray(getFileOffsetShifted(), getFileLengthShifted()); } + /** * @see java.lang.Object#toString() */ @Override - public String toString() { + public String toString() { //if MSB is set, then resourceID is a unique id of this resource... if ((resourceID & 0x8000) != 0) { return "" + (resourceID & 0x7fff); @@ -159,12 +168,14 @@ public class Resource { //index to a resource name relative to the //beginning of the resource table... ResourceName[] names = rt.getResourceNames(); - for (int i = 0; i < names.length; ++i) { - if (resourceID == names[i].getIndex() - rt.getIndex()) { - return names[i].getName(); + for (ResourceName name : names) { + if (resourceID == name.getIndex() - rt.getIndex()) { + return name.getName(); } } - throw new RuntimeException( - "NE - Resource - unknown id - " + Conv.toHexString(resourceID)); + if (resourceID >= 0 && resourceID < names.length) { + return names[resourceID].getName(); + } + return ("NE - Resource - unknown id - " + Conv.toHexString(resourceID)); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/ResourceType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/ResourceType.java index 6d426f6955..e73ef7fcb2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/ResourceType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/ResourceType.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +15,12 @@ */ package ghidra.app.util.bin.format.ne; -import ghidra.app.util.bin.format.*; -import ghidra.util.Conv; - import java.io.IOException; import java.util.ArrayList; +import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; +import ghidra.util.Conv; + /** * An implementation of the TTYPEINFO structure. * @@ -30,123 +29,143 @@ import java.util.ArrayList; public class ResourceType { //0x00 is not defined...? /**Constant indicating cursor resource type.*/ - public final static short RT_CURSOR = 0x01; + public final static short RT_CURSOR = 0x01; /**Constant indicating bitmap resource type.*/ - public final static short RT_BITMAP = 0x02; + public final static short RT_BITMAP = 0x02; /**Constant indicating icon resource type.*/ - public final static short RT_ICON = 0x03; + public final static short RT_ICON = 0x03; /**Constant indicating menu resource type.*/ - public final static short RT_MENU = 0x04; + public final static short RT_MENU = 0x04; /**Constant indicating dialog resource type.*/ - public final static short RT_DIALOG = 0x05; + public final static short RT_DIALOG = 0x05; /**Constant indicating string resource type.*/ - public final static short RT_STRING = 0x06; + public final static short RT_STRING = 0x06; /**Constant indicating font directory resource type.*/ - public final static short RT_FONTDIR = 0x07; + public final static short RT_FONTDIR = 0x07; /**Constant indicating font resource type.*/ - public final static short RT_FONT = 0x08; + public final static short RT_FONT = 0x08; /**Constant indicating an accelerator resource type.*/ - public final static short RT_ACCELERATOR = 0x09; + public final static short RT_ACCELERATOR = 0x09; /**Constant indicating RC data resource type.*/ - public final static short RT_RCDATA = 0x0a; + public final static short RT_RCDATA = 0x0a; /**Constant indicating message table resource type.*/ - public final static short RT_MESSAGETABLE = 0x0b; + public final static short RT_MESSAGETABLE = 0x0b; /**Constant indicating cursor group resource type.*/ - public final static short RT_GROUP_CURSOR = 0x0c; - //0x0d is not defined...? + public final static short RT_GROUP_CURSOR = 0x0c; + //0x0d is not defined...? /**Constant indicating icon group resource type.*/ - public final static short RT_GROUP_ICON = 0x0e; - //0x0f is not defined...? + public final static short RT_GROUP_ICON = 0x0e; + //0x0f is not defined...? /**Constant indicating version resource type.*/ - public final static byte RT_VERSION = 0x10; + public final static byte RT_VERSION = 0x10; - private short typeID; //if >= 0x8000, then - private short count; //number of resources of this type - private int reserved; //reserved...for what? - private Resource [] resources; + private short typeID; //if >= 0x8000, then + private short count; //number of resources of this type + private int reserved; //reserved...for what? + private Resource[] resources; /** * Constructs a new resource type. * @param reader the binary reader * @param rt the resource table */ - ResourceType(FactoryBundledWithBinaryReader reader, ResourceTable rt) throws IOException { - typeID = reader.readNextShort(); - if (typeID == 0) return; //not a valid resource type... + ResourceType(FactoryBundledWithBinaryReader reader, ResourceTable rt) throws IOException { + typeID = reader.readNextShort(); + if (typeID == 0) { + return; //not a valid resource type... + } - count = reader.readNextShort(); - reserved = reader.readNextInt(); + count = reader.readNextShort(); + reserved = reader.readNextInt(); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList(); - int count_int = Conv.shortToInt(count); - for (int i = 0 ; i < count_int ; ++i) { - if ((short)(typeID&0x7fff) == RT_STRING) { - list.add(new ResourceStringTable(reader, rt)); - } - else { - list.add(new Resource(reader, rt)); - } - } - resources = new Resource[list.size()]; - list.toArray(resources); - } + int count_int = Conv.shortToInt(count); + for (int i = 0; i < count_int; ++i) { + if ((short) (typeID & 0x7fff) == RT_STRING) { + list.add(new ResourceStringTable(reader, rt)); + } + else { + list.add(new Resource(reader, rt)); + } + } + resources = new Resource[list.size()]; + list.toArray(resources); + } /** * Returns the resource type ID. * @return the resource type ID */ - public short getTypeID() { - return typeID; - } - /** - * Returns the number of resources of this type. - * @return the number of resources of this type - */ - public short getCount() { - return count; - } - /** - * Returns the reserved value (purpose is unknown). - * @return the reserved value - */ - public int getReserved() { - return reserved; - } - /** - * Returns the array of resources of this type. - * @return the array of resources of this type - */ - public Resource [] getResources() { - return resources; - } + public short getTypeID() { + return typeID; + } + + /** + * Returns the number of resources of this type. + * @return the number of resources of this type + */ + public short getCount() { + return count; + } + + /** + * Returns the reserved value (purpose is unknown). + * @return the reserved value + */ + public int getReserved() { + return reserved; + } + + /** + * Returns the array of resources of this type. + * @return the array of resources of this type + */ + public Resource[] getResources() { + return resources; + } + /** * @see java.lang.Object#toString() */ - @Override - public String toString() { - if ((typeID & 0x8000) == 0) { - throw new RuntimeException("NE - ResourceType - name lookup required - "+typeID); - } - int idx = typeID&0x7fff; - switch (idx) { - case RT_CURSOR: return "Cursor"; - case RT_BITMAP: return "Bitmap"; - case RT_ICON: return "Icon"; - case RT_MENU: return "Menu"; - case RT_DIALOG: return "Dialog Box"; - case RT_STRING: return "String Table"; - case RT_FONTDIR: return "Font Directory"; - case RT_FONT: return "Font"; - case RT_ACCELERATOR: return "Accelerator Table"; - case RT_RCDATA: return "Resource Data"; - case RT_MESSAGETABLE: return "Message Table"; - case RT_GROUP_CURSOR: return "Cursor Directory"; - case RT_GROUP_ICON: return "Icon Directory"; - case RT_VERSION: return "Version Information"; + @Override + public String toString() { + if ((typeID & 0x8000) == 0) { + return "UnknownResourceType_" + typeID; + } + int idx = typeID & 0x7fff; + switch (idx) { + case RT_CURSOR: + return "Cursor"; + case RT_BITMAP: + return "Bitmap"; + case RT_ICON: + return "Icon"; + case RT_MENU: + return "Menu"; + case RT_DIALOG: + return "Dialog Box"; + case RT_STRING: + return "String Table"; + case RT_FONTDIR: + return "Font Directory"; + case RT_FONT: + return "Font"; + case RT_ACCELERATOR: + return "Accelerator Table"; + case RT_RCDATA: + return "Resource Data"; + case RT_MESSAGETABLE: + return "Message Table"; + case RT_GROUP_CURSOR: + return "Cursor Directory"; + case RT_GROUP_ICON: + return "Icon Directory"; + case RT_VERSION: + return "Version Information"; - default: - return "Unknown_"+idx; - } - } + default: + return "Unknown_" + idx; + } + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java index cf81045b2d..db764ee0d9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java @@ -362,7 +362,9 @@ public class NeLoader extends AbstractLibrarySupportLoader { buf.append("Handle: " + Conv.toHexString(resource.getHandle()) + "\n"); buf.append("Usage: " + Conv.toHexString(resource.getUsage()) + "\n"); CodeUnit cu = listing.getCodeUnitAt(addr); - cu.setComment(CodeUnit.PRE_COMMENT, buf.toString()); + if (cu != null) { + cu.setComment(CodeUnit.PRE_COMMENT, buf.toString()); + } //if this resource is a string table, //then go and create the strings... @@ -435,7 +437,8 @@ public class NeLoader extends AbstractLibrarySupportLoader { Function refFunction = null; try { ExternalLocation loc; - loc = externalManager.addExtFunction(moduleName, callname, null, SourceType.IMPORTED); + loc = externalManager.addExtFunction(moduleName, callname, null, + SourceType.IMPORTED); refFunction = loc.getFunction(); } catch (DuplicateNameException e) {