Skip to content

Instantly share code, notes, and snippets.

@vbe0201
Last active November 4, 2021 22:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vbe0201/acabc5c6dfc65b0ad0f44a9947d84a45 to your computer and use it in GitHub Desktop.
Save vbe0201/acabc5c6dfc65b0ad0f44a9947d84a45 to your computer and use it in GitHub Desktop.
Ghidra script that finds unique signature patterns for selected functions
# Finds unique signature patterns for selected functions
# @author Valentin B.
# @category Binary
from itertools import chain
from ghidra.program.model.lang import OperandType
def getSelectedFunction():
if currentSelection:
for addr in chain.from_iterable(currentSelection):
func = getFunctionContaining(addr)
if func is not None:
return func
else:
return getFunctionContaining(currentAddress)
def isPatternUnique(pattern):
# If more than one match for the pattern exists, it is not unique.
return len(findBytes(None, pattern, 2)) == 1
# Modify this function if a custom pattern style is desired.
# The `pattern` input contains `.` for unknown/wildcard bytes and `\\xab` for static bytes.
def formatPattern(pattern):
pattern = pattern.replace(".", " ?? ")
return " ".join(pattern.split("\\x")).replace(" ", " ").strip()
def main():
func = getSelectedFunction()
if not func:
raise RuntimeError("Please select a function with your cursor first")
func_body = func.getBody()
function_start_addr = func_body.getMinAddress()
function_end_addr = func_body.getMaxAddress().next() # Inclusive end.
print(
"Finding unique signature for %s (%s)"
% (func.getName(), func.getSignature().getPrototypeString())
)
found = False
pattern = ""
addr = function_start_addr
while not monitor.isCancelled() and addr != function_end_addr:
insn = getInstructionAt(addr)
if insn:
insn_bytes = insn.getBytes()
for i in range(len(insn_bytes)):
# If the operand is dynamic, we use a wildcard pattern instead of a concrete byte.
if insn.getOperandType(i) & OperandType.DYNAMIC != 0:
pattern += "."
else:
pattern += "\\x%02x" % (insn_bytes[i] & 0xFF)
# Check if we already have a unique signature.
if isPatternUnique(pattern):
found = True
break
if found:
break
addr = addr.next()
if not found:
raise RuntimeError("Failed to find unique signature pattern")
if not monitor.isCancelled():
# Print out the result only if the script was not cancelled.
print("Found signature pattern: %s" % formatPattern(pattern))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment