Merge remote-tracking branch 'origin/GP-258_dev747368_fix_pe_securitycertificate--SQUASHED' into Ghidra_9.2

This commit is contained in:
ghidra1 2020-10-27 17:16:15 -04:00
commit 8dfe8ca13a
4 changed files with 51 additions and 152 deletions

View File

@ -72,7 +72,7 @@ public class BinaryReader {
* @param newIndex the new index
* @return a clone of this reader positioned at the new index
*/
public BinaryReader clone(int newIndex) {
public BinaryReader clone(long newIndex) {
BinaryReader clone = new BinaryReader(provider, isLittleEndian());
clone.converter = converter;
clone.currentIndex = newIndex;
@ -643,21 +643,6 @@ public class BinaryReader {
return readInt(index) & NumberUtil.UNSIGNED_INT_MASK;
}
/**
* Returns the INTEGER at <code>index</code>, after coercing it into the range
* [minClamp-maxClamp].
*
* @param index the index where the INTEGER begins
* @param minClamp minimum value that will be returned
* @param maxClamp maximum value that will be returned
* @return the INTEGER
* @exception IOException if an I/O error occurs
*/
public int readInt(long index, int minClamp, int maxClamp) throws IOException {
int i = readInt(index);
return clampInt(i, minClamp, maxClamp);
}
/**
* Returns the signed LONG at <code>index</code>.
* @param index the index where the LONG begins
@ -801,27 +786,4 @@ public class BinaryReader {
return provider;
}
/**
* Returns the specified integer after it has been forced to be within the range of
* [minClamp-maxClamp].
* <p>
* @param i value to force into range
* @param minClamp minimum value the integer is allowed to take (inclusive)
* @param maxClamp maximum value the integer is allowed to take (inclusive)
* @return value of {@code i} if it is within the range [min-max], otherwise min if {@code i} is less than min
* or max if {@code i} is greater than max.
*/
private int clampInt(int i, int minClamp, int maxClamp) {
if (maxClamp < minClamp) {
throw new IllegalArgumentException("maxClamp < minClamp not allowed");
}
if (i < minClamp) {
i = minClamp;
}
else if (i > maxClamp) {
i = maxClamp;
}
return i;
}
}

View File

@ -1,82 +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;
import generic.jar.ResourceFile;
import ghidra.framework.Application;
import ghidra.util.Msg;
import java.io.*;
import java.util.Properties;
public class ClampPropertiesLookup {
public static final String CLAMP_PROPERTIES_FILENAME = "formats/clamp.properties";
private static boolean UNINITIALIZED = true;
private static Properties properties = null;
public static long getClampValue(String clampKey, long defaultValue) {
initialize();
try {
String property = properties.getProperty(clampKey);
if (property != null) {
try {
long value = Long.parseLong(property);
return value;
}
catch (NumberFormatException e) {
return defaultValue;
}
}
}
catch (NullPointerException e) {
// no such property
}
return defaultValue;
}
private static synchronized void initialize() {
if (UNINITIALIZED) {
InputStream inputStream = null;
try {
ResourceFile propertiesFile =
Application.getModuleDataFile(CLAMP_PROPERTIES_FILENAME);
properties = new Properties();
inputStream = propertiesFile.getInputStream();
properties.load(inputStream);
}
catch (FileNotFoundException e) {
Msg.warn(ClampPropertiesLookup.class, "couldn't find clamp properties file");
}
catch (IOException e) {
Msg.warn(ClampPropertiesLookup.class, "IOException reading clamp properties file",
e);
}
finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
// yeah well we tried
}
}
}
UNINITIALIZED = false;
}
}
}

View File

