ghidra/Ghidra/Features/Base/ghidra_scripts/mark_in_out.py

100 lines
4.9 KiB
Python

# Sets up IOPORT IN/OUT references for the Program
#@category Instructions
# Before running this script, you should have created an OVERLAY memory
# space called IOMEM, starting at address 0, size 0x10000.
#
# Note: This script is rather sloppy and should probably be cleaned up.
from ghidra.program.model.lang.OperandType import SCALAR, REGISTER
from ghidra.program.model.symbol.RefType import READ, WRITE
from ghidra.program.model.symbol.SourceType import *
def add_io_reference(instruction, opIndex, refType):
"""Creates an I/O memory reference for the given scalar operand
of the given instruction."""
# delete all current references from the port address field
for ref in refMgr.getReferences(instruction.address, opIndex):
print " Deleting reference to address", ref.toAddress
refMgr.delete(ref)
# must use int() to avoid creating a long...
# we only have 16 bits of I/O address space, and a long
# would append an 'L' to the hex address
ioAddr = int(instruction.getOpObjects(opIndex)[0].value)
ioAddress = addrFactory.getAddress("IOMEM::" + hex(ioAddr))
print " Adding", refType, "reference from", instruction.address, \
"to address", ioAddress
# from, to, type, sourceType, opIndex
refMgr.addMemoryReference(instruction.address, ioAddress,
refType, ANALYSIS, opIndex)
refMgr = currentProgram.referenceManager
addrFactory = currentProgram.addressFactory
# True means min->max as opposed to listing the Program backwards...
instructions = currentProgram.listing.getInstructions(True)
for instruction in instructions:
if instruction.mnemonicString == "IN":
#print "IN @", instruction.address
if (instruction.getOperandType(1) & SCALAR) != 0:
add_io_reference(instruction, 1, READ)
# no absolute address? okay, let's see if it was set above
prevInstructionAddr = instruction.fallFrom
if prevInstructionAddr is None:
# could be the first instruction in a function, for example
continue
prevInstruction = getInstructionAt(prevInstructionAddr)
if prevInstruction.mnemonicString == "MOV":
# did we move an absolute address into EDX?
if (prevInstruction.getOperandType(1) & SCALAR) != 0:
# we moved a scalar...
if (prevInstruction.getOperandType(0) & REGISTER) != 0:
# okay, we moved into a register...
register = prevInstruction.getOpObjects(0)[0]
if register.getBaseRegister().name == "EDX":
# hooray!
add_io_reference(prevInstruction, 1, READ)
elif instruction.mnemonicString == "OUT":
#print "OUT @", instruction.address
if (instruction.getOperandType(0) & SCALAR) != 0:
add_io_reference(instruction, 0, WRITE)
# no absolute address? okay, let's see if it was set above
prevInstructionAddr = instruction.fallFrom
if prevInstructionAddr is None:
# could be the first instruction in a function, for example
continue
prevInstruction = getInstructionAt(prevInstructionAddr)
if prevInstruction.mnemonicString == "MOV":
# did we move an absolute address into EDX?
if (prevInstruction.getOperandType(1) & SCALAR) != 0:
# we moved a scalar...
if (prevInstruction.getOperandType(0) & REGISTER) != 0:
# okay, we moved into a register...
register = prevInstruction.getOpObjects(0)[0]
if register.getBaseRegister().name == "EDX":
# hooray!
add_io_reference(prevInstruction, 1, WRITE)
elif register.getBaseRegister().name == "EAX":
# d'oh, we were writing to EAX (the value to write to
# the port)! one more try...
try:
prevInstr = getInstructionAt(prevInstruction.fallFrom)
if prevInstr.mnemonicString == "MOV":
# did we move an absolute address into EDX?
if (prevInstr.getOperandType(1) & SCALAR) != 0:
# we moved a scalar...
if (prevInstr.getOperandType(0) &
REGISTER) != 0:
# okay, we moved into a register...
register = prevInstr.getOpObjects(0)[0]
if register.getBaseRegister().name == \
"EDX":
# hooray!
add_io_reference(prevInstr, 1, WRITE)
except:
# oh well
pass