├── Malware ├── Glastopf │ ├── README.md │ ├── glastopf-report.sh │ ├── glastopfdb-query.py │ └── gng-query.py ├── Google │ ├── README.md │ ├── google-safe-lookup.py │ ├── gsb-reporter.cfg.dist │ └── gsb-reporter.py ├── Kippo │ ├── README.md │ ├── kippo-log-grabber.py │ ├── kippo-report.sh │ └── read-passdb.py ├── PE │ ├── README.md │ ├── dll_exports.py │ ├── packdetect.py │ └── pe_compiledate.py ├── README.md ├── Thug │ ├── README.md │ ├── runthug.sh │ ├── spider.py │ ├── thug-parse.py │ ├── thugdor.sh │ └── url-dumper.py ├── Virustotal │ ├── README.md │ ├── vtbulkcheck.py │ ├── vtdomaincheck.py │ ├── vtevilsubmit.py │ └── vthashcheck.py ├── Web │ ├── README.md │ ├── php_decode.py │ └── webshellfind.sh ├── b64decode.py ├── expandshorturl.py ├── geolookup.py ├── lazyconverter.py ├── uberhexparser.py └── xorer.py ├── Networking ├── dns-cachesnoop.py ├── dns-test.py ├── dnsquery.py ├── dnsresolve-v2.py ├── domaincheck.py ├── ftp-check.py ├── header-grab.py ├── imaptester.py ├── ipchicken.py ├── libwww-python.py ├── listener.py ├── mass-geoiplookup.py ├── sendmail.py ├── smtp-test.ps1 ├── statdnsquery.py ├── subdomainquery.py ├── twitter.py ├── urlparser.py ├── whoisxmlapiquery.py └── zonetransfer.py ├── Office365 ├── O365-Audit.ps1 └── README.md ├── Powershell ├── Group-Audit.ps1 ├── PasswordGen.ps1 └── SendSlack.ps1 ├── README.md ├── Security ├── Wordpress │ ├── README.md │ ├── plugins.json.dist │ ├── wpplugin-check.py │ └── wpvdb-api.py ├── bitly-expand.py ├── courier-attacks.sh ├── cve-search.py ├── docker-brute.py ├── fbid-finder.py ├── hasher.py ├── haveibeenpwned.py ├── httprecon.py ├── nmap-parse.py ├── redirtrace.py ├── rot13.py ├── shodan-search.py ├── ss-binlookup.py └── ssh-attacks.sh └── Shodan ├── README.md └── shodan-tls-info.py /Malware/Glastopf/README.md: -------------------------------------------------------------------------------- 1 | If you're not using [Glastopf](https://github.com/glastopf/glastopf) as your web honeypot, you 2 | might be doing something wrong. 3 | 4 | These are just some scripts I pulled together to look at the log file 5 | 6 | 7 | glastopf-report.sh 8 | ------------------ 9 | 10 | Just a quick and dirty bash script to pull useful info from your Glastopf log file. 11 | 12 | Usage: 13 | 14 | ``` 15 | ./glastopf-report.sh /path/to/your/glastopf.log 16 | ``` 17 | 18 | Useful stuff in the report: 19 | 20 | * Total sessions 21 | * Offenders 22 | * Requested URLs 23 | 24 | glastopfdb-query.py 25 | ------------------- 26 | 27 | A simple script to query the Glastopf database and return useful information 28 | 29 | Usage: 30 | 31 | ``` 32 | ./glastopfdb-query.py -d /path/to/your/glastopf.db [-a] [-s attackerip] [-i attackid] [-l] [-S] 33 | ``` 34 | 35 | Useful stuff in the report: 36 | 37 | * Dump all entries in the database 38 | * Show a specific attack ID 39 | * Search for a specific attacker 40 | * List all attackers in the database (with number of attacks and attack IDs) 41 | * Summary report for the database (Not quite done) 42 | 43 | -------------------------------------------------------------------------------- /Malware/Glastopf/glastopf-report.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Simple Glastopf stats reporting script 3 | 4 | LOGFILE="${1}" 5 | 6 | if [ "${LOGFILE}" = "" ] 7 | then 8 | echo "We need a log file" 9 | exit 0 10 | fi 11 | 12 | if [ -f $LOGFILE ] 13 | then 14 | true 15 | else 16 | echo "Log file doesn't exist" 17 | exit 0 18 | fi 19 | 20 | START=`head -1 ${LOGFILE} | awk -F" " '{print $1" " $2}'` 21 | STOP=`tail -1 ${LOGFILE} | awk -F" " '{print $1" " $2}'` 22 | 23 | echo "Glastopf Summary Report" 24 | echo "Reporting Period: ${START} - ${STOP}" 25 | echo "----------------------------------------" 26 | echo 27 | echo -n "Total sessions: " 28 | grep "requested " ${LOGFILE} | wc -l 29 | echo 30 | 31 | echo "Offenders" 32 | echo "----------" 33 | cat ${LOGFILE} | cut -d ' ' -f 4 | sort | uniq > /tmp/attackers 34 | for x in `cat /tmp/attackers` 35 | do 36 | echo -n "${x}: " 37 | grep ${x} ${LOGFILE} | grep requested | wc -l 38 | done 39 | rm /tmp/attackers 40 | echo 41 | 42 | echo "Requested URLs" 43 | echo "---------------" 44 | cat ${LOGFILE} | cut -d ' ' -f 4,6,7 45 | echo 46 | 47 | -------------------------------------------------------------------------------- /Malware/Glastopf/glastopfdb-query.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple Glastopf database query tool 3 | 4 | from pysqlite2 import dbapi2 as sqlite 5 | import sys 6 | import argparse 7 | 8 | 9 | def returnall(adatabase): 10 | """Dump all entries in our database""" 11 | print "Connecting to database" 12 | connection = sqlite.connect(adatabase) 13 | cursor = connection.cursor() 14 | cursor.execute('SELECT * FROM events') 15 | for row in cursor: 16 | print "\nDate: %s" % row[1] 17 | print "Attack ID: %s" % row[0] 18 | print "Attacker: %s" % row[2] 19 | print "Request: %s" % row[3] 20 | print "\n*** Raw Request ***\n%s" % row[4] 21 | print "-" * 80 22 | connection.close() 23 | 24 | 25 | def search(adatabase, aid): 26 | """Search for a specific attack ID""" 27 | print "Connecting to database" 28 | print "Returning info for attack ID: " + aid 29 | connection = sqlite.connect(adatabase) 30 | cursor = connection.cursor() 31 | cursor.execute("SELECT * FROM events WHERE id = '"+aid+"'") 32 | for row in cursor: 33 | print "\nDate: %s" % row[1] 34 | print "Attacker: %s" % row[2] 35 | print "Request: %s" % row[3] 36 | print "\n*** Raw Request ***\n%s" % row[4] 37 | print "-" * 80 38 | connection.close() 39 | 40 | 41 | def ipquery(adatabase, asource): 42 | """Search for a specific IP address in our attack list""" 43 | print "Connecting to database" 44 | print "Returning info for attacker: " + asource 45 | connection = sqlite.connect(adatabase) 46 | cursor = connection.cursor() 47 | cursor.execute("SELECT * FROM events WHERE source LIKE '%"+asource+"%'") 48 | for row in cursor: 49 | print "\nDate: %s" % row[1] 50 | print "Attacker: %s" % row[2] 51 | print "Request: %s" % row[3] 52 | print "\n*** Raw Request *** \n%s" % row[4] 53 | print "-" * 80 54 | connection.close() 55 | 56 | 57 | def listattackers(adatabase): 58 | """Print list of all attackers and their attack IDs""" 59 | print "Connecting to database" 60 | print "Attacker with total requests and related attack IDs\n" 61 | connection = sqlite.connect(adatabase) 62 | attackers = [] 63 | cursor = connection.cursor() 64 | cursor.execute("SELECT * FROM events") 65 | for row in cursor: 66 | w = row[2] 67 | x = w.split(':')[0] 68 | attackers.append(x) 69 | newattackers = sorted(set(attackers)) 70 | for attacker in newattackers: 71 | ids = connection.cursor() 72 | ids.execute("SELECT * from events where source like '"+attacker+"%';") 73 | attackid = [] 74 | for id in ids: 75 | x =id[0] 76 | attackid.append(x) 77 | cursor.execute("SELECT source, COUNT(*) from events where source like '"+attacker+"%';") 78 | for row in cursor: 79 | count = row[1] 80 | print attacker + ": " + str(count), 81 | print attackid 82 | connection.close() 83 | 84 | 85 | def summaryreport(adatabase): 86 | """Print a simple summary report""" 87 | print "Summary report \n" 88 | connection = sqlite.connect(adatabase) 89 | attackers = [] 90 | cursor = connection.cursor() 91 | cursor.execute("SELECT source, COUNT(*) from events;") 92 | for row in cursor: 93 | print "Total events: %s" % row[1] 94 | connection.close() 95 | 96 | 97 | def attacksummary(adatabase): 98 | """Print a simple summary of all attacks""" 99 | print "Attack Summary report \n" 100 | connection = sqlite.connect(adatabase) 101 | attackers = [] 102 | cursor = connection.cursor() 103 | cursor.execute("SELECT * from events;") 104 | for row in cursor: 105 | print "[%s] %s" % (row[0], row[3]) 106 | connection.close() 107 | 108 | 109 | def __main__(): 110 | """Get this party started""" 111 | parser = argparse.ArgumentParser(description='Basic Glastopf Database Query Tool') 112 | parser.add_argument('--database', '-d', dest='database', default='glastopf.db', help='Database to query') 113 | parser.add_argument('--all', '-a', dest='all', action="store_true", help='Return all queries') 114 | parser.add_argument('--id', '-i', dest='id', help='Search for a specific attack ID') 115 | parser.add_argument('--source', '-s', dest='source', help='Search for a specific attacker') 116 | parser.add_argument('--list', '-l', dest='list', action="store_true", help='List all the attackers in database') 117 | parser.add_argument('--summary', '-S', dest='summary', action="store_true", help='Quick summary report') 118 | parser.add_argument('--attacks', '-A', dest='attacks', action="store_true", help='Just list the attacks in database') 119 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 120 | args = parser.parse_args() 121 | adatabase = args.database 122 | aid = args.id 123 | asource = args.source 124 | alist = args.list 125 | asummary = args.summary 126 | aattacks = args.attacks 127 | aall = args.all 128 | 129 | if not args.database: 130 | sys.exit(parser.print_help()) 131 | 132 | if args.all: 133 | returnall(adatabase) 134 | if args.id: 135 | search(adatabase, aid) 136 | if args.source: 137 | ipquery(adatabase, asource) 138 | if args.list: 139 | listattackers(adatabase) 140 | if args.summary: 141 | summaryreport(adatabase) 142 | if args.attacks: 143 | attacksummary(adatabase) 144 | 145 | 146 | if __name__ == '__main__': 147 | __main__() 148 | -------------------------------------------------------------------------------- /Malware/Glastopf/gng-query.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple GlastopfNG database query tool 3 | # v2 will allow you to specify the database to query 4 | 5 | from pysqlite2 import dbapi2 as sqlite 6 | import sys 7 | 8 | args = sys.argv[1] 9 | 10 | connection = sqlite.connect('sqLitedb.db') 11 | cursor = connection.cursor() 12 | 13 | # Show all database entries 14 | def returnall(): 15 | cursor.execute('SELECT * FROM log') 16 | for row in cursor: 17 | print row 18 | 19 | # Search for a specific string 20 | def search(): 21 | query = sys.argv[2] 22 | cursor.execute("SELECT * FROM log WHERE request LIKE '%"+query+"%'") 23 | for row in cursor: 24 | print row 25 | 26 | # Search for a specific IP address 27 | def ipquery(): 28 | ip = sys.argv[2] 29 | cursor.execute("SELECT * FROM log WHERE attacker = '"+ip+"'") 30 | for row in cursor: 31 | print row 32 | 33 | if args == "-a": 34 | returnall() 35 | elif args == "-s": 36 | search() 37 | elif args == "-i": 38 | ipquery() 39 | 40 | -------------------------------------------------------------------------------- /Malware/Google/README.md: -------------------------------------------------------------------------------- 1 | Google Scripts 2 | ============== 3 | 4 | Mostly stuff for the Google Safe Browsing API 5 | 6 | * google-safe-lookup - script to check GSB for malicious listings from a file or command line 7 | * gsb-reporter - Similar to the google-safe-lookup script but more automated 8 | 9 | -------------------------------------------------------------------------------- /Malware/Google/google-safe-lookup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Bulk Google Safe Browsing API lookup 3 | 4 | import argparse 5 | import sys 6 | import os 7 | import urllib 8 | try: 9 | import requests 10 | except: 11 | print "You need the requests library" 12 | 13 | 14 | def load_apikey(): 15 | """Load our API key from file""" 16 | fullpath = os.getenv("HOME") 17 | try: 18 | with open(fullpath + '/.googlesafe.key', 'r') as keyfile: 19 | for line in keyfile: 20 | googlekey = line.rstrip() 21 | keyfile.close() 22 | return googlekey 23 | except: 24 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.googlesafe.key") 25 | 26 | 27 | def standalone_lookup(url): 28 | """One shot lookup from command line""" 29 | print "Checking: ", 30 | gsb = google_lookup(url) 31 | if gsb == 0: 32 | print url + " [ok]" 33 | elif gsb == 200: 34 | print url + " [MALICIOUS]" 35 | else: 36 | print "This means we probably errored out" 37 | 38 | 39 | def google_lookup(url): 40 | """Check Google for our urls""" 41 | googlekey = load_apikey() 42 | encoded_url = urllib.quote_plus(url) 43 | google_url = "https://sb-ssl.google.com/safebrowsing/api/lookup?client=firefox&apikey=" + \ 44 | googlekey + "&appver=1.0&pver=3.0&url=" + \ 45 | encoded_url 46 | try: 47 | # Simple GET request to Google 48 | resp = requests.get(google_url) 49 | except: 50 | sys.exit("Problem with HTTP request to Google") 51 | scode = resp.status_code 52 | if scode == 204: 53 | return 0 54 | elif scode == 200: 55 | return 200 56 | elif scode == 400: 57 | sys.exit("Error: 400 Bad Request") 58 | elif scode == 401: 59 | sys.exit("Error: 401 API Key problem") 60 | elif scode == 403: 61 | sys.exit("Error: 403 API Key problem") 62 | elif scode == 503: 63 | sys.exit("Error: 503 Service unavailable") 64 | 65 | 66 | def load_files(afile, quiet): 67 | """Load urls from file""" 68 | print "\nChecking Google Safe Browsing...\n" 69 | with open(afile, 'r') as fh: 70 | lines = 0 71 | checked = 0 72 | good = 0 73 | for line in fh: 74 | lines += 1 75 | url = line.rstrip() 76 | gsb = google_lookup(url) 77 | checked += 1 78 | if gsb == 0: 79 | if quiet == "1": 80 | good += 1 81 | pass 82 | else: 83 | good += 1 84 | print url + " [ok]" 85 | elif gsb == 200: 86 | print url + " [MALICIOUS]" 87 | 88 | if checked == good: 89 | print "\n[ No Malicious Links Reported ]" 90 | print "\n[ Analysis Complete: " + str(lines) + " URLs checked. ]" 91 | 92 | 93 | def __main__(): 94 | """Get this party started""" 95 | parser = argparse.ArgumentParser(description='basic menu system') 96 | parser.add_argument('--file', '-f', dest='file', help='File to pull URLs from') 97 | parser.add_argument('--stdin', '-s', dest='stdin', help='Check the host supplied as an arguement') 98 | parser.add_argument('--quiet', '-q', dest='quiet', action='store_true', help='Less verbose') 99 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 100 | args = parser.parse_args() 101 | afile = args.file 102 | astdin = args.stdin 103 | aquiet = args.quiet 104 | 105 | if not (args.file or args.stdin): 106 | sys.exit(parser.print_help()) 107 | elif args.stdin: 108 | standalone_lookup(astdin) 109 | else: 110 | if args.quiet: 111 | quiet = "1" 112 | load_files(afile, quiet) 113 | else: 114 | quiet = "0" 115 | load_files(afile, quiet) 116 | 117 | 118 | if __name__ == '__main__': 119 | __main__() -------------------------------------------------------------------------------- /Malware/Google/gsb-reporter.cfg.dist: -------------------------------------------------------------------------------- 1 | { 2 | "subject": "Malicious Domain Report", 3 | "from": "malware-report@zonbi.org", 4 | "to": "csirt@zonbi.org", 5 | "tmpfile" : "/tmp/malreport.txt", 6 | "smtpserver" : "yourmailserver.com" 7 | } 8 | -------------------------------------------------------------------------------- /Malware/Google/gsb-reporter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Bulk Google Safe Browsing API lookup and reporter 3 | 4 | import argparse 5 | import sys 6 | import os 7 | import json 8 | import smtplib 9 | from email.mime.text import MIMEText 10 | import urllib 11 | try: 12 | import requests 13 | except: 14 | print "You need the requests library" 15 | 16 | 17 | def load_apikey(): 18 | """Load our API key from file""" 19 | fullpath = os.getenv("HOME") 20 | try: 21 | with open(fullpath + '/.googlesafe.key', 'r') as keyfile: 22 | for line in keyfile: 23 | googlekey = line.rstrip() 24 | keyfile.close() 25 | return googlekey 26 | except: 27 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.googlesafe.key") 28 | 29 | 30 | def load_config(aconfig): 31 | """Load our config settings from file""" 32 | try: 33 | jconfig=open(aconfig) 34 | except: 35 | sys.exit(" ** [Error: Problem loading config file]") 36 | data = json.load(jconfig) 37 | jconfig.close() 38 | 39 | global mailfrom 40 | mailfrom = data["from"] 41 | global mailto 42 | mailto = data["to"] 43 | global subject 44 | subject = data["subject"] 45 | global tmpfile 46 | tmpfile = data["tmpfile"] 47 | global smtpserver 48 | smtpserver = data["smtpserver"] 49 | 50 | def send_report(): 51 | """Email our report""" 52 | with open(tmpfile, 'r') as fp: 53 | # Create a text/plain message 54 | msg = MIMEText(fp.read()) 55 | fp.close() 56 | msg['Subject'] = subject 57 | msg['From'] = mailfrom 58 | msg['To'] = mailto 59 | 60 | 61 | print "\nSending report to: " + mailto, 62 | s = smtplib.SMTP(smtpserver) 63 | s.sendmail(mailfrom, [mailto], msg.as_string()) 64 | s.quit() 65 | os.remove(tmpfile) 66 | print "...done." 67 | 68 | 69 | def google_lookup(url): 70 | """Check Google for our urls""" 71 | googlekey = load_apikey() 72 | encoded_url = urllib.quote_plus(url) 73 | google_url = "https://sb-ssl.google.com/safebrowsing/api/lookup?client=firefox&apikey=" + \ 74 | googlekey + "&appver=1.0&pver=3.0&url=" + \ 75 | encoded_url 76 | try: 77 | # Simple GET request to Google 78 | resp = requests.get(google_url) 79 | except: 80 | sys.exit("Problem with HTTP request to Google") 81 | scode = resp.status_code 82 | if scode == 204: 83 | return 0 84 | elif scode == 200: 85 | return 200 86 | elif scode == 400: 87 | sys.exit("Error: 400 Bad Request") 88 | elif scode == 401: 89 | sys.exit("Error: 401 API Key problem") 90 | elif scode == 403: 91 | sys.exit("Error: 403 API Key problem") 92 | elif scode == 503: 93 | sys.exit("Error: 503 Service unavailable") 94 | 95 | 96 | def load_files(afile, quiet): 97 | """Load urls from file""" 98 | print "Checking Google Safe Browsing..." 99 | print "Loading configuration", 100 | load_config(aconfig) 101 | print "...ok\n" 102 | malreport = [] 103 | with open(afile, 'r') as fh: 104 | lines = 0 105 | checked = 0 106 | good = 0 107 | for line in fh: 108 | lines += 1 109 | url = line.rstrip() 110 | gsb = google_lookup(url) 111 | checked += 1 112 | if gsb == 0: 113 | if quiet == "1": 114 | good += 1 115 | pass 116 | else: 117 | good += 1 118 | print url + " [ok]" 119 | elif gsb == 200: 120 | maltext = url + " [MALICIOUS]" 121 | malreport.append(maltext) 122 | print url + " [MALICIOUS]" 123 | 124 | if checked == good: 125 | print "\n[ No Malicious Links Reported ]" 126 | else: 127 | # I know this can be done better. 128 | with open(tmpfile, 'w') as reportfile: 129 | for line in malreport: 130 | reportfile.write(line) 131 | reportfile.write("\n") 132 | reportfile.close() 133 | send_report() 134 | print "\n[ URLs checked: " + str(lines) + " ]" 135 | print "[ Analysis Complete ]" 136 | 137 | 138 | def __main__(): 139 | """Get this party started""" 140 | parser = argparse.ArgumentParser(description='Google Safe Browsing Check and Notify System') 141 | parser.add_argument('--file', '-f', dest='file', help='File to pull URLs from') 142 | parser.add_argument('--config', '-c', dest='config', help='Configuration file to pull settings from') 143 | parser.add_argument('--quiet', '-q', dest='quiet', action='store_true', help='Less verbose') 144 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 145 | args = parser.parse_args() 146 | afile = args.file 147 | global aconfig 148 | aconfig = args.config 149 | aquiet = args.quiet 150 | 151 | if not (args.file or args.config): 152 | sys.exit(parser.print_help()) 153 | else: 154 | if args.quiet: 155 | quiet = "1" 156 | load_files(afile, quiet) 157 | else: 158 | quiet = "0" 159 | load_files(afile, quiet) 160 | 161 | 162 | if __name__ == '__main__': 163 | __main__() 164 | -------------------------------------------------------------------------------- /Malware/Kippo/README.md: -------------------------------------------------------------------------------- 1 | Kippo is a great little SSH honey pot. It's available [here](https://code.google.com/p/kippo/) 2 | 3 | Yes, it's probably pretty easy to fingerprint, but it's still interesting. 4 | 5 | These are just some scripts I pulled together to look at the Kippo log files. 6 | 7 | 8 | kippo-report.sh 9 | --------------- 10 | 11 | Just a quick and dirty bash script to pull useful info from your kippo log file. 12 | 13 | Usage: 14 | 15 | ./kippo-report.sh /path/to/your/kippo.log 16 | 17 | Useful stuff in the report: 18 | 19 | * Total sessions 20 | * Successful logins 21 | * Total unique failed usernames 22 | * Failed usernames with frequency 23 | * Failed Username and Password Combinations 24 | * Successful Usernames with frequency 25 | * Passwords used in successful logins 26 | * Actual interactive sessions 27 | * Downloaded files 28 | 29 | 30 | 31 | kippo-log-grabber.py 32 | -------------------- 33 | 34 | This script will log into your Honeypot via ssh, run my other script and return the 35 | results to the screen and/or dump to a text file. 36 | 37 | Usage: 38 | 39 | python ./kippo-log-grabber.py -H myfirstkippo.com -p 23 -u USERNAME -k /path/to/your/ssh/key -f /path/to/your/kippo.log 40 | 41 | TODO: 42 | 43 | * Add password logins 44 | * Maybe do a list of hosts to login and check ? 45 | -------------------------------------------------------------------------------- /Malware/Kippo/kippo-log-grabber.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Log into our honeypot and run report script 3 | 4 | import paramiko 5 | import argparse 6 | import sys 7 | 8 | 9 | def sshconnect(ahost, aport, afile, auser, akey): 10 | """Connect to our ssh server""" 11 | command = "/usr/local/bin/kippo-report.sh " + afile 12 | print "Connecting to : " + ahost 13 | try: 14 | client = paramiko.SSHClient() 15 | client.load_system_host_keys() 16 | client.set_missing_host_key_policy(paramiko.WarningPolicy) 17 | client.connect(ahost, port=aport, username=auser, key_filename=akey) 18 | stdin, stdout, stderr = client.exec_command(command) 19 | report = stdout.read() 20 | client.close() 21 | except: 22 | print "Something has gone wrong" 23 | sys.exit() 24 | 25 | print_report = raw_input("Print report to screen ? Y/N ") 26 | if print_report == "y": 27 | print report 28 | else: 29 | pass 30 | 31 | save_report = raw_input("Save report to file ? Y/N ") 32 | if save_report == "y": 33 | fout = open('kippo-report.txt', 'w') 34 | print "Saving report" 35 | for line in report: 36 | fout.write(line) 37 | fout.close() 38 | 39 | print "Report saved: kippo-report.txt" 40 | print "We're done here." 41 | 42 | 43 | def __main__(): 44 | """Get this party started""" 45 | parser = argparse.ArgumentParser(description='Kippo log file grabber') 46 | parser.add_argument('--file', '-f', dest='file', help='Log file to parse') 47 | parser.add_argument('--host', '-H', dest='host', help='Host to connect to') 48 | parser.add_argument('--port', '-p', dest='port', default='22', help='Port to connect on') 49 | parser.add_argument('--user', '-u', dest='user', help='Username to use') 50 | parser.add_argument('--password', '-P', dest='password', help='Password to use') 51 | parser.add_argument('--key', '-k', dest='key', help='SSH key file to use') 52 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 53 | args = parser.parse_args() 54 | afile = args.file 55 | ahost = args.host 56 | aport = int(args.port) 57 | auser = args.user 58 | apassword = args.password 59 | akey = args.key 60 | 61 | if args.key: 62 | sshconnect(ahost, aport, afile, auser, akey) 63 | elif args.password: 64 | print "You should be using keys" 65 | sys.exit() 66 | else: 67 | sys.exit(parser.print_help()) 68 | 69 | 70 | if __name__ == '__main__': 71 | __main__() 72 | 73 | -------------------------------------------------------------------------------- /Malware/Kippo/kippo-report.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Simple Kippo stats reporting script 3 | 4 | LOGFILE="${1}" 5 | 6 | if [ "${LOGFILE}" = "" ] 7 | then 8 | echo "We need a log file" 9 | exit 0 10 | fi 11 | 12 | if [ -f $LOGFILE ] 13 | then 14 | true 15 | else 16 | echo "Log file doesn't exist" 17 | exit 0 18 | fi 19 | 20 | START=`head -1 ${LOGFILE} | awk -F" " '{print $1" " $2}'` 21 | STOP=`tail -1 ${LOGFILE} | awk -F" " '{print $1" " $2}'` 22 | 23 | echo "Kippo Summary" 24 | echo "Reporting Period: ${START} - ${STOP}" 25 | echo 26 | echo -n "Total sessions: " 27 | grep "session: " ${LOGFILE} | wc -l 28 | 29 | echo -n "Successful logins: " 30 | grep "login attempt" ${LOGFILE} | grep succeeded | wc -l 31 | echo 32 | 33 | echo -n "Total unique failed usernames: " 34 | grep "login attempt" ${LOGFILE} | grep failed | cut -d\/ -f 1 | cut -d \[ -f3 | sort | uniq | wc -l 35 | echo 36 | 37 | echo "Failed usernames with frequency" 38 | echo "-------------------------------" 39 | grep "login attempt" ${LOGFILE} | grep failed | cut -d\/ -f 1 | cut -d \[ -f3 | sort | uniq > /tmp/fusers 40 | for x in `cat /tmp/fusers` 41 | do 42 | echo -n "${x}: " 43 | grep "login attempt" ${LOGFILE} | grep failed | grep ${x} | cut -d\/ -f 1 | cut -d \[ -f3 | sort | uniq | wc -l 44 | done 45 | rm /tmp/fusers 46 | echo 47 | 48 | echo "Failed Username and Password Combinations" 49 | echo "------------------------------------------" 50 | grep "login attempt" ${LOGFILE} | grep failed | cut -d\[ -f 3| cut -f1 -d \] | sort | uniq 51 | echo 52 | 53 | echo "Successful Usernames with frequency: " 54 | echo "-------------------------------------" 55 | grep "authenticated with" ${LOGFILE} | awk -F" " '{print $7}' | sort | uniq > /tmp/users 56 | grep "authenticated with" ${LOGFILE} > /tmp/sessions 57 | for x in `cat /tmp/users` 58 | do echo -n "${x}: " 59 | grep ${x} /tmp/sessions | wc -l 60 | done 61 | rm /tmp/users /tmp/sessions 62 | echo 63 | 64 | echo "Passwords used in successful logins" 65 | echo "-----------------------------------" 66 | grep succeeded ${LOGFILE} | cut -f 2 -d\/ | cut -f 1 -d \] | sort | uniq > /tmp/passes 67 | for x in `cat /tmp/passes` 68 | do 69 | echo -n "${x}: " 70 | grep ${x} ${LOGFILE} | grep succeeded | wc -l 71 | done 72 | echo "-----------------------------------" 73 | rm /tmp/passes 74 | echo 75 | 76 | echo "Actual interactive sessions" 77 | echo "--------------------------" 78 | grep "Opening TTY log" ${LOGFILE} | awk -F"," '{ print $3 }' | awk -F"]" '{ print $1 }' > /tmp/sessip 79 | for x in `cat /tmp/sessip` 80 | do 81 | echo "${x}: " 82 | echo "-------------------" 83 | DATE=`grep ${x} ${LOGFILE} | grep "Opening TTY log" | awk -F" " '{ print $1 " " $2}' | sort | uniq ` 84 | BLAH=`grep "Opening TTY log" ${LOGFILE} | grep $x | awk -F" " '{ print "/home/matt/kippo/kippo-0.8/"$14 }' ` 85 | SIZE=`ls -lh ${BLAH} | awk -F" " '{ print $5 }'` 86 | LOG=`grep ${x} ${LOGFILE} | grep "Opening TTY log" | awk -F":" '{ print $4 }' ` 87 | echo "${DATE}: ${LOG} (${SIZE})" 88 | echo "" 89 | done 90 | rm /tmp/sessip 91 | echo 92 | 93 | echo "Downloaded files" 94 | echo "--------------------------" 95 | echo 96 | grep "Starting factory /tmp/dlip 97 | for x in `cat /tmp/dlip` 98 | do 99 | echo -n "${x}: " 100 | grep ${x} ${LOGFILE} | grep "Starting factory " '{ print $1 }' 101 | done 102 | rm /tmp/dlip 103 | echo 104 | -------------------------------------------------------------------------------- /Malware/Kippo/read-passdb.py: -------------------------------------------------------------------------------- 1 | #!/bin/python 2 | # This is a fork of Andrews work here: https://bitbucket.org/infosanity/kippoanalysis 3 | 4 | import dbhash 5 | import MySQLdb 6 | import os 7 | 8 | #os.system('clear') 9 | 10 | # Database basics from: 11 | ## Berkley DB - http://stackoverflow.com/questions/37644/examining-berkeley-db-files-from-the-cli 12 | ## MySQL - http://stackoverflow.com/questions/372885/how-do-i-connect-to-a-mysql-database-in-python 13 | 14 | # open Kippo' password file 15 | passdb = dbhash.open('/opt/kippo-svn/data/pass.db') 16 | 17 | # open connection to Kippo' MySQL database 18 | kippodb = MySQLdb.connect(host='localhost', user='kippo', passwd='kipposecret', db='kippo') 19 | 20 | cur = kippodb.cursor() 21 | 22 | # Iterate through password file 23 | for passwd, junk in passdb.iteritems(): 24 | passwd = str(passwd) 25 | 26 | # need to insert $passwd into SQL string 27 | creationSessionSQL = "SELECT session FROM input WHERE input = '%s'" % passwd 28 | 29 | cur.execute(creationSessionSQL) 30 | 31 | for row in cur.fetchall(): 32 | sessionID = row[0] 33 | 34 | print "Account with password %s created under session %s" %(passwd, sessionID) 35 | 36 | # get account creation details 37 | sessionDetailsSQL = "SELECT * FROM sessions WHERE id = %s" % sessionID 38 | cur.execute(sessionDetailsSQL) 39 | 40 | for row in cur.fetchall(): 41 | sessionDate = row[1] 42 | sessionIP = row[4] 43 | 44 | print "[*] created: \t %s" % sessionDate 45 | print "[*] from: \t %s" % sessionIP 46 | 47 | # Session input during account creation 48 | sessionInputSQL = "SELECT input FROM input WHERE session = %s" % sessionID 49 | cur.execute(sessionInputSQL) 50 | for row in cur.fetchall(): 51 | print "[input]\t %s" %row[0] 52 | 53 | 54 | # Later sessions with same passwd 55 | loginSQL = "Select session FROM auth WHERE success = 1 AND password = '%s'" % passwd 56 | cur.execute(loginSQL) 57 | for row in cur.fetchall(): 58 | sessionID = row[0] 59 | sessionDetailsSQL = "SELECT * FROM sessions WHERE id = %s" % sessionID 60 | 61 | # Session summaries 62 | sessionCur = kippodb.cursor() 63 | sessionCur.execute(sessionDetailsSQL) 64 | for sessionRow in sessionCur.fetchall(): 65 | print "[*]Date: %s from %s" % (sessionRow[1], sessionRow[4]) 66 | 67 | -------------------------------------------------------------------------------- /Malware/PE/README.md: -------------------------------------------------------------------------------- 1 | PE Files 2 | ======== 3 | 4 | Code for working with PE files and their related shenanigans. 5 | 6 | This is mostly stuff to automate various tasks. 7 | 8 | -------------------------------------------------------------------------------- /Malware/PE/dll_exports.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # grab the exports of a given dll 4 | 5 | import pefile 6 | import sys 7 | import argparse 8 | 9 | 10 | def parse_dll(arg_dll): 11 | 12 | dll = pefile.PE(arg_dll) 13 | for exp in dll.DIRECTORY_ENTRY_EXPORT.symbols: 14 | print hex(dll.OPTIONAL_HEADER.ImageBase + exp.address), exp.name, exp.ordinal 15 | 16 | 17 | def __main__(): 18 | 19 | parser = argparse.ArgumentParser(description='check the exports of a given dll', usage='%(prog)s -f file') 20 | parser.add_argument('--file', '-f', dest='dll', help='dll to examine') 21 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 22 | args = parser.parse_args() 23 | arg_dll = args.dll 24 | 25 | if not args.dll: 26 | sys.exit(parser.print_help()) 27 | 28 | try: 29 | parse_dll(arg_dll) 30 | except: 31 | print "Error!! Something is wrong...call the police" 32 | 33 | if __name__ == '__main__': 34 | __main__() 35 | -------------------------------------------------------------------------------- /Malware/PE/packdetect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # simple packer detection script using the PEiD database 4 | 5 | import peutils 6 | import pefile 7 | import argparse 8 | import sys 9 | 10 | # Adjust this accordingly 11 | USERDB = "/home/matt/tools/UserDB.TXT" 12 | 13 | 14 | def packdetect(arg_pe): 15 | """attempt to detect the packer in use""" 16 | pe = pefile.PE(arg_pe) 17 | signatures = peutils.SignatureDatabase(USERDB) 18 | with file(USERDB, 'rt') as f: 19 | sig_data = f.read() 20 | signatures = peutils.SignatureDatabase(data = sig_data) 21 | if arg_showall: 22 | matches = signatures.match_all(pe, ep_only = True) 23 | else: 24 | matches = signatures.match(pe, ep_only = True) 25 | sys.stdout.write("Possible packer: ") 26 | print matches 27 | 28 | 29 | def main(): 30 | 31 | # menu system 32 | parser = argparse.ArgumentParser(description='Basic packer detector', usage='%(prog)s -f file') 33 | parser.add_argument('--file', '-f', dest='pefile', help='file to check') 34 | parser.add_argument('--all', '-a', dest='all', help='show all matches', action="store_true") 35 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 36 | args = parser.parse_args() 37 | 38 | if len(sys.argv) == 1: 39 | sys.exit(parser.print_help()) 40 | 41 | arg_pe = args.pefile 42 | global arg_showall 43 | arg_showall = args.all 44 | 45 | if not args.pefile: 46 | sys.exit(parser.print_help()) 47 | 48 | print "analysing..." 49 | packdetect(arg_pe) 50 | 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /Malware/PE/pe_compiledate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # grab the compile time of a piece of malware 4 | 5 | import time 6 | import pefile 7 | import sys 8 | import argparse 9 | 10 | def parse_pe(arg_file): 11 | pe = pefile.PE(arg_file) 12 | epoch = pe.FILE_HEADER.TimeDateStamp 13 | humantime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(epoch)) 14 | print "Possible compile time: " + humantime 15 | 16 | def __main__(): 17 | parser = argparse.ArgumentParser(description='grab the compile date of a file', usage='%(prog)s -f file') 18 | parser.add_argument('--file', '-f', dest='filein', help='file to nuke') 19 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 20 | args = parser.parse_args() 21 | arg_file = args.filein 22 | 23 | if not args.filein: 24 | sys.exit(parser.print_help()) 25 | 26 | try: 27 | parse_pe(arg_file) 28 | except: 29 | print "Error!! Looks like there's a problem with the PE file" 30 | 31 | 32 | if __name__ == '__main__': 33 | __main__() 34 | 35 | 36 | -------------------------------------------------------------------------------- /Malware/README.md: -------------------------------------------------------------------------------- 1 | Malware 2 | ======= 3 | 4 | Malware related code. Mostly to learn stuff to solve challenges I face 5 | when looking at bad software. 6 | 7 | * Glastopf - Stuff for [Glastopf](https://github.com/glastopf/glastopf) 8 | * Kippo - Stuff for [Kippo](https://code.google.com/p/kippo/) 9 | * VirusTotal - Stuff for [Virus Total](https://www.virustotal.com/en/documentation/public-api/) 10 | * Web - Stuff for web related malware, usually PHP shells and the like 11 | * PE - Stuff for Windows related malware 12 | * Thug - Stuff for [Thug](https://github.com/buffer/thug) 13 | * Google - Stuff for Google API's 14 | 15 | Some of this code will be incomplete. I have the attention span of a gnat. 16 | 17 | -------------------------------------------------------------------------------- /Malware/Thug/README.md: -------------------------------------------------------------------------------- 1 | Thug 2 | ==== 3 | 4 | [Thug](https://github.com/buffer/thug/) is awesome. You should use Thug. 5 | These are various scripts for Thug. 6 | 7 | * runthug.sh - lameass script for running Thug over multiple profiles 8 | * thug-parse.py - script to parse a report and do GSB/VT lookups on links 9 | * url-dumper.py - does a simple python get request on a list of urls and dumps to file 10 | * thugdor.sh - control script for Thugdor (tm) 11 | * spider.py - spider script to get the URLs for Thug 12 | 13 | Thugdor 14 | ======= 15 | 16 | Thugdor is (hopefully) going to be a neat little script that will: 17 | 18 | * get a list of URLs from file 19 | * do a simple Python GET request to pull down a local copy of the file 20 | * run thug on that local copy 21 | * pull out all links from the thug report 22 | * run Google Safe Browsing lookups on those links 23 | * run Virus Total lookups on anything GSB flags 24 | * run Virus Total lookups on any executable that's downloaded 25 | 26 | -------------------------------------------------------------------------------- /Malware/Thug/runthug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # version 0.1 4 | # todo: add tor support 5 | 6 | URL=$1 7 | BROWSERS="winxpie60 winxpie61 winxpie70 winxpie80 winxpchrome20 winxpfirefox12 winxpsafari5 win2kie60 win2kie80 win7ie80 win7ie90 win7chrome20 win7safari5 osx10safari5 osx10chrome19" 8 | THUGDIR=/home/matt/thug/thug/src 9 | THUGOUT=/home/matt/thug_out 10 | 11 | echo "Scanning url: $1" 12 | 13 | cd $THUGDIR 14 | for x in $BROWSERS 15 | do 16 | echo "Running scan with $x" 17 | python ./thug.py -u $x -n $THUGOUT/$1-$x $1 18 | echo "" 19 | echo "sleeping" 20 | sleep 60 21 | done -------------------------------------------------------------------------------- /Malware/Thug/spider.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Spider script to dump all URLs to file 3 | 4 | import argparse 5 | import sys 6 | import urllib 7 | import re 8 | from urlparse import urlparse 9 | try: 10 | from bs4 import BeautifulSoup 11 | import requests 12 | except: 13 | print "You're missing libraries" 14 | 15 | 16 | def spider_url(aurl, afile, aauto, averbose): 17 | """Spider our given URL and dump links to file""" 18 | print "\n * Spidering: " + aurl 19 | au = urlparse(aurl) 20 | print "\n * Base FQDN: " + au.hostname 21 | headers = {"User-agent": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"} 22 | r = requests.get(aurl, headers=headers) 23 | links = [] 24 | if r.status_code == 200: 25 | html = r.text 26 | bs = BeautifulSoup(html) 27 | for link in bs.find_all('a'): 28 | links.append((link.get('href'))) 29 | else: 30 | print "We got something other than a 200" 31 | 32 | # Parse our HTML file and dump links to an list 33 | print " * Pulling out links..." 34 | tcount = 0 35 | urls = [] 36 | for link in links: 37 | tcount += 1 38 | if link is None: 39 | pass 40 | else: 41 | if re.match("^https?://", link): 42 | if link not in urls: 43 | urls.append(link) 44 | elif re.search("#disqus_thread$", link): 45 | pass 46 | elif re.match("^/", link): 47 | full_url = aurl + link 48 | if full_url not in urls: 49 | urls.append(full_url) 50 | 51 | if averbose == 1: 52 | print "\n * This is our URL list" 53 | for url in urls: 54 | print url 55 | else: 56 | pass 57 | 58 | print "\n[ Total links: " + str(tcount) + "]" 59 | if aauto == 1: 60 | pass 61 | else: 62 | raw_input("\nPress ENTER to continue.") 63 | print "\n * Adding the following URLs for review" 64 | 65 | added = 0 66 | with open(afile, 'w') as fh: 67 | for url in urls: 68 | purl = urlparse(url) 69 | if purl.hostname != au.hostname: 70 | pass 71 | else: 72 | added += 1 73 | print url + " ...adding" 74 | fh.write(url + "\n") 75 | fh.close() 76 | 77 | print "\n[ Analysis complete...file written. ]" 78 | print "[ Total links: " + str(tcount) + "]" 79 | print "[ Added for analysis: " + str(added) + "]" 80 | 81 | 82 | def __main__(): 83 | """Get this party started""" 84 | parser = argparse.ArgumentParser(description='Basic site spiderererer') 85 | parser.add_argument('--url', '-u', dest='url', help='Base URL to start spidering') 86 | parser.add_argument('--verbose', '-V', dest='verbose', action='store_true', default=False, help='Run with more output') 87 | parser.add_argument('--auto', '-a', dest='auto', action='store_true', default=True, help='Run as a script') 88 | parser.add_argument('--file', '-f', dest='file', default='urls.txt', help='File to dump output to') 89 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 90 | args = parser.parse_args() 91 | afile = args.file 92 | aurl = args.url 93 | aauto = args.auto 94 | averbose = args.verbose 95 | 96 | if not args.url: 97 | sys.exit(parser.print_help()) 98 | elif (aauto is False and averbose is False): 99 | spider_url(aurl, afile, aauto=0, averbose=0) 100 | elif (aauto and not averbose): 101 | spider_url(aurl, afile, aauto=1, averbose=0) 102 | elif (aauto and averbose): 103 | spider_url(aurl, afile, aauto=1, averbose=1) 104 | else: 105 | spider_url(aurl, afile, aauto=1, averbose=0) 106 | 107 | 108 | if __name__ == '__main__': 109 | __main__() 110 | -------------------------------------------------------------------------------- /Malware/Thug/thug-parse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Pull links from a Thug JSON report and check them against VT and GSB 3 | 4 | import argparse 5 | import os 6 | import sys 7 | import json 8 | import urllib 9 | import time 10 | try: 11 | import requests 12 | except: 13 | print "You need the requests library" 14 | 15 | 16 | def load_gsbkey(): 17 | """Load our API key from file""" 18 | fullpath = os.getenv("HOME") 19 | try: 20 | with open(fullpath + '/.googlesafe.key', 'r') as keyfile: 21 | for line in keyfile: 22 | googlekey = line.rstrip() 23 | keyfile.close() 24 | return googlekey 25 | except: 26 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.googlesafe.key") 27 | 28 | 29 | def google_lookup(url): 30 | """Check Google for our urls""" 31 | googlekey = load_gsbkey() 32 | encoded_url = urllib.quote_plus(url) 33 | google_url = "https://sb-ssl.google.com/safebrowsing/api/lookup?client=firefox&apikey=" + \ 34 | googlekey + "&appver=1.0&pver=3.0&url=" + \ 35 | encoded_url 36 | try: 37 | resp = requests.get(google_url) 38 | except: 39 | sys.exit("Error with request to Google") 40 | scode = resp.status_code 41 | if scode == 204: 42 | return 204 43 | if scode == 200: 44 | body = resp.text 45 | return body 46 | elif scode == 400: 47 | return 400 48 | elif scode == 401: 49 | sys.exit("[Error: API key problem]") 50 | elif scode == 403: 51 | sys.exit("[Error: API key problem]") 52 | elif scode == 503: 53 | sys.exit("[Error: Service unavailable]") 54 | 55 | 56 | def load_vtkey(): 57 | """Load our API key from file""" 58 | fullpath = os.getenv("HOME") 59 | try: 60 | keyfile = open(fullpath + '/.virustotal.key', 'r') 61 | except: 62 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.virustotal.key") 63 | 64 | for line in keyfile: 65 | vtkey = line.rstrip() 66 | keyfile.close() 67 | 68 | return vtkey 69 | 70 | 71 | def virustotal_url_lookup(url): 72 | """Check a URL against VT""" 73 | vtkey = load_vtkey() 74 | vturl = "https://www.virustotal.com/vtapi/v2/url/report" 75 | parameters = {"resource": url, "apikey": vtkey} 76 | try: 77 | resp = requests.get(vturl, params=parameters) 78 | except: 79 | sys.exit("Problem with the HTTP request to VT") 80 | 81 | report = resp.json() 82 | resp_code = report.get("response_code", {}) 83 | if resp_code == 0: 84 | evilrating = 0 85 | pass 86 | else: 87 | evilness = report.get("positives", {}) 88 | webutation = report.get("scans", {}).get("Webutation").get("result") 89 | if evilness == 0: 90 | pass 91 | evilrating = evilness 92 | elif evilness == 1: 93 | print "Possibly evil", 94 | if webutation: 95 | print "(Evilness from Webutation)" 96 | evilrating = evilness 97 | elif evilness >= 2: 98 | evilrating = evilness 99 | 100 | return evilrating 101 | 102 | 103 | def load_report(areport): 104 | """Load our report""" 105 | print "\n * Loading report: ", 106 | try: 107 | jreport = open(areport) 108 | except: 109 | sys.exit(" ** [Error: Problem loading report]") 110 | data = json.load(jreport) 111 | jreport.close() 112 | conns = data["connections"] 113 | count = 0 114 | for conn in conns: 115 | count += 1 116 | print str(count) + " URLs" 117 | 118 | return conns 119 | 120 | 121 | def no_lookups(areport, aoutput): 122 | """Don't perform lookups just dump the URLS""" 123 | conns = load_report(areport) 124 | count = 0 125 | url_list = [] 126 | for conn in conns: 127 | url = conn["destination"] 128 | if url is None: 129 | pass 130 | elif url == "javascript:\'\'": 131 | pass 132 | elif url not in url_list: 133 | count += 1 134 | url_list.append(url) 135 | outputf = aoutput + "/urls-for-lookup.txt" 136 | with open(outputf, 'w') as dump_file: 137 | for url in url_list: 138 | dump_file.write(url + "\n") 139 | dump_file.close() 140 | print "\n[ Complete: " + str(count) + " to scan ]" 141 | 142 | 143 | def perform_lookups(areport, aoutput): 144 | """Perform our lookups and report""" 145 | conns = load_report(areport) 146 | count = 0 147 | url_list = [] 148 | for conn in conns: 149 | url = conn["destination"] 150 | if url is None: 151 | pass 152 | elif url == "javascript:\'\'": 153 | pass 154 | elif url not in url_list: 155 | count += 1 156 | url_list.append(url) 157 | 158 | glr = google_lookups(url_list, aoutput) 159 | now = time.strftime("%Y-%m-%d %H:%M") 160 | print "\n [ Analysis Complete: " + now + " Lookups >> GSB:" + str(gsburlcount) + " VT: " + str(vturlcount) + " ]\n" 161 | 162 | 163 | def google_lookups(url_list, aoutput): 164 | """Perform various Google lookups""" 165 | # Do a GSB lookup for all URLs 166 | print "\n * Google Safe Browsing Lookup on URLs\n" 167 | count = 0 168 | exported_evil = 0 169 | global vturlcount 170 | vturlcount = 0 171 | eyewitness = [] 172 | for url in url_list: 173 | count += 1 174 | gsl = google_lookup(url) 175 | if gsl == 204: 176 | pass 177 | elif gsl == 400: 178 | print url 179 | print "[Error 400: Bad Request]" 180 | elif gsl == "malware": 181 | print " !! " + url + " >> Google reported malicious...checking VT", 182 | vturlcount += 1 183 | vtl = virustotal_url_lookup(url) 184 | print "[ Detection: " + str(vtl) + "/52 ]" 185 | eyewitness.append(url) 186 | exported_evil = 1 187 | 188 | if not eyewitness: 189 | pass 190 | else: 191 | print "\n * Dumping URLs for Eyewitness", 192 | eyewitnessf = aoutput + "/eyewitness.txt" 193 | with open(eyewitnessf, 'w') as fh: 194 | for url in eyewitness: 195 | fh.write(url) 196 | fh.close 197 | print "..." + eyewitnessf 198 | 199 | global gsburlcount 200 | gsburlcount = count 201 | 202 | return exported_evil 203 | 204 | 205 | def __main__(): 206 | """Get this party started""" 207 | parser = argparse.ArgumentParser(description='Thug report parser') 208 | parser.add_argument('--report', '-r', dest='report', help='Report to parse') 209 | parser.add_argument('--no-lookups', '-n', dest='nolookups', action='store_true', help='No GSB Lookups just dump to file') 210 | parser.add_argument('--output', '-o', dest='output', default='/tmp', help='Output directory') 211 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 212 | args = parser.parse_args() 213 | areport = args.report 214 | global aoutput 215 | aoutput = args.output 216 | anolookups = args.nolookups 217 | 218 | if not (args.report or args.nolookups): 219 | sys.exit(parser.print_help()) 220 | elif args.nolookups: 221 | print "\n\n[ Malicious Checks Starting ]" 222 | no_lookups(areport, aoutput) 223 | else: 224 | print "\n\n[ Malicious Checks Starting ]" 225 | perform_lookups(areport, aoutput) 226 | 227 | 228 | if __name__ == '__main__': 229 | __main__() 230 | 231 | -------------------------------------------------------------------------------- /Malware/Thug/thugdor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Master script for Thugdor 3 | set -o nounset 4 | set -o errexit 5 | 6 | # TARGET 7 | TARGET=$1 8 | 9 | # CONFIGURATION 10 | # 11 | DATE=`date +%d_%m_%Y` 12 | PYTHON="/usr/bin/python" 13 | # OUTPUT DIRECTORIES 14 | HOMEDIR="/home/matt" 15 | REPORTDIR="${HOMEDIR}/Reports" 16 | THUGREPORTS="${REPORTDIR}/Thug" 17 | EYEWITNESS="${REPORTDIR}/Eyewitness" 18 | URLLIST="${REPORTDIR}/checks.txt" 19 | URLDUMPS="${REPORTDIR}/url_dumps" 20 | TMPTHUGREPORTS="/tmp/thug-reports-$$.txt" 21 | THUGPARSEOUTPUT="${REPORTDIR}/for-google-lookups.txt" 22 | OUTPUTDIR="${HOMEDIR}/Output" 23 | GOOGLESAFEIN="${OUTPUTDIR}/urls-for-lookup.txt" 24 | EYEWITNESSIN="${OUTPUTDIR}/eyewitness.txt" 25 | CHECKTHUG="/tmp/.thugme.txt" 26 | REPORTFILE="${REPORTDIR}/thugdor-report-${DATE}.txt" 27 | # SCRIPTS 28 | SPIDER="${HOMEDIR}/Github/Malware/Thug/spider.py" 29 | URLDUMPER="${HOMEDIR}/Github/Malware/Thug/url-dumper.py" 30 | THUGPARSE="${HOMEDIR}/Github/Malware/Thug/thug-parse.py" 31 | GOOGLELOOKUP="${HOMEDIR}/Github/Malware/Google/google-safe-lookup.py" 32 | EYEWITNESS="${HOMEDIR}/Github/EyeWitness/EyeWitness.py" 33 | # THUG AND OPTIONS 34 | THUG="/opt/tools/thug/src/thug.py" 35 | THUGUA="win7ie90" 36 | THUGOPTS="-q -y" 37 | THUGTIMEOUT="10" 38 | THUGANALYSIS="analysis.json" 39 | 40 | 41 | echo "" > ${REPORTFILE} 42 | echo "[ Thugdor v0.1 ]" | tee -a ${REPORTFILE} 43 | echo | tee -a ${REPORTFILE} 44 | 45 | function spider { 46 | echo -n " * Running Spider" | tee -a ${REPORTFILE} 47 | ${PYTHON} ${SPIDER} -u ${TARGET} -f ${URLLIST} | tee -a ${REPORTFILE} 48 | echo | tee -a ${REPORTFILE} 49 | } 50 | 51 | function urldump { 52 | echo -n " * Running URL Dump script for Thug analysis" | tee -a ${REPORTFILE} 53 | test -d ${URLDUMPS} && true || mkdir -p ${URLDUMPS} 54 | ${PYTHON} ${URLDUMPER} -f ${URLLIST} -d ${URLDUMPS} | tee -a ${REPORTFILE} 55 | echo | tee -a ${REPORTFILE} 56 | } 57 | 58 | function checkthug { 59 | test -f ${CHECKTHUG} && echo "Running Thug" && thuganalize || cleanup 60 | } 61 | 62 | function thuganalize { 63 | echo -n " * Running Thug on local files" | tee -a ${REPORTFILE} 64 | for URL in ${URLDUMPS}/*-SCANME 65 | do 66 | ${PYTHON} ${THUG} -u ${THUGUA} ${THUGOPTS} -T ${THUGTIMEOUT} \ 67 | -n ${THUGREPORTS}/${URL} -l ${URL} | tee -a ${REPORTFILE} 68 | CHOPPED=`basename ${URL} -SCANME` 69 | mv ${URL} ${URLDUMPS}/${CHOPPED}-SCANNED 70 | done 71 | echo | tee -a ${REPORTFILE} 72 | thugparse 73 | } 74 | 75 | function thugparse { 76 | echo -n " * Running Thug parsing script on Thug reports" | tee -a ${REPORTFILE} 77 | find ${THUGREPORTS} -name ${THUGANALYSIS} >> ${TMPTHUGREPORTS} 78 | for THUG in `cat ${TMPTHUGREPORTS}` 79 | do 80 | ${PYTHON} ${THUGPARSE} -r ${THUG} -n -o ${OUTPUTDIR} | tee -a ${REPORTFILE} 81 | done 82 | echo | tee -a ${REPORTFILE} 83 | googlelookup 84 | } 85 | 86 | function googlelookup { 87 | echo -n " * Running Google Safe Browsing Checks" | tee -a ${REPORTFILE} 88 | ${GOOGLELOOKUP} -f ${GOOGLESAFEIN} -q 89 | eyewitness 90 | } 91 | 92 | function eyewitness { 93 | echo -n " * Running Eyewitness on any malicious links found" | tee -a ${REPORTFILE} 94 | test -d ${EYEWITNESSIN} && ${EYEWITNESS} --skipcreds --useragent \ 95 | "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \ 96 | -t 10 -f ${EYEWITNESSIN} | tee -a ${REPORTFILE} \ 97 | || echo " [ No malicious links to grab ] " | tee -a ${REPORTFILE} 98 | echo | tee -a ${REPORTFILE} 99 | cleanup 100 | } 101 | 102 | function cleanup { 103 | echo "" 104 | echo "[ Complete ${DATE} ]" | tee -a ${REPORTFILE} 105 | rm -f ${TMPTHUGREPORTS} > /dev/null 2>&1 106 | rm -fr ${THUGREPORTS}/* > /dev/null 2>&1 107 | rm -fr ${HOMEDIR}/logs > /dev/null 2>&1 108 | rm -f ${CHECKTHUG} > /dev/null 2>&1 109 | } 110 | 111 | # The party starts here 112 | spider 113 | urldump 114 | checkthug 115 | 116 | -------------------------------------------------------------------------------- /Malware/Thug/url-dumper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin.python 2 | # Simple script to pull down a remote URL for analysis with Thug 3 | 4 | import argparse 5 | import sys 6 | import os 7 | import hashlib 8 | try: 9 | import requests 10 | except: 11 | sys.exit("You need the requests library") 12 | 13 | 14 | def hash_url_file(hashme): 15 | """Return a hash of the given url file""" 16 | file = open(hashme, 'rb') 17 | m = hashlib.md5() 18 | m.update(file.read()) 19 | digest = m.hexdigest() 20 | file.close() 21 | 22 | return digest 23 | 24 | 25 | def dup_check(fullpath, adest, r): 26 | """Check if we've already pulled down a copy""" 27 | scanned_file = fullpath + "-SCANNED" 28 | new_hash_file = fullpath + "-SCANME" 29 | tmp_hash_file = fullpath + "-TMP" 30 | check = os.path.isfile(scanned_file) 31 | if check is True: 32 | old_hash = hash_url_file(scanned_file) 33 | with open(tmp_hash_file, 'w') as tmp: 34 | tmp.write(r.content) 35 | tmp.close() 36 | new_hash = hash_url_file(tmp_hash_file) 37 | if old_hash == new_hash: 38 | os.remove(scanned_file) 39 | os.rename(tmp_hash_file, scanned_file) 40 | dup_check = 2 41 | elif old_hash != new_hash: 42 | os.remove(scanned_file) 43 | os.rename(tmp_hash_file, new_hash_file) 44 | dup_check = 1 45 | else: 46 | with open(new_hash_file, 'w') as new: 47 | new.write(r.content) 48 | new.close() 49 | dup_check = 0 50 | 51 | return dup_check 52 | 53 | 54 | def url_pull(url, adest): 55 | """Pull down our URLs for review""" 56 | print " * Checking: " + url, 57 | global md5url 58 | md5url = hashlib.md5(url).hexdigest() 59 | headers = {"User-agent": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"} 60 | r = requests.get(url, headers=headers) 61 | fullpath = adest + "/" + md5url 62 | # Check if we have already scanned the file 63 | dupcheck = dup_check(fullpath, adest, r) 64 | scanning = 0 65 | if dupcheck == 0: 66 | scanning += 1 67 | print " >> No existing hashes. \t[ SCANNING ]" 68 | elif dupcheck == 1: 69 | scanning += 1 70 | print " >> Site content changed. \t[ SCANNING ]" 71 | elif dupcheck == 2: 72 | print " >> Site content hasn't changed. \t[ NOT SCANNING ]" 73 | 74 | return scanning 75 | 76 | 77 | def load_file(afile, adest): 78 | """Load our URLs from file""" 79 | if not os.path.exists(adest): 80 | os.makedirs(adest) 81 | total_scans = 0 82 | with open(afile, 'r') as fh: 83 | for url in fh: 84 | clean_url = url.rstrip() 85 | # Get our URL for scanning 86 | scanning = url_pull(clean_url, adest) 87 | if scanning == 1: 88 | total_scans += 1 89 | print "\n[ Dumped URLs to file for Thug Analysis: " + adest + "\tTotal scans: " + str(total_scans) + " ]" 90 | # Nasty hack for Thug 91 | if total_scans >= 1: 92 | tmp_thug = "/tmp/.thugme.txt" 93 | with open(tmp_thug, 'w') as tmpfile: 94 | tmpfile.write("scan") 95 | tmpfile.close() 96 | else: 97 | pass 98 | 99 | 100 | def __main__(): 101 | """Get this party started""" 102 | parser = argparse.ArgumentParser(description='URL Puller') 103 | parser.add_argument('--file', '-f', dest='file', help='File with URLs to pull down') 104 | parser.add_argument('--dest', '-d', dest='dest', default='/tmp/', help='Directory directory to dump to') 105 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 106 | args = parser.parse_args() 107 | afile = args.file 108 | global adest 109 | adest = args.dest 110 | 111 | if not args.file: 112 | sys.exit(parser.print_help()) 113 | else: 114 | print "\n\n[ Thug URL Dumper ]\n" 115 | load_file(afile, adest) 116 | 117 | if __name__ == '__main__': 118 | __main__() -------------------------------------------------------------------------------- /Malware/Virustotal/README.md: -------------------------------------------------------------------------------- 1 | Virus Total stuff 2 | ================= 3 | 4 | Virus total stuff...mostly for their public API 5 | 6 | 7 | * vtevilsubmit.py - Submit or check files and URLs to the VT API. 8 | * vthashcheck.py - New hash checker for v2 API using the requests module 9 | * vtbulkcheck.py - Simple bulk hash checker (Note: API rate limiting) 10 | 11 | 12 | 13 | vtevilcheck_v2.py 14 | ----------------- 15 | 16 | This script takes a number of arguments. 17 | 18 | * -h for basic help 19 | * -k to specify a different key file to ~/.virustotal.key 20 | * -H to check VT for a specific hash 21 | * -r to check VT for a resource. This can be a hash, scan ID value or a URL 22 | * -f to submit a file to VT for scanning 23 | * -u to submit a URL to VT for scanning 24 | * -i to get a report on an IP address 25 | * -d to get a report on a domain name 26 | * -b to do a bulk hash check (Note: API rate limiting) 27 | 28 | 29 | It's worth noting that both the file and URL submission checks will perform a 30 | precheck on VT to see if the file or URL has been submitted already. 31 | 32 | 33 | 34 | Bugs can go to code at zonbi dot org. 35 | 36 | 37 | Thanks to the VT crew for being full of awesome 38 | 39 | -------------------------------------------------------------------------------- /Malware/Virustotal/vtbulkcheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple bulk hash checker for Virustotal using the requests module 3 | # It expects your VT API Key in ~/.virustotal.key 4 | 5 | import argparse 6 | import sys 7 | import os 8 | import requests 9 | 10 | 11 | def bulkcheck(afile): 12 | """Bulk checker against VT""" 13 | vtkey = load_apikey() 14 | print "Checking hashes in file: " + afile 15 | try: 16 | fhandle = open(afile, 'r') 17 | nlines = sum(1 for line in fhandle) 18 | if nlines > 4: 19 | print "*** WARNING: Bulk checks are limited to 4 per minute on the public API ***" 20 | except IOError, e: 21 | sys.exit("Error: %s" % e) 22 | 23 | vturl = "https://www.virustotal.com/vtapi/v2/file/report" 24 | fhandle = open(afile, 'r') 25 | hashes = fhandle.readlines() 26 | for hash in hashes: 27 | try: 28 | hash = hash.rstrip() 29 | parameters = {"resource": hash, "apikey": vtkey } 30 | resp = requests.get(vturl, params=parameters) 31 | report = resp.json() 32 | resp_code = report.get("response_code", {}) 33 | if resp_code == 0: 34 | sys.exit("Exiting. \nGot an unexpected error back from VT") 35 | evilness = report.get("positives", {}) 36 | totaleng = report.get("total", {}) 37 | print hash + " Evilness: " + str(evilness) + "/" + str(totaleng) 38 | except ValueError, e: 39 | sys.exit("Error: %s" % e) 40 | 41 | 42 | def load_apikey(): 43 | """Load our API key from file""" 44 | fullpath = os.getenv("HOME") 45 | try: 46 | keyfile = open(fullpath + '/.virustotal.key', 'r') 47 | except: 48 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.virustotal.key") 49 | 50 | for line in keyfile: 51 | vtkey = line.rstrip() 52 | keyfile.close() 53 | 54 | return vtkey 55 | 56 | def __main__(): 57 | 58 | parser = argparse.ArgumentParser(description='basic menu system', usage='%(prog)s -f file') 59 | parser.add_argument('--file', '-f', dest='file', help='file with hashes to check') 60 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 61 | args = parser.parse_args() 62 | afile = args.file 63 | 64 | if not args.file: 65 | sys.exit(parser.print_help()) 66 | 67 | bulkcheck(afile) 68 | 69 | 70 | if __name__ == '__main__': 71 | __main__() 72 | -------------------------------------------------------------------------------- /Malware/Virustotal/vtdomaincheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to detect if a domain/ip is malicious 3 | 4 | import os 5 | import argparse 6 | import sys 7 | try: 8 | import requests 9 | except: 10 | print "You need python requests" 11 | 12 | 13 | def load_apikey(): 14 | """Load our API key from file""" 15 | fullpath = os.getenv("HOME") 16 | try: 17 | keyfile = open(fullpath + '/.virustotal.key', 'r') 18 | except: 19 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.virustotal.key") 20 | 21 | for line in keyfile: 22 | vtkey = line.rstrip() 23 | keyfile.close() 24 | return vtkey 25 | 26 | 27 | def check_domain(adomain): 28 | """Check a domain name against VT""" 29 | vtkey = load_apikey() 30 | vturl = "https://www.virustotal.com/vtapi/v2/domain/report" 31 | parameters = {"domain": adomain, "apikey": vtkey } 32 | try: 33 | resp = requests.get(vturl, params=parameters) 34 | except: 35 | sys.exit("Problem with the HTTP request to VT") 36 | report = resp.json() 37 | resp_code = report.get("response_code", {}) 38 | if resp_code == 0: 39 | sys.exit("Nothing found for domain: " + adomain) 40 | 41 | url_list = report.get("detected_urls", {}) 42 | for url in url_list: 43 | evilness = url['positives'] 44 | 45 | return evilness 46 | 47 | 48 | def docheck(adomain): 49 | """Run checks against the supplied IP address and domain""" 50 | evildomain = check_domain(adomain) 51 | if evildomain > 0: 52 | print adomain + ": [EVIL]" 53 | else: 54 | print adomain + ": [OK]" 55 | 56 | 57 | def __main__(): 58 | """Lets get this party started""" 59 | parser = argparse.ArgumentParser(description='Simple virustotal.com domain checker') 60 | parser.add_argument('--domain', '-d', dest='domain', help='Submit a domain name for checking') 61 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.3') 62 | args = parser.parse_args() 63 | adomain = args.domain 64 | 65 | if adomain: 66 | docheck(adomain) 67 | else: 68 | sys.exit(parser.print_help()) 69 | 70 | 71 | 72 | if __name__ == "__main__": 73 | __main__() 74 | 75 | -------------------------------------------------------------------------------- /Malware/Virustotal/vtevilsubmit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple file/url uploader for Virustotal using the requests module 3 | # It expects your VT API Key in ~/.virustotal.key 4 | 5 | 6 | import os 7 | import argparse 8 | import sys 9 | import requests 10 | import hashlib 11 | 12 | 13 | def bulkcheck(abulk): 14 | """Bulk checker against VT""" 15 | vtkey = load_apikey() 16 | print "Checking hashes in file: " + abulk 17 | try: 18 | fhandle = open(abulk, 'r') 19 | nlines = sum(1 for line in fhandle) 20 | if nlines > 4: 21 | print "*** WARNING: Bulk checks are limited to 4 per minute on the public API ***" 22 | pass 23 | except IOError, e: 24 | sys.exit("Error: %s" % e) 25 | 26 | vturl = "https://www.virustotal.com/vtapi/v2/file/report" 27 | fhandle = open(abulk, 'r') 28 | hashes = fhandle.readlines() 29 | for hash in hashes: 30 | try: 31 | hash = hash.rstrip() 32 | parameters = {"resource": hash, "apikey": vtkey } 33 | resp = requests.get(vturl, params=parameters) 34 | report = resp.json() 35 | resp_code = report.get("response_code", {}) 36 | if resp_code == 0: 37 | sys.exit("Exiting. \nGot an unexpected error back from VT") 38 | evilness = report.get("positives", {}) 39 | totaleng = report.get("total", {}) 40 | print hash + " Evilness: " + str(evilness) + "/" + str(totaleng) 41 | except ValueError, e: 42 | sys.exit("Error: %s" % e) 43 | 44 | def filesubmit(asubfile): 45 | """Check a domain name against VT""" 46 | vtkey = load_apikey() 47 | 48 | try: 49 | filehandle = open(asubfile, 'rb').read() 50 | except: 51 | sys.exit("** Error: Supply a file for upload") 52 | 53 | print "Calculating hash for : " + asubfile 54 | filehash = hashlib.md5(filehandle).hexdigest() 55 | print "Checking file: " + asubfile 56 | print "Checking for existing scan results" 57 | precheck = check_resource(filehash, rtype="FILE") 58 | if precheck == True: 59 | sys.exit() 60 | else: 61 | pass 62 | print "Uploading file to VT" 63 | vturl = "https://www.virustotal.com/vtapi/v2/file/scan" 64 | payload = {"apikey": vtkey, "file": (asubfile, filehandle) } 65 | try: 66 | resp = requests.post(vturl, files=payload) 67 | except: 68 | sys.exit("Unexpected error 31") 69 | report = resp.json() 70 | resp_code = report.get("response_code", {}) 71 | if resp_code == 0: 72 | sys.exit("Nothing found for file: " + asubfile) 73 | 74 | verb_msg = report.get("verbose_msg", {}) 75 | scan_date = report.get("scan_date", {}) 76 | scan_id = report.get("scan_id", {}) 77 | permalink = report.get("permalink", {}) 78 | print "Message: " + verb_msg 79 | print "Scan date: " + str(scan_date) 80 | print "Scan id: " + str(scan_id) 81 | print "\nPermalink: " + permalink 82 | 83 | 84 | 85 | def check_domain(asubdomain): 86 | """Check a domain name against VT""" 87 | vtkey = load_apikey() 88 | print "Checking IP: " + asubdomain 89 | vturl = "https://www.virustotal.com/vtapi/v2/domain/report" 90 | parameters = {"domain": asubdomain, "apikey": vtkey } 91 | try: 92 | resp = requests.get(vturl, params=parameters) 93 | except: 94 | sys.exit() 95 | report = resp.json() 96 | resp_code = report.get("response_code", {}) 97 | if resp_code == 0: 98 | sys.exit("Nothing found for domain: " + asubdomain) 99 | 100 | verb_msg = report.get("verbose_msg", {}) 101 | print "Message: " + verb_msg 102 | print "\nPassive DNS report for: " + asubdomain + "\n" 103 | hostlist = report.get("resolutions", {}) 104 | for hosts in hostlist: 105 | lastseen = hosts['last_resolved'] 106 | host = hosts['ip_address'] 107 | print "IP Address: " + host + "\tLast seen: " + lastseen 108 | 109 | print "\nDetected URLS\n" 110 | url_list = report.get("detected_urls", {}) 111 | for url in url_list: 112 | detectedurl = url['url'] 113 | evilness = url['positives'] 114 | totalness = url['total'] 115 | scan_date = url['scan_date'] 116 | print "URL Detected: " + detectedurl 117 | print "\_-> Evilness: " + str(int(evilness)) + "/" + str(int(totalness)), 118 | print "Scan date: " + str(scan_date) 119 | 120 | 121 | def check_ip(asubip): 122 | """Check an IP against VT""" 123 | vtkey = load_apikey() 124 | print "Checking IP: " + asubip 125 | vturl = "https://www.virustotal.com/vtapi/v2/ip-address/report" 126 | parameters = {"ip": asubip, "apikey": vtkey } 127 | try: 128 | resp = requests.get(vturl, params=parameters) 129 | except: 130 | sys.exit() 131 | report = resp.json() 132 | resp_code = report.get("response_code", {}) 133 | if resp_code == 0: 134 | sys.exit("Exiting. IP not in dataset.") 135 | 136 | verb_msg = report.get("verbose_msg", {}) 137 | print "Message: " + verb_msg 138 | print "\nPassive DNS report for: " + asubip + "\n" 139 | hostlist = report.get("resolutions", {}) 140 | for hosts in hostlist: 141 | lastseen = hosts['last_resolved'] 142 | host = hosts['hostname'] 143 | print "Hostname: " + host + "\tLast seen: " + lastseen 144 | 145 | 146 | print "\nDetected URLS\n" 147 | url_list = report.get("detected_urls", {}) 148 | for url in url_list: 149 | detectedurl = url['url'] 150 | evilness = url['positives'] 151 | totalness = url['total'] 152 | scan_date = url['scan_date'] 153 | print "URL Detected: " + detectedurl + "\t(Evilness: " + str(int(evilness)) + "/" + str(int(totalness)) + "\t[Scan date: " + str(scan_date) + "])" 154 | 155 | 156 | def urlsubmit(asuburl): 157 | """Submit a URL for scanning""" 158 | vtkey = load_apikey() 159 | print "Checking for existing scan results" 160 | precheck = check_resource(asuburl, rtype="URL") 161 | if precheck == True: 162 | sys.exit() 163 | else: 164 | pass 165 | 166 | print "Submitting URL: " + asuburl 167 | vturl = "https://www.virustotal.com/vtapi/v2/url/scan" 168 | payload = {"url": asuburl, "apikey": vtkey } 169 | try: 170 | resp = requests.post(vturl, data=payload) 171 | except: 172 | sys.exit() 173 | 174 | report = resp.json() 175 | resp_code = report.get("response_code", {}) 176 | if resp_code == 0: 177 | sys.exit("Exiting. \nGot an unexpected error back from VT") 178 | 179 | verb_msg = report.get("verbose_msg", {}) 180 | scan_date = report.get("scan_date", {}) 181 | scan_id = report.get("scan_id", {}) 182 | permalink = report.get("permalink", {}) 183 | print "Message: " + verb_msg 184 | print "Scan date: " + scan_date 185 | print "Scan id: " + scan_id 186 | print "\nPermalink: " + permalink 187 | 188 | 189 | def check_resource(aresourceid, rtype): 190 | """Check VT for an existing scan ID/URL""" 191 | print "Resource check: " + rtype 192 | vtkey = load_apikey() 193 | print "Checking for resource ID: " + aresourceid 194 | vturl_url = "https://www.virustotal.com/vtapi/v2/url/report" 195 | vturl_file = "https://www.virustotal.com/vtapi/v2/file/report" 196 | parameters = {"resource": aresourceid, "apikey": vtkey } 197 | if rtype == "URL": 198 | try: 199 | resp = requests.get(vturl_url, params=parameters) 200 | except: 201 | sys.exit("Error 31") 202 | elif rtype == "FILE": 203 | try: 204 | resp = requests.get(vturl_file, params=parameters) 205 | except: 206 | sys.exit("Error 31") 207 | 208 | report = resp.json() 209 | resp_code = report.get("response_code", {}) 210 | if resp_code == 0: 211 | print "No existing scan results found for: " + aresourceid 212 | return False 213 | else: 214 | print "Existing scan results for: " + aresourceid 215 | report = resp.json() 216 | verb_msg = report.get("verbose_msg", {}) 217 | scan_date = report.get("scan_date", {}) 218 | scan_url = report.get("url", {}) 219 | evilness = report.get("positives", {}) 220 | totaleng = report.get("total", {}) 221 | permalink = report.get("permalink", {}) 222 | scanners = report.get("scans", {}) 223 | print "\nMessage: " + verb_msg 224 | print "Scan date: " + scan_date 225 | print "Scan URL: " + str(scan_url) 226 | print "\nMalicious Detects: " + str(evilness) + "/" + str(totaleng) 227 | print "\nAV detections: ", 228 | if rtype == "FILE": 229 | print "file report.\n" 230 | detected = [] 231 | undetected = [] 232 | for scanner in scanners: 233 | avreport = report.get("scans", {}).get(scanner, {}).get("result") 234 | avversion = report.get("scans", {}).get(scanner, {}).get("version") 235 | if avreport == None: 236 | undetected.append(scanner + " / " + str(avversion)) 237 | else: 238 | detected.append(scanner + " / " + str(avversion) + "\t\tDetection: " + str(avreport)) 239 | 240 | print "Successful detections: " 241 | for good in detected: 242 | print "\t" + good 243 | 244 | print "\nUnsuccessful at detection: " 245 | for bad in undetected: 246 | print "\t" + bad 247 | else: 248 | print "URL report.\n" 249 | detected = [] 250 | undetected = [] 251 | for scanner in scanners: 252 | avreport = report.get("scans", {}).get(scanner, {}).get("result") 253 | avversion = report.get("scans", {}).get(scanner, {}).get("version") 254 | if avreport == "clean site": 255 | detected.append(scanner + " / " + str(avversion) + "\t\tDetection: " + str(avreport)) 256 | else: 257 | undetected.append(scanner + " / " + str(avversion)) 258 | 259 | print "Detections: " 260 | for good in detected: 261 | print "\t" + good 262 | 263 | print "\nNo detections: " 264 | for bad in undetected: 265 | print "\t" + bad 266 | 267 | print "\nPermalink: " + permalink 268 | return True 269 | 270 | def check_hash(ahash): 271 | """check hash against the virustotal.com database""" 272 | print "Checking VT API key" 273 | vtkey = load_apikey() 274 | print "Checking hash: ", ahash 275 | vturl = "https://www.virustotal.com/vtapi/v2/file/report" 276 | parameters = {"resource": ahash, "apikey": vtkey } 277 | try: 278 | resp = requests.get(vturl, params=parameters) 279 | except: 280 | sys.exit() 281 | 282 | report = resp.json() 283 | resp_code = report.get("response_code", {}) 284 | if resp_code == 0: 285 | sys.exit("Exiting. \nGot an unexpected error back from VT") 286 | verb_msg = report.get("verbose_msg", {}) 287 | scan_date = report.get("scan_date", {}) 288 | evilness = report.get("positives", {}) 289 | totaleng = report.get("total", {}) 290 | permalink = report.get("permalink", {}) 291 | scanners = report.get("scans", {}) 292 | print "Message: " + verb_msg 293 | print "Scan date: " + scan_date 294 | print "\nMalicious Detects: " + str(evilness) + "/" + str(totaleng) 295 | print "\nAV detections\n" 296 | detected = [] 297 | undetected = [] 298 | for scanner in scanners: 299 | avreport = report.get("scans", {}).get(scanner, {}).get("result") 300 | avversion = report.get("scans", {}).get(scanner, {}).get("version") 301 | if avreport == None: 302 | undetected.append(scanner + " / " + str(avversion)) 303 | else: 304 | detected.append(scanner + " / " + str(avversion) + "\t\tDetection: " + str(avreport)) 305 | 306 | print "Successful detections: " 307 | for good in detected: 308 | print "\t" + good 309 | 310 | print "\nUnsuccessful at detection: " 311 | for bad in undetected: 312 | print "\t" + bad 313 | 314 | print "\nPermalink: " + permalink 315 | 316 | 317 | def load_apikey(): 318 | """Load our API key from file""" 319 | fullpath = os.getenv("HOME") 320 | try: 321 | keyfile = open(fullpath + '/.virustotal.key', 'r') 322 | except: 323 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.virustotal.key") 324 | 325 | for line in keyfile: 326 | vtkey = line.rstrip() 327 | keyfile.close() 328 | 329 | return vtkey 330 | 331 | 332 | def __main__(): 333 | """Lets get this party started""" 334 | parser = argparse.ArgumentParser(description='Simple virustotal.com file/url/hash/ip/domain checker/uploader', usage='%(prog)s -h help') 335 | parser.add_argument('--hash', '-H', dest='hash', help='Check VT for this hash') 336 | parser.add_argument('--resourceid', '-r', dest='resourceid', help='Check VT for this scan ID/resource') 337 | parser.add_argument('--file', '-f', dest='subfile', help='Submit file for scanning') 338 | parser.add_argument('--url', '-u', dest='suburl', help='Submit URL for scanning') 339 | parser.add_argument('--ip', '-i', dest='subip', help='Submit an IP address for checking') 340 | parser.add_argument('--domain', '-d', dest='subdomain', help='Submit a domain name for checking') 341 | parser.add_argument('--bulk', '-b', dest='bulk', help='Submit hashes in file for hash checking') 342 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.3') 343 | args = parser.parse_args() 344 | ahash = args.hash 345 | aresourceid = args.resourceid 346 | asubfile = args.subfile 347 | asuburl = args.suburl 348 | asubip = args.subip 349 | asubdomain = args.subdomain 350 | abulk = args.bulk 351 | 352 | if ahash: 353 | check_hash(ahash) 354 | elif aresourceid: 355 | check_resource(aresourceid, rtype="FILE") 356 | elif asubfile: 357 | filesubmit(asubfile) 358 | elif asuburl: 359 | urlsubmit(asuburl) 360 | elif asubip: 361 | check_ip(asubip) 362 | elif asubdomain: 363 | check_domain(asubdomain) 364 | elif abulk: 365 | bulkcheck(abulk) 366 | else: 367 | sys.exit(parser.print_help()) 368 | 369 | 370 | 371 | if __name__ == "__main__": 372 | __main__() -------------------------------------------------------------------------------- /Malware/Virustotal/vthashcheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple hash checker for Virus total using the requests module 3 | # It expects your VT API Key in ~/.virustotal.key 4 | # Basic usage ./vthackcheck.py -H 5 | 6 | import argparse 7 | import sys 8 | import getpass 9 | import requests 10 | 11 | 12 | def hashcheck(ahash): 13 | """check hash against the virustotal.com database""" 14 | vtkey = load_apikey() 15 | print "Checking hash: " + ahash 16 | parameters = {"resource": ahash, "apikey": vtkey } 17 | try: 18 | resp = requests.get("https://www.virustotal.com/vtapi/v2/file/report", params=parameters) 19 | except: 20 | sys.exit() 21 | 22 | report = resp.json() 23 | resp_code = report.get("response_code", {}) 24 | if resp_code == 0: 25 | sys.exit("Exiting. \nPossibly unknown sample.") 26 | verb_msg = report.get("verbose_msg", {}) 27 | scan_date = report.get("scan_date", {}) 28 | evilness = report.get("positives", {}) 29 | totaleng = report.get("total", {}) 30 | permalink = report.get("permalink", {}) 31 | scanners = report.get("scans", {}) 32 | print "Message: " + verb_msg 33 | print "Scan date: " + scan_date 34 | print "\nMalicious Detects: " + str(evilness) + "/" + str(totaleng) 35 | print "\nAV detections\n" 36 | detected = [] 37 | undetected = [] 38 | for scanner in scanners: 39 | avreport = report.get("scans", {}).get(scanner, {}).get("result") 40 | avversion = report.get("scans", {}).get(scanner, {}).get("version") 41 | if avreport == None: 42 | undetected.append(scanner + " / " + avversion) 43 | else: 44 | detected.append(scanner + " / " + avversion + "\t\tDetection: " + str(avreport)) 45 | 46 | print "Successful detections: " 47 | for good in detected: 48 | print "\t" + good 49 | 50 | print "\nUnsuccessful at detection: " 51 | for bad in undetected: 52 | print "\t" + bad 53 | 54 | print "\nPermalink: " + permalink 55 | 56 | 57 | def load_apikey(): 58 | """Load our API key from file""" 59 | user = getpass.getuser() 60 | fullpath = '/home/' + user 61 | try: 62 | keyfile = open(fullpath + '/.virustotal.key', 'r') 63 | except: 64 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.virustotal.key") 65 | 66 | for line in keyfile: 67 | vtkey = line.rstrip() 68 | keyfile.close() 69 | return vtkey 70 | 71 | 72 | def __main__(): 73 | """basic menu system""" 74 | parser = argparse.ArgumentParser(description='virustotal.com hash checker', usage='%(prog)s -H hash') 75 | parser.add_argument('--hash', '-H', dest='hash', help='hash to check') 76 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.2') 77 | args = parser.parse_args() 78 | ahash = args.hash 79 | 80 | if not args.hash: 81 | sys.exit(parser.print_help()) 82 | 83 | hashcheck(ahash) 84 | 85 | 86 | if __name__ == '__main__': 87 | __main__() 88 | -------------------------------------------------------------------------------- /Malware/Web/README.md: -------------------------------------------------------------------------------- 1 | Web Malware 2 | =========== 3 | 4 | Web malware related code. Mostly to automate stuff or to learn something. 5 | 6 | Consider stuff in this directory very janky. 7 | 8 | -------------------------------------------------------------------------------- /Malware/Web/php_decode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Simple PHP malware decoder. 4 | 5 | import argparse 6 | import sys 7 | import base64 8 | import zlib 9 | import codecs 10 | 11 | 12 | def base64_decode(arg_file): 13 | """Base64 decode the blob of data""" 14 | print " decoding base64 data..." 15 | inputfile = open(arg_file, 'r') 16 | for line in inputfile: 17 | to_rot13 = base64.b64decode(line) 18 | inputfile.close() 19 | unrot13(to_rot13) 20 | 21 | 22 | def unrot13(to_rot13): 23 | """Derot13 the data passed to us from the base64 decode process""" 24 | print " rotating 13 the other way..." 25 | unrot13_out = codecs.decode(to_rot13, 'rot13') 26 | gzip_inflate(unrot13_out) 27 | 28 | 29 | def gzip_inflate(unrot13_out): 30 | """Gzip inflate the data from the unrot13 process""" 31 | print " inflating the data..." 32 | gzip_output = zlib.decompress(unrot13_out) 33 | printoutput(gzip_output) 34 | 35 | 36 | def printoutput(gzip_output, arg_output): 37 | """Print the output out to the console""" 38 | print " printing output" 39 | output = file(arg_output, 'w') 40 | output.write(gzip_output) 41 | output.close() 42 | print "file written to " + arg_output 43 | print "we're done here." 44 | 45 | 46 | def __main__(): 47 | """Get this party started here 48 | Basic menu system""" 49 | parser = argparse.ArgumentParser(description='basic menu system', usage='%(prog)s -f file') 50 | parser.add_argument('--file', '-f', dest='filein', help='file to examine') 51 | parser.add_argument('--output', '-o', dest='fileout', help='write to file') 52 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 53 | args = parser.parse_args() 54 | arg_file = args.filein 55 | arg_output = args.fileout 56 | 57 | if not args.filein: 58 | sys.exit(parser.print_help()) 59 | 60 | print "examining file " 61 | print "(" + arg_file + ")" 62 | base64_decode(arg_file) 63 | 64 | 65 | if __name__ == '__main__': 66 | __main__() 67 | -------------------------------------------------------------------------------- /Malware/Web/webshellfind.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Very simple web shell finder 4 | # from here http://pentestlab.org/hunting-malicious-perl-irc-bots/ 5 | 6 | PATH=$1 7 | 8 | echo "Scanning $PATH" 9 | echo -n "Scanning for " 10 | echo -n "tcp, " 11 | /bin/grep -Rn "tcp *(" $PATH 12 | echo -n "system, " 13 | /bin/grep -Rn "system *(" $PATH 14 | echo -n "shell." 15 | /bin/grep -Rn "shell *(" $PATH 16 | echo -n "shell_exec." 17 | /bin/grep -Rn “shell_exec *(” $PATH 18 | echo -n "base64_decode." 19 | /bin/grep -Rn “base64_decode *(” $PATH 20 | echo -n "phpinfo." 21 | /bin/grep -Rn “phpinfo *(” $PATH 22 | echo -n "php_uname." 23 | /bin/grep -Rn “php_uname *(” $PATH 24 | echo -n "chmod." 25 | /bin/grep -Rn “chmod *(” $PATH 26 | echo -n "fopen." 27 | /bin/grep -Rn “fopen *(” $PATH 28 | echo -n "fclose." 29 | /bin/grep -Rn “fclose *(” $PATH 30 | echo -n "readfile." 31 | /bin/grep -Rn “readfile *(” $PATH 32 | echo -n "edoced_46esab." 33 | /bin/grep -Rn “edoced_46esab *(” $PATH 34 | echo -n "eval." 35 | /bin/grep -Rn “eval *(” $PATH 36 | echo -n "passthru." 37 | /bin/grep -Rn “passthru *(” $PATH 38 | 39 | echo "We're done here" 40 | -------------------------------------------------------------------------------- /Malware/b64decode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple base64 decoder 3 | 4 | import sys 5 | import argparse 6 | 7 | def b64decode(adecode): 8 | """Decode base64 stuff given to us""" 9 | print "Decoding: " + adecode 10 | try: 11 | print adecode.decode("base64") 12 | except Exception, err: 13 | sys.exit("Error: %s" % str(err)) 14 | 15 | def b64encode(aencode): 16 | """Encode stuff given to us into base64""" 17 | print "Encoding: " + aencode 18 | try: 19 | print aencode.encode("base64") 20 | except Exception, err: 21 | sys.exit("Error: %s" % str(err)) 22 | 23 | def __main__(): 24 | 25 | parser = argparse.ArgumentParser(description='basic base64 {en,de}coder', usage='%(prog)s -e stuff / -d stuff') 26 | parser.add_argument('--decode', '-d', dest='decode', help='stuff to decode') 27 | parser.add_argument('--encode', '-e', dest='encode', help='stuff to encode') 28 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.2') 29 | args = parser.parse_args() 30 | adecode = args.decode 31 | aencode = args.encode 32 | 33 | if args.decode: 34 | b64decode(adecode) 35 | elif args.encode: 36 | b64encode(aencode) 37 | else: 38 | sys.exit(parser.print_help()) 39 | 40 | 41 | if __name__ == '__main__': 42 | __main__() 43 | -------------------------------------------------------------------------------- /Malware/expandshorturl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to expand a short url using the http://longurl.org API 3 | 4 | import sys 5 | import argparse 6 | import requests 7 | 8 | 9 | def urlparse(aurl): 10 | """Send our URL off for parsing""" 11 | headers = { "User-Agent" :"shorturl-parser-v1" } 12 | payload = { 'url' : aurl, 'format' : "json" } 13 | request = requests.get("http://api.longurl.org/v2/expand?%s", params=payload) 14 | scode = request.status_code 15 | if scode == 400: 16 | sys.exit("We errored out: %s" % scode) 17 | elif scode == 500: 18 | print scode, 19 | sys.exit("We errored out: %s" % scode) 20 | elif scode == 400: 21 | print scode, 22 | sys.exit("We errored out: %s" % scode) 23 | elif scode == 200: 24 | data = request.json() 25 | report = data.get("long-url", {}) 26 | print "Expanding: " + aurl + " <~> "+ report 27 | 28 | 29 | def __main__(): 30 | """Get this party started""" 31 | parser = argparse.ArgumentParser(description='Short URL expander using longurl.org', usage='%(prog)s -u URL') 32 | parser.add_argument('--url', '-u', dest='url', help='url to expand') 33 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.2') 34 | args = parser.parse_args() 35 | aurl = args.url 36 | 37 | if not args.url: 38 | sys.exit(parser.print_help()) 39 | 40 | urlparse(aurl) 41 | 42 | if __name__ == '__main__': 43 | __main__() 44 | -------------------------------------------------------------------------------- /Malware/geolookup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple GeoIP DB lookup 3 | 4 | import argparse 5 | import sys 6 | import os 7 | import geoip2.database 8 | 9 | def checkip(): 10 | """Check the IP address against our DB""" 11 | print "Checking IP's" 12 | 13 | 14 | def checkdb(): 15 | """Check that our DB files exist""" 16 | print "Checking databases" 17 | 18 | fullpath = os.getenv("HOME") 19 | try: 20 | dbfile = open(fullpath + '/.glcountry.mmdb', 'r') 21 | except: 22 | sys.exit("** ERROR ** \n> Database file not found. Please check ~/.glcountry.mmdb") 23 | 24 | reader = geoip2.database.Reader(dbfile) 25 | response = reader.city('128.101.101.101') 26 | isocode = response.country.iso_code 27 | countryname = response.country.name 28 | cityname = response.city.name 29 | 30 | print "isocode " + isocode 31 | print "countryname " + countryname 32 | print "city " + cityname 33 | 34 | #checkip() 35 | 36 | 37 | def __main__(): 38 | 39 | parser = argparse.ArgumentParser(description='basic GeoIP system', usage='%(prog)s -i IP address') 40 | parser.add_argument('--ip', '-i', dest='ip', help='IP address to lookup') 41 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 42 | args = parser.parse_args() 43 | aip = args.ip 44 | 45 | if not args.ip: 46 | sys.exit(parser.print_help()) 47 | 48 | checkdb() 49 | 50 | 51 | if __name__ == '__main__': 52 | __main__() 53 | -------------------------------------------------------------------------------- /Malware/lazyconverter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Simple ascii to hex / hex to ascii converter 4 | 5 | # code @ zonbi dot org 6 | 7 | import binascii 8 | import sys 9 | import argparse 10 | 11 | class Converter(object): 12 | """Convert stuff""" 13 | 14 | def convert_to_ascii(self): 15 | print "converting hex to ascii" 16 | print "hex: " + con_string 17 | #output = binascii.hexlify(con_string) 18 | output = con_string.decode("hex") 19 | print "ascii: " 20 | 21 | def convert_to_hex(self): 22 | print "converting ascii to hex" 23 | print "ascii: " + con_string 24 | output = con_string.encode("hex") 25 | print "hex: " + output 26 | 27 | def main(): 28 | parser = argparse.ArgumentParser(description='basic converter', usage='%(prog)s -x/-a -s INPUT') 29 | parser.add_argument('--ascii', '-a', dest='ascii', action='store_true', help='convert to ascii') 30 | parser.add_argument('--hex', '-x', dest='hex', action='store_true', help='convert to hex') 31 | parser.add_argument('--string', '-s', dest='constring', help='string to convert') 32 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 33 | args = parser.parse_args() 34 | 35 | if len(sys.argv) == 1: 36 | sys.exit(parser.print_help()) 37 | 38 | global arg_ascii 39 | global arg_hex 40 | global con_string 41 | arg_ascii = args.ascii 42 | arg_hex = args.hex 43 | con_string = args.constring 44 | 45 | if args.ascii: 46 | con = Converter() 47 | con.convert_to_ascii() 48 | elif args.hex: 49 | con = Converter() 50 | con.convert_to_hex() 51 | else: 52 | sys.exit(parser.print_help()) 53 | 54 | 55 | 56 | if __name__ == '__main__': 57 | main() -------------------------------------------------------------------------------- /Malware/uberhexparser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # no not really...this is a fucking ugly hack 3 | 4 | import argparse 5 | import sys 6 | 7 | 8 | def splitstring(line, length): 9 | """split the raw string up into 2 byte chars""" 10 | 11 | sys.stdout.write("splitting, ") 12 | return ' '.join(line[i: i + length] for i in xrange(0, len(line), length)) 13 | 14 | 15 | def addsecretsauce(fin): 16 | """add hex chars so we can parse properly""" 17 | 18 | sys.stdout.write("hexing, ") 19 | return fin.replace(" ", "\\x") 20 | 21 | 22 | def snipper(nomoresecrets): 23 | """tidying up unneeded crap""" 24 | 25 | match = '\\x' 26 | sys.stdout.write("tidying up, ") 27 | sys.stdout.write("topping, ") 28 | addheader = ''.join(('\\x', nomoresecrets)) 29 | sys.stdout.write("tailing") 30 | removetail = addheader 31 | return ('\n'.join((line[:-len(match)] if line.endswith(match) else line) 32 | for line in removetail.splitlines())) 33 | 34 | 35 | def dumptofile(fout): 36 | """write our newly hacked file to our output file""" 37 | 38 | print "\ndumping to file: " + afileout 39 | fwrite = open(afileout, 'w') 40 | fwrite.write(fout) 41 | fwrite.close() 42 | 43 | 44 | def doshit(line, afileout): 45 | """this is where we mix magic""" 46 | 47 | fin = splitstring(line, 2) 48 | trim = addsecretsauce(fin) 49 | fout = snipper(trim) 50 | sys.stdout.write("...done") 51 | dumptofile(fout) 52 | print "and I'm spent..." 53 | 54 | 55 | def main(): 56 | """get this party started""" 57 | 58 | parser = argparse.ArgumentParser(description='convert raw ascii to hex', usage='%(prog)s -f file') 59 | parser.add_argument('--input', '-i', dest='filein', help='input file') 60 | parser.add_argument('--output', '-o', dest='fileout', help='output file') 61 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 62 | args = parser.parse_args() 63 | afilein = args.filein 64 | global afileout 65 | afileout = args.fileout 66 | 67 | if not afilein: 68 | sys.exit(parser.print_help()) 69 | 70 | print "Getting started..." 71 | parseme = open(afilein, 'r') 72 | for line in parseme: 73 | doshit(line, afileout) 74 | parseme.close() 75 | 76 | if __name__ == '__main__': 77 | main() 78 | -------------------------------------------------------------------------------- /Malware/xorer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # simple script to XOR encrypt / decrypt text with a key 4 | 5 | import argparse 6 | import sys 7 | from itertools import izip, cycle 8 | 9 | def main(): 10 | parser = argparse.ArgumentParser(description='xor or unxor text', usage='%(prog)s -i inputfile -k key -o outputfile') 11 | parser.add_argument('--encrypt', '-e', action='store_true',dest='encrypt', help='encrypt data') 12 | parser.add_argument('--decrypt', '-d', action='store_true',dest='decrypt', help='decrypt data') 13 | parser.add_argument('--input', '-i', dest='infile', help='file for input') 14 | parser.add_argument('--key', '-k', dest='xorkey', help='key to use') 15 | parser.add_argument('--output', '-o', dest='outfile', help='file for output') 16 | args = parser.parse_args() 17 | 18 | if len(sys.argv) == 1: 19 | parser.print_help() 20 | sys.exit(1) 21 | 22 | global infile 23 | global xorkey 24 | global outfile 25 | infile = args.infile 26 | xorkey = args.xorkey 27 | outfile = args.outfile 28 | 29 | # basic error checking 30 | if not args.infile: 31 | parser.print_help() 32 | sys.exit(1) 33 | 34 | # basic error checking 35 | if not args.infile: 36 | parser.print_help() 37 | sys.exit(1) 38 | 39 | # basic error checking 40 | if not args.xorkey: 41 | parser.print_help() 42 | sys.exit(1) 43 | 44 | # basic error checking 45 | if not args.outfile: 46 | parser.print_help() 47 | sys.exit(1) 48 | 49 | # basic error checking FIX THIS 50 | #if not args.encrypt or not args.decrypt: 51 | # parser.print_help() 52 | # sys.exit(1) 53 | 54 | # do encryption 55 | if args.encrypt: 56 | print "encrypting" 57 | xor_encrypt() 58 | 59 | # do decryption 60 | if args.decrypt: 61 | print "decrypting" 62 | xor_decrypt() 63 | 64 | 65 | def xor_crypt_string(data, key): 66 | return ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(data, cycle(key))) 67 | 68 | def xor_encrypt(): 69 | global encrypted 70 | encrypted = open(infile, 'r') 71 | file_out = open(outfile, 'w') 72 | 73 | print "key: " + xorkey 74 | for line in encrypted: 75 | encrypt_line = xor_crypt_string(line, key=xorkey) 76 | file_out.write(encrypt_line) 77 | 78 | file_out.close() 79 | encrypted.close() 80 | print "done." 81 | 82 | def xor_decrypt(): 83 | global encrypted 84 | decrypted = open(infile, 'r') 85 | file_out = open(outfile, 'w') 86 | 87 | print "key: " + xorkey 88 | for line in decrypted: 89 | decrypt_line = xor_crypt_string(line, key=xorkey) 90 | file_out.write(decrypt_line) 91 | 92 | decrypted.close() 93 | file_out.close() 94 | print "done." 95 | 96 | if __name__ == '__main__': 97 | main() -------------------------------------------------------------------------------- /Networking/dns-cachesnoop.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # DNS Cache snooping with Scapy 3 | 4 | import argparse 5 | import sys 6 | import logging 7 | logging.getLogger("scapy.runtime").setLevel(logging.ERROR) 8 | from scapy.all import * 9 | 10 | def dnssnoop(adomains, aresolver): 11 | """Check the server for hosts in our list""" 12 | 13 | domains = open(adomains, 'r') 14 | for host in domains: 15 | nhost = host.rstrip('\n') 16 | dnsquery = sr1(IP(dst=aresolver)/UDP()/DNS(rd=0,qd=DNSQR(qname=nhost)),verbose=0) 17 | if "root-servers" in dnsquery[DNSRR].rdata: 18 | print "Not cached: %s" % nhost 19 | else: 20 | print "Cached: " + dnsquery[DNSRR].rrname + "\t\t\tResponse: " + dnsquery[DNSRR].rdata 21 | domains.close() 22 | 23 | def __main__(): 24 | 25 | parser = argparse.ArgumentParser(description='dns cache snooping', usage='%(prog)s -d domains.txt') 26 | parser.add_argument('--domains', '-d', dest='domains', help='file with domains to check') 27 | parser.add_argument('--resolver', '-r', dest='resolver', help='DNS server to use') 28 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 29 | args = parser.parse_args() 30 | adomains = args.domains 31 | aresolver = args.resolver 32 | 33 | if not args.domains and not args.resolver: 34 | sys.exit(parser.print_help()) 35 | 36 | dnssnoop(adomains, aresolver) 37 | 38 | 39 | if __name__ == '__main__': 40 | __main__() 41 | -------------------------------------------------------------------------------- /Networking/dns-test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple DNS test system 3 | # Tests the records in a file against the actual 4 | # DNS queries for that specific host. 5 | # Format for input: DNSQUERYTYPE:FQDN:IP 6 | # Example: A:www.zonbi.org:192.168.0.1 7 | 8 | import argparse 9 | import sys 10 | import socket 11 | from dns import resolver,reversename, name 12 | 13 | 14 | def loadfile(afile): 15 | """Load our file to pull zone info from""" 16 | print "Resolver: " + adnsserver 17 | fh = open(afile, 'r') 18 | for line in fh: 19 | hostentry = line.rstrip() 20 | entry = hostentry.split(":", 2) 21 | lookup = entry[0] 22 | host = entry[1] 23 | fip = entry[2] 24 | if lookup == "PTR": 25 | print lookup + " record " + host, 26 | do_reverse_check(lookup, fip, host) 27 | else: 28 | print lookup + " record " + host + " (" + fip + ")", 29 | do_check(lookup, fip, host) 30 | fh.close() 31 | 32 | 33 | def do_reverse_check(lookup, fip, host): 34 | """Do PTR record checks""" 35 | hostfromdns = name.from_text(fip) 36 | if str(hostfromdns) == str(fip): 37 | print " [OK] " 38 | else: 39 | print " [ERROR!! DNS:" + str(hostfromdns) + " FILE: " + fip + "] " 40 | 41 | 42 | def do_check(lookup, fip, host): 43 | """Do the actual check of file against DNS""" 44 | dnsresult = dns_query(adnsserver, lookup, host) 45 | if str(dnsresult) == str(fip): 46 | print " [OK] " 47 | else: 48 | print " [ERROR!! DNS:" + str(dnsresult) + " FILE: " + fip + "] " 49 | 50 | 51 | def dns_query(adnsserver, lookup, host): 52 | """Perform DNS query""" 53 | dresolver = resolver.Resolver() 54 | check_dnsserver = adnsserver 55 | try: 56 | socket.inet_aton(check_dnsserver) 57 | cdnsserver = check_dnsserver 58 | except: 59 | cdnsserver = socket.gethostbyname(check_dnsserver) 60 | 61 | dresolver.nameservers = [cdnsserver] 62 | ans = dresolver.query(host, lookup) 63 | try: 64 | for rdata in ans: 65 | return rdata 66 | except Exception as e: 67 | print "Error: %s" % e 68 | 69 | 70 | def __main__(): 71 | 72 | parser = argparse.ArgumentParser(description='basic menu system') 73 | parser.add_argument('--file', '-f', dest='file', default='zones.txt', help='File with DNS entries to check') 74 | parser.add_argument('--server', '-s', dest='dnsserver', default='8.8.8.8', help='DNS server to query') 75 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 76 | args = parser.parse_args() 77 | afile = args.file 78 | global adnsserver 79 | adnsserver = args.dnsserver 80 | 81 | if not args.file: 82 | sys.exit(parser.print_help()) 83 | 84 | loadfile(afile) 85 | 86 | 87 | if __name__ == '__main__': 88 | __main__() 89 | 90 | -------------------------------------------------------------------------------- /Networking/dnsquery.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Basic DNS query system 3 | 4 | import argparse 5 | import sys 6 | import dns.resolver 7 | import dns.reversename 8 | 9 | 10 | def rdnsquery(aip): 11 | """Perform reverse DNS query for IP address""" 12 | # Not exactly what I'm after 13 | print dns.reversename.from_address(aip) 14 | 15 | 16 | def dnsquery(ahost, aqtype): 17 | """Perform DNS queries""" 18 | dresolver = dns.resolver.Resolver() 19 | dresolver.nameservers = [adnsserver] 20 | ans = dresolver.query(ahost, aqtype) 21 | if aqtype == "MX": 22 | try: 23 | for rdata in ans: 24 | print '>>', rdata.exchange, '\tweight:', rdata.preference 25 | except Exception as e: 26 | print "Error: %s" % e 27 | else: 28 | try: 29 | for rdata in ans: 30 | print rdata.address 31 | except Exception as e: 32 | print "Error: %s" % e 33 | 34 | def __main__(): 35 | """Get this party started""" 36 | parser = argparse.ArgumentParser(description='basic dns query system', usage='%(prog)s -f file -t ') 37 | parser.add_argument('--file', '-f', dest='filein', help='file to pull hosts from') 38 | parser.add_argument('--host', '-H', dest='host', help='Hostname to query') 39 | parser.add_argument('--server', '-s', dest='dnsserver', default='8.8.8.8', help='DNS server to query') 40 | parser.add_argument('--ip', '-i', dest='ip', help='IP address to query') 41 | parser.add_argument('--type', '-t', dest='query', help='DNS query type') 42 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 43 | args = parser.parse_args() 44 | afile = args.filein 45 | aip = args.ip 46 | ahost = args.host 47 | aqtype = args.query 48 | global adnsserver 49 | adnsserver = args.dnsserver 50 | 51 | #if not args.filein: 52 | # sys.exit(parser.print_help()) 53 | 54 | if args.host: 55 | dnsquery(ahost, aqtype) 56 | elif args.ip: 57 | rdnsquery(aip) 58 | 59 | 60 | if __name__ == '__main__': 61 | __main__() 62 | 63 | -------------------------------------------------------------------------------- /Networking/dnsresolve-v2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Pull DNS entries from a hosts list 3 | 4 | import argparse 5 | import dns.resolver 6 | import dns.reversename 7 | import socket 8 | 9 | 10 | def dnsquery(ahost, adnsserver, aoutput): 11 | """Perform DNS queries""" 12 | dresolver = dns.resolver.Resolver() 13 | dresolver.nameservers = [adnsserver] 14 | fout = open(aoutput, 'a') 15 | try: 16 | ans = dresolver.query(ahost) 17 | for rdata in ans: 18 | print "[*] DNS Record found : ", 19 | rhost = rdata.address 20 | print "Opening socket: " + rhost, 21 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 22 | result = sock.connect_ex((rhost,443)) 23 | if result == 0: 24 | print " : Port open. Adding to file :)" 25 | fout.write(rhost + '\n') 26 | else: 27 | print " : Port closed." 28 | sock.close() 29 | 30 | except dns.exception.DNSException as e: 31 | if isinstance(e, dns.resolver.NoNameservers): 32 | print "[*] No name server record: %s " % ahost 33 | 34 | 35 | def fileparse(ahost, adnsserver, afile, aoutput): 36 | """Pull hosts from a file""" 37 | print "Dumping to file: " + aoutput 38 | fh = open(afile, 'r') 39 | for line in fh: 40 | qhost = line.rstrip() 41 | dnsquery(qhost, adnsserver, aoutput) 42 | 43 | fh.close() 44 | print "We're done here" 45 | 46 | def __main__(): 47 | """Get this party started""" 48 | parser = argparse.ArgumentParser(description='basic dns query system', usage='%(prog)s -f file -t ') 49 | parser.add_argument('--file', '-f', dest='filein', help='file to pull hosts from') 50 | parser.add_argument('--output', '-o', dest='output', help='file to dump results to') 51 | parser.add_argument('--host', '-H', dest='host', help='Hostname to query') 52 | parser.add_argument('--server', '-s', dest='dnsserver', default='8.8.8.8', help='DNS server to query') 53 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 54 | args = parser.parse_args() 55 | afile = args.filein 56 | ahost = args.host 57 | aoutput = args.output 58 | global adnsserver 59 | adnsserver = args.dnsserver 60 | 61 | 62 | if args.filein: 63 | fileparse(ahost, adnsserver, afile, aoutput) 64 | else: 65 | dnsquery(ahost, adnsserver, aoutput) 66 | 67 | 68 | if __name__ == '__main__': 69 | __main__() 70 | -------------------------------------------------------------------------------- /Networking/domaincheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple IP check script 3 | 4 | import argparse 5 | import sys 6 | import dns.resolver 7 | import dns.reversename 8 | import whois 9 | 10 | 11 | def check_dns(ahost, anameserver): 12 | """Check DNS entry for hostname""" 13 | dresolver = dns.resolver.Resolver() 14 | dresolver.nameservers = [anameserver] 15 | dresolver.timeout = 3 16 | print "DNS Resolver: " + anameserver 17 | ans = dresolver.query(ahost) 18 | try: 19 | for rdata in ans: 20 | return rdata.address 21 | except Exception as e: 22 | print "Error: %s" % e 23 | 24 | 25 | def check_reverse(dns_check): 26 | """Check the reverse DNS for the IP given in DNS""" 27 | addr = dns.reversename.from_address(dns_check) 28 | reverse = dns.resolver.query(addr, "PTR")[0] 29 | return reverse 30 | 31 | 32 | def check_whois(ahost): 33 | """Check whois for the domain""" 34 | domain = ahost.partition('.')[2] 35 | domain = whois.query(ahost) 36 | print "Whois information:" 37 | print "Registrar: " + str(domain.registrar) 38 | print "Creation date: " + str(domain.creation_date) 39 | print "Expiration date: " + str(domain.expiration_date) 40 | print "Name servers: " 41 | for ns_servers in domain.name_servers: 42 | print "\t" + ns_servers 43 | 44 | 45 | 46 | def run_checks(ahost, anameserver): 47 | """All our checks start here""" 48 | dns_check = check_dns(ahost, anameserver) 49 | print "DNS Check: " + dns_check 50 | reverse_dns = check_reverse(dns_check) 51 | print "Reverse IP: " + str(reverse_dns) 52 | whois_check = check_whois(ahost) 53 | 54 | 55 | def __main__(): 56 | 57 | parser = argparse.ArgumentParser(description='Simple hostname check script') 58 | parser.add_argument('--host', '-H', dest='host', help='hostname to check') 59 | parser.add_argument('--nameserver', '-n', dest='nameserver', default='8.8.8.8', help='nameserver to check against') 60 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 61 | args = parser.parse_args() 62 | ahost = args.host 63 | anameserver = args.nameserver 64 | 65 | if not args.host: 66 | sys.exit(parser.print_help()) 67 | 68 | print "Checking: " + ahost 69 | run_checks(ahost, anameserver) 70 | 71 | 72 | if __name__ == '__main__': 73 | __main__() 74 | -------------------------------------------------------------------------------- /Networking/ftp-check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple FTP check script 3 | 4 | import argparse 5 | import sys 6 | import ftplib 7 | import errno 8 | import socket 9 | 10 | 11 | def check_ftp(rhost): 12 | """Log into FTP server""" 13 | try: 14 | ftp = ftplib.FTP(rhost, timeout=10) 15 | except socket.error as e: 16 | print "Problem connecting...moving on" 17 | problem_hosts.append(rhost) 18 | else: 19 | try: 20 | ftp.login() 21 | except ftplib.error_perm as e: 22 | print "something went horribly wrong with logging in." 23 | problem_hosts.append(rhost) 24 | print ftp.getwelcome() 25 | try: 26 | ftp.retrlines('LIST') 27 | except ftplib.error_perm as e: 28 | print "Something went horribly wrong with directory listing." 29 | problem_hosts.append(rhost) 30 | ftp.quit() 31 | print "Done.\n" 32 | 33 | return problem_hosts 34 | 35 | 36 | def load_file(afile): 37 | """Load our servers from file""" 38 | with open(afile, 'r') as fh: 39 | global problem_hosts 40 | problem_hosts = [] 41 | for line in fh: 42 | rhost = line.rstrip() 43 | print "Checking: " + rhost + " >>", 44 | checks = check_ftp(rhost) 45 | 46 | print "[*] Scanning complete" 47 | print "\n[*] Problems with the following hosts: " 48 | for host in checks: 49 | print "\t" + host 50 | 51 | print "\nWe're done here" 52 | 53 | 54 | def __main__(): 55 | """Get this party started""" 56 | parser = argparse.ArgumentParser(description='Simple FTP check script') 57 | parser.add_argument('--file', '-f', dest='file', help='Pull our FTP server list from this file') 58 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 59 | args = parser.parse_args() 60 | afile = args.file 61 | 62 | if not args.file: 63 | sys.exit(parser.print_help()) 64 | else: 65 | load_file(afile) 66 | 67 | 68 | if __name__ == '__main__': 69 | __main__() 70 | -------------------------------------------------------------------------------- /Networking/header-grab.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to grab the headers from a bunch of hosts 3 | 4 | import argparse 5 | import sys 6 | import requests 7 | 8 | 9 | def list_headers(): 10 | """Dump a list of known headers""" 11 | print "Some common headers to check for\n" 12 | headers = ['Accept', 'Accept-Encoding', 'Authorization', 'Cache-Control', 'Cookie', 'Content-Type', 13 | 'Host', 'User-agent', 'Via', 'Server', 'P3P', 'Status'] 14 | 15 | for header in headers: 16 | print header 17 | sys.exit("\nWe're done here") 18 | 19 | 20 | def pull_headers(ahost, aheader): 21 | """Pull the headers from our host URL""" 22 | print "Checking: " + ahost + " -> ", 23 | try: 24 | req = requests.get(ahost, verify=False, timeout=60) 25 | except Exception, err: 26 | print "Something has gone horribly wrong: %s" % err 27 | 28 | if req.status_code == 200: 29 | print req.headers[aheader] 30 | else: 31 | print "Status code: " + str(req.status_code) 32 | 33 | 34 | def parse_file(ainfile, aheader): 35 | """Parse our input file""" 36 | try: 37 | print "Parsing input file" 38 | with open(ainfile, 'r') as fh: 39 | for host in fh: 40 | pull_headers(str(host.strip()), aheader) 41 | except Exception, err: 42 | sys.exit("[ERROR] Something has gone horribly wrong: %s" % err) 43 | 44 | 45 | def __main__(): 46 | """Get this party started""" 47 | parser = argparse.ArgumentParser(description='HTTP Header Grabber') 48 | parser.add_argument('--infile', '-f', dest='infile', help='Input file of hosts') 49 | parser.add_argument('--header', '-H', dest='header', default='server', help='Header to check') 50 | parser.add_argument('--supported-headers', '-l', dest='listing', action='store_true', help='List common headers') 51 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 52 | args = parser.parse_args() 53 | ainfile = args.infile 54 | aheader = args.header 55 | alisting = args.listing 56 | 57 | if args.listing: 58 | list_headers() 59 | 60 | if not args.infile: 61 | sys.exit(parser.print_help()) 62 | else: 63 | parse_file(ainfile, aheader) 64 | 65 | 66 | if __name__ == '__main__': 67 | __main__() 68 | 69 | -------------------------------------------------------------------------------- /Networking/imaptester.py: -------------------------------------------------------------------------------- 1 | # Simple IMAP Test Script 2 | 3 | from imapclient import IMAPClient 4 | import argparse 5 | import sys 6 | 7 | 8 | def testserver(aserver, aport, auser, apassword): 9 | """Do work""" 10 | server = IMAPClient(aserver, aport, use_uid=True, ssl=False) 11 | print "Logging in" 12 | try: 13 | server.login(auser, apassword) 14 | except Exception: 15 | print "\n *** Something has gone horribly wrong ***\n" 16 | else: 17 | print "\n Great Success !\n" 18 | pass 19 | 20 | select_info = server.select_folder('INBOX') 21 | print '%d messages in INBOX' % select_info['EXISTS'] 22 | 23 | messages = server.search(['NOT DELETED']) 24 | print "%d messages that aren't deleted" % len(messages) 25 | 26 | print "\n Message Summary:" 27 | response = server.fetch(messages, ['FLAGS', 'RFC822.SIZE']) 28 | for msgid, data in response.iteritems(): 29 | print ' ID %d: %d bytes, flags=%s' % (msgid, 30 | data['RFC822.SIZE'], 31 | data['FLAGS']) 32 | 33 | sys.exit("\nWe're done here") 34 | 35 | 36 | def __main__(): 37 | 38 | parser = argparse.ArgumentParser(description='Simple imap tester', usage='%(prog)s -s server -p port -u user -P password') 39 | parser.add_argument('--server', '-s', dest='server', help='server to test') 40 | parser.add_argument('--port', '-p', dest='port', help='port to use') 41 | parser.add_argument('--user', '-u', dest='user', help='username') 42 | parser.add_argument('--password', '-P', dest='password', help='password') 43 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 44 | args = parser.parse_args() 45 | aserver = args.server 46 | aport = args.port 47 | auser = args.user 48 | apassword = args.password 49 | 50 | if not args.server: 51 | sys.exit(parser.print_help()) 52 | 53 | print "" 54 | print "Starting IMAP Tester" 55 | testserver(aserver, aport, auser, apassword) 56 | 57 | 58 | if __name__ == '__main__': 59 | __main__() 60 | -------------------------------------------------------------------------------- /Networking/ipchicken.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Grab my external IP address 3 | # parts of this was borrowed from 4 | # http://johnklann.com/python-how-to-get-external-ip-address/ 5 | 6 | import urllib 7 | import re 8 | from socket import gethostbyaddr 9 | 10 | URL="http://ipchicken.com" 11 | 12 | request = urllib.urlopen(URL).read() 13 | ip = re.findall(r'[0-9]+(?:\.[0-9]+){3}', request) 14 | hostname = gethostbyaddr(str((ip[0]))) 15 | print "[*] external ip: " + str(ip[0]) 16 | print "[*] hostname: " + str(hostname[0]) 17 | 18 | -------------------------------------------------------------------------------- /Networking/libwww-python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple implementation of libwww-perl in Python 3 | 4 | import argparse 5 | import sys 6 | import requests 7 | 8 | 9 | def getrequest(aurl, req): 10 | """Make actual request""" 11 | if req == "GET": 12 | resp = requests.get(aurl) 13 | print ">> GET: " + resp.url 14 | elif req == "POST": 15 | resp = requests.get(aurl) 16 | print ">> POST: " + resp.url 17 | 18 | return resp 19 | 20 | 21 | def headers(): 22 | """Grab HTTP Headers""" 23 | if aget: 24 | data = getrequest(aurl, req="GET") 25 | if apost: 26 | data = getrequest(aurl, req="POST") 27 | print " < Status Code: " + str(data.status_code) 28 | print "\n<< Response" 29 | print " Headers: " 30 | headers = data.headers 31 | for key, value in headers.items(): 32 | print " < " + key + ": " + value 33 | 34 | 35 | 36 | def __main__(): 37 | """Get this party started""" 38 | parser = argparse.ArgumentParser(description='libwww-perl buti in python', usage='%(prog)s --help') 39 | parser.add_argument('--url', '-u', dest='url', help='url to do stuff to') 40 | parser.add_argument('--get', '-G', dest='get', action='store_true', help='GET request') 41 | parser.add_argument('--post', '-P', dest='post', action='store_true', help='POST request') 42 | parser.add_argument('--data', '-d', dest='data', help='data for POST request') 43 | parser.add_argument('--headers', '-H', dest='headers', action='store_true', help='print headers') 44 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 45 | args = parser.parse_args() 46 | global aurl 47 | aurl = args.url 48 | global aget 49 | aget = args.get 50 | global apost 51 | apost = args.post 52 | adata = args.data 53 | aheaders = args.headers 54 | 55 | if not args.url: 56 | sys.exit(parser.print_help()) 57 | 58 | if args.headers: 59 | headers() 60 | 61 | 62 | if __name__ == '__main__': 63 | __main__() 64 | 65 | -------------------------------------------------------------------------------- /Networking/listener.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Simple python listener 4 | # Bugs ? code@zonbi.org 5 | 6 | import socket, sys 7 | 8 | if len(sys.argv) < 4: 9 | sys.exit("Usage: " + sys.argv[0] + " ") 10 | 11 | lproto = sys.argv[1] 12 | lport = int(sys.argv[2]) 13 | outfile = sys.argv[3] 14 | 15 | print "Firing up "+ lproto + " listener on ", lport 16 | print "Writing to file", outfile 17 | print "-------------------------------------" 18 | 19 | if lproto == "tcp": 20 | proto = socket.SOCK_STREAM 21 | elif lproto == "udp": 22 | proto = socket.SOCK_DGRAM 23 | else: 24 | sys.exit("Wrong protocol.") 25 | 26 | socket = socket.socket(socket.AF_INET,proto) 27 | socket.bind(('', lport)) 28 | socket.listen(5) 29 | 30 | while 1: 31 | connection, addr = socket.accept() 32 | print "New connection from: ", addr 33 | data = connection.recv(1024) 34 | connection.close() 35 | print "Data received: ", data 36 | outputfile = open(outfile, "a") 37 | outputfile.write(data) 38 | 39 | socket.close() 40 | outputfile.close() 41 | -------------------------------------------------------------------------------- /Networking/mass-geoiplookup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Mass geoip lookups 3 | 4 | import argparse 5 | import sys 6 | import os 7 | import geoip2.database 8 | 9 | 10 | def geoip_lookup(ipaddr): 11 | """Perform GeoIP lookups""" 12 | homepath = os.getenv("HOME") 13 | try: 14 | rd = geoip2.database.Reader(homepath + '/.GeoLite2-Country.mmdb') 15 | except: 16 | print "Unable to load Maxmind database" 17 | try: 18 | resp = rd.city(ipaddr) 19 | country = resp.country.name 20 | except: 21 | print ipaddr + " not in database" 22 | country = True 23 | 24 | return country 25 | 26 | 27 | def load_file(afile): 28 | """Load our file""" 29 | with open(afile, 'r') as fh: 30 | for line in fh: 31 | ipaddr = line.rstrip() 32 | country = geoip_lookup(ipaddr) 33 | print ipaddr + " " + str(country) 34 | fh.close() 35 | 36 | 37 | def __main__(): 38 | """Get this party started""" 39 | parser = argparse.ArgumentParser(description='Mass GeoIP lookups') 40 | parser.add_argument('--file', '-f', dest='file', help='Pull IP addresses from this file') 41 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 42 | args = parser.parse_args() 43 | afile = args.file 44 | 45 | if not args.file: 46 | sys.exit(parser.print_help()) 47 | else: 48 | load_file(afile) 49 | 50 | 51 | if __name__ == '__main__': 52 | __main__() 53 | -------------------------------------------------------------------------------- /Networking/sendmail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to send out email 3 | 4 | import smtplib 5 | from email.mime.text import MIMEText 6 | 7 | me = "matt@example.com" 8 | you = "matt@ilovechaosmonkey.com" 9 | 10 | msg = MIMEText("This is a test body") 11 | msg['Subject'] = "This is a subject line" 12 | msg['From'] = me 13 | msg['To'] = you 14 | 15 | 16 | s = smtplib.SMTP("there.must.be.a.better.way.com") 17 | s.sendmail(me, [you], msg.as_string()) 18 | s.quit() 19 | -------------------------------------------------------------------------------- /Networking/smtp-test.ps1: -------------------------------------------------------------------------------- 1 | $CREDENTIALS = Get-Credential 2 | 3 | Send-MailMessage –From italerts@example.com –To user@example.com –Subject “Test Email” –Body “Test SMTP Relay Service” -SmtpServer smtp.office365.com -Credential $CREDENTIALS -UseSsl -Port 587 4 | -------------------------------------------------------------------------------- /Networking/statdnsquery.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple query tool for statdns.com 3 | 4 | import argparse 5 | import sys 6 | import requests 7 | 8 | 9 | def dnsquery(aqtype, adomain): 10 | """check statdns.com for our domain""" 11 | 12 | print "Checking domain: " + str(adomain) + " for DNS record type: " + str(aqtype).upper() 13 | print " >>" 14 | fullurl = "http://api.statdns.com/" + adomain + "/" + aqtype 15 | resp = requests.get(fullurl) 16 | 17 | report = resp.json() 18 | resp_code = report.get("response_code", {}) 19 | if resp_code == 400: 20 | print "Error" 21 | results = report.get("answer", {}) 22 | additional = report.get("additional", {}) 23 | print results 24 | print additional 25 | 26 | 27 | def reversequery(adomain): 28 | """Do a PTR lookup""" 29 | print "Getting PTR record for: " + str(adomain) 30 | fullurl = "http://api.statdns.com/x/" + str(adomain).rstrip('\n') 31 | resp = requests.get(fullurl) 32 | 33 | report = resp.json() 34 | resp_code = report.get("response_code", {}) 35 | if resp_code == 400: 36 | print "Error" 37 | results = report.get("answer", {}) 38 | 39 | print results 40 | 41 | sys.exit() 42 | 43 | 44 | def querylist(): 45 | """Print out a list of valid query types""" 46 | print "Valid query types: ", 47 | for query in ['a', 'aaaa', 'cert', 'cname', 'dhcid', 'dlv', 'dname', 'dnskey', 'ds', 48 | 'hinfo', 'hip', 'ipseckey', 'kx', 'loc', 'mx', 'naptr', 'ns', 'nsec', 49 | 'nsec3', 'nsec3param', 'opt', 'ptr', 'rrsig', 'soa', 'spf', 'srv', 50 | 'sshfp', 'tai', 'talink', 'tlsa', 'txt']: 51 | print query.upper(), 52 | 53 | sys.exit() 54 | 55 | 56 | def __main__(): 57 | """basic menu system""" 58 | parser = argparse.ArgumentParser(description='DNS Query tool') 59 | parser.add_argument('--type', '-t', dest='qtype', help='type of query') 60 | parser.add_argument('--reverse', '-r', dest='reverse', help='reverse PTR records for query') 61 | parser.add_argument('--domain', '-d', dest='domain', help='domain/hostname we are interested in') 62 | parser.add_argument('--list', '-l', dest='querylist', action='store_true', help='list valid query types') 63 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.2') 64 | args = parser.parse_args() 65 | aqtype = args.qtype 66 | adomain = args.domain 67 | areverse = args.reverse 68 | 69 | if args.reverse: 70 | reversequery(areverse) 71 | elif args.querylist: 72 | querylist() 73 | elif (args.qtype and args.domain): 74 | dnsquery(aqtype, adomain) 75 | else: 76 | sys.exit(parser.print_help()) 77 | 78 | 79 | if __name__ == '__main__': 80 | __main__() 81 | 82 | -------------------------------------------------------------------------------- /Networking/subdomainquery.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple subdomain search tool 3 | # Usage: ./subdomainquery.py -S 8.8.8.8 -s blog -f /tmp/domain_input.txt -o /tmp/output.txt 4 | 5 | import argparse 6 | import sys 7 | import dns.resolver 8 | import dns.reversename 9 | 10 | 11 | def subdomain_query(asubdomain, adomain, afile, adnsserver, aoutput): 12 | """Query a domain list for subdomains""" 13 | print '[*] Looking for "' + asubdomain + '" in our domain list\n' 14 | fh = open(afile, 'r') 15 | fo = open(aoutput, 'a') 16 | for domain in fh: 17 | querydomain = str(asubdomain) + "." + str(domain) 18 | query = dnsquery(querydomain, adnsserver) 19 | fo.write(querydomain.rstrip() + ": " + str(query) + "\n") 20 | print querydomain.rstrip() + ": " + str(query) 21 | fh.close() 22 | print "\n[*] Output to: " + aoutput 23 | fo.close() 24 | print "[*] We're done here." 25 | 26 | def dnsquery(querydomain, adnsserver): 27 | """Perform DNS queries""" 28 | dresolver = dns.resolver.Resolver() 29 | dresolver.nameservers = [adnsserver] 30 | try: 31 | ans = dresolver.query(querydomain.rstrip(), 'a') 32 | try: 33 | for rdata in ans: 34 | return rdata.address 35 | except Exception as e: 36 | print "Error: %s" % e 37 | except dns.exception.DNSException as e: 38 | if isinstance(e, dns.resolver.NoNameservers): 39 | print "[*] No name server record: %s " % querydomain 40 | 41 | 42 | def __main__(): 43 | """Get this party started""" 44 | parser = argparse.ArgumentParser(description='Search for a certain subdomain', usage='%(prog)s -f file -t ') 45 | parser.add_argument('--file', '-f', dest='filein', help='file to pull hosts from') 46 | parser.add_argument('--domain', '-d', dest='domain', help='domain to query') 47 | parser.add_argument('--subdomain', '-s', dest='subdomain', help='Use this subdomain for mass query') 48 | parser.add_argument('--server', '-S', dest='dnsserver', default='8.8.8.8', help='DNS server to query') 49 | parser.add_argument('--output', '-o', dest='output', help='file to dump results to') 50 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 51 | args = parser.parse_args() 52 | afile = args.filein 53 | adomain = args.domain 54 | asubdomain = args.subdomain 55 | aoutput = args.output 56 | global adnsserver 57 | adnsserver = args.dnsserver 58 | 59 | if not args.subdomain: 60 | sys.exit(parser.print_help()) 61 | 62 | if args.subdomain: 63 | subdomain_query(asubdomain, adomain, afile, adnsserver, aoutput) 64 | 65 | 66 | if __name__ == '__main__': 67 | __main__() 68 | 69 | -------------------------------------------------------------------------------- /Networking/twitter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple Tweet script 3 | 4 | import os 5 | import argparse 6 | import sys 7 | import twitter 8 | import re 9 | 10 | 11 | def send_tweet(atweet): 12 | """Send tweets""" 13 | # Gotta be a better way to do this 14 | keys = [] 15 | keys = load_apikey() 16 | consumer_key = keys[0] 17 | consumer_secret = keys[1] 18 | access_token_key = keys[2] 19 | access_token_secret = keys[3] 20 | print "Should we send: '" + atweet + "' ?" 21 | query = raw_input("(y)/(n): ").lower() 22 | if query == "y": 23 | api = twitter.Api() 24 | api = twitter.Api(consumer_key, consumer_secret, access_token_key, access_token_secret) 25 | status = api.PostUpdate(atweet) 26 | print status.text 27 | else: 28 | sys.exit("Not tweeting :(") 29 | 30 | 31 | def load_apikey(): 32 | """Load our API keys from file""" 33 | print "Loading API keys" 34 | fullpath = os.getenv("HOME") 35 | try: 36 | keyfile = open(fullpath + '/.twitter.key', 'r') 37 | except: 38 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.twitter.key") 39 | 40 | for line in keyfile: 41 | # This is fucking ugly 42 | if re.match("ConsumerKey", line): 43 | ConsumerKey = line 44 | if re.match("ConsumerSecret", line): 45 | ConsumerSecret = line 46 | if re.match("AccessTokenKey", line): 47 | AccessTokenKey = line 48 | if re.match("AccessTokenSecret", line): 49 | AccessTokenSecret = line 50 | 51 | keyfile.close() 52 | return ConsumerKey, ConsumerSecret, AccessTokenKey, AccessTokenSecret 53 | 54 | 55 | def main(): 56 | """Basic menu system""" 57 | parser = argparse.ArgumentParser(description='basic tweet sender', usage='%(prog)s -t tweet') 58 | parser.add_argument('--tweet', '-t', dest='tweet', help='tweet to send') 59 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 60 | args = parser.parse_args() 61 | atweet = args.tweet 62 | 63 | if not args.tweet: 64 | sys.exit(parser.print_help()) 65 | 66 | send_tweet(atweet) 67 | 68 | if __name__ == '__main__': 69 | main() -------------------------------------------------------------------------------- /Networking/urlparser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # simple http parser 4 | 5 | import argparse 6 | import sys 7 | import re 8 | import string 9 | 10 | def get_urls(filein): 11 | pat = r'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^%s\s]|/)))' 12 | pat = pat % re.sub(r'([-\\\]])', r'\\\1', string.punctuation) 13 | 14 | return re.finditer(pat, filein) 15 | 16 | def main(): 17 | 18 | parser = argparse.ArgumentParser(description='Simple URL parser', usage='%(prog)s -f file') 19 | parser.add_argument('-f', dest='filein', help='file to parse') 20 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 21 | args = parser.parse_args() 22 | 23 | # error checking 24 | if len(sys.argv)== 1: 25 | parser.print_help() 26 | sys.exit(1) 27 | 28 | global filein 29 | filein = args.filein 30 | 31 | get_urls(filein) 32 | 33 | if __name__ == "__main__": 34 | main() 35 | -------------------------------------------------------------------------------- /Networking/whoisxmlapiquery.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Whois query from https://www.whoisxmlapi.com 3 | 4 | import sys 5 | import json 6 | import requests 7 | import argparse 8 | 9 | 10 | def query_api(QUERY, OUTPUT): 11 | """HELP""" 12 | print "Query: " + str(QUERY) 13 | full_query = 'https://www.whoisxmlapi.com/whoisserver/WhoisService?domainName=' + QUERY + '&outputFormat=json' 14 | req = requests.get(full_query) 15 | if req.status_code == 200: 16 | jdata = req.json() 17 | print jdata 18 | print "Dumping JSON report" 19 | with open(OUTPUT, 'w') as fh: 20 | json.dump(jdata, fh) 21 | else: 22 | print "[ERROR] Code: " + req.status_code 23 | 24 | 25 | def __main__(): 26 | """Get this party started""" 27 | parser = argparse.ArgumentParser(description='DESCRIPTION HERE') 28 | parser.add_argument('--query', '-q', dest='query', help='Domain/IP to query') 29 | parser.add_argument('--output', '-o', dest='output', default='whois.json', help='Output file to write') 30 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 31 | args = parser.parse_args() 32 | QUERY = args.query 33 | OUTPUT = args.output 34 | 35 | if not args.query: 36 | sys.exit(parser.print_help()) 37 | else: 38 | query_api(QUERY, OUTPUT) 39 | 40 | 41 | if __name__ == '__main__': 42 | __main__() 43 | -------------------------------------------------------------------------------- /Networking/zonetransfer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Zone transfer test script 3 | 4 | import argparse 5 | import sys 6 | import dns.resolver 7 | import dns.zone 8 | 9 | 10 | def get_ns_records(adomain, aserver): 11 | """Pull NS records for our domain""" 12 | print "> Pulling NS records for: " + adomain 13 | dresolver = dns.resolver.Resolver() 14 | dresolver.nameservers = [aserver] 15 | ans = dresolver.query(adomain, 'ns') 16 | ns_list = [] 17 | try: 18 | for rdata in ans: 19 | ns_list.append(rdata) 20 | except Exception as e: 21 | print "Error: %s" % e 22 | 23 | return ns_list 24 | 25 | 26 | def zone_transfer(adomain, aserver, aquiet): 27 | """Perform zone transfers against our name servers""" 28 | ns_list = get_ns_records(adomain, aserver) 29 | for server in ns_list: 30 | print "> Testing: " + str(server), 31 | try: 32 | z = dns.zone.from_xfr(dns.query.xfr(str(server), adomain)) 33 | names = z.nodes.keys() 34 | names.sort() 35 | if aquiet == True: 36 | print "[WARNING] AXFR is allowed" 37 | else: 38 | for n in names: 39 | print z[n].to_text(n) 40 | except Exception as e: 41 | msg = "AXFR not allowed (probably)" 42 | print "Error: %s %s" % (e, msg) 43 | 44 | print "" 45 | 46 | 47 | def __main__(): 48 | """Get this party started""" 49 | parser = argparse.ArgumentParser(description='Check name servers for zone transfers') 50 | parser.add_argument('--domain', '-d', dest='domain', help='domain to check') 51 | parser.add_argument('--server', '-s', dest='dnsserver', default='8.8.8.8', help='DNS server to query') 52 | parser.add_argument('--quiet', '-q', dest='quiet', action="store_true", help='Test but dont dump') 53 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 54 | args = parser.parse_args() 55 | adomain = args.domain 56 | aserver = args.dnsserver 57 | aquiet = args.quiet 58 | 59 | if not args.domain: 60 | sys.exit(parser.print_help()) 61 | if aquiet: 62 | aquiet = True 63 | 64 | print "Zone transfer of doom v1..." 65 | zone_transfer(adomain, aserver, aquiet) 66 | 67 | 68 | if __name__ == '__main__': 69 | __main__() 70 | -------------------------------------------------------------------------------- /Office365/O365-Audit.ps1: -------------------------------------------------------------------------------- 1 | # Powershell script to dump all Office365 Users 2 | 3 | # Change this if necesssary 4 | $DATE = Get-Date -Format dd-MM-yyyy 5 | $LOUTPUT = "C:\Users\matt\Licensed-O365-Audit-$DATE.csv" 6 | 7 | Import-Module MSOnline 8 | 9 | Write-Host "[INFO] Connecting to O365" 10 | Connect-MsolService 11 | 12 | Write-Host "[INFO] Pulling data from O365" 13 | Get-MsolUser | Where-Object { $_.isLicensed -eq "True" } | Select-Object UserPrincipalName, DisplayName, Country, Department | Export-Csv $LOUTPUT 14 | Write-Host "[INFO] Writing output" 15 | Write-Host "[INFO] Complete" 16 | -------------------------------------------------------------------------------- /Office365/README.md: -------------------------------------------------------------------------------- 1 | # Office 365 Scripts (Mostly Powershell) 2 | 3 | Just some scripts to do stuff to^H^H with Office365 4 | 5 | 6 | ### Scripts 7 | 8 | * O365-Audit.ps1 - Dumps a list of Office365 users 9 | -------------------------------------------------------------------------------- /Powershell/Group-Audit.ps1: -------------------------------------------------------------------------------- 1 | # Powershell script to dump all AD groups and their members 2 | # (Taken from another script and modified) 3 | 4 | # Change this if necesssary 5 | $DATE = Get-Date -Format dd-MM-yyyy 6 | $OUTPUT = "C:\Users\matt\SecurityGroups-$DATE.csv" 7 | Write-Host "[INFO] Importing module..." 8 | Import-Module ActiveDirectory 9 | 10 | $Groups = (Get-AdGroup -filter * | Where {$_.name -like "**"} | select name -ExpandProperty name) 11 | 12 | $Table = @() 13 | 14 | $Record = @{ 15 | "Group Name" = "" 16 | "Name" = "" 17 | "Username" = "" 18 | } 19 | 20 | Write-Host "[INFO] Digging through AD..." 21 | Foreach ($Group in $Groups) { 22 | 23 | $Arrayofmembers = Get-ADGroupMember -identity $Group -recursive | select name,samaccountname 24 | 25 | foreach ($Member in $Arrayofmembers) { 26 | $Record."Group Name" = $Group 27 | $Record."Name" = $Member.name 28 | $Record."UserName" = $Member.samaccountname 29 | $objRecord = New-Object PSObject -property $Record 30 | $Table += $objrecord 31 | 32 | } 33 | } 34 | 35 | Write-Host "[INFO] Writing output to file" 36 | $Table | Export-Csv $OUTPUT -NoTypeInformation 37 | 38 | Write-Host "[INFO] Complete." 39 | -------------------------------------------------------------------------------- /Powershell/PasswordGen.ps1: -------------------------------------------------------------------------------- 1 | # Simple script to generate a decent password and copy to clipboard 2 | 3 | param( 4 | [string] $length = 15, 5 | [string] $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_!@#$%^&*()_" 6 | ) 7 | 8 | Write-Output "Generating Password with length: $length" 9 | if ($length -le "10") { 10 | Write-Output "[WARNING] Passwords less than 10 caracters are considered weak" 11 | } 12 | 13 | $bytes = new-object "System.Byte[]" $length 14 | $rnd = new-object System.Security.Cryptography.RNGCryptoServiceProvider 15 | $rnd.GetBytes($bytes) 16 | $result = "" 17 | 18 | for( $i=0; $i -lt $length; $i++ ) 19 | { 20 | $result += $chars[ $bytes[$i] % $chars.length ] 21 | } 22 | 23 | # This copies stuff to the clipboard 24 | function To-Clipboard { 25 | 26 | $null = [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 27 | $dataObject = New-Object windows.forms.dataobject 28 | $dataObject.SetData([Windows.Forms.DataFormats]::UnicodeText, $true, $result) 29 | [Windows.Forms.Clipboard]::SetDataObject($dataObject, $true) 30 | } 31 | 32 | To-Clipboard 33 | Write-Output "`r`nPassword copied to clipboard`r`n" 34 | Write-Output "Password: $result" 35 | -------------------------------------------------------------------------------- /Powershell/SendSlack.ps1: -------------------------------------------------------------------------------- 1 | Function Send-Slack 2 | { 3 | 4 | Param( 5 | [parameter(Mandatory=$true)] 6 | [String] 7 | $SlackString 8 | ) 9 | 10 | $SlackWebHook = 'https://hooks.slack.com/services/LOLS/KTHXBIBBQWTF/Bieber' 11 | $SlackData = @{text = $SlackString} 12 | $SlackPayload = ConvertTo-Json $SlackData 13 | Write-Host "Sending Slack message..." 14 | Invoke-WebRequest -Uri $SlackWebHook -TimeoutSec 5 -Method POST -Body $SlackPayload | Out-Null 15 | } 16 | Export-ModuleMember -Function Send-Slack 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scripts of Doom 2 | 3 | General scripts to automate stuff 4 | 5 | Mostly boring sysadmin type stuff. 6 | 7 | Bear in mind that stuff here is likely to be incomplete and/or broken. 8 | I take no responsibility if you wife/girlfriend/pet leaves you because of this. 9 | 10 | I like cake 11 | 12 | 13 | ### Script Categories 14 | 15 | 16 | * Networking 17 | * Office365 18 | * Powershell 19 | * Malware 20 | * Security 21 | * Shodan 22 | -------------------------------------------------------------------------------- /Security/Wordpress/README.md: -------------------------------------------------------------------------------- 1 | Wordpress 2 | ========= 3 | 4 | Just a couple of scripts for interacting with the WPScan Vulnerability Database. 5 | 6 | * wpplugin-check.py - Mass query script for the VDB API (example JSON file included) 7 | * plugins.json.dist - Sample JSON file of plugins 8 | * wpvdb-api.py - Simple query script for the API -------------------------------------------------------------------------------- /Security/Wordpress/plugins.json.dist: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | { 4 | "title": "category-sticky-post", 5 | "version": "2.5.0", 6 | "active": "true" 7 | }, 8 | { 9 | "title": "contact-form-7", 10 | "version": "3.9.3", 11 | "active": "true" 12 | }, 13 | { 14 | "title": "contact-form-db", 15 | "version": "2.8.10", 16 | "active": "true" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /Security/Wordpress/wpplugin-check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to query the WPScan VulnDB for our plugins 3 | # TODO: Match our version against the reported version for 4 | # more accurate reporting 5 | 6 | import argparse 7 | import sys 8 | import json 9 | try: 10 | import requests 11 | except: 12 | sys.exit("You're missing the Requests library") 13 | 14 | 15 | def query_api(plugin): 16 | """Check the API""" 17 | print "Querying API for " + plugin + " : ", 18 | url = "https://wpvulndb.com/api/v1/plugins/" 19 | r = requests.get(url + str(plugin)) 20 | if r.status_code == 404: 21 | print "No vulnerabilties found.\n" 22 | else: 23 | print "Vulnerabilities found." 24 | jdata = r.json() 25 | vulns = jdata.get("plugin", {}) 26 | for i in range(len(vulns['vulnerabilities'])): 27 | vulnerability = vulns['vulnerabilities'][i]['title'] 28 | print " * " + vulnerability 29 | print "\n" 30 | 31 | 32 | def parse_json(aplugins): 33 | """Parse our JSON file""" 34 | print "Parsing file", 35 | with open(aplugins, 'r') as json_data: 36 | data = json.load(json_data) 37 | json_data.close() 38 | print "...ok" 39 | 40 | print "Checking plugins for vulnerabilities" 41 | for i in range(len(data['plugins'])): 42 | plugin = data['plugins'][i]['title'] 43 | query_api(plugin) 44 | 45 | 46 | def __main__(): 47 | """Get this party started""" 48 | parser = argparse.ArgumentParser(description='Simple Vuln checking script') 49 | parser.add_argument('--plugins', '-p', dest='plugins', help='File with our plugin directory') 50 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 51 | args = parser.parse_args() 52 | aplugins = args.plugins 53 | 54 | if not args.plugins: 55 | sys.exit(parser.print_help()) 56 | else: 57 | parse_json(aplugins) 58 | 59 | 60 | if __name__ == '__main__': 61 | __main__() 62 | 63 | -------------------------------------------------------------------------------- /Security/Wordpress/wpvdb-api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to query the WPScan Vulnerability Database API 3 | 4 | import argparse 5 | import sys 6 | try: 7 | import requests 8 | except: 9 | sys.exit("Python Requests library required") 10 | 11 | 12 | def query_api(url, check): 13 | """Check the API""" 14 | print "Checking API...", 15 | r = requests.get(url + str(check)) 16 | if r.status_code == 404: 17 | sys.exit("No vulnerabilties found.") 18 | if r.status_code != 200: 19 | sys.exit("Something has gone horribly wrong. Error code: " + str(r.status_code)) 20 | else: 21 | data = r.json() 22 | 23 | print " ok" 24 | return data 25 | 26 | 27 | def wp_theme_check(athemecheck): 28 | """Checks for vulnerable themes""" 29 | PLUGIN_API_URL = "https://wpvulndb.com/api/v1/themes/" 30 | plugin_check = query_api(PLUGIN_API_URL, athemecheck) 31 | print "Vulnerabilty report" 32 | vulns = plugin_check.get("theme", {}) 33 | for i in range(len(vulns['vulnerabilities'])): 34 | vulnerability = vulns['vulnerabilities'][i]['title'] 35 | print "* " + vulnerability 36 | 37 | 38 | def wp_plugin_check(aplugincheck): 39 | """Checks for vulnerable plugins""" 40 | PLUGIN_API_URL = "https://wpvulndb.com/api/v1/plugins/" 41 | plugin_check = query_api(PLUGIN_API_URL, aplugincheck) 42 | print "Vulnerabilty report" 43 | vulns = plugin_check.get("plugin", {}) 44 | for i in range(len(vulns['vulnerabilities'])): 45 | vulnerability = vulns['vulnerabilities'][i]['title'] 46 | print "* " + vulnerability 47 | 48 | 49 | def wp_version_check(awpcheck): 50 | """Checks for vulnerable Wordpress version""" 51 | WP_API_URL = "https://wpvulndb.com/api/v1/wordpresses/" 52 | wp_check = query_api(WP_API_URL, awpcheck) 53 | print "Vulnerabilty report" 54 | vulns = wp_check.get("wordpress", {}) 55 | for i in range(len(vulns['vulnerabilities'])): 56 | vulnerability = vulns['vulnerabilities'][i]['title'] 57 | print "* " + vulnerability 58 | 59 | 60 | def __main__(): 61 | """Get this party started""" 62 | parser = argparse.ArgumentParser(description='WPScan Vulnerability Database API Search Tool of Doom') 63 | parser.add_argument('--wordpress', '-w', dest='wpcheck', help='Is my Wordpress vulnerable') 64 | parser.add_argument('--themes', '-t', dest='themecheck', help='Is my Wordpress theme vulnerable') 65 | parser.add_argument('--plugin', '-p', dest='plugincheck', help='Is my Wordpress plugin vulnerable') 66 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 67 | args = parser.parse_args() 68 | global awpcheck 69 | awpcheck = args.wpcheck 70 | global athemecheck 71 | athemecheck = args.themecheck 72 | global aplugincheck 73 | aplugincheck = args.plugincheck 74 | 75 | if args.wpcheck: 76 | wp_version_check(awpcheck) 77 | elif args.themecheck: 78 | wp_theme_check(athemecheck) 79 | elif args.plugincheck: 80 | wp_plugin_check(aplugincheck) 81 | else: 82 | sys.exit(parser.print_help()) 83 | 84 | 85 | if __name__ == '__main__': 86 | __main__() 87 | -------------------------------------------------------------------------------- /Security/bitly-expand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to expand a bitly link 3 | 4 | import requests 5 | import argparse 6 | import json 7 | import sys 8 | import os 9 | 10 | 11 | def expandurl(url): 12 | """Check our hash against the Bit.ly API""" 13 | print "Expanding Bit.ly URL...", 14 | headers = {'Content-type': 'application/json', "User-Agent": "curl/7.43.0"} 15 | try: 16 | token = os.environ['BITLY_TOKEN'] 17 | except Exception as err: 18 | sys.exit("No API token exported") 19 | bitlyurl = "https://api-ssl.bitly.com/v3/expand?access_token=" + token + "&hash=" + url + "&format=json" 20 | try: 21 | req = requests.get(bitlyurl, headers=headers, verify=True).json() 22 | print req['status_code'] 23 | if req['status_code'] == 404: 24 | print "We got a 404." 25 | elif req['status_code'] == 200: 26 | print "Expanded URL: " + req['data']['expand'][0]['long_url'] 27 | elif req['status_code'] == 500: 28 | print "We got a " + req['status_code'] 29 | except Exception as err: 30 | print "Nope..." 31 | 32 | 33 | def __main__(): 34 | """Lets get this party started""" 35 | parser = argparse.ArgumentParser(description='Expand a Bit.ly URL', usage='%(prog)s -u URL') 36 | parser.add_argument('--url', '-u', dest='url', help='URL to expand') 37 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.3') 38 | args = parser.parse_args() 39 | url = args.url 40 | 41 | if args.url: 42 | expandurl(url) 43 | else: 44 | print "Exiting" 45 | 46 | 47 | if __name__ == '__main__': 48 | __main__() 49 | -------------------------------------------------------------------------------- /Security/courier-attacks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Simple script to parse the Exim reject log and pull some naughty stats 3 | 4 | LOGFILE="/var/log/exim4/rejectlog" 5 | ATTACKERS="/tmp/.attackers" 6 | USERS="/tmp/.users" 7 | REGEX="Incorrect" 8 | DUMPREPORT="./attacker-report.txt" 9 | 10 | 11 | function attackersummary() { 12 | echo "Attacker Summary" 13 | echo "---------------------------------------" 14 | for x in `cat ${ATTACKERS}` 15 | do 16 | echo -n "${x}: " 17 | grep ${REGEX} ${LOGFILE} | grep -e "${x}" | awk -F"=" ' { print $2} ' | awk -F")" '{ print $1 }' | wc -l 18 | done 19 | echo "---------------------------------------" 20 | } 21 | 22 | function summaryquery() { 23 | echo -n "Print username summary Y/N? " 24 | read ANSWER 25 | if [ ${ANSWER} == "y" ]; then 26 | usersummary 27 | else 28 | dumpreport 29 | # Clean up 30 | rm ${ATTACKERS} ${USERS} 31 | echo "Exiting" 32 | exit 0 33 | fi 34 | } 35 | 36 | function usersummary() { 37 | echo "Attacker username summary" 38 | echo "---------------------------------------" 39 | for x in `cat ${ATTACKERS}` 40 | do 41 | grep ${REGEX} ${LOGFILE} | grep -w "${x}" > /tmp/${x}-attack_summary.txt 42 | echo "Attacker: ${x}" 43 | for y in `cat ${USERS}` 44 | do 45 | ATTACKS=`grep -w "${y}" /tmp/${x}-attack_summary.txt | awk -F"=" ' { print $2} ' | awk -F")" '{ print $1 }' | wc -l` 46 | if [ ${ATTACKS} == "0" ]; 47 | then 48 | continue 49 | else 50 | echo -n "${y}: " 51 | echo ${ATTACKS} 52 | fi 53 | done 54 | echo "---------------------------------------" 55 | rm /tmp/${x}-attack_summary.txt 56 | done 57 | } 58 | 59 | function dumpreport() { 60 | echo -n "Dump report to file ? Y/N " 61 | read ANSWER 62 | if [ ${ANSWER} = "y" ] 63 | then 64 | echo "Dumping: ${DUMPREPORT}" 65 | usersummary > ${DUMPREPORT} 66 | else 67 | echo "We're done here." 68 | exit 0 69 | fi 70 | } 71 | 72 | function rootcheck() { 73 | if [ "$(id -u)" != "0" ]; then 74 | echo "This script must be run as root" 1>&2 75 | exit 1 76 | fi 77 | } 78 | 79 | rootcheck 80 | 81 | echo "Getting stats" 82 | cat ${LOGFILE} | grep ${REGEX} | awk -F"]" '{ print $2}' | awk -F"[" '{ print $2 }'| sort | uniq > ${ATTACKERS} 83 | cat ${LOGFILE} | grep ${REGEX} | awk -F"=" ' { print $2} ' | awk -F")" '{ print $1 }' | sort | uniq > ${USERS} 84 | 85 | attackersummary 86 | summaryquery 87 | dumpreport 88 | 89 | echo "Report complete" 90 | 91 | -------------------------------------------------------------------------------- /Security/cve-search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Search the CVE service offered by CircLU (https://www.circl.lu/services/cve-search/) 3 | 4 | import requests 5 | import argparse 6 | import sys 7 | import json 8 | 9 | 10 | def search_cve(_cve): 11 | """Simple CVE search""" 12 | print "Searching: " + _cve 13 | SEARCHURL = "http://cve.circl.lu/api/cve/" + _cve 14 | r = requests.get(SEARCHURL) 15 | if r.status_code != 200: 16 | sys.exit("Something has gone horribly wrong.") 17 | else: 18 | data = json.loads(r.text) 19 | print "Summary: " + data['summary'] 20 | print "CVSS Score: " + str(data['cvss']) 21 | 22 | 23 | def show_vendor_product(_vendor, _product): 24 | """Show a specific product for a vendor""" 25 | print "Searching: " + _product + " from " + _vendor 26 | SEARCHURL = "http://cve.circl.lu/api/search/" + _vendor + "/" + _product 27 | r = requests.get(SEARCHURL) 28 | if r.status_code != 200: 29 | sys.exit("Something has gone horribly wrong.") 30 | else: 31 | jdata = json.loads(r.text) 32 | for item in jdata: 33 | print "\nSummary: " + item['summary'] 34 | print "CVE: " + item['id'] 35 | print "CVSS: " + str(item['cvss']) 36 | 37 | 38 | def list_vendor_products(_vendor): 39 | """Search for a vendor""" 40 | print "Vendor Search: " + _vendor, 41 | SEARCHURL = "http://cve.circl.lu/api/browse/" + _vendor 42 | r = requests.get(SEARCHURL) 43 | if r.status_code != 200: 44 | sys.exit("Something has gone horribly wrong.") 45 | else: 46 | print " ... " + str(r.status_code) 47 | try: 48 | data = json.loads(r.text)['product'] 49 | print "Available products from " + _vendor 50 | for item in data: 51 | print item 52 | except: 53 | sys.exit("[!!] Vendor not in list") 54 | 55 | 56 | def list_vendors(): 57 | """List all the available vendors in the API""" 58 | print "Listing Vendors", 59 | SEARCHURL = "http://cve.circl.lu/api/browse" 60 | r = requests.get(SEARCHURL) 61 | if r.status_code != 200: 62 | sys.exit("Something has gone horribly wrong.") 63 | else: 64 | print " ... " + str(r.status_code) 65 | data = json.loads(r.text)['vendor'] 66 | print "Available Vendors: " 67 | for item in data: 68 | print item 69 | 70 | 71 | def __main__(): 72 | """Get this party started""" 73 | parser = argparse.ArgumentParser(description='CIRCL CVE API Search') 74 | parser.add_argument('--list-vendors', '-l', dest='listvendors', action='store_true', help='List the available vendors') 75 | parser.add_argument('--product', '-p', dest='product', help='Search for a product') 76 | parser.add_argument('--vendors', '-v', dest='vendor', help='Search for a vendor') 77 | parser.add_argument('--cve', '-c', dest='cve', help='Search for this CVE') 78 | parser.add_argument('--version', '-V', action='version', version='%(prog)s 0.1') 79 | args = parser.parse_args() 80 | _cve = args.cve 81 | _product = args.product 82 | _vendor = args.vendor 83 | _listvendors = args.listvendors 84 | 85 | # TODO: This needs to be improved 86 | if (args.vendor and args.product): 87 | show_vendor_product(_vendor, _product) 88 | else: 89 | if args.cve: 90 | search_cve(_cve) 91 | elif (args.vendor and not args.product): 92 | list_vendor_products(_vendor) 93 | elif args.listvendors: 94 | list_vendors() 95 | 96 | if __name__ == '__main__': 97 | __main__() -------------------------------------------------------------------------------- /Security/docker-brute.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Brute force tool for Docker registry server 3 | 4 | import sys 5 | import requests 6 | import argparse 7 | 8 | # Annoying TLS warnings 9 | requests.packages.urllib3.disable_warnings() 10 | 11 | 12 | def run_brute_attack(USERNAME, PASSWORD): 13 | """Run our brute force attack""" 14 | 15 | # Adjust this as necessary 16 | URL = "https://testregistry.example.com/v2/_catalog" 17 | 18 | print "[INFO] Requesting with password: " + PASSWORD, 19 | resp = requests.get(URL, auth=(USERNAME, PASSWORD), verify=False) 20 | 21 | if resp.status_code == 401: 22 | print "[ERROR] Auth failed :(" 23 | elif resp.status_code == 200: 24 | # print "[DATA] " + resp.text 25 | print "[SUCCESS] We're in" 26 | else: 27 | print "[ERROR] Something has gone horrily wrong :(" 28 | print resp.text 29 | 30 | 31 | def parse_passwords(PASSWORDLIST): 32 | """Parse out our password list""" 33 | print "[INFO] Parsing password list" 34 | passwords = [] 35 | try: 36 | with open(PASSWORDLIST, 'r') as fh: 37 | data = fh.readlines() 38 | for item in data: 39 | password = item.split()[0] 40 | # print "[INFO] Adding " + password 41 | passwords.append(password) 42 | except: 43 | sys.exit("[ERROR] Problem parsing password list") 44 | 45 | print "[INFO] Total passwords: " + str(len(passwords)) 46 | 47 | return passwords 48 | 49 | 50 | def __main__(): 51 | """Get this party started""" 52 | parser = argparse.ArgumentParser(description='Docker Registry Brute Forcer') 53 | parser.add_argument('--username', '-u', dest='username', help='username to use') 54 | parser.add_argument('--password-list', '-p', dest='passwordlist', help='Password wordlist file') 55 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 56 | args = parser.parse_args() 57 | USERNAME = args.username 58 | PASSWORDLIST = args.passwordlist 59 | 60 | if not args.passwordlist: 61 | sys.exit(parser.print_help()) 62 | else: 63 | passwords = parse_passwords(PASSWORDLIST) 64 | for password in passwords: 65 | run_brute_attack(USERNAME, password) 66 | 67 | 68 | if __name__ == '__main__': 69 | __main__() 70 | -------------------------------------------------------------------------------- /Security/fbid-finder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # FBID Finder 3 | # This is ugly as hell but it'll get the job done 4 | 5 | import argparse 6 | import sys 7 | import requests 8 | from bs4 import BeautifulSoup 9 | 10 | 11 | def search_username(ausername): 12 | """Search for our usernames numeric ID""" 13 | print "Searching: " + ausername + " -> ", 14 | url = "http://www.findmyfbid.com/" 15 | post_data = "https://www.facebook.com/" + ausername 16 | user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:42.0) Gecko/20100101 Firefox/42.0" 17 | headers = {'User-Agent': user_agent} 18 | req = requests.post(url, headers=headers, data = { "url": post_data}) 19 | html_data = req.text 20 | soup = BeautifulSoup(html_data, 'html.parser') 21 | resp = str(soup.code) 22 | ugly1 = resp.split(">") 23 | ugly2 = ugly1[1].split("<") 24 | if resp == "https://www.facebook.com": 25 | print "No ID found :(" 26 | else: 27 | print ugly2[0] 28 | 29 | def __main__(): 30 | """Get this party started""" 31 | parser = argparse.ArgumentParser(description='Facebook ID Finder') 32 | parser.add_argument('--username', '-u', dest='username', help='Username to search for') 33 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 34 | args = parser.parse_args() 35 | ausername = args.username 36 | 37 | if not args.username: 38 | sys.exit(parser.print_help()) 39 | else: 40 | search_username(ausername) 41 | 42 | 43 | if __name__ == '__main__': 44 | __main__() 45 | -------------------------------------------------------------------------------- /Security/hasher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple hash creator because I'm lazy 3 | 4 | import hashlib 5 | import sys 6 | import argparse 7 | 8 | 9 | def gethash(afile, hashtype): 10 | """Get the hash value for our file""" 11 | print "Hashing file: " + afile + " (" + hashtype + ")" 12 | try: 13 | data = open(afile, 'rb').read() 14 | except IOError, e: 15 | sys.exit(e) 16 | if hashtype == "all": 17 | for ht in ['md5', 'sha1', 'sha256']: 18 | md5 = hashlib.md5(data).hexdigest() 19 | sha1 = hashlib.sha1(data).hexdigest() 20 | sha256 = hashlib.sha256(data).hexdigest() 21 | print "MD5: %s" % md5 22 | print "SHA1: %s" % sha1 23 | print "SHA256: %s" % sha256 24 | elif hashtype == "md5": 25 | hashout = hashlib.md5(data).hexdigest() 26 | print "%s: %s" % (hashtype, hashout) 27 | elif hashtype == "sha1": 28 | hashout = hashlib.sha1(data).hexdigest() 29 | print "%s: %s" % (hashtype, hashout) 30 | elif hashtype == "sha256": 31 | hashout = hashlib.sha256(data).hexdigest() 32 | print "%s: %s" % (hashtype, hashout) 33 | 34 | 35 | def __main__(): 36 | """Get this party started""" 37 | parser = argparse.ArgumentParser(description='basic hashing tool', usage='%(prog)s -f file') 38 | parser.add_argument('--file', '-f', dest='file', help='file to hash') 39 | parser.add_argument('--md5', '-m', dest='md5', action="store_true", help='just print the MD5') 40 | parser.add_argument('--sha1', '-1', dest='sha1', action="store_true", help='just print the SHA1') 41 | parser.add_argument('--sha256', '-2', dest='sha256', action="store_true", help='just print the SHA256') 42 | parser.add_argument('--all', '-a', dest='all', action="store_true", help='print all the hash values for a file') 43 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 44 | args = parser.parse_args() 45 | afile = args.file 46 | amd5 = args.md5 47 | asha1 = args.sha1 48 | asha256 = args.sha256 49 | 50 | if not args.file: 51 | sys.exit(parser.print_help()) 52 | 53 | if amd5: 54 | gethash(afile, hashtype="md5") 55 | elif asha1: 56 | gethash(afile, hashtype="sha1") 57 | elif asha256: 58 | gethash(afile, hashtype="sha256") 59 | else: 60 | gethash(afile, hashtype="all") 61 | 62 | if __name__ == '__main__': 63 | __main__() 64 | -------------------------------------------------------------------------------- /Security/haveibeenpwned.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to check an email against haveibeenpwned.com 3 | 4 | import requests 5 | import argparse 6 | import urllib 7 | <<<<<<< HEAD 8 | ======= 9 | import sys 10 | >>>>>>> 7f22a727073ba1185e06b9ef42475f33279c645e 11 | 12 | def do_check(checkemail): 13 | """Do the actual checking against HIBP""" 14 | customheaders = {"User-Agent": "haveibeenpwned-dot-py"} 15 | checkurl = "https://haveibeenpwned.com/api/v2/breachedaccount/" + urllib.quote(checkemail) 16 | r = requests.get(checkurl, headers=customheaders, verify=False) 17 | if r.status_code == 404: 18 | print "You're good, " + checkemail + " not found." 19 | elif r.status_code == 200: 20 | print "Bad things happened: " + checkemail + " found on lists", 21 | # parse this shit properly 22 | report = r.json() 23 | print report 24 | else: 25 | print "Something else happened" 26 | 27 | 28 | def check_email(aemail): 29 | """Do the actual checking""" 30 | print "Checking Email...", 31 | do_check(aemail) 32 | 33 | 34 | def check_email_list(aelist): 35 | """Check a list of emails against HIBP""" 36 | print "Checking email list: " + aelist 37 | f = open(aelist, 'r') 38 | for email in f: 39 | do_check(email.rstrip()) 40 | f.close() 41 | 42 | 43 | def get_breach_details(): 44 | """Get a list of the breaches available""" 45 | <<<<<<< HEAD 46 | customheaders = {"User-Agent": "haveibeenpwned-dot-py"} 47 | ======= 48 | customheaders = { "User-Agent" : "haveibeenpwned-dot-py" } 49 | <<<<<<< HEAD 50 | >>>>>>> 7f22a727073ba1185e06b9ef42475f33279c645e 51 | ======= 52 | >>>>>>> 7f22a727073ba1185e06b9ef42475f33279c645e 53 | checkurl = "https://haveibeenpwned.com/api/v2/breaches" 54 | r = requests.get(checkurl, headers=customheaders, verify=False) 55 | if r.status_code == 404: 56 | print "Something bad happened" 57 | print r.text 58 | 59 | 60 | def __main__(): 61 | """Lets get this party started""" 62 | parser = argparse.ArgumentParser(description='Check an email against haveibeenpwned.com', usage='%(prog)s -e email') 63 | parser.add_argument('--email', '-e', dest='email', help='Email to check') 64 | parser.add_argument('--details', '-d', dest='details', action='store_true', help='Get breach details') 65 | parser.add_argument('--list', '-l', dest='email_list', help='Email list to check, one email per line') 66 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.2') 67 | args = parser.parse_args() 68 | adetails = args.details 69 | aemail = args.email 70 | aemail_list = args.email_list 71 | 72 | # fix me 73 | #if not (args.email or args.email_list): 74 | # sys.exit(parser.print_help()) 75 | #elif not args.details: 76 | # sys.exit(parser.print_help()) 77 | 78 | if args.email_list: 79 | check_email_list(aemail_list) 80 | elif args.details: 81 | get_breach_details() 82 | else: 83 | check_email(aemail) 84 | 85 | if __name__ == '__main__': 86 | __main__() 87 | 88 | -------------------------------------------------------------------------------- /Security/httprecon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # simple script to pull common web stuff for recon purposes 3 | # Matt Erasmus code@zonbi.org 4 | 5 | import httplib 6 | import sys 7 | 8 | sys.argv.pop(0) 9 | if len(sys.argv) == 0: 10 | print "please give us a test host" 11 | sys.exit(1) 12 | 13 | host = sys.argv[0] 14 | 15 | print "" 16 | print " << HTTPRecon Script >> " 17 | print "<----------------------------------------------->" 18 | print "" 19 | 20 | # Headers 21 | print "Headers for ", host 22 | print "<----------------------------------------------->" 23 | connect = httplib.HTTPConnection(host) 24 | robots_url = "/" 25 | connect.request("GET", robots_url) 26 | response = connect.getresponse() 27 | responsecode = response.status 28 | print "Server Flags:", response.getheader("Server") 29 | print "Date:", response.getheader("Date") 30 | print "Cookie:", response.getheader("cookie") 31 | print "Response Code:", responsecode 32 | 33 | # Robots.txt 34 | print "" 35 | print "Robots.txt" 36 | print "<----------------------------------------------->" 37 | connect = httplib.HTTPConnection(host) 38 | robots_url = "/robots.txt" 39 | connect.request("GET", robots_url) 40 | response = connect.getresponse() 41 | # basic error checking 42 | if response.status != 200: 43 | print 'Error!', 'status code:', response.status 44 | robots = response.read() 45 | print robots 46 | save = raw_input("(s)ave / (c)ontinue / (q)uit: ") 47 | 48 | if save == "q": 49 | print ">> quitting..." 50 | sys.exit(1) 51 | elif save == "s": 52 | print ">> saving to ./robots.txt" 53 | output = open("robots.txt", 'w') 54 | output.write(robots) 55 | output.close() 56 | else: 57 | print "onward..." 58 | 59 | # crossdomain.xml 60 | print "" 61 | print "crossdomain.xml" 62 | print "<----------------------------------------------->" 63 | connect = httplib.HTTPConnection(host) 64 | cdxml_url = "/crossdomain.xml" 65 | connect.request("GET", cdxml_url) 66 | response = connect.getresponse() 67 | # basic error checking 68 | if response.status != 200: 69 | print 'Error!', 'status code:', response.status 70 | 71 | cdxml = response.read() 72 | print cdxml 73 | save = raw_input("(s)ave / (c)ontinue / (q)uit: ") 74 | 75 | if save == "q": 76 | print ">> quitting..." 77 | sys.exit(1) 78 | elif save == "s": 79 | print ">> saving to ./crossdomain.xml" 80 | output = open("crossdomain.xml", 'w') 81 | output.write(cdxml) 82 | output.close() 83 | else: 84 | print "onward..." 85 | 86 | 87 | print "" 88 | print "all done" 89 | print "bugs: code@zonbi.org" -------------------------------------------------------------------------------- /Security/nmap-parse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple script to parse nmap XML and output to CSV 3 | # Hacked from here: http://blog.poultonfam.com/brad/2010/02/24/python-nmap-xml-parser/ 4 | 5 | import argparse 6 | import sys 7 | import datetime 8 | import re 9 | from xml.dom.minidom import parse, parseString 10 | 11 | 12 | def parse_xml(ainput, aoutput): 13 | """Parse our XML file""" 14 | print "Parsing", 15 | dom = parse(ainput) 16 | nmapvars = {} 17 | hostname = '' 18 | os = '' 19 | difficulty = '' 20 | args = '' 21 | date = '' 22 | port = [] 23 | name = [] 24 | protocol = [] 25 | product = [] 26 | product = [] 27 | version = [] 28 | extrainfo = [] 29 | portstate = [] 30 | goodXML = [] 31 | 32 | scaninfo = dom.getElementsByTagName('nmaprun')[0] 33 | date = scaninfo.getAttribute("startstr") 34 | args = scaninfo.getAttribute('args') 35 | 36 | def translateXml(node): 37 | """This is a black hole to me :)""" 38 | if node.nodeName == 'hostname': 39 | hostname = node.getAttribute('name') 40 | noutput.write(node.getAttribute('name')) 41 | noutput.write(',') 42 | elif node.nodeName == 'address': 43 | if 'ip' in node.getAttribute('addrtype'): 44 | noutput.write('\n') 45 | ipaddr = node.getAttribute('addr') 46 | noutput.write(node.getAttribute('addr')) 47 | noutput.write(',') 48 | elif node.nodeName == "port": 49 | noutput.write('\n') 50 | noutput.write(',') 51 | noutput.write(',') 52 | noutput.write(',') 53 | port.append(node.getAttribute("portid")) 54 | noutput.write(node.getAttribute("portid")) 55 | noutput.write(',') 56 | elif node.nodeName == "state": 57 | portstate.append(node.getAttribute('state')) 58 | noutput.write(node.getAttribute('state')) 59 | noutput.write(',') 60 | elif node.nodeName == "service": 61 | name.append(node.getAttribute("name")) 62 | noutput.write(node.getAttribute('name')) 63 | noutput.write(',') 64 | product.append(node.getAttribute("product")) 65 | noutput.write(node.getAttribute('product')) 66 | noutput.write(',') 67 | version.append(node.getAttribute("version")) 68 | noutput.write(node.getAttribute('version')) 69 | noutput.write(',') 70 | extrainfo.append(node.getAttribute("extrainfo")) 71 | noutput.write(node.getAttribute('extrainfo')) 72 | noutput.write(',') 73 | elif node.nodeName == 'osmatch': 74 | os = node.getAttribute('name') 75 | noutput.write(node.getAttribute('name')) 76 | noutput.write(',') 77 | 78 | with open(aoutput, 'w') as noutput: 79 | noutput.write(',,,,,,,,,\n') 80 | noutput.write('IP Address,Host Name,All Ports Filtered,Open Ports,') 81 | noutput.write('State (O/C),Service,Version,Device Type,Running,OS Details\n') 82 | for node in dom.getElementsByTagName('host'): 83 | for subnode in node.childNodes: 84 | if subnode.attributes is not None: 85 | translateXml(subnode) 86 | if len(subnode.childNodes) > 0: 87 | for subsubnode in subnode.childNodes: 88 | if subsubnode.attributes is not None: 89 | translateXml(subsubnode) 90 | if len(subsubnode.childNodes) > 0: 91 | for subsubsubnode in subsubnode.childNodes: 92 | if subsubsubnode.attributes is not None: 93 | translateXml(subsubsubnode) 94 | 95 | dom.unlink() 96 | noutput.close() 97 | print "...complete." 98 | 99 | 100 | def load_file(ainput, aoutput): 101 | """Load our XML file""" 102 | try: 103 | with open(ainput, 'r') as xmlinput: 104 | print "Loading XML" 105 | parse_xml(ainput, aoutput) 106 | except: 107 | sys.exit("Error: Something has gone horribly wrong.") 108 | 109 | 110 | def __main__(): 111 | """Get this party started""" 112 | parser = argparse.ArgumentParser(description='Nmap XML to CSV') 113 | parser.add_argument('--input-file', '-i', dest='input', help='XML file for input') 114 | parser.add_argument('--output-file', '-o', dest='output', default='nmap-output.csv', help='CSV output file') 115 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 116 | args = parser.parse_args() 117 | ainput = args.input 118 | aoutput = args.output 119 | 120 | if not args.input: 121 | sys.exit(parser.print_help()) 122 | else: 123 | load_file(ainput, aoutput) 124 | 125 | 126 | if __name__ == '__main__': 127 | __main__() 128 | 129 | -------------------------------------------------------------------------------- /Security/redirtrace.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple redirect checker for URLS 3 | 4 | import argparse 5 | import sys 6 | import requests 7 | import re 8 | 9 | 10 | def parsebody(bodydata): 11 | """Parsing body for the good stuff""" 12 | print "\nParsing body""" 13 | #print bodydata 14 | 15 | 16 | 17 | def parseheaders(headerdata): 18 | """Parsing headers for the good stuff""" 19 | server = headerdata['server'] 20 | print "`~> Server: " + server 21 | 22 | try: 23 | location = headerdata['Location'] 24 | if (location) == None: 25 | parsebody(body) 26 | else: 27 | print " `~> Header Redirect: " + location 28 | print "\n>> New request: " + location + "\n" 29 | headers = headerrequest(location) 30 | parseheaders(headers) 31 | except KeyError: 32 | print "`~> No location redirects in headers :(" 33 | 34 | 35 | def headerrequest(requrl): 36 | """Make the HTTP request""" 37 | req = requests.head(requrl) 38 | headers = req.headers 39 | status_code = req.status_code 40 | history = req.history 41 | if history == []: 42 | pass 43 | else: 44 | print "Redirect " + str(history) 45 | if status_code == 404: 46 | sys.exit("Erroring out: We got a 404") 47 | 48 | print "Request: " + str(requrl) + " (" + str(status_code) + ")" 49 | 50 | return headers 51 | 52 | 53 | def checkurl(url): 54 | """Check a URL for redirects and the like""" 55 | headers = headerrequest(url) 56 | parseheaders(headers) 57 | 58 | 59 | def __main__(): 60 | """Get this party started""" 61 | parser = argparse.ArgumentParser(description='Simple redirect follower', usage='%(prog)s -u url') 62 | parser.add_argument('--url', '-u', dest='url', help='url to check') 63 | parser.add_argument('--ssl', '-s', dest='ssl', action='store_true', help='URL is SSL enabled') 64 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 65 | args = parser.parse_args() 66 | aurl = args.url 67 | assl = args.ssl 68 | 69 | if (not args.url and args.ssl): 70 | sys.exit(parser.print_help()) 71 | 72 | if not args.url: 73 | sys.exit(parser.print_help()) 74 | 75 | # Simple sanity check to add http or https 76 | regex = re.compile(r'^https?://', re.IGNORECASE) 77 | sanitycheck = regex.search(aurl) 78 | if sanitycheck: 79 | pass 80 | else: 81 | if args.ssl: 82 | aurl = "https://" + aurl 83 | else: 84 | aurl = "http://" + aurl 85 | print "Checking: " + str(aurl) + "\n" 86 | checkurl(aurl) 87 | 88 | 89 | if __name__ == '__main__': 90 | __main__() 91 | 92 | -------------------------------------------------------------------------------- /Security/rot13.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple rotX decoder 3 | 4 | import argparse 5 | import string 6 | import sys 7 | 8 | 9 | def derot(astring): 10 | """Do some bit shifting""" 11 | rot13 = string.maketrans( 12 | "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", 13 | "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm") 14 | output = string.translate(astring, rot13) 15 | print output 16 | 17 | 18 | def menu(): 19 | """Get this party started""" 20 | parser = argparse.ArgumentParser(description='basic menu system', usage='%(prog)s -r rotation') 21 | parser.add_argument('--string', '-s', dest='string', help='string to tinker with') 22 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 23 | args = parser.parse_args() 24 | astring = args.string 25 | 26 | if not args.string: 27 | sys.exit(parser.print_help()) 28 | 29 | derot(astring) 30 | 31 | if __name__ == '__main__': 32 | menu() 33 | -------------------------------------------------------------------------------- /Security/shodan-search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Simple Shodan search script 3 | 4 | import os 5 | import argparse 6 | import sys 7 | try: 8 | import shodan 9 | except: 10 | print "You need the Shodan Python module" 11 | print "Available here: https://github.com/achillean/shodan-python" 12 | sys.exit() 13 | 14 | 15 | def load_apikey(): 16 | """Load API key from file""" 17 | fullpath = os.getenv("HOME") 18 | try: 19 | keyfile = open(fullpath + '/.shodan.key', 'r') 20 | except: 21 | sys.exit("** ERROR ** \n> Key file not found. Please check ~/.shodan.key") 22 | 23 | for line in keyfile: 24 | shodankey = line.rstrip() 25 | keyfile.close() 26 | 27 | return shodankey 28 | 29 | 30 | def shodan_ip(aip): 31 | """Search Shodan for our given IP""" 32 | apikey = load_apikey() 33 | api = shodan.Shodan(apikey) 34 | print "Searching..." 35 | host = api.host(aip) 36 | print "\nGeneral Information" 37 | print "-" * 30 38 | print """ 39 | IP: %s 40 | Organization: %s 41 | Operating System: %s 42 | """ % (host['ip_str'], host.get('org', 'n/a'), host.get('os', 'n/a')) 43 | 44 | print "All banner information" 45 | print "-" * 30 46 | for item in host['data']: 47 | print """ 48 | Port: %s 49 | Banner: %s 50 | 51 | """ % (item['port'], item['data']) 52 | 53 | 54 | def __main__(): 55 | """Get this party started""" 56 | print "Shodan API Search" 57 | parser = argparse.ArgumentParser(description='Simple Shodan Search') 58 | parser.add_argument('--ip', '-i', dest='ip', help='IP address to search') 59 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 60 | args = parser.parse_args() 61 | aip = args.ip 62 | 63 | if not args.ip: 64 | sys.exit(parser.print_help()) 65 | else: 66 | shodan_ip(aip) 67 | 68 | 69 | if __name__ == '__main__': 70 | __main__() 71 | 72 | -------------------------------------------------------------------------------- /Security/ss-binlookup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Shadowserver binary lookup 3 | 4 | import argparse 5 | import sys 6 | import json 7 | try: 8 | import requests 9 | except: 10 | print "Python requests library required" 11 | 12 | 13 | def binlookup(ahash): 14 | """HELP""" 15 | print "Checking hash against Shadow Server" 16 | ssurl = "http://bin-test.shadowserver.org/api?md5=" + str(ahash) 17 | r = requests.get(ssurl) 18 | if r.status_code == 404: 19 | print "[ERROR] 404" 20 | elif r.status_code == 200: 21 | # There has to be a better way to do this 22 | raw = r.content.split() 23 | jdata = raw[1:] 24 | dump = json.dumps(jdata) 25 | x = json.loads(dump) 26 | print "Source: " + x[3].strip(",") 27 | print "Filename: " + x[5].strip(",") 28 | print "Product: " + x[9].strip(",") 29 | print "Manufacturer: " + x[11].strip(",") 30 | print "Operating System: " + x[14] + x[15] 31 | print "OS Version: " + x[25].strip(",") 32 | print "Language: " + x[17].strip(",") 33 | print "Product Version: " + x[21].strip(",") 34 | print "File Size: " + x[29].strip(",") 35 | print "Application: " + x[27].strip(",") 36 | else: 37 | print "Something else happened" 38 | 39 | 40 | def __main__(): 41 | """Get this party started""" 42 | parser = argparse.ArgumentParser(description='Check executable against a list of known software') 43 | parser.add_argument('--hash', '-H', dest='hash', help='Hash to lookup') 44 | parser.add_argument('--version', '-v', action='version', version='%(prog)s 0.1') 45 | args = parser.parse_args() 46 | ahash = args.hash 47 | 48 | if not args.hash: 49 | sys.exit(parser.print_help()) 50 | else: 51 | binlookup(ahash) 52 | 53 | 54 | if __name__ == '__main__': 55 | __main__() 56 | -------------------------------------------------------------------------------- /Security/ssh-attacks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Simple script to parse the auth log and pull some naughty stats 3 | 4 | LOGFILE="$1" 5 | BADREGEX="Failed password for invalid" 6 | GOODREGEX="Failed password for " 7 | PASSWORDREGEX="Accepted password for" 8 | PUBKEYREGEX="Accepted publickey for" 9 | START=`head -1 ${LOGFILE} | awk -F" " '{ print $1" "$2" "$3}'` 10 | STOP=`tail -1 ${LOGFILE} | awk -F" " '{ print $1" "$2" "$3}'` 11 | 12 | if [ "${LOGFILE}" = "" ] 13 | then 14 | echo "We need a log file" 15 | exit 0 16 | fi 17 | 18 | if [ -f $LOGFILE ] 19 | then 20 | continue 21 | else 22 | echo "Log file doesn't exist" 23 | exit 0 24 | fi 25 | 26 | echo "Getting stats" 27 | echo 28 | echo "Reporting Period: ${START} - ${STOP}" 29 | 30 | echo -n "Total attacks: " 31 | grep "${BADREGEX}" ${LOGFILE} | wc -l 32 | echo -n "Total successful logins: " 33 | grep "${PASSWORDREGEX}" ${LOGFILE} | wc -l > /tmp/.totpass 34 | grep "${PUBKEYREGEX}" ${LOGFILE} | wc -l >> /tmp/.totpub 35 | TOTPASS=`cat /tmp/.totpass` 36 | TOTPUB=`cat /tmp/.totpub` 37 | TOTAL=`expr ${TOTPASS} + ${TOTPUB}` 38 | rm /tmp/.totpass /tmp/.totpub 39 | echo ${TOTAL} 40 | echo -n "Total good(ish) failed logins: " 41 | grep "${GOODREGEX}" ${LOGFILE} | grep -v "invalid" | wc -l 42 | echo 43 | 44 | echo "Usernames in use" 45 | echo "-----------------" 46 | grep "${BADREGEX}" ${LOGFILE} | awk -F" " '{ print $11 }' | sort | uniq > /tmp/.users 47 | for x in `cat /tmp/.users` 48 | do 49 | echo -n "${x}: " 50 | grep "${BADREGEX}" ${LOGFILE} | grep -w "${x}" | wc -l 51 | done 52 | rm /tmp/.users 53 | echo "-----------------" 54 | echo 55 | 56 | echo "Attackers (with attacks)" 57 | echo "------------------------" 58 | grep "${BADREGEX}" ${LOGFILE} | awk -F" " '{ print $13 }' | sort | uniq > /tmp/.attackers 59 | for x in `cat /tmp/.attackers` 60 | do 61 | echo -n "${x}: " 62 | grep ${x} ${LOGFILE} | grep "${BADREGEX}" | wc -l 63 | done 64 | rm /tmp/.attackers 65 | echo "------------------------" 66 | echo 67 | 68 | echo "Failed logins from good users" 69 | echo "--------------------------" 70 | grep "${GOODREGEX}" ${LOGFILE} | grep -v "invalid" | awk -F" " '{ print "Date: " $1" "$2" "$3 " IP: " $11" User: " $9 }' 71 | echo "--------------------------" 72 | echo 73 | 74 | echo "Successful Password Logins" 75 | echo "--------------------------" 76 | grep "${PASSWORDREGEX}" ${LOGFILE} | awk -F" " '{ print "Date: " $1" "$2" "$3 " IP: " $11" User: " $9 }' 77 | echo "--------------------------" 78 | echo 79 | 80 | echo "Successful Public Key Logins" 81 | echo "----------------------------" 82 | grep "${PUBKEYREGEX}" ${LOGFILE} | awk -F" " '{ print "Date: " $1" "$2" "$3 " IP: " $11" User: " $9 }' 83 | echo "----------------------------" 84 | echo 85 | -------------------------------------------------------------------------------- /Shodan/README.md: -------------------------------------------------------------------------------- 1 | Shodan 2 | ====== 3 | 4 | Scripts for talking to the Shodan API 5 | 6 | * shodan-tls-info.py - Get basic TLS certificate information for a host 7 | -------------------------------------------------------------------------------- /Shodan/shodan-tls-info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Pull TLS certification information for IP 3 | 4 | import shodan 5 | import sys 6 | 7 | try: 8 | host = sys.argv[1] 9 | except: 10 | sys.exit("[ERROR] We need an IP to lookup") 11 | 12 | print "[HOST] " + host 13 | 14 | SHODAN_API_KEY = "DEAR_LORD_I_POSTED_MY_API_KEY" 15 | 16 | api = shodan.Shodan(SHODAN_API_KEY) 17 | host_data = api.host(host) 18 | print "Last update: " + host_data['last_update'] 19 | 20 | data = host_data['data'] 21 | tlsdata = data[0]['ssl'] 22 | print "Expired: " + str(tlsdata['cert']['expired']) 23 | print "Expires: " + tlsdata['cert']['expires'] 24 | --------------------------------------------------------------------------------