Class: RubySMB::SMB2::Pipe
- Includes:
- Dcerpc
- Defined in:
- lib/ruby_smb/smb2/pipe.rb
Overview
Represents a pipe on the Remote server that we can perform various I/O operations on.
Constant Summary collapse
- STATUS_CONNECTED =
0x00000003
- STATUS_CLOSING =
0x00000004
Constants included from Dcerpc
Dcerpc::DCE_C_AUTHZ_DCE, Dcerpc::DCE_C_AUTHZ_NAME, Dcerpc::MAX_RECV_FRAG, Dcerpc::MAX_XMIT_FRAG, Dcerpc::RPC_C_AUTHN_DEFAULT, Dcerpc::RPC_C_AUTHN_GSS_KERBEROS, Dcerpc::RPC_C_AUTHN_GSS_NEGOTIATE, Dcerpc::RPC_C_AUTHN_GSS_SCHANNEL, Dcerpc::RPC_C_AUTHN_LEVEL_CALL, Dcerpc::RPC_C_AUTHN_LEVEL_CONNECT, Dcerpc::RPC_C_AUTHN_LEVEL_DEFAULT, Dcerpc::RPC_C_AUTHN_LEVEL_NONE, Dcerpc::RPC_C_AUTHN_LEVEL_PKT, Dcerpc::RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, Dcerpc::RPC_C_AUTHN_LEVEL_PKT_PRIVACY, Dcerpc::RPC_C_AUTHN_NETLOGON, Dcerpc::RPC_C_AUTHN_NONE, Dcerpc::RPC_C_AUTHN_WINNT
Constants inherited from File
Instance Attribute Summary
Attributes inherited from File
#attributes, #guid, #last_access, #last_change, #last_write, #name, #size, #size_on_disk, #tree, #tree_connect_encrypt_data
Instance Method Summary collapse
- #bind(options = {}) ⇒ Object
- #dcerpc_request(stub_packet, options = {}) ⇒ Object
-
#initialize(tree:, response:, name:) ⇒ Pipe
constructor
A new instance of Pipe.
- #ioctl_send_recv(action, options = {}) ⇒ Object
-
#is_connected? ⇒ Boolean
True if pipe is connected, false otherwise.
-
#peek(peek_size: 0) ⇒ RubySMB::SMB2::Packet::IoctlResponse
Performs a peek operation on the named pipe.
-
#peek_available ⇒ Integer
The number of bytes available to be read from the pipe.
-
#peek_state ⇒ Integer
Pipe status.
Methods included from Dcerpc
#add_auth_verifier, #auth_provider_complete_handshake, #auth_provider_decrypt_and_verify, #auth_provider_encrypt_and_sign, #auth_provider_init, #force_set_auth_params, #get_auth_padding_length, #get_response_full_stub, #handle_integrity_privacy, #max_buffer_size=, #process_ntlm_type2, #recv_struct, #send_packet, #set_decrypted_packet, #set_encrypted_packet, #set_integrity_privacy, #set_signature_on_packet
Methods inherited from File
#append, #close, #delete, #delete_packet, #read, #read_packet, #rename, #rename_packet, #send_recv_read, #send_recv_write, #set_header_fields, #write, #write_packet
Constructor Details
#initialize(tree:, response:, name:) ⇒ Pipe
Returns a new instance of Pipe.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 13 def initialize(tree:, response:, name:) raise ArgumentError, 'No Name Provided' if name.nil? case name when 'netlogon', '\\netlogon' extend RubySMB::Dcerpc::Netlogon when 'srvsvc', '\\srvsvc' extend RubySMB::Dcerpc::Srvsvc when 'svcctl', '\\svcctl' extend RubySMB::Dcerpc::Svcctl when 'winreg', '\\winreg' extend RubySMB::Dcerpc::Winreg when 'samr', '\\samr' extend RubySMB::Dcerpc::Samr when 'wkssvc', '\\wkssvc' extend RubySMB::Dcerpc::Wkssvc when 'lsarpc', '\\lsarpc' extend RubySMB::Dcerpc::Lsarpc when 'netdfs', '\\netdfs' extend RubySMB::Dcerpc::Dfsnm when 'cert', '\\cert' extend RubySMB::Dcerpc::Icpr when 'efsrpc', '\\efsrpc' extend RubySMB::Dcerpc::Efsrpc end super(tree: tree, response: response, name: name) end |
Instance Method Details
#bind(options = {}) ⇒ Object
40 41 42 43 44 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 40 def bind(={}) @size = 1024 @ntlm_client = @tree.client.ntlm_client super end |
#dcerpc_request(stub_packet, options = {}) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 102 def dcerpc_request(stub_packet, ={}) .merge!(endpoint: stub_packet.class.name.split('::').at(-2)) dcerpc_request = RubySMB::Dcerpc::Request.new({ opnum: stub_packet.opnum }, ) dcerpc_request.stub.read(stub_packet.to_binary_s) if [:auth_level] && [RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY].include?([:auth_level]) set_integrity_privacy(dcerpc_request, auth_level: [:auth_level], auth_type: [:auth_type]) end ioctl_send_recv(dcerpc_request, ) end |
#ioctl_send_recv(action, options = {}) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 114 def ioctl_send_recv(action, ={}) request = set_header_fields(RubySMB::SMB2::Packet::IoctlRequest.new()) request.ctl_code = 0x0011C017 request.flags.is_fsctl = 0x00000001 # TODO: handle fragmentation when the request size > MAX_XMIT_FRAG request.buffer = action.to_binary_s ioctl_raw_response = @tree.client.send_recv(request) ioctl_response = RubySMB::SMB2::Packet::IoctlResponse.read(ioctl_raw_response) unless ioctl_response.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID, expected_cmd: RubySMB::SMB2::Packet::IoctlRequest::COMMAND, packet: ioctl_response ) end unless [WindowsError::NTStatus::STATUS_SUCCESS, WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW].include?(ioctl_response.status_code) raise RubySMB::Error::UnexpectedStatusCode, ioctl_response.status_code end raw_data = ioctl_response.output_data if ioctl_response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW raw_data << read(bytes: @tree.client.max_buffer_size - ioctl_response.output_count) dcerpc_response = dcerpc_response_from_raw_response(raw_data) unless dcerpc_response.pdu_header.pfc_flags.first_frag == 1 raise RubySMB::Dcerpc::Error::InvalidPacket, "Not the first fragment" end if [:auth_level] && [RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY].include?([:auth_level]) handle_integrity_privacy(dcerpc_response, auth_level: [:auth_level], auth_type: [:auth_type]) end stub_data = dcerpc_response.stub.to_s loop do break if dcerpc_response.pdu_header.pfc_flags.last_frag == 1 raw_data = read(bytes: @tree.client.max_buffer_size) dcerpc_response = dcerpc_response_from_raw_response(raw_data) if [:auth_level] && [RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY].include?([:auth_level]) handle_integrity_privacy(dcerpc_response, auth_level: [:auth_level], auth_type: [:auth_type]) end stub_data << dcerpc_response.stub.to_s end stub_data else dcerpc_response = dcerpc_response_from_raw_response(raw_data) if [:auth_level] && [RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY].include?([:auth_level]) handle_integrity_privacy(dcerpc_response, auth_level: [:auth_level], auth_type: [:auth_type]) end dcerpc_response.stub.to_s end end |
#is_connected? ⇒ Boolean
Returns True if pipe is connected, false otherwise.
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 90 def is_connected? begin state = peek_state rescue RubySMB::Error::UnexpectedStatusCode => e if e. == 'STATUS_FILE_CLOSED' return false end raise e end state == STATUS_CONNECTED end |
#peek(peek_size: 0) ⇒ RubySMB::SMB2::Packet::IoctlResponse
Performs a peek operation on the named pipe
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 52 def peek(peek_size: 0) packet = RubySMB::SMB2::Packet::IoctlRequest.new packet.ctl_code = RubySMB::Fscc::ControlCodes::FSCTL_PIPE_PEEK packet.flags.is_fsctl = true # read at least 16 bytes for state, avail, msg_count, first_msg_len packet.max_output_response = 16 + peek_size packet = set_header_fields(packet) raw_response = @tree.client.send_recv(packet) response = RubySMB::SMB2::Packet::IoctlResponse.read(raw_response) unless response.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID, expected_cmd: RubySMB::SMB2::Packet::IoctlResponse::COMMAND, packet: response ) end unless response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW or response.status_code == WindowsError::NTStatus::STATUS_SUCCESS raise RubySMB::Error::UnexpectedStatusCode, response.status_code end response end |
#peek_available ⇒ Integer
Returns The number of bytes available to be read from the pipe.
76 77 78 79 80 81 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 76 def peek_available packet = peek state, avail, msg_count, first_msg_len = packet.buffer.unpack('VVVV') # Only 1 of these should be non-zero avail or first_msg_len end |
#peek_state ⇒ Integer
Returns Pipe status.
84 85 86 87 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 84 def peek_state packet = peek packet.buffer.unpack('V')[0] end |