MCPcopy Create free account
hub / github.com/GH05TCREW/MetasploitMCP / _execute_module_rpc

Function _execute_module_rpc

MetasploitMCP.py:454–601  ·  view source on GitHub ↗

Helper to execute an exploit, auxiliary, or post module as a background job via RPC. Includes polling logic for exploit sessions.

(
    module_type: str,
    module_name: str, # Can be full path or base name
    module_options: Dict[str, Any],
    payload_spec: Optional[Union[str, Dict[str, Any]]] = None # Payload name or {name: ..., options: ...}
)

Source from the content-addressed store, hash-verified

452 raise ValueError(f"Failed to set option '{k}' to '{original_value}': {e}") from e
453
454async def _execute_module_rpc(
455 module_type: str,
456 module_name: str, # Can be full path or base name
457 module_options: Dict[str, Any],
458 payload_spec: Optional[Union[str, Dict[str, Any]]] = None # Payload name or {name: ..., options: ...}
459) -> Dict[str, Any]:
460 """
461 Helper to execute an exploit, auxiliary, or post module as a background job via RPC.
462 Includes polling logic for exploit sessions.
463 """
464 client = get_msf_client()
465 module_obj = await _get_module_object(module_type, module_name) # Handles path variants
466 full_module_path = getattr(module_obj, 'fullname', f"{module_type}/{module_name}") # Get canonical name
467
468 await _set_module_options(module_obj, module_options)
469
470 payload_obj_to_pass = None
471 payload_name_for_log = None
472 payload_options_for_log = None
473
474 # Prepare payload if needed (primarily for exploits, also used by start_listener)
475 if module_type == 'exploit' and payload_spec:
476 if isinstance(payload_spec, str):
477 payload_name_for_log = payload_spec
478 # Passing name string directly is supported by exploit.execute
479 payload_obj_to_pass = payload_name_for_log
480 logger.info(f"Executing {full_module_path} with payload '{payload_name_for_log}' (passed as string).")
481 elif isinstance(payload_spec, dict) and 'name' in payload_spec:
482 payload_name = payload_spec['name']
483 payload_options = payload_spec.get('options', {})
484 payload_name_for_log = payload_name
485 payload_options_for_log = payload_options
486 try:
487 payload_obj = await _get_module_object('payload', payload_name)
488 await _set_module_options(payload_obj, payload_options)
489 payload_obj_to_pass = payload_obj # Pass the configured payload object
490 logger.info(f"Executing {full_module_path} with configured payload object for '{payload_name}'.")
491 except (ValueError, MsfRpcError) as e:
492 logger.error(f"Failed to prepare payload object for '{payload_name}': {e}")
493 return {"status": "error", "message": f"Failed to prepare payload '{payload_name}': {e}"}
494 else:
495 logger.warning(f"Invalid payload_spec format: {payload_spec}. Expected string or dict with 'name'.")
496 return {"status": "error", "message": "Invalid payload specification format."}
497
498 logger.info(f"Executing module {full_module_path} as background job via RPC...")
499 try:
500 if module_type == 'exploit':
501 exec_result = await asyncio.to_thread(lambda: module_obj.execute(payload=payload_obj_to_pass))
502 else: # auxiliary, post
503 exec_result = await asyncio.to_thread(lambda: module_obj.execute())
504
505 logger.info(f"RPC execute() result for {full_module_path}: {exec_result}")
506
507 # --- Process Execution Result ---
508 if not isinstance(exec_result, dict):
509 logger.error(f"Unexpected result type from {module_type} execution: {type(exec_result)} - {exec_result}")
510 return {"status": "error", "message": f"Unexpected result from module execution: {exec_result}", "module": full_module_path}
511

Callers 4

run_exploitFunction · 0.85
run_post_moduleFunction · 0.85
run_auxiliary_moduleFunction · 0.85
start_listenerFunction · 0.85

Calls 4

get_msf_clientFunction · 0.85
_get_module_objectFunction · 0.85
_set_module_optionsFunction · 0.85
executeMethod · 0.80

Tested by

no test coverage detected