summaryrefslogtreecommitdiff
path: root/tmap
blob: 4f120bf117f90628bb760224d60fc882ac9ca62d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/python
from socket import *
import socks
import argparse
import time
from ipaddress import *

## This function tries to open a connection on a specific port
def connScan(host, port, wait, notor):
	## If notor is set to True, it doesn't use the socks proxy
	if notor:
		sckt = socket(AF_INET, SOCK_STREAM)
	else:
		sckt = socks.socksocket()

	sckt.settimeout(wait)
	## Try to connect, return True on success and False on failure
	try:
		sckt.connect((host, port))
		sckt.close()
		return True
	except KeyboardInterrupt:
		exit()
	except:
		return False


## This function goes throgh all ports and calls connScan for each one
def portScan(host, ports, wait, notor):
	openports = list()
	for p in ports:
		if connScan(host, p, wait, notor):
			openports.append(p)
	return openports

## This function goes throgh all hosts and calls portScan for each one
def hostScan(host, ports, wait, notor):
	ret = dict()
	## Check if python version 3
	try:
		host = unicode(host)
	except:
		pass

	## Check if host is a network range, don't use tor for private IPs
	try:
		ips = ip_network(host)
		if ips.num_addresses > 1:
			for ip in ips.hosts():
				if ip.is_private:
					ret[str(ip)] = portScan(str(ip), ports, wait, True)
				else:
					ret[str(ip)] = portScan(str(ip), ports, wait, notor)
		else:
			if ips.is_private:
				ret[str(host)] = portScan(str(host), ports, wait, True)
			else:
				ret[str(host)] = portScan(str(host), ports, wait, notor)
	## Otherwise scan host as usual
	except:
		if host == 'localhost':
			ret[str(host)] = portScan(str(host), ports, wait, True)
		else:
			ret[str(host)] = portScan(str(host), ports, wait, notor)

	return ret

def main():
	startTime = time.time()

	## Define and parse the arguments
	parser = argparse.ArgumentParser(description="Simple port scanner that works over Tor")
	parser.add_argument("--version", dest="version", help="print version info and exit", action="store_true")
	parser.add_argument("HOSTS", help="IP or domain to scan", default="empty_host", nargs="?")
	parser.add_argument("-H", "--hosts", metavar="HOSTS", dest="tgtHost", help="IP or domain to scan", default="empty_host_option")
	parser.add_argument("-p", "--ports", metavar="PORTS", dest="tgtPort", help="ports to scan", default="20-25,53,80-85,443-445,8080,8333,9050,9150")
	parser.add_argument("-t", "--timeout", metavar="TIMEOUT", dest="sockTimeout", type=int, help="seconds to wait before connection timeout for each port", default=2)
	parser.add_argument("--clearnet", dest="clearnet", help="don't use Tor for scanning", action="store_true")
	parser.add_argument("--torport", metavar="TORPORT", dest="torPort", type=int, help="port for Tor proxy", default="9050")

	args = parser.parse_args()

	## Version argument
	if args.version:
		print("Tmap 1.0.0")
		print("License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>")
		print("This is free software: you are free to change and redistribute it.")
		print("There is NO WARRANTY, to the extent permitted by law.")
		exit()

	## Combine HOST and --hosts values
	if args.HOSTS == "empty_host":
		if args.tgtHost == "empty_host_option":
			parser.print_help()
			print ("Host must be specified")
			exit()
		else:
			args.HOSTS = args.tgtHost
	else:
		if args.tgtHost != "empty_host_option":
			args.HOSTS = args.HOSTS + "," + args.tgtHost

	## Set Tor as default Tor proxy for the scanner
	socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", args.torPort)

	## Load specified ports into PORTS list
	PORTS = list()
	for p in args.tgtPort.split(","):
		if "-" not in p:
			try:
				p = int(p)
				PORTS.append(p)
			except:
				parser.print_help()
				exit()
		else:
			try:
				p = list(map(int, p.split("-")))
			except:
				parser.print_help()
				exit()
			if len(p) != 2 or p[0]>p[1]:
				parser.print_help()
				exit()
			else:
				p = list(range(p[0],p[1]+1))
				PORTS += p

	## Load other variables
	HOSTS = args.HOSTS.split(",")
	WAIT_TIME = args.sockTimeout
	CLEARNET = False

	if args.clearnet:
		CLEARNET=True

	if CLEARNET == False:
		if connScan("127.0.0.1", args.torPort, 3, True):
			pass
		else:
			print("Tor is not running on port {}.".format(args.torPort))
			exit()

	## Scan each host in HOSTS list
	r = dict()
	for h in HOSTS:
		r = hostScan(h, PORTS, WAIT_TIME, CLEARNET)
		for i in r.keys():
			if len(r[i]) != 0:
				print('{} open ports: {}'.format(i, str(r[i])))

	endTime = time.time()
	totalTime = endTime - startTime
	print("Scan done in {} seconds".format(round(totalTime, 2)))

if __name__ == "__main__":
	main()