diff --git a/spec/acceptance/non_meterpreter_spec.rb b/spec/acceptance/non_meterpreter_spec.rb index 46385353a0724..02fc79c485053 100644 --- a/spec/acceptance/non_meterpreter_spec.rb +++ b/spec/acceptance/non_meterpreter_spec.rb @@ -141,17 +141,18 @@ def initialize(path) session_id = nil # Wait for the session to open, or break early if the payload is detected as dead - wait_for_expect do + larger_retry_count_for_powershell = 600 + wait_for_expect(larger_retry_count_for_powershell) do unless payload_process.alive? break end # TODO: Was strictly for Meterpreter sessions, now more generic # - can be reverted if we decide to move these new tests - session_opened_matcher = /\w.* session (\d+) opened[^\n]*\n/ + session_opened_matcher = /session (\d+) opened[^\n]*\n/ session_message = '' begin - session_message = console.recvuntil(session_opened_matcher, timeout: 1) + session_message = console.recvuntil_debug(session_opened_matcher, timeout: 1) rescue Acceptance::ChildProcessRecvError # noop end diff --git a/spec/support/acceptance/child_process.rb b/spec/support/acceptance/child_process.rb index cb70f50f3043e..fc07b8e3c08b0 100644 --- a/spec/support/acceptance/child_process.rb +++ b/spec/support/acceptance/child_process.rb @@ -101,6 +101,42 @@ def recvuntil(delim, timeout: @default_timeout, drop_delim: false) raise ChildProcessRecvError, "Failed #{__method__}: Did not match #{delim.inspect}, process was alive?=#{alive?.inspect}, remaining buffer: #{self.buffer.string[self.buffer.pos..].inspect}" end + + def recvuntil_debug(delim, timeout: @default_timeout, drop_delim: false) + buffer = '' + result = nil + + with_countdown(timeout) do |countdown| + while alive? && !countdown.elapsed? + data_chunk = recv(timeout: [countdown.remaining_time, 1].min) + if !data_chunk + next + end + + buffer += data_chunk + $stderr.puts "Attempting o to match buffer: #{buffer.inspect} with delim #{delim.inspect}" + has_delimiter = delim.is_a?(Regexp) ? buffer.match?(delim) : buffer.include?(delim) + next unless has_delimiter + + result, matched_delim, remaining = buffer.partition(delim) + unless drop_delim + result += matched_delim + end + unrecv(remaining) + # Reset the temporary buffer to avoid the `ensure` mechanism unrecv'ing the buffer unintentionally + buffer = '' + + return result + end + ensure + unrecv(buffer) + end + + result + rescue ChildProcessTimeoutError + raise ChildProcessRecvError, "Failed #{__method__}: Did not match #{delim.inspect}, process was alive?=#{alive?.inspect}, remaining buffer: #{self.buffer.string[self.buffer.pos..].inspect}" + end + # @return [String] Recv until additional reads would cause a block, or eof is reached, or a maximum timeout is reached def recv_available(timeout: @default_timeout) result = ''