-
Notifications
You must be signed in to change notification settings - Fork 6
/
malwaremuncher.py
240 lines (201 loc) · 8.67 KB
/
malwaremuncher.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#!/usr/bin/env python3
"""
Author: Thomas Roccia | @fr0gger_
Version: 1.0
MalwareMuncher is a proof of concept (POC) that uses Frida to instrument
malware and extract relevant information. It also uses GPT to enrich the output of the script.
EXAMPLES:
1. Show help:
python malwaremuncher.py -h
2. Run all hooking functions on a file and extract analysis using OpenAI:
python malwaremuncher.py -f sample.exe -a -o
3. Extract mutex and show registry modification for a file:
python malwaremuncher.py -f sample.exe -m -r
"""
from __future__ import print_function
import argparse
import sys
import os
import frida
import psutil
import openai
CSCRIPT64 = "C:\\Windows\SysWOW64\\"
CSCRIPT32 = "C:\\Windows\System32\\"
CSCRIPT = 'cscript.exe'
message_list = []
openai.api_key = ""
def request_openai(output):
# Create an empty list to store the OpenAI API responses
gptlist = []
prompt1 = f"I am analyzing a piece of malware and I've hooked some API calls. Can you summarize what the malware is doing here, and identify any potential Indicators of Compromise (IOCs) such as mutexes, IP addresses, domains, file paths, or registry keys? Additionally, please identify any relevant MITRE ATT&CK techniques that may be associated with this activity. The output from FRIDA I'm analyzing is: {output[:40]}"
print("\n[+] Malware Muncher is requesting GPT, please wait...")
prompt = prompt1
result = openai.Completion.create(
engine="text-davinci-003",
max_tokens=2500,
top_p=1,
frequency_penalty=1,
presence_penalty=1,
prompt=prompt,
temperature=0.7,
stop=None
)
gptlist.append(result["choices"][0]["text"])
return gptlist
def checkIfProcessRunning(processName):
'''
Check if there is any running process that contains the given name processName.
'''
#Iterate over the all the running process
for proc in psutil.process_iter():
try:
# Check if process name contains the given name string.
if processName.lower() in proc.name().lower():
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False
def on_message(message, data):
message_list.append(message)
print(message)
def load_frida(sample, js, gpt):
file_extension = os.path.splitext(sample)[1]
session = None
# Create a list to store the messages
try:
if file_extension == '.exe':
if checkIfProcessRunning(sample):
print(f'[+] Process is running: {sample}')
session = frida.kill(sample)
session = frida.spawn(sample)
session = frida.attach(sample)
else:
print(f'[+] Running process: {sample}')
session = frida.spawn(sample)
session = frida.attach(sample)
print("[!] Hit CTRL+C at the end of the analysis to trigger GPT or terminate the script")
script = session.create_script(js)
script.on('message', on_message)
script.load()
frida.resume(sample)
sys.stdin.read()
elif file_extension in ['.js', '.vbs', '.wsf']:
if checkIfProcessRunning(sample):
print(f'[+] Process is running: {sample}')
session = frida.kill(sample)
session = frida.spawn(sample)
session = frida.attach(sample)
else:
print(f'[+] Running process: {sample}')
path = CSCRIPT32 + CSCRIPT if not os.path.exists(CSCRIPT64) else CSCRIPT64 + CSCRIPT
cmd = [path, sample]
pid = frida.spawn(cmd)
session = frida.attach(pid)
script = session.create_script(js)
script.on('message', on_message)
script.load()
frida.resume(pid)
sys.stdin.read()
else:
print(f'{sample} has an unknown extension')
except KeyboardInterrupt:
# Code to run when user hits Control-C if -o option trigger openai
if gpt == True and len(message_list) != 0:
result = request_openai(message_list)
formatted_output = ""
for line in result:
formatted_output += "\n" + line.strip()
print(formatted_output)
try:
print("\n[+] Program exited!")
if file_extension in ['.js', '.vbs', '.wsf']:
frida.kill(pid)
if session is not None:
frida.kill(sample)
sys.exit(0)
except:
sys.exit(0)
# Frida scripts load
def dump(sample, gpt):
with open("jsscripts\\VirtualProtect_dump.js") as f:
js = f.read()
load_frida(sample, js, gpt)
def getproc(sample, gpt):
with open("jsscripts\\getprocaddress.js") as f:
js = f.read()
load_frida(sample, js, gpt)
def mutex(sample, gpt):
with open("jsscripts\\mutex.js") as f:
js = f.read()
load_frida(sample, js, gpt)
def registry(sample, gpt):
with open("jsscripts\\registry.js") as f:
js = f.read()
load_frida(sample, js, gpt)
def internet(sample, gpt):
with open("jsscripts\\internet.js") as f:
js = f.read()
load_frida(sample, js, gpt)
def wscript(sample, gpt):
with open("jsscripts\\wscript.js") as f:
js = f.read()
load_frida(sample, js, gpt)
def fileactivity(sample, gpt):
with open("jsscripts\\filemodif.js") as f:
js = f.read()
load_frida(sample, js, gpt)
def allscripts(sample, gpt):
# Initialize an empty string to hold the contents of the JS files
path = "jsscripts\\"
js = ''
# Loop over all files in the directory
for filename in os.listdir(path):
if filename.endswith('.js'):
# Read the contents of the file and append it to the string
with open(os.path.join(path, filename), 'r') as f:
js += f.read()
load_frida(sample, js, gpt)
def main():
# Create the parser
parser = argparse.ArgumentParser(description='MalwareMuncher version 1.0 by Thomas Roccia')
# Add the arguments
parser.add_argument('-f', '--file', type=str, help='File to process')
parser.add_argument('-d', '--dump', action='store_true', help='Dump file from the memory')
parser.add_argument('-g', '--getproc', action='store_true', help='Deobfuscate API calls')
parser.add_argument('-m', '--mutex', action='store_true', help='Extract mutex')
parser.add_argument('-r', '--registry', action='store_true', help='Shows registry modification')
parser.add_argument('-i', '--internet', action='store_true', help='Shows remote connection')
parser.add_argument('-c', '--fileactivity', action='store_true', help='Shows file creation and more')
parser.add_argument('-w', '--wscript', action='store_true', help='Hook wscript.exe for js script')
parser.add_argument('-a', '--allscripts', action='store_true', help='Run all hooking functions')
parser.add_argument('-o', '--openai', action='store_true', help='Request GPT for enrichment', default=False)
# Parse the arguments
args = parser.parse_args()
print(f"[+] {__file__} v1.0 by @fr0gger_")
# Check which options were passed and call the corresponding function
if args.dump:
# Call the dump function with the specified file and OpenAI option
dump(args.file, args.openai)
elif args.getproc:
# Call the getproc function with the specified file and OpenAI option
getproc(args.file, args.openai)
elif args.mutex:
# Call the mutex function with the specified file and OpenAI option
mutex(args.file, args.openai)
elif args.registry:
# Call the registry function with the specified file and OpenAI option
registry(args.file, args.openai)
elif args.internet:
# Call the internet function with the specified file and OpenAI option
internet(args.file, args.openai)
elif args.fileactivity:
# Call the internet function with the specified file and OpenAI option
fileactivity(args.file, args.openai)
elif args.wscript:
# Call the wscript function with the specified file and OpenAI option
wscript(args.file, args.openai)
elif args.allscripts:
# Call the allscripts function with the specified file and OpenAI option
allscripts(args.file, args.openai)
if __name__ == '__main__':
main()