mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 19:04:15 +01:00
Added domain site and group enumerations
This commit is contained in:
parent
063eecbbf8
commit
5f0e4bb1c0
@ -119,7 +119,7 @@ class Group(Fact):
|
||||
self.members: PersistentList = PersistentList(members)
|
||||
|
||||
def __repr__(self):
|
||||
return f"""Group(gid={self.id}, name={repr(self.name)}, members={repr(self.members)})"""
|
||||
return f"""Group(gid={repr(self.id)}, name={repr(self.name)}, members={repr(self.members)})"""
|
||||
|
||||
|
||||
class User(Fact):
|
||||
|
@ -115,8 +115,10 @@ class WindowsGroup(Group):
|
||||
description: str,
|
||||
principal_source: str,
|
||||
members: List[str],
|
||||
domain: Optional[str] = None,
|
||||
):
|
||||
super().__init__(source=source, name=name, gid=gid, members=members)
|
||||
|
||||
self.group_description: str = description
|
||||
self.principal_source: str = principal_source
|
||||
self.domain: Optional[str] = domain
|
||||
|
89
pwncat/modules/windows/enumerate/domain/group.py
Normal file
89
pwncat/modules/windows/enumerate/domain/group.py
Normal file
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
from typing import Any, Dict, List, Optional
|
||||
from collections import namedtuple
|
||||
|
||||
from pwncat.db import Fact
|
||||
from pwncat.modules import Status, ModuleFailed
|
||||
from pwncat.facts.windows import WindowsGroup
|
||||
from pwncat.platform.windows import Windows, PowershellError
|
||||
from pwncat.modules.enumerate import Schedule, EnumerateModule
|
||||
|
||||
|
||||
class DomainGroup(WindowsGroup):
|
||||
""" Builds on Windows Groups to add domain specific information """
|
||||
|
||||
def __init__(self, source: str, domain: str, data: Dict, members: List[str]):
|
||||
super().__init__(
|
||||
source=source,
|
||||
name=data["samaccountname"],
|
||||
gid=data["objectsid"],
|
||||
description=data.get("description"),
|
||||
principal_source=None,
|
||||
domain=domain,
|
||||
members=members,
|
||||
)
|
||||
|
||||
self.types.append("domain.group")
|
||||
|
||||
self.grouptype: int = data.get("grouptype") or 0
|
||||
self.samaccounttype: int = data.get("samaccounttype") or 0
|
||||
self.objectclass: List[str] = data.get("objectclass") or []
|
||||
self.cn: str = data.get("cn") or None
|
||||
self.distinguishedname: Optional[str] = data.get("distinguishedname") or None
|
||||
self.objectcategory: str = data.get("objectcategory")
|
||||
|
||||
def __repr__(self):
|
||||
return f"""DomainGroup(gid={repr(self.id)}, name={repr(self.name)}, domain={repr(self.domain)}, members={repr(self.members)})"""
|
||||
|
||||
|
||||
class Module(EnumerateModule):
|
||||
""" Retrieve information on all domain computers """
|
||||
|
||||
PLATFORM = [Windows]
|
||||
PROVIDES = ["domain.group", "group"]
|
||||
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:
|
||||
domain = session.run("enumerate.domain")[0]
|
||||
except IndexError:
|
||||
# Not a domain joined machine
|
||||
return
|
||||
|
||||
try:
|
||||
yield Status("requesting domain groups")
|
||||
groups = session.platform.powershell("Get-DomainGroup")[0]
|
||||
except (IndexError, PowershellError) as exc:
|
||||
# Doesn't appear to be a domain joined group
|
||||
return
|
||||
|
||||
if isinstance(groups, dict):
|
||||
groups = [groups]
|
||||
|
||||
for group in groups:
|
||||
|
||||
try:
|
||||
yield Status(
|
||||
f"[cyan]{group['samaccountname']}[/cyan]: requesting members"
|
||||
)
|
||||
members = session.platform.powershell(
|
||||
f"Get-DomainGroupMember \"{group['samaccountname']}\""
|
||||
)[0]
|
||||
|
||||
if isinstance(members, dict):
|
||||
members = [members]
|
||||
|
||||
except (IndexError, PowershellError) as exc:
|
||||
members = []
|
||||
|
||||
members = [member["MemberSID"] for member in members]
|
||||
|
||||
yield DomainGroup(
|
||||
self.name, domain=domain["Name"], data=group, members=members
|
||||
)
|
50
pwncat/modules/windows/enumerate/domain/site.py
Normal file
50
pwncat/modules/windows/enumerate/domain/site.py
Normal file
@ -0,0 +1,50 @@
|
||||
#!/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 SiteObject(Fact):
|
||||
def __init__(self, source: str, data: Dict):
|
||||
super().__init__(source=source, types=["domain.site"])
|
||||
|
||||
self.site = data
|
||||
|
||||
def __getitem__(self, name: str):
|
||||
""" Shortcut for getting properties from the `self.site` property. """
|
||||
|
||||
return self.site[name]
|
||||
|
||||
def title(self, session: "pwncat.manager.Session"):
|
||||
return f"[cyan]{self['distinguishedname']}[/cyan]"
|
||||
|
||||
|
||||
class Module(EnumerateModule):
|
||||
""" Retrieve information on all domain computers """
|
||||
|
||||
PLATFORM = [Windows]
|
||||
PROVIDES = ["domain.site"]
|
||||
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 sites")
|
||||
sites = session.platform.powershell("Get-DomainSite")[0]
|
||||
except (IndexError, PowershellError) as exc:
|
||||
# Doesn't appear to be a domain joined site
|
||||
return
|
||||
|
||||
if isinstance(sites, dict):
|
||||
yield SiteObject(self.name, sites)
|
||||
else:
|
||||
yield from (SiteObject(self.name, site) for site in sites)
|
Loading…
Reference in New Issue
Block a user