Skip to content

Commit 778899a

Browse files
committed
Fixed escalation shell tracking
1 parent 49b23fd commit 778899a

File tree

3 files changed

+38
-20
lines changed

3 files changed

+38
-20
lines changed

pwncat/commands/escalate.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import pwncat
55
from pwncat.util import console
6+
from pwncat.manager import Manager
67
from pwncat.modules import ModuleFailed
78
from pwncat.commands import Complete, Parameter, CommandDefinition
89

@@ -133,7 +134,7 @@ def list_abilities(self, manager, args):
133134
elif not found:
134135
console.log("[yellow]warning[/yellow]: no direct escalations found")
135136

136-
def do_escalate(self, manager: "pwncat.manager.Manager", task, user, args):
137+
def do_escalate(self, manager: Manager, task, user, args):
137138
"""Execute escalations until we find one that works"""
138139

139140
attempted = []
@@ -178,7 +179,7 @@ def do_escalate(self, manager: "pwncat.manager.Manager", task, user, args):
178179

179180
time.sleep(0.1)
180181

181-
manager.target.platform.refresh_uid()
182+
manager.target.platform.context_changed()
182183

183184
# Construct the escalation link
184185
link = Link(manager.target, escalation, result)
@@ -199,7 +200,10 @@ def do_escalate(self, manager: "pwncat.manager.Manager", task, user, args):
199200
manager.print(f" - {link}")
200201

201202
return result
202-
except ModuleFailed:
203+
except ModuleFailed as exc:
204+
manager.target.log(
205+
f"{escalation.title(manager.target)}: failed: {exc}"
206+
)
203207
failed.append(escalation)
204208

205209
if not args.recursive:
@@ -219,6 +223,7 @@ def do_escalate(self, manager: "pwncat.manager.Manager", task, user, args):
219223
time.sleep(0.1)
220224

221225
manager.target.platform.refresh_uid()
226+
222227
link = Link(manager.target, escalation, result)
223228

224229
if escalation.type == "escalate.replace":
@@ -229,5 +234,8 @@ def do_escalate(self, manager: "pwncat.manager.Manager", task, user, args):
229234
chain.append(link)
230235
attempted.append(escalation.uid)
231236
break
232-
except ModuleFailed:
237+
except ModuleFailed as exc:
238+
manager.target.log(
239+
f"{escalation.title(manager.target)}: failed: {exc}"
240+
)
233241
failed.append(escalation)

pwncat/platform/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,10 @@ def __str__(self):
570570
"""Retrieve a string describing the platform connection"""
571571
return str(self.channel)
572572

573+
@abstractmethod
574+
def context_changed(self):
575+
"""Used to notify the platform that the pwncat framework changed shell or user context."""
576+
573577
@abstractmethod
574578
def exit(self):
575579
"""Exit this session"""

pwncat/platform/linux.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,11 +1047,11 @@ def compile(
10471047
with open(source, "rb") as src:
10481048
with self.tempfile(suffix=".c", mode="wb") as dest:
10491049
shutil.copyfileobj(src, dest)
1050-
real_sources.append(dest.name)
1050+
real_sources.append(str(dest.name))
10511051
else:
10521052
with self.tempfile(mode="w", suffix=".c") as dest:
10531053
shutil.copyfileobj(source, dest)
1054-
real_sources.append(dest.name)
1054+
real_sources.append(str(dest.name))
10551055

10561056
if output is None:
10571057
# We just need to create a file...
@@ -1630,6 +1630,24 @@ def sudo(
16301630

16311631
return proc
16321632

1633+
def context_changed(self):
1634+
"""Shell or user context has been manually changed by the framework"""
1635+
1636+
# Update self.shell just in case the user changed shells
1637+
try:
1638+
# Get the PID of the running shell
1639+
pid = self.getenv("$")
1640+
# Grab the path to the executable representing the shell
1641+
self.shell = self.Path("/proc", pid, "exe").readlink()
1642+
except (FileNotFoundError, PermissionError, OSError):
1643+
# Fall back to SHELL even though it's not really trustworthy
1644+
self.shell = self.getenv("SHELL")
1645+
if self.shell is None or self.shell == "":
1646+
self.shell = "/bin/sh"
1647+
1648+
# Refresh the currently tracked user and group IDs
1649+
self.refresh_uid()
1650+
16331651
@property
16341652
def interactive(self) -> bool:
16351653
"""
@@ -1656,20 +1674,8 @@ def interactive(self, value: bool):
16561674
self.channel.drain()
16571675
self._interactive = False
16581676

1659-
# Update self.shell just in case the user changed shells
1660-
try:
1661-
# Get the PID of the running shell
1662-
pid = self.getenv("$")
1663-
# Grab the path to the executable representing the shell
1664-
self.shell = self.Path("/proc", pid, "exe").readlink()
1665-
except (FileNotFoundError, PermissionError, OSError):
1666-
# Fall back to SHELL even though it's not really trustworthy
1667-
self.shell = self.getenv("SHELL")
1668-
if self.shell is None or self.shell == "":
1669-
self.shell = "/bin/sh"
1670-
1671-
# Refresh the currently tracked user and group IDs
1672-
self.refresh_uid()
1677+
# update current user and shell variable
1678+
self.context_changed()
16731679
else:
16741680

16751681
# Going interactive requires a pty

0 commit comments

Comments
 (0)