mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-24 01:25:37 +01:00
Merge branch 'powershell-utilities' of github.com:calebstewart/pwncat into powershell-utilities
This commit is contained in:
commit
f78dd52500
@ -162,7 +162,7 @@ class EnumerateModule(BaseModule):
|
||||
|
||||
# Yield all the know facts which have already been enumerated
|
||||
if cache and types:
|
||||
yield from (
|
||||
cached = [
|
||||
f
|
||||
for f in target.facts
|
||||
if f.source == self.name
|
||||
@ -170,9 +170,13 @@ class EnumerateModule(BaseModule):
|
||||
any(fnmatch.fnmatch(item_type, req_type) for req_type in types)
|
||||
for item_type in f.types
|
||||
)
|
||||
)
|
||||
]
|
||||
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
|
||||
if (self.name in target.enumerate_state) and (
|
||||
@ -194,19 +198,22 @@ class EnumerateModule(BaseModule):
|
||||
# Only add the item if it doesn't exist
|
||||
for f in target.facts:
|
||||
if f == item:
|
||||
yield Status(item.title(session))
|
||||
break
|
||||
else:
|
||||
target.facts.append(item)
|
||||
|
||||
# Don't yield the actual fact if we didn't ask for this type
|
||||
if not types or any(
|
||||
any(fnmatch.fnmatch(item_type, req_type) for req_type in types)
|
||||
for item_type in item.types
|
||||
):
|
||||
yield item
|
||||
# Don't yield the actual fact if we didn't ask for this type
|
||||
if not types or any(
|
||||
any(fnmatch.fnmatch(item_type, req_type) for req_type in types)
|
||||
for item_type in item.types
|
||||
):
|
||||
for c in cached:
|
||||
if item == c:
|
||||
break
|
||||
else:
|
||||
yield Status(item.title(session))
|
||||
yield item
|
||||
else:
|
||||
yield Status(item.title(session))
|
||||
|
||||
# Update state for restricted modules
|
||||
if self.SCHEDULE == Schedule.ONCE:
|
||||
|
83
pwncat/modules/windows/enumerate/domain/computer.py
Normal file
83
pwncat/modules/windows/enumerate/domain/computer.py
Normal 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)
|
38
pwncat/modules/windows/enumerate/domain/fileserver.py
Normal file
38
pwncat/modules/windows/enumerate/domain/fileserver.py
Normal 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
|
Loading…
Reference in New Issue
Block a user