mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +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
|
@ -0,0 +1,16 @@
|
|||
# Adds a comment to a program.
|
||||
|
||||
# DISCLAIMER: This is a recreation of a Java Ghidra script for example
|
||||
# use only. Please run the Java version in a production environment.
|
||||
|
||||
#@category Examples.Python
|
||||
|
||||
|
||||
from ghidra.program.model.address.Address import *
|
||||
from ghidra.program.model.listing.CodeUnit import *
|
||||
from ghidra.program.model.listing.Listing import *
|
||||
|
||||
minAddress = currentProgram.getMinAddress()
|
||||
listing = currentProgram.getListing()
|
||||
codeUnit = listing.getCodeUnitAt(minAddress)
|
||||
codeUnit.setComment(codeUnit.PLATE_COMMENT, "AddCommentToProgramScript - This is an added comment!")
|
90
Ghidra/Features/Python/ghidra_scripts/AskScriptPy.py
Normal file
90
Ghidra/Features/Python/ghidra_scripts/AskScriptPy.py
Normal file
|
@ -0,0 +1,90 @@
|
|||
# An example of asking for user input.
|
||||
|
||||
# Note the ability to pre-populate values for some of these variables when AskScript.properties file exists.
|
||||
# Also notice how the previous input is saved.
|
||||
|
||||
# DISCLAIMER: This is a recreation of a Java Ghidra script for example
|
||||
# use only. Please run the Java version in a production environment.
|
||||
|
||||
#@category Examples.Python
|
||||
|
||||
from ghidra.framework.model import DomainFile
|
||||
from ghidra.framework.model import DomainFolder
|
||||
from ghidra.program.model.address import Address
|
||||
from ghidra.program.model.lang import LanguageCompilerSpecPair
|
||||
from ghidra.program.model.listing import Program
|
||||
from ghidra.util import Msg
|
||||
|
||||
from java.lang import IllegalArgumentException
|
||||
|
||||
# The presence of the AskScript.properties file in the same location (as AskScript.java)
|
||||
# allows for the following behavior:
|
||||
# - GUI: if applicable, auto-populates the input field with the value in the
|
||||
# .properties file (the first time that input field appears)
|
||||
# - Headless: uses the value in the .properties file for the variable assigned to the
|
||||
# corresponding askXxx() method in the GhidraScript.
|
||||
try:
|
||||
file1 = askFile("FILE", "Choose file:")
|
||||
print "file was: " + str(file1)
|
||||
|
||||
directory1 = askDirectory("Directory", "Choose directory:")
|
||||
print "directory was: " + str(directory1)
|
||||
|
||||
lang = askLanguage("Language Picker", "I want this one!")
|
||||
print "language was: " + lang.toString()
|
||||
|
||||
domFolder = askProjectFolder("Please pick a domain folder!")
|
||||
print "domFolder was: " + domFolder.getName()
|
||||
|
||||
int1 = askInt("integer 1", "enter integer 1")
|
||||
int2 = askInt("integer 2", "enter integer 2")
|
||||
print "int1 + int2 = " + str(int1 + int2)
|
||||
|
||||
long1 = askLong("long 1", "enter long 1")
|
||||
long2 = askLong("long 2", "enter long 2")
|
||||
print "long1 + long2 = " + str(long1 + long2)
|
||||
|
||||
address1 = askAddress("address 1", "enter address 1")
|
||||
address2 = askAddress("address 2", "enter address 2")
|
||||
print "address1 + address2 = " + address1.add(address2.getOffset()).toString()
|
||||
|
||||
#bytes = askBytes("bytes", "enter byte pattern")
|
||||
#for b in bytes:
|
||||
# print "b = " + str(b & 0xff)
|
||||
|
||||
prog = askProgram("Please choose a program to open.")
|
||||
print "Program picked: " + prog.getName()
|
||||
|
||||
domFile = askDomainFile("Which domain file would you like?")
|
||||
print "Domain file: " + domFile.getName()
|
||||
|
||||
d1 = askDouble("double 1", "enter double 1")
|
||||
d2 = askDouble("double 2", "enter double 2")
|
||||
print "d1 + d2 = " + str(d1 + d2)
|
||||
|
||||
myStr = askString("String Specification", "Please type a string: ")
|
||||
myOtherStr = askString("Another String Specification", "Please type another string: ", "replace me!")
|
||||
print "You typed: " + myStr + " and " + myOtherStr
|
||||
|
||||
choice = askChoice("Choice", "Please choose one", [ "grumpy", "dopey", "sleepy", "doc", "bashful" ], "bashful")
|
||||
print "Choice? " + choice
|
||||
|
||||
choices1 = askChoices("Choices 1", "Please choose one or more numbers.", [ 1, 2, 3, 4, 5, 6 ])
|
||||
print "Choices 1: "
|
||||
for intChoice in choices1:
|
||||
print str(intChoice) + " "
|
||||
print ""
|
||||
|
||||
choices2 = askChoices("Choices 2", "Please choose one or more of the following.",
|
||||
[ 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 ], ["Part 1", "Part 2", "Part 3", "Part 4", "Part 5", "Part 6" ])
|
||||
print "Choices 2: "
|
||||
for intChoice in choices2:
|
||||
print str(intChoice) + " "
|
||||
print ""
|
||||
|
||||
yesOrNo = askYesNo("yes or no", "is this a yes/no question?")
|
||||
print "Yes or No? " + str(yesOrNo)
|
||||
|
||||
except IllegalArgumentException as error:
|
||||
Msg.warn(self, "Error during headless processing: " + error.toString())
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
# Shows how to run a script on all of the programs within the current project.
|
||||
|
||||
# DISCLAIMER: This is a recreation of a Java Ghidra script for example
|
||||
# use only. Please run the Java version in a production environment.
|
||||
|
||||
# NOTE: Script will only process unversioned and checked-out files.
|
||||
|
||||
#@category Examples.Python
|
||||
|
||||
from ghidra.app.script import GhidraState
|
||||
from ghidra.framework.model import *
|
||||
from ghidra.program.database import ProgramContentHandler
|
||||
from ghidra.program.model.listing import Program
|
||||
from ghidra.util.exception import CancelledException
|
||||
from ghidra.util.exception import VersionException
|
||||
|
||||
from java.io import IOException
|
||||
|
||||
# The script referenced in the following line should be replaced with the script to be called
|
||||
SUBSCRIPT_NAME = "AddCommentToProgramScript.java"
|
||||
|
||||
def recurseProjectFolder(domainFolder):
|
||||
files = domainFolder.getFiles()
|
||||
for domainFile in files:
|
||||
processDomainFile(domainFile)
|
||||
folders = domainFolder.getFolders()
|
||||
for folder in folders:
|
||||
recurseProjectFolder(folder)
|
||||
|
||||
def processDomainFile(domainFile):
|
||||
if not ProgramContentHandler.PROGRAM_CONTENT_TYPE == domainFile.getContentType():
|
||||
return # skip non-Program files
|
||||
if domainFile.isVersioned() and not domainFile.isCheckedOut():
|
||||
println("WARNING! Skipping versioned file - not checked-out: " + domainFile.getPathname())
|
||||
program = None
|
||||
consumer = java.lang.Object()
|
||||
try:
|
||||
program = domainFile.getDomainObject(consumer, True, False, monitor)
|
||||
processProgram(program)
|
||||
|
||||
except VersionException:
|
||||
println("ERROR! Failed to process file due to upgrade issue: " + domainFile.getPathname())
|
||||
|
||||
finally:
|
||||
if program is not None:
|
||||
program.release(consumer)
|
||||
|
||||
def processProgram(program):
|
||||
"""Do you program work here """
|
||||
println("Processing: " + program.getDomainFile().getPathname())
|
||||
monitor.setMessage("Processing: " + program.getDomainFile().getName())
|
||||
id = program.startTransaction("Batch Script Transaction")
|
||||
try:
|
||||
newState = GhidraState(state.getTool(), state.getProject(), program, None, None, None)
|
||||
runScript(SUBSCRIPT_NAME, newState)
|
||||
|
||||
except Exception:
|
||||
printerr("ERROR! Exception occurred while processing file: " + program.getDomainFile().getPathname())
|
||||
printerr(" " + Exception.getMessage())
|
||||
e.printStackTrace()
|
||||
|
||||
finally:
|
||||
program.endTransaction(id, True)
|
||||
|
||||
# ...save any changes
|
||||
program.save("Changes made by script: " + SUBSCRIPT_NAME, monitor)
|
||||
|
||||
if currentProgram is not None:
|
||||
popup("This script should be run from a tool with no open programs")
|
||||
exit()
|
||||
|
||||
project = state.getProject()
|
||||
projectData = project.getProjectData()
|
||||
rootFolder = projectData.getRootFolder()
|
||||
recurseProjectFolder(rootFolder)
|
|
@ -0,0 +1,9 @@
|
|||
# Example of a script calling another script.
|
||||
|
||||
# DISCLAIMER: This is a recreation of a Java Ghidra script for example
|
||||
# use only. Please run the Java version in a production environment.
|
||||
|
||||
#@category Examples.Python
|
||||
|
||||
runScript("HelloWorldScript.java")
|
||||
runScript("HelloWorldPopupScript.java")
|
|
@ -0,0 +1,21 @@
|
|||
# Example of a script prompting the user for a data type.
|
||||
|
||||
# DISCLAIMER: This is a recreation of a Java Ghidra script for example
|
||||
# use only. Please run the Java version in a production environment.
|
||||
|
||||
#@category Examples.Python
|
||||
|
||||
from ghidra.app.util.datatype import DataTypeSelectionDialog
|
||||
from ghidra.framework.plugintool import PluginTool
|
||||
from ghidra.program.model.data import DataType
|
||||
from ghidra.program.model.data import DataTypeManager
|
||||
from ghidra.util.data.DataTypeParser import AllowedDataTypes
|
||||
|
||||
|
||||
tool = state.getTool()
|
||||
dtm = currentProgram.getDataTypeManager()
|
||||
selectionDialog = DataTypeSelectionDialog(tool, dtm, -1, AllowedDataTypes.FIXED_LENGTH)
|
||||
tool.showDialog(selectionDialog)
|
||||
dataType = selectionDialog.getUserChosenDataType()
|
||||
if dataType is not None:
|
||||
print "Chosen data type: " + str(dataType)
|
|
@ -0,0 +1,33 @@
|
|||
# An example of how to color the listing background
|
||||
|
||||
# DISCLAIMER: This is a recreation of a Java Ghidra script for example
|
||||
# use only. Please run the Java version in a production environment.
|
||||
|
||||
#@category Examples.Python
|
||||
|
||||
from ghidra.app.plugin.core.colorizer import ColorizingService
|
||||
from ghidra.app.script import GhidraScript
|
||||
from ghidra.program.model.address import Address
|
||||
from ghidra.program.model.address import AddressSet
|
||||
|
||||
from java.awt import Color
|
||||
|
||||
service = state.getTool().getService(ColorizingService)
|
||||
if service is None:
|
||||
print "Can't find ColorizingService service"
|
||||
if currentSelection is not None:
|
||||
service.setBackgroundColor(currentSelection, Color(255, 200, 200))
|
||||
elif currentAddress is not None:
|
||||
service.setBackgroundColor(currentAddress, currentAddress, Color(255, 200, 200))
|
||||
else:
|
||||
print "No selection or current address to color"
|
||||
|
||||
anotherAddress = currentAddress.add(10)
|
||||
setBackgroundColor(anotherAddress, Color.YELLOW)
|
||||
|
||||
# create an address set with values you want to change
|
||||
addresses = AddressSet()
|
||||
addresses.add(currentAddress.add(10))
|
||||
addresses.add(currentAddress.add(11))
|
||||
addresses.add(currentAddress.add(12))
|
||||
setBackgroundColor(addresses, Color(100, 100, 200))
|
|
@ -0,0 +1,28 @@
|
|||
# An example using the Python string formatting.
|
||||
# See FormatExampleScript.java for examples of using the printf() method.
|
||||
|
||||
# DISCLAIMER: This is a recreation of a Java Ghidra script for example
|
||||
# use only. Please run the Java version in a production environment.
|
||||
|
||||
#@category Examples.Python
|
||||
|
||||
from time import *
|
||||
import java.util.Calendar
|
||||
|
||||
print "The %s jumped over the %s" % ("cow", "moon")
|
||||
|
||||
print "The %s jumped over the %s " % ("cow", "moon") + strftime("%X")
|
||||
|
||||
print "The %s jumped over the %s - timestamp: %s" % ("cow", "moon", strftime("%c %Z"))
|
||||
|
||||
print "The %s jumped over the %s at %s on %s" % ("cow", "moon", strftime("%I:%M%p"), strftime("%A, %b %d"))
|
||||
|
||||
print "Padding: %03d" % (1)
|
||||
|
||||
print "Hex: 0x%x" % (10)
|
||||
|
||||
print "Left-justified: %-10d" % (1)
|
||||
print "Right-justified: %10d" % (1)
|
||||
|
||||
print "String fill: '%10s'" % ("Fill")
|
||||
print "String fill, left justified: '%-10s'" % ("Fill")
|
11
Ghidra/Features/Python/ghidra_scripts/ImportSymbolsScript.py
Normal file
11
Ghidra/Features/Python/ghidra_scripts/ImportSymbolsScript.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
#Imports a file with lines in the form "symbolName 0xADDRESS"
|
||||
#@category Data
|
||||
#@author
|
||||
|
||||
f = askFile("Give me a file to open", "Go baby go!")
|
||||
|
||||
for line in file(f.absolutePath): # note, cannot use open(), since that is in GhidraScript
|
||||
pieces = line.split()
|
||||
address = toAddr(long(pieces[1], 16))
|
||||
print "creating symbol", pieces[0], "at address", address
|
||||
createLabel(address, pieces[0], False)
|
|
@ -0,0 +1,5 @@
|
|||
# Prints out all the functions in the program that have a non-zero stack purge size
|
||||
|
||||
for func in currentProgram.getFunctionManager().getFunctions(currentProgram.evaluateAddress("0"), 1):
|
||||
if func.getStackPurgeSize() != 0:
|
||||
print "Function", func, "at", func.getEntryPoint(), "has nonzero purge size", func.getStackPurgeSize()
|
|
@ -0,0 +1,21 @@
|
|||
# Writes properties to the tool.
|
||||
|
||||
# DISCLAIMER: This is a recreation of a Java Ghidra script for example
|
||||
# use only. Please run the Java version in a production environment.
|
||||
|
||||
#@category Examples.Python
|
||||
|
||||
from ghidra.framework.options import Options
|
||||
from ghidra.framework.plugintool import PluginTool
|
||||
|
||||
tool = state.getTool()
|
||||
options = tool.getOptions("name of my script")
|
||||
|
||||
fooString = options.getString("foo", None)
|
||||
|
||||
if fooString is not None : #does not exist in tool options
|
||||
fooString = askString("enter foo", "what value for foo:")
|
||||
if fooString is not None :
|
||||
options.setString("foo", fooString)
|
||||
|
||||
popup(fooString)
|
|
@ -0,0 +1,18 @@
|
|||
# Example of being imported by a Ghidra Python script/module
|
||||
# @category: Examples.Python
|
||||
|
||||
# The following line will fail if this module is imported from external_module_caller.py,
|
||||
# because only the script that gets directly launched by Ghidra inherits fields and methods
|
||||
# from the GhidraScript/FlatProgramAPI.
|
||||
try:
|
||||
print currentProgram.getName()
|
||||
except NameError:
|
||||
print "Failed to get the program name"
|
||||
|
||||
# The Python module that Ghidra directly launches is always called __main__. If we import
|
||||
# everything from that module, this module will behave as if Ghidra directly launched it.
|
||||
from __main__ import *
|
||||
|
||||
# The below method call should now work
|
||||
print currentProgram.getName()
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# Example of importing an external Ghidra Python module
|
||||
# @category: Examples.Python
|
||||
|
||||
# Import the external module that wants to access the Ghidra scripting API.
|
||||
# NOTE: see external_module_callee.py for additional tips.
|
||||
import external_module_callee
|
62
Ghidra/Features/Python/ghidra_scripts/ghidra_basics.py
Normal file
62
Ghidra/Features/Python/ghidra_scripts/ghidra_basics.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
# Examples of basic Ghidra scripting in Python
|
||||
# @category: Examples.Python
|
||||
|
||||
# Get info about the current program
|
||||
print
|
||||
print "Program Info:"
|
||||
program_name = currentProgram.getName()
|
||||
creation_date = currentProgram.getCreationDate()
|
||||
language_id = currentProgram.getLanguageID()
|
||||
compiler_spec_id = currentProgram.getCompilerSpec().getCompilerSpecID()
|
||||
print "%s: %s_%s (%s)\n" % (program_name, language_id, compiler_spec_id, creation_date)
|
||||
|
||||
# Get info about the current program's memory layout
|
||||
print "Memory layout:"
|
||||
print "Imagebase: " + hex(currentProgram.getImageBase().getOffset())
|
||||
for block in getMemoryBlocks():
|
||||
start = block.getStart().getOffset()
|
||||
end = block.getEnd().getOffset()
|
||||
print "%s [start: 0x%x, end: 0x%x]" % (block.getName(), start, end)
|
||||
print
|
||||
|
||||
# Get the current program's function names
|
||||
function = getFirstFunction()
|
||||
while function is not None:
|
||||
print function.getName()
|
||||
function = getFunctionAfter(function)
|
||||
print
|
||||
|
||||
# Get the address of the current program's current location
|
||||
print "Current location: " + hex(currentLocation.getAddress().getOffset())
|
||||
|
||||
# Get some user input
|
||||
val = askString("Hello", "Please enter a value")
|
||||
print val
|
||||
|
||||
# Output to a popup window
|
||||
popup(val)
|
||||
|
||||
# Add a comment to the current program
|
||||
minAddress = currentProgram.getMinAddress()
|
||||
listing = currentProgram.getListing()
|
||||
codeUnit = listing.getCodeUnitAt(minAddress)
|
||||
codeUnit.setComment(codeUnit.PLATE_COMMENT, "This is an added comment!")
|
||||
|
||||
# Get a data type from the user
|
||||
from ghidra.app.util.datatype import DataTypeSelectionDialog
|
||||
from ghidra.util.data.DataTypeParser import AllowedDataTypes
|
||||
tool = state.getTool()
|
||||
dtm = currentProgram.getDataTypeManager()
|
||||
selectionDialog = DataTypeSelectionDialog(tool, dtm, -1, AllowedDataTypes.FIXED_LENGTH)
|
||||
tool.showDialog(selectionDialog)
|
||||
dataType = selectionDialog.getUserChosenDataType()
|
||||
if dataType != None: print "Chosen data type: " + str(dataType)
|
||||
|
||||
# Report progress to the GUI. Do this in all script loops!
|
||||
import time
|
||||
monitor.initialize(10)
|
||||
for i in range(10):
|
||||
monitor.checkCanceled() # check to see if the user clicked cancel
|
||||
time.sleep(1) # pause a bit so we can see progress
|
||||
monitor.incrementProgress(1) # update the progress
|
||||
monitor.setMessage("Working on " + str(i)) # update the status message
|
38
Ghidra/Features/Python/ghidra_scripts/jython_basics.py
Normal file
38
Ghidra/Features/Python/ghidra_scripts/jython_basics.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Examples of Jython-specific functionality
|
||||
# @category: Examples.Python
|
||||
|
||||
# Using Java data structures from Jython
|
||||
python_list = [1, 2, 3]
|
||||
java_list = java.util.LinkedList(java.util.Arrays.asList(1, 2, 3))
|
||||
print str(type(python_list))
|
||||
print str(type(java_list))
|
||||
|
||||
# Importing Java packages for simpler Java calls
|
||||
from java.util import LinkedList, Arrays
|
||||
python_list = [1, 2, 3]
|
||||
java_list = LinkedList(Arrays.asList(1, 2, 3))
|
||||
print str(type(python_list))
|
||||
print str(type(java_list))
|
||||
|
||||
# Python adds helpful syntax to Java data structures
|
||||
print python_list[0]
|
||||
print java_list[0] # can't normally do this in java
|
||||
print java_list[0:2] # can't normally do this in java
|
||||
|
||||
# Iterate over Java collection the Python way
|
||||
for entry in java_list:
|
||||
print entry
|
||||
|
||||
# "in" keyword compatibility
|
||||
print str(3 in java_list)
|
||||
|
||||
# Create GUI with Java Swing
|
||||
from javax.swing import JFrame
|
||||
frame = JFrame() # don't call constructor with "new"
|
||||
frame.setSize(400,400)
|
||||
frame.setLocation(200, 200)
|
||||
frame.setTitle("Jython JFrame")
|
||||
frame.setVisible(True)
|
||||
|
||||
# Use JavaBean properties in constructor with keyword arguments!
|
||||
JFrame(title="Super Jython JFrame", size=(400,400), visible=True)
|
102
Ghidra/Features/Python/ghidra_scripts/python_basics.py
Normal file
102
Ghidra/Features/Python/ghidra_scripts/python_basics.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
# Examples of basic Python
|
||||
# @category: Examples.Python
|
||||
|
||||
# Python data types
|
||||
my_int = 32
|
||||
print my_int
|
||||
print hex(my_int)
|
||||
|
||||
my_bool = True
|
||||
print my_bool
|
||||
print not my_bool
|
||||
|
||||
my_string = 'this is a string'
|
||||
print my_string
|
||||
print my_string[:4]
|
||||
print my_string[-5:]
|
||||
print type(my_string)
|
||||
|
||||
my_list = ["a", 2, 5.3, my_string]
|
||||
print my_list
|
||||
print my_list[1]
|
||||
print my_list[1:2]
|
||||
print my_list + [1, 2, 3]
|
||||
print type(my_list)
|
||||
|
||||
my_tuple = (1, 2, 3)
|
||||
print my_tuple
|
||||
print my_tuple + (4,)
|
||||
print type(my_tuple)
|
||||
|
||||
my_dictionary = {"key1": "1", "key2": 2, "key3": my_list}
|
||||
print my_dictionary["key3"]
|
||||
print type(my_dictionary)
|
||||
|
||||
my_null = None
|
||||
print my_null
|
||||
print type(my_null)
|
||||
|
||||
# Python conditionals
|
||||
if len(my_string) == 16:
|
||||
print "length of my_string is 16!"
|
||||
|
||||
if 4 not in my_list:
|
||||
print "4 is not in my_list!"
|
||||
|
||||
if type(my_dictionary) == type(dict):
|
||||
print "my_dictionary is a dictionary!"
|
||||
|
||||
if my_null is None and 2 + 2 == 4:
|
||||
print "my_null is None and 2 + 2 == 4!"
|
||||
|
||||
# Python loops
|
||||
for i in range(1, 10):
|
||||
print i
|
||||
|
||||
for letter in "word":
|
||||
print letter
|
||||
|
||||
for element in [100, 200, 300]:
|
||||
print element
|
||||
|
||||
for key in my_dictionary:
|
||||
print "%s:%s" % (key, my_dictionary[key])
|
||||
|
||||
i = 5
|
||||
while i < 8:
|
||||
print i
|
||||
i += 1
|
||||
|
||||
# Python functions
|
||||
def factorial(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
return n * factorial(n-1)
|
||||
|
||||
i = 4
|
||||
print str(i) + "! = " + str(factorial(4))
|
||||
|
||||
# Python exceptions
|
||||
def error_function():
|
||||
raise IOError("An IO error occurred!")
|
||||
|
||||
try:
|
||||
error_function()
|
||||
print "I won't print"
|
||||
except IOError as e:
|
||||
print e.message
|
||||
|
||||
# Python class
|
||||
class Employee:
|
||||
def __init__(self, id, name):
|
||||
self.id = id
|
||||
self.name = name
|
||||
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
e = Employee(5555, "Snoopy")
|
||||
print e.getName()
|
Loading…
Add table
Add a link
Reference in a new issue