Skip to content

Back to the category index / Back to the command index

Registers a temporary task through Task Scheduler RPC to run a command on a target Windows host.

ItemDetails
Implementationexamples/atexec.py
CategoryRemote execution / WMI / services
Size339 lines
DistributionInstalled as a script through scripts=examples/*.py in setup.py

Run python examples/atexec.py -h for the current option definitions.

ArgumentDescription
target[[domain/]username[:password]@]
commandCommand to run on the target
-session-idExisting logon session to use (no output or cmd.exe)
-tsAdd a timestamp to each log message
-silentcommandRun the given command without cmd.exe (no output)
-overflowSet the task XML Author to 4,000 bytes, affecting Security Event 4698 logging; cannot be used with -author-log
-author-logPut the specified value in the task XML Author field, affecting the Author field in Security Event 4698; cannot be used with -overflow
-debugEnable debug output
-codecHelp text generated dynamically from the runtime value
-hashesNTLM hashes in LMHASH:NTHASH format
-no-passDo not prompt for a password (useful with -k)
-kUse Kerberos authentication. Look for matching credentials in the ccache file named by KRB5CCNAME; if none are valid, use those specified on the command line
-aesKeyAES key for Kerberos authentication (128 or 256 bits)
-dc-ipDomain controller IP address; if omitted, use the domain name (FQDN) from the target parameter
-keytabRead SPN keys from a keytab file

The tool creates an SMB/RPC transport, binds to the TSCH interface, and registers and runs an XML task with a random name. If output capture is enabled, it redirects the command’s stdout and stderr to a temporary file on a share and reads it back over SMB. It deletes the task and temporary file after completion or failure.

This method uses the Windows Task Scheduler RPC interface as its control plane without transferring a persistent agent. play() creates a DCE/RPC transport, binds to the TSCH interface, and builds an XML definition with a random task name and the command to execute. Registration, execution, and completion checks are separate RPC operations.

To capture output, the registered command line includes a wrapper that redirects stdout and stderr to a temporary file on ADMIN$ or another share. After the task runs, the tool repeatedly tries to open that file through SMB. It waits for a bounded period when a share violation occurs or the file has not yet been created, treating these as signs that execution is still in progress. -silentcommand skips output retrieval and stops after starting the task.

Registration can succeed even if the tool fails before execution, so cleanup only at the end of the success path is insufficient. The task and output file are separate resources; check for each before removing it. A session ID changes the conditions for execution in an interactive session, so account for XML schema and scheduler version differences.

SymbolLocationWhere to trace its responsibility
TSCH_EXEC45__init__(), play(), doStuff()
ModuleMain names used
impacket.exampleslogger
impacketversion
impacket.dcerpc.v5transport, tsch
impacket.dcerpc.v5.dtypesNULL
impacket.dcerpc.v5.rpcrtRPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_LEVEL_PKT_PRIVACY
impacket.examples.utilsparse_target
impacket.krb5.keytabKeytab
Import nameDistribution packageImport path and declaration status
sixsixImported directly; declared

Output, side effects, and required privileges

Section titled “Output, side effects, and required privileges”
  • Some operations change the target’s state. Check the target name, SID, and path before making changes.
  • Some paths use temporary resources such as remote services, tasks, files, shares, and WMI/RPC resources. Cleaning them up after an abnormal exit is part of the behavior contract.
  • On failure, use protocol status codes to determine whether name resolution, connection, authentication, service state, or permissions caused the stop.
  • Even without an explicit cleanup function, check for finally-equivalent paths and closure or deletion of protocol handles.

The code depends on dcerpc.v5.tsch, transport, Kerberos keytabs, and the shared target parser. TSCH_EXEC.play() and doStuff() handle orchestration. When changing the code, check polling, session-ID and silent-command branches, and cleanup.