A tiny interface around a subset of libBFD. Code based on https://github.com/Groundworkstech/pybfd


Keywords
binary, libbfd
License
MIT
Install
pip install bfdpie==0.1.15

Documentation

Bfdpie

PyPI MIT License

Bfdpie is a tiny wrapper library around binutils (more precisely, libbfd). The project draws code and concepts from pybfd.

Installing

Any setup that can successfully compile binutils as well as python modules should be able to install bfdpie. To install bfdpie, use

pip install bfdpie

The code was tested on Linux, OSX and Windows (cygwin). On Windows, the prerequisites in cygwin were make, zlib-devel, make, and difftools.

Description

The libbfd is a complex beast, and bfdpie only exposes the binary loading and disassembling parts of it. The goal of this library is to provide a simple and clean means of loading and disassembling various binary formats, the likes of which are often encountered in CTF challanges. For example, we can print all the symbols of any binary file that libbfd supports by simply doing:

>>> from bfdpie import *
>>> b = Binary("/bin/ls")
>>> print b
Binary<'/bin/ls', 'mach', Arch<name:X86_64, bits:64, little_endian:1>>

>>> print b.symbols
{
   '_strlen': Symbol<_strlen, 0x0>, 
   '__DATA.__got': Section<__DATA.__got, 0x5000>, 
   '__TEXT.__stub_helper': Section<__TEXT.__stub_helper, 0x45f8>, 
   ...
}   

>>> text_section = b.symbols[".text"]
>>> print text_section
Section<.text, 0xe94>

>>> print hex(text_section.vma)
0xe94

>>> print b.symbols["_strlen"]
Symbol<_strlen, 0x0>

The b.symbols holds all the symbols the file has. If we need to know precisely where the symbols come from, we can access the different kinds through b.static_symbols, b.dynamic_symbols, b.synthetic_symbols and b.relocs.

Using the disassembler is equally easy.

>>> b = Binary()
>>> dis = b.disassemble_simple(
...    "\xba\x00\x04\x00\x00" +
...    "\x48\x89\xc6" +
...    "\xbf\x00\x00\x00\x00" +
...    "\xb8\x00\x00\x00\x00",
...    ARCH_X86_64
... )
mov edx,0x400
mov rsi,rax
mov edi,0x0
mov eax,0x0

Adding new architectures is easy, as long as binutils supports them. Currently, the following architectures are supported

archs = [
   ARCH_I686,
   ARCH_X86_64,
   ARCH_ARMEL,
   ARCH_ARMEL_THUMB,
   ARCH_ARMEB,
   ARCH_ARMEB_THUMB,
   ARCH_AARCH64,
   ARCH_AARCH64_BE,
   ARCH_MIPS,
   ARCH_MIPSEL,
   ARCH_MIPS64,
   ARCH_MIPS64EL,
   ARCH_PPC32,
   ARCH_PPC64,
   ARCH_SPARC,
   ARCH_SPARC64,
   ARCH_SH4,
   ARCH_SH4EB,
   ARCH_ALPHA,
   ARCH_CRISV32,
   ARCH_S390X,
   ARCH_MICROBLAZE,
   ARCH_MICROBLAZEEL,
]
>>> b.disassemble_simple(
...    "\xe3\x40\xf1\x10\x00\x04" +
...    "\xeb\xcf\xf1\x00\x00\x04" +
...    "\x07\xf4" +
...    "\x07\x07",
...    ARCH_S390X
... )
lg %r4,272(%r15)
lmg %r12,%r15,256(%r15)
br %r4
nopr %r7