Skip to content

Instantly share code, notes, and snippets.

@clubby789
Created November 6, 2023 09:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clubby789/48ba6260973e0e247bf738e4106caabb to your computer and use it in GitHub Desktop.
Save clubby789/48ba6260973e0e247bf738e4106caabb to your computer and use it in GitHub Desktop.
BN DWARF Plugin
import binaryninja
from binaryninja.architecture import Architecture
from binaryninja.function import RegisterInfo, InstructionInfo, InstructionTextToken as ITT
from binaryninja.enums import InstructionTextTokenType as ITTT, BranchType
from binaryninja.log import log_error, log_info
from binaryninja.lowlevelil import LowLevelILLabel
import struct
class DWARFArchitecture(Architecture):
name = "DWARF"
address_size = 2
default_integer_size = 2
regs = {
'RDI': RegisterInfo('RDI', 8),
'RSI': RegisterInfo('RSI', 8),
'RDX': RegisterInfo('RDX', 8),
'SP': RegisterInfo('SP', 8),
}
stack_pointer = "SP"
def __init__(self):
super().__init__()
def get_instruction_info(self, data, addr):
opc = data[0]
res = InstructionInfo()
res.length = 1
match opc:
case 8: res.length = 2
case 0xa: res.length = 3
case 0xc: res.length = 5
case 0xe: res.length = 9
case n if n in range(0x12, 0x23): res.length = 1
case 0x26:
res.length = 1
res.add_branch(BranchType.FunctionReturn)
case 0x28:
res.length = 3
res.add_branch(BranchType.TrueBranch, addr + 3 + struct.unpack("h", data[1:3])[0])
res.add_branch(BranchType.FalseBranch, addr + 3)
case n if n in range(0x29, 0x2f): res.length = 1
case 0x48: res.length = 1
case 0x70|0x71|0x72|0x73|0x74|0x75|0x76: res.length = 2
case 0x9f: res.length = 1
case _: log_error(f"inf: opcode {opc:#x} ({addr:#X}) not implemented")
return res
def get_instruction_text(self, data, addr):
result = None
length = 1
opc = data[0]
match opc:
case 8:
result = [ITT(ITTT.TextToken, "const1u"), ITT(ITTT.IntegerToken, hex(data[1]), data[1])]
length = 2
case 0xa:
val = struct.unpack("H", data[1:3])[0]
result = [ITT(ITTT.TextToken, "const2u"), ITT(ITTT.IntegerToken, hex(val), val)]
length = 3
case 0xc:
val = struct.unpack("I", data[1:5])[0]
result = [ITT(ITTT.TextToken, "const4u"), ITT(ITTT.IntegerToken, hex(val), val)]
length = 5
case 0xe:
val = struct.unpack("Q", data[1:9])[0]
result = [ITT(ITTT.TextToken, "const8u"), ITT(ITTT.IntegerToken, hex(val), val)]
length = 9
case 0x12:
result = [ITT(ITTT.TextToken, f"DUP")]
length = 1
case 0x1a:
result = [ITT(ITTT.TextToken, f"AND")]
length = 1
case 0x1e:
result = [ITT(ITTT.TextToken, f"MUL")]
length = 1
case 0x22:
result = [ITT(ITTT.TextToken, f"PLUS")]
length = 1
case n if n in range(0x12, 0x23):
result = [ITT(ITTT.TextToken, f"<unary op {n:#x}>")]
length = 1
case 0x26:
result = [ITT(ITTT.TextToken, f"SHRA")]
length = 1
case 0x28:
length = 3
tgt = addr + 3 + struct.unpack("h", data[1:3])[0]
result = [ITT(ITTT.TextToken, "bra"), ITT(ITTT.PossibleAddressToken, f"0x{tgt:X}", tgt)]
case 0x29:
result = [ITT(ITTT.TextToken, "EQ")]
length = 1
case 0x2e:
result = [ITT(ITTT.TextToken, f"NE")]
length = 1
case n if n in range(0x29, 0x2f):
result = [ITT(ITTT.TextToken, f"<binary op {n:#x}>")]
length = 1
case 0x71:
result = [ITT(ITTT.TextToken, f"push (rdx)")]
length = 2
case 0x74:
result = [ITT(ITTT.TextToken, f"push (rsi)")]
length = 2
case 0x75:
result = [ITT(ITTT.TextToken, f"push (rdi)")]
length = 2
case 0x9f:
result = [ITT(ITTT.TextToken, f"TOS")]
length = 1
case _: log_error(f"txt: opcode {opc:#x} ({addr:#X}) not implemented")
if len(result) > 1:
result.insert(1, ITT(ITTT.TextToken, " "))
return (result, length)
def get_instruction_low_level_il(self, data, addr, il):
length = 1
opc = data[0]
match opc:
case 8:
val = il.const(8, data[1])
il.append(il.push(8, val))
case 0xa:
length = 3
val = struct.unpack("H", data[1:3])[0]
val = il.const(8, val)
il.append(il.push(8, val))
case 0xc:
length = 5
val = struct.unpack("I", data[1:5])[0]
val = il.const(8, val)
il.append(il.push(8, val))
case 0xe:
length = 9
val = struct.unpack("Q", data[1:9])[0]
val = il.const(8, val)
il.append(il.push(8, val))
case 0x12:
val = il.load(8, il.reg(8, 'SP'))
il.append(il.push(8, val))
case 0x1a:
il.append(il.push(8, il.and_expr(8, il.pop(8), il.pop(8))))
case 0x1e:
il.append(il.push(8, il.mult(8, il.pop(8), il.pop(8))))
case 0x22:
il.append(il.push(8, il.add(8, il.pop(8), il.pop(8))))
case 0x26:
# 'shra' shouldn't actually be hit
il.append(il.no_ret())
case n if n in range(0x12, 0x27):
il.append(il.unimplemented())
case 0x28:
length = 3
tgt = addr + length + struct.unpack("h", data[1:3])[0]
true_label = il.get_label_for_address(Architecture["DWARF"], tgt)
false_label = il.get_label_for_address(Architecture["DWARF"], addr + length)
if true_label and false_label:
il.append(il.if_expr(il.pop(8), true_label, false_label))
else:
il.append(il.no_ret())
case 0x29:
length = 1
rhs = il.pop(8)
lhs = il.pop(8)
il.append(il.push(8, il.compare_equal(8, lhs, rhs)))
case 0x2e:
length = 1
rhs = il.pop(8)
lhs = il.pop(8)
il.append(il.push(8, il.compare_not_equal(8, lhs, rhs)))
case n if n in range(0x29, 0x2f):
il.append(il.unimplemented())
length = 1
case 0x71:
il.append(il.push(8, il.reg(8, 'RDX')))
length = 2
case 0x74:
il.append(il.push(8, il.reg(8, 'RSI')))
length = 2
case 0x75:
il.append(il.push(8, il.reg(8, 'RDI')))
length = 2
case 0x9f:
il.append(il.ret(il.pop(8)))
length = 1
case _: log_error(f"txt: opcode {opc:#x} ({addr:#X}) not implemented")
return length
DWARFArchitecture.register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment