コンテンツにスキップ

DCE/RPC と NDR

技術目次へ戻る

RPC はクライアントからリモートの関数を呼び出す仕組みです。Impacket の MSRPC 実装は、接続先の特定、メッセージの交換、引数の符号化をそれぞれ 別の層で扱います。C706 と [MS-RPCE] の 接続指向実装で、transport、runtime、NDR、各 interface が分かれています。

モジュール責務
transport.pystring binding → TCP / SMB pipe / HTTP / UDP / local
rpcrt.pyPDU、bind / alter context、AUTH3、SIGN/SEAL
rpch.pyRPC over HTTP v1/v2
ndr.pyNDR / NDR64 の pack
epm.pyEndpoint Mapper
dcomrt.py + dcom/DCOM OXID / OBJREF、WMI

関連コマンド: rpcdump、rpcmap、 services、atexec、 wmiexec、samrdump

[uuid@]proto:address[endpoint,opt=val]

DCERPCTransportFactory() の分岐:

protoクラス典型
ncacn_npSMBTransportncacn_np:host[\pipe\svcctl]
ncacn_ip_tcpTCPTransport既定 135。動的ポートは EPM で引く
ncacn_httpHTTPTransport直結 593、または RpcProxy=host:443
ncadg_ip_udpUDPTransport接続レス。DCERPC_v4
ncalocalLOCALTransport\\\\.\\PIPE\\...。LPC (ncalrpc) ではない

SMBTransport は既存 SMBConnection を再利用できます。複数 interface を 同じセッションで開くときはこれを使います。

rpch.py は [MS-RPCH] です。

  • 直結: ポート 593、バナー ncacn_http/1.0 (RPC_OVER_HTTP_v1)
  • Proxy: option RpcProxy=host:80|443 → /rpc/rpcproxy.dll?RemoteName:RemotePort。IN チャネル (RPC_IN_DATA) と OUT チャネル (RPC_OUT_DATA) を対で張り、RTS (CONN_A1/B1/A3/C2) でトンネルを確立します
  • Exchange は 6001–6004 (OXCRPC / OXABREF / OXNSPI) をよく使います

set_credentials() は auth level を自動で CONNECT まで上げます。 DRSUAPI や一部 DCOM が要求する PKT_PRIVACY は呼び出し側が明示します。

資格情報は transport に置き、DCERPC_v5.set_credentials() が bind 時に 拾います。SMB transport では同じ SMBConnection を再利用できます。

主要 type (rpcrt.py):

値名前
0x00 / 0x02REQUEST / RESPONSE
0x03FAULT
0x0B / 0x0C / 0x0DBIND / BINDACK / BINDNAK
0x0E / 0x0FALTERCTX / ALTERCTX_R
0x10AUTH3 (NTLM Type3)
0x14RTS (RPC over HTTP)

DCERPC_v5.bind(iface_uuid) は abstract syntax (interface UUID+version) と transfer syntax を CtxItem に載せます。

Transfer syntaxUUID
NDR 2.08a885d04-1ceb-11c9-9fe8-08002b104860
NDR64 1.071710533-beba-4937-8319-b5dbef9ccc36

bogus_binds はダミー context を先に足します (一部ホストの指紋回避)。 bind が拒否されると rpc_cont_def_result / rpc_status_codes 付きの DCERPCException になります。

EPM (epm.py) UUID は E1AF8308-5D1F-11C9-91A4-08002B14A0FA v3.0、既定 binding は ncacn_ip_tcp:host[135] です。

helper役割
hept_lookup全 tower + annotation。rpcdump
hept_map指定 interface の string binding を 1 つ返す。DRSUAPI/GKDI の動的ポート
PrintStringBindingfloor を文字列へ

tower は interface UUID、transfer syntax、protocol、pipe/port、host の floor 列です。rpcmap は指定 binding 上で mgmt (hinq_if_ids) または UUID/opnum 探索をします。

共有型は dtypes.py ([MS-DTYP]: DWORD、WSTR、RPC_SID、GUID、SECURITY_DESCRIPTOR)。 NULL は NDRPOINTERNULL のシングルトンです。

DCERPC.request(req) は req と同じモジュールの {ClassName}Response を探し、末尾 4 byte が 0 でなければ そのモジュールの DCERPCSessionError を投げます。

set_auth_type / set_auth_level:

auth_type値実装
RPC_C_AUTHN_NONE0x00無し
RPC_C_AUTHN_GSS_NEGOTIATE0x09Kerberos (getKerberosType1)
RPC_C_AUTHN_WINNT0x0ANTLMSSP (既定)
RPC_C_AUTHN_NETLOGON0x44Secure Channel (nrpc.getSSPType1)
auth_level値意味
NONE1認証無し
CONNECT2bind 時だけ (set_credentials の既定)
CALL3コール単位
PKT4パケット単位
PKT_INTEGRITY5署名
PKT_PRIVACY6署名 + 暗号化

