mirror of
https://github.com/lgandx/Responder.git
synced 2024-10-18 05:00:39 -07:00
495 lines
16 KiB
Python
495 lines
16 KiB
Python
# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved.
|
|
#
|
|
# This software is provided under under a slightly modified version
|
|
# of the Apache Software License. See the accompanying LICENSE file
|
|
# for more information.
|
|
#
|
|
# Author: Alberto Solino (@agsolino)
|
|
#
|
|
# Description:
|
|
# [MS-LSAT] Interface implementation
|
|
#
|
|
# Best way to learn how to use these calls is to grab the protocol standard
|
|
# so you understand what the call does, and then read the test case located
|
|
# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC
|
|
#
|
|
# Some calls have helper functions, which makes it even easier to use.
|
|
# They are located at the end of this file.
|
|
# Helper functions start with "h"<name of the call>.
|
|
# There are test cases for them too.
|
|
#
|
|
from impacket import nt_errors
|
|
from impacket.dcerpc.v5.dtypes import ULONG, LONG, PRPC_SID, RPC_UNICODE_STRING, LPWSTR, PRPC_UNICODE_STRING, NTSTATUS, \
|
|
NULL
|
|
from impacket.dcerpc.v5.enum import Enum
|
|
from impacket.dcerpc.v5.lsad import LSAPR_HANDLE, PLSAPR_TRUST_INFORMATION_ARRAY
|
|
from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRENUM, NDRPOINTER, NDRUniConformantArray
|
|
from impacket.dcerpc.v5.rpcrt import DCERPCException
|
|
from impacket.dcerpc.v5.samr import SID_NAME_USE
|
|
from impacket.uuid import uuidtup_to_bin
|
|
|
|
MSRPC_UUID_LSAT = uuidtup_to_bin(('12345778-1234-ABCD-EF00-0123456789AB','0.0'))
|
|
|
|
class DCERPCSessionError(DCERPCException):
|
|
def __init__(self, error_string=None, error_code=None, packet=None):
|
|
DCERPCException.__init__(self, error_string, error_code, packet)
|
|
|
|
def __str__( self ):
|
|
key = self.error_code
|
|
if key in nt_errors.ERROR_MESSAGES:
|
|
error_msg_short = nt_errors.ERROR_MESSAGES[key][0]
|
|
error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1]
|
|
return 'LSAT SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
|
|
else:
|
|
return 'LSAT SessionError: unknown error code: 0x%x' % self.error_code
|
|
|
|
################################################################################
|
|
# CONSTANTS
|
|
################################################################################
|
|
# 2.2.10 ACCESS_MASK
|
|
POLICY_LOOKUP_NAMES = 0x00000800
|
|
|
|
################################################################################
|
|
# STRUCTURES
|
|
################################################################################
|
|
# 2.2.12 LSAPR_REFERENCED_DOMAIN_LIST
|
|
class LSAPR_REFERENCED_DOMAIN_LIST(NDRSTRUCT):
|
|
structure = (
|
|
('Entries', ULONG),
|
|
('Domains', PLSAPR_TRUST_INFORMATION_ARRAY),
|
|
('MaxEntries', ULONG),
|
|
)
|
|
|
|
class PLSAPR_REFERENCED_DOMAIN_LIST(NDRPOINTER):
|
|
referent = (
|
|
('Data', LSAPR_REFERENCED_DOMAIN_LIST),
|
|
)
|
|
|
|
# 2.2.14 LSA_TRANSLATED_SID
|
|
class LSA_TRANSLATED_SID(NDRSTRUCT):
|
|
structure = (
|
|
('Use', SID_NAME_USE),
|
|
('RelativeId', ULONG),
|
|
('DomainIndex', LONG),
|
|
)
|
|
|
|
# 2.2.15 LSAPR_TRANSLATED_SIDS
|
|
class LSA_TRANSLATED_SID_ARRAY(NDRUniConformantArray):
|
|
item = LSA_TRANSLATED_SID
|
|
|
|
class PLSA_TRANSLATED_SID_ARRAY(NDRPOINTER):
|
|
referent = (
|
|
('Data', LSA_TRANSLATED_SID_ARRAY),
|
|
)
|
|
|
|
class LSAPR_TRANSLATED_SIDS(NDRSTRUCT):
|
|
structure = (
|
|
('Entries', ULONG),
|
|
('Sids', PLSA_TRANSLATED_SID_ARRAY),
|
|
)
|
|
|
|
# 2.2.16 LSAP_LOOKUP_LEVEL
|
|
class LSAP_LOOKUP_LEVEL(NDRENUM):
|
|
class enumItems(Enum):
|
|
LsapLookupWksta = 1
|
|
LsapLookupPDC = 2
|
|
LsapLookupTDL = 3
|
|
LsapLookupGC = 4
|
|
LsapLookupXForestReferral = 5
|
|
LsapLookupXForestResolve = 6
|
|
LsapLookupRODCReferralToFullDC = 7
|
|
|
|
# 2.2.17 LSAPR_SID_INFORMATION
|
|
class LSAPR_SID_INFORMATION(NDRSTRUCT):
|
|
structure = (
|
|
('Sid', PRPC_SID),
|
|
)
|
|
|
|
# 2.2.18 LSAPR_SID_ENUM_BUFFER
|
|
class LSAPR_SID_INFORMATION_ARRAY(NDRUniConformantArray):
|
|
item = LSAPR_SID_INFORMATION
|
|
|
|
class PLSAPR_SID_INFORMATION_ARRAY(NDRPOINTER):
|
|
referent = (
|
|
('Data', LSAPR_SID_INFORMATION_ARRAY),
|
|
)
|
|
|
|
class LSAPR_SID_ENUM_BUFFER(NDRSTRUCT):
|
|
structure = (
|
|
('Entries', ULONG),
|
|
('SidInfo', PLSAPR_SID_INFORMATION_ARRAY),
|
|
)
|
|
|
|
# 2.2.19 LSAPR_TRANSLATED_NAME
|
|
class LSAPR_TRANSLATED_NAME(NDRSTRUCT):
|
|
structure = (
|
|
('Use', SID_NAME_USE),
|
|
('Name', RPC_UNICODE_STRING),
|
|
('DomainIndex', LONG),
|
|
)
|
|
|
|
# 2.2.20 LSAPR_TRANSLATED_NAMES
|
|
class LSAPR_TRANSLATED_NAME_ARRAY(NDRUniConformantArray):
|
|
item = LSAPR_TRANSLATED_NAME
|
|
|
|
class PLSAPR_TRANSLATED_NAME_ARRAY(NDRPOINTER):
|
|
referent = (
|
|
('Data', LSAPR_TRANSLATED_NAME_ARRAY),
|
|
)
|
|
|
|
class LSAPR_TRANSLATED_NAMES(NDRSTRUCT):
|
|
structure = (
|
|
('Entries', ULONG),
|
|
('Names', PLSAPR_TRANSLATED_NAME_ARRAY),
|
|
)
|
|
|
|
# 2.2.21 LSAPR_TRANSLATED_NAME_EX
|
|
class LSAPR_TRANSLATED_NAME_EX(NDRSTRUCT):
|
|
structure = (
|
|
('Use', SID_NAME_USE),
|
|
('Name', RPC_UNICODE_STRING),
|
|
('DomainIndex', LONG),
|
|
('Flags', ULONG),
|
|
)
|
|
|
|
# 2.2.22 LSAPR_TRANSLATED_NAMES_EX
|
|
class LSAPR_TRANSLATED_NAME_EX_ARRAY(NDRUniConformantArray):
|
|
item = LSAPR_TRANSLATED_NAME_EX
|
|
|
|
class PLSAPR_TRANSLATED_NAME_EX_ARRAY(NDRPOINTER):
|
|
referent = (
|
|
('Data', LSAPR_TRANSLATED_NAME_EX_ARRAY),
|
|
)
|
|
|
|
class LSAPR_TRANSLATED_NAMES_EX(NDRSTRUCT):
|
|
structure = (
|
|
('Entries', ULONG),
|
|
('Names', PLSAPR_TRANSLATED_NAME_EX_ARRAY),
|
|
)
|
|
|
|
# 2.2.23 LSAPR_TRANSLATED_SID_EX
|
|
class LSAPR_TRANSLATED_SID_EX(NDRSTRUCT):
|
|
structure = (
|
|
('Use', SID_NAME_USE),
|
|
('RelativeId', ULONG),
|
|
('DomainIndex', LONG),
|
|
('Flags', ULONG),
|
|
)
|
|
|
|
# 2.2.24 LSAPR_TRANSLATED_SIDS_EX
|
|
class LSAPR_TRANSLATED_SID_EX_ARRAY(NDRUniConformantArray):
|
|
item = LSAPR_TRANSLATED_SID_EX
|
|
|
|
class PLSAPR_TRANSLATED_SID_EX_ARRAY(NDRPOINTER):
|
|
referent = (
|
|
('Data', LSAPR_TRANSLATED_SID_EX_ARRAY),
|
|
)
|
|
|
|
class LSAPR_TRANSLATED_SIDS_EX(NDRSTRUCT):
|
|
structure = (
|
|
('Entries', ULONG),
|
|
('Sids', PLSAPR_TRANSLATED_SID_EX_ARRAY),
|
|
)
|
|
|
|
# 2.2.25 LSAPR_TRANSLATED_SID_EX2
|
|
class LSAPR_TRANSLATED_SID_EX2(NDRSTRUCT):
|
|
structure = (
|
|
('Use', SID_NAME_USE),
|
|
('Sid', PRPC_SID),
|
|
('DomainIndex', LONG),
|
|
('Flags', ULONG),
|
|
)
|
|
|
|
# 2.2.26 LSAPR_TRANSLATED_SIDS_EX2
|
|
class LSAPR_TRANSLATED_SID_EX2_ARRAY(NDRUniConformantArray):
|
|
item = LSAPR_TRANSLATED_SID_EX2
|
|
|
|
class PLSAPR_TRANSLATED_SID_EX2_ARRAY(NDRPOINTER):
|
|
referent = (
|
|
('Data', LSAPR_TRANSLATED_SID_EX2_ARRAY),
|
|
)
|
|
|
|
class LSAPR_TRANSLATED_SIDS_EX2(NDRSTRUCT):
|
|
structure = (
|
|
('Entries', ULONG),
|
|
('Sids', PLSAPR_TRANSLATED_SID_EX2_ARRAY),
|
|
)
|
|
|
|
class RPC_UNICODE_STRING_ARRAY(NDRUniConformantArray):
|
|
item = RPC_UNICODE_STRING
|
|
|
|
################################################################################
|
|
# RPC CALLS
|
|
################################################################################
|
|
# 3.1.4.4 LsarGetUserName (Opnum 45)
|
|
class LsarGetUserName(NDRCALL):
|
|
opnum = 45
|
|
structure = (
|
|
('SystemName', LPWSTR),
|
|
('UserName', PRPC_UNICODE_STRING),
|
|
('DomainName', PRPC_UNICODE_STRING),
|
|
)
|
|
|
|
class LsarGetUserNameResponse(NDRCALL):
|
|
structure = (
|
|
('UserName', PRPC_UNICODE_STRING),
|
|
('DomainName', PRPC_UNICODE_STRING),
|
|
('ErrorCode', NTSTATUS),
|
|
)
|
|
|
|
# 3.1.4.5 LsarLookupNames4 (Opnum 77)
|
|
class LsarLookupNames4(NDRCALL):
|
|
opnum = 77
|
|
structure = (
|
|
('Count', ULONG),
|
|
('Names', RPC_UNICODE_STRING_ARRAY),
|
|
('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2),
|
|
('LookupLevel', LSAP_LOOKUP_LEVEL),
|
|
('MappedCount', ULONG),
|
|
('LookupOptions', ULONG),
|
|
('ClientRevision', ULONG),
|
|
)
|
|
|
|
class LsarLookupNames4Response(NDRCALL):
|
|
structure = (
|
|
('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST),
|
|
('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2),
|
|
('MappedCount', ULONG),
|
|
('ErrorCode', NTSTATUS),
|
|
)
|
|
|
|
# 3.1.4.6 LsarLookupNames3 (Opnum 68)
|
|
class LsarLookupNames3(NDRCALL):
|
|
opnum = 68
|
|
structure = (
|
|
('PolicyHandle', LSAPR_HANDLE),
|
|
('Count', ULONG),
|
|
('Names', RPC_UNICODE_STRING_ARRAY),
|
|
('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2),
|
|
('LookupLevel', LSAP_LOOKUP_LEVEL),
|
|
('MappedCount', ULONG),
|
|
('LookupOptions', ULONG),
|
|
('ClientRevision', ULONG),
|
|
)
|
|
|
|
class LsarLookupNames3Response(NDRCALL):
|
|
structure = (
|
|
('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST),
|
|
('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2),
|
|
('MappedCount', ULONG),
|
|
('ErrorCode', NTSTATUS),
|
|
)
|
|
|
|
# 3.1.4.7 LsarLookupNames2 (Opnum 58)
|
|
class LsarLookupNames2(NDRCALL):
|
|
opnum = 58
|
|
structure = (
|
|
('PolicyHandle', LSAPR_HANDLE),
|
|
('Count', ULONG),
|
|
('Names', RPC_UNICODE_STRING_ARRAY),
|
|
('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX),
|
|
('LookupLevel', LSAP_LOOKUP_LEVEL),
|
|
('MappedCount', ULONG),
|
|
('LookupOptions', ULONG),
|
|
('ClientRevision', ULONG),
|
|
)
|
|
|
|
class LsarLookupNames2Response(NDRCALL):
|
|
structure = (
|
|
('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST),
|
|
('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX),
|
|
('MappedCount', ULONG),
|
|
('ErrorCode', NTSTATUS),
|
|
)
|
|
|
|
# 3.1.4.8 LsarLookupNames (Opnum 14)
|
|
class LsarLookupNames(NDRCALL):
|
|
opnum = 14
|
|
structure = (
|
|
('PolicyHandle', LSAPR_HANDLE),
|
|
('Count', ULONG),
|
|
('Names', RPC_UNICODE_STRING_ARRAY),
|
|
('TranslatedSids', LSAPR_TRANSLATED_SIDS),
|
|
('LookupLevel', LSAP_LOOKUP_LEVEL),
|
|
('MappedCount', ULONG),
|
|
)
|
|
|
|
class LsarLookupNamesResponse(NDRCALL):
|
|
structure = (
|
|
('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST),
|
|
('TranslatedSids', LSAPR_TRANSLATED_SIDS),
|
|
('MappedCount', ULONG),
|
|
('ErrorCode', NTSTATUS),
|
|
)
|
|
|
|
# 3.1.4.9 LsarLookupSids3 (Opnum 76)
|
|
class LsarLookupSids3(NDRCALL):
|
|
opnum = 76
|
|
structure = (
|
|
('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER),
|
|
('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX),
|
|
('LookupLevel', LSAP_LOOKUP_LEVEL),
|
|
('MappedCount', ULONG),
|
|
('LookupOptions', ULONG),
|
|
('ClientRevision', ULONG),
|
|
)
|
|
|
|
class LsarLookupSids3Response(NDRCALL):
|
|
structure = (
|
|
('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST),
|
|
('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX),
|
|
('MappedCount', ULONG),
|
|
('ErrorCode', NTSTATUS),
|
|
)
|
|
|
|
# 3.1.4.10 LsarLookupSids2 (Opnum 57)
|
|
class LsarLookupSids2(NDRCALL):
|
|
opnum = 57
|
|
structure = (
|
|
('PolicyHandle', LSAPR_HANDLE),
|
|
('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER),
|
|
('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX),
|
|
('LookupLevel', LSAP_LOOKUP_LEVEL),
|
|
('MappedCount', ULONG),
|
|
('LookupOptions', ULONG),
|
|
('ClientRevision', ULONG),
|
|
)
|
|
|
|
class LsarLookupSids2Response(NDRCALL):
|
|
structure = (
|
|
('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST),
|
|
('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX),
|
|
('MappedCount', ULONG),
|
|
('ErrorCode', NTSTATUS),
|
|
)
|
|
|
|
# 3.1.4.11 LsarLookupSids (Opnum 15)
|
|
class LsarLookupSids(NDRCALL):
|
|
opnum = 15
|
|
structure = (
|
|
('PolicyHandle', LSAPR_HANDLE),
|
|
('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER),
|
|
('TranslatedNames', LSAPR_TRANSLATED_NAMES),
|
|
('LookupLevel', LSAP_LOOKUP_LEVEL),
|
|
('MappedCount', ULONG),
|
|
)
|
|
|
|
class LsarLookupSidsResponse(NDRCALL):
|
|
structure = (
|
|
('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST),
|
|
('TranslatedNames', LSAPR_TRANSLATED_NAMES),
|
|
('MappedCount', ULONG),
|
|
('ErrorCode', NTSTATUS),
|
|
)
|
|
|
|
################################################################################
|
|
# OPNUMs and their corresponding structures
|
|
################################################################################
|
|
OPNUMS = {
|
|
14 : (LsarLookupNames, LsarLookupNamesResponse),
|
|
15 : (LsarLookupSids, LsarLookupSidsResponse),
|
|
45 : (LsarGetUserName, LsarGetUserNameResponse),
|
|
57 : (LsarLookupSids2, LsarLookupSids2Response),
|
|
58 : (LsarLookupNames2, LsarLookupNames2Response),
|
|
68 : (LsarLookupNames3, LsarLookupNames3Response),
|
|
76 : (LsarLookupSids3, LsarLookupSids3Response),
|
|
77 : (LsarLookupNames4, LsarLookupNames4Response),
|
|
}
|
|
|
|
################################################################################
|
|
# HELPER FUNCTIONS
|
|
################################################################################
|
|
def hLsarGetUserName(dce, userName = NULL, domainName = NULL):
|
|
request = LsarGetUserName()
|
|
request['SystemName'] = NULL
|
|
request['UserName'] = userName
|
|
request['DomainName'] = domainName
|
|
return dce.request(request)
|
|
|
|
def hLsarLookupNames4(dce, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001):
|
|
request = LsarLookupNames4()
|
|
request['Count'] = len(names)
|
|
for name in names:
|
|
itemn = RPC_UNICODE_STRING()
|
|
itemn['Data'] = name
|
|
request['Names'].append(itemn)
|
|
request['TranslatedSids']['Sids'] = NULL
|
|
request['LookupLevel'] = lookupLevel
|
|
request['LookupOptions'] = lookupOptions
|
|
request['ClientRevision'] = clientRevision
|
|
|
|
return dce.request(request)
|
|
|
|
def hLsarLookupNames3(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001):
|
|
request = LsarLookupNames3()
|
|
request['PolicyHandle'] = policyHandle
|
|
request['Count'] = len(names)
|
|
for name in names:
|
|
itemn = RPC_UNICODE_STRING()
|
|
itemn['Data'] = name
|
|
request['Names'].append(itemn)
|
|
request['TranslatedSids']['Sids'] = NULL
|
|
request['LookupLevel'] = lookupLevel
|
|
request['LookupOptions'] = lookupOptions
|
|
request['ClientRevision'] = clientRevision
|
|
|
|
return dce.request(request)
|
|
|
|
def hLsarLookupNames2(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001):
|
|
request = LsarLookupNames2()
|
|
request['PolicyHandle'] = policyHandle
|
|
request['Count'] = len(names)
|
|
for name in names:
|
|
itemn = RPC_UNICODE_STRING()
|
|
itemn['Data'] = name
|
|
request['Names'].append(itemn)
|
|
request['TranslatedSids']['Sids'] = NULL
|
|
request['LookupLevel'] = lookupLevel
|
|
request['LookupOptions'] = lookupOptions
|
|
request['ClientRevision'] = clientRevision
|
|
|
|
return dce.request(request)
|
|
|
|
def hLsarLookupNames(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta):
|
|
request = LsarLookupNames()
|
|
request['PolicyHandle'] = policyHandle
|
|
request['Count'] = len(names)
|
|
for name in names:
|
|
itemn = RPC_UNICODE_STRING()
|
|
itemn['Data'] = name
|
|
request['Names'].append(itemn)
|
|
request['TranslatedSids']['Sids'] = NULL
|
|
request['LookupLevel'] = lookupLevel
|
|
|
|
return dce.request(request)
|
|
|
|
def hLsarLookupSids2(dce, policyHandle, sids, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001):
|
|
request = LsarLookupSids2()
|
|
request['PolicyHandle'] = policyHandle
|
|
request['SidEnumBuffer']['Entries'] = len(sids)
|
|
for sid in sids:
|
|
itemn = LSAPR_SID_INFORMATION()
|
|
itemn['Sid'].fromCanonical(sid)
|
|
request['SidEnumBuffer']['SidInfo'].append(itemn)
|
|
|
|
request['TranslatedNames']['Names'] = NULL
|
|
request['LookupLevel'] = lookupLevel
|
|
request['LookupOptions'] = lookupOptions
|
|
request['ClientRevision'] = clientRevision
|
|
|
|
return dce.request(request)
|
|
|
|
def hLsarLookupSids(dce, policyHandle, sids, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta):
|
|
request = LsarLookupSids()
|
|
request['PolicyHandle'] = policyHandle
|
|
request['SidEnumBuffer']['Entries'] = len(sids)
|
|
for sid in sids:
|
|
itemn = LSAPR_SID_INFORMATION()
|
|
itemn['Sid'].fromCanonical(sid)
|
|
request['SidEnumBuffer']['SidInfo'].append(itemn)
|
|
|
|
request['TranslatedNames']['Names'] = NULL
|
|
request['LookupLevel'] = lookupLevel
|
|
|
|
return dce.request(request)
|