DCE/RPC and NDR
RPC lets a client call a function on a remote system. Impacket’s MSRPC implementation separates locating the endpoint, exchanging messages, and encoding arguments into distinct layers. It implements connection-oriented RPC from C706 and [MS-RPCE], with separate transport, runtime, NDR, and interface layers.
| Module | Responsibility |
|---|---|
transport.py | string binding → TCP / SMB pipe / HTTP / UDP / local |
rpcrt.py | PDUs, bind / alter context, AUTH3, SIGN/SEAL |
rpch.py | RPC over HTTP v1/v2 |
ndr.py | NDR / NDR64 packing |
epm.py | Endpoint Mapper |
dcomrt.py + dcom/ | DCOM OXID / OBJREF, WMI |
Related commands: rpcdump, rpcmap, services, atexec, wmiexec, samrdump
String Bindings and Transports
Section titled “String Bindings and Transports”[uuid@]proto:address[endpoint,opt=val]DCERPCTransportFactory() selects a transport:
| Proto | Class | Typical Use |
|---|---|---|
ncacn_np | SMBTransport | ncacn_np:host[\pipe\svcctl] |
ncacn_ip_tcp | TCPTransport | Port 135 by default; resolve dynamic ports through EPM |
ncacn_http | HTTPTransport | Direct port 593 or RpcProxy=host:443 |
ncadg_ip_udp | UDPTransport | Connectionless DCERPC_v4 |
ncalocal | LOCALTransport | \\\\.\\PIPE\\...; not LPC (ncalrpc) |
SMBTransport can reuse an existing SMBConnection. Use this when opening
multiple interfaces over the same session.
RPC over HTTP
Section titled “RPC over HTTP”rpch.py implements [MS-RPCH].
- Direct: port 593, banner
ncacn_http/1.0(RPC_OVER_HTTP_v1) - Proxy: option
RpcProxy=host:80|443→/rpc/rpcproxy.dll?RemoteName:RemotePort. It opens paired IN (RPC_IN_DATA) and OUT (RPC_OUT_DATA) channels, then establishes the tunnel through RTS (CONN_A1/B1/A3/C2) - Exchange commonly uses ports 6001–6004 (OXCRPC / OXABREF / OXNSPI)
set_credentials() automatically raises the authentication level to CONNECT.
The caller must explicitly set PKT_PRIVACY when required by DRSUAPI or some DCOM interfaces.
Credentials reside on the transport and DCERPC_v5.set_credentials() reads them
during bind. An SMB transport can reuse the same SMBConnection.
PDUs and Bind
Section titled “PDUs and Bind”Main types (rpcrt.py):
| Value | Name |
|---|---|
| 0x00 / 0x02 | REQUEST / RESPONSE |
| 0x03 | FAULT |
| 0x0B / 0x0C / 0x0D | BIND / BINDACK / BINDNAK |
| 0x0E / 0x0F | ALTERCTX / ALTERCTX_R |
| 0x10 | AUTH3 (NTLM Type3) |
| 0x14 | RTS (RPC over HTTP) |
DCERPC_v5.bind(iface_uuid) puts the abstract syntax (interface UUID+version)
and transfer syntax in a CtxItem.
| Transfer syntax | UUID |
|---|---|
| NDR 2.0 | 8a885d04-1ceb-11c9-9fe8-08002b104860 |
| NDR64 1.0 | 71710533-beba-4937-8319-b5dbef9ccc36 |
bogus_binds prepends dummy contexts (to avoid fingerprinting by some hosts).
If the bind is rejected, it raises DCERPCException with
rpc_cont_def_result / rpc_status_codes.
The EPM (epm.py) UUID is
E1AF8308-5D1F-11C9-91A4-08002B14A0FA v3.0, and its default binding is
ncacn_ip_tcp:host[135].
| Helper | Role |
|---|---|
hept_lookup | All towers and annotations; used by rpcdump |
hept_map | Returns one string binding for an interface; dynamic DRSUAPI/GKDI ports |
PrintStringBinding | Converts floors to a string |
A tower is a sequence of floors for the interface UUID, transfer syntax,
protocol, pipe/port, and host. rpcmap uses mgmt (hinq_if_ids) or
UUID/opnum probing on a specified binding.
Shared types in dtypes.py ([MS-DTYP]) include
DWORD, WSTR, RPC_SID, GUID, and SECURITY_DESCRIPTOR.
NULL is the NDRPOINTERNULL singleton.
DCERPC.request(req) looks for a {ClassName}Response in the same module
as req and raises that module’s DCERPCSessionError if the trailing
four bytes are nonzero.
Authentication Levels
Section titled “Authentication Levels”set_auth_type / set_auth_level:
| auth_type | Value | Implementation |
|---|---|---|
RPC_C_AUTHN_NONE | 0x00 | None |
RPC_C_AUTHN_GSS_NEGOTIATE | 0x09 | Kerberos (getKerberosType1) |
RPC_C_AUTHN_WINNT | 0x0A | NTLMSSP (default) |
RPC_C_AUTHN_NETLOGON | 0x44 | Secure Channel (nrpc.getSSPType1) |
| auth_level | Value | Meaning |
|---|---|---|
NONE | 1 | No authentication |
CONNECT | 2 | Bind only (default with set_credentials) |
CALL | 3 | Per call |
PKT | 4 | Per packet |
PKT_INTEGRITY | 5 | Signing |
PKT_PRIVACY | 6 | Signing and encryption |
An NTLM bind puts Type1 in BIND, reads Type2 from BINDACK, and sends
Type3 in AUTH3. With PKT_INTEGRITY / PKT_PRIVACY, subsequent REQUESTs
carry a SEC_TRAILER and signing/encryption. Kerberos uses a SPNEGO
AP-REQ/AP-REP (DCE_STYLE).
Over SMB3, RPC uses the ApplicationKey from
SMBConnection.getSessionKey() as its signing key, not the raw NTLM exported key.
NDR uses declarations similar to Structure,
but follows C706 alignment rules. It inserts minimal padding before primitives.
| Class | Purpose |
|---|---|
NDRSMALL / NDRSHORT / NDRLONG / NDRHYPER and unsigned variants | Scalars |
NDRBOOLEAN / NDRCHAR / NDRFLOAT | Other primitives |
NDRENUM | Enumeration |
NDRSTRUCT | Structure |
NDRUNION | Discriminated union |
NDRUniFixedArray / NDRUniConformantArray / NDRUniVaryingArray / NDRUniConformantVaryingArray | Arrays |
NDRVaryingString / NDRConformantVaryingString | Strings |
NDRPOINTER / NDRPOINTERNULL | Reference pointers; referents follow later |
NDRCALL | Top-level requests / responses |
isNDR64=True switches to commonHdr64 / structure64 / align64.
Pointers grow from four to eight bytes.
The pattern in interface modules is:
MSRPC_UUID_* = uuidtup_to_bin((uuid, version))- Declare types with
NDRSTRUCT/NDRPOINTER - Make each operation an
NDRCALLsubclass and add a helperhXxxYyy(dce, ...)
When adding an operation, follow the IDL’s alignment and the
MaximumCount / Offset / ActualCount values for conformant arrays.
Building a Structure manually gives the wrong padding.
Main Implemented Interfaces
Section titled “Main Implemented Interfaces”Named pipes shown here are representative. On some hosts, an interface may be reachable only over TCP via EPM or through a pipe with another name.
| Module | UUID (excerpt) | Typical Pipe / Port | Purpose |
|---|---|---|---|
epm | E1AF8308-...A0FA v3 | TCP 135 | Endpoint resolution |
mgmt | afa8bd80-... | Any | Interface inquiry (rpcmap) |
samr | 12345778-...89AC v1 | samr | Account enumeration, creation, passwords |
lsat / lsad | 12345778-...89AB v0 | lsarpc | SID lookup, policies, secrets |
nrpc | 12345678-...CFFB v1 | netlogon | Secure Channel, challenge/authenticate |
scmr | 367ABB81-... v2 | svcctl | Create, start, or stop services; also RCreateWowService (opnum 60) and ROpenSCManager2 (opnum 64) |
tsch | 86D35949-... v1 | TaskScheduler | XML tasks (atexec) |
atsvc / sasec | 1FF70682-... | atsvc | Legacy AT jobs, task accounts |
srvs | 4B324FC8-...E188 v3 | srvsvc | Shares and sessions |
fsrvp | A8E0653C-...2292 v1 | FssagentRpc | File server remote VSS (MS-FSRVP) |
wkst | 6BFFD098-...345A v1 | wkssvc | Workstation / join |
rrp | 338CD001-... v1 | winreg | Remote Registry, including boot key class names |
drsuapi | E3514235-...DCD2 v4 | TCP (EPM) | DRSGetNCChanges; usually PKT_PRIVACY |
bkrp | 3dde7c30-...db40 v1 | — | DPAPI domain backup key |
gkdi | B9785960-...2085 v1 | TCP (EPM) | GkdiGetKey for LAPS v2 / DPAPI-NG |
dcomrt + dcom/wmi | OXID / IWbem* | TCP 135 + dynamic ports | WMI / MMC / ShellWindows; OXID ping thread |
nspi | F5CC5A18-...8426 v56 | Also HTTP 6004 | Exchange address book |
oxabref | 1544F5E0-...BD09 | Around HTTP 6001 | RfrGetNewDSA |
icpr | 91ae6020-...91be | cert | Certificate requests (AD CS relay) |
tsts | Multiple | LSM_API_service, etc. | Session operations (tstool) |
rprn / par | 12345678-...89AB, etc. | spoolss | Print spooler |
even / even6 | 82273FDC-... / F6BEAFF7-... | eventlog | Event logs |
mimilib | 17FC11E9-...6244 | — | mimikatz RPC (not a Microsoft interface) |
dhcpm / raa / iphlp / dssp | Various specifications | — | DHCP, Authz, machine roles |
Beyond a normal bind, DCOM has OXID resolution, OBJREF, and IRemUnknown
reference counting. wmiexec uses Win32_Process.Create,
dcomexec uses ShellWindows / ShellBrowserWindow / MMC20.Application,
and wmipersist uses a permanent event subscription. On intermediate failures,
RemRelease / object release is part of the contract.
Typical Client Procedure
Section titled “Typical Client Procedure”rpctransport = transport.DCERPCTransportFactory(r'ncacn_np:host[\pipe\svcctl]')rpctransport.set_credentials(user, password, domain, lmhash, nthash)dce = rpctransport.get_dce_rpc()dce.connect()dce.bind(scmr.MSRPC_UUID_SCMR)# scmr.hROpenSCManagerW(dce, ...)dce.disconnect()For Kerberos, also call set_kerberos(True, kdcHost) on the transport.
Checks When Making Changes
Section titled “Checks When Making Changes”- Changing an interface UUID, version, or opnum causes a FAULT from the peer
- Switching to NDR64 changes both pointer widths and array headers
- A new auth_type needs handling in bind, AUTH3, and SIGN/SEAL on subsequent PDUs
- Related tests:
tests/dcerpc/,tests/misc/test_dcerpc_v5_ndr.py

