
Beyond the NT_STATUS_ACCESS_DENIED Wall
“Connected” is the most expensive lie rpcclient tells. You fire off one confident command, and the target answers with the same icy refrain: NT_STATUS_ACCESS_DENIED.
On Kioptrix-era boxes and modern Samba/Windows configs alike, the problem isn’t transport, it’s the wrong door. While the SMB session binds, specific RPC procedures (often SAMR) are rejected by permission checks, even when others (like LSARPC) remain open for limited lookups.
- 01. Verify Confirm effective auth (Anon vs. Guest vs. User)
- 02. Extract Identify domain context and SID via LSARPC
- 03. Pivot Attempt SAMR once, then branch with purpose
No “try everything.” No magical command. Just a repeatable branch.
Table of Contents

Who this is for / not for
For: you can connect to SMB and get an rpcclient $> prompt, but most commands deny
If you’re reaching the prompt reliably and the denial happens after you issue RPC calls, you’re in the right place. This is the classic “bind is fine, privilege is not” swamp.
For: you’re in a Kioptrix-style lab where anonymous/low-priv access is inconsistent
Old-school targets often behave like a bouncer with a mood. Null sessions might work on one service, fail on another, or be silently downgraded to guest. The result: “I swear this worked on another host.” Yep.
Not for: you can’t reach SMB (port/transport issue) or rpcclient can’t connect at all
If 445/139 isn’t reachable, DNS is wrong, or SMB negotiation fails, fix transport first. This article starts after you can connect. (If you’re still deciding whether you should be testing SMB null session behavior on port 139 vs 445, solve that first, then come back.)
Not for: you’re hunting “one magic command” without checking pipe + auth context first
There’s no single incantation. There’s a process. The process is what makes you fast.
- The prompt only proves a session, not privileges.
- Different pipes expose different interfaces and permission checks.
- Your goal is a repeatable baseline before deeper enumeration.
Apply in 60 seconds: Write down: target, auth (anon/guest/user), and which pipe you’re on before you run a second command.
After-connect denial triage: confirm it’s a pipe/privilege problem (not transport)
Quick check: “connect succeeded” vs “bind succeeded” vs “call authorized”
Three different “yes” answers get mixed up:
- Connect succeeded: you reached SMB and opened a session to IPC$.
- Bind succeeded: the client bound to an RPC interface (over a named pipe).
- Call authorized: the server allowed a specific procedure call.
On a Kioptrix/SMB-era target, it’s common to see the first two succeed while the third fails loudly. That’s not “broken.” That’s “permission boundary.”
Read the vibe: ACCESS_DENIED on everything vs only on user/group enum
Two patterns matter:
- Deny-all: even trivial identity/domain queries are denied. This often means you’re effectively anonymous/guest with no rights on that interface, or the server blocks the pipe entirely.
- Selective-deny: “light” queries work, but
enumdomusers, group enumeration, or policy dumps fail. That’s a privilege ladder problem (and you can still harvest value). If this is your exact symptom, you’ll want the focused companion piece: why rpcclient enumdomusers fails and what to do next.
Let’s be honest… “Connected” is not “Authorized.” The prompt is a receipt that you entered the building, not that you can open the vault.
Establish a baseline command set you’ll reuse across pipes (one tiny checklist)
Before you chase anything fancy, you want 3–5 commands that answer:
- Who am I to the server?
- What domain/workgroup context is this?
- Can I resolve names ↔ SIDs at all?
Show me the nerdy details
In Samba’s tooling (including rpcclient), the “RPC over SMB named pipe” model is essentially: SMB session → open a pipe (like \\pipe\\lsarpc) → bind to an interface UUID → call opnums. Authorization can happen at bind time, call time, or both, depending on server policy and interface implementation.
I keep a little “baseline card” in my notes because I’ve personally face-planted on this. Once, I convinced myself a lab box was “patched” because my first command was a high-priv SAMR call. Ten minutes later, I realized LSARPC lookups still worked and the box was basically shouting its structure at me. That was a coffee-spill lesson.

