Module: RubySMB::Dcerpc::Drsr

Defined in:
lib/ruby_smb/dcerpc/drsr.rb,
lib/ruby_smb/dcerpc/drsr/drs_extensions.rb,
lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb,
lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb,
lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb,
lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb,
lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb,
lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb,
lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb,
lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb,
lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb,
lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb

Defined Under Namespace

Modules: AttrtypRequestPlugin, AttrtypResponsePlugin Classes: Attr, AttrArrayPtr, Attrblock, Attrtyp, Attrval, AttrvalArrayPtr, Attrvalblock, DrsBindRequest, DrsBindResponse, DrsByteArrayPtr, DrsCompAlgType, DrsCompressedBlob, DrsConfStringz, DrsConfStringz16, DrsCrackNamesRequest, DrsCrackNamesResponse, DrsDomainControllerInfoRequest, DrsDomainControllerInfoResponse, DrsExtensions, DrsExtensionsInt, DrsExtensionsPtr, DrsGetNcChangesRequest, DrsGetNcChangesResponse, DrsHandle, DrsMsgCrackreply, DrsMsgCrackreplyV1, DrsMsgCrackreq, DrsMsgCrackreqV1, DrsMsgDcinforeply, DrsMsgDcinforeplyV1, DrsMsgDcinforeplyV2, DrsMsgDcinforeplyV3, DrsMsgDcinforeplyVffffffff, DrsMsgDcinforeq, DrsMsgDcinforeqV1, DrsMsgGetchgreply, DrsMsgGetchgreplyV1, DrsMsgGetchgreplyV2, DrsMsgGetchgreplyV6, DrsMsgGetchgreplyV7, DrsMsgGetchgreplyV9, DrsMsgGetchgreq, DrsMsgGetchgreqV10, DrsMsgGetchgreqV11, DrsMsgGetchgreqV3, DrsMsgGetchgreqV4, DrsMsgGetchgreqV5, DrsMsgGetchgreqV7, DrsMsgGetchgreqV8, DrsNameArrayPtr, DrsUnbindRequest, DrsUnbindResponse, DsDomainControllerInfo1w, DsDomainControllerInfo1wPtr, DsDomainControllerInfo2w, DsDomainControllerInfo2wPtr, DsDomainControllerInfo3w, DsDomainControllerInfo3wPtr, DsDomainControllerInfoFfffffffw, DsDomainControllerInfoFfffffffwPtr, DsName, DsNamePtr, DsNameResultItemw, DsNameResultItemwArrayPtr, DsNameResultw, DsNameResultwPtr, Dstime, EncryptedPayload, Entinf, MtxAddr, MtxAddrPtr, OidT, PartialAttrVectorV1Ext, PartialAttrVectorV1ExtPtr, PrefixTableEntry, PrefixTableEntryArrayPtr, PropertyMetaDataExt, PropertyMetaDataExtVector, PropertyMetaDataExtVectorPtr, ReplentinflistPtr, ReplvalinfV1, ReplvalinfV1ArrayPtr, ReplvalinfV3, ReplvalinfV3ArrayPtr, SchemaPrefixTable, UptodateCursorV1, UptodateCursorV2, UptodateVectorV1Ext, UptodateVectorV1ExtPtr, UptodateVectorV2Ext, UptodateVectorV2ExtPtr, Usn, UsnVector, ValueMetaDataExtV1, ValueMetaDataExtV3, VarSizeBufferWithVersion, VarSizeBufferWithVersionPtr

Constant Summary collapse

UUID =
'E3514235-4B06-11D1-AB04-00C04FC2DCD2'
VER_MAJOR =
4
VER_MINOR =
0
NTSAPI_CLIENT_GUID =
'e24d201a-4fd6-11d1-a3da-0000f875ae0d'
DRS_BIND =

Operation numbers

0x0000
DRS_UNBIND =
0x0001
DRS_GET_NC_CHANGES =
0x0003
DRS_CRACK_NAMES =
0x000C
DRS_DOMAIN_CONTROLLER_INFO =
0x0010
DRS_EXT_BASE =

DRS_EXTENSIONS_INT Flags 5.39 DRS_EXTENSIONS_INT

