mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-24 01:25:37 +01:00
Replaced systemd service enumeration
This version is compatible with update-to-date and older systemd as seen in CentOS 7.9. Fixes #103.
This commit is contained in:
parent
2de02baee9
commit
377f948a93
@ -1,10 +1,13 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
import subprocess
|
||||||
|
|
||||||
import rich.markup
|
import rich.markup
|
||||||
|
|
||||||
import pwncat
|
import pwncat
|
||||||
from pwncat.db import Fact
|
from pwncat.db import Fact
|
||||||
from pwncat.util import Init
|
from pwncat.util import Init
|
||||||
|
from pwncat.modules import Status, ModuleFailed
|
||||||
|
from pwncat.subprocess import CalledProcessError
|
||||||
from pwncat.platform.linux import Linux
|
from pwncat.platform.linux import Linux
|
||||||
from pwncat.modules.enumerate import Schedule, EnumerateModule
|
from pwncat.modules.enumerate import Schedule, EnumerateModule
|
||||||
|
|
||||||
@ -50,6 +53,37 @@ class ServiceData(Fact):
|
|||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
def build_service_data(session, source, service):
|
||||||
|
""" Build a service data object from a dictionary """
|
||||||
|
|
||||||
|
# Grab the user name if available
|
||||||
|
user = service.get("User", None).strip()
|
||||||
|
|
||||||
|
# Resolve to user object
|
||||||
|
if user is not None:
|
||||||
|
user = session.find_user(name=user)
|
||||||
|
|
||||||
|
# If the user existed, grab the ID
|
||||||
|
if user is not None:
|
||||||
|
uid = user.id
|
||||||
|
else:
|
||||||
|
# Otherwise, assume it was root
|
||||||
|
uid = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
pid = int(service.get("MainPID", None))
|
||||||
|
except ValueError:
|
||||||
|
pid = None
|
||||||
|
|
||||||
|
return ServiceData(
|
||||||
|
source=source,
|
||||||
|
name=service["Id"].strip(),
|
||||||
|
uid=uid,
|
||||||
|
state=service.get("SubState", "unknown").strip(),
|
||||||
|
pid=pid,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Module(EnumerateModule):
|
class Module(EnumerateModule):
|
||||||
"""Enumerate systemd services on the victim"""
|
"""Enumerate systemd services on the victim"""
|
||||||
|
|
||||||
@ -66,32 +100,38 @@ class Module(EnumerateModule):
|
|||||||
return
|
return
|
||||||
break
|
break
|
||||||
|
|
||||||
# Request the list of services
|
# Ensure we build the user cache
|
||||||
# For the generic call, we grab the name, PID, user, and state
|
session.find_user(uid=0)
|
||||||
# of each process. If some part of pwncat needs more, it can
|
|
||||||
# request it specifically.
|
|
||||||
|
|
||||||
data = session.platform.run(
|
try:
|
||||||
"systemctl show --type=service --no-pager --all --value --property Id --property MainPID --property UID --property SubState \\*",
|
# List all services and grab the details
|
||||||
capture_output=True,
|
proc = session.platform.Popen(
|
||||||
text=True,
|
"systemctl list-units --type=service --no-pager --all --no-legend --plain | cut -d' ' -f1 | xargs systemctl show --no-pager --all --property Id --property User --property MainPID --property SubState",
|
||||||
check=True,
|
shell=True,
|
||||||
)
|
stdout=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
if data.stdout:
|
service = {}
|
||||||
data = data.stdout.split("\n\n")
|
|
||||||
|
|
||||||
for segment in data:
|
for line in proc.stdout:
|
||||||
section = segment.split("\n")
|
if line.strip() == "":
|
||||||
try:
|
# We can only build a service structure if we know the name
|
||||||
pid = int(section[0])
|
if "Id" in service and service["Id"].strip() != "":
|
||||||
except ValueError as exc:
|
yield build_service_data(session, self.name, service)
|
||||||
|
|
||||||
|
# Reset service dict
|
||||||
|
service = {}
|
||||||
continue
|
continue
|
||||||
if section[1] == "[not set]":
|
|
||||||
uid = 0
|
|
||||||
else:
|
|
||||||
uid = int(section[1])
|
|
||||||
name = section[2].removesuffix(".service")
|
|
||||||
state = section[3]
|
|
||||||
|
|
||||||
yield ServiceData(self.name, name, uid, state, pid)
|
# Store the key-value pair in the dict
|
||||||
|
name, *value = line.split("=")
|
||||||
|
value = "=".join(value)
|
||||||
|
service[name] = value
|
||||||
|
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
proc.wait(2)
|
||||||
|
except TimeoutError:
|
||||||
|
proc.kill()
|
||||||
|
proc.wait()
|
||||||
|
Loading…
Reference in New Issue
Block a user