> 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/enum-info-via-dcerpc.md).

# Enumerating Remote Servers Via DCERPC

You need to gather host information, logged-on users, shares, sessions, network transports, disk inventory, and event log data from remote Windows machines for administrative inventory or pre-engagement reconnaissance.

## What you need

* Valid credentials on the target (admin for some interfaces, standard user for others)
* Network access to port 445

***

## The common flow

Every query below follows the same pattern: create a transport, set credentials, connect, bind to the interface UUID, call a helper function, parse the response, disconnect. The only things that change are the pipe name, the UUID, and the helper function.

***

## Query server information via SRVS (\pipe\srvsvc)

### Get server name, OS version, and platform

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

rpctransport = transport.DCERPCTransportFactory(rf'ncacn_np:{target_ip}[\pipe\srvsvc]')
rpctransport.set_credentials(username, password, domain)

dce = rpctransport.get_dce_rpc()
dce.connect()
dce.bind(srvs.MSRPC_UUID_SRVS)

resp = srvs.hNetrServerGetInfo(dce, 101)
info = resp['InfoStruct']['ServerInfo101']
print(f"Name:     {info['sv101_name']}")
print(f"Version:  {info['sv101_version_major']}.{info['sv101_version_minor']}")
print(f"Platform: {info['sv101_platform_id']}")
print(f"Comment:  {info['sv101_comment']}")

dce.disconnect()
```

### Enumerate shares

```python
resp = srvs.hNetrShareEnum(dce, 1)
for share in resp['InfoStruct']['ShareInfo']['Level1']['Buffer']:
    name = share['shi1_netname'][:-1]
    share_type = share['shi1_type']
    remark = share['shi1_remark'][:-1]
    print(f"  {name:<20} type={share_type:<12} {remark}")
```

### Get detailed share information

```python
resp = srvs.hNetrShareGetInfo(dce, 'ADMIN$\x00', 2)
share_info = resp['InfoStruct']['ShareInfo2']
print(f"  Path:        {share_info['shi2_path'][:-1]}")
print(f"  Permissions: {share_info['shi2_permissions']}")
print(f"  Max users:   {share_info['shi2_max_uses']}")
print(f"  Current:     {share_info['shi2_current_uses']}")
```

### List active sessions

```python
resp = srvs.hNetrSessionEnum(dce, NULL, NULL, 10)
for session in resp['InfoStruct']['SessionInfo']['Level10']['Buffer']:
    client = session['sesi10_cname'][:-1]
    user = session['sesi10_username'][:-1]
    time = session['sesi10_time']
    idle = session['sesi10_idle_time']
    print(f"  {user:<20} from {client:<20} active={time}s idle={idle}s")
```

### List open files

```python
resp = srvs.hNetrFileEnum(dce, NULL, NULL, 3)
for f in resp['InfoStruct']['FileInfo']['Level3']['Buffer']:
    file_id = f['fi3_id']
    path = f['fi3_pathname'][:-1]
    user = f['fi3_username'][:-1]
    print(f"  [{file_id}] {path} opened by {user}")
```

### Enumerate server disks

```python
resp = srvs.hNetrServerDiskEnum(dce, 0)
for disk in resp['DiskInfoStruct']['Buffer']:
    disk_name = disk['Disk']
    if disk_name and disk_name.strip('\x00'):
        print(f"  Disk: {disk_name.strip(chr(0))}")
```

### Get remote time of day

```python
resp = srvs.hNetrRemoteTOD(dce)
tod = resp['BufferPtr']
print(f"  Date: {tod['tod_month']}/{tod['tod_day']}/{tod['tod_year']}")
print(f"  Time: {tod['tod_hours']}:{tod['tod_mins']:02d}:{tod['tod_secs']:02d}")
print(f"  TZ offset: {tod['tod_timezone']} minutes from GMT")
```

### Enumerate network transports

```python
resp = srvs.hNetrServerTransportEnum(dce, 0)
for t in resp['InfoStruct']['XportInfo']['Level0']['Buffer']:
    transport_name = t['svti0_transportname'][:-1]
    print(f"  Transport: {transport_name}")