0x00000001
DRS_EXT_ASYNCREPL =
0x00000002
DRS_EXT_REMOVEAPI =
0x00000004
DRS_EXT_MOVEREQ_V2 =
0x00000008
DRS_EXT_GETCHG_DEFLATE =
0x00000010
DRS_EXT_DCINFO_V1 =
0x00000020
DRS_EXT_RESTORE_USN_OPTIMIZATION =
0x00000040
DRS_EXT_ADDENTRY =
0x00000080
DRS_EXT_KCC_EXECUTE =
0x00000100
DRS_EXT_ADDENTRY_V2 =
0x00000200
DRS_EXT_LINKED_VALUE_REPLICATION =
0x00000400
DRS_EXT_DCINFO_V2 =
0x00000800
DRS_EXT_INSTANCE_TYPE_NOT_REQ_ON_MOD =
0x00001000
DRS_EXT_CRYPTO_BIND =
0x00002000
DRS_EXT_GET_REPL_INFO =
0x00004000
DRS_EXT_STRONG_ENCRYPTION =
0x00008000
DRS_EXT_DCINFO_VFFFFFFFF =
0x00010000
DRS_EXT_TRANSITIVE_MEMBERSHIP =
0x00020000
DRS_EXT_ADD_SID_HISTORY =
0x00040000
DRS_EXT_POST_BETA3 =
0x00080000
DRS_EXT_GETCHGREQ_V5 =
0x00100000
DRS_EXT_GETMEMBERSHIPS2 =
0x00200000
DRS_EXT_GETCHGREQ_V6 =
0x00400000
DRS_EXT_NONDOMAIN_NCS =
0x00800000
DRS_EXT_GETCHGREQ_V8 =
0x01000000
DRS_EXT_GETCHGREPLY_V5 =
0x02000000
DRS_EXT_GETCHGREPLY_V6 =
0x04000000
DRS_EXT_GETCHGREPLY_V9 =
0x00000100
DRS_EXT_WHISTLER_BETA3 =
0x08000000
DRS_EXT_W2K3_DEFLATE =
0x10000000
DRS_EXT_GETCHGREQ_V10 =
0x20000000
DRS_EXT_RESERVED_FOR_WIN2K_OR_DOTNET_PART2 =
0x40000000
DRS_EXT_RESERVED_FOR_WIN2K_OR_DOTNET_PART3 =
0x80000000
DRS_EXT_ADAM =

DRS_EXTENSIONS_INT FlagsExt 5.39 DRS_EXTENSIONS_INT

0x00000001
DRS_EXT_LH_BETA2 =
0x00000002
DRS_EXT_RECYCLE_BIN =
0x00000004
DRS_EXT_RPC_CORRELATIONID_1 =

DRS_EXT_GETCHGREPLY_V9 = 0x00000100 (already defined)

0x00000400
DRS_ASYNC_OP =
0x00000001
DRS_GETCHG_CHECK =
0x00000002
DRS_UPDATE_NOTIFICATION =
0x00000002
DRS_ADD_REF =
0x00000004
DRS_SYNC_ALL =
0x00000008
DRS_DEL_REF =
0x00000008
DRS_WRIT_REP =
0x00000010
DRS_INIT_SYNC =
0x00000020
DRS_PER_SYNC =
0x00000040
DRS_MAIL_REP =
0x00000080
DRS_ASYNC_REP =
0x00000100
DRS_IGNORE_ERROR =
0x00000100
DRS_TWOWAY_SYNC =
0x00000200
DRS_CRITICAL_ONLY =
0x00000400
DRS_GET_ANC =
0x00000800
DRS_GET_NC_SIZE =
0x00001000
DRS_LOCAL_ONLY =
0x00001000
DRS_NONGC_RO_REP =
0x00002000
DRS_SYNC_BYNAME =
0x00004000
DRS_REF_OK =
0x00004000
DRS_FULL_SYNC_NOW =
0x00008000
DRS_NO_SOURCE =
0x00008000
DRS_FULL_SYNC_IN_PROGRESS =
0x00010000
DRS_FULL_SYNC_PACKET =
0x00020000
DRS_SYNC_REQUEUE =
0x00040000
DRS_SYNC_URGENT =
0x00080000
DRS_REF_GCSPN =
0x00100000
DRS_NO_DISCARD =
0x00100000
DRS_NEVER_SYNCED =
0x00200000
DRS_SPECIAL_SECRET_PROCESSING =
0x00400000
DRS_INIT_SYNC_NOW =
0x00800000
DRS_PREEMPTED =
0x01000000
DRS_SYNC_FORCED =
0x02000000
DRS_DISABLE_AUTO_SYNC =
0x04000000
DRS_DISABLE_PERIODIC_SYNC =
0x08000000
DRS_USE_COMPRESSION =
0x10000000
DRS_NEVER_NOTIFY =
0x20000000
DRS_SYNC_PAS =
0x40000000
DRS_GET_ALL_GROUP_MEMBERSHIP =
0x80000000
EXOP_FSMO_REQ_ROLE =
0x00000001
EXOP_FSMO_REQ_RID_ALLOC =
0x00000002
EXOP_FSMO_RID_REQ_ROLE =
0x00000003
EXOP_FSMO_REQ_PDC =
0x00000004
EXOP_FSMO_ABANDON_ROLE =
0x00000005
EXOP_REPL_OBJ =
0x00000006
EXOP_REPL_SECRETS =
0x00000007
DRS_COMP_ALG_NONE =

