iflow-mcp_developermode-korea_reversecore-mcp 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/METADATA +543 -0
  2. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/RECORD +79 -0
  3. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/WHEEL +5 -0
  4. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/entry_points.txt +2 -0
  5. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/licenses/LICENSE +21 -0
  6. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/top_level.txt +1 -0
  7. reversecore_mcp/__init__.py +9 -0
  8. reversecore_mcp/core/__init__.py +78 -0
  9. reversecore_mcp/core/audit.py +101 -0
  10. reversecore_mcp/core/binary_cache.py +138 -0
  11. reversecore_mcp/core/command_spec.py +357 -0
  12. reversecore_mcp/core/config.py +432 -0
  13. reversecore_mcp/core/container.py +288 -0
  14. reversecore_mcp/core/decorators.py +152 -0
  15. reversecore_mcp/core/error_formatting.py +93 -0
  16. reversecore_mcp/core/error_handling.py +142 -0
  17. reversecore_mcp/core/evidence.py +229 -0
  18. reversecore_mcp/core/exceptions.py +296 -0
  19. reversecore_mcp/core/execution.py +240 -0
  20. reversecore_mcp/core/ghidra.py +642 -0
  21. reversecore_mcp/core/ghidra_helper.py +481 -0
  22. reversecore_mcp/core/ghidra_manager.py +234 -0
  23. reversecore_mcp/core/json_utils.py +131 -0
  24. reversecore_mcp/core/loader.py +73 -0
  25. reversecore_mcp/core/logging_config.py +206 -0
  26. reversecore_mcp/core/memory.py +721 -0
  27. reversecore_mcp/core/metrics.py +198 -0
  28. reversecore_mcp/core/mitre_mapper.py +365 -0
  29. reversecore_mcp/core/plugin.py +45 -0
  30. reversecore_mcp/core/r2_helpers.py +404 -0
  31. reversecore_mcp/core/r2_pool.py +403 -0
  32. reversecore_mcp/core/report_generator.py +268 -0
  33. reversecore_mcp/core/resilience.py +252 -0
  34. reversecore_mcp/core/resource_manager.py +169 -0
  35. reversecore_mcp/core/result.py +132 -0
  36. reversecore_mcp/core/security.py +213 -0
  37. reversecore_mcp/core/validators.py +238 -0
  38. reversecore_mcp/dashboard/__init__.py +221 -0
  39. reversecore_mcp/prompts/__init__.py +56 -0
  40. reversecore_mcp/prompts/common.py +24 -0
  41. reversecore_mcp/prompts/game.py +280 -0
  42. reversecore_mcp/prompts/malware.py +1219 -0
  43. reversecore_mcp/prompts/report.py +150 -0
  44. reversecore_mcp/prompts/security.py +136 -0
  45. reversecore_mcp/resources.py +329 -0
  46. reversecore_mcp/server.py +727 -0
  47. reversecore_mcp/tools/__init__.py +49 -0
  48. reversecore_mcp/tools/analysis/__init__.py +74 -0
  49. reversecore_mcp/tools/analysis/capa_tools.py +215 -0
  50. reversecore_mcp/tools/analysis/die_tools.py +180 -0
  51. reversecore_mcp/tools/analysis/diff_tools.py +643 -0
  52. reversecore_mcp/tools/analysis/lief_tools.py +272 -0
  53. reversecore_mcp/tools/analysis/signature_tools.py +591 -0
  54. reversecore_mcp/tools/analysis/static_analysis.py +479 -0
  55. reversecore_mcp/tools/common/__init__.py +58 -0
  56. reversecore_mcp/tools/common/file_operations.py +352 -0
  57. reversecore_mcp/tools/common/memory_tools.py +516 -0
  58. reversecore_mcp/tools/common/patch_explainer.py +230 -0
  59. reversecore_mcp/tools/common/server_tools.py +115 -0
  60. reversecore_mcp/tools/ghidra/__init__.py +19 -0
  61. reversecore_mcp/tools/ghidra/decompilation.py +975 -0
  62. reversecore_mcp/tools/ghidra/ghidra_tools.py +1052 -0
  63. reversecore_mcp/tools/malware/__init__.py +61 -0
  64. reversecore_mcp/tools/malware/adaptive_vaccine.py +579 -0
  65. reversecore_mcp/tools/malware/dormant_detector.py +756 -0
  66. reversecore_mcp/tools/malware/ioc_tools.py +228 -0
  67. reversecore_mcp/tools/malware/vulnerability_hunter.py +519 -0
  68. reversecore_mcp/tools/malware/yara_tools.py +214 -0
  69. reversecore_mcp/tools/patch_explainer.py +19 -0
  70. reversecore_mcp/tools/radare2/__init__.py +13 -0
  71. reversecore_mcp/tools/radare2/r2_analysis.py +972 -0
  72. reversecore_mcp/tools/radare2/r2_session.py +376 -0
  73. reversecore_mcp/tools/radare2/radare2_mcp_tools.py +1183 -0
  74. reversecore_mcp/tools/report/__init__.py +4 -0
  75. reversecore_mcp/tools/report/email.py +82 -0
  76. reversecore_mcp/tools/report/report_mcp_tools.py +344 -0
  77. reversecore_mcp/tools/report/report_tools.py +1076 -0
  78. reversecore_mcp/tools/report/session.py +194 -0
  79. reversecore_mcp/tools/report_tools.py +11 -0