NTLM の bind は Type1 を BIND に載せ、BINDACK の Type2 を見て AUTH3 で Type3 を送ります。PKT_INTEGRITY / PKT_PRIVACY では以後の REQUEST に SEC_TRAILER と署名/暗号が付きます。Kerberos は SPNEGO AP-REQ/AP-REP (DCE_STYLE) です。

SMB3 上では RPC 署名鍵に SMBConnection.getSessionKey() の ApplicationKey を使います。NTLM exported key そのものではありません。

NDR は Structure に似た宣言型ですが、C706 の alignment 規則を持ちます。プリミティブの前に 最小のパディングが入ります。

クラス用途
NDRSMALL / NDRSHORT / NDRLONG / NDRHYPER と符号無し版スカラ
NDRBOOLEAN / NDRCHAR / NDRFLOATその他プリミティブ
NDRENUM列挙
NDRSTRUCT構造体
NDRUNION判別 union
NDRUniFixedArray / NDRUniConformantArray / NDRUniVaryingArray / NDRUniConformantVaryingArray配列
NDRVaryingString / NDRConformantVaryingString文字列
NDRPOINTER / NDRPOINTERNULL参照ポインタ。referent は後置
NDRCALLrequest / response のトップレベル

isNDR64=True で commonHdr64 / structure64 / align64 に切り替わります。 ポインタは 4 byte から 8 byte になります。

interface モジュールのパターン:

  1. MSRPC_UUID_* = uuidtup_to_bin((uuid, version))
  2. 型を NDRSTRUCT / NDRPOINTER で宣言
  3. 各 op を NDRCALL サブクラスにし、helper hXxxYyy(dce, ...) を置く

新しい op を足すときは IDL の alignment と conformant 配列の MaximumCount / Offset / ActualCount を守ってください。手で Structure を組むとパディングがずれます。

named pipe は代表値です。ホストによっては EPM 経由の TCP だけ、 または別名 pipe のことがあります。

モジュールUUID (抜粋)代表 pipe / ポート用途
epmE1AF8308-...A0FA v3TCP 135endpoint 解決
mgmtafa8bd80-...任意interface inquiry (rpcmap)
samr12345778-...89AC v1samrアカウント列挙・作成・password
lsat / lsad12345778-...89AB v0lsarpcSID lookup、policy、secret
nrpc12345678-...CFFB v1netlogonSecure Channel、challenge/authenticate
scmr367ABB81-... v2svcctlサービス作成/開始/停止。RCreateWowService(opnum 60)と ROpenSCManager2(opnum 64)も含む
tsch86D35949-... v1TaskSchedulerXML タスク (atexec)
atsvc / sasec1FF70682-...atsvc古い AT job、タスクアカウント
srvs4B324FC8-...E188 v3srvsvc共有・セッション
fsrvpA8E0653C-...2292 v1FssagentRpcファイルサーバ remote VSS(MS-FSRVP)
wkst6BFFD098-...345A v1wkssvcワークステーション / join
rrp338CD001-... v1winregRemote Registry。boot key のクラス名もここ
drsuapiE3514235-...DCD2 v4TCP (EPM)DRSGetNCChanges。通常 PKT_PRIVACY
bkrp3dde7c30-...db40 v1—DPAPI domain backup key
gkdiB9785960-...2085 v1TCP (EPM)LAPS v2 / DPAPI-NG の GkdiGetKey
dcomrt + dcom/wmiOXID / IWbem*TCP 135 + 動的WMI / MMC / ShellWindows。OXID ping スレッドあり
nspiF5CC5A18-...8426 v56HTTP 6004 もExchange address book
oxabref1544F5E0-...BD09HTTP 6001 付近RfrGetNewDSA
icpr91ae6020-...91becert証明書要求 (AD CS relay)
tsts複数LSM_API_service 等セッション操作 (tstool)
rprn / par12345678-...89AB 等spoolss印刷スプーラ
even / even682273FDC-... / F6BEAFF7-...eventlogイベントログ
mimilib17FC11E9-...6244—mimikatz RPC (Microsoft interface ではない)
dhcpm / raa / iphlp / dssp各仕様—DHCP、Authz、マシンロール

DCOM は通常の bind に加え、OXID resolver、OBJREF、IRemUnknown の 参照カウントがあります。wmiexec は Win32_Process.Create、 dcomexec は ShellWindows / ShellBrowserWindow / MMC20.Application、 wmipersist は permanent event subscription です。途中失敗時の RemRelease / object 解放が契約です。

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()

Kerberos なら transport に set_kerberos(True, kdcHost) を付けます。

  • interface UUID / version / opnum を変えると相手は FAULT を返す
  • NDR64 切替はポインタ幅と配列ヘッダの両方に効く
  • 新しい auth_type は bind、AUTH3、以降 PDU の SIGN/SEAL の 3 箇所が必要
  • 関連テスト: tests/dcerpc/、tests/misc/test_dcerpc_v5_ndr.py