diff --git a/lib/ruby_smb/dcerpc/request.rb b/lib/ruby_smb/dcerpc/request.rb index 819b18e2b..32d28f9dd 100644 --- a/lib/ruby_smb/dcerpc/request.rb +++ b/lib/ruby_smb/dcerpc/request.rb @@ -79,6 +79,8 @@ class Request < BinData::Record samr_set_information_user2_request Samr::SAMR_SET_INFORMATION_USER2 samr_delete_user_request Samr::SAMR_DELETE_USER samr_query_information_domain_request Samr::SAMR_QUERY_INFORMATION_DOMAIN + samr_unicode_change_password_user2_request Samr::SAMR_UNICODE_CHANGE_PASSWORD_USER2 + samr_change_password_user_request Samr::SAMR_CHANGE_PASSWORD_USER string :default end choice 'Wkssvc', selection: -> { opnum } do diff --git a/lib/ruby_smb/dcerpc/samr.rb b/lib/ruby_smb/dcerpc/samr.rb index 44db53bc9..9e2c86a5a 100644 --- a/lib/ruby_smb/dcerpc/samr.rb +++ b/lib/ruby_smb/dcerpc/samr.rb @@ -24,8 +24,10 @@ module Samr SAMR_GET_MEMBERS_IN_GROUP = 0x0019 SAMR_OPEN_USER = 0x0022 SAMR_DELETE_USER = 0x0023 + SAMR_CHANGE_PASSWORD_USER = 0x0026 SAMR_GET_GROUPS_FOR_USER = 0x0027 SAMR_CREATE_USER2_IN_DOMAIN = 0x0032 + SAMR_UNICODE_CHANGE_PASSWORD_USER2 = 0x0037 SAMR_SET_INFORMATION_USER2 = 0x003a SAMR_CONNECT5 = 0x0040 SAMR_RID_TO_SID = 0x0041 @@ -318,6 +320,58 @@ class PulongArray < Ndr::NdrConfArray extend Ndr::PointerClassPlugin end + # [2.2.7.3 ENCRYPTED_NT_OWF_PASSWORD](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/ce061fef-6d4f-4802-bd5d-26b11f14f4a6) + class EncryptedNtOwfPassword < Ndr::NdrStruct + default_parameter byte_align: 4 + ndr_fixed_byte_array :buffer, initial_length: 16 + + # [2.2.11.1.2 Encrypting a 64-bit block with a 7-byte key](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/ebdb15df-8d0d-4347-9d62-082e6eccac40) + def self.to_output_key(input_key) + output_key = [] + input_key = input_key.unpack('C'*7) + output_key.append(input_key[0] >> 0x01) + output_key.append(((input_key[0]&0x01)<<6) | (input_key[1]>>2)) + output_key.append(((input_key[1]&0x03)<<5) | (input_key[2]>>3)) + output_key.append(((input_key[2]&0x07)<<4) | (input_key[3]>>4)) + output_key.append(((input_key[3]&0x0F)<<3) | (input_key[4]>>5)) + output_key.append(((input_key[4]&0x1F)<<2) | (input_key[5]>>6)) + output_key.append(((input_key[5]&0x3F)<<1) | (input_key[6]>>7)) + output_key.append(input_key[6] & 0x7F) + + output_key = output_key.map {|x| (x << 1) & 0xFE} + + output_key.pack('C'*8) + end + + # [2.2.11.1 DES-ECB-LM](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/3f5ec79d-b449-4ab2-9423-c4dccbe0b184) + def self.encrypt_hash(hash:, key:) + block1 = hash[0..7] + block2 = hash[8..] + key1 = to_output_key(key[0..6]) + key2 = to_output_key(key[7..13]) # The last two bytes are ignored + + cipher1 = OpenSSL::Cipher.new('des-ecb').tap do |cipher| + cipher.encrypt + cipher.key = key1 + end + + cipher2 = OpenSSL::Cipher.new('des-ecb').tap do |cipher| + cipher.encrypt + cipher.key = key2 + end + + cipher1.update(block1) + cipher2.update(block2) + end + end + + EncryptedLmOwfPassword = EncryptedNtOwfPassword + + class PencryptedNtOwfPassword < EncryptedNtOwfPassword + extend Ndr::PointerClassPlugin + end + + PencryptedLmOwfPassword = PencryptedNtOwfPassword + # [2.2.7.4 SAMPR_ULONG_ARRAY](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/2feb3806-4db2-45b7-90d2-86c8336a31ba) class SamprUlongArray < Ndr::NdrStruct default_parameter byte_align: 4 @@ -333,6 +387,28 @@ class RpcShortBlob < BinData::Record ndr_uint16_array_ptr :buffer end + # [2.2.6.21 SAMPR_ENCRYPTED_USER_PASSWORD](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/23f9ef4c-cf3e-4330-9287-ea4799b03201) + class SamprEncryptedUserPassword < Ndr::NdrStruct + default_parameter byte_align: 4 + ndr_fixed_byte_array :buffer, initial_length: 516 + + def self.encrypt_password(password, old_password_nt) + # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/5fe3c4c4-e71b-440d-b2fd-8448bfaf6e04 + password = password.encode('UTF-16LE').force_encoding('ASCII-8BIT') + buffer = password.rjust(512, "\x00") + [ password.length ].pack('V') + cipher = OpenSSL::Cipher.new('RC4').tap do |cipher| + cipher.encrypt + cipher.key = old_password_nt + end + cipher.update(buffer) + end + end + + class PsamprEncryptedUserPassword < SamprEncryptedUserPassword + extend Ndr::PointerClassPlugin + end + + # [2.2.6.22 SAMPR_ENCRYPTED_USER_PASSWORD_NEW](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/112ecc94-1cbe-41cd-b669-377402c20786) class SamprEncryptedUserPasswordNew < BinData::Record ndr_fixed_byte_array :buffer, initial_length: 532 @@ -413,12 +489,22 @@ class UserControlInformation < BinData::Record ndr_uint32 :user_account_control end + # [2.2.6.25 SAMPR_USER_INTERNAL1_INFORMATION](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/50d17755-c6b8-40bd-8cac-bd6cfa31adf2) + class SamprUserInternal1Information < BinData::Record + encrypted_nt_owf_password :encrypted_nt_owf_password + encrypted_nt_owf_password :encrypted_lm_owf_password + ndr_uint8 :nt_password_present + ndr_uint8 :lm_password_present + ndr_uint8 :password_expired + end + # [2.2.6.29 SAMPR_USER_INFO_BUFFER](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/9496c26e-490b-4e76-827f-2695fc216f35) class SamprUserInfoBuffer < BinData::Record ndr_uint16 :tag choice :member, selection: :tag do user_control_information USER_CONTROL_INFORMATION sampr_user_internal4_information_new USER_INTERNAL4_INFORMATION_NEW + sampr_user_internal1_information USER_INTERNAL1_INFORMATION end end @@ -523,6 +609,10 @@ def get_key_values require 'ruby_smb/dcerpc/samr/samr_get_groups_for_user_response' require 'ruby_smb/dcerpc/samr/samr_set_information_user2_request' require 'ruby_smb/dcerpc/samr/samr_set_information_user2_response' + require 'ruby_smb/dcerpc/samr/samr_change_password_user_request' + require 'ruby_smb/dcerpc/samr/samr_change_password_user_response' + require 'ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request' + require 'ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response' require 'ruby_smb/dcerpc/samr/samr_delete_user_request' require 'ruby_smb/dcerpc/samr/samr_delete_user_response' require 'ruby_smb/dcerpc/samr/samr_query_information_domain_request' @@ -882,6 +972,117 @@ def samr_set_information_user2(user_handle:, user_info:) nil end + # Change the password on a user object. + # + # @param user_handle [SamprHandle] Handle representing the user to change the password for + # @param old_password [String] The previous password (either this or old_nt_hash must be specified) + # @param new_password [String] The password to set on the account + # @param new_nt_hash [String] The new password's NT hash + # @param new_lm_hash [String] The new password's LM hash + # @param old_nt_hash [String] The previous password's NT hash (either this or old_password must be specified) + # @param old_lm_hash [String] The previous password's LM hash (currently ignored) + # @return nothing is returned on success + # @raise [RubySMB::Dcerpc::Error::SamrError] if the response error status + # is not STATUS_SUCCESS + def samr_change_password_user(user_handle:, old_password:nil, new_password:nil, new_nt_hash:nil, new_lm_hash:nil, old_nt_hash:nil, old_lm_hash:nil) + if new_password.nil? == new_nt_hash.nil? + raise ArgumentError.new('Provide either new password or new password hashes, but not both') + end + + if old_password.nil? == old_nt_hash.nil? + raise ArgumentError.new('Provide either old password or old password hashes, but not both') + end + + if old_password + old_lm_hash = Net::NTLM.lm_hash(old_password[0..13]) + old_nt_hash = Net::NTLM.ntlm_hash(old_password) + end + + if new_nt_hash.nil? + new_nt_hash = Net::NTLM::ntlm_hash(new_password) + new_lm_hash = Net::NTLM.lm_hash(new_password[0..13]) + elsif new_lm_hash.nil? + new_lm_hash = Net::NTLM.lm_hash('') + end + + samr_change_password_user_request = SamrChangePasswordUserRequest.new( + user_handle: user_handle, + lm_present: 0, + old_lm_encrypted_with_new_lm: nil, + new_lm_encrypted_with_old_lm: nil, + nt_present: 1, + old_nt_encrypted_with_new_nt: PencryptedNtOwfPassword.new(buffer: EncryptedNtOwfPassword.encrypt_hash(hash: old_nt_hash, key: new_nt_hash)), + new_nt_encrypted_with_old_nt: PencryptedNtOwfPassword.new(buffer: EncryptedNtOwfPassword.encrypt_hash(hash: new_nt_hash, key: old_nt_hash)), + nt_cross_encryption_present: 0, + new_nt_encrypted_with_new_lm: nil, + lm_cross_encryption_present: 1, + new_lm_encrypted_with_new_nt: PencryptedNtOwfPassword.new(buffer: EncryptedNtOwfPassword.encrypt_hash(hash: new_lm_hash, key: new_nt_hash)), + ) + response = dcerpc_request(samr_change_password_user_request) + begin + samr_unicode_change_password_user2_response = SamrChangePasswordUserResponse.read(response) + rescue IOError + raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading SamrUnicodeChangePasswordUser2Response' + end + unless samr_unicode_change_password_user2_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS + raise RubySMB::Dcerpc::Error::SamrError, + "Error returned while changing user password: "\ + "#{WindowsError::NTStatus.find_by_retval(samr_unicode_change_password_user2_response.error_status.value).join(',')}" + end + + nil + end + + + # Change the password on a user. + # + # @param server_name [String] The server name; can be ignored by the server + # @param target_username [String] The user for which we're changing the password + # @param old_password [String] The previous password (either this or old_nt_hash must be specified) + # @param new_password [String] The password to set on the account + # @param old_nt_hash [String] The previous password's NT hash (either this or old_password must be specified) + # @param old_lm_hash [String] The previous password's LM hash (currently ignored) + # @return nothing is returned on success + # @raise [RubySMB::Dcerpc::Error::SamrError] if the response error status + # is not STATUS_SUCCESS + def samr_unicode_change_password_user2(server_name: "", target_username:, old_password:nil, new_password:, old_nt_hash:nil, old_lm_hash:nil) + #if old_lm_hash.nil? != old_nt_hash.nil? + # raise ArgumentError.new('If providing the previous NT/LM hash, must provide both') + #end + if old_password.nil? == old_nt_hash.nil? + raise ArgumentError.new('Provide either old password or old password hashes, but not both') + end + + if old_password + old_lm_hash = Net::NTLM.lm_hash(old_password[0..13]) + old_nt_hash = Net::NTLM.ntlm_hash(old_password) + end + + new_nt_hash = Net::NTLM::ntlm_hash(new_password) + + samr_unicode_change_password_user2_request = SamrUnicodeChangePasswordUser2Request.new( + server_name: server_name, + user_name: target_username, + new_password_encrypted_with_old_nt: SamprEncryptedUserPassword.new(buffer: SamprEncryptedUserPassword.encrypt_password(new_password, old_nt_hash)), + old_nt_owf_password_encrypted_with_new_nt: PencryptedNtOwfPassword.new(buffer: EncryptedNtOwfPassword.encrypt_hash(hash: old_nt_hash, key: new_nt_hash)), + lm_present: 0 + ) + samr_unicode_change_password_user2_request + response = dcerpc_request(samr_unicode_change_password_user2_request) + begin + samr_unicode_change_password_user2_response = SamrUnicodeChangePasswordUser2Response.read(response) + rescue IOError + raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading SamrUnicodeChangePasswordUser2Response' + end + unless samr_unicode_change_password_user2_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS + raise RubySMB::Dcerpc::Error::SamrError, + "Error returned while changing user password: "\ + "#{WindowsError::NTStatus.find_by_retval(samr_unicode_change_password_user2_response.error_status.value).join(',')}" + end + + nil + end + # Closes (that is, releases server-side resources used by) any context # handle obtained from this RPC interface # diff --git a/lib/ruby_smb/dcerpc/samr/samr_change_password_user_request.rb b/lib/ruby_smb/dcerpc/samr/samr_change_password_user_request.rb new file mode 100755 index 000000000..da8d4f0ce --- /dev/null +++ b/lib/ruby_smb/dcerpc/samr/samr_change_password_user_request.rb @@ -0,0 +1,31 @@ +module RubySMB + module Dcerpc + module Samr + + # [3.1.5.10.1 SamrChangePasswordUser (Opnum 38)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/9699d8ca-e1a4-433c-a8c3-d7bebeb01476) + class SamrChangePasswordUserRequest < BinData::Record + attr_reader :opnum + + endian :little + + sampr_handle :user_handle + ndr_uint8 :lm_present + pencrypted_nt_owf_password :old_lm_encrypted_with_new_lm + pencrypted_nt_owf_password :new_lm_encrypted_with_old_lm + ndr_uint8 :nt_present + pencrypted_nt_owf_password :old_nt_encrypted_with_new_nt + pencrypted_nt_owf_password :new_nt_encrypted_with_old_nt + ndr_uint8 :nt_cross_encryption_present + pencrypted_nt_owf_password :new_nt_encrypted_with_new_nt + ndr_uint8 :lm_cross_encryption_present + pencrypted_nt_owf_password :new_lm_encrypted_with_new_nt + + def initialize_instance + super + @opnum = SAMR_CHANGE_PASSWORD_USER + end + end + + end + end +end diff --git a/lib/ruby_smb/dcerpc/samr/samr_change_password_user_response.rb b/lib/ruby_smb/dcerpc/samr/samr_change_password_user_response.rb new file mode 100755 index 000000000..58f777b2d --- /dev/null +++ b/lib/ruby_smb/dcerpc/samr/samr_change_password_user_response.rb @@ -0,0 +1,21 @@ +module RubySMB + module Dcerpc + module Samr + + # [3.1.5.10.1 SamrChangePasswordUser (Opnum 38)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/9699d8ca-e1a4-433c-a8c3-d7bebeb01476) + class SamrChangePasswordUserResponse < BinData::Record + attr_reader :opnum + + endian :little + + ndr_uint32 :error_status + + def initialize_instance + super + @opnum = SAMR_CHANGE_PASSWORD_USER + end + end + + end + end +end diff --git a/lib/ruby_smb/dcerpc/samr/samr_get_members_in_group_response.rb b/lib/ruby_smb/dcerpc/samr/samr_get_members_in_group_response.rb index 498b39f4e..7da2f33e9 100755 --- a/lib/ruby_smb/dcerpc/samr/samr_get_members_in_group_response.rb +++ b/lib/ruby_smb/dcerpc/samr/samr_get_members_in_group_response.rb @@ -14,7 +14,7 @@ class PsamprGetMembersBuffer < SamprGetMembersBuffer extend Ndr::PointerClassPlugin end - # [2.1.5.8.3 SamrGetMembersInGroup (Opnum 25)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/a4adbf20-040f-4416-a960-e5b7917fdae7) + # [3.1.5.8.3 SamrGetMembersInGroup (Opnum 25)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/3ed5030d-88a3-42ca-a6e0-8c12aa2fdfbd) class SamrGetMembersInGroupResponse < BinData::Record attr_reader :opnum diff --git a/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request.rb b/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request.rb new file mode 100755 index 000000000..d0ea4532a --- /dev/null +++ b/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request.rb @@ -0,0 +1,27 @@ +module RubySMB + module Dcerpc + module Samr + + # [3.1.5.10.3 SamrUnicodeChangePasswordUser2 (Opnum 55)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/acb3204a-da8b-478e-9139-1ea589edb880) + class SamrUnicodeChangePasswordUser2Request < BinData::Record + attr_reader :opnum + + endian :little + + prpc_unicode_string :server_name + rpc_unicode_string :user_name + psampr_encrypted_user_password :new_password_encrypted_with_old_nt + pencrypted_nt_owf_password :old_nt_owf_password_encrypted_with_new_nt + ndr_uint8 :lm_present + psampr_encrypted_user_password :new_password_encrypted_with_old_lm + pencrypted_nt_owf_password :old_lm_owf_password_encrypted_with_new_nt + + def initialize_instance + super + @opnum = SAMR_UNICODE_CHANGE_PASSWORD_USER2 + end + end + + end + end +end diff --git a/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response.rb b/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response.rb new file mode 100755 index 000000000..f1dc336d1 --- /dev/null +++ b/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response.rb @@ -0,0 +1,21 @@ +module RubySMB + module Dcerpc + module Samr + + # [3.1.5.10.3 SamrUnicodeChangePasswordUser2 (Opnum 55)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/acb3204a-da8b-478e-9139-1ea589edb880) + class SamrUnicodeChangePasswordUser2Response < BinData::Record + attr_reader :opnum + + endian :little + + ndr_uint32 :error_status + + def initialize_instance + super + @opnum = SAMR_UNICODE_CHANGE_PASSWORD_USER2 + end + end + + end + end +end diff --git a/spec/lib/ruby_smb/dcerpc/samr/encrypted_nt_owf_password_spec.rb b/spec/lib/ruby_smb/dcerpc/samr/encrypted_nt_owf_password_spec.rb new file mode 100755 index 000000000..58514c2f2 --- /dev/null +++ b/spec/lib/ruby_smb/dcerpc/samr/encrypted_nt_owf_password_spec.rb @@ -0,0 +1,10 @@ +RSpec.describe RubySMB::Dcerpc::Samr::EncryptedNtOwfPassword do + it 'Creates output key' do + expect(described_class.to_output_key('ABCDEFG')).to eq ["40a09068442A188E"].pack('H*') + expect(described_class.to_output_key('AAAAAAA')).to eq ["40A05028140A0482"].pack('H*') + end + + it 'Encrypts a hash' do + expect(described_class.encrypt_hash(hash: 'AAAAAAAAAAAAAAAA', key: 'BBBBBBBBBBBBBB')).to eq ["8cd90c3de08ecda28cd90c3de08ecda2"].pack('H*') + end +end diff --git a/spec/lib/ruby_smb/dcerpc/samr/sampr_encrypted_user_password_spec.rb b/spec/lib/ruby_smb/dcerpc/samr/sampr_encrypted_user_password_spec.rb new file mode 100755 index 000000000..0b5ef0434 --- /dev/null +++ b/spec/lib/ruby_smb/dcerpc/samr/sampr_encrypted_user_password_spec.rb @@ -0,0 +1,9 @@ +RSpec.describe RubySMB::Dcerpc::Samr::SamprEncryptedUserPassword do + + it 'Encrypts correctly' do + password = 'newPassword1!' + old_password_nt = 'AAAAAAAAAAAAAAAA' + expected = ['c2cbe63dc0a3cda1baab695ce4f0352b774592b214a905796a6ba9fd30e0ffc56d60812bfd7f45420f5332922b50cfdcde3133e3e45c5eb6c16023006cb4ff7d41f54fa009a64fa66b00fa41094d7db6c4cc9a430a7ad43122047b696d934645974fee7551dcafac28c0869106417fd3fbfc34a87a56d6141aac2b6d134723f2224791b39749bc93f4405f78ba09dcd9b4d29e72ae0c873a8d468323793fffccc2a9d8dc4d975c42064208d898df71ef0889b2e5a9cfa6c8c2758eb15b6fdd332d6d7d2829f3a3bc2a7ecd7f87d1fd4aed25d93de6a7baf8e0247e2f5b831ca7646eef7a11e2f9410574707ef85c9db8cc125fb6254fe1e111a662006343299fcb8f8fb641cb1d188ff6e5c50334ca199603a93907093e6d35d80b2dade79360bc672870d29cdf5f80120ac53e9ce3c3718d0f8097cdae2318b8e27108fc1066491e5b034f55c1e8ff00a53d2eb7b0e0ffc10236a5a530795b84f33d66eb51388d6da112886c8ea482af0ec7e9c0a549a561244ee9185b5387b05d3c5e74d88e355aef22dab1d5039d0a0caa22437f6e520121ef5d21da729bb0cdee5cbb3b450bf1d0fcafad5ac518b0535628e2a96a2d0d2f8acd3e42147e700c2889cbc92c5533f1889b49d41c0ae9a05fc0a754060c0680296de5c712a3299cdd5c646582348fc2e32a68ae4fc2a3b91fb423adc617a20b28c1d6297f14a870329e6aa802d22ba97c'].pack('H*') + expect(described_class.encrypt_password(password, old_password_nt)).to eq expected + end +end diff --git a/spec/lib/ruby_smb/dcerpc/samr/samr_change_password_user_request_spec.rb b/spec/lib/ruby_smb/dcerpc/samr/samr_change_password_user_request_spec.rb new file mode 100755 index 000000000..c0a4556dc --- /dev/null +++ b/spec/lib/ruby_smb/dcerpc/samr/samr_change_password_user_request_spec.rb @@ -0,0 +1,28 @@ +RSpec.describe RubySMB::Dcerpc::Samr::SamrChangePasswordUserRequest do + subject(:packet) { described_class.new } + + describe '#initialize_instance' do + it 'sets #opnum to SAMR_CHANGE_PASSWORD_USER constant' do + expect(packet.opnum).to eq(RubySMB::Dcerpc::Samr::SAMR_CHANGE_PASSWORD_USER) + end + end + + it 'reads itself' do + uuid = RubySMB::Dcerpc::Uuid.new + uuid.set(SecureRandom.uuid) + new_packet = described_class.new({ + user_handle: RubySMB::Dcerpc::Samr::SamprHandle.new(context_handle_attributes: 42, :context_handle_uuid => uuid), + lm_present: 1, + old_lm_encrypted_with_new_lm: RubySMB::Dcerpc::Samr::PencryptedNtOwfPassword.new(buffer: SecureRandom::bytes(16)), + new_lm_encrypted_with_old_lm: RubySMB::Dcerpc::Samr::PencryptedNtOwfPassword.new(buffer: SecureRandom::bytes(16)), + nt_present: 1, + old_nt_encrypted_with_new_nt: RubySMB::Dcerpc::Samr::PencryptedNtOwfPassword.new(buffer: SecureRandom::bytes(16)), + new_nt_encrypted_with_old_nt: RubySMB::Dcerpc::Samr::PencryptedNtOwfPassword.new(buffer: SecureRandom::bytes(16)), + nt_cross_encryption_present: 1, + new_nt_encrypted_with_new_nt: RubySMB::Dcerpc::Samr::PencryptedNtOwfPassword.new(buffer: SecureRandom::bytes(16)), + lm_cross_encryption_present: 1, + new_lm_encrypted_with_new_nt: RubySMB::Dcerpc::Samr::PencryptedNtOwfPassword.new(buffer: SecureRandom::bytes(16)) + }) + expect(packet.read(new_packet.to_binary_s)).to eq(new_packet) + end +end diff --git a/spec/lib/ruby_smb/dcerpc/samr/samr_change_password_user_response_spec.rb b/spec/lib/ruby_smb/dcerpc/samr/samr_change_password_user_response_spec.rb new file mode 100755 index 000000000..cd5bbc4f5 --- /dev/null +++ b/spec/lib/ruby_smb/dcerpc/samr/samr_change_password_user_response_spec.rb @@ -0,0 +1,16 @@ +RSpec.describe RubySMB::Dcerpc::Samr::SamrChangePasswordUserResponse do + subject(:packet) { described_class.new } + + describe '#initialize_instance' do + it 'sets #opnum to SAMR_CHANGE_PASSWORD_USER constant' do + expect(packet.opnum).to eq(RubySMB::Dcerpc::Samr::SAMR_CHANGE_PASSWORD_USER) + end + end + + it 'reads itself' do + new_packet = described_class.new({ + error_status: 4 + }) + expect(packet.read(new_packet.to_binary_s)).to eq(new_packet) + end +end diff --git a/spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request_spec.rb b/spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request_spec.rb new file mode 100755 index 000000000..44d07ed5a --- /dev/null +++ b/spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request_spec.rb @@ -0,0 +1,22 @@ +RSpec.describe RubySMB::Dcerpc::Samr::SamrUnicodeChangePasswordUser2Request do + subject(:packet) { described_class.new } + + describe '#initialize_instance' do + it 'sets #opnum to SAMR_UNICODE_CHANGE_PASSWORD_USER2 constant' do + expect(packet.opnum).to eq(RubySMB::Dcerpc::Samr::SAMR_UNICODE_CHANGE_PASSWORD_USER2) + end + end + + it 'reads itself' do + new_packet = described_class.new({ + server_name: 'my-server', + user_name: 'user.person', + new_password_encrypted_with_old_nt: RubySMB::Dcerpc::Samr::PsamprEncryptedUserPassword.new(buffer: SecureRandom::bytes(516)), + pencrypted_nt_owf_password: RubySMB::Dcerpc::Samr::PencryptedNtOwfPassword.new(buffer: SecureRandom::bytes(16)), + lm_present: 1, + new_password_encrypted_with_old_lm: RubySMB::Dcerpc::Samr::PsamprEncryptedUserPassword.new(buffer: SecureRandom::bytes(516)), + old_lm_owf_password_encrypted_with_new_nt: RubySMB::Dcerpc::Samr::PencryptedNtOwfPassword.new(buffer: SecureRandom::bytes(16)), + }) + expect(packet.read(new_packet.to_binary_s)).to eq(new_packet) + end +end diff --git a/spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response_spec.rb b/spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response_spec.rb new file mode 100755 index 000000000..dfab6e206 --- /dev/null +++ b/spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response_spec.rb @@ -0,0 +1,16 @@ +RSpec.describe RubySMB::Dcerpc::Samr::SamrUnicodeChangePasswordUser2Response do + subject(:packet) { described_class.new } + + describe '#initialize_instance' do + it 'sets #opnum to SAMR_UNICODE_CHANGE_PASSWORD_USER2 constant' do + expect(packet.opnum).to eq(RubySMB::Dcerpc::Samr::SAMR_UNICODE_CHANGE_PASSWORD_USER2) + end + end + + it 'reads itself' do + new_packet = described_class.new({ + error_status: 4 + }) + expect(packet.read(new_packet.to_binary_s)).to eq(new_packet) + end +end