Pipe switching 101: what samr vs lsarpc actually unlocks
samr: accounts/groups/aliases, but commonly privilege-gated
SAMR is the door to account and group enumeration. It’s also the door that’s most likely to have a guard with a clipboard. On hardened hosts (or labs that emulate hardening), “list me all users” is exactly the kind of request that gets denied without apology.
lsarpc: policy/SID/lookups, sometimes more forgiving for low-priv
LSARPC often still allows certain lookup operations even when full user enumeration is blocked. This is where you can map names to SIDs, discover domain SIDs, and get enough structure to pivot intelligently.
Why one pipe denies while the other works (service hardening, anonymous restrictions)
Different interfaces implement different authorization checks. Even with the same username, the server may treat “policy lookup” very differently from “enumerate all accounts.” In practice, you’ll see:
- Anonymous restrictions blocking enumeration but permitting limited lookups.
- Guest mapping that lets you bind but denies privileged calls.
- Service configuration where one pipe is available and another is restricted or filtered.
The weird part: the same username can behave differently per interface. That’s not you going crazy. That’s the system being… itself.
Operator note: When you see mixed behavior, resist the urge to “fix credentials.” First, fix your mental model: pipe/interface dictates what questions you’re allowed to ask.
Timely, truthful grounding: rpcclient is part of the Samba suite, and it’s designed for talking to RPC services over SMB named pipes. The Samba project’s own manual page is the most reliable place to confirm options and behavior when you’re unsure (and it’s less “bloggy” than most blog posts, which is a compliment). Microsoft’s Open Specifications docs explain the underlying SAMR/LSA protocols if you want the boring truth in full daylight.
The clean workflow: connect once, switch pipes deliberately, test in layers
This is the workflow I wish someone had handed me years ago, before I built a small museum of useless terminal scrollback.
Layer 1: minimal “identity + domain” queries (prove what you are allowed to see)
Your goal is not “enumerate everything.” Your goal is “prove a capability.” Start with low-priv questions. If you can’t answer basic identity/context questions, you have to fix auth or choose a different approach.
Layer 2: SID and name lookups (use lsarpc-friendly paths first)
If LSARPC lets you do lookups, you can often map partial knowledge into better knowledge. Even when lists are blocked, lookups can still succeed. That means you can test hypotheses about usernames or groups without needing full enumeration.
Layer 3: only then attempt user/group enumeration (often samr)
Once you’ve proven LSARPC works, then you try SAMR enumeration. If it denies, you already have a salvage path. If it works, great, you climb.
Here’s what no one tells you… enumeration is a privilege ladder, not a menu. You don’t order “users” like a side dish. You earn the right to ask the question.
- Run a tiny baseline set on LSARPC first.
- If it works, you can extract structure even when SAMR is blocked.
- If it fails, stop and validate auth (you may be guest/anon).
Apply in 60 seconds: Make your first three commands “context” commands, not “dump” commands.
- Yes/No: Do you get
rpcclient $>without errors? - Yes/No: Does at least one low-priv lookup (LSA-style) succeed?
- Yes/No: Do only “list everything” commands fail?
- Yes/No: Can you confirm whether you’re anonymous/guest vs authenticated?
Next step: If you answered “No” to #2, pivot to auth validation before trying more enumeration.
Personal note: I used to start with the loudest commands because it felt efficient. It wasn’t. It was just emotionally satisfying, like punching a vending machine. The machine always wins.
💡 Read the official Kioptrix rpcclient NT_STATUS_ACCESS_DENIED switching pipes guidance
When samr denies: salvage value with lsarpc-first enumeration
If SAMR slams the door, don’t interpret it as “game over.” Interpret it as “wrong tool for this level.” You can still learn a lot without direct user listing.
Pivot to SID discovery and name mapping (what you can still learn)
Even with restrictive configs, LSARPC may still allow:
- Discovering the domain SID pattern you’re dealing with.
- Resolving known names to SIDs (or vice versa).
- Confirming whether an account exists (sometimes indirectly) by how lookups respond.
This matters because many follow-on techniques (including pass-the-hash workflows, SMB share targeting, or service-specific enumeration) become far more efficient when you’ve nailed the correct domain vs local context. (And yes, this is where “I got NT_STATUS_LOGON_FAILURE in SMBMap” becomes relevant: see SMBMap NT_STATUS_LOGON_FAILURE troubleshooting when the problem is truly auth, not pipe privileges.)
Use lookup patterns to infer users/groups without listing them directly
Think of this like guessing the shape of a key by looking at the lock. You’re not dumping the full directory, but you can still:
- Test likely lab defaults (e.g., common training usernames).
- Validate whether “Administrator” is local, domain, renamed, or disabled.
- Identify group names that tend to exist (and matter) in the target’s context.
Identify domain vs local context (don’t mix them or you’ll misread results)
This is the mistake that quietly ruins an afternoon. Domain SAMR and local SAM look similar until they don’t, and then your assumptions get wobbly:
- Domain context: you’re dealing with a domain SID, domain groups, and domain accounts.
- Local context: you’re dealing with the local machine SAM and local groups.
If you mix them, you’ll interpret “denied” as “doesn’t exist” or “blocked” as “patched.” That’s how myths are born.
A denial can still leak structure if you ask the right interface. The server is still responding, and responses have texture.
Show me the nerdy details
In many environments, “enumeration” calls are treated as higher impact than “lookup” calls. Enumeration may require privileges like “read domain” equivalents, while name-to-SID resolution can be permitted more broadly. This is especially true when systems are configured to reduce anonymous data exposure while still supporting legitimate name resolution workflows.
Personal anecdote: I once spent 30 minutes trying to “force” user listing through SAMR. Then I tried a humble lookup path and realized the target happily confirmed which names existed. The box wasn’t silent. I was just yelling the wrong question at it.
- Choose LSARPC-first when: you’re low-priv/guest, SAMR denies, and you need domain/SID structure quickly.
- Choose SAMR-first when: you have known valid creds and you’re expecting full account enumeration.
- Time trade-off: LSARPC-first typically saves 10–30 minutes of blind retries on hardened targets.
Next step: Run LSARPC baseline, then attempt SAMR exactly once and branch based on result.
When lsarpc denies: the “anonymous is dead” scenario (what to try next)
If LSARPC denies even the “light” stuff, assume you’re effectively unauthenticated, guest-mapped, or facing server-side restrictions that treat your session as untrusted. This is where you stop guessing and validate identity.
Validate you’re not in guest/anonymous without realizing it
Some targets accept a connection but treat you as guest behind the scenes. In labs, you’ll see this when:
- Anonymous binds “work” but every call denies.
- Your expected username doesn’t “stick” (server maps you to guest).
- You can connect to SMB shares but can’t query RPC interfaces meaningfully.
Try authenticated binds with the weakest known creds (lab defaults, discovered creds)
When this is a lab: use what you actually know. Don’t invent credentials. If you have a discovered username/password, try it. If you don’t, pivot to credential discovery paths (web app, config files, service banners) instead of hammering RPC.
I’ve seen people burn an hour treating RPC as a “credential oracle.” It’s not. It’s a permissions wall.
Confirm server-side restrictions (null session policies, SMB signing, etc.)
Some restrictions don’t show up as “can’t connect,” they show up as “can’t do anything useful.” If you’re in a mixed lab, one box might allow null sessions, another might not. That’s normal in training ranges designed to teach you exactly this lesson.
Why did it work yesterday? Small config shifts change RPC behavior fast. Different VM snapshots, different Samba configs, different Windows policies. Same vibe, different locks.
Real-world tooling context: operators often pair Nmap for service detection (if you’re tightening your scan plan, compare Nmap -Pn vs -sn), Wireshark for understanding negotiation failures, and frameworks like Impacket or Metasploit when they need alternate RPC implementations or higher-level modules. That’s not a recommendation to “spam tools,” it’s a reminder that “rpcclient denied” is a symptom, not a final verdict. If your Kali install is fighting you on packages, keep installing Impacket on Kali under PEP 668 bookmarked so your tooling doesn’t become the obstacle.
Common mistakes (the time-sink museum)
Mistake 1: treating NT_STATUS_ACCESS_DENIED as “wrong password”
Sometimes it is. Often it isn’t. Especially if you can bind but specific calls fail, it’s more likely: wrong pipe, wrong interface, or insufficient rights for that operation.
Mistake 2: running high-priv samr calls first and concluding “RPC is blocked”
This is the classic: you try an enum command, it denies, you declare the whole RPC surface dead. Meanwhile LSARPC is quietly available and useful. You just never asked.
Mistake 3: mixing domain and local SAM assumptions (wrong target, wrong expectations)
Domain vs local matters for what “users” even means. If you assume domain context on a standalone machine, you’ll read results sideways.
Mistake 4: ignoring which pipe you’re bound to when you paste command chains
Pasting a “great command list” without tracking pipe context is like copying a recipe but swapping salt for sugar and insisting the oven is broken.
- Access denied is not a diagnosis, it’s a clue.
- Start with the lowest-impact questions.
- Track pipe + auth like you track IP + port.
Apply in 60 seconds: Add “pipe:” and “auth:” to your note template for every target.
Personal anecdote: I once mixed local and domain assumptions and spent 25 minutes “proving” a user didn’t exist. The user existed. My brain didn’t.
Don’t do this: two traps that produce false “dead ends”
Trap A: “spray-and-pray” command lists without pipe-aware branching
Command dumps feel productive. They also create noise that hides the signal. If you run 40 commands and 39 deny, you learn nothing. If you run 5 commands with a branching rule, you learn everything you need.
Trap B: concluding “no users exist” because enumdomusers denies
This is the most expensive misunderstanding. Denial is about your rights, not about the target’s population.
Mini-fix: define a fallback path that always tries lsarpc lookups before quitting
Your fallback is the difference between “stuck” and “progress.” Even when full enumeration is blocked, lookups can give you:
- Correct domain naming context
- SID patterns
- A list of likely accounts or groups through hypothesis testing
Estimate how much time you burn when you keep trying high-priv commands before validating pipe + auth.
Estimated time lost: —
Next step: Replace your next 10 retries with 3 baseline checks across LSARPC and SAMR.
Personal anecdote: The first time I measured this, I got mad. Not at the target. At myself. The target was just being a target. I was the one donating minutes like spare change.
Evidence-driven debugging: what to capture for repeatable wins
Capture: exact command, pipe, auth method, and first denial point
When you capture the right evidence, you stop re-litigating the same question. For each attempt, write down:
- Command: what you ran
- Pipe/interface: LSARPC vs SAMR (and any other you tried)
- Auth: anonymous, guest, username, domain context
- Result: success, access denied, or other error
- First denial point: where the workflow changed from “works” to “denied”
Compare behaviors across pipes with a tiny matrix (command × pipe × auth)
Make a simple grid. It doesn’t have to be fancy. A notebook table is enough. (If you want this to become automatic, you can adapt your workflow from Kali Linux lab logging and plug it into your note system so every target gets the same evidence skeleton.)
- LSARPC + anon: lookup succeeds? (Y/N)
- LSARPC + user: lookup succeeds? (Y/N)
- SAMR + anon: enum succeeds? (Y/N)
- SAMR + user: enum succeeds? (Y/N)
Next step: Make one change at a time (pipe or auth), not five changes at once.
Translate error patterns into next moves (deny-all vs selective-deny)
Here’s the practical translation layer:
- Deny-all on both pipes: assume guest/anon restrictions or wrong auth context. Pivot to credential discovery, not more RPC commands. If your share checks are also failing, distinguish “RPC denied” from “share denied” with SMBMap access denied troubleshooting.
- LSARPC works, SAMR denies: harvest structure via lookups; consider alternate enumeration paths (shares, services, web app, config leaks).
- SAMR works, LSARPC denies: less common, but still possible; treat it as “use what works,” and don’t overthink the why until after you’ve extracted value.
Your logs can predict the right pipe before you brute-force anything. Patterns repeat. That’s the whole point of being an operator instead of a gambler.
Show me the nerdy details
Authorization failures at the RPC layer can be influenced by server policy (anonymous restrictions), interface-specific access checks, and how the SMB session is mapped (guest mapping). A “bind success” does not imply that the server grants the caller permission for opnums that enumerate sensitive objects.
Short Story: The Pipe That Saved My Night (120–180 words) …
I was in a lab late, trying to “finish one more box” before sleep, the kind of decision that always ends with you bargaining with your own eyelids. rpcclient connected instantly, which felt like permission to sprint. I ran the usual user enumeration command. Denied. I tried a second one. Denied. Then a third, because apparently I needed emotional confirmation. Denied again.
I started suspecting the VM was broken, patched, haunted, or all three. Finally, out of embarrassment more than wisdom, I switched to an LSARPC-friendly lookup path and asked a smaller question: “Can you resolve a name?” It answered. Not everything, but enough. The domain structure became visible, like stage lights clicking on. Ten minutes later I had the context to pivot into share enumeration and grab what I needed. The box wasn’t blocking me. It was teaching me to ask better questions.
- Target OS/Samba hints from banners or service detection
- Whether SMB maps you to guest (and under what conditions)
- Which pipe(s) allow at least one successful low-priv call
- One “good” example command output per pipe (for baseline)
- Any creds discovered elsewhere (web app, config files, reuse patterns)
Next step: Capture this list once per target so you can switch tools (rpcclient, Impacket, Metasploit) without resetting your brain.

