177 lines
5.2 KiB
Python
177 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import argparse
|
|
import logging
|
|
import os
|
|
import sys
|
|
import threading
|
|
import traceback
|
|
from datetime import datetime
|
|
from time import sleep
|
|
|
|
import requests
|
|
|
|
requests.packages.urllib3.disable_warnings()
|
|
|
|
__author__ = 'moony'
|
|
__version__ = '1.0.0'
|
|
|
|
DIR = os.path.abspath(os.path.dirname(__file__))
|
|
|
|
logging.captureWarnings(True)
|
|
FORMAT = '%(asctime)s (%(levelname)s): %(message)s'
|
|
logging.basicConfig(filename=DIR + '/logs/aftermath_' +
|
|
str(datetime.today().date()) + '_' +
|
|
str(datetime.today().time().strftime('%H:%M:%S')) + '.log',
|
|
format=FORMAT,
|
|
level=logging.INFO)
|
|
|
|
|
|
class ui:
|
|
END = '\33[0m'
|
|
BOLD = '\33[1m'
|
|
RED = '\33[31m'
|
|
GREEN = '\33[32m'
|
|
BLUE = '\33[34m'
|
|
|
|
def getTime():
|
|
now = datetime.now().strftime('%H:%M:%S')
|
|
return now
|
|
|
|
def getDate():
|
|
today = datetime.today().date()
|
|
return today
|
|
|
|
def prompt():
|
|
now = datetime.today().time().strftime('%H:%M:%S')
|
|
prompt = f' {ui.BLUE}[{ui.GREEN}{now}{ui.BLUE}]{ui.END}'
|
|
return prompt
|
|
|
|
|
|
def scan_target(target, args):
|
|
try:
|
|
target = target.replace('\n', '')
|
|
|
|
headers = {
|
|
'User-Agent':
|
|
'Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0',
|
|
'Accept':
|
|
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
|
'Accept-Language': 'en-US,en;q=0.5',
|
|
'Connection': 'keep-alive'
|
|
}
|
|
|
|
r = requests.get(target,
|
|
headers=headers,
|
|
timeout=args.timeout,
|
|
allow_redirects=False,
|
|
verify=False)
|
|
|
|
if r.status_code == 200 and 'SCRIPTS MUST BE ENABLED FOR SHELL TO WORK' in r.text:
|
|
print(
|
|
f'{ui.prompt()} operational webshell FOUND: {ui.GREEN}{target}{ui.END}'
|
|
)
|
|
logging.info(f'operational webshell FOUND: {target}')
|
|
|
|
with open(args.output_file, 'a+') as f:
|
|
f.write(f'{target}\n')
|
|
f.close()
|
|
|
|
else:
|
|
print(f'{ui.prompt()} no shell found: {target}')
|
|
logging.info(f'no shell found: {target}')
|
|
|
|
except Exception as e:
|
|
logging.error(e)
|
|
pass
|
|
|
|
|
|
def main():
|
|
try:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-v',
|
|
dest='verbose',
|
|
action='count',
|
|
default=0,
|
|
help='enable verbose output. (ex: -v, -vv, -vvv)')
|
|
|
|
parser.add_argument('-f',
|
|
'--file',
|
|
dest='input_file',
|
|
required=True,
|
|
metavar='<input_file>',
|
|
help='input file of urls to scan for shell')
|
|
|
|
parser.add_argument(
|
|
'-o',
|
|
'--output',
|
|
dest='output_file',
|
|
default=
|
|
f'{DIR}/output/{datetime.today().time()}_{datetime.today().date()}.txt',
|
|
metavar='<output_file>',
|
|
help='output file to save valid urls')
|
|
|
|
parser.add_argument('-t',
|
|
'--threads',
|
|
type=int,
|
|
dest='threads',
|
|
default=5,
|
|
metavar='<threads>',
|
|
help='number of threads to use')
|
|
|
|
parser.add_argument('-T',
|
|
'--timeout',
|
|
type=int,
|
|
dest='timeout',
|
|
default=10,
|
|
metavar='<timeout>',
|
|
help='the request timeout in seconds')
|
|
|
|
args = parser.parse_args()
|
|
|
|
print(
|
|
f'{ui.prompt()} {ui.BLUE}aftermath{ui.END} v{ui.BLUE}{__version__}{ui.END} by {ui.BLUE}{__author__}{ui.END} - scanning initiated'
|
|
)
|
|
logging.info(
|
|
f'aftermath v{__version__} by {__author__} - scanning initiated')
|
|
|
|
f = open(args.input_file, 'r')
|
|
targets = f.readlines()
|
|
|
|
for target in targets:
|
|
thread = threading.Thread(target=scan_target, args=(target, args))
|
|
thread.daemon = True
|
|
thread.start()
|
|
|
|
while threading.active_count() > args.threads:
|
|
sleep(0.001)
|
|
|
|
while threading.active_count() > 1:
|
|
sleep(0.001)
|
|
|
|
valid = len(open(args.output_file).readlines())
|
|
|
|
print(
|
|
f'{ui.prompt()} scanning completed. valid webshells: {ui.GREEN}{valid:,}{ui.END}'
|
|
)
|
|
|
|
logging.info(f'scanning completed. valid webshells: {valid}')
|
|
sys.exit(-1)
|
|
|
|
except KeyboardInterrupt:
|
|
print(f'{ui.prompt()} user interrupt detected - exiting')
|
|
logging.info('user interrupt detected. exiting.')
|
|
sys.exit(-1)
|
|
|
|
except Exception as e:
|
|
print(
|
|
f'{ui.prompt()} fatal exception occurred - check the log for detauls'
|
|
)
|
|
logging.error(e, exc_info=traceback)
|
|
sys.exit(-1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|