> 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/tutorials/wmi-and-dcom-ops.md).

# WMI Queries Over DCOM

## What you'll build

A script that connects to a remote Windows machine over DCOM, runs WMI queries, and lists all running processes with their PIDs and owners.

## Prerequisites

* Everything from the [DCE/RPC tutorial](https://github.com/ThatTotallyRealMyth/Impacket-Documentation/tree/main/tutorials/dcerpc-in-impacket.md)
* A target Windows machine with DCOM enabled (default on most Windows installations)
* An account with administrator privileges on the target

| Placeholder | Meaning                          | Example         |
| ----------- | -------------------------------- | --------------- |
| `TARGET_IP` | IP of the target machine         | `192.168.56.10` |
| `USERNAME`  | Admin account                    | `Administrator` |
| `PASSWORD`  | Password                         | `Password123!`  |
| `DOMAIN`    | Domain or `.` for local accounts | `.`             |

```bash
touch wmi_basics.py
```

***

## Step 1: Create a DCOM connection

```python
from impacket.dcerpc.v5.dcomrt import DCOMConnection

target_ip = "192.168.56.10"
username  = "Administrator"
password  = "Password123!"
domain    = "."

dcom = DCOMConnection(target_ip, username, password, domain)
print(f"[+] DCOM connection established to {target_ip}")
```

Run it. `DCOMConnection` handles the Endpoint Mapper lookup, the RPC bind, and the DCOM object activation in one call.

***

## Step 2: Get an IWbemServices interface

WMI access goes through two objects. First you get `IWbemLevel1Login`, then call `NTLMLogin` on it to get `IWbemServices`, which is the interface you run queries against:

```python
from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.wmi import IID_IWbemLevel1Login, IWbemLevel1Login, CLSID_WbemLevel1Login

target_ip = "192.168.56.10"
username  = "Administrator"
password  = "Password123!"
domain    = "."

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

# Activate the WbemLevel1Login object
iInterface = dcom.CoCreateInstanceEx(CLSID_WbemLevel1Login, IID_IWbemLevel1Login)
iWbemLevel1Login = IWbemLevel1Login(iInterface)

# Log in to the WMI namespace
iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)

# Release the login object, we don't need it anymore
iWbemLevel1Login.RemRelease()

print("[+] Connected to root/cimv2")
```

Add the missing import at the top:

```python
from impacket.dcerpc.v5.dtypes import NULL
```

***

## Step 3: Run your first WQL query

`IWbemServices.ExecQuery()` takes a WQL string (WMI Query Language, which looks like SQL) and returns an enumerator:

```python
# Query for the operating system name
enumerator = iWbemServices.ExecQuery('SELECT Caption, Version FROM Win32_OperatingSystem')

while True:
    try:
        results = enumerator.Next(0xffffffff, 1)
    except Exception:
        break

    for obj in results:
        record = obj.getProperties()
        print(f"  OS:      {record['Caption']['value']}")
        print(f"  Version: {record['Version']['value']}")
```

Run it:

```
  OS:      Microsoft Windows 10 Pro
  Version: 10.0.19045
```

The pattern: call `ExecQuery()`, then loop on `enumerator.Next()` until it raises an exception (no more results). Each result is an `IWbemClassObject` whose `getProperties()` returns a dictionary of property names to their values.

***

## Step 4: Enumerate running processes

```python
enumerator = iWbemServices.ExecQuery(
    'SELECT ProcessId, Name, CommandLine FROM Win32_Process'
)

while True:
    try:
        results = enumerator.Next(0xffffffff, 1)
    except Exception:
        break

    for obj in results:
        record = obj.getProperties()
        pid  = record['ProcessId']['value']
        name = record['Name']['value']
        cmd  = record['CommandLine']['value'] or ""
        print(f"  {pid:<8} {name:<30} {cmd[:60]}")
```

Run it. You'll see every process on the target machine.

***

## Step 5: Query a different WMI class

WQL works against any WMI class. Try listing installed services:

```python
enumerator = iWbemServices.ExecQuery(
    'SELECT Name, State, StartName FROM Win32_Service'
)

while True:
    try:
        results = enumerator.Next(0xffffffff, 1)
    except Exception:
        break

    for obj in results:
        record = obj.getProperties()
        name  = record['Name']['value']
        state = record['State']['value']
        acct  = record['StartName']['value'] or ""
        print(f"  {name:<40} {state:<12} {acct}")
```

The query structure is always the same: change the class name and the `SELECT` fields, iterate the same way.

***

## Step 6: Clean up the connection

```python
dcom.disconnect()
print("[*] Disconnected")
```

DCOM runs a background ping thread to keep objects alive. `disconnect()` stops it and tears down the RPC session.

***

## Mini project: process enumerator

```python
#!/usr/bin/env python3
"""
wmi_procs.py

Lists all running processes on a remote machine via WMI/DCOM.

Usage:
    python3 wmi_procs.py <target> <domain> <username> <password>
"""

import sys
from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.wmi import (
    CLSID_WbemLevel1Login, IID_IWbemLevel1Login, IWbemLevel1Login,
)
from impacket.dcerpc.v5.dtypes import NULL


def connect_wmi(target, domain, username, password):
    dcom = DCOMConnection(target, username, password, domain)
    iInterface = dcom.CoCreateInstanceEx(CLSID_WbemLevel1Login, IID_IWbemLevel1Login)
    iWbemLevel1Login = IWbemLevel1Login(iInterface)
    iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
    iWbemLevel1Login.RemRelease()
    return dcom, iWbemServices


def get_processes(iWbemServices):
    processes = []
    enumerator = iWbemServices.ExecQuery(
        'SELECT ProcessId, Name, ParentProcessId, CommandLine FROM Win32_Process'
    )

    while True:
        try:
            results = enumerator.Next(0xffffffff, 1)
        except Exception:
            break

        for obj in results:
            record = obj.getProperties()
            processes.append({
                'pid':    record['ProcessId']['value'],
                'name':   record['Name']['value'],
                'ppid':   record['ParentProcessId']['value'],
                'cmd':    record['CommandLine']['value'] or '',
            })

    return processes


def main():
    if len(sys.argv) != 5:
        print("Usage: python3 wmi_procs.py <target> <domain> <username> <password>")
        sys.exit(1)

    target, domain, username, password = sys.argv[1:]

    dcom, iWbemServices = connect_wmi(target, domain, username, password)
    processes = get_processes(iWbemServices)

    print(f"[*] {len(processes)} processes on {target}\n")
    print(f"  {'PID':<8} {'PPID':<8} {'Name':<30} Command Line")
    print(f"  {'---':<8} {'----':<8} {'----':<30} ------------")

    for p in sorted(processes, key=lambda x: x['pid']):
        print(f"  {p['pid']:<8} {p['ppid']:<8} {p['name']:<30} {p['cmd'][:50]}")

    dcom.disconnect()


if __name__ == "__main__":
    main()
```

### Test it

```bash
python3 wmi_procs.py 192.168.56.10 . Administrator 'Password123!'
```

***

## Review: what you learned

1. **`DCOMConnection(target, user, password, domain)`** establishes a DCOM session.
2. **`CoCreateInstanceEx(CLSID, IID)`** activates a remote COM object and returns an interface.
3. **`IWbemLevel1Login.NTLMLogin(namespace, NULL, NULL)`** authenticates to a WMI namespace and returns `IWbemServices`.
4. **`IWbemServices.ExecQuery(wql_string)`** runs a WQL query and returns an enumerator.
5. **`enumerator.Next(timeout, count)`** retrieves result objects. Loop until it raises an exception.
6. **`obj.getProperties()`** returns a dictionary of `{property_name: {value: ..., qualifiers: ...}}`.
7. **`dcom.disconnect()`** tears down the session and stops the background ping thread.


---

# 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/tutorials/wmi-and-dcom-ops.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.
