Skip to content

Commit

Permalink
Add docs for Xenial binutils, and attempt to auto-detect Debian packa…
Browse files Browse the repository at this point in the history
…ges (#718)

An error message will be printed like this when a package is found:

>>> context.arch='powerpc'
>>> pwnlib.asm.print_binutils_instructions('objdump', context)
[ERROR] Could not find 'objdump' installed for ContextType(arch = 'powerpc', bits = 32, endian = 'big')
    Try installing binutils for this architecture:
    $ sudo apt-get install binutils-powerpc-linux-gnu
  • Loading branch information
zachriggle committed Sep 2, 2016
1 parent ae6a074 commit 8f06c1f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 8 deletions.
5 changes: 4 additions & 1 deletion docs/source/install/binutils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ Building `binutils` from source takes about 60 seconds on a modern 8-core machin

Ubuntu
^^^^^^^^^^^^^^^^
First, add our `Personal Package Archive repository <http://binutils.pwntools.com>`__.

For Ubuntu 12.04 through 15.10, you must first add the pwntools `Personal Package Archive repository <http://binutils.pwntools.com>`__.

Ubuntu Xenial (16.04) has official packages for most architectures, and does not require this step.

.. code-block:: bash
Expand Down
63 changes: 56 additions & 7 deletions pwnlib/asm.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,60 @@
_basedir = path.split(__file__)[0]
_incdir = path.join(_basedir, 'data', 'includes')

def dpkg_search_for_binutils(arch, util):
"""Use dpkg to search for any available assemblers which will work.
Returns:
A list of candidate package names.
"""

# Example output:
# $ dpkg -S 'arm*linux*-as'
# binutils-arm-linux-gnu: /usr/bin/arm-linux-gnu-as
# binutils-arm-linux-gnueabihf: /usr/bin/arm-linux-gnueabihf-as
# binutils-arm-linux-gnueabihf: /usr/x86_64-linux-gnu/arm-linux-gnueabihf/include/dis-asm.h
# binutils-arm-linux-gnu: /usr/x86_64-linux-gnu/arm-linux-gnu/include/dis-asm.h
packages = []

try:
filename = 'bin/%s*linux*-%s' % (arch, util)
output = subprocess.check_output(['dpkg','-S',filename])
for line in output.strip().splitlines():
package, path = line.split(':', 1)
packages.append(package)
except OSError:
pass
except subprocess.CalledProcessError:
pass

return packages

def print_binutils_instructions(util, context):
"""On failure to find a binutils utility, inform the user of a way
they can get it easily.
"""
# This links to our instructions on how to manually install binutils
# for several architectures.
instructions = 'https://docs.pwntools.com/en/stable/install/binutils.html'

# However, if we can directly provide a useful command, go for it.
binutils_arch = {
'amd64': 'x86_64',
'arm': 'armeabi',
'thumb': 'armeabi',
}.get(context.arch, context.arch)

packages = dpkg_search_for_binutils(binutils_arch, util)

if packages:
instructions = '$ sudo apt-get install %s' % packages[0]

log.error("""
Could not find %(util)r installed for %(context)s
Try installing binutils for this architecture:
%(instructions)s
""".strip() % locals())

@LocalContext
def which_binutils(util):
"""
Expand Down Expand Up @@ -129,13 +183,8 @@ def which_binutils(util):
if res:
return res[0]

locals()['context'] = context
log.warning("""
Could not find %(util)r installed for %(context)s
Try installing binutils for this architecture:
https://docs.pwntools.com/en/stable/install/binutils.html
""".strip() % locals())
raise Exception('Could not find %(util)r installed for %(context)s' % locals())
# No dice!
print_binutils_instructions(util, context)

checked_assembler_version = defaultdict(lambda: False)

Expand Down

0 comments on commit 8f06c1f

Please sign in to comment.