-
Notifications
You must be signed in to change notification settings - Fork 202
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add type library creation and dumping examples
- Loading branch information
Showing
2 changed files
with
246 additions
and
0 deletions.
There are no files selected for viewing
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
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') | ||
|
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
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)) |