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::MAX_RECV_FRAG, Dcerpc::MAX_XMIT_FRAG
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
- #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
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 |
# 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 'srvsvc' extend RubySMB::Dcerpc::Srvsvc when 'winreg' extend RubySMB::Dcerpc::Winreg end super(tree: tree, response: response, name: name) end |
Instance Method Details
#dcerpc_request(stub_packet, options = {}) ⇒ Object
81 82 83 84 85 86 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 81 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) ioctl_send_recv(dcerpc_request, ) end |
#ioctl_send_recv(action, options = {}) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 88 def ioctl_send_recv(action, ={}) request = set_header_fields(RubySMB::SMB2::Packet::IoctlRequest.new()) request.ctl_code = 0x0011C017 request.flags.is_fsctl = 0x00000001 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, received_proto: ioctl_response.smb2_header.protocol, received_cmd: ioctl_response.smb2_header.command ) 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 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) stub_data << dcerpc_response.stub.to_s end stub_data else dcerpc_response = dcerpc_response_from_raw_response(raw_data) dcerpc_response.stub.to_s end end |
#is_connected? ⇒ Boolean
Returns True if pipe is connected, false otherwise.
69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 69 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
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 30 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, received_proto: response.smb2_header.protocol, received_cmd: response.smb2_header.command ) 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.
55 56 57 58 59 60 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 55 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.
63 64 65 66 |
# File 'lib/ruby_smb/smb2/pipe.rb', line 63 def peek_state packet = peek packet.buffer.unpack('V')[0] end |