diff --git a/README.md b/README.md index 4b3b54c..3306fba 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ more sophisticated emulation and easier maintenance. ## Installation -* Clone Git repository: `git clone https://github.com/zeroq/amun.git` +* Clone Git repository: `git clone -b Amun-lyz https://github.com/aichimzh/amun.git` * Edit Amun main configuration file: `vim conf/amun.conf` * for example set the ip address for Amun to listen on (0.0.0.0 to listen on all) * enable or disbale vulnerability modules as needed diff --git a/core/amun_request_handler.py b/core/amun_request_handler.py index d7bf60a..edba41e 100644 --- a/core/amun_request_handler.py +++ b/core/amun_request_handler.py @@ -14,7 +14,8 @@ from psyco.classes import * except ImportError: pass - + +import logging import asynchat import StringIO import traceback @@ -56,6 +57,16 @@ def __init__(self, divLogger): self.proxyResult = None self.sendRequest = "" self.log_obj = amun_logging.amun_logging("amun_request_handler", divLogger['requestHandler']) + self.logger = logging.getLogger('connection_logger') + self.logger.setLevel(logging.DEBUG) + log_file = 'ConnectionDuration.log' + file_handler = logging.FileHandler(log_file) + file_handler.setLevel(logging.DEBUG) + if not self.logger.handlers: + self.logger.addHandler(file_handler) + self.divLogger = divLogger + self.start_time = time.time() + self.end_time = None def __del__(self): pass @@ -144,6 +155,14 @@ def setup_remote_connection(self, remote_ip=None): raise def handle_close(self): + self.end_time = time.time() + duration = self.end_time - self.start_time + msg = "Remote IP: {}, Remote port: {}, Own port: {}, ConnectionDuration: {} seconds".format(self.remote_ip, + self.remote_port, + self.own_port, + duration) + print(msg) + self.logger.debug("({}),".format(msg)) try: self.connected = False try: diff --git a/core/shellcode_mgr_core.py b/core/shellcode_mgr_core.py index f3bcf22..86f09ca 100644 --- a/core/shellcode_mgr_core.py +++ b/core/shellcode_mgr_core.py @@ -12,6 +12,8 @@ try: import psyco ; psyco.full() from psyco.classes import * + import os + import requests except ImportError: pass @@ -26,12 +28,13 @@ from sys import exit, stdout from StringIO import StringIO import traceback - +import requests from iprange import IPRange from amun_logging import amun_logging class shell_mgr: - def __init__(self, decodersDict, shLogger, config_dict): + def __init__(self, decodersDict, shLogger, config_dict, hexdump_dir="hexdumps"): + """initialize shellcode decoder class Keyword arguments: @@ -53,6 +56,8 @@ def __init__(self, decodersDict, shLogger, config_dict): self.log_obj = amun_logging("shellcode_manager", shLogger) ### load shellcodes self.decodersDict = decodersDict + self.hexdump_dir = hexdump_dir + def getNewResultSet(self, vulnName, attIP, ownIP): """Return a new empty result set to be used for detected shellcode @@ -1784,40 +1789,82 @@ def handle_lichtenfels(self, key, dec_shellcode): return True return False - def write_hexdump(self, shellcode=None, extension=None, ownPort="None"): - """Write unknown/undetected shellcode as a hexdump to disc for later analysis - - Keyword arguments: - shellcode -- specific shellcode that was not detected (default None, i.e. use global self.shellcode) - extension -- use specifial extension on stored hexdump (default None) - ownPort -- attach the network port of the vulnerability that was exploited to filename (default "None") - """ - if not shellcode: + + + def write_hexdump(self, shellcode=None, extension=None, ownPort="None"): + if not shellcode: file_data = "".join(self.shellcode) - else: + else: file_data = "".join(shellcode) ### ignore zero size hexdumps - if len(file_data)==0 or (extension=="MS03049" and (file_data.count('PIPE')>=2 or file_data.count('\x50\x00\x49\x00\x50\x00\x45')>=2)) or len(file_data)<100: + if len(file_data)==0 or (extension=="MS03049" and (file_data.count('PIPE')>=2 or file_data.count('\x50\x00\x49\x00\x50\x00\x45')>=2)) or len(file_data)<100: return ### generate md5 fingerprint of shellcode - hash = md5(file_data) - digest = hash.hexdigest() - if extension!=None: + hash = md5(file_data) + digest = hash.hexdigest() + if extension!=None: filename = "hexdumps/%s-%s-%s.hex" % (extension.strip(), digest, ownPort) - else: + else: filename = "hexdumps/%s-%s.hex" % (digest, ownPort) - ### write hexdump to disc - if not ospath.exists(filename): + + + + if not ospath.exists(filename): + response = self.query_virustotal(digest) + if response: + print(digest + "Recorded by VirusTotal") + + try: - fp = open(filename, 'a+') - fp.write(file_data) - fp.close() - self.log_obj.log("(%s) no match, writing hexdump (%s :%s) - %s" % (self.attIP, digest, len(file_data), self.resultSet['vulnname']), 9, "warn", True, True) - except IOError, e: - self.log_obj.log("(%s) failed writing hexdump (%s) (%s :%s) - %s" % (self.attIP, e, digest, len(file_data), self.resultSet['vulnname']), 9, "crit", True, True) + fp = open(filename, 'a+') + fp.write(file_data) + fp.close() + filename = filename.replace(".hex", "_recorded(VT).hex") + self.log_obj.log("(%s) no match, writing hexdump (%s :%s) - %s Recorded by VT" % (self.attIP, digest, len(file_data), self.resultSet['vulnname']), 9, "warn", True, True) + except IOError, e: + self.log_obj.log("(%s) failed writing hexdump (%s) (%s :%s) - %s" % (self.attIP, e, digest, len(file_data), self.resultSet['vulnname']), 9, "crit", True, True) + + return False + + else: + try: + fp = open(filename, 'a+') + fp.write(file_data) + fp.close() + self.log_obj.log("(%s) no match, writing hexdump (%s :%s) - %s" % (self.attIP, digest, len(file_data), self.resultSet['vulnname']), 9, "warn", True, True) + except IOError, e: + + self.log_obj.log("(%s) failed writing hexdump (%s) (%s :%s) - %s" % (self.attIP, e, digest, len(file_data), self.resultSet['vulnname']), 9, "crit", True, True) + + return False + + return True + + + def query_virustotal(hash, api_key="your_VT_APIkey"): + + url = 'https://www.virustotal.com/api/v3/file/%s' % hash + headers = {'x-apikey': api_key} + response = requests.get(url, headers=headers) + print(response.status_code) + + if response.status_code == 200: + + result = True + + + + return result + else: + + result = False + + + return result + def match_direct_file(self, dec_shellcode=None): """Check if given shellcode is an executable file