gxenos commited on
Commit
a7c80d4
·
1 Parent(s): 650f87b

first commit

Browse files
Files changed (4) hide show
  1. README.md +114 -3
  2. app.py +12 -0
  3. interface.py +157 -0
  4. mcp_server.py +353 -0
README.md CHANGED
@@ -1,14 +1,125 @@
1
  ---
2
  title: Talosav
3
- emoji: 🌍
4
  colorFrom: blue
5
  colorTo: yellow
6
  sdk: gradio
7
  sdk_version: 5.33.0
8
  app_file: app.py
9
- pinned: false
10
  license: apache-2.0
11
  short_description: Turn any LLM into a fully fledged Antivirus!
 
 
 
12
  ---
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: Talosav
3
+ emoji: 🛡️
4
  colorFrom: blue
5
  colorTo: yellow
6
  sdk: gradio
7
  sdk_version: 5.33.0
8
  app_file: app.py
9
+ pinned: true
10
  license: apache-2.0
11
  short_description: Turn any LLM into a fully fledged Antivirus!
12
+ tags:
13
+ - mcp-server-track
14
+ - agent-demo-track
15
  ---
16
 
17
+ # Talos.AV: Antivirus Agent
18
+
19
+ ![Header Image](images/header.png)
20
+
21
+ ### This is an MCP server designed to turn any LLM into a fully fledged Anti Virus. By providing tools necesary to analyze potentially malicious files, we can transform your chatbot to a master malware analyst!
22
+
23
+ > 🔧 Track 1: MCP Server and 🤖 Track 3: Agentic Demo Showcase
24
+
25
+ **Demo can be viewed at [Youtube](https://youtu.be/tYrIzMEOW2Y).**
26
+
27
+ ## Key Antivirus Features
28
+
29
+ - Malware detection on your local files
30
+ - Cyber Threat Intelligence retrieval
31
+ - Static analysis performed on-device
32
+ - Calculating malware capabilities
33
+ - Detailed reporting
34
+ - Email notifications
35
+
36
+ ## Screenshots
37
+ **Analyze local files and detect malware through your LLM!**
38
+ <p float="center">
39
+ <img src="images/analysis.png" width="45%" style="padding:5px" />
40
+ <img src="images/detection.png" width="45%" style="padding:5px" />
41
+ </p>
42
+
43
+ **Deep inspect files and send reports to your email!**
44
+ <p float="center">
45
+ <img src="images/capa.png" width="45%" style="padding:5px" />
46
+ <img src="images/email.png" width="45%" style="padding:5px" />
47
+ </p>
48
+
49
+ ## Target Audience
50
+
51
+ - 🏠 **everyday users** who want to be protected from malware
52
+ - 🔬 **malware analysts** who want to analyse and understand a malware file
53
+ - 🏢 **organisations** who wish to provide an additional security layer
54
+
55
+ ## Tools
56
+
57
+ There are 10 tools in total that are being employed:
58
+
59
+ 1. Getting **file hash** for further analysis
60
+ 2. Getting the date of the **first submition** to **Virus Total**
61
+ 3. Getting a **Capa report** which showcases the executables capabilities
62
+ 4. Extracting **strings**
63
+ 5. Calculating **entropy**
64
+ 6. Matching **YARA rules**
65
+ 7. Get results from **3rd party antivuirus**
66
+ 8. Get detailed **antivirus reports**
67
+ 9. Get **sandbox** results
68
+ 10. **Sending** analysis results to specified **email**
69
+
70
+ > Most state of the art LLMs with reasoning skills are able to understand the results from each tool and intepret them accordngly allowing for a substantial help while performing the analysis.
71
+
72
+ ## Installation
73
+
74
+ This is designed to be used as an MCP server and is advisable to be treated as such.
75
+
76
+ 1. In a .env there should be the Virus Total key and email credentials in the form of:
77
+
78
+ ```
79
+ VT_KEY=TEST-KEY
80
+ MAIL_PASS=TEST-PASSWORD
81
+ MAIL_ADD=TEST-EMAIL-ADDRESS
82
+ ```
83
+
84
+ 2. Install the binary of Capa from the [official repository](https://github.com/mandiant/capa) and update the path towards it
85
+
86
+ 3. Install yara [official repository](https://github.com/Yara-Rules/rules)
87
+
88
+ ```
89
+ brew install yara # on macos
90
+ apt install yara # on linux
91
+ ```
92
+
93
+ and download compiled yara rules or compile them locally
94
+
95
+ 4. Install requirements:
96
+
97
+ ```
98
+ pip3 install -r requirements.txt
99
+ ```
100
+
101
+ 5. Run it:
102
+
103
+ ```
104
+ sudo python3 app.py
105
+ ```
106
+
107
+ 6. Connect it to your choice of chatbot as an MCP server. To make your experience better you can also connect a filesystem MCP server (Claude has its own pre-configured).
108
+
109
+ ## ⚠️ Security Considerations
110
+
111
+ Because of potential safety concerns we have NOT uploaded malware samples in this space and the UI is not fully usable (can't upload files).
112
+
113
+ ## Notes
114
+
115
+ > The server was designed as an on-device MCP solution as a safeguard for uploading potentially malicious software. As a result it also has the innate ability to access the filesystem.
116
+
117
+ > Capa can be time consuming, so if the analysis is urgent it's tool can be deactivated.
118
+
119
+ > If a file is not on Virus Total (most likely for benign files) then there will be no CTI reporting, thus the analysis will mainly be done from the local modules.
120
+
121
+ ## Credits
122
+
123
+ George Xenos, Cybersecurity Resarcher, CTI Patras Greece
124
+
125
+ Emmanouil Tzagakis, Software Engineer, CTI Patras Greece
app.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from interface import run_interface
2
+ from mcp_server import run_server
3
+ from multiprocessing import Process
4
+
5
+ if __name__ == "__main__":
6
+ p1 = Process(target=run_interface)
7
+ p2 = Process(target=run_server)
8
+
9
+ p1.start()
10
+ p2.start()
11
+ p1.join()
12
+ p2.join()
interface.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from mcp_server import *
3
+
4
+ FANCY_OUTPUTS = [
5
+ "🔐 Calculate Hash", "🧵 Extract Strings", "📊 Calculate Entropy",
6
+ "🧬 Match Yara Rules", "🔍 Run Capa Analysis",
7
+ "🛡️ Get Results from 3rd party antivirus", "🧪 Get Sandbox Results"
8
+ ]
9
+
10
+ OUTPUTS = [
11
+ "Calculate Hash", "Extract Strings", "Calculate Entropy",
12
+ "Match Yara Rules", "Run Capa Analysis",
13
+ "Get Results from 3rd party antivirus", "Get Sandbox Results"
14
+ ]
15
+
16
+ def handle_file_upload(file, checked_features, email_address=None):
17
+ if file is None:
18
+ return "No file uploaded."
19
+
20
+ res = {}
21
+ file_hash = get_file_hash(file.name)
22
+ for i in OUTPUTS:
23
+ if i in checked_features:
24
+ if i == "Calculate Hash":
25
+ res[i] = get_file_hash(file.name)
26
+ elif i == "Extract Strings":
27
+ res[i] = extract_strings(file.name)
28
+ elif i == "Calculate Entropy":
29
+ res[i] = file_entropy(file.name)
30
+ elif i == "Match Yara Rules":
31
+ res[i] = run_compiled_yara(file.name)
32
+ elif i == "Get Results from 3rd party antivirus":
33
+ res[i] = get_antivirus_detailed_reports(file_hash)
34
+ elif i == "Get Sandbox Results":
35
+ res[i] = get_sandbox_detailed_reports(file_hash)
36
+ elif i == "Run Capa Analysis":
37
+ res[i] = capa_malware_analysis(file.name)
38
+ else:
39
+ res[i] = f"{i} not selected."
40
+
41
+ if email_address:
42
+ try:
43
+ send_email(email_address, str(res), f"Malware Analysis Results for {file.name}")
44
+ email_status = "Email sent successfully."
45
+ except Exception as e:
46
+ print(f"Error sending email: {str(e)}")
47
+ email_status = f"Failed to send email: {str(e)}"
48
+ else:
49
+ email_status = "Email not requested."
50
+
51
+ return [res[x] for x in OUTPUTS] + [email_status]
52
+
53
+ def create_interface():
54
+
55
+ with gr.Blocks() as demo:
56
+ gr.HTML("""
57
+ <style>
58
+
59
+ .selected input.svelte-1e02hys{
60
+ background-color:#0e203f!important;
61
+ color: white !important;
62
+ fill: white !important;
63
+ accent-color: white !important;
64
+ border-color: white !important;
65
+ }
66
+
67
+ #feature_checkbox_group {
68
+ padding: 10px;
69
+ border-radius: 10px;
70
+ background-color:#0e203f;
71
+ }
72
+ #static_analysis_accordion {
73
+ background-color: #0e203f !important;
74
+ color: black;
75
+ border-radius: 8px;
76
+ padding: 8px;
77
+ }
78
+ #capa_analysis_accordion {
79
+ background-color: #0e203f !important;
80
+ color: black;
81
+ border-radius: 8px;
82
+ padding: 8px;
83
+ }
84
+ #cyber_threat_intelligence_accordion {
85
+ background-color: #0e203f !important;
86
+ color: black;
87
+ border-radius: 8px;
88
+ padding: 8px;
89
+ }
90
+ #email_status_box {
91
+ background-color: #1b3d77 !important;
92
+ color: black;
93
+ border-radius: 8px;
94
+ padding: 8px;
95
+ }
96
+
97
+ #submit_button {
98
+ background-color: #0e203f !important;
99
+ color: white;
100
+ border-radius: 8px;
101
+ padding: 8px;
102
+ }
103
+ #submit_button:hover {
104
+ background-color: #1b3d77 !important;
105
+ color: white;
106
+ }
107
+ </style>
108
+ """)
109
+ gr.Markdown("# Malware Analysis Toolkit")
110
+ gr.Image("header.png", height=150, show_label=False, show_download_button=False, container=False, elem_id="logo")
111
+ gr.Markdown("Analyze files using CAPA, YARA, entropy, string extraction, and VirusTotal integrations.")
112
+ gr.Markdown("This is created in order to be used as a MCP for malware analysis. \
113
+ As a result this UI is not fully functional and is meant to be installed locally in addition to \
114
+ an LLM that supports MCP connections. In order to run the MCP server you need to install and run \
115
+ it locally, for instructions please refer to the README")
116
+ with gr.Row():
117
+ with gr.Column(elem_id="input_column"):
118
+ input_file = gr.File(label="File to be analysed")
119
+ feature_checklist = gr.CheckboxGroup(
120
+ choices=OUTPUTS,
121
+ label="Select Analysis Features",
122
+ elem_id="feature_checkbox_group"
123
+ )
124
+ send_email_checkbox = gr.Checkbox(label="Send results by email?")
125
+ email_input = gr.Textbox(label="Email Address", visible=False)
126
+ submit_button = gr.Button("Submit", elem_id="submit_button")
127
+ with gr.Column():
128
+ with gr.Accordion("Static Analysis", open=True, elem_id="static_analysis_accordion"):
129
+ output_hash = gr.Textbox(label=FANCY_OUTPUTS[0], interactive=False)
130
+ output_strings = gr.Textbox(label=FANCY_OUTPUTS[1], interactive=False)
131
+ output_entropy = gr.Textbox(label=FANCY_OUTPUTS[2], interactive=False)
132
+ output_yara = gr.Textbox(label=FANCY_OUTPUTS[3], interactive=False)
133
+ with gr.Accordion("Capa Analysis", open=False, elem_id="capa_analysis_accordion"):
134
+ output_capa = gr.Textbox(label=FANCY_OUTPUTS[4], interactive=False)
135
+ with gr.Accordion("Cyber Threat Intelligence", open=False, elem_id="cyber_threat_intelligence_accordion"):
136
+ output_antivirus = gr.Textbox(label=FANCY_OUTPUTS[5], interactive=False)
137
+ output_sandbox = gr.Textbox(label=FANCY_OUTPUTS[6], interactive=False)
138
+ output_boxes = [output_hash, output_strings, output_entropy, output_yara, output_capa, output_antivirus, output_sandbox]
139
+ email_status = gr.Textbox(label="Email Status", interactive=False, elem_id="email_status_box")
140
+
141
+
142
+ send_email_checkbox.change(
143
+ lambda checked: gr.update(visible=checked, interactive=checked),
144
+ inputs=send_email_checkbox,
145
+ outputs=email_input
146
+ )
147
+ submit_button.click(handle_file_upload,
148
+ inputs=[input_file, feature_checklist, email_input],
149
+ outputs=output_boxes+ [email_status])
150
+
151
+ return demo
152
+
153
+ def run_interface():
154
+ interface = create_interface()
155
+ interface.launch(server_port=7861)
156
+
157
+
mcp_server.py ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import subprocess
3
+ import string
4
+ import math
5
+ from collections import Counter
6
+
7
+ import hashlib
8
+ from dotenv import load_dotenv
9
+ import vt
10
+ import os
11
+
12
+ import smtplib
13
+ from email.mime.text import MIMEText
14
+ from email.mime.multipart import MIMEMultipart
15
+
16
+ load_dotenv()
17
+ VT_KEY = os.getenv('VT_KEY')
18
+ file = None
19
+
20
+ CAPA_PATH = "../Desktop/capa"
21
+ YARA_RULES_PATH = "../Desktop/compiled_yara_rules"
22
+
23
+ SENDER_EMAIL = os.getenv("MAIL_ADD")
24
+ SENDER_PASSWORD = os.getenv("MAIL_PASS")
25
+
26
+
27
+ def get_file_hash(filepath):
28
+ """
29
+ Get the SHA256 hash of a file.
30
+
31
+ Args:
32
+ filepath: The file path to analyze
33
+
34
+ Returns:
35
+ The SHA256 hash of the file as a string
36
+ """
37
+ sha256_hash = hashlib.sha256()
38
+ md5_hash = hashlib.sha256()
39
+ with open(filepath, 'rb') as f:
40
+ for byte_block in iter(lambda: f.read(4096),b""):
41
+ sha256_hash.update(byte_block)
42
+ md5_hash.update(byte_block)
43
+
44
+ return sha256_hash.hexdigest()
45
+
46
+
47
+ def setup_threat_information_request(hash):
48
+ """
49
+ Never run!!! this function directly, it is used to set up the VirusTotal client
50
+
51
+ """
52
+ with vt.Client(VT_KEY) as client:
53
+ global file
54
+ file = client.get_object(f"/files/{hash}")
55
+
56
+ return file
57
+
58
+ def get_first_submission_date(hash):
59
+ """
60
+ Get the first submission date of a file from VirusTotal.
61
+
62
+ Args:
63
+ hash: The SHA256 hash of the file to analyze
64
+ Returns:
65
+ The first submission date of the file as a datetime object.
66
+ """
67
+ global file
68
+ if file is None:
69
+ file = setup_threat_information_request(hash)
70
+
71
+ return file.first_submission_date
72
+
73
+
74
+ def capa_malware_analysis(filepath):
75
+ """
76
+ Analyze a file for malware using Capa.
77
+ Can be time consuming an analysis may take several minutes. Before running
78
+ ask the user if they want to continue.
79
+ Only run this function if the user has a .exe file to analyze and specifically
80
+ asks for Capa.
81
+
82
+ Args:
83
+ filepath: The file path to a .exe file to analyze
84
+
85
+ Returns:
86
+ A string information about the file's malware characteristics
87
+ """
88
+ try:
89
+ alveos = subprocess.check_output(["sudo", CAPA_PATH, filepath])
90
+ except subprocess.CalledProcessError as e:
91
+ alveos = e.output
92
+
93
+ return str(alveos.decode("utf-8"))
94
+
95
+
96
+ def extract_strings(filepath, min_length=4):
97
+ """
98
+ Extract strings from file. As they are a lot, the
99
+ agent can search for specific strings like ip addresses, urls, paths, etc.
100
+ If the strings rerurn gibberish you should check the file's entropy.
101
+
102
+ Args:
103
+ filepath: The filepath to analyze
104
+
105
+ Returns:
106
+ A list of strings extracted from the file
107
+ """
108
+ with open(filepath, 'rb') as f:
109
+ result = []
110
+ current = ''
111
+ for byte in f.read():
112
+ char = chr(byte)
113
+ if char in string.printable and char not in '\t\n\r\x0b\x0c':
114
+ current += char
115
+ continue
116
+ if len(current) >= min_length:
117
+ result.append(current)
118
+ current = ''
119
+ if len(current) >= min_length:
120
+ result.append(current)
121
+ if len(result) > 10**2:
122
+ return result[:10**2]
123
+ return result
124
+
125
+
126
+ def file_entropy(filepath):
127
+ """
128
+ Calculates the Shannon entropy of the entire file content.
129
+ Low entropy indicates that the file is likely to be uncompressed or contains repetitive data,
130
+ while high entropy suggests that the file is more random and potentially encrypted or packed.
131
+
132
+ Args:
133
+ filepath: The path to the file to analyze
134
+
135
+ Returns:
136
+ The Shannon entropy of the file content as a float.
137
+ """
138
+ with open(filepath, 'rb') as f:
139
+ data = f.read()
140
+ if not data:
141
+ return 0.0
142
+
143
+ length = len(data)
144
+ counter = Counter(data)
145
+ entropy = -sum((count / length) * math.log2(count / length) for count in counter.values())
146
+ return entropy
147
+
148
+
149
+ def run_compiled_yara(filepath):
150
+ """
151
+ Run compiled YARA rules against a file to detect patterns or signatures.
152
+
153
+ Args:
154
+ filepath: The path to the file to analyze
155
+
156
+ Returns:
157
+ The output of the YARA rule matching as a string.
158
+ If no matches are found, it returns an empty string.
159
+ If YARA is not installed or the rules are not compiled, it raises an error.
160
+ Try to explain the rules that matched the file.
161
+ """
162
+
163
+ result = subprocess.run(
164
+ ['yara', '-C', YARA_RULES_PATH, filepath],
165
+ capture_output=True,
166
+ text=True
167
+ )
168
+ return result.stdout.strip()
169
+
170
+
171
+ def get_antivirus_statistics(hash):
172
+ """
173
+ Get the antivirus statistics for a file from VirusTotal.
174
+ This is the first step for malware analysis and you should always run it first.
175
+ If the user asks follow up questions or the sample is not found on virus total
176
+ you can continue calling the other functions.
177
+
178
+ Turn the output to histogram to present it to the user.
179
+
180
+ Args:
181
+ hash: The SHA256 hash of the file to analyze
182
+ Returns:
183
+ A dictionary containing the antivirus statistics, including the number of engines that detected the file as malicious.
184
+ Turn this into a histogram to present it to the user.
185
+ """
186
+ global file
187
+ if file is None:
188
+ file = setup_threat_information_request(hash)
189
+
190
+ return file.last_analysis_stats
191
+
192
+
193
+ def get_antivirus_detailed_reports(hash):
194
+ """
195
+ Get detailed antivirus reports for a file from VirusTotal.
196
+ Args:
197
+ hash: The SHA256 hash of the file to analyze
198
+ Returns:
199
+ A dictionary containing the detailed antivirus reports, including the results of each antivirus engine that analyzed the file.
200
+ """
201
+ global file
202
+ if file is None:
203
+ file = setup_threat_information_request(hash)
204
+
205
+ return file.last_analysis_results
206
+
207
+
208
+ def get_sandbox_detailed_reports(hash):
209
+ """
210
+ Get detailed sandbox reports for a file from VirusTotal.
211
+ Args:
212
+ hash: The SHA256 hash of the file to analyze
213
+ Returns:
214
+ A dictionary containing the detailed sandbox reports, including the results of each sandbox that analyzed the file.
215
+ """
216
+ global file
217
+ if file is None:
218
+ file = setup_threat_information_request(hash)
219
+
220
+ return file.sandbox_verdicts
221
+
222
+
223
+ def send_email(to_email, text, subject="File Analysis Results"):
224
+ """
225
+ Send an email with the analysis results if the user requests it.
226
+
227
+ Args:
228
+ to_email: The recipient's email address
229
+ text: The content of the email
230
+ subject: The subject of the email (default is "File Analysis Results")
231
+ """
232
+
233
+ msg = MIMEText(text)
234
+ msg['Subject'] = subject
235
+ msg['From'] = SENDER_EMAIL
236
+ msg['To'] = to_email
237
+
238
+ with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
239
+ server.login(SENDER_EMAIL, SENDER_PASSWORD)
240
+ server.sendmail(SENDER_EMAIL, to_email, msg.as_string())
241
+ server.quit()
242
+
243
+
244
+ def after_analysis_interactive_artifact():
245
+ """
246
+ This function is called after the analysis is complete.
247
+ You should create an INTERACTIVE ARTIFACT that showcases the results of the analysis.
248
+ This can include visualizations, charts, or any other relevant information.
249
+
250
+ Args:
251
+ None
252
+ Returns:
253
+ A string indicating that the analysis is complete and asking if the user wants to see the results in an interactive artifact.
254
+ """
255
+ return "Analysis complete. Do you want to see the results in an interactive artifact?"
256
+
257
+
258
+ with gr.Blocks(title="Malware Analysis Toolkit") as demo:
259
+ gr.Markdown("# Malware Analysis Toolkit")
260
+ # gr.Image("header.png", height=150, show_label=False, show_download_button=False, container=False, elem_id="logo")
261
+ gr.Markdown("Analyze files using CAPA, YARA, entropy, string extraction, and VirusTotal integrations.")
262
+ gr.Markdown("This is created in order to be used as an MCP server for malware analysis. \
263
+ As a result this UI is not fully functional and is meant to be installed locally in addition to \
264
+ an LLM that supports MCP connections.")
265
+
266
+ with gr.Tabs():
267
+ with gr.Tab("CAPA Analysis"):
268
+ gr.Markdown("### Run [CAPA](https://github.com/mandiant/capa) on a file to identify potential capabilities.")
269
+ with gr.Row():
270
+ file_input = gr.Textbox(label="File Path", placeholder="Enter the path to the file")
271
+ analysis_output = gr.Textbox(label="CAPA Results", placeholder="Results will appear here", lines=10)
272
+ file_input.change(capa_malware_analysis, inputs=file_input, outputs=analysis_output)
273
+
274
+ with gr.Tab("String Extraction"):
275
+ gr.Markdown("### Extract readable strings from a file.")
276
+ with gr.Row():
277
+ string_file_input = gr.Textbox(label="File Path", placeholder="Enter the path to the file")
278
+ string_output = gr.Textbox(label="Extracted Strings", placeholder="Strings will appear here", lines=10)
279
+ string_file_input.change(extract_strings, inputs=string_file_input, outputs=string_output)
280
+
281
+ with gr.Tab("File Entropy"):
282
+ gr.Markdown("### Calculate Shannon entropy of a file to detect obfuscation.")
283
+ with gr.Row():
284
+ entropy_file_input = gr.Textbox(label="File Path", placeholder="Enter the path to the file")
285
+ entropy_output = gr.Number(label="Entropy Value")
286
+ entropy_file_input.change(file_entropy, inputs=entropy_file_input, outputs=entropy_output)
287
+
288
+ with gr.Tab("YARA Matching"):
289
+ gr.Markdown("### Match the file against precompiled YARA rules.")
290
+ with gr.Row():
291
+ yara_file_input = gr.Textbox(label="File Path", placeholder="Enter the path to the file")
292
+ yara_output = gr.Textbox(label="YARA Matches", placeholder="Matches will appear here", lines=10)
293
+ yara_file_input.change(run_compiled_yara, inputs=yara_file_input, outputs=yara_output)
294
+
295
+ with gr.Tab("VirusTotal - Threat Info"):
296
+ gr.Markdown("### Get first submission date from VirusTotal using SHA256.")
297
+ with gr.Row():
298
+ hash_input = gr.Textbox(label="SHA256 Hash")
299
+ submission_date_output = gr.Textbox(label="First Submission Date")
300
+ hash_input.change(get_first_submission_date, inputs=hash_input, outputs=submission_date_output)
301
+
302
+ with gr.Tab("Get File Hash"):
303
+ gr.Markdown("### Calculate the SHA256 hash of a given file.")
304
+ with gr.Row():
305
+ hash_file_input = gr.Textbox(label="File Path")
306
+ hash_output = gr.Textbox(label="SHA256 Hash", placeholder="Hash will appear here")
307
+ hash_file_input.change(get_file_hash, inputs=hash_file_input, outputs=hash_output)
308
+
309
+ with gr.Tab("VirusTotal - AV Statistics"):
310
+ gr.Markdown("### Get aggregated antivirus detection statistics from VirusTotal.")
311
+ with gr.Row():
312
+ vt_hash_input = gr.Textbox(label="SHA256 Hash")
313
+ vt_stats_output = gr.Textbox(label="Antivirus Statistics", placeholder="Statistics will appear here", lines=10)
314
+ vt_hash_input.change(get_antivirus_statistics, inputs=vt_hash_input, outputs=vt_stats_output)
315
+
316
+ with gr.Tab("VirusTotal - AV Reports"):
317
+ gr.Markdown("### Get detailed antivirus reports from VirusTotal.")
318
+ with gr.Row():
319
+ vt_detailed_input = gr.Textbox(label="SHA256 Hash")
320
+ vt_detailed_output = gr.Textbox(label="Detailed Reports", placeholder="Reports will appear here", lines=10)
321
+ vt_detailed_input.change(get_antivirus_detailed_reports, inputs=vt_detailed_input, outputs=vt_detailed_output)
322
+
323
+ with gr.Tab("VirusTotal - Sandbox Reports"):
324
+ gr.Markdown("### Get sandbox execution details from VirusTotal.")
325
+ with gr.Row():
326
+ vt_sandbox_input = gr.Textbox(label="SHA256 Hash")
327
+ vt_sandbox_output = gr.Textbox(label="Sandbox Reports", placeholder="Reports will appear here", lines=10)
328
+ vt_sandbox_input.change(get_sandbox_detailed_reports, inputs=vt_sandbox_input, outputs=vt_sandbox_output)
329
+
330
+ with gr.Tab("Send Email"):
331
+ gr.Markdown("### Send analysis results via email.")
332
+ with gr.Row():
333
+ email_input = gr.Textbox(label="Recipient Email", placeholder="Enter recipient's email")
334
+ email_text_input = gr.Textbox(label="Email Content", placeholder="Enter the content of the email", lines=5)
335
+ email_subject_input = gr.Textbox(label="Email Subject", placeholder="Enter the subject of the email")
336
+ send_email_button = gr.Button("Send Email")
337
+ send_email_button.click(send_email, inputs=[email_input, email_text_input, email_subject_input], outputs=None)
338
+
339
+ with gr.Tab("Interactive Artifact"):
340
+ gr.Markdown("### Create an interactive artifact after analysis.")
341
+ with gr.Row():
342
+ artifact_output = gr.Textbox(label="Interactive Artifact", placeholder="Results will appear here", lines=5)
343
+ artifact_output.value = after_analysis_interactive_artifact()
344
+
345
+ def run_server():
346
+ demo.launch(server_port=7860 ,mcp_server=True, debug=True)
347
+
348
+ if __name__ == "__main__":
349
+ run_server()
350
+
351
+
352
+
353
+