Enumeration for identifying a compression algorithm. 4.1.10.2.18 DRS_COMP_ALG_TYPE

0,
DRS_COMP_ALG_UNUSED = 1,
DRS_COMP_ALG_MSZIP = 2,
DRS_COMP_ALG_WIN2K3 = 3
EXOP_ERR_SUCCESS =
0x00000001
EXOP_ERR_UNKNOWN_OP =
0x00000002
EXOP_ERR_FSMO_NOT_OWNER =
0x00000003
EXOP_ERR_UPDATE_ERR =
0x00000004
EXOP_ERR_EXCEPTION =
0x00000005
EXOP_ERR_UNKNOWN_CALLER =
0x00000006
EXOP_ERR_RID_ALLOC =
0x00000007
EXOP_ERR_FSMO_OWNER_DELETED =
0x00000008
EXOP_ERR_FSMO_PENDING_OP =
0x00000009
EXOP_ERR_MISMATCH =
0x0000000A
EXOP_ERR_COULDNT_CONTACT =
0x0000000B
EXOP_ERR_FSMO_REFUSING_ROLES =
0x0000000C
EXOP_ERR_DIR_ERROR =
0x0000000D
EXOP_ERR_FSMO_MISSING_SETTINGS =
0x0000000E
EXOP_ERR_ACCESS_DENIED =
0x0000000F
EXOP_ERR_PARAM_ERROR =
0x00000010
DS_NAME_FLAG_GCVERIFY =

DRS_MSG_CRACKREQ_V1 dwFlags 4.1.4.1.2 DRS_MSG_CRACKREQ_V1

0x00000004
DS_NAME_FLAG_TRUST_REFERRAL =
0x00000008
DS_NAME_FLAG_PRIVATE_RESOLVE_FPOS =
0x80000000
DS_UNKNOWN_NAME =
0x00000000,
DS_FQDN_1779_NAME          = 0x00000001,
DS_NT4_ACCOUNT_NAME        = 0x00000002,
DS_DISPLAY_NAME            = 0x00000003,
DS_UNIQUE_ID_NAME          = 0x00000006,
DS_CANONICAL_NAME          = 0x00000007,
DS_USER_PRINCIPAL_NAME     = 0x00000008,
DS_CANONICAL_NAME_EX       = 0x00000009,
DS_SERVICE_PRINCIPAL_NAME  = 0x0000000A,
DS_SID_OR_SID_HISTORY_NAME = 0x0000000B,
DS_DNS_DOMAIN_NAME         = 0x0000000C
DS_LIST_SITES =

formatOffered: DS_NAME_FORMAT flags, plus these flags

0xFFFFFFFF
DS_LIST_SERVERS_IN_SITE =
0xFFFFFFFE
DS_LIST_DOMAINS_IN_SITE =
0xFFFFFFFD
DS_LIST_SERVERS_FOR_DOMAIN_IN_SITE =
0xFFFFFFFC
DS_LIST_INFO_FOR_SERVER =
0xFFFFFFFB
DS_LIST_ROLES =
0xFFFFFFFA
DS_NT4_ACCOUNT_NAME_SANS_DOMAIN =
0xFFFFFFF9
DS_MAP_SCHEMA_GUID =
0xFFFFFFF8
DS_LIST_DOMAINS =
0xFFFFFFF7
DS_LIST_NCS =
0xFFFFFFF6
DS_ALT_SECURITY_IDENTITIES_NAME =
0xFFFFFFF5
DS_STRING_SID_NAME =
0xFFFFFFF4
DS_LIST_SERVERS_WITH_DCS_IN_SITE =
0xFFFFFFF3
DS_LIST_GLOBAL_CATALOG_SERVERS =
0xFFFFFFF1
DS_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX =
0xFFFFFFF0
DS_USER_PRINCIPAL_NAME_AND_ALTSECID =
0xFFFFFFEF
DS_USER_PRINCIPAL_NAME_FOR_LOGON =

