Skip to content

Commit 8861d61

Browse files
committed
Add stderr/stdout capture and var extraction
1 parent fb0d766 commit 8861d61

File tree

3 files changed

+71
-9
lines changed

3 files changed

+71
-9
lines changed

lib/rex/post/meterpreter/extensions/python/python.rb

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,39 @@ def initialize(client)
3333
])
3434
end
3535

36+
def reset
37+
request = Packet.create_request('python_reset')
38+
client.send_request(request)
39+
40+
return true
41+
end
42+
3643
#
3744
# Dump the LSA secrets from the target machine.
3845
#
3946
# @return [Hash<Symbol,Object>]
40-
def execute_string(code)
47+
def execute_string(code, result_var)
4148
request = Packet.create_request('python_execute_string')
42-
request.add_tlv(TLV_TYPE_PYTHON_STRING, code)
49+
request.add_tlv(TLV_TYPE_PYTHON_CODE, code)
50+
request.add_tlv(TLV_TYPE_PYTHON_RESULT_VAR, result_var) if result_var
4351

4452
response = client.send_request(request)
4553

46-
response.get_tlv_value(TLV_TYPE_PYTHON_OUTPUT)
54+
result = {
55+
result: response.get_tlv_value(TLV_TYPE_PYTHON_RESULT),
56+
stdout: "",
57+
stderr: ""
58+
}
59+
60+
response.each(TLV_TYPE_PYTHON_STDOUT) do |o|
61+
result[:stdout] << o.value
62+
end
63+
64+
response.each(TLV_TYPE_PYTHON_STDERR) do |e|
65+
result[:stderr] << e.value
66+
end
67+
68+
result
4769
end
4870

4971
end

lib/rex/post/meterpreter/extensions/python/tlv.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ module Meterpreter
55
module Extensions
66
module Python
77

8-
TLV_TYPE_PYTHON_STRING = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 1)
9-
TLV_TYPE_PYTHON_OUTPUT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 2)
8+
TLV_TYPE_PYTHON_STDOUT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 1)
9+
TLV_TYPE_PYTHON_STDERR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 2)
10+
TLV_TYPE_PYTHON_CODE = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 3)
11+
TLV_TYPE_PYTHON_RESULT_VAR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 4)
12+
TLV_TYPE_PYTHON_RESULT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 5)
1013

1114
end
1215
end

lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,63 @@ def name
2929
#
3030
def commands
3131
{
32+
'python_reset' => 'Resets/restarts the Python interpreter',
3233
'python_execute' => 'Execute a python command string'
3334
}
3435
end
3536

37+
def cmd_python_reset(*args)
38+
client.python.reset
39+
print_good('Python interpreter successfully reset')
40+
end
41+
42+
@@python_execute_opts = Rex::Parser::Arguments.new(
43+
'-h' => [false, 'Help banner'],
44+
'-r' => [true, 'Name of the variable containing the result']
45+
)
46+
3647
def python_execute_usage
37-
print_line('Usage: python_execute [python code]')
48+
print_line('Usage: python_execute <python code> [-r result var name]')
3849
print_line
39-
print_line('Runs the given python string on the target and returns the output.')
50+
print_line('Runs the given python string on the target. If a result is required,')
51+
print_line('it should be stored in a python variable, and that variable should')
52+
print_line('passed using the -r parameter.')
53+
print_line(@@python_execute_opts.usage)
4054
end
4155

4256
#
4357
# Execute a simple python command string
4458
#
4559
def cmd_python_execute(*args)
46-
if args.length == 0
60+
if args.length == 0 || args.include?('-h')
4761
python_execute_usage
4862
return false
4963
end
5064

51-
client.python.execute_string(args[0])
65+
code = args.shift
66+
result_var = nil
67+
68+
@@python_execute_opts.parse(args) { |opt, idx, val|
69+
case opt
70+
when '-r'
71+
result_var = val
72+
end
73+
}
74+
75+
result = client.python.execute_string(code, result_var)
76+
if result[:result]
77+
print_good("#{result_var} = #{result[:result]}")
78+
elsif result[:stdout].length == 0 and result[:stderr].length == 0
79+
print_good("Command executed without returning a result")
80+
end
81+
82+
if result[:stdout].length > 0
83+
print_good("Content written to stdout:\n#{result[:stdout]}")
84+
end
85+
86+
if result[:stderr].length > 0
87+
print_error("Content written to stderr:\n#{result[:stderr]}")
88+
end
5289
end
5390

5491
end

0 commit comments

Comments
 (0)