1# Dispatch for various request types. 2# 3# Copyright (C) Catalyst IT Ltd. 2017 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 3 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <http://www.gnu.org/licenses/>. 17# 18import os 19import ctypes 20import random 21 22from samba.net import Net 23from samba.dcerpc import security, drsuapi, nbt, lsa, netlogon, ntlmssp 24from samba.dcerpc.netlogon import netr_WorkstationInformation 25from samba.dcerpc.security import dom_sid 26from samba.netbios import Node 27from samba.ndr import ndr_pack 28from samba.credentials import ( 29 CLI_CRED_NTLMv2_AUTH, 30 MUST_USE_KERBEROS, 31 DONT_USE_KERBEROS 32) 33from samba import NTSTATUSError 34from samba.ntstatus import ( 35 NT_STATUS_OBJECT_NAME_NOT_FOUND, 36 NT_STATUS_NO_SUCH_DOMAIN 37) 38import samba 39import dns.resolver 40from ldb import SCOPE_BASE 41 42def uint32(v): 43 return ctypes.c_uint32(v).value 44 45 46def check_runtime_error(runtime, val): 47 if runtime is None: 48 return False 49 50 err32 = uint32(runtime.args[0]) 51 if err32 == val: 52 return True 53 54 return False 55 56 57name_formats = [ 58 drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 59 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, 60 drsuapi.DRSUAPI_DS_NAME_FORMAT_DISPLAY, 61 drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID, 62 drsuapi.DRSUAPI_DS_NAME_FORMAT_CANONICAL, 63 drsuapi.DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, 64 drsuapi.DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX, 65 drsuapi.DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL, 66 drsuapi.DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY, 67 drsuapi.DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN, 68 drsuapi.DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID, 69 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX, 70 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS, 71 drsuapi.DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON, 72 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE, 73 drsuapi.DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME, 74 drsuapi.DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME, 75 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_NCS, 76 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS, 77 drsuapi.DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID, 78 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN, 79 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_ROLES, 80 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER, 81 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE, 82 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE, 83 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE, 84 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SITES, 85] 86 87 88def warning(message): 89 print("\033[37;41;1m" "Warning: %s" "\033[00m" % (message)) 90 91############################################################################### 92# 93# Packet generation functions: 94# 95# All the packet generation functions have the following form: 96# packet_${protocol}_${opcode}(packet, conversation, context) 97# 98# The functions return true, if statistics should be collected for the packet 99# false, the packet has been ignored. 100# 101# Where: 102# protocol is the protocol, i.e. cldap, dcerpc, ... 103# opcode is the protocol op code i.e. type of the packet to be 104# generated. 105# 106# packet contains data about the captured/generated packet 107# provides any extra data needed to generate the packet 108# 109# conversation Details of the current client/server interaction 110# 111# context state data for the current interaction 112# 113# 114# 115# The following protocols are not currently handled: 116# smb 117# smb2 118# browser 119# smb_netlogon 120# 121# The following drsuapi replication packets are currently ignored: 122# DsReplicaSync 123# DsGetNCChanges 124# DsReplicaUpdateRefs 125 126 127# Packet generators that do NOTHING are assigned to the null_packet 128# function which allows the conversation generators to notice this and 129# avoid a whole lot of pointless work. 130def null_packet(packet, conversation, context): 131 return False 132 133 134def packet_cldap_3(packet, conversation, context): 135 # searchRequest 136 net = Net(creds=context.creds, lp=context.lp) 137 net.finddc(domain=context.lp.get('realm'), 138 flags=(nbt.NBT_SERVER_LDAP | 139 nbt.NBT_SERVER_DS | 140 nbt.NBT_SERVER_WRITABLE)) 141 return True 142 143 144packet_cldap_5 = null_packet 145# searchResDone 146 147packet_dcerpc_0 = null_packet 148# Request 149# Can be ignored, it's the continuation of an existing conversation 150 151packet_dcerpc_2 = null_packet 152# Request 153# Server response, so should be ignored 154 155packet_dcerpc_3 = null_packet 156 157packet_dcerpc_11 = null_packet 158# Bind 159# creation of the rpc dcerpc connection is managed by the higher level 160# protocol drivers. So we ignore it when generating traffic 161 162 163packet_dcerpc_12 = null_packet 164# Bind_ack 165# Server response, so should be ignored 166 167 168packet_dcerpc_13 = null_packet 169# Bind_nak 170# Server response, so should be ignored 171 172 173packet_dcerpc_14 = null_packet 174# Alter_context 175# Generated as part of the connect process 176 177 178def packet_dcerpc_15(packet, conversation, context): 179 # Alter_context_resp 180 # This means it was GSSAPI/krb5 (probably) 181 # Check the kerberos_state and issue a diagnostic if kerberos not enabled 182 if context.user_creds.get_kerberos_state() == DONT_USE_KERBEROS: 183 warning("Kerberos disabled but have dcerpc Alter_context_resp " 184 "indicating Kerberos was used") 185 return False 186 187 188def packet_dcerpc_16(packet, conversation, context): 189 # AUTH3 190 # This means it was NTLMSSP 191 # Check the kerberos_state and issue a diagnostic if kerberos enabled 192 if context.user_creds.get_kerberos_state() == MUST_USE_KERBEROS: 193 warning("Kerberos enabled but have dcerpc AUTH3 " 194 "indicating NTLMSSP was used") 195 return False 196 197 198def packet_dns_0(packet, conversation, context): 199 # query 200 name, rtype = context.guess_a_dns_lookup() 201 dns.resolver.query(name, rtype) 202 return True 203 204 205packet_dns_1 = null_packet 206# response 207# Server response, so should be ignored 208 209 210def packet_drsuapi_0(packet, conversation, context): 211 # DsBind 212 context.get_drsuapi_connection_pair(True) 213 return True 214 215 216NAME_FORMATS = [getattr(drsuapi, _x) for _x in dir(drsuapi) 217 if 'NAME_FORMAT' in _x] 218 219 220def packet_drsuapi_12(packet, conversation, context): 221 # DsCrackNames 222 drs, handle = context.get_drsuapi_connection_pair() 223 224 names = drsuapi.DsNameString() 225 names.str = context.server 226 227 req = drsuapi.DsNameRequest1() 228 req.format_flags = 0 229 req.format_offered = 7 230 req.format_desired = random.choice(name_formats) 231 req.codepage = 1252 232 req.language = 1033 # German, I think 233 req.format_flags = 0 234 req.count = 1 235 req.names = [names] 236 237 (result, ctr) = drs.DsCrackNames(handle, 1, req) 238 return True 239 240 241def packet_drsuapi_13(packet, conversation, context): 242 # DsWriteAccountSpn 243 req = drsuapi.DsWriteAccountSpnRequest1() 244 req.operation = drsuapi.DRSUAPI_DS_SPN_OPERATION_REPLACE 245 req.unknown1 = 0 # Unused, must be 0 246 req.object_dn = context.user_dn 247 req.count = 1 # only 1 name 248 spn_name = drsuapi.DsNameString() 249 spn_name.str = 'foo/{}'.format(context.username) 250 req.spn_names = [spn_name] 251 (drs, handle) = context.get_drsuapi_connection_pair() 252 (level, res) = drs.DsWriteAccountSpn(handle, 1, req) 253 return True 254 255 256def packet_drsuapi_1(packet, conversation, context): 257 # DsUnbind 258 (drs, handle) = context.get_drsuapi_connection_pair() 259 drs.DsUnbind(handle) 260 del context.drsuapi_connections[-1] 261 return True 262 263 264packet_drsuapi_2 = null_packet 265# DsReplicaSync 266# This is between DCs, triggered on a DB change 267# Ignoring for now 268 269 270packet_drsuapi_3 = null_packet 271# DsGetNCChanges 272# This is between DCs, trigger with DB operation, 273# or DsReplicaSync between DCs. 274# Ignoring for now 275 276 277packet_drsuapi_4 = null_packet 278# DsReplicaUpdateRefs 279# Ignoring for now 280 281 282packet_epm_3 = null_packet 283# Map 284# Will be generated by higher level protocol calls 285 286 287def packet_kerberos_(packet, conversation, context): 288 # Use the presence of kerberos packets as a hint to enable kerberos 289 # for the rest of the conversation. 290 # i.e. kerberos packets are not explicitly generated. 291 context.user_creds.set_kerberos_state(MUST_USE_KERBEROS) 292 context.user_creds_bad.set_kerberos_state(MUST_USE_KERBEROS) 293 context.machine_creds.set_kerberos_state(MUST_USE_KERBEROS) 294 context.machine_creds_bad.set_kerberos_state(MUST_USE_KERBEROS) 295 context.creds.set_kerberos_state(MUST_USE_KERBEROS) 296 return False 297 298 299packet_ldap_ = null_packet 300# Unknown 301# The ldap payload was probably encrypted so just ignore it. 302 303 304def packet_ldap_0(packet, conversation, context): 305 # bindRequest 306 if packet.extra[5] == "simple": 307 # Perform a simple bind. 308 context.get_ldap_connection(new=True, simple=True) 309 else: 310 # Perform a sasl bind. 311 context.get_ldap_connection(new=True, simple=False) 312 return True 313 314 315packet_ldap_1 = null_packet 316# bindResponse 317# Server response ignored for traffic generation 318 319 320def packet_ldap_2(packet, conversation, context): 321 # unbindRequest 322 # pop the last one off -- most likely we're in a bind/unbind ping. 323 del context.ldap_connections[-1:] 324 return False 325 326 327def packet_ldap_3(packet, conversation, context): 328 # searchRequest 329 330 (scope, dn_sig, filter, attrs, extra, desc, oid) = packet.extra 331 if not scope: 332 scope = SCOPE_BASE 333 334 samdb = context.get_ldap_connection() 335 dn = context.get_matching_dn(dn_sig) 336 337 # try to guess the search expression (don't bother for base searches, as 338 # they're only looking up a single object) 339 if (filter is None or filter is '') and scope != SCOPE_BASE: 340 filter = context.guess_search_filter(attrs, dn_sig, dn) 341 342 samdb.search(dn, 343 expression=filter, 344 scope=int(scope), 345 attrs=attrs.split(','), 346 controls=["paged_results:1:1000"]) 347 return True 348 349 350packet_ldap_4 = null_packet 351# searchResEntry 352# Server response ignored for traffic generation 353 354 355packet_ldap_5 = null_packet 356# Server response ignored for traffic generation 357 358packet_ldap_6 = null_packet 359 360packet_ldap_7 = null_packet 361 362packet_ldap_8 = null_packet 363 364packet_ldap_9 = null_packet 365 366packet_ldap_16 = null_packet 367 368packet_lsarpc_0 = null_packet 369# lsarClose 370 371packet_lsarpc_1 = null_packet 372# lsarDelete 373 374packet_lsarpc_2 = null_packet 375# lsarEnumeratePrivileges 376 377packet_lsarpc_3 = null_packet 378# LsarQuerySecurityObject 379 380packet_lsarpc_4 = null_packet 381# LsarSetSecurityObject 382 383packet_lsarpc_5 = null_packet 384# LsarChangePassword 385 386packet_lsarpc_6 = null_packet 387# lsa_OpenPolicy 388# We ignore this, but take it as a hint that the lsarpc handle should 389# be over a named pipe. 390# 391 392 393def packet_lsarpc_14(packet, conversation, context): 394 # lsa_LookupNames 395 c = context.get_lsarpc_named_pipe_connection() 396 397 objectAttr = lsa.ObjectAttribute() 398 pol_handle = c.OpenPolicy2(u'', objectAttr, 399 security.SEC_FLAG_MAXIMUM_ALLOWED) 400 401 sids = lsa.TransSidArray() 402 names = [lsa.String("This Organization"), 403 lsa.String("Digest Authentication")] 404 level = lsa.LSA_LOOKUP_NAMES_ALL 405 count = 0 406 c.LookupNames(pol_handle, names, sids, level, count) 407 return True 408 409 410def packet_lsarpc_15(packet, conversation, context): 411 # lsa_LookupSids 412 c = context.get_lsarpc_named_pipe_connection() 413 414 objectAttr = lsa.ObjectAttribute() 415 pol_handle = c.OpenPolicy2(u'', objectAttr, 416 security.SEC_FLAG_MAXIMUM_ALLOWED) 417 418 sids = lsa.SidArray() 419 sid = lsa.SidPtr() 420 421 x = dom_sid("S-1-5-7") 422 sid.sid = x 423 sids.sids = [sid] 424 sids.num_sids = 1 425 names = lsa.TransNameArray() 426 level = lsa.LSA_LOOKUP_NAMES_ALL 427 count = 0 428 429 c.LookupSids(pol_handle, sids, names, level, count) 430 return True 431 432 433def packet_lsarpc_39(packet, conversation, context): 434 # lsa_QueryTrustedDomainInfoBySid 435 # Samba does not support trusted domains, so this call is expected to fail 436 # 437 c = context.get_lsarpc_named_pipe_connection() 438 439 objectAttr = lsa.ObjectAttribute() 440 441 pol_handle = c.OpenPolicy2(u'', objectAttr, 442 security.SEC_FLAG_MAXIMUM_ALLOWED) 443 444 domsid = security.dom_sid(context.domain_sid) 445 level = 1 446 try: 447 c.QueryTrustedDomainInfoBySid(pol_handle, domsid, level) 448 except NTSTATUSError as error: 449 # Object Not found is the expected result from samba, 450 # while No Such Domain is the expected result from windows, 451 # anything else is a failure. 452 if not check_runtime_error(error, NT_STATUS_OBJECT_NAME_NOT_FOUND) \ 453 and not check_runtime_error(error, NT_STATUS_NO_SUCH_DOMAIN): 454 raise 455 return True 456 457 458packet_lsarpc_40 = null_packet 459# lsa_SetTrustedDomainInfo 460# Not currently supported 461 462 463packet_lsarpc_43 = null_packet 464# LsaStorePrivateData 465 466 467packet_lsarpc_44 = null_packet 468# LsaRetrievePrivateData 469 470 471packet_lsarpc_68 = null_packet 472# LsarLookupNames3 473 474 475def packet_lsarpc_76(packet, conversation, context): 476 # lsa_LookupSids3 477 c = context.get_lsarpc_connection() 478 sids = lsa.SidArray() 479 sid = lsa.SidPtr() 480 # Need a set 481 x = dom_sid("S-1-5-7") 482 sid.sid = x 483 sids.sids = [sid] 484 sids.num_sids = 1 485 names = lsa.TransNameArray2() 486 level = lsa.LSA_LOOKUP_NAMES_ALL 487 count = 0 488 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES 489 client_revision = lsa.LSA_CLIENT_REVISION_2 490 c.LookupSids3(sids, names, level, count, lookup_options, client_revision) 491 return True 492 493 494def packet_lsarpc_77(packet, conversation, context): 495 # lsa_LookupNames4 496 c = context.get_lsarpc_connection() 497 sids = lsa.TransSidArray3() 498 names = [lsa.String("This Organization"), 499 lsa.String("Digest Authentication")] 500 level = lsa.LSA_LOOKUP_NAMES_ALL 501 count = 0 502 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES 503 client_revision = lsa.LSA_CLIENT_REVISION_2 504 c.LookupNames4(names, sids, level, count, lookup_options, client_revision) 505 return True 506 507 508def packet_nbns_0(packet, conversation, context): 509 # query 510 n = Node() 511 try: 512 n.query_name("ANAME", context.server, timeout=4, broadcast=False) 513 except: 514 pass 515 return True 516 517 518packet_nbns_1 = null_packet 519# response 520# Server response, not generated by the client 521 522 523packet_rpc_netlogon_0 = null_packet 524 525packet_rpc_netlogon_1 = null_packet 526 527packet_rpc_netlogon_4 = null_packet 528# NetrServerReqChallenge 529# generated by higher level protocol drivers 530# ignored for traffic generation 531 532packet_rpc_netlogon_14 = null_packet 533 534packet_rpc_netlogon_15 = null_packet 535 536packet_rpc_netlogon_21 = null_packet 537# NetrLogonDummyRoutine1 538# Used to determine security settings. Triggered from schannel setup 539# So no need for an explicit generator 540 541 542packet_rpc_netlogon_26 = null_packet 543# NetrServerAuthenticate3 544# Triggered from schannel set up, no need for an explicit generator 545 546 547def packet_rpc_netlogon_29(packet, conversation, context): 548 # NetrLogonGetDomainInfo [531] 549 c = context.get_netlogon_connection() 550 (auth, succ) = context.get_authenticator() 551 query = netr_WorkstationInformation() 552 553 c.netr_LogonGetDomainInfo(context.server, 554 context.netbios_name, 555 auth, 556 succ, 557 2, # TODO are there other values? 558 query) 559 return True 560 561 562def packet_rpc_netlogon_30(packet, conversation, context): 563 # NetrServerPasswordSet2 564 c = context.get_netlogon_connection() 565 (auth, succ) = context.get_authenticator() 566 DATA_LEN = 512 567 # Set the new password to the existing password, this generates the same 568 # work load as a new value, and leaves the account password intact for 569 # subsequent runs 570 newpass = context.machine_creds.get_password().encode('utf-16-le') 571 pwd_len = len(newpass) 572 filler = [x if isinstance(x, int) else ord(x) for x in os.urandom(DATA_LEN - pwd_len)] 573 pwd = netlogon.netr_CryptPassword() 574 pwd.length = pwd_len 575 pwd.data = filler + [x if isinstance(x, int) else ord(x) for x in newpass] 576 context.machine_creds.encrypt_netr_crypt_password(pwd) 577 c.netr_ServerPasswordSet2(context.server, 578 # must ends with $, so use get_username instead 579 # of get_workstation here 580 context.machine_creds.get_username(), 581 context.machine_creds.get_secure_channel_type(), 582 context.netbios_name, 583 auth, 584 pwd) 585 return True 586 587 588packet_rpc_netlogon_34 = null_packet 589 590 591def packet_rpc_netlogon_39(packet, conversation, context): 592 # NetrLogonSamLogonEx [4331] 593 def connect(creds): 594 c = context.get_netlogon_connection() 595 596 # Disable Kerberos in cli creds to extract NTLM response 597 old_state = creds.get_kerberos_state() 598 creds.set_kerberos_state(DONT_USE_KERBEROS) 599 600 logon = samlogon_logon_info(context.domain, 601 context.netbios_name, 602 creds) 603 logon_level = netlogon.NetlogonNetworkTransitiveInformation 604 validation_level = netlogon.NetlogonValidationSamInfo4 605 netr_flags = 0 606 c.netr_LogonSamLogonEx(context.server, 607 context.machine_creds.get_workstation(), 608 logon_level, 609 logon, 610 validation_level, 611 netr_flags) 612 613 creds.set_kerberos_state(old_state) 614 615 context.last_samlogon_bad =\ 616 context.with_random_bad_credentials(connect, 617 context.user_creds, 618 context.user_creds_bad, 619 context.last_samlogon_bad) 620 return True 621 622 623def samlogon_target(domain_name, computer_name): 624 target_info = ntlmssp.AV_PAIR_LIST() 625 target_info.count = 3 626 computername = ntlmssp.AV_PAIR() 627 computername.AvId = ntlmssp.MsvAvNbComputerName 628 computername.Value = computer_name 629 630 domainname = ntlmssp.AV_PAIR() 631 domainname.AvId = ntlmssp.MsvAvNbDomainName 632 domainname.Value = domain_name 633 634 eol = ntlmssp.AV_PAIR() 635 eol.AvId = ntlmssp.MsvAvEOL 636 target_info.pair = [domainname, computername, eol] 637 638 return ndr_pack(target_info) 639 640 641def samlogon_logon_info(domain_name, computer_name, creds): 642 643 target_info_blob = samlogon_target(domain_name, computer_name) 644 645 challenge = b"abcdefgh" 646 # User account under test 647 response = creds.get_ntlm_response(flags=CLI_CRED_NTLMv2_AUTH, 648 challenge=challenge, 649 target_info=target_info_blob) 650 651 logon = netlogon.netr_NetworkInfo() 652 653 logon.challenge = [x if isinstance(x, int) else ord(x) for x in challenge] 654 logon.nt = netlogon.netr_ChallengeResponse() 655 logon.nt.length = len(response["nt_response"]) 656 logon.nt.data = [x if isinstance(x, int) else ord(x) for x in response["nt_response"]] 657 658 logon.identity_info = netlogon.netr_IdentityInfo() 659 660 (username, domain) = creds.get_ntlm_username_domain() 661 logon.identity_info.domain_name.string = domain 662 logon.identity_info.account_name.string = username 663 logon.identity_info.workstation.string = creds.get_workstation() 664 665 return logon 666 667 668def packet_rpc_netlogon_40(packet, conversation, context): 669 # DsrEnumerateDomainTrusts 670 c = context.get_netlogon_connection() 671 c.netr_DsrEnumerateDomainTrusts( 672 context.server, 673 netlogon.NETR_TRUST_FLAG_IN_FOREST | 674 netlogon.NETR_TRUST_FLAG_OUTBOUND | 675 netlogon.NETR_TRUST_FLAG_INBOUND) 676 return True 677 678 679def packet_rpc_netlogon_45(packet, conversation, context): 680 # NetrLogonSamLogonWithFlags [7] 681 def connect(creds): 682 c = context.get_netlogon_connection() 683 (auth, succ) = context.get_authenticator() 684 685 # Disable Kerberos in cli creds to extract NTLM response 686 old_state = creds.get_kerberos_state() 687 creds.set_kerberos_state(DONT_USE_KERBEROS) 688 689 logon = samlogon_logon_info(context.domain, 690 context.netbios_name, 691 creds) 692 logon_level = netlogon.NetlogonNetworkTransitiveInformation 693 validation_level = netlogon.NetlogonValidationSamInfo4 694 netr_flags = 0 695 c.netr_LogonSamLogonWithFlags(context.server, 696 context.machine_creds.get_workstation(), 697 auth, 698 succ, 699 logon_level, 700 logon, 701 validation_level, 702 netr_flags) 703 704 creds.set_kerberos_state(old_state) 705 706 context.last_samlogon_bad =\ 707 context.with_random_bad_credentials(connect, 708 context.user_creds, 709 context.user_creds_bad, 710 context.last_samlogon_bad) 711 return True 712 713 714def packet_samr_0(packet, conversation, context): 715 # Open 716 c = context.get_samr_context() 717 c.get_handle() 718 return True 719 720 721def packet_samr_1(packet, conversation, context): 722 # Close 723 c = context.get_samr_context() 724 s = c.get_connection() 725 # close the last opened handle, may not always be accurate 726 # but will do for load simulation 727 if c.user_handle is not None: 728 s.Close(c.user_handle) 729 c.user_handle = None 730 elif c.group_handle is not None: 731 s.Close(c.group_handle) 732 c.group_handle = None 733 elif c.domain_handle is not None: 734 s.Close(c.domain_handle) 735 c.domain_handle = None 736 c.rids = None 737 elif c.handle is not None: 738 s.Close(c.handle) 739 c.handle = None 740 c.domain_sid = None 741 return True 742 743 744def packet_samr_3(packet, conversation, context): 745 # QuerySecurity 746 c = context.get_samr_context() 747 s = c.get_connection() 748 if c.user_handle is None: 749 packet_samr_34(packet, conversation, context) 750 s.QuerySecurity(c.user_handle, 1) 751 return True 752 753 754def packet_samr_5(packet, conversation, context): 755 # LookupDomain 756 c = context.get_samr_context() 757 s = c.get_connection() 758 h = c.get_handle() 759 d = lsa.String() 760 d.string = context.domain 761 c.domain_sid = s.LookupDomain(h, d) 762 return True 763 764 765def packet_samr_6(packet, conversation, context): 766 # EnumDomains 767 c = context.get_samr_context() 768 s = c.get_connection() 769 h = c.get_handle() 770 s.EnumDomains(h, 0, 0) 771 return True 772 773 774def packet_samr_7(packet, conversation, context): 775 # OpenDomain 776 c = context.get_samr_context() 777 s = c.get_connection() 778 h = c.get_handle() 779 if c.domain_sid is None: 780 packet_samr_5(packet, conversation, context) 781 782 c.domain_handle = s.OpenDomain(h, 783 security.SEC_FLAG_MAXIMUM_ALLOWED, 784 c.domain_sid) 785 return True 786 787 788SAMR_QUERY_DOMAIN_INFO_LEVELS = [8, 12] 789 790 791def packet_samr_8(packet, conversation, context): 792 # QueryDomainInfo [228] 793 c = context.get_samr_context() 794 s = c.get_connection() 795 if c.domain_handle is None: 796 packet_samr_7(packet, conversation, context) 797 level = random.choice(SAMR_QUERY_DOMAIN_INFO_LEVELS) 798 s.QueryDomainInfo(c.domain_handle, level) 799 return True 800 801 802packet_samr_14 = null_packet 803# CreateDomainAlias 804# Ignore these for now. 805 806 807def packet_samr_15(packet, conversation, context): 808 # EnumDomainAliases 809 c = context.get_samr_context() 810 s = c.get_connection() 811 if c.domain_handle is None: 812 packet_samr_7(packet, conversation, context) 813 814 s.EnumDomainAliases(c.domain_handle, 100, 0) 815 return True 816 817 818def packet_samr_16(packet, conversation, context): 819 # GetAliasMembership 820 c = context.get_samr_context() 821 s = c.get_connection() 822 if c.domain_handle is None: 823 packet_samr_7(packet, conversation, context) 824 825 sids = lsa.SidArray() 826 sid = lsa.SidPtr() 827 sid.sid = c.domain_sid 828 sids.sids = [sid] 829 s.GetAliasMembership(c.domain_handle, sids) 830 return True 831 832 833def packet_samr_17(packet, conversation, context): 834 # LookupNames 835 c = context.get_samr_context() 836 s = c.get_connection() 837 if c.domain_handle is None: 838 packet_samr_7(packet, conversation, context) 839 840 name = lsa.String(context.username) 841 c.rids = s.LookupNames(c.domain_handle, [name]) 842 return True 843 844 845def packet_samr_18(packet, conversation, context): 846 # LookupRids 847 c = context.get_samr_context() 848 s = c.get_connection() 849 if c.rids is None: 850 packet_samr_17(packet, conversation, context) 851 rids = [] 852 for r in c.rids: 853 for i in r.ids: 854 rids.append(i) 855 s.LookupRids(c.domain_handle, rids) 856 return True 857 858 859def packet_samr_19(packet, conversation, context): 860 # OpenGroup 861 c = context.get_samr_context() 862 s = c.get_connection() 863 if c.domain_handle is None: 864 packet_samr_7(packet, conversation, context) 865 866 rid = 0x202 # Users I think. 867 c.group_handle = s.OpenGroup(c.domain_handle, 868 security.SEC_FLAG_MAXIMUM_ALLOWED, 869 rid) 870 return True 871 872 873def packet_samr_25(packet, conversation, context): 874 # QueryGroupMember 875 c = context.get_samr_context() 876 s = c.get_connection() 877 if c.group_handle is None: 878 packet_samr_19(packet, conversation, context) 879 s.QueryGroupMember(c.group_handle) 880 return True 881 882 883def packet_samr_34(packet, conversation, context): 884 # OpenUser 885 c = context.get_samr_context() 886 s = c.get_connection() 887 if c.rids is None: 888 packet_samr_17(packet, conversation, context) 889 c.user_handle = s.OpenUser(c.domain_handle, 890 security.SEC_FLAG_MAXIMUM_ALLOWED, 891 c.rids[0].ids[0]) 892 return True 893 894 895def packet_samr_36(packet, conversation, context): 896 # QueryUserInfo 897 c = context.get_samr_context() 898 s = c.get_connection() 899 if c.user_handle is None: 900 packet_samr_34(packet, conversation, context) 901 level = 1 902 s.QueryUserInfo(c.user_handle, level) 903 return True 904 905 906packet_samr_37 = null_packet 907 908 909def packet_samr_39(packet, conversation, context): 910 # GetGroupsForUser 911 c = context.get_samr_context() 912 s = c.get_connection() 913 if c.user_handle is None: 914 packet_samr_34(packet, conversation, context) 915 s.GetGroupsForUser(c.user_handle) 916 return True 917 918 919packet_samr_40 = null_packet 920 921packet_samr_44 = null_packet 922 923 924def packet_samr_57(packet, conversation, context): 925 # Connect2 926 c = context.get_samr_context() 927 c.get_handle() 928 return True 929 930 931def packet_samr_64(packet, conversation, context): 932 # Connect5 933 c = context.get_samr_context() 934 c.get_handle() 935 return True 936 937 938packet_samr_68 = null_packet 939 940 941def packet_srvsvc_16(packet, conversation, context): 942 # NetShareGetInfo 943 s = context.get_srvsvc_connection() 944 server_unc = "\\\\" + context.server 945 share_name = "IPC$" 946 level = 1 947 s.NetShareGetInfo(server_unc, share_name, level) 948 return True 949 950 951def packet_srvsvc_21(packet, conversation, context): 952 """NetSrvGetInfo 953 954 FIXME: Level changed from 102 to 101 here, to bypass Windows error. 955 956 Level 102 will cause WERR_ACCESS_DENIED error against Windows, because: 957 958 > If the level is 102 or 502, the Windows implementation checks whether 959 > the caller is a member of one of the groups previously mentioned or 960 > is a member of the Power Users local group. 961 962 It passed against Samba since this check is not implemented by Samba yet. 963 964 refer to: 965 966 https://msdn.microsoft.com/en-us/library/cc247297.aspx#Appendix_A_80 967 968 """ 969 srvsvc = context.get_srvsvc_connection() 970 server_unc = "\\\\" + context.server 971 level = 101 972 srvsvc.NetSrvGetInfo(server_unc, level) 973 return True 974