mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Candidate release of source code.
This commit is contained in:
parent
db81e6b3b0
commit
79d8f164f8
12449 changed files with 2800756 additions and 16 deletions
147
Ghidra/Features/Base/ghidra_scripts/RecursiveStringFinder.py
Normal file
147
Ghidra/Features/Base/ghidra_scripts/RecursiveStringFinder.py
Normal file
|
@ -0,0 +1,147 @@
|
|||
#Given a function, find all strings used within all called funtions.
|
||||
# @category: Strings
|
||||
|
||||
# Handles only functions, not subroutines, as of now. Hopefully this will change later
|
||||
|
||||
import ghidra.app.script.GhidraScript
|
||||
import ghidra.program.model.data.StringDataType as StringDataType
|
||||
import exceptions
|
||||
|
||||
class Node:
|
||||
def __str__(self):
|
||||
raise NotImplementedError("Must sub-class")
|
||||
def indentedString(self, depth=0):
|
||||
raise NotImplementedError("")
|
||||
def __str__(self):
|
||||
return self.indentedString(depth=0)
|
||||
|
||||
class ReferenceNode(Node):
|
||||
def __init__(self, fromAddr, toAddr):
|
||||
self.fromAddr = fromAddr
|
||||
self.toAddr = toAddr
|
||||
def indentedString(self, depth=0):
|
||||
raise NotImplementedError("")
|
||||
|
||||
class StringNode(ReferenceNode):
|
||||
def __init__(self, fromAddr, toAddr, string):
|
||||
ReferenceNode.__init__(self, fromAddr, toAddr)
|
||||
self.string = string
|
||||
def __str__(self):
|
||||
return self.indentedString(depth=0)
|
||||
def indentedString(self, depth=0):
|
||||
string = "%s\n" % ( self.string)
|
||||
return string
|
||||
def hasString(self):
|
||||
return True
|
||||
|
||||
class FunctionNode(ReferenceNode):
|
||||
def __init__(self, fromAddr, toAddr):
|
||||
ReferenceNode.__init__(self, fromAddr, toAddr)
|
||||
self.fn = getFunctionContaining(toAddr)
|
||||
self.references = []
|
||||
def hasString(self):
|
||||
for r in self.references:
|
||||
if isinstance(r, StringNode) or r.hasString():
|
||||
return True
|
||||
return False
|
||||
def indentedString(self, depth=0):
|
||||
string = "%s()\n" % (self.fn.getName())
|
||||
for r in self.references:
|
||||
if r.hasString():
|
||||
string += "%s@%s - %s" % (" " * (depth+1), r.fromAddr, r.indentedString(depth=depth+1))
|
||||
return string
|
||||
def getAddresses(self):
|
||||
return self.fn.getBody().getAddresses(True)
|
||||
def addReference(self, reference):
|
||||
rlist = []
|
||||
if not isinstance(reference, list):
|
||||
rlist.append(reference)
|
||||
for r in rlist:
|
||||
if not isinstance(r, ReferenceNode):
|
||||
raise ValueError("Must only add ReferenceNode type")
|
||||
else:
|
||||
self.references.append(r)
|
||||
def getName(self):
|
||||
if self.fn is not None:
|
||||
return self.fn.getName()
|
||||
else:
|
||||
return "fun_%s" % (self.toAddr)
|
||||
def process(self, processed=[]):
|
||||
if self.fn is None:
|
||||
return processed
|
||||
print "Processing %s -> %s" % (str(self.fromAddr), str(self.toAddr))
|
||||
if self.getName() in processed:
|
||||
return processed
|
||||
addresses = self.getAddresses()
|
||||
print str(type(addresses))
|
||||
while addresses.hasNext():
|
||||
#for a in addresses:
|
||||
a = addresses.next()
|
||||
insn = getInstructionAt(a)
|
||||
if insn is not None:
|
||||
refs = getReferences(insn)
|
||||
for r in refs:
|
||||
self.addReference(r)
|
||||
|
||||
processed.append(self.getName())
|
||||
for r in self.references:
|
||||
if isinstance(r, FunctionNode):
|
||||
processed = r.process(processed=processed)
|
||||
return processed
|
||||
|
||||
class FunctionNotFoundException(exceptions.Exception):
|
||||
pass
|
||||
|
||||
def getStringAtAddr(addr):
|
||||
"""Get string at an address, if present"""
|
||||
data = getDataAt(addr)
|
||||
if data is not None:
|
||||
dt = data.getDataType()
|
||||
if isinstance(dt, StringDataType):
|
||||
return str(data)
|
||||
return None
|
||||
|
||||
def getStringReferences(insn):
|
||||
"""Get strings referenced in any/all operands of an instruction, if present"""
|
||||
numOperands = insn.getNumOperands()
|
||||
found = []
|
||||
for i in range(numOperands):
|
||||
opRefs = insn.getOperandReferences(i)
|
||||
for o in opRefs:
|
||||
if o.getReferenceType().isData():
|
||||
string = getStringAtAddr(o.getToAddress())
|
||||
if string is not None:
|
||||
found.append( StringNode(insn.getMinAddress(), o.getToAddress(), string) )
|
||||
return found
|
||||
|
||||
def getFunctionReferences(insn):
|
||||
"""Return a list of functions referenced in the given instruction"""
|
||||
numOperands = insn.getNumOperands()
|
||||
lst = []
|
||||
for i in range(numOperands):
|
||||
opRefs = insn.getOperandReferences(i)
|
||||
for o in opRefs:
|
||||
if o.getReferenceType().isCall():
|
||||
lst.append( FunctionNode(insn.getMinAddress(), o.getToAddress()) )
|
||||
return lst
|
||||
|
||||
def getReferences(insn):
|
||||
refs = []
|
||||
refs += getStringReferences(insn)
|
||||
refs += getFunctionReferences(insn)
|
||||
return refs
|
||||
|
||||
bigfunc = getFunctionContaining(currentAddress)
|
||||
if bigfunc is None:
|
||||
print "Please place the cursor within a function!"
|
||||
else:
|
||||
AddrSetView = bigfunc.getBody()
|
||||
func = FunctionNode(None, AddrSetView.getMinAddress())
|
||||
func.process()
|
||||
print str(func.indentedString())
|
||||
#findStrings(func)
|
||||
print "Done!"
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue