How to solve VM-based challenges with the help of Cerbero.
This is the template code:
from Pro.Core import *
from Pro.UI import *
from Pro.ccast import sbyte
import os, struct
REG_COUNT = 16
def regName(id):
return "R" + str(id)
def disassemble(code, regs):
return "instr"
STEP_VIEW_ID = 1
DISASM_VIEW_ID = 2
MEMORY_VIEW_ID = 3
REGISTERS_VIEW_ID = 4
STACK_VIEW_ID = 5
# the dump directory should have files with increasing number as name
# e.g.: 0, 1, 2, etc.
DBGDIR = r"path/to/state/dumps"
BPX = -1
# logic to extract the instruction pointer from the dumps
# we use that as text in the Trace table and to go to a break point
def loadStepDescr(ud, steps):
stepsdescr = []
bpx_pos = -1
for step in steps:
with open(os.path.join(DBGDIR, str(step)), "rb") as f:
f.seek((REG_COUNT - 1) * 2)
ip = struct.unpack_from(">H", f.read(2), 0)[0]
if bpx_pos == -1 and ip == BPX:
bpx_pos = len(stepsdescr)
stepsdescr.append("%04X" % (ip,))
ud["stepsdescr"] = stepsdescr
if bpx_pos != -1:
ud["bpxpos"] = bpx_pos
def loadStep(cv, step, ud):
#with open(os.path.join(DBGDIR, str(step)), "rb") as f:
# dump = f.read()
dump = b"\x00\x01" * REG_COUNT
regs = struct.unpack_from("<" + ("H" * REG_COUNT), dump, 0)
ud["regs"] = regs
# set up regs table
t = cv.getView(REGISTERS_VIEW_ID)
labels = NTStringList()
labels.append("Register")
labels.append("Value")
t.setColumnCount(2)
t.setRowCount(REG_COUNT)
t.setColumnLabels(labels)
t.setColumnCWidth(0, 10)
t.setColumnCWidth(1, 20)
# set up memory
h = cv.getView(MEMORY_VIEW_ID)
curoffs = h.getCurrentOffset()
cursoroffs = h.getCursorOffset()
#mem = dump[REG_COUNT * 2:]
mem = b"dummy memory"
ud["mem"] = mem
h.setBytes(mem)
h.setCursorOffset(cursoroffs)
h.setCurrentOffset(curoffs)
# set up stack table
stack = (0x1000, 0x2000, 0x3000)
ud["cursp"] = 0x6000
ud["stack"] = stack
t = cv.getView(STACK_VIEW_ID)
labels = NTStringList()
labels.append("Stack address")
labels.append("Value")
t.setColumnCount(2)
t.setRowCount(len(stack))
t.setColumnLabels(labels)
t.setColumnCWidth(0, 10)
t.setColumnCWidth(1, 20)
# set up disasm
t = cv.getView(DISASM_VIEW_ID)
disasm = disassemble(mem, regs)
t.setText(disasm)
def tracerCallback(cv, ud, code, view, data):
if code == pvnInit:
# get steps
steps = os.listdir(dbgdir)
steps = [int(e) for e in steps]
steps = sorted(steps)
ud["steps"] = steps
loadStepDescr(ud, steps)
# set up steps
t = cv.getView(STEP_VIEW_ID)
labels = NTStringList()
labels.append("Trace")
t.setColumnCount(1)
t.setRowCount(len(steps))
t.setColumnLabels(labels)
t.setColumnCWidth(0, 10)
# go to bpx if any
if "bpxpos" in ud:
bpxpos = ud["bpxpos"]
t.setSelectedRow(bpxpos)
return 1
elif code == pvnGetTableRow:
vid = view.id()
if vid == STEP_VIEW_ID:
data.setText(0, str(ud["stepsdescr"][data.row]))
elif vid == REGISTERS_VIEW_ID:
data.setText(0, regName(data.row))
v = ud["regs"][data.row]
data.setText(1, "%d (0x%X)" % (v, v))
if data.row >= 13:
data.setBgColor(0, ProColor_Special)
data.setBgColor(1, ProColor_Special)
elif vid == STACK_VIEW_ID:
spaddr = ud["cursp"] + (data.row * 2)
data.setText(0, "0x%04X" % (spaddr,))
v = ud["stack"][data.row]
data.setText(1, "%d (0x%X)" % (v, v))
elif code == pvnRowSelected:
vid = view.id()
if vid == STEP_VIEW_ID:
loadStep(cv, ud["steps"][data.row], ud)
return 0
def tracerDlg():
ctx = proContext()
v = ctx.createView(ProView.Type_Custom, "Tracer Demo")
user_data = {}
v.setup("<ui><hs><table id='1'/><vs><text id='2'/><hex id='3'/></vs><table id='4'/><table id='5'/></hs></ui>", tracerCallback, user_data)
dlg = ctx.createDialog(v)
dlg.show()
tracerDlg()