|
1 | 1 | # -*- coding:binary -*-
|
2 | 2 | require 'spec_helper'
|
| 3 | +require 'rex/post/meterpreter/extensions/stdapi/command_ids' |
3 | 4 |
|
4 | 5 | RSpec.describe Msf::RPC::RPC_Session do
|
5 | 6 | include_context 'Msf::Simple::Framework'
|
6 | 7 | include_context 'Metasploit::Framework::Spec::Constants cleaner'
|
7 | 8 | include_context 'Msf::Framework#threads cleaner', verify_cleanup_required: false
|
8 | 9 | include_context 'wait_for_expect'
|
9 | 10 |
|
| 11 | + def command_ids_for(base_extension_command_id) |
| 12 | + (base_extension_command_id..base_extension_command_id+Rex::Post::Meterpreter::COMMAND_ID_RANGE).to_a |
| 13 | + end |
| 14 | + |
10 | 15 | def create_mock_session(klass)
|
11 | 16 | instance_double(
|
12 | 17 | klass,
|
13 | 18 | sid: target_sid,
|
14 |
| - type: klass.type |
| 19 | + type: klass.type, |
| 20 | + ) |
| 21 | + end |
| 22 | + |
| 23 | + def create_mock_meterpreter_session(klass) |
| 24 | + new_klass_with_core_alias = Class.new(klass) do |
| 25 | + # This methods is dynamically registered on a real session; so we need to define it |
| 26 | + # upfront for instance_double to work |
| 27 | + def core |
| 28 | + nil |
| 29 | + end |
| 30 | + end |
| 31 | + instance = instance_double( |
| 32 | + new_klass_with_core_alias, |
| 33 | + sid: target_sid, |
| 34 | + type: klass.type, |
| 35 | + platform: 'linux', |
| 36 | + base_platform: 'linux', |
| 37 | + arch: ARCH_PYTHON, |
| 38 | + commands: command_ids_for(Rex::Post::Meterpreter::EXTENSION_ID_CORE) + command_ids_for(Rex::Post::Meterpreter::Extensions::Stdapi::EXTENSION_ID_STDAPI), |
| 39 | + ext: instance_double(Rex::Post::Meterpreter::ObjectAliasesContainer, aliases: []), |
| 40 | + core: instance_double(Rex::Post::Meterpreter::ClientCore, use: nil) |
15 | 41 | )
|
| 42 | + instance |
16 | 43 | end
|
17 | 44 |
|
18 | 45 | let(:service) { Msf::RPC::Service.new(framework) }
|
@@ -41,7 +68,7 @@ def create_mock_session(klass)
|
41 | 68 | instance_double(Rex::IO::Stream)
|
42 | 69 | end
|
43 | 70 |
|
44 |
| - let(:meterpreter_session) { create_mock_session(::Msf::Sessions::Meterpreter_x64_Win) } |
| 71 | + let(:meterpreter_session) { create_mock_meterpreter_session(::Msf::Sessions::Meterpreter_x64_Win) } |
45 | 72 | let(:postgresql_session) { create_mock_session(::Msf::Sessions::PostgreSQL) }
|
46 | 73 | let(:shell_session) { create_mock_session(::Msf::Sessions::CommandShell) }
|
47 | 74 |
|
@@ -131,6 +158,27 @@ def create_mock_session(klass)
|
131 | 158 | end
|
132 | 159 | end
|
133 | 160 |
|
| 161 | + describe '#rpc_compatible_modules' do |
| 162 | + context 'when the session does not exist' do |
| 163 | + let(:session) { meterpreter_session } |
| 164 | + |
| 165 | + it 'returns an empty array' do |
| 166 | + expect(rpc.rpc_compatible_modules(-1)).to eq({ "modules" => [] }) |
| 167 | + end |
| 168 | + end |
| 169 | + |
| 170 | + context 'when the session exists' do |
| 171 | + let(:session) { meterpreter_session } |
| 172 | + |
| 173 | + it 'returns compatible modules' do |
| 174 | + expected = { |
| 175 | + "modules" => array_including("auxiliary/cloud/kubernetes/enum_kubernetes") |
| 176 | + } |
| 177 | + expect(rpc.rpc_compatible_modules(target_sid)).to match(expected) |
| 178 | + end |
| 179 | + end |
| 180 | + end |
| 181 | + |
134 | 182 | describe '#rpc_meterpreter_read' do
|
135 | 183 | subject(:response) { rpc.rpc_meterpreter_read(target_sid) }
|
136 | 184 |
|
|
0 commit comments