From f23fcf81a97059726ee91da62a58964403eeb13e Mon Sep 17 00:00:00 2001 From: Christian Blichmann Date: Thu, 4 Apr 2019 16:13:02 +0200 Subject: [PATCH 1/2] Add SHA256 hash to `Program` interface Implements the first part of #291 Signed-off-by: Christian Blichmann --- .../util/opinion/AbstractProgramLoader.java | 9 ++++++ .../ghidra/program/database/ProgramDB.java | 28 +++++++++++++++++-- .../ghidra/program/model/listing/Program.java | 12 ++++++++ .../program/model/ProgramTestDouble.java | 10 +++++++ .../ghidra/server/remote/ServerTestUtil.java | 12 ++++---- 5 files changed, 64 insertions(+), 7 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java index c4ac06b46a..8aeb2eff10 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java @@ -41,6 +41,7 @@ import ghidra.program.util.DefaultLanguageService; import ghidra.program.util.GhidraProgramUtilities; import ghidra.util.InvalidNameException; import ghidra.util.MD5Utilities; +import ghidra.util.HashUtilities; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -285,6 +286,8 @@ public abstract class AbstractProgramLoader implements Loader { } String md5 = computeBinaryMD5(provider); prog.setExecutableMD5(md5); + String sha256 = computeBinarySHA256(provider); + prog.setExecutableSHA256(sha256); if (shouldSetImageBase(prog, imageBase)) { try { @@ -465,6 +468,12 @@ public abstract class AbstractProgramLoader implements Loader { } } + private String computeBinarySHA256(ByteProvider provider) throws IOException { + try (InputStream in = provider.getInputStream(0)) { + return HashUtilities.getHash(HashUtilities.SHA256_ALGORITHM, in); + } + } + private boolean shouldSetImageBase(Program prog, Address imageBase) { if (imageBase == null || imageBase instanceof SegmentedAddress) { return false; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java index 1652471336..6a536dda2e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java @@ -128,6 +128,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM private static final String EXECUTABLE_PATH = "Executable Location"; private static final String EXECUTABLE_FORMAT = "Executable Format"; private static final String EXECUTABLE_MD5 = "Executable MD5"; + private static final String EXECUTABLE_SHA256 = "Executable SHA256"; private static final String TABLE_NAME = "Program"; private static final String EXECUTE_PATH = "Execute Path"; private static final String EXECUTE_FORMAT = "Execute Format"; @@ -716,7 +717,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM } /** - * * @see ghidra.program.model.listing.Program#setExecutableFormat(java.lang.String) */ @Override @@ -742,7 +742,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM } /** - * * @see ghidra.program.model.listing.Program#setExecutableMD5(java.lang.String) */ @Override @@ -752,6 +751,31 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM changed = true; } + /** + * @see ghidra.program.model.listing.Program#getExecutableSHA256() + */ + @Override + public String getExecutableSHA256() { + String format = null; + try { + Options pl = getOptions(PROGRAM_INFO); + format = pl.getString(EXECUTABLE_SHA256, (String) null); + } + catch (Exception e) { + } + return format == null ? UNKNOWN : format; + } + + /** + * @see ghidra.program.model.listing.Program#setExecutableSHA256(java.lang.String) + */ + @Override + public void setExecutableSHA256(String sha256) { + Options pl = getOptions(PROGRAM_INFO); + pl.setString(EXECUTABLE_SHA256, sha256); + changed = true; + } + /** * @see ghidra.program.model.listing.Program#getCreationDate() */ diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java index 0429b915da..ab99d72d18 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java @@ -190,6 +190,18 @@ public interface Program extends DataTypeManagerDomainObject { */ public void setExecutableMD5(String md5); + /** + * Sets the value corresponding to the original binary file SHA256 hash. + * @param sha256 SHA256 binary file hash + */ + public void setExecutableSHA256(String sha256); + + /** + * Returns a value corresponding to the original binary file SHA256 hash. + * May be null if program source did not correspond to a binary file. + */ + public String getExecutableSHA256(); + /** * Returns the creation date of this program. * If the program was created before this property diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/ProgramTestDouble.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/ProgramTestDouble.java index 662c10ac1b..fdbd8ed09a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/ProgramTestDouble.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/ProgramTestDouble.java @@ -406,6 +406,16 @@ public class ProgramTestDouble implements Program { throw new UnsupportedOperationException(); } + @Override + public String getExecutableSHA256() { + throw new UnsupportedOperationException(); + } + + @Override + public void setExecutableSHA256(String sha256) { + throw new UnsupportedOperationException(); + } + @Override public Date getCreationDate() { throw new UnsupportedOperationException(); diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java index f38f7db0c6..197627e482 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java @@ -786,7 +786,7 @@ public class ServerTestUtil { funcAddr += 2; } - setProgramMd5(program); + setProgramHashes(program); ContentHandler contentHandler = DomainObjectAdapter.getContentHandler(program); long checkoutId = contentHandler.createFile(repoFilesystem, null, folderPath, name, @@ -856,15 +856,17 @@ public class ServerTestUtil { } /** - * Sets a dummy MD5 value for the given program. - * + * Sets dummy hash values for the given program. + * * @param program the current program */ - private static void setProgramMd5(Program program) { - int id = program.startTransaction("setmd5"); + private static void setProgramHashes(Program program) { + int id = program.startTransaction("sethashes"); try { String md5 = RandomStringUtils.randomNumeric(32); program.setExecutableMD5(md5); + String sha256 = RandomStringUtils.randomNumeric(64); + program.setExecutableSHA256(sha256); } finally { program.endTransaction(id, true); From 69ceac93162aa0ae0dbe769bdc429519a0896803 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Fri, 12 Apr 2019 10:42:19 -0400 Subject: [PATCH 2/2] GT-2753: Formatted and certified Pulled-from: Christian Blichmann --- .../util/opinion/AbstractProgramLoader.java | 8 +++----- .../ghidra/program/model/listing/Program.java | 10 +++++----- .../program/model/ProgramTestDouble.java | 20 +++++++++---------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java index 8aeb2eff10..5a47708e43 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java @@ -39,9 +39,7 @@ import ghidra.program.model.symbol.*; import ghidra.program.model.util.AddressLabelInfo; import ghidra.program.util.DefaultLanguageService; import ghidra.program.util.GhidraProgramUtilities; -import ghidra.util.InvalidNameException; -import ghidra.util.MD5Utilities; -import ghidra.util.HashUtilities; +import ghidra.util.*; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -112,8 +110,8 @@ public abstract class AbstractProgramLoader implements Loader { return results; } - List programs = loadProgram(provider, name, folder, loadSpec, options, messageLog, - consumer, monitor); + List programs = + loadProgram(provider, name, folder, loadSpec, options, messageLog, consumer, monitor); boolean success = false; try { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java index ab99d72d18..efeb0afadf 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java @@ -102,7 +102,7 @@ public interface Program extends DataTypeManagerDomainObject { public SymbolTable getSymbolTable(); /** - + * Returns the external manager. */ public ExternalManager getExternalManager(); @@ -355,8 +355,8 @@ public interface Program extends DataTypeManagerDomainObject { * This will never be thrown if commit is false. * @throws IllegalStateException if the program state is not suitable for setting the image base. */ - public void setImageBase(Address base, boolean commit) throws AddressOverflowException, - LockException, IllegalStateException; + public void setImageBase(Address base, boolean commit) + throws AddressOverflowException, LockException, IllegalStateException; /** * Restores the last committed image base. @@ -377,8 +377,8 @@ public interface Program extends DataTypeManagerDomainObject { * @throws LockException if the program is shared and not checked out exclusively. */ public void setLanguage(Language language, CompilerSpecID compilerSpecID, - boolean forceRedisassembly, TaskMonitor monitor) throws IllegalStateException, - IncompatibleLanguageException, LockException; + boolean forceRedisassembly, TaskMonitor monitor) + throws IllegalStateException, IncompatibleLanguageException, LockException; /** * Returns the global namespace for this program diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/ProgramTestDouble.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/ProgramTestDouble.java index fdbd8ed09a..79fb37a1ef 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/ProgramTestDouble.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/ProgramTestDouble.java @@ -15,6 +15,10 @@ */ package ghidra.program.model; +import java.io.File; +import java.io.IOException; +import java.util.*; + import ghidra.framework.model.*; import ghidra.framework.options.Options; import ghidra.framework.store.LockException; @@ -34,10 +38,6 @@ import ghidra.util.exception.CancelledException; import ghidra.util.exception.DuplicateNameException; import ghidra.util.task.TaskMonitor; -import java.io.File; -import java.io.IOException; -import java.util.*; - public class ProgramTestDouble implements Program { @Override @@ -111,8 +111,8 @@ public class ProgramTestDouble implements Program { } @Override - public void saveToPackedFile(File outputFile, TaskMonitor monitor) throws IOException, - CancelledException { + public void saveToPackedFile(File outputFile, TaskMonitor monitor) + throws IOException, CancelledException { throw new UnsupportedOperationException(); } @@ -517,8 +517,8 @@ public class ProgramTestDouble implements Program { } @Override - public void setImageBase(Address base, boolean commit) throws AddressOverflowException, - LockException, IllegalStateException { + public void setImageBase(Address base, boolean commit) + throws AddressOverflowException, LockException, IllegalStateException { throw new UnsupportedOperationException(); } @@ -529,8 +529,8 @@ public class ProgramTestDouble implements Program { @Override public void setLanguage(Language language, CompilerSpecID compilerSpecID, - boolean forceRedisassembly, TaskMonitor monitor) throws IllegalStateException, - IncompatibleLanguageException, LockException { + boolean forceRedisassembly, TaskMonitor monitor) + throws IllegalStateException, IncompatibleLanguageException, LockException { throw new UnsupportedOperationException(); }