```

***

## Query workstation information via WKST (\pipe\wkssvc)

### Get workstation name, domain, and OS version

```python
from impacket.dcerpc.v5 import wkst

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

resp = wkst.hNetrWkstaGetInfo(dce, 100)
info = resp['WkstaInfo']['WkstaInfo100']
print(f"Computer: {info['wki100_computername']}")
print(f"Domain:   {info['wki100_langroup']}")
print(f"Platform: {info['wki100_platform_id']}")
print(f"Version:  {info['wki100_ver_major']}.{info['wki100_ver_minor']}")
```

### Enumerate logged-on users

```python
resp = wkst.hNetrWkstaUserEnum(dce, 1)
for user in resp['UserInfo']['WkstaUserInfo']['Level1']['Buffer']:
    username_val = user['wkui1_username'][:-1]
    logon_domain = user['wkui1_logon_domain'][:-1]
    logon_server = user['wkui1_logon_server'][:-1]
    print(f"  {logon_domain}\\{username_val} (via {logon_server})")
```

### Get domain join information

```python
resp = wkst.hNetrGetJoinInformation(dce, '')
join_name = resp['NameBuffer'][:-1]
join_type = resp['BufferType']
join_types = {0: "Unknown", 1: "Unjoined", 2: "Workgroup", 3: "Domain"}
print(f"  Joined to: {join_name} ({join_types.get(join_type, str(join_type))})")
```

### Enumerate network transports

```python
resp = wkst.hNetrWkstaTransportEnum(dce, 0)
for t in resp['TransportInfo']['WkstaTransportInfo']['Level0']['Buffer']:
    name = t['wkti0_transport_name'][:-1]
    address = t['wkti0_transport_address']
    print(f"  {name}: {address}")

dce.disconnect()
```

***

## Enumerate users and groups via SAMR (\pipe\samr)

### Open a domain handle

```python
from impacket.dcerpc.v5 import samr

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

resp = samr.hSamrConnect(dce)
server_handle = resp['ServerHandle']

# Enumerate available domains
resp = samr.hSamrEnumerateDomainsInSamServer(dce, server_handle)
for domain_entry in resp['Buffer']['Buffer']:
    print(f"  Domain: {domain_entry['Name']}")

# Open the target domain
resp = samr.hSamrLookupDomainInSamServer(dce, server_handle, domain)
resp = samr.hSamrOpenDomain(dce, server_handle, domainId=resp['DomainId'])
domain_handle = resp['DomainHandle']
```

### Enumerate users

```python
resp = samr.hSamrEnumerateUsersInDomain(dce, domain_handle)
for user in resp['Buffer']['Buffer']:
    print(f"  {user['Name']} (RID: {user['RelativeId']})")
```

### Enumerate groups

```python
resp = samr.hSamrEnumerateGroupsInDomain(dce, domain_handle)
for group in resp['Buffer']['Buffer']:
    print(f"  {group['Name']} (RID: {group['RelativeId']})")
```

### Enumerate aliases (local groups)

```python
resp = samr.hSamrEnumerateAliasesInDomain(dce, domain_handle)
for alias in resp['Buffer']['Buffer']:
    print(f"  {alias['Name']} (RID: {alias['RelativeId']})")
```

### Get members of a specific alias (e.g., local Administrators, RID 544)

```python
resp = samr.hSamrOpenAlias(dce, domain_handle, aliasId=544)
alias_handle = resp['AliasHandle']

resp = samr.hSamrGetMembersInAlias(dce, alias_handle)
for member in resp['Members']['Sids']:
    sid = member['SidPointer'].formatCanonical()
    print(f"  Member SID: {sid}")

samr.hSamrCloseHandle(dce, alias_handle)
```

### Query individual user details

```python
user_rid = 500  # Administrator
resp = samr.hSamrOpenUser(dce, domain_handle, userId=user_rid)
user_handle = resp['UserHandle']

resp = samr.hSamrQueryInformationUser2(dce, user_handle,
    samr.USER_INFORMATION_CLASS.UserAllInformation)
user_info = resp['Buffer']['All']