formatDesired: DS_NAME_FORMAT flags, plus these flags

0xFFFFFFF2
ATTRTYP_TO_ATTID =
{
    'userPrincipalName'       => '1.2.840.113556.1.4.656',
    'sAMAccountName'          => '1.2.840.113556.1.4.221',
    'unicodePwd'              => '1.2.840.113556.1.4.90',
    'dBCSPwd'                 => '1.2.840.113556.1.4.55',
    'ntPwdHistory'            => '1.2.840.113556.1.4.94',
    'lmPwdHistory'            => '1.2.840.113556.1.4.160',
    'supplementalCredentials' => '1.2.840.113556.1.4.125',
    'objectSid'               => '1.2.840.113556.1.4.146',
    'pwdLastSet'              => '1.2.840.113556.1.4.96',
    'userAccountControl'      => '1.2.840.113556.1.4.8',
    'accountExpires'          => '1.2.840.113556.1.4.159',
    'lastLogonTimestamp'      => '1.2.840.113556.1.4.1696'
}

Instance Method Summary collapse

Instance Method Details

#decrypt_attribute_value(attribute) ⇒ Object



789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 789

def decrypt_attribute_value(attribute)
  unless @session_key
    raise RubySMB::Error::EncryptionError, 'Unable to decrypt attribute value: session key is empty'
  end

  encrypted_payload = EncryptedPayload.read(attribute)
  signature = OpenSSL::Digest::MD5.digest(@session_key + encrypted_payload.salt.to_binary_s)
  rc4 = OpenSSL::Cipher.new('rc4')
  rc4.decrypt
  rc4.key = signature
  plain_text = rc4.update(
    encrypted_payload.check_sum.to_binary_s +
    encrypted_payload.encrypted_data.to_binary_s
  )
  plain_text += rc4.final

  plain_text[4..-1]
end

#derive_key(base_key) ⇒ Object



824
825
826
827
828
829
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 824

def derive_key(base_key)
  key = [base_key].pack('L<')
  key1 = [key[0] , key[1] , key[2] , key[3] , key[0] , key[1] , key[2]]
  key2 = [key[3] , key[0] , key[1] , key[2] , key[3] , key[0] , key[1]]
  [transform_key(key1.join), transform_key(key2.join)]
end

#drs_bindRubySMB::Dcerpc::Drsr::DrsHandle

Creates a context handle that is necessary to call any other method in this interface

Returns:

Raises:



608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 608

def drs_bind
  drs_extensions_int = DrsExtensionsInt.new(
    dw_flags: DRS_EXT_GETCHGREQ_V6 | DRS_EXT_GETCHGREPLY_V6 | DRS_EXT_GETCHGREQ_V8 | DRS_EXT_STRONG_ENCRYPTION,
    dw_ext_caps: 0xFFFFFFFF
  )
  drs_bind_request = DrsBindRequest.new(pext_client: drs_extensions_int)
  response = dcerpc_request(
    drs_bind_request,
    auth_level: @auth_level,
    auth_type: @auth_type
  )
  begin
    drs_bind_response = DrsBindResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading DrsBindResponse'
  end
  unless drs_bind_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
    raise RubySMB::Dcerpc::Error::DrsrError,
      "Error returned with drs_bind: "\
      "#{WindowsError::NTStatus.find_by_retval(drs_bind_response.error_status.value).join(',')}"
  end

  ppext_server = drs_bind_response.ppext_server
  raw_drs_extensions_int = ppext_server.cb.to_binary_s + ppext_server.rgb.to_binary_s
  drs_extensions_int_response = DrsExtensionsInt.new
  # If dwExtCaps is not included, just add zeros to parse it correctly
  raw_drs_extensions_int << "\x00".b * (drs_extensions_int.num_bytes - ppext_server.cb)
  drs_extensions_int_response.read(raw_drs_extensions_int)

  unless drs_extensions_int_response.dw_repl_epoch == 0
    # Different epoch, we have to call DRSBind again
    drs_extensions_int.dw_repl_epoch = drs_extensions_int_response.dw_repl_epoch
    drs_bind_request.pext_client.assign(drs_extensions_int)
    response = dcerpc_request(
      drs_bind_request,
      auth_level: @auth_level,
      auth_type: @auth_type
    )
    begin
      drs_bind_response = DrsBindResponse.read(response)
    rescue IOError
      raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading DrsBindResponse'
    end
    unless drs_bind_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
      raise RubySMB::Dcerpc::Error::DrsrError,
        "Error returned with drs_bind: "\
        "#{WindowsError::NTStatus.find_by_retval(drs_bind_response.error_status.value).join(',')}"
    end
  end

  drs_bind_response.ph_drs
