Skip to content

Commit

Permalink
Add type library creation and dumping examples
Browse files Browse the repository at this point in the history
  • Loading branch information
lwerdna committed Jun 28, 2021
1 parent 0bb2a55 commit 58e515b
Show file tree
Hide file tree
Showing 2 changed files with 246 additions and 0 deletions.
126 changes: 126 additions & 0 deletions python/examples/typelib_create.py
Original file line number Diff line number Diff line change
@@ -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')

120 changes: 120 additions & 0 deletions python/examples/typelib_dump.py
Original file line number Diff line number Diff line change
@@ -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))

0 comments on commit 58e515b

Please sign in to comment.