1# Copyright (c) 2003-2016 CORE Security Technologies 2# 3# This software is provided under under a slightly modified version 4# of the Apache Software License. See the accompanying LICENSE file 5# for more information. 6# 7# Author: Alberto Solino (@agsolino) 8# 9# Description: 10# [MS-LSAT] Interface implementation 11# 12# Best way to learn how to use these calls is to grab the protocol standard 13# so you understand what the call does, and then read the test case located 14# at https://github.com/CoreSecurity/impacket/tree/master/impacket/testcases/SMB_RPC 15# 16# Some calls have helper functions, which makes it even easier to use. 17# They are located at the end of this file. 18# Helper functions start with "h"<name of the call>. 19# There are test cases for them too. 20# 21from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRENUM, NDRPOINTER, NDRUniConformantArray 22from impacket.dcerpc.v5.dtypes import ULONG, LONG, PRPC_SID, RPC_UNICODE_STRING, LPWSTR, PRPC_UNICODE_STRING, NTSTATUS, \ 23 NULL 24from impacket import nt_errors 25from impacket.uuid import uuidtup_to_bin 26from impacket.dcerpc.v5.enum import Enum 27from impacket.dcerpc.v5.lsad import LSAPR_HANDLE, LSAPR_ACL, SECURITY_DESCRIPTOR_CONTROL, LSAPR_SECURITY_DESCRIPTOR, \ 28 PLSAPR_SECURITY_DESCRIPTOR, SECURITY_IMPERSONATION_LEVEL, SECURITY_CONTEXT_TRACKING_MODE, \ 29 SECURITY_QUALITY_OF_SERVICE, LSAPR_OBJECT_ATTRIBUTES, LSAPR_TRUST_INFORMATION, PLSAPR_TRUST_INFORMATION_ARRAY, \ 30 PRPC_UNICODE_STRING_ARRAY, LsarOpenPolicy2, LsarOpenPolicy, LsarClose, hLsarOpenPolicy2, hLsarOpenPolicy, hLsarClose 31from impacket.dcerpc.v5.samr import SID_NAME_USE 32from impacket.dcerpc.v5.rpcrt import DCERPCException 33 34MSRPC_UUID_LSAT = uuidtup_to_bin(('12345778-1234-ABCD-EF00-0123456789AB','0.0')) 35 36class DCERPCSessionError(DCERPCException): 37 def __init__(self, error_string=None, error_code=None, packet=None): 38 DCERPCException.__init__(self, error_string, error_code, packet) 39 40 def __str__( self ): 41 key = self.error_code 42 if nt_errors.ERROR_MESSAGES.has_key(key): 43 error_msg_short = nt_errors.ERROR_MESSAGES[key][0] 44 error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] 45 return 'LSAT SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) 46 else: 47 return 'LSAT SessionError: unknown error code: 0x%x' % self.error_code 48 49################################################################################ 50# CONSTANTS 51################################################################################ 52# 2.2.10 ACCESS_MASK 53POLICY_LOOKUP_NAMES = 0x00000800 54 55################################################################################ 56# STRUCTURES 57################################################################################ 58# 2.2.12 LSAPR_REFERENCED_DOMAIN_LIST 59class LSAPR_REFERENCED_DOMAIN_LIST(NDRSTRUCT): 60 structure = ( 61 ('Entries', ULONG), 62 ('Domains', PLSAPR_TRUST_INFORMATION_ARRAY), 63 ('MaxEntries', ULONG), 64 ) 65 66class PLSAPR_REFERENCED_DOMAIN_LIST(NDRPOINTER): 67 referent = ( 68 ('Data', LSAPR_REFERENCED_DOMAIN_LIST), 69 ) 70 71# 2.2.14 LSA_TRANSLATED_SID 72class LSA_TRANSLATED_SID(NDRSTRUCT): 73 structure = ( 74 ('Use', SID_NAME_USE), 75 ('RelativeId', ULONG), 76 ('DomainIndex', LONG), 77 ) 78 79# 2.2.15 LSAPR_TRANSLATED_SIDS 80class LSA_TRANSLATED_SID_ARRAY(NDRUniConformantArray): 81 item = LSA_TRANSLATED_SID 82 83class PLSA_TRANSLATED_SID_ARRAY(NDRPOINTER): 84 referent = ( 85 ('Data', LSA_TRANSLATED_SID_ARRAY), 86 ) 87 88class LSAPR_TRANSLATED_SIDS(NDRSTRUCT): 89 structure = ( 90 ('Entries', ULONG), 91 ('Sids', PLSA_TRANSLATED_SID_ARRAY), 92 ) 93 94# 2.2.16 LSAP_LOOKUP_LEVEL 95class LSAP_LOOKUP_LEVEL(NDRENUM): 96 class enumItems(Enum): 97 LsapLookupWksta = 1 98 LsapLookupPDC = 2 99 LsapLookupTDL = 3 100 LsapLookupGC = 4 101 LsapLookupXForestReferral = 5 102 LsapLookupXForestResolve = 6 103 LsapLookupRODCReferralToFullDC = 7 104 105# 2.2.17 LSAPR_SID_INFORMATION 106class LSAPR_SID_INFORMATION(NDRSTRUCT): 107 structure = ( 108 ('Sid', PRPC_SID), 109 ) 110 111# 2.2.18 LSAPR_SID_ENUM_BUFFER 112class LSAPR_SID_INFORMATION_ARRAY(NDRUniConformantArray): 113 item = LSAPR_SID_INFORMATION 114 115class PLSAPR_SID_INFORMATION_ARRAY(NDRPOINTER): 116 referent = ( 117 ('Data', LSAPR_SID_INFORMATION_ARRAY), 118 ) 119 120class LSAPR_SID_ENUM_BUFFER(NDRSTRUCT): 121 structure = ( 122 ('Entries', ULONG), 123 ('SidInfo', PLSAPR_SID_INFORMATION_ARRAY), 124 ) 125 126# 2.2.19 LSAPR_TRANSLATED_NAME 127class LSAPR_TRANSLATED_NAME(NDRSTRUCT): 128 structure = ( 129 ('Use', SID_NAME_USE), 130 ('Name', RPC_UNICODE_STRING), 131 ('DomainIndex', LONG), 132 ) 133 134# 2.2.20 LSAPR_TRANSLATED_NAMES 135class LSAPR_TRANSLATED_NAME_ARRAY(NDRUniConformantArray): 136 item = LSAPR_TRANSLATED_NAME 137 138class PLSAPR_TRANSLATED_NAME_ARRAY(NDRPOINTER): 139 referent = ( 140 ('Data', LSAPR_TRANSLATED_NAME_ARRAY), 141 ) 142 143class LSAPR_TRANSLATED_NAMES(NDRSTRUCT): 144 structure = ( 145 ('Entries', ULONG), 146 ('Names', PLSAPR_TRANSLATED_NAME_ARRAY), 147 ) 148 149# 2.2.21 LSAPR_TRANSLATED_NAME_EX 150class LSAPR_TRANSLATED_NAME_EX(NDRSTRUCT): 151 structure = ( 152 ('Use', SID_NAME_USE), 153 ('Name', RPC_UNICODE_STRING), 154 ('DomainIndex', LONG), 155 ('Flags', ULONG), 156 ) 157 158# 2.2.22 LSAPR_TRANSLATED_NAMES_EX 159class LSAPR_TRANSLATED_NAME_EX_ARRAY(NDRUniConformantArray): 160 item = LSAPR_TRANSLATED_NAME_EX 161 162class PLSAPR_TRANSLATED_NAME_EX_ARRAY(NDRPOINTER): 163 referent = ( 164 ('Data', LSAPR_TRANSLATED_NAME_EX_ARRAY), 165 ) 166 167class LSAPR_TRANSLATED_NAMES_EX(NDRSTRUCT): 168 structure = ( 169 ('Entries', ULONG), 170 ('Names', PLSAPR_TRANSLATED_NAME_EX_ARRAY), 171 ) 172 173# 2.2.23 LSAPR_TRANSLATED_SID_EX 174class LSAPR_TRANSLATED_SID_EX(NDRSTRUCT): 175 structure = ( 176 ('Use', SID_NAME_USE), 177 ('RelativeId', ULONG), 178 ('DomainIndex', LONG), 179 ('Flags', ULONG), 180 ) 181 182# 2.2.24 LSAPR_TRANSLATED_SIDS_EX 183class LSAPR_TRANSLATED_SID_EX_ARRAY(NDRUniConformantArray): 184 item = LSAPR_TRANSLATED_SID_EX 185 186class PLSAPR_TRANSLATED_SID_EX_ARRAY(NDRPOINTER): 187 referent = ( 188 ('Data', LSAPR_TRANSLATED_SID_EX_ARRAY), 189 ) 190 191class LSAPR_TRANSLATED_SIDS_EX(NDRSTRUCT): 192 structure = ( 193 ('Entries', ULONG), 194 ('Sids', PLSAPR_TRANSLATED_SID_EX_ARRAY), 195 ) 196 197# 2.2.25 LSAPR_TRANSLATED_SID_EX2 198class LSAPR_TRANSLATED_SID_EX2(NDRSTRUCT): 199 structure = ( 200 ('Use', SID_NAME_USE), 201 ('Sid', PRPC_SID), 202 ('DomainIndex', LONG), 203 ('Flags', ULONG), 204 ) 205 206# 2.2.26 LSAPR_TRANSLATED_SIDS_EX2 207class LSAPR_TRANSLATED_SID_EX2_ARRAY(NDRUniConformantArray): 208 item = LSAPR_TRANSLATED_SID_EX2 209 210class PLSAPR_TRANSLATED_SID_EX2_ARRAY(NDRPOINTER): 211 referent = ( 212 ('Data', LSAPR_TRANSLATED_SID_EX2_ARRAY), 213 ) 214 215class LSAPR_TRANSLATED_SIDS_EX2(NDRSTRUCT): 216 structure = ( 217 ('Entries', ULONG), 218 ('Sids', PLSAPR_TRANSLATED_SID_EX2_ARRAY), 219 ) 220 221class RPC_UNICODE_STRING_ARRAY(NDRUniConformantArray): 222 item = RPC_UNICODE_STRING 223 224################################################################################ 225# RPC CALLS 226################################################################################ 227# 3.1.4.4 LsarGetUserName (Opnum 45) 228class LsarGetUserName(NDRCALL): 229 opnum = 45 230 structure = ( 231 ('SystemName', LPWSTR), 232 ('UserName', PRPC_UNICODE_STRING), 233 ('DomainName', PRPC_UNICODE_STRING), 234 ) 235 236class LsarGetUserNameResponse(NDRCALL): 237 structure = ( 238 ('UserName', PRPC_UNICODE_STRING), 239 ('DomainName', PRPC_UNICODE_STRING), 240 ('ErrorCode', NTSTATUS), 241 ) 242 243# 3.1.4.5 LsarLookupNames4 (Opnum 77) 244class LsarLookupNames4(NDRCALL): 245 opnum = 77 246 structure = ( 247 ('Count', ULONG), 248 ('Names', RPC_UNICODE_STRING_ARRAY), 249 ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2), 250 ('LookupLevel', LSAP_LOOKUP_LEVEL), 251 ('MappedCount', ULONG), 252 ('LookupOptions', ULONG), 253 ('ClientRevision', ULONG), 254 ) 255 256class LsarLookupNames4Response(NDRCALL): 257 structure = ( 258 ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), 259 ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2), 260 ('MappedCount', ULONG), 261 ('ErrorCode', NTSTATUS), 262 ) 263 264# 3.1.4.6 LsarLookupNames3 (Opnum 68) 265class LsarLookupNames3(NDRCALL): 266 opnum = 68 267 structure = ( 268 ('PolicyHandle', LSAPR_HANDLE), 269 ('Count', ULONG), 270 ('Names', RPC_UNICODE_STRING_ARRAY), 271 ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2), 272 ('LookupLevel', LSAP_LOOKUP_LEVEL), 273 ('MappedCount', ULONG), 274 ('LookupOptions', ULONG), 275 ('ClientRevision', ULONG), 276 ) 277 278class LsarLookupNames3Response(NDRCALL): 279 structure = ( 280 ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), 281 ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2), 282 ('MappedCount', ULONG), 283 ('ErrorCode', NTSTATUS), 284 ) 285 286# 3.1.4.7 LsarLookupNames2 (Opnum 58) 287class LsarLookupNames2(NDRCALL): 288 opnum = 58 289 structure = ( 290 ('PolicyHandle', LSAPR_HANDLE), 291 ('Count', ULONG), 292 ('Names', RPC_UNICODE_STRING_ARRAY), 293 ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX), 294 ('LookupLevel', LSAP_LOOKUP_LEVEL), 295 ('MappedCount', ULONG), 296 ('LookupOptions', ULONG), 297 ('ClientRevision', ULONG), 298 ) 299 300class LsarLookupNames2Response(NDRCALL): 301 structure = ( 302 ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), 303 ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX), 304 ('MappedCount', ULONG), 305 ('ErrorCode', NTSTATUS), 306 ) 307 308# 3.1.4.8 LsarLookupNames (Opnum 14) 309class LsarLookupNames(NDRCALL): 310 opnum = 14 311 structure = ( 312 ('PolicyHandle', LSAPR_HANDLE), 313 ('Count', ULONG), 314 ('Names', RPC_UNICODE_STRING_ARRAY), 315 ('TranslatedSids', LSAPR_TRANSLATED_SIDS), 316 ('LookupLevel', LSAP_LOOKUP_LEVEL), 317 ('MappedCount', ULONG), 318 ) 319 320class LsarLookupNamesResponse(NDRCALL): 321 structure = ( 322 ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), 323 ('TranslatedSids', LSAPR_TRANSLATED_SIDS), 324 ('MappedCount', ULONG), 325 ('ErrorCode', NTSTATUS), 326 ) 327 328# 3.1.4.9 LsarLookupSids3 (Opnum 76) 329class LsarLookupSids3(NDRCALL): 330 opnum = 76 331 structure = ( 332 ('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER), 333 ('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX), 334 ('LookupLevel', LSAP_LOOKUP_LEVEL), 335 ('MappedCount', ULONG), 336 ('LookupOptions', ULONG), 337 ('ClientRevision', ULONG), 338 ) 339 340class LsarLookupSids3Response(NDRCALL): 341 structure = ( 342 ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), 343 ('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX), 344 ('MappedCount', ULONG), 345 ('ErrorCode', NTSTATUS), 346 ) 347 348# 3.1.4.10 LsarLookupSids2 (Opnum 57) 349class LsarLookupSids2(NDRCALL): 350 opnum = 57 351 structure = ( 352 ('PolicyHandle', LSAPR_HANDLE), 353 ('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER), 354 ('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX), 355 ('LookupLevel', LSAP_LOOKUP_LEVEL), 356 ('MappedCount', ULONG), 357 ('LookupOptions', ULONG), 358 ('ClientRevision', ULONG), 359 ) 360 361class LsarLookupSids2Response(NDRCALL): 362 structure = ( 363 ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), 364 ('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX), 365 ('MappedCount', ULONG), 366 ('ErrorCode', NTSTATUS), 367 ) 368 369# 3.1.4.11 LsarLookupSids (Opnum 15) 370class LsarLookupSids(NDRCALL): 371 opnum = 15 372 structure = ( 373 ('PolicyHandle', LSAPR_HANDLE), 374 ('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER), 375 ('TranslatedNames', LSAPR_TRANSLATED_NAMES), 376 ('LookupLevel', LSAP_LOOKUP_LEVEL), 377 ('MappedCount', ULONG), 378 ) 379 380class LsarLookupSidsResponse(NDRCALL): 381 structure = ( 382 ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), 383 ('TranslatedNames', LSAPR_TRANSLATED_NAMES), 384 ('MappedCount', ULONG), 385 ('ErrorCode', NTSTATUS), 386 ) 387 388################################################################################ 389# OPNUMs and their corresponding structures 390################################################################################ 391OPNUMS = { 392 14 : (LsarLookupNames, LsarLookupNamesResponse), 393 15 : (LsarLookupSids, LsarLookupSidsResponse), 394 45 : (LsarGetUserName, LsarGetUserNameResponse), 395 57 : (LsarLookupSids2, LsarLookupSids2Response), 396 58 : (LsarLookupNames2, LsarLookupNames2Response), 397 68 : (LsarLookupNames3, LsarLookupNames3Response), 398 76 : (LsarLookupSids3, LsarLookupSids3Response), 399 77 : (LsarLookupNames4, LsarLookupNames4Response), 400} 401 402################################################################################ 403# HELPER FUNCTIONS 404################################################################################ 405def hLsarGetUserName(dce, userName = NULL, domainName = NULL): 406 request = LsarGetUserName() 407 request['SystemName'] = NULL 408 request['UserName'] = userName 409 request['DomainName'] = domainName 410 return dce.request(request) 411 412def hLsarLookupNames4(dce, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001): 413 request = LsarLookupNames4() 414 request['Count'] = len(names) 415 for name in names: 416 itemn = RPC_UNICODE_STRING() 417 itemn['Data'] = name 418 request['Names'].append(itemn) 419 request['TranslatedSids']['Sids'] = NULL 420 request['LookupLevel'] = lookupLevel 421 request['LookupOptions'] = lookupOptions 422 request['ClientRevision'] = clientRevision 423 424 return dce.request(request) 425 426def hLsarLookupNames3(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001): 427 request = LsarLookupNames3() 428 request['PolicyHandle'] = policyHandle 429 request['Count'] = len(names) 430 for name in names: 431 itemn = RPC_UNICODE_STRING() 432 itemn['Data'] = name 433 request['Names'].append(itemn) 434 request['TranslatedSids']['Sids'] = NULL 435 request['LookupLevel'] = lookupLevel 436 request['LookupOptions'] = lookupOptions 437 request['ClientRevision'] = clientRevision 438 439 return dce.request(request) 440 441def hLsarLookupNames2(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001): 442 request = LsarLookupNames2() 443 request['PolicyHandle'] = policyHandle 444 request['Count'] = len(names) 445 for name in names: 446 itemn = RPC_UNICODE_STRING() 447 itemn['Data'] = name 448 request['Names'].append(itemn) 449 request['TranslatedSids']['Sids'] = NULL 450 request['LookupLevel'] = lookupLevel 451 request['LookupOptions'] = lookupOptions 452 request['ClientRevision'] = clientRevision 453 454 return dce.request(request) 455 456def hLsarLookupNames(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta): 457 request = LsarLookupNames() 458 request['PolicyHandle'] = policyHandle 459 request['Count'] = len(names) 460 for name in names: 461 itemn = RPC_UNICODE_STRING() 462 itemn['Data'] = name 463 request['Names'].append(itemn) 464 request['TranslatedSids']['Sids'] = NULL 465 request['LookupLevel'] = lookupLevel 466 467 return dce.request(request) 468 469def hLsarLookupSids2(dce, policyHandle, sids, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001): 470 request = LsarLookupSids2() 471 request['PolicyHandle'] = policyHandle 472 request['SidEnumBuffer']['Entries'] = len(sids) 473 for sid in sids: 474 itemn = LSAPR_SID_INFORMATION() 475 itemn['Sid'].fromCanonical(sid) 476 request['SidEnumBuffer']['SidInfo'].append(itemn) 477 478 request['TranslatedNames']['Names'] = NULL 479 request['LookupLevel'] = lookupLevel 480 request['LookupOptions'] = lookupOptions 481 request['ClientRevision'] = clientRevision 482 483 return dce.request(request) 484 485def hLsarLookupSids(dce, policyHandle, sids, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta): 486 request = LsarLookupSids() 487 request['PolicyHandle'] = policyHandle 488 request['SidEnumBuffer']['Entries'] = len(sids) 489 for sid in sids: 490 itemn = LSAPR_SID_INFORMATION() 491 itemn['Sid'].fromCanonical(sid) 492 request['SidEnumBuffer']['SidInfo'].append(itemn) 493 494 request['TranslatedNames']['Names'] = NULL 495 request['LookupLevel'] = lookupLevel 496 497 return dce.request(request) 498 499