end

#drs_crack_names(h_drs, flags: 0, format_offered: DS_SID_OR_SID_HISTORY_NAME, format_desired: DS_UNIQUE_ID_NAME, rp_names: []) ⇒ Array<RubySMB::Dcerpc::Drsr::DsNameResultItemwPtr>

Looks up each of a set of objects in the directory and returns it to the caller in the requested format

Parameters:

  • h_drs (RubySMB::Dcerpc::Drsr::DrsHandle)

    Context handle previously created by the #drs_bind method

  • flags (Integer) (defaults to: 0)

    Flags (see DRS_MSG_CRACKREQ_V1 dwFlags in this file)

  • format_offered (Integer) (defaults to: DS_SID_OR_SID_HISTORY_NAME)

    The format of the names in rp_names (see DS_NAME_FORMAT constants in this file )

  • format_desired (Integer) (defaults to: DS_UNIQUE_ID_NAME)

    The format of the names returned (see DS_NAME_FORMAT constants in this file )

  • rp_names (Array<String>) (defaults to: [])

    Input names to translate

Returns:

  • (Array<RubySMB::Dcerpc::Drsr::DsNameResultItemwPtr>)

    Array of DsNameResultItemwPtr containing the translated names

Raises:



747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 747

def drs_crack_names(h_drs, flags: 0, format_offered: DS_SID_OR_SID_HISTORY_NAME, format_desired: DS_UNIQUE_ID_NAME, rp_names: [])
  drs_crack_names_request = DrsCrackNamesRequest.new(
    h_drs: h_drs,
    pmsg_in: {
      switch_type: 1,
      msg_crack: {
        dw_flags: flags,
        format_offered: format_offered,
        format_desired: format_desired,
        rp_names: rp_names
      }
    }
  )
  response = dcerpc_request(
    drs_crack_names_request,
    auth_level: @auth_level,
    auth_type: @auth_type
  )
  begin
    drs_crack_names_response = DrsCrackNamesResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading DrsCrackNamesResponse'
  end
  unless drs_crack_names_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
    raise RubySMB::Dcerpc::Error::DrsrError,
      "Error returned with drs_crack_names: "\
      "#{WindowsError::NTStatus.find_by_retval(drs_crack_names_response.error_status.value).join(',')}"
  end

  drs_crack_names_response.pmsg_out.msg_crack.p_result.r_items.to_ary
end

#drs_domain_controller_info(h_drs, domain) ⇒ Array<RubySMB::Dcerpc::Drsr::DsDomainControllerInfo1wPtr>

Retrieves information about DCs in a given domain

Parameters:

Returns:

Raises:



699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 699

def drs_domain_controller_info(h_drs, domain)
  drs_domain_controller_info_request = DrsDomainControllerInfoRequest.new(
    h_drs: h_drs,
    pmsg_in: {
      switch_type: 1,
      msg_dcinfo: {
        domain: domain,
        info_level: 2
      }
    }
  )
  response = dcerpc_request(
    drs_domain_controller_info_request,
    auth_level: @auth_level,
    auth_type: @auth_type
  )
  begin
    drs_domain_controller_info_response = DrsDomainControllerInfoResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading DrsDomainControllerInfoResponse'
  end
  unless drs_domain_controller_info_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
    raise RubySMB::Dcerpc::Error::DrsrError,
      "Error returned with drs_domain_controller_info: "\
      "#{WindowsError::NTStatus.find_by_retval(drs_domain_controller_info_response.error_status.value).join(',')}"
  end

  drs_domain_controller_info_response.pmsg_out.msg_dcinfo.r_items.to_ary
end

#drs_get_nc_changes(h_drs, nc_guid:, dsa_object_guid:) ⇒ RubySMB::Dcerpc::Drsr::DrsGetNcChangesResponse