FAQ
Why does rpcclient connect but every command returns NT_STATUS_ACCESS_DENIED?
Because connection and authorization are different steps. You may be able to open a session and even bind to an interface, but the server denies procedure calls due to privileges, anonymous restrictions, or guest mapping. Treat it as “permission boundary,” then validate pipe and authentication context.
What’s the difference between the samr and lsarpc pipes in rpcclient?
samr is commonly used for account and group enumeration, which is frequently privilege-gated. lsarpc relates to security policy and lookup operations (like name ↔ SID mapping), which can be more permissive for low-priv users in some configurations.
How do I switch RPC pipes in rpcclient without restarting everything?
Conceptually, you switch by connecting/binding to a different named pipe interface. The exact command options vary by environment and tool version, so the safest move is to confirm the supported flags and behavior in the Samba rpcclient manual and then apply a consistent baseline workflow after each switch.
Which rpcclient commands usually work with low-priv or guest access?
It depends on the target’s policies, but “lookup-style” operations often survive longer than “enumerate everything” calls. Your best strategy is to test low-impact identity/context queries first, then name/SID lookups via LSARPC-style paths, then attempt SAMR enumeration only after you’ve proven what’s allowed.
Why does enumdomusers fail but SID lookups still succeed?
Because enumeration can be treated as sensitive (bulk disclosure), while lookups can be allowed for legitimate name resolution. Many systems restrict anonymous or low-priv bulk listing but still permit certain targeted queries.
Is NT_STATUS_ACCESS_DENIED caused by SMB signing or SMB version issues?
SMB signing and negotiation issues usually show up as connection/negotiation failures rather than consistent authorization denials after a successful prompt. If you can connect reliably and only specific calls deny, it’s more likely a privilege/interface restriction than a signing/version mismatch.
What if samr works on one host but not another in the same lab?
Different boxes can have different policy snapshots. One might allow older-style anonymous enumeration, another might restrict it. Assume “per-host policy variance” rather than “your tool is broken,” and apply the same baseline workflow on each target.
How do I tell if I’m accidentally using anonymous/guest authentication?
Look for patterns: deny-all behavior across pipes, inconsistent identity context, and access that feels “default.” The most practical method is to test with known valid credentials (if you have them) and compare outcomes while changing only one variable at a time.
Conclusion
Remember the hook: the prompt that lies. The cure is not “more commands.” The cure is better sequencing. When rpcclient connects but your calls deny, you’re not stuck, you’re being redirected to the right door. Start with LSARPC-style baseline checks, harvest what you can, and treat SAMR enumeration as a privilege tier you earn, not a default entitlement.
Here’s a quick visual you can keep in your notes. It’s intentionally simple, because the point is speed under stress.
One last practical CTA you can do in the next 15 minutes: build a tiny checklist in your notes titled “rpcclient pipe-first” with three lines: connect → LSARPC baseline → SAMR attempt. Then add a single matrix row for your current target. That alone will save you from the “scrollback spiral” on your next box. (If you want a “professional operator” baseline for documenting this cleanly, see the Obsidian OSCP host template and the OSCP enumeration template. And when you feel the urge to chase 12 side paths at once, keep the OSCP rabbit hole rule nearby.)
💡 Read the official SAMR protocol guidance
Last reviewed: 2026-02-27.