mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-27 06:32:10 +00:00
GT-3409 MDMang MD5-hashed symbols
This commit is contained in:
parent
9ad7c6843f
commit
1c1cd58eb9
@ -480,6 +480,17 @@ public class MDMang {
|
||||
public MDObjectCPP getEmbeddedObject(MDObjectCPP obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is meant to be overridden as needed to process a hashed
|
||||
* object. In this default case (MDMang), we properly process the
|
||||
* hashed object. Overridden methods might just throw an exception,
|
||||
* allowing a failed demangling.
|
||||
*/
|
||||
public void processHashedObject(MDObjectCPP obj) throws MDException {
|
||||
obj.processHashedObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -46,10 +46,6 @@ public class MDMangGhidra extends MDMang {
|
||||
return dataTypeResult;
|
||||
}
|
||||
|
||||
private DemangledType processNamespace(MDQualifiedBasicName qualifiedBasicName) {
|
||||
return processNamespace(qualifiedBasicName.getQualification());
|
||||
}
|
||||
|
||||
public DemangledType processNamespace(MDQualifiedName qualifiedName) {
|
||||
return processNamespace(qualifiedName.getQualification());
|
||||
}
|
||||
@ -183,8 +179,8 @@ public class MDMangGhidra extends MDMang {
|
||||
}
|
||||
else {
|
||||
variable = new DemangledVariable(
|
||||
objectCPP.getQualifiedName().getBasicName().toString());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualifiedName()));
|
||||
objectCPP.getName());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualfication()));
|
||||
}
|
||||
variable.setDatatype(dt);
|
||||
resultObject = variable;
|
||||
@ -204,8 +200,8 @@ public class MDMangGhidra extends MDMang {
|
||||
}
|
||||
else if (typeinfo instanceof MDFunctionInfo) {
|
||||
DemangledFunction function =
|
||||
new DemangledFunction(objectCPP.getQualifiedName().getBasicName().toString());
|
||||
function.setNamespace(processNamespace(objectCPP.getQualifiedName()));
|
||||
new DemangledFunction(objectCPP.getName());
|
||||
function.setNamespace(processNamespace(objectCPP.getQualfication()));
|
||||
resultObject = function;
|
||||
objectResult = processFunction((MDFunctionInfo) typeinfo, function);
|
||||
// Any other special values to be set?
|
||||
@ -233,8 +229,8 @@ public class MDMangGhidra extends MDMang {
|
||||
else if (typeinfo instanceof MDVxTable) { //Includes VFTable, VBTable, and RTTI4
|
||||
MDVxTable vxtable = (MDVxTable) typeinfo;
|
||||
DemangledVariable variable =
|
||||
new DemangledVariable(objectCPP.getQualifiedName().getBasicName().toString());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualifiedName()));
|
||||
new DemangledVariable(objectCPP.getName());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualfication()));
|
||||
variable.setConst(vxtable.isConst());
|
||||
variable.setVolatile(vxtable.isVolatile());
|
||||
variable.setPointer64(vxtable.isPointer64());
|
||||
@ -245,8 +241,8 @@ public class MDMangGhidra extends MDMang {
|
||||
}
|
||||
else if (typeinfo instanceof AbstractMDMetaClass) { //Includes all RTTI, except RTTI4
|
||||
DemangledVariable variable =
|
||||
new DemangledVariable(objectCPP.getQualifiedName().getBasicName().toString());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualifiedName()));
|
||||
new DemangledVariable(objectCPP.getName());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualfication()));
|
||||
resultObject = variable;
|
||||
// The following code would be an alternative, depending on whether we get
|
||||
// customer complaints or other fall-out from having created a variable here.
|
||||
@ -254,8 +250,8 @@ public class MDMangGhidra extends MDMang {
|
||||
}
|
||||
else if (typeinfo instanceof MDGuard) {
|
||||
DemangledVariable variable =
|
||||
new DemangledVariable(objectCPP.getQualifiedName().getBasicName().toString());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualifiedName()));
|
||||
new DemangledVariable(objectCPP.getName());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualfication()));
|
||||
resultObject = variable;
|
||||
// The following code would be an alternative, depending on whether we get
|
||||
// customer complaints or other fall-out from having created a variable here.
|
||||
@ -264,8 +260,8 @@ public class MDMangGhidra extends MDMang {
|
||||
else {
|
||||
// Any others (e.g., case '9')
|
||||
DemangledVariable variable =
|
||||
new DemangledVariable(objectCPP.getQualifiedName().getBasicName().toString());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualifiedName()));
|
||||
new DemangledVariable(objectCPP.getName());
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualfication()));
|
||||
resultObject = variable;
|
||||
// The following code would be an alternative, depending on whether we get
|
||||
// customer complaints or other fall-out from having created a variable here.
|
||||
@ -288,9 +284,9 @@ public class MDMangGhidra extends MDMang {
|
||||
}
|
||||
}
|
||||
else {
|
||||
String baseName = objectCPP.getQualifiedName().getBasicName().toString();
|
||||
if (objectCPP.getQualifiedName().isString()) {
|
||||
MDString mstring = objectCPP.getQualifiedName().getBasicName().getMDString();
|
||||
String baseName = objectCPP.getName();
|
||||
if (objectCPP.isString()) {
|
||||
MDString mstring = objectCPP.getMDString();
|
||||
DemangledString demangledString = new DemangledString(mstring.getName(),
|
||||
mstring.toString(), mstring.getLength(), mstring.isUnicode());
|
||||
resultObject = demangledString;
|
||||
@ -298,7 +294,7 @@ public class MDMangGhidra extends MDMang {
|
||||
else if (baseName.length() != 0) {
|
||||
DemangledVariable variable;
|
||||
variable = new DemangledVariable(baseName);
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualifiedName()));
|
||||
variable.setNamespace(processNamespace(objectCPP.getQualfication()));
|
||||
resultObject = variable;
|
||||
}
|
||||
}
|
||||
@ -803,13 +799,10 @@ public class MDMangGhidra extends MDMang {
|
||||
|
||||
@Override
|
||||
public MDObjectCPP getEmbeddedObject(MDObjectCPP obj) {
|
||||
MDObjectCPP embedded = obj.getQualifiedName().getBasicName().getEmbeddedObject();
|
||||
if (embedded != null) {
|
||||
return embedded;
|
||||
}
|
||||
return obj;
|
||||
return obj.getEmbeddedObject();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -111,6 +111,12 @@ public class MDMangVS2015 extends MDMang {
|
||||
public MDObjectCPP getEmbeddedObject(MDObjectCPP obj) {
|
||||
return obj.getEmbeddedObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processHashedObject(MDObjectCPP obj) throws MDException {
|
||||
obj.processHashedObjectMSVC();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -61,6 +61,10 @@ public class MDQualifiedBasicName extends MDParsableItem {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the symbol's Basic Name is of a {@link MDString} type.
|
||||
* @return {@code true} if Basic Name is of {@link MDString} type.
|
||||
*/
|
||||
public boolean isString() {
|
||||
if (basicName == null) {
|
||||
return false;
|
||||
@ -68,6 +72,18 @@ public class MDQualifiedBasicName extends MDParsableItem {
|
||||
return basicName.isString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MDString} from the Basic Name if it is a symbol of that type; else
|
||||
* returns null.
|
||||
* @return the {@link MDString} or null if does not exist.
|
||||
*/
|
||||
public MDString getMDString() {
|
||||
if (isString()) {
|
||||
return basicName.getMDString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(StringBuilder builder) {
|
||||
basicName.insert(builder);
|
||||
|
@ -15,10 +15,8 @@
|
||||
*/
|
||||
package mdemangler.object;
|
||||
|
||||
import mdemangler.MDException;
|
||||
import mdemangler.MDMang;
|
||||
import mdemangler.naming.MDBasicName;
|
||||
import mdemangler.naming.MDQualifiedBasicName;
|
||||
import mdemangler.*;
|
||||
import mdemangler.naming.*;
|
||||
import mdemangler.typeinfo.MDTypeInfo;
|
||||
import mdemangler.typeinfo.MDTypeInfoParser;
|
||||
|
||||
@ -26,9 +24,11 @@ import mdemangler.typeinfo.MDTypeInfoParser;
|
||||
* This class represents a derivative of an <b><code>MDObject</code></b> which is a C++ object.
|
||||
*/
|
||||
public class MDObjectCPP extends MDObject {
|
||||
protected MDHashedObject hashedObject;
|
||||
protected MDQualifiedBasicName qualifiedName;
|
||||
protected MDTypeInfo typeInfo;
|
||||
protected boolean embeddedObjectFlag;
|
||||
protected boolean hashedObjectFlag;
|
||||
|
||||
public MDObjectCPP(MDMang dmang) {
|
||||
super(dmang);
|
||||
@ -49,16 +49,66 @@ public class MDObjectCPP extends MDObject {
|
||||
*/
|
||||
public MDObjectCPP getEmbeddedObject() {
|
||||
if (embeddedObjectFlag) {
|
||||
return getQualifiedName().getBasicName().getEmbeddedObject();
|
||||
return qualifiedName.getBasicName().getEmbeddedObject();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the symbol, minus any namespace component.
|
||||
* @return the name.
|
||||
*/
|
||||
public String getName() {
|
||||
if (hashedObjectFlag) {
|
||||
return hashedObject.toString();
|
||||
}
|
||||
return getQualifiedName().getBasicName().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MDQualification} component that represents the namespace.
|
||||
* @return the namespace information.
|
||||
*/
|
||||
public MDQualification getQualfication() {
|
||||
if (hashedObjectFlag) {
|
||||
return hashedObject.getQualification();
|
||||
}
|
||||
return getQualifiedName().getQualification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the symbol's Basic Name is of a {@link MDString} type.
|
||||
* @return {@code true} if Basic Name is of {@link MDString} type.
|
||||
*/
|
||||
public boolean isString() {
|
||||
if (qualifiedName == null) {
|
||||
return false;
|
||||
}
|
||||
return qualifiedName.isString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MDString} from the Basic Name if it is a symbol of that type; else
|
||||
* returns null.
|
||||
* @return the {@link MDString} or null if does not exist.
|
||||
*/
|
||||
public MDString getMDString() {
|
||||
if (isString()) {
|
||||
return qualifiedName.getMDString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(StringBuilder builder) {
|
||||
qualifiedName.insert(builder);
|
||||
if (typeInfo != null) {
|
||||
typeInfo.insert(builder);
|
||||
if (hashedObjectFlag) {
|
||||
hashedObject.insert(builder);
|
||||
}
|
||||
else {
|
||||
qualifiedName.insert(builder);
|
||||
if (typeInfo != null) {
|
||||
typeInfo.insert(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,23 +121,123 @@ public class MDObjectCPP extends MDObject {
|
||||
if ((dmang.peek(0) == '?') && (dmang.peek(1) == '?')) { //??? prefix
|
||||
embeddedObjectFlag = true;
|
||||
}
|
||||
qualifiedName = new MDQualifiedBasicName(dmang);
|
||||
qualifiedName.parse();
|
||||
if (qualifiedName.isString()) {
|
||||
return;
|
||||
|
||||
if ((dmang.peek(0) == '?') && (dmang.peek(1) == '@')) { //??@ prefix
|
||||
// MDMANG SPECIALIZATION USED.
|
||||
dmang.processHashedObject(this);
|
||||
}
|
||||
if (dmang.peek() != MDMang.DONE) {
|
||||
int RTTINum = qualifiedName.getRTTINumber();
|
||||
typeInfo = MDTypeInfoParser.parse(dmang, RTTINum);
|
||||
if (qualifiedName.isTypeCast()) {
|
||||
typeInfo.setTypeCast();
|
||||
else {
|
||||
qualifiedName = new MDQualifiedBasicName(dmang);
|
||||
qualifiedName.parse();
|
||||
if (qualifiedName.isString()) {
|
||||
return;
|
||||
}
|
||||
typeInfo.parse();
|
||||
if (!typeInfo.getNameModifier().isEmpty()) {
|
||||
qualifiedName.setNameModifier(typeInfo.getNameModifier());
|
||||
if (dmang.peek() != MDMang.DONE) {
|
||||
int RTTINum = qualifiedName.getRTTINumber();
|
||||
typeInfo = MDTypeInfoParser.parse(dmang, RTTINum);
|
||||
if (qualifiedName.isTypeCast()) {
|
||||
typeInfo.setTypeCast();
|
||||
}
|
||||
typeInfo.parse();
|
||||
if (!typeInfo.getNameModifier().isEmpty()) {
|
||||
qualifiedName.setNameModifier(typeInfo.getNameModifier());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processHashedObject() throws MDException {
|
||||
hashedObject = new MDHashedObject(dmang);
|
||||
hashedObject.parse();
|
||||
hashedObjectFlag = true;
|
||||
}
|
||||
|
||||
public void processHashedObjectMSVC() throws MDException {
|
||||
throw new MDException("cannot parse hashed symbol");
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the MD5 hashed representation of the internals of the {@link MDObjectCPP}.
|
||||
* It takes the place of the {@link MDQualifiedBasicName}. We have included an unused
|
||||
* (except to be able to return one that is empty) {@link MDQualification} so that the
|
||||
* {@link MDObjectCPP} has one to return.
|
||||
* <p>
|
||||
* Not sure that we will keep this class in the long run or find a way to include it
|
||||
* inside of the {@link MDObjectCPP} or if this {@link MDHashedObject} should be pulled
|
||||
* out separately and detected/parsed by the {@link MDMangObjectParser}. If this last
|
||||
* thing is done, then we would have to find places in the package where we explicitly
|
||||
* create {@link MDObjectCPP MDObjectCPPs}, such as in {@link MDNestedName}, and check to
|
||||
* see if we can modify those locations (in all cases) to perform the detecting/parsing
|
||||
* using the {@link MDMangObjectParser}. This will need more study when more time is
|
||||
* available.
|
||||
*/
|
||||
public class MDHashedObject extends MDParsableItem {
|
||||
private String hashString = "";
|
||||
private MDQualification qualification; // We are making this dummy object
|
||||
|
||||
/**
|
||||
* Constructor for {@link MDHashedObject}
|
||||
* @param dmang The {@link MDMang} for which the work is performed and from from which
|
||||
* the information is parsed.
|
||||
*/
|
||||
public MDHashedObject(MDMang dmang) {
|
||||
super(dmang);
|
||||
qualification = new MDQualification(dmang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hashed string.
|
||||
* @return the hashed string.
|
||||
*/
|
||||
public String getHashString() {
|
||||
return hashString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty {@link MDQualification} that represents the namespace of the symbol.
|
||||
* Note: we have yet to decide whether we should do anything but this.
|
||||
* @return the namespace information (empty for now).
|
||||
*/
|
||||
public MDQualification getQualification() {
|
||||
return qualification;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
|
||||
if ((dmang.peek() != '?') && (dmang.peek(1) != '@')) {
|
||||
throw new MDException("Invalid HashedObject");
|
||||
}
|
||||
dmang.increment(2);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
char ch;
|
||||
int start = dmang.getIndex();
|
||||
while ((ch = dmang.peek()) != MDMang.DONE) {
|
||||
if (ch == '@') {
|
||||
break;
|
||||
}
|
||||
if (!(Character.isLetter(ch) || Character.isDigit(ch))) {
|
||||
break;
|
||||
}
|
||||
builder.append(ch);
|
||||
dmang.next();
|
||||
}
|
||||
int end = dmang.getIndex();
|
||||
if ((end - start) != 32 || ch != '@') {
|
||||
throw new MDException("Invalid HashedObject");
|
||||
}
|
||||
dmang.increment();
|
||||
hashString = builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(StringBuilder builder) {
|
||||
// We have made up the output format. Nothing is sacrosanct about this output.
|
||||
builder.append("`" + hashString + "'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -14472,6 +14472,26 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
//Issue 1344: Long symbols get MD5-hashed.
|
||||
// We have made up the output format. Nothing is sacrosanct about this output.
|
||||
@Test
|
||||
public void testHashedSymbolComponentsLongerThan5096_1() throws Exception {
|
||||
mangled = "??@f4873c94f485cd6716c2319fc51ac714@";
|
||||
msTruth = "";
|
||||
mdTruth = "`f4873c94f485cd6716c2319fc51ac714'";
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
//Issue 1344: Long symbols get MD5-hashed.
|
||||
// We have made up the output format. Nothing is sacrosanct about this output.
|
||||
@Test
|
||||
public void testHashedSymbolComponentsLongerThan5096_2() throws Exception {
|
||||
mangled = "?catch$0@?0???@f4873c94f485cd6716c2319fc51ac714@@4HA";
|
||||
msTruth = "";
|
||||
mdTruth = "int ``f4873c94f485cd6716c2319fc51ac714''::`1'::catch$0";
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
//TODO: ignore for now.
|
||||
@Ignore
|
||||
public void testFuzzyFit() throws Exception {
|
||||
|
Loading…
Reference in New Issue
Block a user