Replicates updates from an NC replica on the server

Parameters:

  • h_drs (RubySMB::Dcerpc::Drsr::DrsHandle)

    Context handle previously created by the #drs_bind method

  • nc_guid (String)

    GUID of the DSName representing the NC (naming context) root of the replica to replicate

  • nc_guid (String)

    DSA GUID of the DC.

Returns:

Raises:



864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 864

def drs_get_nc_changes(h_drs, nc_guid:, dsa_object_guid:)
  drs_get_nc_changes_request = DrsGetNcChangesRequest.new(
    h_drs: h_drs,
    dw_in_version: 8,
    pmsg_in: {
      msg_getchg: {
        uuid_dsa_obj_dest: dsa_object_guid,
        uuid_invoc_id_src: dsa_object_guid,
        p_nc: {
          guid: nc_guid,
          string_name: ["\0"]
        },
        ul_flags: DRS_INIT_SYNC | DRS_WRIT_REP,
        c_max_objects: 1,
        ul_extended_op: EXOP_REPL_OBJ
      }
    }
  )

  ATTRTYP_TO_ATTID.values.each do |oid|
    drs_get_nc_changes_request.pmsg_in.msg_getchg.add_attrtyp_from_oid(oid)
  end

  response = dcerpc_request(
    drs_get_nc_changes_request,
    auth_level: @auth_level,
    auth_type: @auth_type
  )
  begin
    drs_get_nc_changes_response = DrsGetNcChangesResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading DrsGetNcChangesResponse'
  end
  unless drs_get_nc_changes_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
    raise RubySMB::Dcerpc::Error::DrsrError,
      "Error returned with drs_get_nc_changes: "\
      "#{WindowsError::NTStatus.find_by_retval(drs_get_nc_changes_response.error_status.value).join(',')}"
  end

  drs_get_nc_changes_response
end

#drs_unbind(ph_drs) ⇒ Object

Destroys a context handle previously created by the #drs_bind method

Raises:



667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 667

def drs_unbind(ph_drs)
  drs_unbind_request = DrsUnbindRequest.new(ph_drs: ph_drs)
  response = dcerpc_request(
    drs_unbind_request,
      auth_level: @auth_level,
      auth_type: @auth_type
  )
  begin
    drs_unbind_response = DrsUnbindResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading DrsUnbindResponse'
  end
  unless drs_unbind_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
    raise RubySMB::Dcerpc::Error::DrsrError,
      "Error returned with drs_unbind: "\
      "#{WindowsError::NTStatus.find_by_retval(drs_unbind_response.error_status.value).join(',')}"
  end

  nil
end

#remove_des_layer(crypted_hash, rid) ⇒ Object



831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 831

def remove_des_layer(crypted_hash, rid)
  key1, key2 = derive_key(rid)

  des = OpenSSL::Cipher.new('des-ecb')
  des.decrypt
  des.key = key1
  des.padding = 0
  decrypted_hash = des.update(crypted_hash[0,8])
  decrypted_hash += des.final

  des.reset
  des.decrypt
  des.key = key2
  des.padding = 0
  decrypted_hash += des.update(crypted_hash[8..-1])
  decrypted_hash += des.final

  decrypted_hash
end

#transform_key(input_key) ⇒ Object



809
810
811
812
813
814
815
816
817
818
819
820
821
# File 'lib/ruby_smb/dcerpc/drsr.rb', line 809

def transform_key(input_key)
  output_key = []
  output_key << (input_key[0].ord >> 0x01).chr
  output_key << (((input_key[0].ord & 0x01) << 6) | (input_key[1].ord >> 2)).chr
  output_key << (((input_key[1].ord & 0x03) << 5) | (input_key[2].ord >> 3)).chr
  output_key << (((input_key[2].ord & 0x07) << 4) | (input_key[3].ord >> 4)).chr
  output_key << (((input_key[3].ord & 0x0F) << 3) | (input_key[4].ord >> 5)).chr
  output_key << (((input_key[4].ord & 0x1F) << 2) | (input_key[5].ord >> 6)).chr
  output_key << (((input_key[5].ord & 0x3F) << 1) | (input_key[6].ord >> 7)).chr
  output_key << (input_key[6].ord & 0x7F).chr

  output_key.map { |byte| ((byte.ord << 1) & 0xFE).chr }.join
end