projectdiscovery/nuclei · error
epmapper bind: %w
Error message
epmapper bind: %w
What it means
TCP to 135 succeeded but the DCE/RPC bind to the EPMAPPER interface (rpc.Bind with the epmapper UUID/version) failed. A protocol-level rejection rather than a connectivity failure: the endpoint-mapper service is broken, or a middlebox (IDS/IPS, RPC filter, TCP proxy) mangles the bind PDU, or (rarely) a version-negotiation mismatch.
Source
Thrown at pkg/js/libs/dcerpc/dcerpc.go:222
// for (const e of eps) { log(e.UUID + ' ' + e.Annotation); }
// ```
func (c *Client) RpcDump(ctx context.Context) ([]Endpoint, error) {
if !protocolstate.IsHostAllowed(c.nj.ExecutionId(), c.Host) {
return nil, protocolstate.ErrHostDenied.Msgf(c.Host)
}
dialer := protocolstate.GetDialersWithId(c.nj.ExecutionId())
if dialer == nil {
return nil, fmt.Errorf("dialers not initialized for execution %s", c.nj.ExecutionId())
}
conn, err := dialer.Fastdialer.Dial(ctx, "tcp", net.JoinHostPort(c.Host, strconv.Itoa(135)))
if err != nil {
return nil, fmt.Errorf("dial epmapper: %w", err)
}
defer func() { _ = conn.Close() }()
rpc := gprpc.NewClientTCP(gprpc.NewTCPTransport(conn))
if err := rpc.Bind(gpepm.UUID, gpepm.MajorVersion, gpepm.MinorVersion); err != nil {
return nil, fmt.Errorf("epmapper bind: %w", err)
}
epm := gpepm.NewEpmClient(rpc)
return epm.Lookup()
}
// SamrEnumerateUsers connects to SAMR and returns every domain user record
// (impacket: samrdump.py).
//
// @example
// ```javascript
// const c = new dcerpc.Client('dc01', 'acme.local', 'admin', 'P@ss');
// const users = c.SamrEnumerateUsers();
// for (const u of users) { log(u.Name + ' ' + u.RID); }
// ```
func (c *Client) SamrEnumerateUsers() ([]DomainUser, error) {
rpc, err := c.rpcOverNamedPipe("samr", gpsamr.UUID, gpsamr.MajorVersion, gpsamr.MinorVersion)
if err != nil {
return nil, errView on GitHub (pinned to 265b3a3dec)
Solutions
- Cross-check with impacket's rpcdump.py — if it also fails, the problem is host-side or path-side, not nuclei.
- Retry once: some middleboxes drop the first PDU of a connection.
- Inspect the path for IPS/proxies that intercept 135.
- Fall back to named-pipe enumeration methods over 445 which avoid the endpoint mapper.
Example fix
// before
const eps = c.RpcDump(); // epmapper bind: ...
// after (single retry, then fall back)
let eps = null;
for (let i = 0; i < 2 && eps === null; i++) {
try { eps = c.RpcDump(); } catch (e) { log('epmapper bind attempt ' + i + ' failed: ' + e); }
}
if (eps === null) eps = []; // continue with pipe-based methods instead Defensive patterns
Strategy: try-catch
Try / catch
try {
const eps = c.RpcDump();
} catch (e) {
const msg = String(e);
if (msg.includes('epmapper bind')) {
// port 135 answers but RPC bind is rejected: middlebox or broken service
log('epmapper bind rejected: ' + msg);
} else throw e;
} Prevention
- Cross-validate EPM behavior with an independent tool (rpcdump.py) when triaging.
- Treat bind failure differently from dial failure in template logic — they have different causes.
- Retain a named-pipe fallback path that avoids the endpoint mapper entirely.
When it happens
Trigger: RpcDump() where something answers on 135 but never returns a valid bind ack: crashed RPC service after patching, transparent proxies/IPS on the path, or a honeypot accepting any TCP connection.
Common situations: IPS signatures tripping on DCE/RPC binds; partially broken hosts; deceptive endpoints answering all ports.
Related errors
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/eb2cf26c4fdfabc7.
Report an issue: GitHub.