Skip to content

Debug watching accesses

Bennett Blodinger edited this page Mar 18, 2017 · 1 revision

Watching Address Accessess

  • debug.watchWriteAccesses(memoryAddress, numberOfBytes, callback)
  • debug.watchReadAndWriteAccesses(memoryAddress, numberOfBytes, callback)
  • debug.removeWatchAccesses(memoryAddress)
  • def callback(dataAddress, instructionAddress, registers)

debug.watchWriteAccesses and debug.watchReadAndWriteAccesses set up a hardware watchpoint to watch for when a value at memoryAddress with length numberOfBytes is written into, or read & written into, respectively. numberOfBytes must be either 1, 2, 4, or 8 if the target is a 64-bit process. Additionally, memoryAddress should be byte-aligned according to numberOfBytes.

You will need to pass a callback which takes an address to memory address being accessed, an address to instruction that accessed it, and a dictionary of available registers. See example below.

Note that today's hardware can only support up to 4 hardware breakpoints, so it's not too unlikely that these can fail.

Finally, you can remove watching for accesses by passing the memoryAddress you want to stop observing into a debug.removeWatchAccesses call. Note that all watchpoints are removed when a script terminates regardless whether or not you explicitly remove them.

debug.watchWriteAccesses and debug.watchReadAndWriteAccesses raise bitslicer.DebuggerError if a watchpoint could not be added or a ValueError if the callback is not callable.

Example

##Watch Data!
import bitslicer

LIVES_ADDRESS = 0x1A164

class Script(object):
    def __init__(self):
        self.oldLives = vm.readInt32(LIVES_ADDRESS)
        debug.watchWriteAccesses(LIVES_ADDRESS, 4, self.livesChanged)
        
    def livesChanged(self, dataAddress, instructionAddress, registers):
        newLives = vm.readInt32(dataAddress)
        #look up python formatters if you're unfamilar with them
        debug.log("Hey, I saw you change! You used to be %d, now you are %d" % (self.oldLives, newLives))
        debug.log("Instruction %s accessed data at address %s" % (hex(instructionAddress), hex(dataAddress)))
        debug.log(registers)

        #stop watching since I'm only interested in the first change
        debug.removeWatchAccesses(dataAddress)