From aa528a5a87e651528cdfb5c8d5bf31dae23fdc60 Mon Sep 17 00:00:00 2001 From: Caleb Stewart Date: Sun, 19 Sep 2021 02:50:19 -0400 Subject: [PATCH] Added Linux which fallback routine --- CHANGELOG.md | 5 +++-- pwncat/platform/linux.py | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0916400..dba04c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,9 @@ and simply didn't have the time to go back and retroactively create one. - Fixed verbose logging handler to be __unique__ for every `channel` - Fixed docstrings in `Command` modules - Changed docker base image to `python3.9-alpine` to fix python version issues. -- Added logic for calling correct paramiko method when reloading an encrypted SSH privat ekey ([#185](https://github.com/calebstewart/issues/185)). -- Forced `Stream.RAW` for all GTFOBins interaction ([#195](https://github.com/calebstewart/issues/195)). +- Added logic for calling correct paramiko method when reloading an encrypted SSH privat ekey ([#185](https://github.com/calebstewart/pwncat/issues/185)). +- Forced `Stream.RAW` for all GTFOBins interaction ([#195](https://github.com/calebstewart/pwncat/issues/195)). +- Added custom `which` implementation for linux when `which` is not available ([#193](https://github.com/calebstewart/pwncat/issues/193)). ### Added - Added alternatives to `bash` to be used during _shell upgrade_ for a _better shell_ - Added a warning message when a `KeyboardInterrupt` is caught diff --git a/pwncat/platform/linux.py b/pwncat/platform/linux.py index 8ed1daf..8b58546 100644 --- a/pwncat/platform/linux.py +++ b/pwncat/platform/linux.py @@ -621,6 +621,9 @@ class Linux(Platform): self.shell = "/bin/sh" self.channel.sendline(b" export SHELL=/bin/sh") + if True or self._do_which("which") is None: + self._do_which = self._do_custom_which + if os.path.basename(self.shell) in ["sh", "dash"]: # Try to find a better shell # a custom `pwncat shell prompt` may not be available for all shells @@ -816,6 +819,25 @@ class Linux(Platform): for name in p.stdout.split("\n"): yield name + def _do_custom_which(self, name: str): + """This is custom which implementation that will not find built-in commands. + It is altogether inferior to the real which, but if `which` isn't available, + it will do the job.""" + + try: + result = self.run( + f"""IFS=':'; for path in $PATH; do if [ -f "$path/{name}" ]; then echo "$path/{name}"; break; fi; done; IFS=' '""", + shell=True, + capture_output=True, + check=True, + text=True, + ) + if result.stdout.rstrip("\n") == "": + return None + return result.stdout.rstrip("\n") + except CalledProcessError: + return None + def _do_which(self, name: str) -> str: """ Locate the specified binary on the remote host. Normally, this is done through