@@ -0,0 +1,198 @@
1
+ """
2
+ Performance metrics collection for monitoring.
3
+ """
4
+
5
+ import inspect
6
+ import threading
7
+ import time
8
+ from collections import defaultdict
9
+ from functools import wraps
10
+ from typing import Any
11
+
12
+ from reversecore_mcp.core.result import ToolError
13
+
14
+
15
+ class MetricsCollector:
16
+ """
17
+ Thread-safe performance metrics collector with bounded memory.
18
+
19
+ Uses threading.Lock to ensure safe concurrent access in multi-threaded
20
+ or async environments (e.g., FastMCP server with multiple tool calls).
21
+
22
+ Memory protection: Limits entries to MAX_ENTRIES to prevent unbounded growth.
23
+ """
24
+
25
+ # Maximum number of unique entries per category to prevent memory leaks
26
+ MAX_TOOL_ENTRIES = 500
27
+ MAX_CACHE_ENTRIES = 200
28
+ MAX_CIRCUIT_BREAKER_ENTRIES = 100
29
+
30
+ def __init__(self):
31
+ self._lock = threading.Lock()
32
+ # Use regular dict instead of defaultdict for LRU control
33
+ self.tool_metrics: dict[str, dict[str, Any]] = {}
34
+ self.cache_metrics: dict[str, dict[str, int]] = {}
35
+ self.circuit_breaker_states: dict[str, str] = {}
36
+
37
+ def _get_default_tool_metrics(self) -> dict[str, Any]:
38
+ """Create default metrics dict for a new tool."""
39
+ return {
40
+ "calls": 0,
41
+ "errors": 0,
42
+ "total_time": 0.0,
43
+ "avg_time": 0.0,
44
+ "max_time": 0.0,
45
+ "min_time": float("inf"),
46
+ }
47
+
48
+ def _get_default_cache_metrics(self) -> dict[str, int]:
49
+ """Create default metrics dict for a new cache."""
50
+ return {"hits": 0, "misses": 0}
51
+
52
+ def _evict_oldest(self, d: dict, max_entries: int) -> None:
53
+ """Evict oldest entries if dict exceeds max size (FIFO eviction)."""
54
+ while len(d) > max_entries:
55
+ oldest_key = next(iter(d))
56
+ del d[oldest_key]
57
+
58
+ def record_tool_execution(self, tool_name: str, execution_time: float, success: bool = True):
59
+ """
60
+ Record metrics for a tool execution (thread-safe, bounded).
61
+
62
+ Args:
63
+ tool_name: Name of the tool
64
+ execution_time: Execution duration in seconds
65
+ success: Whether the execution succeeded
66
+ """
67
+ with self._lock:
68
+ if tool_name not in self.tool_metrics:
69
+ self._evict_oldest(self.tool_metrics, self.MAX_TOOL_ENTRIES - 1)
70
+ self.tool_metrics[tool_name] = self._get_default_tool_metrics()
71
+
72
+ metrics = self.tool_metrics[tool_name]
73
+ metrics["calls"] += 1
74
+
75
+ if not success:
76
+ metrics["errors"] += 1
77
+
78
+ metrics["total_time"] += execution_time
79
+ metrics["avg_time"] = metrics["total_time"] / metrics["calls"]
80
+ metrics["max_time"] = max(metrics["max_time"], execution_time)
81
+ metrics["min_time"] = min(metrics["min_time"], execution_time)
82
+
83
+ def record_cache_hit(self, cache_name: str):
84
+ """Record a cache hit (thread-safe, bounded)."""
85
+ with self._lock:
86
+ if cache_name not in self.cache_metrics:
87
+ self._evict_oldest(self.cache_metrics, self.MAX_CACHE_ENTRIES - 1)
88
+ self.cache_metrics[cache_name] = self._get_default_cache_metrics()
89
+ self.cache_metrics[cache_name]["hits"] += 1
90
+
91
+ def record_cache_miss(self, cache_name: str):
92
+ """Record a cache miss (thread-safe, bounded)."""
93
+ with self._lock:
94
+ if cache_name not in self.cache_metrics:
95
+ self._evict_oldest(self.cache_metrics, self.MAX_CACHE_ENTRIES - 1)
96
+ self.cache_metrics[cache_name] = self._get_default_cache_metrics()
97
+ self.cache_metrics[cache_name]["misses"] += 1
98
+
99
+ def record_circuit_breaker_state(self, tool_name: str, state: str):
100
+ """Record circuit breaker state change (thread-safe, bounded)."""
101
+ with self._lock:
102
+ if tool_name not in self.circuit_breaker_states:
103
+ self._evict_oldest(self.circuit_breaker_states, self.MAX_CIRCUIT_BREAKER_ENTRIES - 1)
104
+ self.circuit_breaker_states[tool_name] = state
105
+
106
+ def get_metrics(self) -> dict[str, Any]:
107
+ """Get all collected metrics (thread-safe)."""
108
+ with self._lock:
109
+ return {
110
+ "tools": dict(self.tool_metrics),
111
+ "cache": dict(self.cache_metrics),
112
+ "circuit_breakers": dict(self.circuit_breaker_states),
113
+ }
114
+
115
+ def reset(self):
116
+ """Reset all metrics (thread-safe)."""
117
+ with self._lock:
118
+ self.tool_metrics.clear()
119
+ self.cache_metrics.clear()
120
+ self.circuit_breaker_states.clear()
121
+
122
+
123
+ # Global metrics collector
124
+ metrics_collector = MetricsCollector()
125
+
126
+
127
+ def _determine_success(result: Any) -> bool:
128
+ """
129
+ Determine if a tool execution result indicates success.
130
+
131
+ This helper function consolidates the success determination logic
132
+ used in both sync and async wrappers, reducing code duplication.
133
+
134
+ Args:
135
+ result: The result returned by the tool function
136
+
137
+ Returns:
138
+ True if the result indicates success, False otherwise
139
+ """
140
+ if isinstance(result, ToolError):
141
+ return False
142
+ if hasattr(result, "status"):
143
+ return result.status == "success"
144
+ if isinstance(result, dict) and "status" in result:
145
+ return result["status"] == "success"
146
+ return True
147
+
148
+
149
+ def track_metrics(tool_name: str):
150
+ """
151
+ Decorator to track tool execution metrics.
152
+
153
+ Supports both synchronous and asynchronous functions.
154
+ Automatically detects function type using inspect.iscoroutinefunction().
155
+ """
156
+
157
+ def decorator(func):
158
+ # Check if function is async
159
+ if inspect.iscoroutinefunction(func):
160
+
161
+ @wraps(func)
162
+ async def async_wrapper(*args, **kwargs):
163
+ start_time = time.time()
164
+ success = True
165
+
166
+ try:
167
+ result = await func(*args, **kwargs)
168
+ success = _determine_success(result)
169
+ return result
170
+ except Exception:
171
+ success = False
172
+ raise
173
+ finally:
174
+ execution_time = time.time() - start_time
175
+ metrics_collector.record_tool_execution(tool_name, execution_time, success)
176
+
177
+ return async_wrapper
178
+ else:
179
+
180
+ @wraps(func)
181
+ def sync_wrapper(*args, **kwargs):
182
+ start_time = time.time()
183
+ success = True
184
+
185
+ try:
186
+ result = func(*args, **kwargs)
187
+ success = _determine_success(result)
188
+ return result
189
+ except Exception:
190
+ success = False
191
+ raise
192
+ finally:
193
+ execution_time = time.time() - start_time
194
+ metrics_collector.record_tool_execution(tool_name, execution_time, success)
195
+
196
+ return sync_wrapper
197
+
198
+ return decorator
@@ -0,0 +1,365 @@
1
+ """
2
+ MITRE ATT&CK Mapping Engine.
3
+
4
+ This module provides automated MITRE ATT&CK technique mapping based on
5
+ observable evidence from binary analysis, with confidence-based scoring.
6
+ """
7
+
8
+ from dataclasses import dataclass, field
9
+ from typing import Any, Optional
10
+
11
+ from reversecore_mcp.core.evidence import MITREConfidence, MITRETechnique, Evidence
12
+
13
+
14
+ @dataclass
15
+ class MappingRule:
16
+ """A rule for mapping indicators to MITRE techniques."""
17
+ technique_id: str
18
+ technique_name: str
19
+ tactic: str
20
+ indicators: list[str] # API names, strings, behaviors to look for
21
+ min_indicators: int = 1 # Minimum indicators required
22
+ confidence_boost_per_indicator: float = 0.1
23
+ base_confidence: MITREConfidence = MITREConfidence.MEDIUM
24
+
25
+
26
+ # =============================================================================
27
+ # MITRE ATT&CK Mapping Rules Database
28
+ # =============================================================================
29
+
30
+ MITRE_MAPPING_RULES: list[MappingRule] = [
31
+ # Defense Evasion
32
+ MappingRule(
33
+ technique_id="T1055",
34
+ technique_name="Process Injection",
35
+ tactic="Defense Evasion",
36
+ indicators=["VirtualAllocEx", "WriteProcessMemory", "CreateRemoteThread",
37
+ "NtCreateThreadEx", "RtlCreateUserThread"],
38
+ min_indicators=2,
39
+ base_confidence=MITREConfidence.HIGH,
40
+ ),
41
+ MappingRule(
42
+ technique_id="T1140",
43
+ technique_name="Deobfuscate/Decode Files or Information",
44
+ tactic="Defense Evasion",
45
+ indicators=["CryptDecrypt", "CryptStringToBinary", "Base64", "XOR"],
46
+ min_indicators=1,
47
+ base_confidence=MITREConfidence.MEDIUM,
48
+ ),
49
+ MappingRule(
50
+ technique_id="T1112",
51
+ technique_name="Modify Registry",
52
+ tactic="Defense Evasion",
53
+ indicators=["RegSetValueEx", "RegCreateKey", "RegOpenKey", "RegDeleteValue"],
54
+ min_indicators=1,
55
+ base_confidence=MITREConfidence.HIGH,
56
+ ),
57
+
58
+ # Persistence
59
+ MappingRule(
60
+ technique_id="T1543.003",
61
+ technique_name="Create or Modify System Process: Windows Service",
62
+ tactic="Persistence",
63
+ indicators=["CreateService", "OpenService", "StartService", "ChangeServiceConfig"],
64
+ min_indicators=2,
65
+ base_confidence=MITREConfidence.HIGH,
66
+ ),
67
+ MappingRule(
68
+ technique_id="T1547.001",
69
+ technique_name="Boot or Logon Autostart Execution: Registry Run Keys",
70
+ tactic="Persistence",
71
+ indicators=["\\Run", "\\RunOnce", "CurrentVersion\\Run", "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"],
72
+ min_indicators=1,
73
+ base_confidence=MITREConfidence.HIGH,
74
+ ),
75
+ MappingRule(
76
+ technique_id="T1053.005",
77
+ technique_name="Scheduled Task/Job: Scheduled Task",
78
+ tactic="Persistence",
79
+ indicators=["schtasks", "at.exe", "TaskScheduler", "ITaskService"],
80
+ min_indicators=1,
81
+ base_confidence=MITREConfidence.HIGH,
82
+ ),
83
+
84
+ # Discovery
85
+ MappingRule(
86
+ technique_id="T1082",
87
+ technique_name="System Information Discovery",
88
+ tactic="Discovery",
89
+ indicators=["GetComputerName", "GetSystemInfo", "GetVersionEx", "GetNativeSystemInfo"],
90
+ min_indicators=2,
91
+ base_confidence=MITREConfidence.MEDIUM,
92
+ ),
93
+ MappingRule(
94
+ technique_id="T1083",
95
+ technique_name="File and Directory Discovery",
96
+ tactic="Discovery",
97
+ indicators=["FindFirstFile", "FindNextFile", "GetFileAttributes", "PathFileExists"],
98
+ min_indicators=2,
99
+ base_confidence=MITREConfidence.LOW,
100
+ ),
101
+ MappingRule(
102
+ technique_id="T1057",
103
+ technique_name="Process Discovery",
104
+ tactic="Discovery",
105
+ indicators=["CreateToolhelp32Snapshot", "Process32First", "Process32Next", "EnumProcesses"],
106
+ min_indicators=2,
107
+ base_confidence=MITREConfidence.MEDIUM,
108
+ ),
109
+
110
+ # Impact
111
+ MappingRule(
112
+ technique_id="T1486",
113
+ technique_name="Data Encrypted for Impact",
114
+ tactic="Impact",
115
+ indicators=["CryptEncrypt", "CryptGenKey", "CryptDeriveKey", "CryptAcquireContext",
116
+ ".encrypted", ".locked", "bitcoin", "ransom", "decrypt"],
117
+ min_indicators=3,
118
+ base_confidence=MITREConfidence.HIGH,
119
+ ),
120
+ MappingRule(
121
+ technique_id="T1485",
122
+ technique_name="Data Destruction",
123
+ tactic="Impact",
124
+ indicators=["DeleteFile", "SHFileOperation", "cmd /c del", "wipe", "shred"],
125
+ min_indicators=2,
126
+ base_confidence=MITREConfidence.MEDIUM,
127
+ ),
128
+ MappingRule(
129
+ technique_id="T1489",
130
+ technique_name="Service Stop",
131
+ tactic="Impact",
132
+ indicators=["ControlService", "SERVICE_CONTROL_STOP", "net stop", "sc stop"],
133
+ min_indicators=2,
134
+ base_confidence=MITREConfidence.MEDIUM,
135
+ ),
136
+
137
+ # Command and Control
138
+ MappingRule(
139
+ technique_id="T1071.001",
140
+ technique_name="Application Layer Protocol: Web Protocols",
141
+ tactic="Command and Control",
142
+ indicators=["InternetOpen", "HttpOpenRequest", "InternetConnect", "WinHttpOpen"],
143
+ min_indicators=2,
144
+ base_confidence=MITREConfidence.HIGH,
145
+ ),
146
+ MappingRule(
147
+ technique_id="T1095",
148
+ technique_name="Non-Application Layer Protocol",
149
+ tactic="Command and Control",
150
+ indicators=["socket", "connect", "send", "recv", "WSASocket"],
151
+ min_indicators=2,
152
+ base_confidence=MITREConfidence.MEDIUM,
153
+ ),
154
+
155
+ # Execution
156
+ MappingRule(
157
+ technique_id="T1059.001",
158
+ technique_name="Command and Scripting Interpreter: PowerShell",
159
+ tactic="Execution",
160
+ indicators=["powershell", "-enc", "-ExecutionPolicy", "Invoke-Expression"],
161
+ min_indicators=1,
162
+ base_confidence=MITREConfidence.HIGH,
163
+ ),
164
+ MappingRule(
165
+ technique_id="T1059.003",
166
+ technique_name="Command and Scripting Interpreter: Windows Command Shell",
167
+ tactic="Execution",
168
+ indicators=["cmd.exe", "cmd /c", "cmd /k", "CreateProcess"],
169
+ min_indicators=2,
170
+ base_confidence=MITREConfidence.MEDIUM,
171
+ ),
172
+ MappingRule(
173
+ technique_id="T1106",
174
+ technique_name="Native API",
175
+ tactic="Execution",
176
+ indicators=["NtCreateProcess", "NtAllocateVirtualMemory", "NtProtectVirtualMemory", "LdrLoadDll"],
177
+ min_indicators=2,
178
+ base_confidence=MITREConfidence.HIGH,
179
+ ),
180
+
181
+ # Lateral Movement
182
+ MappingRule(
183
+ technique_id="T1570",
184
+ technique_name="Lateral Tool Transfer",
185
+ tactic="Lateral Movement",
186
+ indicators=["\\\\", "ADMIN$", "C$", "IPC$", "NetShareEnum", "WNetAddConnection"],
187
+ min_indicators=2,
188
+ base_confidence=MITREConfidence.MEDIUM,
189
+ ),
190
+ MappingRule(
191
+ technique_id="T1021.002",
192
+ technique_name="Remote Services: SMB/Windows Admin Shares",
193
+ tactic="Lateral Movement",
194
+ indicators=["\\\\pipe\\", "SMB", "port 445", "NetUseAdd"],
195
+ min_indicators=2,
196
+ base_confidence=MITREConfidence.MEDIUM,
197
+ ),
198
+
199
+ # Collection
200
+ MappingRule(
201
+ technique_id="T1560",
202
+ technique_name="Archive Collected Data",
203
+ tactic="Collection",
204
+ indicators=["zip", "7z", "rar", "tar", "compress", "CreateZipFile"],
205
+ min_indicators=1,
206
+ base_confidence=MITREConfidence.LOW,
207
+ ),
208
+ MappingRule(
209
+ technique_id="T1005",
210
+ technique_name="Data from Local System",
211
+ tactic="Collection",
212
+ indicators=["ReadFile", "fread", "GetFileSize", ".doc", ".xls", ".pdf"],
213
+ min_indicators=3,
214
+ base_confidence=MITREConfidence.LOW,
215
+ ),
216
+ ]
217
+
218
+
219
+ class MITREMapper:
220
+ """MITRE ATT&CK mapping engine with confidence-based scoring."""
221
+
222
+ def __init__(self, rules: list[MappingRule] = None):
223
+ self.rules = rules or MITRE_MAPPING_RULES
224
+
225
+ def map_indicators(
226
+ self,
227
+ imports: list[str],
228
+ strings: list[str],
229
+ behaviors: list[str] = None,
230
+ ) -> list[MITRETechnique]:
231
+ """
232
+ Map observed indicators to MITRE ATT&CK techniques.
233
+
234
+ Args:
235
+ imports: List of imported API functions
236
+ strings: List of strings found in binary
237
+ behaviors: List of observed behaviors (optional)
238
+
239
+ Returns:
240
+ List of MITRETechnique with confidence levels
241
+ """
242
+ all_indicators = set()
243
+
244
+ # Normalize and collect all indicators
245
+ for imp in imports:
246
+ all_indicators.add(imp.lower())
247
+ for s in strings:
248
+ all_indicators.add(s.lower())
249
+ if behaviors:
250
+ for b in behaviors:
251
+ all_indicators.add(b.lower())
252
+
253
+ results = []
254
+
255
+ for rule in self.rules:
256
+ matched_indicators = []
257
+
258
+ for indicator in rule.indicators:
259
+ indicator_lower = indicator.lower()
260
+ # Check if any observed indicator contains this pattern
261
+ for observed in all_indicators:
262
+ if indicator_lower in observed or observed in indicator_lower:
263
+ matched_indicators.append(indicator)
264
+ break
265
+
266
+ # Check if minimum indicators matched
267
+ if len(matched_indicators) >= rule.min_indicators:
268
+ # Calculate confidence based on matches
269
+ match_ratio = len(matched_indicators) / len(rule.indicators)
270
+
271
+ if match_ratio >= 0.8:
272
+ confidence = MITREConfidence.CONFIRMED
273
+ elif match_ratio >= 0.5 or rule.base_confidence == MITREConfidence.HIGH:
274
+ confidence = MITREConfidence.HIGH
275
+ elif match_ratio >= 0.3:
276
+ confidence = MITREConfidence.MEDIUM
277
+ else:
278
+ confidence = MITREConfidence.LOW
279
+
280
+ # Build evidence from matched indicators
281
+ evidence = [
282
+ Evidence(
283
+ source="indicator_match",
284
+ location="imports/strings",
285
+ description=f"Matched indicator: {ind}",
286
+ )
287
+ for ind in matched_indicators
288
+ ]
289
+
290
+ technique = MITRETechnique(
291
+ technique_id=rule.technique_id,
292
+ technique_name=rule.technique_name,
293
+ tactic=rule.tactic,
294
+ confidence=confidence,
295
+ evidence=evidence,
296
+ )
297
+ results.append(technique)
298
+
299
+ # Sort by confidence (CONFIRMED > HIGH > MEDIUM > LOW)
300
+ confidence_order = {
301
+ MITREConfidence.CONFIRMED: 0,
302
+ MITREConfidence.HIGH: 1,
303
+ MITREConfidence.MEDIUM: 2,
304
+ MITREConfidence.LOW: 3,
305
+ }
306
+ results.sort(key=lambda t: confidence_order[t.confidence])
307
+
308
+ return results
309
+
310
+ def generate_mitre_report(self, techniques: list[MITRETechnique]) -> str:
311
+ """Generate a markdown MITRE mapping report."""
312
+ lines = [
313
+ "## MITRE ATT&CK Mapping",
314
+ "",
315
+ "> **Confidence Levels**: ✅ Confirmed | 🟢 High | 🟡 Medium | 🔴 Low",
316
+ "",
317
+ "| Technique ID | Name | Tactic | Confidence | Evidence Count |",
318
+ "|-------------|------|--------|------------|----------------|",
319
+ ]
320
+
321
+ for t in techniques:
322
+ conf_symbol = {
323
+ "confirmed": "✅",
324
+ "high": "🟢",
325
+ "medium": "🟡",
326
+ "low": "🔴",
327
+ }[t.confidence.value]
328
+
329
+ lines.append(
330
+ f"| {t.technique_id} | {t.technique_name} | {t.tactic} | "
331
+ f"{conf_symbol} {t.confidence.value} | {len(t.evidence)} |"
332
+ )
333
+
334
+ return "\n".join(lines)
335
+
336
+
337
+ # Singleton instance for convenience
338
+ _mapper: Optional[MITREMapper] = None
339
+
340
+
341
+ def get_mitre_mapper() -> MITREMapper:
342
+ """Get the global MITRE mapper instance."""
343
+ global _mapper
344
+ if _mapper is None:
345
+ _mapper = MITREMapper()
346
+ return _mapper
347
+
348
+
349
+ def map_to_mitre(
350
+ imports: list[str],
351
+ strings: list[str],
352
+ behaviors: list[str] = None,
353
+ ) -> list[MITRETechnique]:
354
+ """
355
+ Quick helper to map indicators to MITRE techniques.
356
+
357
+ Args:
358
+ imports: List of imported API functions
359
+ strings: List of strings found in binary
360
+ behaviors: List of observed behaviors (optional)
361
+
362
+ Returns:
363
+ List of MITRETechnique with confidence levels
364
+ """
365
+ return get_mitre_mapper().map_indicators(imports, strings, behaviors)
@@ -0,0 +1,45 @@
1
+ """
2
+ Plugin interface definition for Reversecore MCP.
3
+
4
+ This module defines the contract that all plugins must adhere to.
5
+ """
6
+
7
+ from abc import ABC, abstractmethod
8
+ from collections.abc import Callable
9
+ from typing import Any
10
+
11
+ from pydantic import BaseModel
12
+
13
+
14
+ class Tool(BaseModel):
15
+ """Wrapper for an MCP tool function."""
16
+
17
+ name: str
18
+ description: str
19
+ func: Callable
20
+ parameters: dict | None = None # Optional schema override
21
+
22
+
23
+ class Plugin(ABC):
24
+ """Abstract base class for all plugins."""
25
+
26
+ @property
27
+ @abstractmethod
28
+ def name(self) -> str:
29
+ """Return the unique name of the plugin."""
30
+ pass
31
+
32
+ @property
33
+ def description(self) -> str:
34
+ """Return a brief description of the plugin."""
35
+ return ""
36
+
37
+ @abstractmethod
38
+ def register(self, mcp_server: Any) -> None:
39
+ """
40
+ Register tools with the MCP server.
41
+
42
+ Args:
43
+ mcp_server: The FastMCP server instance
44
+ """
45
+ pass