Class: RubySMB::SMB1::Pipe
- Includes:
- Dcerpc
- Defined in:
- lib/ruby_smb/smb1/pipe.rb
Overview
Represents a pipe on the Remote server that we can perform various I/O operations on.
Constant Summary collapse
- STATUS_DISCONNECTED =
0x0001
- STATUS_LISTENING =
0x0002
- STATUS_OK =
0x0003
- STATUS_CLOSED =
0x0004
Constants included from Dcerpc
Dcerpc::MAX_RECV_FRAG, Dcerpc::MAX_XMIT_FRAG
Instance Attribute Summary
Attributes inherited from File
#attributes, #fid, #last_access, #last_change, #last_write, #name, #size, #size_on_disk, #tree
Instance Method Summary collapse
-
#dcerpc_request(stub_packet, options = {}) ⇒ String
Send a DCERPC request with the provided stub packet.
-
#initialize(tree:, response:, name:) ⇒ Pipe
constructor
A new instance of Pipe.
-
#is_connected? ⇒ Boolean
True if pipe is connected, false otherwise.
-
#peek(peek_size: 0) ⇒ RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse
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.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/ruby_smb/smb1/pipe.rb', line 16 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 end super(tree: tree, response: response, name: name) end |
Instance Method Details
#dcerpc_request(stub_packet, options = {}) ⇒ String
Send a DCERPC request with the provided stub packet.
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 130 131 132 133 134 |
# File 'lib/ruby_smb/smb1/pipe.rb', line 91 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) trans_nmpipe_request = RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest.new() @tree.set_header_fields(trans_nmpipe_request) trans_nmpipe_request.set_fid(@fid) trans_nmpipe_request.data_block.trans_data.write_data = dcerpc_request.to_binary_s trans_nmpipe_raw_response = @tree.client.send_recv(trans_nmpipe_request) trans_nmpipe_response = RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse.read(trans_nmpipe_raw_response) unless trans_nmpipe_response.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID, expected_cmd: RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse::COMMAND, packet: trans_nmpipe_response ) end unless [WindowsError::NTStatus::STATUS_SUCCESS, WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW].include?(trans_nmpipe_response.status_code) raise RubySMB::Error::UnexpectedStatusCode, trans_nmpipe_response.status_code end raw_data = trans_nmpipe_response.data_block.trans_data.read_data.to_binary_s if trans_nmpipe_response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW raw_data << read(bytes: @tree.client.max_buffer_size - trans_nmpipe_response.parameter_block.data_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.
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ruby_smb/smb1/pipe.rb', line 73 def is_connected? begin state = peek_state rescue RubySMB::Error::UnexpectedStatusCode => e if e. == 'STATUS_INVALID_HANDLE' return false end raise e end state == STATUS_OK end |
#peek(peek_size: 0) ⇒ RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse
Performs a peek operation on the named pipe
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/ruby_smb/smb1/pipe.rb', line 37 def peek(peek_size: 0) packet = RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest.new packet.fid = @fid packet.parameter_block.max_data_count = peek_size packet = @tree.set_header_fields(packet) raw_response = @tree.client.send_recv(packet) response = RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse.read(raw_response) unless response.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID, expected_cmd: RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest::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.
60 61 62 63 64 |
# File 'lib/ruby_smb/smb1/pipe.rb', line 60 def peek_available packet = peek # Only 1 of these should be non-zero packet.data_block.trans_parameters.read_data_available or packet.data_block.trans_parameters. end |
#peek_state ⇒ Integer
Returns Pipe status.
67 68 69 70 |
# File 'lib/ruby_smb/smb1/pipe.rb', line 67 def peek_state packet = peek packet.data_block.trans_parameters.pipe_state end |