> For the complete documentation index, see [llms.txt](https://www.impacket.wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.impacket.wiki/how-to-guides/remote-execution.md).

# Remote Execution

You have administrator credentials and need to run a command on a remote Windows machine and retrieve the output.

## What you need

* An account with local administrator privileges on the target
* Network access to port 445, port 135, or both, depending on the method

## Choosing a method

Each method uses different ports, creates different artifacts, and has different tradeoffs:

* **SCMR service creation** — port 445. Creates and starts a temporary Windows service. Generates Event ID 7045.
* **SMBExec variant** — port 445. Creates a service but writes output to a share file instead of a named pipe. Same artifacts as SCMR but different output channel.
* **WMI via DCOM** — port 135 + dynamic RPC. Creates a `Win32_Process`. Output retrieval requires a second channel.
* **DCOM via MMC20.Application** — port 135 + dynamic RPC. Uses `ExecuteShellCommand` through the MMC DCOM object. No WMI involvement.
* **Task Scheduler (TSCH)** — port 445. Creates and runs a scheduled task. Generates Task Scheduler events (106, 200).

***

## Method 1: SCMR service creation

The most common approach. Create a service whose binary path is a `cmd.exe` invocation, start it, read the output file.

```python
from impacket.smbconnection import SMBConnection
from impacket.dcerpc.v5 import transport, scmr
import random, string, time

smb_conn = SMBConnection(target_ip, target_ip)
smb_conn.login(username, password, domain)

rpctransport = transport.DCERPCTransportFactory(rf'ncacn_np:{target_ip}[\pipe\svcctl]')
rpctransport.set_smb_connection(smb_conn)
dce = rpctransport.get_dce_rpc()
dce.connect()
dce.bind(scmr.MSRPC_UUID_SCMR)

resp = scmr.hROpenSCManagerW(dce)
sc_handle = resp['lpScHandle']

# Generate random names to avoid collisions
svc_name = ''.join(random.choices(string.ascii_letters, k=8))
out_file = ''.join(random.choices(string.ascii_letters, k=8)) + '.tmp'
command = 'whoami /all'

binary_path = f'%COMSPEC% /Q /c {command} > %SystemRoot%\\Temp\\{out_file} 2>&1'

resp = scmr.hRCreateServiceW(
    dce, sc_handle, svc_name + '\x00', svc_name + '\x00',
    lpBinaryPathName=binary_path + '\x00',
    dwStartType=scmr.SERVICE_DEMAND_START,
)
svc_handle = resp['lpServiceHandle']

try:
    scmr.hRStartServiceW(dce, svc_handle)
except Exception:
    pass

time.sleep(2)

# Read output
tree_id = smb_conn.connectTree('ADMIN$')
fid = smb_conn.openFile(tree_id, f'Temp\\{out_file}')
output = smb_conn.readFile(tree_id, fid)
smb_conn.closeFile(tree_id, fid)
smb_conn.deleteFile('ADMIN$', f'Temp\\{out_file}')
print(output.decode())

# Clean up the service
scmr.hRDeleteService(dce, svc_handle)
scmr.hRCloseServiceHandle(dce, svc_handle)
scmr.hRCloseServiceHandle(dce, sc_handle)
dce.disconnect()
smb_conn.close()
```

***

## Method 2: SMBExec variant (batch file + output file)

Instead of directly embedding the command in the service binary path, write a batch file, execute it through a service, and read the output from a second file. This handles longer or more complex commands:

```python
batch_file = '%TEMP%\\execute.bat'
output_file = '%SystemRoot%\\Temp\\__output'
command = 'ipconfig /all'

# The service creates the batch, runs it, and cleans up
binary_path = (
    f'%COMSPEC% /Q /c echo {command} ^> {output_file} 2^>^&1 > {batch_file} '
    f'& %COMSPEC% /Q /c {batch_file} '
    f'& del {batch_file}'
)

resp = scmr.hRCreateServiceW(
    dce, sc_handle, svc_name + '\x00', svc_name + '\x00',
    lpBinaryPathName=binary_path + '\x00',
    dwStartType=scmr.SERVICE_DEMAND_START,
)
svc_handle = resp['lpServiceHandle']

try:
    scmr.hRStartServiceW(dce, svc_handle)
except Exception:
    pass

scmr.hRDeleteService(dce, svc_handle)
scmr.hRCloseServiceHandle(dce, svc_handle)

time.sleep(2)

# Read from ADMIN$ share
tree_id = smb_conn.connectTree('ADMIN$')
fid = smb_conn.openFile(tree_id, 'Temp\\__output')
output = smb_conn.readFile(tree_id, fid)
smb_conn.closeFile(tree_id, fid)
smb_conn.deleteFile('ADMIN$', 'Temp\\__output')
```

***

## Method 3: WMI process creation via DCOM

Uses WMI's `Win32_Process.Create` through DCOM. The command runs on the target, but output must be retrieved separately (typically over SMB).

```python
from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom import wmi
from impacket.dcerpc.v5.dtypes import NULL

dcom = DCOMConnection(target_ip, username, password, domain)
iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
iWbemLevel1Login.RemRelease()

win32_process, _ = iWbemServices.GetObject('Win32_Process')

output_path = 'C:\\Windows\\Temp\\wmi_out.tmp'
command = f'cmd.exe /Q /c whoami /all > {output_path} 2>&1'

win32_process.Create(command, 'C:\\', None)
dcom.disconnect()

# Retrieve output over SMB
time.sleep(2)
smb_conn = SMBConnection(target_ip, target_ip)
smb_conn.login(username, password, domain)
tree_id = smb_conn.connectTree('ADMIN$')
fid = smb_conn.openFile(tree_id, 'Temp\\wmi_out.tmp')
output = smb_conn.readFile(tree_id, fid)
smb_conn.closeFile(tree_id, fid)
smb_conn.deleteFile('ADMIN$', 'Temp\\wmi_out.tmp')
smb_conn.close()
```

For running WQL queries to check the process status or wait for completion:

```python
# Re-establish DCOM and check if the process finished
enumerator = iWbemServices.ExecQuery(
    'SELECT ProcessId, Name FROM Win32_Process WHERE Name = "cmd.exe"'
)
while True:
    try:
        results = enumerator.Next(0xffffffff, 1)
    except Exception:
        break
    for obj in results:
        record = obj.getProperties()
        print(f"  PID {record['ProcessId']['value']}: {record['Name']['value']}")
```

***

## Method 4: DCOM via MMC20.Application

Uses the `MMC20.Application` COM object's `ExecuteShellCommand` method. This avoids WMI entirely and uses a different DCOM activation path.

```python
from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.oaut import IID_IDispatch, IDispatch, DISPPARAMS, DISPATCH_PROPERTYGET, VARIANT, VARENUM, DISPATCH_METHOD
from impacket.dcerpc.v5.dtypes import NULL
from impacket import uuid

dcom = DCOMConnection(target_ip, username, password, domain)

# MMC20.Application CLSID
clsid = uuid.string_to_bin('49B2791A-B1AE-4C90-9B8E-E860BA07F889')
iInterface = dcom.CoCreateInstanceEx(clsid, IID_IDispatch)
iMMC = IDispatch(iInterface)

# Navigate: MMC -> Document -> ActiveView -> ExecuteShellCommand
resp = iMMC.GetIDsOfNames(('Document',))
dispParams = DISPPARAMS(None, False)
dispParams['rgvarg'] = NULL
dispParams['rgdispidNamedArgs'] = NULL
dispParams['cArgs'] = 0
dispParams['cNamedArgs'] = 0

resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], [])
# Continue navigating the COM object hierarchy to reach ExecuteShellCommand
# and invoke it with cmd.exe and your arguments
```

This method is more complex to set up due to the IDispatch navigation, but it creates different artifacts than WMI (no Win32\_Process creation events).

***

## Method 5: Task Scheduler (TSCH)

Creates a scheduled task, runs it immediately, and deletes it.

```python
from impacket.dcerpc.v5 import transport, tsch

rpctransport = transport.DCERPCTransportFactory(rf'ncacn_np:{target_ip}[\pipe\atsvc]')
rpctransport.set_credentials(username, password, domain)
dce = rpctransport.get_dce_rpc()
dce.connect()
dce.bind(tsch.MSRPC_UUID_TSCHS)

task_name = '\\' + ''.join(random.choices(string.ascii_letters, k=8))
output_path = 'C:\\Windows\\Temp\\task_out.tmp'

xml = f"""<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2025-01-01T00:00:00</StartBoundary>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="LocalSystem">
      <UserId>S-1-5-18</UserId>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>true</Hidden>
  </Settings>
  <Actions Context="LocalSystem">
    <Exec>
      <Command>cmd.exe</Command>
      <Arguments>/Q /c whoami /all &gt; {output_path} 2&gt;&amp;1</Arguments>
    </Exec>
  </Actions>
</Task>"""

tsch.hSchRpcRegisterTask(dce, task_name, xml, tsch.TASK_CREATE, NULL, tsch.TASK_LOGON_NONE)
tsch.hSchRpcRun(dce, task_name)

time.sleep(3)

tsch.hSchRpcDelete(dce, task_name)
dce.disconnect()

# Retrieve output over SMB
smb_conn = SMBConnection(target_ip, target_ip)
smb_conn.login(username, password, domain)
tree_id = smb_conn.connectTree('ADMIN$')
fid = smb_conn.openFile(tree_id, 'Temp\\task_out.tmp')
output = smb_conn.readFile(tree_id, fid)
smb_conn.closeFile(tree_id, fid)
smb_conn.deleteFile('ADMIN$', 'Temp\\task_out.tmp')
smb_conn.close()
```

The task XML runs as SYSTEM with the `Hidden` flag set. Adjust the `Principal` if you need to run as the relayed user instead.

***

## Method 6: MSSQL xp\_cmdshell (port 1433)

If your only access is through a SQL Server instance with sysadmin privileges:

```python
from impacket import tds

client = tds.MSSQL(target_ip, 1433)
client.connect()
client.login(None, sql_user, sql_pass)

# Enable xp_cmdshell
client.sql_query("EXEC sp_configure 'show advanced options', 1; RECONFIGURE;")
client.printReplies()
client.sql_query("EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;")
client.printReplies()

# Execute
client.sql_query("EXEC xp_cmdshell 'whoami /all'")
client.printReplies()
for row in client.rows:
    if row['output']:
        print(row['output'])

# Disable xp_cmdshell if it was originally off
client.sql_query("EXEC sp_configure 'xp_cmdshell', 0; RECONFIGURE;")
client.sql_query("EXEC sp_configure 'show advanced options', 0; RECONFIGURE;")
client.printReplies()

client.disconnect()
```

Output comes back directly through the SQL result set, no need for SMB output retrieval.

***

## Choosing based on your situation

If port 445 is available and you want simplicity, use SCMR (Method 1). If you need to avoid service creation events but have DCOM access, use WMI (Method 3) or MMC20 (Method 4). If SMB and DCOM are both blocked but you have SQL access, use xp\_cmdshell (Method 6). If you need the command to run as SYSTEM regardless of your account's local privileges, use TSCH (Method 5) with the SYSTEM principal.

For all methods except MSSQL, output retrieval requires SMB access to read the output file. If SMB read access is blocked, you can redirect output to a share the account can access, or use xp\_cmdshell where output returns inline.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://www.impacket.wiki/how-to-guides/remote-execution.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
