RPC Access Denied 2k22 for event log query
Hey,
I've been trying to use even and even6 to query event logs over RPC.
No matter what I do I'm always getting access denied when trying to get a handle to the security log.
I've tried both even and even6 bindings, local admin, domain admin, kerberos auth, ntlm auth, added users to event log reader and disabled UAC entirely.
No matter what I do I cannot get a handle successfully over SMB rpc. When I use powershell it works fine using the rpc via 135 -> high port.
Anyone successfully bound on 2k22 before? ..
Could you give a short PoC script showing the error? I recently had trouble using OpenBackupEventLogW on Server 2025 which was related to how rpc buffer length is now calculated, maybe this is related? https://github.com/oiweiwei/go-msrpc/issues/52
Could you give a short PoC script showing the error? I recently had trouble using OpenBackupEventLogW on Server 2025 which was related to how rpc buffer length is now calculated, maybe this is related? oiweiwei/go-msrpc#52
## short snipped functions
stringbinding = f'ncacn_np:{target}[\\pipe\\eventlog]'
rpctransport = transport.DCERPCTransportFactory(stringbinding)
rpctransport.set_credentials(username, password, domain, lmhash, nthash)
dce = rpctransport.get_dce_rpc()
dce.connect()
dce.bind(even.MSRPC_UUID_EVEN)
resp = even.hElfrOpenELW(dce, moduleName=logname)
handle = resp['LogHandle']
# Get record range
num_resp = even.hElfrNumberOfRecords(dce, handle)
oldest_resp = even.hElfrOldestRecordNumber(dce, handle)
## snipped some init functions, basic read
try:
resp = even.hElfrReadELW(dce, handle, flags, current_offset, MAX_BATCH_BUFF)
data = b''.join(resp['Buffer'])
except Exception as e
break
My issue is I'm having some real inconsistent binds. On some machines 2k12+ it binds and reads fine. Others I'll bind and get rpc access denied. I can't figure out what the niche difference is.
For 2k25 unless microsoft disabled legacy API, I always get access denied. In the process of porting to even6.
Could you give a short PoC script showing the error? I recently had trouble using OpenBackupEventLogW on Server 2025 which was related to how rpc buffer length is now calculated, maybe this is related? oiweiwei/go-msrpc#52
# Use SMB named pipe binding for MS-EVEN6 (EventLog RPC)
stringbinding = f'ncacn_np:{address}[\\pipe\\eventlog]'
rpctransport = transport.DCERPCTransportFactory(stringbinding)
# Set credentials
rpctransport.set_credentials(username, password, domain, lmhash, nthash)
# Enable Kerberos if requested
if kerberos:
if not dc_ip:
raise Exception("Kerberos requires --dc-ip (Domain Controller IP).")
rpctransport.set_kerberos(True, dc_ip)
# Get DCE/RPC connection
dce = rpctransport.get_dce_rpc()
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
print(f"[+] Connecting to {address} EventLog service over SMB pipe as {domain}\\{username} using {'Kerberos' if kerberos else 'NTLM'}")
dce.connect()
try:
dce.bind(even6.MSRPC_UUID_EVEN6)
except Exception as e:
print(f"[*] bind failed - {e}")
print("[+] DCE/RPC bind successful.")
# Register log query
flags = even6.EvtReadNewestToOldest
try:
resp = even6.hEvtRpcRegisterLogQuery(dce, path=log_name, flags=flags)
log_handle = resp['Handle']
print(f"[+] Opened query handle for log: {log_name}")
except DCERPCException as ex:
if "rpc_s_access_denied" in str(ex):
print("[-] Access denied: Kerberos or additional privileges required for Security log.")
return
else:
raise
2k25 I always get access denied using ntlm - tried forcing a kerberos ticket and get the same.
Do you have a full example? I tried using LogHunter which had three problems:
- Sealing/Signing was not activated https://github.com/rtpt-romankarwacik/LogHunter/commit/edb1f1a90593a053adae7a10507badf93e32d9e2
hElfrOpenELWdid not work properly, asModuleNameandRegModuleNameareRPC_UNICODE_STRING, which somehow calculate theMaximumLengthdifferently on newer Windows versions (I don't know if this is exclusive for MS_EVEN). Workaround for this is here: https://github.com/rtpt-romankarwacik/impacket/commit/943dfdbe592a741224c4c899f1669edd967f8977hElfrReadELWwithEVENTLOG_SEEK_READdid work on Server 2025, but didn't work on my Windows 11 24H2, butEVENTLOG_SEQUENTIAL_READdid work
@rtpt-romankarwacik note, that you need to add +2 to accommodate bytes length with null terminator. adding +1 is a mistake deduced from misinterpreting the captures you've received, even in captures provided I've observed that MaximumLength is +2 and NDR conformant varying array size is +1 (because utf-16 array has a one extra element - null-terminator, which is 2 bytes).
proper way of handling this would be checking if string has a null-terminator, compute maximum length (including null-terminator), trimming it from the string and computing length (without null-terminator)
Do you have a full example? I tried using LogHunter which had three problems:
so here is even6. Regardless of domain admin, local admin, high priv user added into event log query group etc I always get rpc access denied. Same exact thing happens with even.
TokenFilterPolicy UAC key is set too. I can WMI and I can smb client etc.
Haven't even tested this even6 given all I get is access denied when trying to bind to the event log named pipe lol
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import sys
from impacket import version
from impacket.examples import logger
from impacket.examples.utils import parse_target
from impacket.dcerpc.v5 import transport, even6
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_PKT_PRIVACY, DCERPCException
from impacket.smbconnection import SessionError as SMBSessionError
def build_parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(
description="EVEN6 Security/4624 PoC (SMB named-pipe only)",
)
p.add_argument("target", help="[[domain/]username[:password]@]<target>")
p.add_argument("-hashes", metavar="LMHASH:NTHASH", help="NTLM hashes, LMHASH:NTHASH")
p.add_argument("-no-pass", action="store_true", help="Don't prompt for password")
p.add_argument("-count", type=int, default=5, help="Number of events to fetch (default: 5)")
p.add_argument("-timeout", type=int, default=2000, help="Query timeout (ms), default: 2000")
return p
def connect_np(address: str, username: str, password: str, domain: str, lmhash: str, nthash: str):
# Force SMB/named pipe transport to \pipe\eventlog
binding = fr"ncacn_np:{address}[\pipe\eventlog]"
rpctransport = transport.DCERPCTransportFactory(binding)
rpctransport.set_credentials(username, password, domain, lmhash, nthash)
try:
# Not all transports expose these; ignore if they don't.
rpctransport.setRemoteHost(address) # type: ignore[attr-defined]
rpctransport.setRemoteName(address) # type: ignore[attr-defined]
except Exception:
pass
dce = rpctransport.get_dce_rpc()
dce.connect()
dce.bind(even6.MSRPC_UUID_EVEN6)
return dce
def main() -> int:
logger.init()
parser = build_parser()
args = parser.parse_args()
domain, username, password, address = parse_target(args.target)
lmhash = nthash = ""
if args.hashes:
try:
lmhash, nthash = args.hashes.split(":", 1)
except ValueError:
print("[!] Invalid -hashes format; expected LMHASH:NTHASH", file=sys.stderr)
return 2
if password == "" and username and not args.hashes and not args.no_pass:
from getpass import getpass
password = getpass("Password: ")
channel = "Security"
query = "*[System[EventID=4624]]"
dce = None
try:
dce = connect_np(address, username or "", password or "", domain or "", lmhash, nthash)
handle = even6.hEvtRpcRegisterLogQuery(
dce,
channel + " ",
even6.EvtQueryChannelName | even6.EvtReadNewestToOldest,
query + " ",
)["Handle"]
resp = even6.hEvtRpcQueryNext(dce, handle, max(1, args.count), max(1, args.timeout))
count = resp["NumActualRecords"]
buf = resp["ResultBuffer"]
for i in range(count):
off = resp["EventDataIndices"][i]["Data"]
size = resp["EventDataSizes"][i]["Data"]
xml = buf[off: off + size].decode("utf-16-le", "ignore").strip()
print("=" * 80)
print(xml)
even6.hEvtRpcClose(dce, handle)
return 0
except SMBSessionError as e:
print(f"[!] SMB error: {e}")
print(
"[i] Ensure the '\\\\pipe\\eventlog' named pipe is accessible and that firewall/ACLs allow Remote Event Log.")
return 5
except DCERPCException as e:
print(f"[!] DCERPC error: {e}")
return 6
except Exception as e:
print(f"[!] Unexpected error: {e}")
return 1
finally:
if dce:
try:
dce.disconnect()
except Exception:
pass
if __name__ == "__main__":
print(version.BANNER)
sys.exit(main())
[!] DCERPC error: rpc_s_access_denied
The spec says it only works via ncacn_ip_tcp: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-even6/31f0897c-034e-490f-b5cc-f2dd824d7378 Use:
from impacket.dcerpc.v5.epm import hept_map
# [...]
rpctransport = transport.DCERPCTransportFactory(hept_map(address, even6.MSRPC_UUID_EVEN6, protocol="ncacn_ip_tcp"))
The spec says it only works via ncacn_ip_tcp: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-even6/31f0897c-034e-490f-b5cc-f2dd824d7378 Use:
from impacket.dcerpc.v5.epm import hept_map # [...] rpctransport = transport.DCERPCTransportFactory(hept_map(address, even6.MSRPC_UUID_EVEN6, protocol="ncacn_ip_tcp"))
Thanks for the reply. Still throws access denied unfortunately👎
ah this successfully binds.
Now to figure out the disgusting way for parsing the returned data.
def connect_even6_tcp(address: str, username: str, password: str, domain: str,
lmhash: Optional[str], nthash: Optional[str],
do_kerb: bool, kdc_host: Optional[str]):
binding = hept_map(address, even6.MSRPC_UUID_EVEN6, protocol="ncacn_ip_tcp")
println(f"[dbg] EPM binding: {binding}")
rpctransport = transport.DCERPCTransportFactory(binding)
rpctransport.set_credentials(
username=username or "",
password=password or "",
domain=domain or "",
lmhash=lmhash or "",
nthash=nthash or "",
)
dce = rpctransport.get_dce_rpc()
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
if do_kerb:
rpctransport.set_kerberos(True, kdc_host)
dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
else:
rpctransport.set_kerberos(False, None)
dce.set_auth_type(RPC_C_AUTHN_WINNT)
dce.connect()
dce.bind(even6.MSRPC_UUID_EVEN6)
println("[dbg] Bound to EVEN6 over TCP")
return dce