Skip to content

Commit

Permalink
Debug powershell
Browse files Browse the repository at this point in the history
  • Loading branch information
cgranleese-r7 committed Aug 21, 2024
1 parent dd04557 commit c87b138
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 11 deletions.
10 changes: 5 additions & 5 deletions lib/msf/core/payload/windows/powershell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@ def generate_powershell_code(conntype)
script_in.gsub!('LHOST_REPLACE', lhost.to_s)

script = Rex::Powershell::Command.compress_script(script_in)
# script = script_in
command_args = {
noprofile: true,
windowstyle: 'hidden',
noninteractive: true,
executionpolicy: 'bypass'
# noprofile: true,
# windowstyle: 'hidden',
# noninteractive: true,
# executionpolicy: 'bypass'
}
cli = Rex::Powershell::Command.generate_psh_command_line(command_args)
return "#{cli} \"#{script}\""
Expand All @@ -72,4 +73,3 @@ def command_string
end
end
end

9 changes: 6 additions & 3 deletions spec/acceptance/non_meterpreter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,21 +137,24 @@ def initialize(path)

console.sendline payload.handler_command(default_module_datastore: default_module_datastore)
console.recvuntil(/Started reverse TCP handler[^\n]*\n/)
$stderr.puts 'before executed payload'
payload_process = executed_payload
$stderr.puts 'after executed payload'
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
Expand Down
40 changes: 40 additions & 0 deletions spec/support/acceptance/child_process.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ''
Expand Down Expand Up @@ -439,6 +475,7 @@ def initialize(cmd, payload_path, opts = {})

# @return [Process::Waiter] the waiter thread for the payload process
def run
$stderr.puts "about to execute payload with #{@cmd}"
pid = Process.spawn(
@env,
*@cmd,
Expand Down Expand Up @@ -479,8 +516,11 @@ def run_payload(payload, opts)
FileUtils.chmod('+x', payload.path)
end

$stderr.puts 'about to init payload payload'
payload_process = PayloadProcess.new(payload.execute_command, payload.path, opts)
$stderr.puts 'about to execute payload'
payload_process.run
$stderr.puts 'after execute payload'
@payload_processes << payload_process
payload_process
end
Expand Down
6 changes: 3 additions & 3 deletions spec/support/acceptance/non_meterpreter/powershell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ module Acceptance::NonMeterpreter
POWERSHELL = {
payloads: [
{
name: 'windows/x64/powershell_reverse_tcp',
extension: '.exe',
name: 'cmd/windows/powershell_reverse_tcp',
extension: '.ps1',
platforms: [:windows],
execute_cmd: ['${payload_path}'],
executable: true,
generate_options: {
'-f': 'exe'
'-f': 'raw'
},
datastore: {
global: {},
Expand Down

0 comments on commit c87b138

Please sign in to comment.