1
0
mirror of https://github.com/calebstewart/pwncat.git synced 2024-11-30 20:34:15 +01:00

Added computer and file server enumerations

This commit is contained in:
Caleb Stewart 2021-06-05 00:43:47 -04:00
parent 895744a6bd
commit bf5c1fd6cd
3 changed files with 139 additions and 11 deletions

View File

@ -162,7 +162,7 @@ class EnumerateModule(BaseModule):
# Yield all the know facts which have already been enumerated # Yield all the know facts which have already been enumerated
if cache and types: if cache and types:
yield from ( cached = [
f f
for f in target.facts for f in target.facts
if f.source == self.name if f.source == self.name
@ -170,9 +170,13 @@ class EnumerateModule(BaseModule):
any(fnmatch.fnmatch(item_type, req_type) for req_type in types) any(fnmatch.fnmatch(item_type, req_type) for req_type in types)
for item_type in f.types for item_type in f.types
) )
) ]
elif cache: elif cache:
yield from (f for f in target.facts if f.source == self.name) cached = [f for f in target.facts if f.source == self.name]
else:
cached = []
yield from cached
# Check if the module is scheduled to run now # Check if the module is scheduled to run now
if (self.name in target.enumerate_state) and ( if (self.name in target.enumerate_state) and (
@ -194,7 +198,6 @@ class EnumerateModule(BaseModule):
# Only add the item if it doesn't exist # Only add the item if it doesn't exist
for f in target.facts: for f in target.facts:
if f == item: if f == item:
yield Status(item.title(session))
break break
else: else:
target.facts.append(item) target.facts.append(item)
@ -204,6 +207,10 @@ class EnumerateModule(BaseModule):
any(fnmatch.fnmatch(item_type, req_type) for req_type in types) any(fnmatch.fnmatch(item_type, req_type) for req_type in types)
for item_type in item.types for item_type in item.types
): ):
for c in cached:
if item == c:
break
else:
yield item yield item
else: else:
yield Status(item.title(session)) yield Status(item.title(session))

View File

@ -0,0 +1,83 @@
#!/usr/bin/env python3
from typing import Any, Dict
from collections import namedtuple
from pwncat.db import Fact
from pwncat.modules import Status, ModuleFailed
from pwncat.platform.windows import Windows, PowershellError
from pwncat.modules.enumerate import Schedule, EnumerateModule
class ComputerObject(Fact):
def __init__(self, source: str, data: Dict):
super().__init__(source=source, types=["domain.computer"])
self.computer = data
def __getitem__(self, name: str):
""" Shortcut for getting properties from the `self.domain` property. """
return self.computer[name]
def title(self, session: "pwncat.manager.Session"):
return f"[blue]{self['dnshostname']}[/blue] ([cyan]{self['name']}[/cyan])"
def is_dc(self):
""" Query if this computer object is a domain controller """
uac = self.computer.get("useraccountcontrol") or 0
return (uac & 0x2000) > 0
def is_rodc(self):
""" Query if this computer object is a read only domain controller """
uac = self.computer.get("useraccountcontrol") or 0
return (uac & 0x04000000) > 0
def description(self, session: "pwncat.manager.Session"):
output = []
if self.is_rodc():
output.append("[red]Read-Only Domain Controller[/red]")
elif self.is_dc():
output.append("[bold red]Domain Controller[/bold red]")
output.append(f"Computer SID: [cyan]{self['objectsid']}[/cyan]")
output.append(f"Machine Account: [cyan]{self['samaccountname']}[/cyan]")
output.append(
f"Operating System: [blue]{self['operatingsystem']} {self['operatingsystemversion']}[/blue]"
)
output.append(
f"Distinguished Name: [magenta]{self['distinguishedname']}[/magenta]"
)
return "\n".join(output)
class Module(EnumerateModule):
""" Retrieve information on all domain computers """
PLATFORM = [Windows]
PROVIDES = ["domain.computer"]
SCHEDULE = Schedule.ONCE
def enumerate(self, session: "pwncat.manager.Session"):
""" Perform enumeration """
# Ensure we have PowerView loaded
yield Status("loading powersploit recon")
session.run("powersploit", group="recon")
try:
yield Status("requesting domain computers")
computers = session.platform.powershell("Get-DomainComputer")[0]
except (IndexError, PowershellError) as exc:
# Doesn't appear to be a domain joined computer
return
if isinstance(computers, dict):
yield ComputerObject(self.name, computers)
else:
yield from (ComputerObject(self.name, computer) for computer in computers)

View File

@ -0,0 +1,38 @@
#!/usr/bin/env python3
from typing import Any, Dict
from collections import namedtuple
from pwncat.db import Fact
from pwncat.modules import Status, ModuleFailed
from pwncat.platform.windows import Windows, PowershellError
from pwncat.modules.enumerate import Schedule, EnumerateModule
class Module(EnumerateModule):
""" Retrieve information on all domain computers """
PLATFORM = [Windows]
PROVIDES = ["domain.fileserver"]
SCHEDULE = Schedule.ONCE
def enumerate(self, session: "pwncat.manager.Session"):
""" Perform enumeration """
# Ensure we have PowerView loaded
yield Status("loading powersploit recon")
session.run("powersploit", group="recon")
try:
yield Status("requesting domain file servers")
names = session.platform.powershell("Get-DomainFileServer")[0]
except (IndexError, PowershellError) as exc:
return
if not isinstance(names, list):
names = [names]
names = [name.lower() for name in names]
for computer in session.run("enumerate.domain.computer"):
if computer["name"].lower() in names:
yield computer