print(f"  Username:    {user_info['UserName']}")
print(f"  Full name:   {user_info['FullName']}")
print(f"  Comment:     {user_info['AdminComment']}")
print(f"  Last logon:  {user_info['LastLogon']}")
print(f"  Pwd last set:{user_info['PasswordLastSet']}")
print(f"  Logon count: {user_info['LogonCount']}")
print(f"  Bad pwd count: {user_info['BadPasswordCount']}")

samr.hSamrCloseHandle(dce, user_handle)
samr.hSamrCloseHandle(dce, domain_handle)
dce.disconnect()
```

***

## Query event log channels via EVEN6 (\pipe\eventlog)

### List available event log channels

```python
from impacket.dcerpc.v5 import even6

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

resp = even6.hEvtRpcGetChannelList(dce)
for channel in resp['channelPaths']:
    print(f"  {channel}")

dce.disconnect()
```

### Read recent events from a log

```python
dce.connect()
dce.bind(even6.MSRPC_UUID_EVEN6)

# Open a log query for the Security log, last 10 events
resp = even6.hEvtRpcRegisterLogQuery(dce, 'Security\x00', flags=1,
    query='*[System[TimeCreated[timediff(@SystemTime) <= 86400000]]]\x00')
query_handle = resp['Handle']

# Read events
resp = even6.hEvtRpcQueryNext(dce, query_handle, numRequestedRecords=10)
for event in resp['EventDataIndices']:
    print(f"  Event index: {event}")

even6.hEvtRpcClose(dce, query_handle)
dce.disconnect()
```

***

## Query service information via SCMR (\pipe\svcctl)

Already covered in depth in Guide 4 (Execute Commands Remotely), but for inventory purposes:

```python
from impacket.dcerpc.v5 import scmr

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

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

services = scmr.hREnumServicesStatusW(dce, sc_handle)
for svc in services:
    name = svc['lpServiceName'][:-1]
    state = svc['ServiceStatus']['dwCurrentState']
    states = {1: "Stopped", 4: "Running"}
    print(f"  {name:<40} {states.get(state, str(state))}")

scmr.hRCloseServiceHandle(dce, sc_handle)
dce.disconnect()
```

***

## Combining across multiple hosts

All of these queries can be wrapped into a function that takes a target IP and produces an inventory dict. Iterate your target list and build a comprehensive inventory:

```python
def inventory_host(target_ip, username, password, domain):
    result = {'ip': target_ip}

    # SRVS: server info + shares
    rpctransport = transport.DCERPCTransportFactory(rf'ncacn_np:{target_ip}[\pipe\srvsvc]')
    rpctransport.set_credentials(username, password, domain)
    dce = rpctransport.get_dce_rpc()
    dce.connect()
    dce.bind(srvs.MSRPC_UUID_SRVS)

    resp = srvs.hNetrServerGetInfo(dce, 101)
    info = resp['InfoStruct']['ServerInfo101']
    result['name'] = info['sv101_name']
    result['version'] = f"{info['sv101_version_major']}.{info['sv101_version_minor']}"

    resp = srvs.hNetrShareEnum(dce, 1)
    result['shares'] = [s['shi1_netname'][:-1] for s in resp['InfoStruct']['ShareInfo']['Level1']['Buffer']]

    dce.disconnect()

    # WKST: logged-on users
    rpctransport = transport.DCERPCTransportFactory(rf'ncacn_np:{target_ip}[\pipe\wkssvc]')
    rpctransport.set_credentials(username, password, domain)
    dce = rpctransport.get_dce_rpc()
    dce.connect()
    dce.bind(wkst.MSRPC_UUID_WKST)

    resp = wkst.hNetrWkstaUserEnum(dce, 1)
    result['logged_on'] = [u['wkui1_username'][:-1] for u in resp['UserInfo']['WkstaUserInfo']['Level1']['Buffer']]

    dce.disconnect()
    return result
```

This showcases the core value of understanding DCE/RPC in Impacket: every interface follows the same pattern, so adding new queries is just swapping the pipe, UUID, and helper function.


---

# 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/enum-info-via-dcerpc.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.
