Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create schtask.py #54

Merged
merged 12 commits into from
Oct 10, 2023
Merged

Create schtask.py #54

merged 12 commits into from
Oct 10, 2023

Conversation

Dfte
Copy link
Contributor

@Dfte Dfte commented Oct 3, 2023

Add the schtask module that can be used to impersonate loggedon users and run commands on their behalf.
To run a whoami as the WHITEFLAG\Administrateur:

netexec smb 192.168.56.10 -u Administrateur -p pass -M schtask -o CMD="whoami" USER="WHITEFLAG\Administrateur"

This can be used to run remote commands as well:

image

Add the schtask module that can be used to impersonate loggedon users and run commands on their behalf.

Signed-off-by: Defte <aurelien.chalot@protonmail.com>
nxc/modules/schtask.py Outdated Show resolved Hide resolved
@zblurx
Copy link
Collaborator

zblurx commented Oct 3, 2023

In accordance with Defte, I've updated the code to manage the codec.
LGTM now

zblurx
zblurx previously approved these changes Oct 3, 2023
@Marshall-Hallenbeck
Copy link
Collaborator

Please also add this to the tests/e2e_commands.txt in the appropriate section where other SMB modules are tested.

@Shad0wC0ntr0ller
Copy link
Contributor

This looks good, seems to do something similar to ATExec. Some opsec considerations, there is a hardcoded date in the XML used to build the scheduled task

2015-07-15T20:35:13.2757294

we can use a function to generate to get the latest date and build the xml file

something like

from datetime import datetime

def get_current_date():
    # Get current date and time
    now = datetime.now()

    # Format it to match the format in the XML: "YYYY-MM-DDTHH:MM:SS.ssssss"
    return now.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]

current_date = get_current_date()
xml = f"""<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
    <!-- ... -->
    <StartBoundary>{current_date}</StartBoundary>
    <!-- ... -->
    <Principal id="TrustedInstaller">
        <UserId>S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464</UserId>
        <RunLevel>HighestAvailable</RunLevel>
    </Principal>
    <!-- ... -->
</Task>"""

Lastly, i have not fully went through the module to see how your doing it, but we can also swap out the principal id from LocalSystem to "TrustedInstaller" . you also need to change the sid to "S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464". Just another option for more privileges. This is shown in my xml example

@Dfte
Copy link
Contributor Author

Dfte commented Oct 4, 2023

This looks good, seems to do something similar to ATExec. Some opsec considerations, there is a hardcoded date in the XML used to build the scheduled task

2015-07-15T20:35:13.2757294

we can use a function to generate to get the latest date and build the xml file

something like

from datetime import datetime

def get_current_date():
    # Get current date and time
    now = datetime.now()

    # Format it to match the format in the XML: "YYYY-MM-DDTHH:MM:SS.ssssss"
    return now.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]

current_date = get_current_date()
xml = f"""<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
    <!-- ... -->
    <StartBoundary>{current_date}</StartBoundary>
    <!-- ... -->
    <Principal id="TrustedInstaller">
        <UserId>S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464</UserId>
        <RunLevel>HighestAvailable</RunLevel>
    </Principal>
    <!-- ... -->
</Task>"""

Lastly, i have not fully went through the module to see how your doing it, but we can also swap out the principal id from LocalSystem to "TrustedInstaller" . you also need to change the sid to "S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464". Just another option for more privileges. This is shown in my xml example

Yeah we could replace the date! However I'm not sure it is necessarry to replace the TrustedInstaller

Add @Shad0wC0ntr0ller snippet to remove hardcoded date.

Signed-off-by: Defte <aurelien.chalot@protonmail.com>
@Dfte
Copy link
Contributor Author

Dfte commented Oct 5, 2023

I have added the code to remove the hardcoded date. :)

Rename the module to prevent confusion.

Signed-off-by: Defte <aurelien.chalot@protonmail.com>
@XiaoliChan
Copy link
Contributor

XiaoliChan commented Oct 5, 2023

I think this can merged into atexec.py, just add a argument in protocol args like "--atexec-user"

nxc 192.168.1.1 -u pwn -p password -x whoami --exec-method atexec --atexec-user {impersonated user}

This module basically is atexec.py

Modify the variable name to schtask_as
Change the description

Signed-off-by: Defte <aurelien.chalot@protonmail.com>
@Dfte
Copy link
Contributor Author

Dfte commented Oct 5, 2023

I think this can merged into atexec.py, just add a argument in protocol args like "--atexec-user"

nxc 192.168.1.1 -u pwn -p password -x whoami --exec-method atexec --atexec-user {impersonated user}

This module basically is atexec.py

Yeah we thought of doing that but it implies adding another argument and refactor a few things. We thought it'd be easier to add a module on its own

Fix typo

Signed-off-by: Defte <aurelien.chalot@protonmail.com>
@NeffIsBack NeffIsBack self-assigned this Oct 5, 2023
@NeffIsBack
Copy link
Contributor

image
🎉

@NeffIsBack
Copy link
Contributor

image

It looks to me that there is a different error when the user is not logged on or does not exist. Would that maybe be worth to catch and explain that info to the user?

Copy link
Contributor

@NeffIsBack NeffIsBack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rest looks good to me! Also tested and is working on my side

nxc/modules/schtask_as.py Outdated Show resolved Hide resolved
@Dfte
Copy link
Contributor Author

Dfte commented Oct 6, 2023

image It looks to me that there is a different error when the user is not logged on or does not exist. Would that maybe be worth to catch and explain that info to the user?

Definitely, let me do that quickly

- Sed "g/atexec/schtask_as/s"
- Better error output (unknown username, task has not run)
- Added the output.decode("cp437") for french caracters

Signed-off-by: Defte <aurelien.chalot@protonmail.com>
… session, stop printing empty output messages.
@NeffIsBack
Copy link
Contributor

image
Working on my side now!
@Dfte check if the changes make sense to you

Copy link
Contributor

@NeffIsBack NeffIsBack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Dfte
Copy link
Contributor Author

Dfte commented Oct 9, 2023

I have never been able to obtain the "User doesn't exist on the domain" but the PR seems good to me!

@NeffIsBack NeffIsBack merged commit 314b7f6 into Pennyw0rth:develop Oct 10, 2023
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants