Merge branch 'platforms' of github.com:calebstewart/pwncat into platforms
This commit is contained in:
commit
814c3458a7
|
@ -22,9 +22,6 @@ class Group(Fact):
|
|||
def __repr__(self):
|
||||
return f"""Group(gid={self.id}, name={repr(self.name)}, members={repr(self.members)})"""
|
||||
|
||||
def __str__(self):
|
||||
return f"""{rich.markup.escape(self.name)}, gid={self.id}, members={rich.markup.escape(",".join((m for m in self.members)))}"""
|
||||
|
||||
|
||||
class User(Fact):
|
||||
"""Basic representation of a user on the target system. Individual platform
|
||||
|
|
|
@ -23,9 +23,6 @@ class Group(Fact):
|
|||
def __repr__(self):
|
||||
return f"""Group(gid={self.id}, name={repr(self.name)}, members={repr(self.members)})"""
|
||||
|
||||
def __str__(self):
|
||||
return f"""{rich.markup.escape(self.name)}, gid={self.id}, members={rich.markup.escape(",".join((m for m in self.members)))}"""
|
||||
|
||||
|
||||
class User(Fact):
|
||||
"""Basic representation of a user on the target system. Individual platform
|
||||
|
|
|
@ -5,7 +5,7 @@ from pwncat.facts import User, Group
|
|||
|
||||
|
||||
class LinuxUser(User):
|
||||
""" Linux-specific user definition """
|
||||
"""Linux-specific user definition"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -33,7 +33,7 @@ class LinuxUser(User):
|
|||
|
||||
|
||||
class LinuxGroup(Group):
|
||||
""" Linux-specific group definition """
|
||||
"""Linux-specific group definition"""
|
||||
|
||||
def __init__(self, source, group_name, hash, gid, members, password=None):
|
||||
|
||||
|
|
|
@ -48,13 +48,12 @@ class PrivateKeyData(Fact):
|
|||
self.encrypted: bool = encrypted
|
||||
""" Is this private key encrypted? """
|
||||
|
||||
def __str__(self):
|
||||
def title(self, session):
|
||||
if self.uid == 0:
|
||||
color = "red"
|
||||
else:
|
||||
color = "green"
|
||||
return f"Potential private key for [{color}]{self.uid}[/{color}] at [cyan]{rich.markup.escape(self.path)}[/cyan]"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
def description(self, session) -> str:
|
||||
return self.content
|
||||
|
|
|
@ -32,12 +32,6 @@ class FileCapabilityData(Fact):
|
|||
line += "]"
|
||||
return line
|
||||
|
||||
def __str__(self):
|
||||
line = f"[cyan]{rich.markup.escape(self.path)}[/cyan] -> ["
|
||||
line += ",".join(f"[blue]{rich.markup.escape(c)}[/blue]" for c in self.caps)
|
||||
line += "]"
|
||||
return line
|
||||
|
||||
|
||||
class Module(EnumerateModule):
|
||||
"""Enumerate capabilities of the binaries of the remote host"""
|
||||
|
@ -57,10 +51,19 @@ class Module(EnumerateModule):
|
|||
|
||||
# Process the standard output from the command
|
||||
with proc.stdout as stream:
|
||||
for path in stream:
|
||||
for line in stream:
|
||||
# Parse out path and capability list
|
||||
path, caps = [x.strip() for x in path.strip().split(" ")]
|
||||
caps = caps.split(",")
|
||||
|
||||
fact = FileCapabilityData(self.name, path, caps)
|
||||
# getcap is inconsistent in how it displays output.
|
||||
# We can try and handle both cases.
|
||||
if " = " in line:
|
||||
# /usr/bin/mtr-packet = cap_net_raw+ep
|
||||
path, caps = [x.strip() for x in line.strip().split("=")]
|
||||
caps = caps.split(",")
|
||||
fact = FileCapabilityData(self.name, path, caps)
|
||||
else:
|
||||
path, caps = [x.strip() for x in line.strip().split(" ")]
|
||||
caps = caps.split(",")
|
||||
fact = FileCapabilityData(self.name, path, caps)
|
||||
|
||||
yield fact
|
||||
|
|
|
@ -9,6 +9,7 @@ import pwncat
|
|||
from pwncat.db import Fact
|
||||
from pwncat.modules import Status
|
||||
from pwncat.platform.linux import Linux
|
||||
from pwncat.subprocess import CalledProcessError
|
||||
from pwncat.modules.enumerate import Schedule, EnumerateModule
|
||||
|
||||
|
||||
|
@ -92,7 +93,7 @@ class Module(EnumerateModule):
|
|||
)
|
||||
user_entries = proc.stdout
|
||||
|
||||
except FileNotFoundError:
|
||||
except CalledProcessError as exc:
|
||||
# The crontab command doesn't exist :(
|
||||
return
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ class Module(EnumerateModule):
|
|||
"ps -eo pid,ppid,uid,user,command --no-header -ww",
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
if proc.stdout:
|
||||
|
|
|
@ -8,6 +8,12 @@ from pwncat.util import Init
|
|||
from pwncat.platform.linux import Linux
|
||||
from pwncat.modules.enumerate import Schedule, EnumerateModule
|
||||
|
||||
"""
|
||||
TODO: This is weirdly inconsistent. Sometimes it works, other times it misses
|
||||
like more than half of the services. We don't know why. systemctl might be
|
||||
doing something weird?
|
||||
"""
|
||||
|
||||
|
||||
class ServiceData(Fact):
|
||||
def __init__(self, source, name, uid, state, pid):
|
||||
|
@ -80,7 +86,7 @@ class Module(EnumerateModule):
|
|||
try:
|
||||
pid = int(section[0])
|
||||
except ValueError as exc:
|
||||
pwncat.console.log(repr(data), markup=False)
|
||||
continue
|
||||
if section[1] == "[not set]":
|
||||
uid = 0
|
||||
else:
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
import dataclasses
|
||||
from enum import IntFlag
|
||||
|
||||
from rich.table import Table
|
||||
|
||||
from pwncat.platform.windows import Windows
|
||||
from pwncat.modules.enumerate import Schedule, EnumerateModule
|
||||
|
||||
|
||||
class LuidAttributes(IntFlag):
|
||||
|
||||
DISABLED = 0x00
|
||||
SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x01
|
||||
SE_PRIVILEGE_ENABLED = 0x02
|
||||
SE_PRIVILEGE_REMOVE = 0x04
|
||||
SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TokenPrivilegeData:
|
||||
|
||||
privilege: str
|
||||
attributes: LuidAttributes
|
||||
token_handle: int
|
||||
pid: int
|
||||
|
||||
def __str__(self):
|
||||
|
||||
if self.attributes == LuidAttributes.DISABLED:
|
||||
color = "red"
|
||||
else:
|
||||
color = "green"
|
||||
|
||||
attrs = str(self.attributes)
|
||||
attrs = attrs.replace("LuidAttributes.", "")
|
||||
attrs = attrs.replace("|", "[/cyan]|[cyan]")
|
||||
attrs = "[cyan]" + attrs + "[/cyan]"
|
||||
|
||||
return f"[{color}]{self.privilege}[/{color}] -> {attrs}"
|
||||
|
||||
|
||||
class Module(EnumerateModule):
|
||||
"""Enumerate user privileges using PowerView's Get-ProcessTokenPrivilege"""
|
||||
|
||||
PROVIDES = ["user.privs"]
|
||||
PLATFORM = [Windows]
|
||||
|
||||
def enumerate(self, session: "pwncat.manager.Session"):
|
||||
|
||||
# Ensure that powerview is loaded
|
||||
session.run(
|
||||
"manage.powershell.import",
|
||||
path="PowerShellMafia/PowerSploit/Privesc/PowerUp.ps1",
|
||||
)
|
||||
|
||||
# Grab our current token privileges
|
||||
results = session.platform.powershell("Get-ProcessTokenPrivilege")
|
||||
if len(results) == 0:
|
||||
session.log("[red]error[/red]: Get-ProcessTokenPrivilege failed")
|
||||
return
|
||||
|
||||
# They end up in an array in an array
|
||||
privs = results[0]
|
||||
|
||||
# Create our enumeration data types
|
||||
for priv in privs:
|
||||
yield "user.privs", TokenPrivilegeData(
|
||||
privilege=priv["Privilege"],
|
||||
attributes=LuidAttributes(priv["Attributes"]),
|
||||
token_handle=priv["TokenHandle"],
|
||||
pid=priv["ProcessId"],
|
||||
)
|
|
@ -1299,7 +1299,7 @@ class Linux(Platform):
|
|||
" stty sane",
|
||||
f" stty rows {rows} columns {columns}",
|
||||
f" export TERM='{TERM}'",
|
||||
"""export PS1='$(command printf "\\033[01;31m(remote)\\033[0m \\033[01;33m$(whoami)@$(hostname)\\033[0m:\\033[1;36m$PWD\\033[0m$ ")'""",
|
||||
"""export PS1='$(command printf "\\033[01;31m(remote)\\033[0m \\033[01;33m$(whoami)@$(hostname)\\033[0m:\\033[1;36m$PWD\\033[0m\\$ ")'""",
|
||||
]
|
||||
)
|
||||
+ "\n"
|
||||
|
|
Loading…
Reference in New Issue