Skip to content

Commit 6849ada

Browse files
committed
Adjusted to include import
1 parent 8861d61 commit 6849ada

File tree

3 files changed

+105
-6
lines changed

3 files changed

+105
-6
lines changed

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

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ module Python
1717

1818
class Python < Extension
1919

20+
PY_CODE_TYPE_STRING = 0
21+
PY_CODE_TYPE_PY = 1
22+
PY_CODE_TYPE_PYC = 2
23+
24+
PY_CODE_FILE_TYPES = [ '.py', '.pyc' ]
25+
26+
PY_CODE_FILE_TYPE_MAP = {
27+
'.py' => PY_CODE_TYPE_PY,
28+
'.pyc' => PY_CODE_TYPE_PYC
29+
}
30+
2031
#
2132
# Typical extension initialization routine.
2233
#
@@ -40,15 +51,44 @@ def reset
4051
return true
4152
end
4253

54+
def import(file, mod_name, result_var)
55+
unless ::File.file?(file)
56+
raise ArgumentError, "File not found: #{file}"
57+
end
58+
59+
ext = ::File.extname(file).downcase
60+
unless PY_CODE_FILE_TYPES.include?(ext)
61+
raise ArgumentError, "File not a valid type: #{file}"
62+
end
63+
64+
code = ::File.read(file)
65+
66+
request = Packet.create_request('python_execute')
67+
request.add_tlv(TLV_TYPE_PYTHON_CODE, code)
68+
request.add_tlv(TLV_TYPE_PYTHON_CODE_LEN, code.length)
69+
request.add_tlv(TLV_TYPE_PYTHON_CODE_TYPE, PY_CODE_FILE_TYPE_MAP[ext])
70+
request.add_tlv(TLV_TYPE_PYTHON_NAME, mod_name) if mod_name
71+
request.add_tlv(TLV_TYPE_PYTHON_RESULT_VAR, result_var) if result_var
72+
73+
run_exec_request(request)
74+
end
75+
4376
#
4477
# Dump the LSA secrets from the target machine.
4578
#
4679
# @return [Hash<Symbol,Object>]
4780
def execute_string(code, result_var)
48-
request = Packet.create_request('python_execute_string')
81+
request = Packet.create_request('python_execute')
4982
request.add_tlv(TLV_TYPE_PYTHON_CODE, code)
83+
request.add_tlv(TLV_TYPE_PYTHON_CODE_TYPE, PY_CODE_TYPE_STRING)
5084
request.add_tlv(TLV_TYPE_PYTHON_RESULT_VAR, result_var) if result_var
5185

86+
run_exec_request(request)
87+
end
88+
89+
private
90+
91+
def run_exec_request(request)
5292
response = client.send_request(request)
5393

5494
result = {

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ module Python
77

88
TLV_TYPE_PYTHON_STDOUT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 1)
99
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)
10+
TLV_TYPE_PYTHON_CODE = TLV_META_TYPE_RAW | (TLV_EXTENSIONS + 3)
11+
TLV_TYPE_PYTHON_CODE_LEN = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 4)
12+
TLV_TYPE_PYTHON_CODE_TYPE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 5)
13+
TLV_TYPE_PYTHON_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 6)
14+
TLV_TYPE_PYTHON_RESULT_VAR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 7)
15+
TLV_TYPE_PYTHON_RESULT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 8)
1316

1417
end
1518
end

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

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ def name
3030
def commands
3131
{
3232
'python_reset' => 'Resets/restarts the Python interpreter',
33-
'python_execute' => 'Execute a python command string'
33+
'python_execute' => 'Execute a python command string',
34+
'python_import' => 'Import/run a python run'
3435
}
3536
end
3637

@@ -39,9 +40,57 @@ def cmd_python_reset(*args)
3940
print_good('Python interpreter successfully reset')
4041
end
4142

43+
@@python_import_opts = Rex::Parser::Arguments.new(
44+
'-h' => [false, 'Help banner'],
45+
'-f' => [true, 'Path to the file (.py, .pyc) to import'],
46+
'-m' => [true, 'Name of the module (optional)'],
47+
'-r' => [true, 'Name of the variable containing the result (optional)']
48+
)
49+
50+
def python_import_usage
51+
print_line('Usage: python_imoprt <-f file path> [-m mod name] [-r result var name]')
52+
print_line
53+
print_line('Loads a python code file from disk into memory on the target.')
54+
print_line(@@python_import_opts.usage)
55+
end
56+
57+
#
58+
# Import/run a python file
59+
#
60+
def cmd_python_import(*args)
61+
if args.length == 0 || args.include?('-h')
62+
python_import_usage
63+
return false
64+
end
65+
66+
result_var = nil
67+
file = nil
68+
mod_name = nil
69+
70+
@@python_import_opts.parse(args) { |opt, idx, val|
71+
case opt
72+
when '-f'
73+
file = val
74+
when '-m'
75+
mod_name = val
76+
when '-r'
77+
result_var = val
78+
end
79+
}
80+
81+
unless file
82+
print_error("File path must be specified")
83+
return false
84+
end
85+
86+
result = client.python.import(file, mod_name, result_var)
87+
88+
handle_exec_result(result, result_var)
89+
end
90+
4291
@@python_execute_opts = Rex::Parser::Arguments.new(
4392
'-h' => [false, 'Help banner'],
44-
'-r' => [true, 'Name of the variable containing the result']
93+
'-r' => [true, 'Name of the variable containing the result (optional)']
4594
)
4695

4796
def python_execute_usage
@@ -73,6 +122,13 @@ def cmd_python_execute(*args)
73122
}
74123

75124
result = client.python.execute_string(code, result_var)
125+
126+
handle_exec_result(result, result_var)
127+
end
128+
129+
private
130+
131+
def handle_exec_result(result, result_var)
76132
if result[:result]
77133
print_good("#{result_var} = #{result[:result]}")
78134
elsif result[:stdout].length == 0 and result[:stderr].length == 0

0 commit comments

Comments
 (0)