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,228 @@
1
+ """IOC (Indicators of Compromise) extraction tools using regex patterns."""
2
+
3
+ import os
4
+ import re
5
+
6
+ # Use high-performance JSON implementation (3-5x faster)
7
+ from reversecore_mcp.core import json_utils as json
8
+ from reversecore_mcp.core.decorators import log_execution
9
+ from reversecore_mcp.core.error_handling import handle_tool_errors
10
+ from reversecore_mcp.core.metrics import track_metrics
11
+ from reversecore_mcp.core.result import ToolResult, failure, success
12
+
13
+ # Pre-compile IOC extraction patterns for better performance
14
+ _IOC_IPV4_PATTERN = re.compile(
15
+ r"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
16
+ )
17
+ _IOC_URL_PATTERN = re.compile(
18
+ r"https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)"
19
+ )
20
+ _IOC_EMAIL_PATTERN = re.compile(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b")
21
+ _IOC_BITCOIN_PATTERN = re.compile(r"\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b")
22
+ _IOC_MD5_PATTERN = re.compile(r"\b[0-9a-fA-F]{32}\b")
23
+ _IOC_SHA1_PATTERN = re.compile(r"\b[0-9a-fA-F]{40}\b")
24
+ _IOC_SHA256_PATTERN = re.compile(r"\b[0-9a-fA-F]{64}\b")
25
+ _IOC_CVE_PATTERN = re.compile(r"\bCVE-\d{4}-\d{4,7}\b")
26
+ _IOC_MAC_PATTERN = re.compile(r"\b(?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2})\b")
27
+ # Regex for common Registry hives (HKEY_...)
28
+ _IOC_REGISTRY_PATTERN = re.compile(
29
+ r"\b(?:HKEY_LOCAL_MACHINE|HKEY_CURRENT_USER|HKEY_CLASSES_ROOT|HKEY_USERS|HKEY_CURRENT_CONFIG|HKLM|HKCU|HKCR|HKU|HKCC)\\[\w\\_-]+\b",
30
+ re.IGNORECASE,
31
+ )
32
+
33
+
34
+ @log_execution(tool_name="extract_iocs")
35
+ @track_metrics("extract_iocs")
36
+ @handle_tool_errors
37
+ def extract_iocs(
38
+ text: str = "",
39
+ file_path: str = "", # Alternative: provide file path directly
40
+ extract_ips: bool = True,
41
+ extract_urls: bool = True,
42
+ extract_emails: bool = True,
43
+ extract_bitcoin: bool = True,
44
+ extract_hashes: bool = True,
45
+ extract_others: bool = True, # CVE, Registry, MAC
46
+ limit: int = 100,
47
+ ) -> ToolResult:
48
+ """
49
+ Extract Indicators of Compromise (IOCs) from text or file using regex.
50
+
51
+ This tool automatically finds and extracts potential IOCs like IP addresses,
52
+ URLs, and email addresses from any text input (e.g., strings output,
53
+ decompiled code, logs).
54
+
55
+ Args:
56
+ text: The text to analyze for IOCs (can also be a file path)
57
+ file_path: Alternative: path to a file to extract IOCs from
58
+ extract_ips: Whether to extract IPv4 addresses (default: True)
59
+ extract_urls: Whether to extract URLs (default: True)
60
+ extract_emails: Whether to extract email addresses (default: True)
61
+ extract_bitcoin: Whether to extract Bitcoin addresses (default: True)
62
+ extract_hashes: Whether to extract MD5/SHA1/SHA256 hashes (default: True)
63
+ extract_others: Whether to extract CVEs, Registry keys, MAC addresses (default: True)
64
+ limit: Maximum number of IOCs to return per category (default: 100)
65
+
66
+ Returns:
67
+ ToolResult with extracted IOCs in structured format
68
+ """
69
+ # If file_path is provided but text is empty, use file_path as text
70
+ if file_path and not text:
71
+ text = file_path
72
+
73
+ if not text:
74
+ return failure(
75
+ "MISSING_INPUT",
76
+ "Either 'text' or 'file_path' parameter is required.",
77
+ hint="Provide text content or a file path to extract IOCs from."
78
+ )
79
+
80
+ iocs = {}
81
+ total_count = 0
82
+
83
+ # Handle JSON input (e.g. ToolResult from another tool)
84
+ if text.strip().startswith("{") and text.strip().endswith("}"):
85
+ try:
86
+ data = json.loads(text)
87
+ # If it's a ToolResult structure, extract the 'data' or 'content'
88
+ if isinstance(data, dict):
89
+ if "data" in data:
90
+ # data can be string or dict
91
+ if isinstance(data["data"], str):
92
+ text = data["data"]
93
+ elif isinstance(data["data"], dict):
94
+ text = json.dumps(data["data"]) # Convert back to string for regex
95
+ elif "content" in data: # Legacy or other format
96
+ if isinstance(data["content"], list):
97
+ text = "\n".join(
98
+ [c.get("text", "") for c in data["content"] if isinstance(c, dict)]
99
+ )
100
+ else:
101
+ text = str(data["content"])
102
+ except json.JSONDecodeError:
103
+ pass # Not valid JSON, treat as raw text
104
+
105
+ # Handle file paths: if text is a valid file path, read its content
106
+ # This handles cases where users pass a file path instead of content
107
+ if len(text) < 260 and os.path.exists(text) and os.path.isfile(text):
108
+ try:
109
+ # Read file content, but limit size to avoid memory issues
110
+ # 10MB limit for text analysis
111
+ if os.path.getsize(text) > 10 * 1024 * 1024:
112
+ return failure(
113
+ "FILE_TOO_LARGE",
114
+ f"File {text} is too large for regex analysis (>10MB).",
115
+ hint="Use 'run_strings' or 'grep' to filter content first.",
116
+ )
117
+ # Use buffered reading for better I/O performance on large files
118
+ # This reduces system calls and improves throughput
119
+ with open(text, encoding="utf-8", errors="ignore", buffering=8192) as f:
120
+ text = f.read()
121
+ except Exception as e:
122
+ return failure("FILE_READ_ERROR", f"Failed to read file: {str(e)}")
123
+
124
+ # Optimization: If text is very large (>100KB), pre-filter to avoid regex performance issues
125
+ # and ReDoS with large single-line files (e.g. minified JS, packed malware)
126
+ if len(text) > 100 * 1024:
127
+ # Check if we have very long lines (indication of minified/packed content)
128
+ # Using find() is much faster than split() for checking first newline
129
+ first_newline = text.find("\n")
130
+ if first_newline == -1 or first_newline > 2000:
131
+ # WARNING: Single HUGE line detected. split('\n') would double memory
132
+ # and regex will hang. Truncate arbitrarily for safety.
133
+ text = text[: 100 * 1024]
134
+
135
+ lines = text.split("\n")
136
+ # Keep lines that look like they might contain IOCs (dots, @, http)
137
+ # This is a rough heuristic to reduce data size before heavy regex
138
+ filtered_lines = [
139
+ line
140
+ for line in lines
141
+ if len(line) < 2000 and ("." in line or "@" in line or ":" in line)
142
+ ]
143
+ # Limit to top 2000 suspicious lines to prevent memory issues
144
+ text = "\n".join(filtered_lines[:2000])
145
+
146
+ # IPv4 Regex - use pre-compiled pattern
147
+ if extract_ips:
148
+ ips = list(set(_IOC_IPV4_PATTERN.findall(text)))
149
+ if len(ips) > limit:
150
+ ips = ips[:limit]
151
+ iocs["ipv4"] = ips
152
+ total_count += len(ips)
153
+
154
+ # URL Regex - use pre-compiled pattern
155
+ if extract_urls:
156
+ raw_urls = _IOC_URL_PATTERN.findall(text)
157
+ # Use set comprehension for better performance
158
+ urls = list({url.rstrip(".,:;?!") for url in raw_urls})
159
+ if len(urls) > limit:
160
+ urls = urls[:limit]
161
+ iocs["urls"] = urls
162
+ total_count += len(urls)
163
+
164
+ # Email Regex - use pre-compiled pattern
165
+ if extract_emails:
166
+ emails = list(set(_IOC_EMAIL_PATTERN.findall(text)))
167
+ if len(emails) > limit:
168
+ emails = emails[:limit]
169
+ iocs["emails"] = emails
170
+ total_count += len(emails)
171
+
172
+ # Bitcoin Regex
173
+ if extract_bitcoin:
174
+ bitcoin_addresses = list(set(_IOC_BITCOIN_PATTERN.findall(text)))
175
+ if len(bitcoin_addresses) > limit:
176
+ bitcoin_addresses = bitcoin_addresses[:limit]
177
+ iocs["bitcoin_addresses"] = bitcoin_addresses
178
+ total_count += len(bitcoin_addresses)
179
+
180
+ # Hashes (MD5, SHA1, SHA256)
181
+ if extract_hashes:
182
+ # MD5
183
+ md5s = list(set(_IOC_MD5_PATTERN.findall(text)))
184
+ if len(md5s) > limit:
185
+ md5s = md5s[:limit]
186
+ iocs["md5"] = md5s
187
+
188
+ # SHA1
189
+ sha1s = list(set(_IOC_SHA1_PATTERN.findall(text)))
190
+ if len(sha1s) > limit:
191
+ sha1s = sha1s[:limit]
192
+ iocs["sha1"] = sha1s
193
+
194
+ # SHA256
195
+ sha256s = list(set(_IOC_SHA256_PATTERN.findall(text)))
196
+ if len(sha256s) > limit:
197
+ sha256s = sha256s[:limit]
198
+ iocs["sha256"] = sha256s
199
+
200
+ total_count += len(md5s) + len(sha1s) + len(sha256s)
201
+
202
+ # Other IOCs (CVE, Registry, MAC)
203
+ if extract_others:
204
+ # CVE
205
+ cves = list(set(_IOC_CVE_PATTERN.findall(text)))
206
+ if len(cves) > limit:
207
+ cves = cves[:limit]
208
+ iocs["cves"] = cves
209
+
210
+ # Registry Keys
211
+ registry_keys = list(set(_IOC_REGISTRY_PATTERN.findall(text)))
212
+ if len(registry_keys) > limit:
213
+ registry_keys = registry_keys[:limit]
214
+ iocs["registry_keys"] = registry_keys
215
+
216
+ # MAC Addresses
217
+ macs = list(set(_IOC_MAC_PATTERN.findall(text)))
218
+ if len(macs) > limit:
219
+ macs = macs[:limit]
220
+ iocs["mac_addresses"] = macs
221
+
222
+ total_count += len(cves) + len(registry_keys) + len(macs)
223
+
224
+ return success(
225
+ iocs,
226
+ ioc_count=total_count,
227
+ description=f"Extracted {total_count} IOCs from text (limit: {limit} per category)",
228
+ )