From 58e515b3bfa3a96e4934b8a625bb6e51399057ec Mon Sep 17 00:00:00 2001 From: Andrew Lamoureux Date: Mon, 28 Jun 2021 13:20:55 -0400 Subject: [PATCH] Add type library creation and dumping examples --- python/examples/typelib_create.py | 126 ++++++++++++++++++++++++++++++ python/examples/typelib_dump.py | 120 ++++++++++++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100755 python/examples/typelib_create.py create mode 100755 python/examples/typelib_dump.py diff --git a/python/examples/typelib_create.py b/python/examples/typelib_create.py new file mode 100755 index 000000000..6974c68f0 --- /dev/null +++ b/python/examples/typelib_create.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# demonstrate creating a type library + +import binaryninja +from binaryninja.enums import * +from binaryninja.types import * + +arch = binaryninja.Architecture['x86_64'] +typelib = binaryninja.typelibrary.TypeLibrary.new(arch, 'libtest.so.1') +typelib.add_platform(binaryninja.Platform['mac-x86_64']) +typelib.add_alternate_name('libtest.so') + +#------------------------------------------------------------------------------ +# PART1: Named Types +#------------------------------------------------------------------------------ + +# example: VoidTypeClass +typelib.add_named_type('MyVoidType', Type.void()) + +# example: BoolTypeClass +typelib.add_named_type('MyBoolType', Type.bool()) + +# example: IntegerTypeClass +typelib.add_named_type('MyCharType', Type.char()) +typelib.add_named_type('MyIntType', Type.int(4, True)) +typelib.add_named_type('MyUnsignedIntType', Type.int(4, False)) + +# example: FloatTypeClass +typelib.add_named_type('MyFloatType', Type.float(4)) + +# example: PointerTypeClass +# char * +typelib.add_named_type('MyPointerType', Type.pointer(arch, Type.char())) + +# example of typedef to primitive type +# typedef int MyTypedefType; +typelib.add_named_type('MyTypedefType', Type.int(4)) + +# example of typedef to typedef +# typedef MyTypedefType MySuperSpecialType; +def create_named_type_reference(type_name:str, to_what:NamedTypeReferenceClass): + ntr = NamedTypeReference(type_class=to_what, name=type_name) + return Type.named_type(ntr) + +typelib.add_named_type('MySuperSpecialType', + create_named_type_reference('MySpecialType', NamedTypeReferenceClass.TypedefNamedTypeClass)) + +# We can demonstrate three type classes in the following example: +# StructureTypeClass, PointerTypeClass, NamedTypeReferenceClass + +# add a named type "Rectangle": +# +# struct +# { +# int width; +# int height; +# struct Point *center; // pointer to possibly undeclared struct +# } + +tmp = Structure() +tmp.append(Type.int(4), 'width') +tmp.append(Type.int(4), 'height') +tmp.append(Type.pointer(arch, + create_named_type_reference('Point', NamedTypeReferenceClass.StructNamedTypeClass)), + 'center') +struct_type = Type.structure_type(tmp) +typelib.add_named_type('Rectangle', struct_type) + +# add a named type "Rectangle2": +# this type cannot be applied to variables until struct Point is declared +# +# struct +# { +# int width; +# int height; +# struct Point center; // actual undeclared struct +# } +tmp = Structure() +tmp.append(Type.int(4), 'width') +tmp.append(Type.int(4), 'height') +tmp.append(create_named_type_reference('Point', NamedTypeReferenceClass.StructNamedTypeClass), + 'center') +struct_type = Type.structure_type(tmp) +typelib.add_named_type('Rectangle2', struct_type) + +# example: EnumerationTypeClass +tmp = Enumeration() +tmp.append('RED', 0) +tmp.append('ORANGE', 1) +tmp.append('YELLOW', 2) +tmp.append('GREEN', 3) +tmp.append('BLUE', 4) +tmp.append('INDIGO', 5) +tmp.append('VIOLET', 6) +enum_type = Type.enumeration_type(arch, tmp) +typelib.add_named_type('MyEnumerationType', enum_type) + +# example: ArrayTypeClass +# +# unsigned char[256] +typelib.add_named_type('MyArrayType', Type.array(Type.int(1), 256)) + +# example: FunctionTypeClass +# +# int ()(int, int, int) +ret = Type.int(4) +params = [Type.int(4), Type.int(4), Type.int(4)] +ftype = Type.function(ret, params) +typelib.add_named_type('MyFunctionType', ftype) + +#------------------------------------------------------------------------------ +# PART2: Named Objects +#------------------------------------------------------------------------------ + +# example: any external/imported functions named _MySuperComputation +# are typed int _MySuperComputation(int, int) + +ret = Type.int(4) +params = [Type.int(4), Type.int(4)] +ftype = Type.function(ret, params) +typelib.add_named_object('_MySuperComputation', ftype) + +# finalize +typelib.finalize() +typelib.write_to_file('test.bntl') + diff --git a/python/examples/typelib_dump.py b/python/examples/typelib_dump.py new file mode 100755 index 000000000..90f6700d0 --- /dev/null +++ b/python/examples/typelib_dump.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# binja type library info utility + +import os, sys, re, random +import binaryninja +from binaryninja.enums import * +from binaryninja import typelibrary + +# The class Type as defined in api/python/types.py is nearly a discriminated union. +# By examining the .type_class member you can decide which properties make sense to access. +# +# For example, if .type_class == FunctionTypeClass then you can access: +# .return_value binaryninja.types.Type +# .parameters [binaryninja.types.FunctionParameter] +# +# For example, if .type_class == StructureTypeClass then you can access: +# .structure binaryninja.types.Structure +# +# etc... + +def obj2str(t, depth=0): + indent = ' '*depth + result = '' + + if type(t) == binaryninja.types.Structure: + result = '%sStructure\n' % (indent) + for m in t.members: + result += obj2str(m, depth+1) + elif type(t) == binaryninja.types.StructureMember: + result = '%sStructureMember "%s"\n' % (indent, t._name) + result += type2str(t.type, depth+1) + elif type(t) == binaryninja.types.FunctionParameter: + result = '%sFunctionParameter "%s"\n' % (indent, t.name) + result += type2str(t.type, depth+1) + elif type(t) == binaryninja.types.NamedTypeReference: + result = '%sNamedTypeReference %s\n' % (indent, repr(t)) + elif type(t) == binaryninja.types.Enumeration: + result = '%sEnumeration\n' % indent + for m in t.members: + result += obj2str(m, depth+1) + elif type(t) == binaryninja.types.EnumerationMember: + result = '%sEnumerationMember %s==%d\n' % (indent, t.name, t.value) + elif t == None: + result = 'unimplemented' + + return result + +def type2str(t:binaryninja.types.Type, depth=0): + indent = ' '*depth + result = 'unimplemented' + + assert type(t) == binaryninja.types.Type + tc = t.type_class + + if tc == TypeClass.VoidTypeClass: + result = '%sType class=Void\n' % indent + elif tc == TypeClass.BoolTypeClass: + result = '%sType class=Bool\n' % indent + elif tc == TypeClass.IntegerTypeClass: + result = '%sType class=Integer width=%d\n' % (indent, t.width) + elif tc == TypeClass.FloatTypeClass: + result = '%sType class=Float\n' % indent + elif tc == TypeClass.StructureTypeClass: + result = '%sType class=Structure\n' % indent + result += obj2str(t.structure, depth+1) + elif tc == TypeClass.EnumerationTypeClass: + result = '%sType class=Enumeration\n' % indent + result += obj2str(t.enumeration, depth+1) + elif tc == TypeClass.PointerTypeClass: + result = '%sType class=Pointer\n' % indent + result += type2str(t.element_type, depth+1) + elif tc == TypeClass.ArrayTypeClass: + result = '%sType class=Array\n' % indent + elif tc == TypeClass.FunctionTypeClass: + result = '%sType class=Function\n' % indent + result += type2str(t.return_value, depth+1) + for param in t.parameters: + result += obj2str(param, depth+1) + elif tc == TypeClass.VarArgsTypeClass: + result = '%sType class=VarArgs\n' % indent + elif tc == TypeClass.ValueTypeClass: + result = '%sType class=Value\n' % indent + elif tc == TypeClass.NamedTypeReferenceClass: + result = '%sType class=NamedTypeReference\n' % indent + result += obj2str(t.named_type_reference, depth+1) + elif tc == TypeClass.WideCharTypeClass: + result = '%sType class=WideChar\n' % indent + + return result + +if __name__ == '__main__': + binaryninja._init_plugins() + + if len(sys.argv) <= 1: + raise Exception('supply typelib file') + + fpath = sys.argv[-1] + print(' reading: %s' % fpath) + + tl = typelibrary.TypeLibrary.load_from_file(fpath) + print(' name: %s' % tl.name) + print(' arch: %s' % tl.arch) + print(' guid: %s' % tl.guid) + print('dependency_name: %s' % tl.dependency_name) + print('alternate_names: %s' % tl.alternate_names) + print(' platform_names: %s' % tl.platform_names) + print('') + + print(' named_objects: %d' % len(tl.named_objects)) + for (key, val) in tl.named_objects.items(): + print('\t"%s" %s' % (str(key), str(val))) + + print('') + + print(' named_types: %d' % len(tl.named_types)) + for (key,val) in tl.named_types.items(): + line = 'typelib.named_types["%s"] =' % (str(key)) + print(line) + print('-'*len(line)) + print(type2str(val))