Created
November 6, 2023 09:50
-
-
Save clubby789/48ba6260973e0e247bf738e4106caabb to your computer and use it in GitHub Desktop.
BN DWARF Plugin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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