@ -19,9 +19,8 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.ClampPropertiesLookup;
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
import ghidra.program.model.data.*;
import ghidra.util.NumericUtilities;
import ghidra.util.exception.DuplicateNameException;
/**
@ -78,34 +77,45 @@ public class SecurityCertificate implements StructConverter {
private short wCertificateType;
private byte [] bCertificate;
static SecurityCertificate createSecurityCertificate(
FactoryBundledWithBinaryReader reader, int index)
throws IOException {
SecurityCertificate securityCertificate = (SecurityCertificate) reader.getFactory().create(SecurityCertificate.class);
securityCertificate.initSecurityCertificate(reader, index);
return securityCertificate;
}
/**
* Read a SecurityCertificate.
*
* @param reader BinaryReader to use
* @param index offset where the SecurityCertificate starts
* @param sizeLimit maximum number of bytes that can be read from the reader
* @return new SecurityCertificate, or null if invalid or bad data
* @throws IOException if io error when reading data
*/
static SecurityCertificate read(BinaryReader reader, long index, int sizeLimit)
throws IOException {
if (sizeLimit < 8) {
return null;
}
reader = reader.clone(index);
SecurityCertificate result = new SecurityCertificate();
result.dwLength = reader.readNextInt();
result.wRevision = reader.readNextShort();
result.wCertificateType = reader.readNextShort();
if (result.dwLength < 8 || sizeLimit < result.dwLength) {
return null;
}
int certByteCount = result.dwLength - 4 - 2 - 2;
result.bCertificate = reader.readNextByteArray(certByteCount);
return result;
}
/**
* DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD.
*/
public SecurityCertificate() {}
private void initSecurityCertificate(FactoryBundledWithBinaryReader reader, int index) throws IOException {
int i = index;
int maxDwLength = (int) ClampPropertiesLookup.getClampValue("ghidra.app.util.bin.format.pe.SecurityCertificate.dwLength.max", 30000);
dwLength = reader.readInt (i, 8, maxDwLength); i += BinaryReader.SIZEOF_INT;
if (dwLength < 0) return;
wRevision = reader.readShort(i); i += BinaryReader.SIZEOF_SHORT;
wCertificateType = reader.readShort(i); i += BinaryReader.SIZEOF_SHORT;
bCertificate = reader.readByteArray(i, dwLength-4-2-2);
}
int getNumberOfBytesConsumed() {
return dwLength + BinaryReader.SIZEOF_INT +
2 * BinaryReader.SIZEOF_SHORT;
}
int getNumberOfBytesConsumed() {
return (int) NumericUtilities.getUnsignedAlignedValue(dwLength, 8);
}
/**
* Returns the length, in bytes, of the signature.
@ -166,7 +176,8 @@ public class SecurityCertificate implements StructConverter {
/**
* @see ghidra.app.util.bin.StructConverter#toDataType()
*/
public DataType toDataType() throws DuplicateNameException {
@Override
public DataType toDataType() throws DuplicateNameException {
StructureDataType struct = new StructureDataType(NAME+"_"+dwLength, 0);
struct.add(DWORD,"dwLength",null);
struct.add( WORD,"wRevision",null);

View File

@ -56,7 +56,9 @@ public class SecurityDataDirectory extends DataDirectory implements ByteArrayCon
private void initSecurityDataDirectory(NTHeader ntHeader, FactoryBundledWithBinaryReader reader) throws IOException {
processDataDirectory(ntHeader, reader);
if (certificates == null) certificates = new SecurityCertificate[0];
if (certificates == null) {
certificates = new SecurityCertificate[0];
}
}
/**
@ -99,7 +101,7 @@ public class SecurityDataDirectory extends DataDirectory implements ByteArrayCon
@Override
public boolean parse() throws IOException {
List<SecurityCertificate> list = new ArrayList<SecurityCertificate>();
List<SecurityCertificate> list = new ArrayList<>();
// Sanity check...
// Sometimes the cert address is not valid
@ -114,16 +116,21 @@ public class SecurityDataDirectory extends DataDirectory implements ByteArrayCon
int certOffset = getVirtualAddress();
int certSize = getSize();
if (certOffset + certSize > reader.length()) {
Msg.warn(this, "Certificate length " + certSize + " exceeds EOF.");
return false;
}
while (certSize > 0 && certSize < NTHeader.MAX_SANE_COUNT) {
SecurityCertificate cert = SecurityCertificate.createSecurityCertificate(reader, certOffset);
if (cert.getLength() < 0) {
SecurityCertificate cert = SecurityCertificate.read(reader, certOffset, certSize);
if (cert == null) {
return false;
}
list.add(cert);
certOffset += cert.getNumberOfBytesConsumed();
certSize -= cert.getNumberOfBytesConsumed();
int certBytesUsed = cert.getNumberOfBytesConsumed();
certOffset += certBytesUsed;
certSize -= certBytesUsed;
}
certificates = new SecurityCertificate[list.size()];
@ -147,6 +154,7 @@ public class SecurityDataDirectory extends DataDirectory implements ByteArrayCon
/**
* @see ghidra.app.util.bin.ByteArrayConverter#toBytes(ghidra.util.DataConverter)
*/
@Override
public byte [] toBytes(DataConverter dc) {
try {
return reader.readByteArray( virtualAddress, size );