├── gif.gif ├── README.md ├── install.py └── pystat_core.py /gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothaxor/PyStat/HEAD/gif.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyStat - Advanced Netstat For Windows 2 | #### Compatible with Python Version 2.7 3 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://www.roothaxor.in) 4 | [![PyPI](https://img.shields.io/pypi/status/Django.svg)](https://github.com/roothaxor/The-Password-Manager) 5 | 6 | #### Features 7 | * Know remote address of process 8 | * Know remote ports of process 9 | * Know which user using process along with title & PID 10 | 11 | #### Changelogs: 12 | * Auto Install python modules support added in install.py 13 | 14 | ### Installation Guide: 15 | > Download the [.zip file](https://github.com/roothaxor/PyStat/archive/master.zip) 16 | 17 | > Extract the pystat folder from .zip file to some drive i.e `C:\tools\pystat` 18 | 19 | > Goto `C:\tools\pystat` Press SHIFT KEY + RIGHT CLICK and select open Command Window here 20 | 21 | > Enter this command `python install.py`, Enjoy 22 | 23 | * Warning! Dont move pystat folder after installation, will stop working 24 | 25 | #### In Work! 26 |

27 | 28 |

29 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | from sys import platform as _platform 3 | import shutil 4 | try: 5 | from termcolor import colored 6 | except ImportError: 7 | print '[!] Failed to Import termcolor' 8 | try: 9 | choice = raw_input('[*] Wana install termcolor? [y/n] ') 10 | except KeyboardInterrupt: 11 | print '\n[!] User Interrupted Choice' 12 | sys.exit(1) 13 | if choice.strip().lower()[0] == 'y': 14 | print '[*] Attempting to Install termcolor... ', 15 | sys.stdout.flush() 16 | try: 17 | import pip 18 | pip.main(['install', '-q', 'termcolor==1.1.0']) 19 | from termcolor import colored 20 | print '[DONE]' 21 | except Exception: 22 | print '[FAIL]' 23 | sys.exit(1) 24 | elif choice.strip().lower()[0] == 'n': 25 | print '[*] User Denied Auto-install' 26 | sys.exit(1) 27 | else: 28 | print '[!] Invalid Decision' 29 | sys.exit(1) 30 | try: 31 | import colorama 32 | except ImportError: 33 | print '[!] Failed to Import colorama' 34 | try: 35 | choice = raw_input('[*] Wana install colorama? [y/n] ') 36 | except KeyboardInterrupt: 37 | print '\n[!] User Interrupted Choice' 38 | sys.exit(1) 39 | if choice.strip().lower()[0] == 'y': 40 | print '[*] Attempting to Install colorama... ', 41 | sys.stdout.flush() 42 | try: 43 | import pip 44 | pip.main(['install', '-q', 'colorama==0.3.9']) 45 | import colorama 46 | print '[DONE]' 47 | except Exception: 48 | print '[FAIL]' 49 | sys.exit(1) 50 | elif choice.strip().lower()[0] == 'n': 51 | print '[*] User Denied Auto-install' 52 | sys.exit(1) 53 | else: 54 | print '[!] Invalid Decision' 55 | sys.exit(1) 56 | 57 | 58 | if _platform == 'win32': 59 | import colorama 60 | colorama.init() 61 | 62 | def yellow(text): 63 | return colored(text, 'yellow', attrs=['bold']) 64 | 65 | def green(text): 66 | return colored(text, 'green', attrs=['bold']) 67 | 68 | def red(text): 69 | return colored(text, 'red', attrs=['bold']) 70 | 71 | def cyan(text): 72 | return colored(text, 'cyan', attrs=['bold']) 73 | 74 | loc = os.getcwd() 75 | file = loc+'\pystat.bat' 76 | contfile = loc+'\pystat_core.py' 77 | cont = '''@echo off 78 | python %s 79 | pause'''%(contfile) 80 | out = open(file, 'w') 81 | out.write(cont) 82 | out.close() 83 | os.system('cls') 84 | print green("\n\n\n[!] Script Generated pystat.bat file") 85 | dest = os.environ['WINDIR'] 86 | full_file_name = file 87 | try: 88 | shutil.copy(full_file_name, dest) 89 | except IOError: 90 | print red("\nError:")+cyan(" Permission denied While moving pystat.bat to C:\Windows") 91 | print green("\n[!] Please copy pystat.bat file to C:\Windows") 92 | print green("\n[+] For test open CMD and enter pystat\n\n\n") -------------------------------------------------------------------------------- /pystat_core.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | import os, re, time, sys 4 | from subprocess import check_output 5 | from sys import platform as _platform 6 | from termcolor import colored 7 | if _platform == 'win32': 8 | import colorama 9 | colorama.init() 10 | 11 | def yellow(text): 12 | return colored(text, 'yellow', attrs=['bold']) 13 | 14 | def green(text): 15 | return colored(text, 'green', attrs=['bold']) 16 | 17 | def red(text): 18 | return colored(text, 'red', attrs=['bold']) 19 | 20 | def cyan(text): 21 | return colored(text, 'cyan', attrs=['bold']) 22 | 23 | 24 | infrm = ''' 25 | =============================================================================================================================================================== 26 | Port RemoteIP PID Executable Name User Title 27 | ===============================================================================================================================================================''' 28 | 29 | 30 | def id_netstat_processes(): 31 | 32 | # First Run netstat to get network connections 33 | # Options 34 | # a Displays all active TCP connections and the TCP and UDP ports on which the computer is listening. 35 | # o Displays active TCP connections and includes the process ID (PID) for each 36 | # connection. You can find the application based on the PID on the Processes 37 | # tab inWindows Task Manager. This parameter can be combined with -a, -n, and -p. 38 | # n Displays active TCP connections, however, addresses and port numbers are 39 | # expressed numerically and no attempt is made to determine names. 40 | result = check_output("netstat -aon", shell=True) 41 | 42 | # Now make an array of terms to remove from the data obtained from netstat 43 | clean_up_array = [ 44 | ("Active Connections", ""), 45 | ("Proto", ""), 46 | ("Local Address", ""), 47 | ("Foreign Address", ""), 48 | ("State", ""), 49 | ("PID", ""), 50 | ("\r", ""), 51 | ("\t", " ") 52 | ] 53 | 54 | # Remove terms from the netstat data 55 | for find, replace in clean_up_array: 56 | result = result.replace(find, replace) 57 | 58 | # * Because I am feeling feisty, I will utilize an evil regular expression to extract the 59 | # netstat information via regex groups via the () command 60 | # 61 | # * Likewise Because terminal output is space padded rather than tabbed we need to account 62 | # for variable spacing via the regex (space)* or ' *' expression 63 | # 64 | # * Becuase the 1st group is either UDP or TCP use (UDP|TCP) to find either or 65 | # 66 | # * Because the 2ed group is either a IPV4 xxx.xxx.xxx.xxx or IPV6 XXXX::XXXX::XXXX::XXXX::XXXX%xx address or [::] 67 | # Use [0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]* for any or none number length with dots or 68 | # [ *[a-z0-9]*:* *[a-z0-9]*:* *[a-z0-9]*:* *[a-z0-9]*:* *[a-z0-9%]*\\] for any or none letters or numbers of : until the port : 69 | # 70 | # * Because the 3ed group is the port use any number [0-9]* 71 | # 72 | # * Because the 4th group is remote ip (i only had ipv4) or *:* use [0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*|\\[:*\\] or \\* 73 | # 74 | # * Because the 5th group is the remote ip use any number [0-9]* 75 | # 76 | # * Because the 6th group is the status use LISTENING|ESTABLISHED|TIME_WAIT|CLOSE_WAIT with any or none group find 77 | # 78 | # * Becuase the 7th group is pid use any number [0-9]* 79 | # a ugly regex string that extracts the required information into groups... does not support IPV6 remote address atm but supports local IPV6 80 | reexstring = " *(UDP|TCP) *([0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*|\\[ *[a-z0-9]*:* *[a-z0-9]*:* *[a-z0-9]*:* *[a-z0-9]*:* *[a-z0-9%]*\\]):([0-9]*) *([0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*|\\[:*\\]|\\*):(\\*|[0-9]*) *(LISTENING|ESTABLISHED|TIME_WAIT|CLOSE_WAIT)* *([0-9]*)" 81 | 82 | # Build the regex string 83 | regexcompiled = re.compile(reexstring) 84 | 85 | # Process the input 86 | items = regexcompiled.finditer(result) 87 | 88 | networkitems = [] 89 | 90 | # Loop thru the results 91 | for match in items: 92 | # we could just do data.append((match.groups())) but do this for user Configurability 93 | # Extract and trim the data obtained 94 | networktype = match.group(1).strip() 95 | localip = match.group(2).strip() 96 | localport = match.group(3).strip() 97 | remoteip = match.group(4).strip() 98 | remoteport = match.group(5).strip() 99 | 100 | # Because status can be None we need to check for None 101 | if not match.group(6) is None: 102 | status = match.group(6).strip() 103 | else: 104 | status = "" 105 | pid = match.group(7).strip() 106 | 107 | # Append items to an array for future processing 108 | networkitems.append(( localip, localport, remoteip, remoteport, status, pid)) 109 | 110 | # At this point we are ready to get a list of all PID running 111 | tasklist = check_output("tasklist /v", shell=True) 112 | 113 | # Again our console result needs to be cleaned up prior to processing 114 | clean_up_array = [ 115 | ("Image Name", "" ), 116 | ("PID", "" ), 117 | ("Session Name", "" ), 118 | ("Session#", "" ), 119 | ("Mem Usage", "" ), 120 | ("Status", "" ), 121 | ("User Name", "" ), 122 | ("CPU Time", "" ), 123 | ("Window Title", "" ), 124 | ("=",""), 125 | ("\r", ""), 126 | ("\t", " ") 127 | ] 128 | 129 | # Remove terms from the tasklist data 130 | for find, replace in clean_up_array: 131 | tasklist = tasklist.replace(find, replace) 132 | 133 | 134 | # Because application names can have spaces in them , our regex becomes a touch more complex and requires look aheads via ? 135 | # Likewise, because the terminal is heavily space padded we can safely assuming two spaces will end each segment 136 | # thus, ' *' (or space space *) and ' *' (space space space *) are used in the look ahead as group stoppers 137 | # Beyond this, wildcard (.*) for any characters are used for group extraction 138 | regexstring2 = "^(.*?) *([0-9]*) *(.*?) *([0-9]*) *([0-9,]* .) *(.*?) *(.*?) *([0-9:]*) *(.*?) " 139 | 140 | # To make life easier, a dictionary will be utilized to lookup the pid 141 | tasks = {} 142 | 143 | # Build the regex string And allow for multiline processing 144 | regexcompiled2 = re.compile(regexstring2, re.MULTILINE) 145 | 146 | # Process the input 147 | items = regexcompiled2.finditer(tasklist) 148 | 149 | # Loop thru the results 150 | for match in items: 151 | # Extract and trim the data obtained 152 | imagename = match.group(1).strip() 153 | pid = match.group(2).strip() 154 | 155 | # Sometimes this approach yields an empty string at the start check for this and continue if found 156 | if pid == '': 157 | continue 158 | 159 | sessionname = match.group(3).strip() 160 | sessionnumber = match.group(4).strip() 161 | memory = match.group(5).strip() 162 | status = match.group(6).strip() 163 | user = match.group(7).strip() 164 | cputime = match.group(8).strip() 165 | title = match.group(9).strip() 166 | 167 | # Populate our dictionary with information 168 | tasks[pid] = (imagename,sessionname,sessionnumber,memory,status,user,cputime,title) 169 | 170 | # Create a variable to hold our output 171 | output = "" 172 | # Loop thru all netstat items 173 | for item in networkitems: 174 | # Extract our array object 175 | localip, localport, remoteip, remoteport, status, pid = item 176 | 177 | # See if the PID exists within our PID array 178 | if pid in tasks.keys(): 179 | # If so extract the PID information and add it to the output 180 | imagename,sessionname,sessionnumber,memory,status,user,cputime,title = tasks[pid] 181 | output += localport.ljust(10) + remoteip.ljust(20) + pid.ljust(10) + imagename.ljust(35) + user.ljust(35) + title + "\n" 182 | else: 183 | # If not report the error in the output, if this happens then the application is likely something hidden deep in 184 | # administrative privileges and googling will be required to attempt to access it. This is the domain of viruses! 185 | output += localport.ljust(10) + remoteip.ljust(20) + "PID "+ pid +" Missing" + "\n" 186 | 187 | # Print output, resize Dos screen size 188 | os.system('mode 160') 189 | os.system('title Python netstat v.0.0.7') 190 | print green(infrm) 191 | print cyan(output) 192 | # This is our application entry point 193 | if __name__ == "__main__": 194 | # Run our extraction function 195 | id_netstat_processes() --------------------------------------------------------------------------------