Skip to content

Instantly share code, notes, and snippets.

@SteelPangolin
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SteelPangolin/b4dd43f42255a5d579d4 to your computer and use it in GitHub Desktop.
Save SteelPangolin/b4dd43f42255a5d579d4 to your computer and use it in GitHub Desktop.
Look for wordexp() imports on your $PATH
#!/usr/bin/python
"""
Look for binaries on $PATH that use the wordexp() POSIX libc function.
Only looks at dynamically linked binaries.
Works on Mac OS X and Linux systems, Python versions 2.4 to 3.4.
"""
import subprocess
import os
import sys
import logging
logging.basicConfig()
logger = logging.getLogger()
class CalledProcessErrorPy24(Exception):
def __init__(self, returncode, cmd):
self.returncode = returncode
self.cmd = cmd
def __str__(self):
return 'Command %r returned non-zero exit status %d' % (self.cmd, self.returncode)
def check_output_py24(args):
proc = subprocess.Popen(args, stdout=subprocess.PIPE)
output, _ = proc.communicate()
if proc.returncode != 0:
raise CalledProcessErrorPy24(proc.returncode, args)
return output
def any_py24(seq):
for s in seq:
if s:
return True
return False
check_output = getattr(subprocess, 'check_output', check_output_py24)
CalledProcessError = getattr(subprocess, 'CalledProcessError', CalledProcessErrorPy24)
try:
any([])
except NameError:
any = any_py24
def is_binary_executable_with_symbols(path):
output = check_output(['file', '-b', path]).decode('utf-8')
return 'executable' in output\
and any(binword in output for binword in ['binary', 'ELF'])\
and not 'static' in output
def has_wordexp(path):
# want to get all unresolved dynamic symbols
if 'darwin' in sys.platform:
nm_args = ['-u']
else:
nm_args = ['-D', '-u']
output = check_output(['nm'] + nm_args + [path]).decode('utf-8')
return 'wordexp' in output
def main():
roots = os.getenv('PATH').split(os.pathsep)
for root in roots:
if not os.path.isdir(root):
continue
for child in os.listdir(root):
try:
path = os.path.join(root, child)
if not os.path.isfile(path):
continue
if not is_binary_executable_with_symbols(path):
continue
if has_wordexp(path):
print(path)
except CalledProcessError:
logger.error("Error scanning file: %s", path, exc_info=True)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment