mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-30 20:34:15 +01:00
Replaced tasklist with Get-WmiObject
This should speed up process enumeration from absolutely horrid to mildly annoying.
This commit is contained in:
parent
1dcd58208b
commit
95ba763202
@ -1,54 +1,87 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
import rich.markup
|
||||||
|
|
||||||
import pwncat
|
import pwncat
|
||||||
import rich.markup
|
|
||||||
from pwncat import util
|
from pwncat import util
|
||||||
from pwncat.db import Fact
|
from pwncat.db import Fact
|
||||||
from pwncat.modules import ModuleFailed
|
from pwncat.modules import Status, ModuleFailed
|
||||||
from pwncat.modules.enumerate import EnumerateModule, Schedule
|
|
||||||
from pwncat.platform import PlatformError
|
from pwncat.platform import PlatformError
|
||||||
from pwncat.platform.windows import PowershellError, Windows
|
from pwncat.platform.windows import Windows, PowershellError
|
||||||
|
from pwncat.modules.enumerate import Schedule, EnumerateModule
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
TODO: This needs to be converted to use WMIC, and CSVreader.
|
|
||||||
"""
|
|
||||||
|
|
||||||
class ProcessData(Fact):
|
class ProcessData(Fact):
|
||||||
|
""" Remote process information """
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
source,
|
source: str,
|
||||||
process_name: str,
|
name: str,
|
||||||
pid: int,
|
pid: int,
|
||||||
session_name: str,
|
session: Optional[int],
|
||||||
status: str,
|
owner: str,
|
||||||
user_name: str,
|
state: int,
|
||||||
|
path: str,
|
||||||
|
commandline: str,
|
||||||
|
handle: int,
|
||||||
):
|
):
|
||||||
super().__init__(source=source, types=["system.processes"])
|
super().__init__(source=source, types=["system.processes"])
|
||||||
|
|
||||||
self.process_name: str = process_name
|
self.name: str = name
|
||||||
|
|
||||||
self.pid: int = pid
|
self.pid: int = pid
|
||||||
|
self.session: int = session
|
||||||
|
self.owner: str = owner
|
||||||
|
self.state: int = state
|
||||||
|
self.path: str = path
|
||||||
|
self.commandline: str = commandline
|
||||||
|
self.handle: int = handle
|
||||||
|
|
||||||
self.session_name: str = session_name
|
if self.path == "":
|
||||||
|
self.path = None
|
||||||
self.status: str = status
|
if self.owner == "":
|
||||||
|
self.owner = None
|
||||||
self.user_name: str = user_name
|
|
||||||
|
|
||||||
def title(self, session):
|
def title(self, session):
|
||||||
out = f"[cyan]{rich.markup.escape(self.process_name)}[/cyan] (PID [blue]{self.pid}[/blue]) status [yellow]{rich.markup.escape(self.status)}[/yellow] as user [magenta]{self.user_name}[/magenta]"
|
""" Build a formatted description for this process """
|
||||||
if "NT AUTHORITY\\SYSTEM" in self.user_name:
|
|
||||||
out = out.replace("[magenta]", "[red]").replace("[/magenta]", "[/red]")
|
out = "[cyan]{name}[/cyan] (PID [blue]{pid}[/blue]) is {state} "
|
||||||
if self.status == "Running":
|
|
||||||
out = out.replace("[yellow]", "[green]").replace("[/yellow]", "[/green]")
|
state = "[green]running[/green]"
|
||||||
return out
|
if self.state == 7:
|
||||||
|
state = "[red]terminated[/red]"
|
||||||
|
elif self.state == 8:
|
||||||
|
state = "[yellow]stopped[/red]"
|
||||||
|
|
||||||
|
if self.owner is None:
|
||||||
|
color = "yellow"
|
||||||
|
owner = "unknown"
|
||||||
|
else:
|
||||||
|
color = "magenta"
|
||||||
|
|
||||||
|
owner = session.find_user(uid=self.owner)
|
||||||
|
if owner is None:
|
||||||
|
owner = session.find_group(gid=self.owner)
|
||||||
|
if owner is None:
|
||||||
|
owner = f"SID({repr(self.owner)})"
|
||||||
|
else:
|
||||||
|
owner = owner.name
|
||||||
|
|
||||||
|
out += "owned by [{color}]{owner}[/{color}]"
|
||||||
|
|
||||||
|
return out.format(
|
||||||
|
name=rich.markup.escape(self.name),
|
||||||
|
pid=self.pid,
|
||||||
|
owner=owner,
|
||||||
|
color=color,
|
||||||
|
state=state,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Module(EnumerateModule):
|
class Module(EnumerateModule):
|
||||||
"""Enumerate the current Windows Defender settings on the target"""
|
""" Retrieve a list of current processes running on the target """
|
||||||
|
|
||||||
PROVIDES = ["system.processes"]
|
PROVIDES = ["system.processes"]
|
||||||
PLATFORM = [Windows]
|
PLATFORM = [Windows]
|
||||||
@ -56,46 +89,37 @@ class Module(EnumerateModule):
|
|||||||
|
|
||||||
def enumerate(self, session):
|
def enumerate(self, session):
|
||||||
|
|
||||||
proc = session.platform.Popen(
|
script = """
|
||||||
["tasklist", "/V", "/FO", "CSV"],
|
Get-WmiObject -Class Win32_Process | % {
|
||||||
stderr=pwncat.subprocess.DEVNULL,
|
[PSCustomObject]@{
|
||||||
stdout=pwncat.subprocess.PIPE
|
commandline=$_.CommandLine;
|
||||||
)
|
description=$_.Description;
|
||||||
|
path=$_.ExecutablePath;
|
||||||
|
state=$_.ExecutionState;
|
||||||
|
handle=$_.Handle;
|
||||||
|
name=$_.Name;
|
||||||
|
id=$_.ProcessId;
|
||||||
|
session=$_.SessionId;
|
||||||
|
owner=$_.GetOwnerSid().Sid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
# Process the standard output from the command
|
try:
|
||||||
with proc.stdout as stream:
|
yield Status("requesting process list...")
|
||||||
for line in stream:
|
processes = session.platform.powershell(script, depth=2)[0]
|
||||||
try:
|
except (IndexError, PowershellError) as exc:
|
||||||
line = line.strip().decode('utf-8')
|
raise ModuleFailed(f"failed to get running processes: {exc}")
|
||||||
except UnicodeDecodeError as exc:
|
|
||||||
try:
|
|
||||||
line = line.strip().decode('utf-16')
|
|
||||||
except UnicodeDecodeError as exc:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if (
|
for proc in processes:
|
||||||
not line
|
yield ProcessData(
|
||||||
or '"Image Name","PID","Session Name","Session#","Mem Usage","Status","User Name","CPU Time","Window Title"'
|
source=self.name,
|
||||||
in line
|
name=proc["name"],
|
||||||
):
|
pid=proc["id"],
|
||||||
continue
|
session=proc.get("session"),
|
||||||
|
owner=proc["owner"],
|
||||||
(
|
state=proc["state"],
|
||||||
process_name,
|
commandline=proc["commandline"],
|
||||||
pid,
|
path=proc["path"],
|
||||||
session_name,
|
handle=proc["handle"],
|
||||||
_,
|
)
|
||||||
_,
|
|
||||||
status,
|
|
||||||
user_name,
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
) = (x.strip('"') for x in line.split('",'))
|
|
||||||
|
|
||||||
pid = int(pid)
|
|
||||||
|
|
||||||
yield ProcessData(
|
|
||||||
self.name, process_name, pid, session_name, status, user_name
|
|
||||||
)
|
|
||||||
|
|
||||||
proc.wait()
|
|
||||||
|
Loading…
Reference in New Issue
Block a user