Skip to content

Instantly share code, notes, and snippets.

@masthoon
Created February 2, 2019 07:28
Show Gist options
  • Save masthoon/a2a0387cad1f3d2f02bb31159c4a4be0 to your computer and use it in GitHub Desktop.
Save masthoon/a2a0387cad1f3d2f02bb31159c4a4be0 to your computer and use it in GitHub Desktop.
Add users / groups listing & privileges
import windows.rpc
from windows.rpc import ndr
import windows.generated_def as gdef
import ctypes
class PLSAPR_OBJECT_ATTRIBUTES(ndr.NdrStructure):
MEMBERS = [ndr.NdrLong,
ndr.NdrUniquePTR(ndr.NdrWString),
ndr.NdrUniquePTR(ndr.NdrLong), # We dont care of the subtype as we will pass None
ndr.NdrLong,
ndr.NdrUniquePTR(ndr.NdrLong), # We dont care of the subtype as we will pass None
ndr.NdrUniquePTR(ndr.NdrLong)] # We dont care of the subtype as we will pass None
## From: RPCVIEW
# long Proc44_LsarOpenPolicy2(
# [in][unique][string] wchar_t* arg_0,
# [in]struct Struct_364_t* arg_1,
# [in]long arg_2,
# [out][context_handle] void** arg_3);
# This function has a [out][context_handle] meaning it return a context_handle
# Context handle are represented by 5 NdrLong where the first one is always 0
# PythonForWindows represent context_handle using NdrContextHandle
class LsarOpenPolicy2Parameter(ndr.NdrParameters):
MEMBERS = [ndr.NdrUniquePTR(ndr.NdrWString),
PLSAPR_OBJECT_ATTRIBUTES,
ndr.NdrLong]
## From: RPCVIEW
# long Proc2_LsarEnumeratePrivileges(
# [in][context_handle] void* arg_0,
# [in][out]long *arg_1,
# [out]struct Struct_110_t* arg_2,
# [in]long arg_3);
# This function has a [in][context_handle] meaning it expect a context_handle
# We can pass the NdrContextHandle returned by Proc44_LsarOpenPolicy2
class LsarEnumeratePrivilegesParameter(ndr.NdrParameters):
MEMBERS = [ndr.NdrContextHandle,
ndr.NdrLong,
ndr.NdrLong]
# NTSTATUS LsarEnumerateAccounts( [Opnum 11]
# [in] LSAPR_HANDLE PolicyHandle,
# [in] [out] unsigned long *EnumerationContext,
# [out] PLSAPR_ACCOUNT_ENUM_BUFFER EnumerationBuffer,
# [in] unsigned long PreferedMaximumLength
# );
class LsarEnumerateAccountsParameter(ndr.NdrParameters):
MEMBERS = [ndr.NdrContextHandle,
ndr.NdrLong,
ndr.NdrLong]
# NTSTATUS LsarEnumerateAccountRights( [Opum 36]
# [in] LSAPR_HANDLE PolicyHandle,
# [in] PRPC_SID AccountSid,
# [out] PLSAPR_USER_RIGHT_SET UserRights
# );
class LsarEnumerateAccountRightsParameter(ndr.NdrParameters):
MEMBERS = [ndr.NdrContextHandle,
ndr.NdrSID]
class LSAPR_POLICY_PRIVILEGE_DEF(object):
@classmethod
def unpack(cls, stream):
size1 = ndr.NdrShort.unpack(stream)
ptr = ndr.NdrShort.unpack(stream)
size2 = ndr.NdrLong.unpack(stream)
luid = ndr.NdrHyper.unpack(stream)
return ptr, luid
class LSAPR_PRIVILEGE_ENUM_BUFFER(object):
@classmethod
def unpack(cls, stream):
entries = ndr.NdrLong.unpack(stream)
array_size = ndr.NdrLong.unpack(stream)
array_ptr = ndr.NdrLong.unpack(stream)
# Unpack pointed array
array_size2 = ndr.NdrLong.unpack(stream)
assert array_size == array_size2
x = []
# unpack each elements LSAPR_POLICY_PRIVILEGE_DEF
for i in range(array_size2):
ptr, luid = LSAPR_POLICY_PRIVILEGE_DEF.unpack(stream)
if ptr:
x.append(luid)
# unpack pointed strings
result = []
for luid in x:
name = ndr.NdrWcharConformantVaryingArrays.unpack(stream)
result.append((luid, name))
return result
class LSAPR_ACCOUNT_ENUM_BUFFER(object):
@classmethod
def unpack(cls, stream):
entries = ndr.NdrLong.unpack(stream)
array_size = ndr.NdrLong.unpack(stream)
array_ptr = ndr.NdrLong.unpack(stream)
# Unpack pointed array
array_size2 = ndr.NdrLong.unpack(stream)
assert array_size == array_size2
x = []
# unpack each elements
for i in range(array_size2):
ptr = ndr.NdrLong.unpack(stream)
if ptr:
x.append(ptr)
# unpack pointed SID
result = []
for ptr in x:
sid = ndr.NdrSID.unpack(stream)
# Convert to PSID
s = ctypes.create_string_buffer(sid)
sid = gdef.PSID(ctypes.addressof(s))
sid.raw = s # keep reference on string_buffer
result.append(sid)
return result
class RPC_UNICODE_STRING(object):
@classmethod
def unpack(cls, stream):
length = ndr.NdrShort.unpack(stream)
max_length = ndr.NdrShort.unpack(stream)
ptr = ndr.NdrLong.unpack(stream)
return ptr
class LSAPR_USER_RIGHT_SET(object):
@classmethod
def unpack(cls, stream):
entries = ndr.NdrLong.unpack(stream)
array_ptr = ndr.NdrLong.unpack(stream)
# Unpack pointed array
array_size2 = ndr.NdrLong.unpack(stream)
if entries != array_size2:
# error raise(windows.winproxy.error.NtStatusException(array_size2))
return []
x = []
# unpack each elements RPC_UNICODE_STRING
for i in range(array_size2):
ptr = RPC_UNICODE_STRING.unpack(stream)
if ptr:
x.append(ptr)
# unpack pointed strings
result = []
for ptr in x:
name = ndr.NdrWcharConformantVaryingArrays.unpack(stream)
result.append(name)
return result
# Actual code
## LSASS alpc endpoints is fixed, no need for the epmapper
client = windows.rpc.RPCClient(r"\RPC Control\lsasspirpc")
## Bind to the desired interface
iid = client.bind('12345778-1234-abcd-ef00-0123456789ab', version=(0,0))
## Craft parameters and call 'LsarOpenPolicy2'
params = LsarOpenPolicy2Parameter.pack([None, (0, None, None, 0, None, None), 0x20000000])
res = client.call(iid, 44, params)
## Unpack the resulting handle
handle = ndr.NdrContextHandle.unpack(ndr.NdrStream(res))
# As context_handle have 4 NdrLong of effective data
# We can represent them as GUID
# NdrContextHandle is just a wrapper packing/unpacking GUID and taking
# care of the leading NdrLong(0) in the actual ndr representation of context_handle
print("Context Handle is: {0}\n".format(handle))
## Craft parameters and call 'LsarEnumeratePrivileges'
x = LsarEnumeratePrivilegesParameter.pack([handle, 0, 10000]);
res = client.call(iid, 2, x)
print("Privileges:")
## Unpack the resulting 'LSAPR_PRIVILEGE_ENUM_BUFFER'
priviledges = LSAPR_PRIVILEGE_ENUM_BUFFER.unpack(ndr.NdrStream(res))
for priv in priviledges:
print priv
# Helper function
def enumerate_account_rights(handle, sid):
x = LsarEnumerateAccountRightsParameter.pack([handle, sid])
res = client.call(iid, 36, x)
return LSAPR_USER_RIGHT_SET.unpack(ndr.NdrStream(res))
## Craft parameters and call 'LsarEnumerateAccounts'
x = LsarEnumerateAccountsParameter.pack([handle, 0, 10000])
res = client.call(iid, 11, x)
## Unpack the resulting 'LSAPR_ACCOUNT_ENUM_BUFFER'
users = LSAPR_ACCOUNT_ENUM_BUFFER.unpack(ndr.NdrStream(res))
print("Users & Rights:")
for user in users:
print "- {0}\\{1}".format(*windows.utils.lookup_sid(user))
for right in enumerate_account_rights(handle, user):
print "\t[*] {}".format(right)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment