diff --git a/CHANGELOG.md b/CHANGELOG.md index 5281d12a5..32774b8be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,10 +61,13 @@ The table below shows which release corresponds to each branch, and what date th - [#1261][1261] Misc `run_in_new_terminal` improvements (notably gdb terminated by default) - [#1695][1695] Allow using GDB Python API - [#1735][1735] Python 3.9 support in safeeval +- [#1738][1738] Which function support custom search path + - process also looks now at `env['PATH']` to find the path for the executable [1261]: https://github.com/Gallopsled/pwntools/pull/1261 [1695]: https://github.com/Gallopsled/pwntools/pull/1695 [1735]: https://github.com/Gallopsled/pwntools/pull/1735 +[1738]: https://github.com/Gallopsled/pwntools/pull/1738 ## 4.4.0 (`beta`) diff --git a/pwnlib/tubes/process.py b/pwnlib/tubes/process.py index a13cc0169..79921abda 100644 --- a/pwnlib/tubes/process.py +++ b/pwnlib/tubes/process.py @@ -278,14 +278,14 @@ def __init__(self, argv = None, #: Full path to the executable self.executable = executable_val + #: Environment passed on envp + self.env = os.environ if env is None else env_val + if self.executable is None: if shell: self.executable = '/bin/sh' else: - self.executable = which(self.argv[0]) - - #: Environment passed on envp - self.env = os.environ if env is None else env_val + self.executable = which(self.argv[0], path=self.env.get('PATH')) self._cwd = os.path.realpath(cwd or os.path.curdir) @@ -550,6 +550,9 @@ def _validate(self, cwd, executable, argv, env): if not isinstance(executable, str): executable = executable.decode('utf-8') + env = os.environ if env is None else env + + path = env.get('PATH') # Do not change absolute paths to binaries if executable.startswith(os.path.sep): pass @@ -558,8 +561,8 @@ def _validate(self, cwd, executable, argv, env): # target directory. # # For example, 'sh' - elif os.path.sep not in executable and which(executable): - executable = which(executable) + elif os.path.sep not in executable and which(executable, path=path): + executable = which(executable, path=path) # Either there is a path component, or the binary is not in $PATH # For example, 'foo/bar' or 'bar' with cwd=='foo' @@ -583,8 +586,6 @@ def _validate(self, cwd, executable, argv, env): # # Create a duplicate so we can modify it safely - env = os.environ if env is None else env - env2 = {} for k,v in env.items(): if not isinstance(k, (bytes, six.text_type)): diff --git a/pwnlib/util/misc.py b/pwnlib/util/misc.py index 9cc37b20a..68986aa7d 100644 --- a/pwnlib/util/misc.py +++ b/pwnlib/util/misc.py @@ -131,7 +131,7 @@ def write(path, data = b'', create_dir = False, mode = 'w'): with open(path, mode) as f: f.write(data) -def which(name, all = False): +def which(name, all = False, path=None): """which(name, flags = os.X_OK, all = False) -> str or str set Works as the system command ``which``; searches $PATH for ``name`` and @@ -159,7 +159,7 @@ def which(name, all = False): isroot = os.getuid() == 0 out = set() try: - path = os.environ['PATH'] + path = path or os.environ['PATH'] except KeyError: log.exception('Environment variable $PATH is not set') for p in path.split(os.pathsep):