1#!/usr/bin/env python
2import os
3import sys
4import shutil
5import tempfile
6import subprocess
7from distutils.core import setup, Command
8from distutils.dir_util import remove_tree
9
10MODULE_NAME = "binwalk"
11SCRIPT_NAME = MODULE_NAME
12
13# Python2/3 compliance
14try:
15    raw_input
16except NameError:
17    raw_input = input
18
19# cd into the src directory, no matter where setup.py was invoked from
20os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "src"))
21
22def which(command):
23    # /usr/local/bin is usually the default install path, though it may not be in $PATH
24    usr_local_bin = os.path.sep.join([os.path.sep, 'usr', 'local', 'bin', command])
25
26    try:
27        location = subprocess.Popen(["which", command], shell=False, stdout=subprocess.PIPE).communicate()[0].strip()
28    except KeyboardInterrupt as e:
29        raise e
30    except Exception as e:
31        pass
32
33    if not location and os.path.exists(usr_local_bin):
34        location = usr_local_bin
35
36    return location
37
38def find_binwalk_module_paths():
39    paths = []
40
41    try:
42        import binwalk
43        paths = binwalk.__path__
44    except KeyboardInterrupt as e:
45        raise e
46    except Exception:
47        pass
48
49    return paths
50
51def remove_binwalk_module(pydir=None, pybin=None):
52    if pydir:
53        module_paths = [pydir]
54    else:
55        module_paths = find_binwalk_module_paths()
56
57    for path in module_paths:
58        try:
59            remove_tree(path)
60        except OSError as e:
61            pass
62
63    if not pybin:
64        pybin = which(MODULE_NAME)
65
66    if pybin:
67        try:
68            sys.stdout.write("removing '%s'\n" % pybin)
69            os.remove(pybin)
70        except KeyboardInterrupt as e:
71            pass
72        except Exception as e:
73            pass
74
75class IDAUnInstallCommand(Command):
76    description = "Uninstalls the binwalk IDA plugin module"
77    user_options = [
78                    ('idadir=', None, 'Specify the path to your IDA install directory.'),
79    ]
80
81    def initialize_options(self):
82        self.idadir = None
83        self.mydir = os.path.dirname(os.path.realpath(__file__))
84
85    def finalize_options(self):
86        pass
87
88    def run(self):
89        if self.idadir is None:
90            sys.stderr.write("Please specify the path to your IDA install directory with the '--idadir' option!\n")
91            return
92
93        binida_dst_path = os.path.join(self.idadir, 'plugins', 'binida.py')
94        binwalk_dst_path = os.path.join(self.idadir, 'python', 'binwalk')
95
96        if os.path.exists(binida_dst_path):
97            sys.stdout.write("removing %s\n" % binida_dst_path)
98            os.remove(binida_dst_path)
99        if os.path.exists(binwalk_dst_path):
100            sys.stdout.write("removing %s\n" % binwalk_dst_path)
101            shutil.rmtree(binwalk_dst_path)
102
103class IDAInstallCommand(Command):
104    description = "Installs the binwalk IDA plugin module"
105    user_options = [
106                    ('idadir=', None, 'Specify the path to your IDA install directory.'),
107    ]
108
109    def initialize_options(self):
110        self.idadir = None
111        self.mydir = os.path.dirname(os.path.realpath(__file__))
112
113    def finalize_options(self):
114        pass
115
116    def run(self):
117        if self.idadir is None:
118            sys.stderr.write("Please specify the path to your IDA install directory with the '--idadir' option!\n")
119            return
120
121        binida_src_path = os.path.join(self.mydir, 'scripts', 'binida.py')
122        binida_dst_path = os.path.join(self.idadir, 'plugins')
123
124        if not os.path.exists(binida_src_path):
125            sys.stderr.write("ERROR: could not locate IDA plugin file '%s'!\n" % binida_src_path)
126            return
127        if not os.path.exists(binida_dst_path):
128            sys.stderr.write("ERROR: could not locate the IDA plugins directory '%s'! Check your --idadir option.\n" % binida_dst_path)
129            return
130
131        binwalk_src_path = os.path.join(self.mydir, 'binwalk')
132        binwalk_dst_path = os.path.join(self.idadir, 'python')
133
134        if not os.path.exists(binwalk_src_path):
135            sys.stderr.write("ERROR: could not locate binwalk source directory '%s'!\n" % binwalk_src_path)
136            return
137        if not os.path.exists(binwalk_dst_path):
138            sys.stderr.write("ERROR: could not locate the IDA python directory '%s'! Check your --idadir option.\n" % binwalk_dst_path)
139            return
140
141        binida_dst_path = os.path.join(binida_dst_path, 'binida.py')
142        binwalk_dst_path = os.path.join(binwalk_dst_path, 'binwalk')
143
144        if os.path.exists(binida_dst_path):
145            os.remove(binida_dst_path)
146        if os.path.exists(binwalk_dst_path):
147            shutil.rmtree(binwalk_dst_path)
148
149        sys.stdout.write("copying %s -> %s\n" % (binida_src_path, binida_dst_path))
150        shutil.copyfile(binida_src_path, binida_dst_path)
151
152        sys.stdout.write("copying %s -> %s\n" % (binwalk_src_path, binwalk_dst_path))
153        shutil.copytree(binwalk_src_path, binwalk_dst_path)
154
155class UninstallCommand(Command):
156    description = "Uninstalls the Python module"
157    user_options = [
158                    ('pydir=', None, 'Specify the path to the binwalk python module to be removed.'),
159                    ('pybin=', None, 'Specify the path to the binwalk executable to be removed.'),
160    ]
161
162    def initialize_options(self):
163        self.pydir = None
164        self.pybin = None
165
166    def finalize_options(self):
167        pass
168
169    def run(self):
170        remove_binwalk_module(self.pydir, self.pybin)
171
172class CleanCommand(Command):
173    description = "Clean Python build directories"
174    user_options = []
175
176    def initialize_options(self):
177        pass
178
179    def finalize_options(self):
180        pass
181
182    def run(self):
183        try:
184            remove_tree("build")
185        except KeyboardInterrupt as e:
186            raise e
187        except Exception:
188            pass
189
190        try:
191            remove_tree("dist")
192        except KeyboardInterrupt as e:
193            raise e
194        except Exception:
195            pass
196
197# The data files to install along with the module
198install_data_files = []
199for data_dir in ["magic", "config", "plugins", "modules", "core"]:
200        install_data_files.append("%s%s*" % (data_dir, os.path.sep))
201
202# Install the module, script, and support files
203setup(name = MODULE_NAME,
204      version = "2.1.1",
205      description = "Firmware analysis tool",
206      author = "Craig Heffner",
207      url = "https://github.com/devttys0/%s" % MODULE_NAME,
208
209      requires = [],
210      packages = [MODULE_NAME],
211      package_data = {MODULE_NAME : install_data_files},
212      scripts = [os.path.join("scripts", SCRIPT_NAME)],
213
214      cmdclass = {'clean' : CleanCommand, 'uninstall' : UninstallCommand, 'idainstall' : IDAInstallCommand, 'idauninstall' : IDAUnInstallCommand}
215)
216
217