Skip to content

Commit dbfee51

Browse files
committed
Add support for folder importing
1 parent 6849ada commit dbfee51

File tree

1 file changed

+47
-13
lines changed
  • lib/rex/post/meterpreter/ui/console/command_dispatcher

1 file changed

+47
-13
lines changed

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

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def commands
3131
{
3232
'python_reset' => 'Resets/restarts the Python interpreter',
3333
'python_execute' => 'Execute a python command string',
34-
'python_import' => 'Import/run a python run'
34+
'python_import' => 'Import/run a python file or module'
3535
}
3636
end
3737

@@ -42,15 +42,18 @@ def cmd_python_reset(*args)
4242

4343
@@python_import_opts = Rex::Parser::Arguments.new(
4444
'-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)']
45+
'-f' => [true, 'Path to the file (.py, .pyc), or module directory to import'],
46+
'-n' => [true, 'Name of the module (optional, for single files only)'],
47+
'-r' => [true, 'Name of the variable containing the result (optional, single files only)']
4848
)
4949

5050
def python_import_usage
51-
print_line('Usage: python_imoprt <-f file path> [-m mod name] [-r result var name]')
51+
print_line('Usage: python_imoprt <-f file path> [-n mod name] [-r result var name]')
5252
print_line
53-
print_line('Loads a python code file from disk into memory on the target.')
53+
print_line('Loads a python code file or module from disk into memory on the target.')
54+
print_line('The module loader requires a path to a folder that contains the module,')
55+
print_line('and the folder name will be used as the module name. Only .py files will')
56+
print_line('work with modules.')
5457
print_line(@@python_import_opts.usage)
5558
end
5659

@@ -64,28 +67,59 @@ def cmd_python_import(*args)
6467
end
6568

6669
result_var = nil
67-
file = nil
70+
source = nil
6871
mod_name = nil
6972

7073
@@python_import_opts.parse(args) { |opt, idx, val|
7174
case opt
7275
when '-f'
73-
file = val
74-
when '-m'
76+
source = val
77+
when '-n'
7578
mod_name = val
7679
when '-r'
7780
result_var = val
7881
end
7982
}
8083

81-
unless file
82-
print_error("File path must be specified")
84+
unless source
85+
print_error("The -f parameter must be specified")
8386
return false
8487
end
8588

86-
result = client.python.import(file, mod_name, result_var)
89+
if ::File.directory?(source)
90+
files = ::Find.find(source).select { |p| /.*\.py$/ =~ p }
91+
if files.length == 0
92+
fail_with("No .py files found in #{source}")
93+
end
94+
95+
base_name = ::File.basename(source)
96+
unless source.end_with?('/')
97+
source << '/'
98+
end
99+
100+
print_status("Importing #{source} with base module name #{base_name} ...")
101+
102+
files.each do |file|
103+
rel_path = file[source.length, file.length - source.length]
104+
parts = rel_path.split('/')
105+
106+
mod_parts = [base_name] + parts[0, parts.length - 1]
107+
108+
if parts[-1] != '__init__.py'
109+
mod_parts << ::File.basename(parts[-1], '.*')
110+
end
111+
112+
mod_name = mod_parts.join('.')
113+
print_status("Importing #{file} as #{mod_name} ...")
114+
result = client.python.import(file, mod_name, nil)
115+
handle_exec_result(result, nil)
116+
end
117+
else
118+
print_status("Importing #{source} ...")
119+
result = client.python.import(source, mod_name, result_var)
120+
handle_exec_result(result, result_var)
121+
end
87122

88-
handle_exec_result(result, result_var)
89123
end
90124

91125
@@python_execute_opts = Rex::Parser::Arguments.new(

0 commit comments

Comments
 (0)