torbot 1.2__py3.6.egg

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
EGG-INFO/PKG-INFO ADDED
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 1.0
2
+ Name: torBot
3
+ Version: 1.2
4
+ Summary: OSINT tool for Deep and Dark Web
5
+ Home-page: UNKNOWN
6
+ Author: UNKNOWN
7
+ Author-email: UNKNOWN
8
+ License: GNU GPLV3.0
9
+ Description: UNKNOWN
10
+ Keywords: tor dark web osint
11
+ Platform: UNKNOWN
EGG-INFO/SOURCES.txt ADDED
@@ -0,0 +1,23 @@
1
+ setup.py
2
+ torBot
3
+ torBot.py
4
+ modules/__init__.py
5
+ modules/bcolors.py
6
+ modules/getemails.py
7
+ modules/getweblinks.py
8
+ modules/go_get_urls.so
9
+ modules/go_linker.py
10
+ modules/info.py
11
+ modules/pagereader.py
12
+ modules/savefile.py
13
+ modules/updater.py
14
+ tests/__init__.py
15
+ tests/test_getemails.py
16
+ tests/test_getweblinks.py
17
+ tests/test_pagereader.py
18
+ tests/test_savetofile.py
19
+ torBot.egg-info/PKG-INFO
20
+ torBot.egg-info/SOURCES.txt
21
+ torBot.egg-info/dependency_links.txt
22
+ torBot.egg-info/requires.txt
23
+ torBot.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+
@@ -0,0 +1 @@
1
+ modules/go_get_urls.so
EGG-INFO/not-zip-safe ADDED
@@ -0,0 +1 @@
1
+
EGG-INFO/requires.txt ADDED
@@ -0,0 +1,8 @@
1
+ PySocks>=1.6.7
2
+ beautifulsoup4>=4.6.0
3
+ pyinstaller>=3.3.1
4
+ pytest>=3.4.2
5
+ requests>=2.18.4
6
+ requests_mock>=1.4.0
7
+ termcolor>=1.1.0
8
+ tldextract>=2.2.0
@@ -0,0 +1,188 @@
1
+ import argparse
2
+ import socket
3
+ import socks
4
+ from modules import (bcolors, getemails, pagereader, getweblinks, updater,
5
+ info, go_linker, savefile)
6
+
7
+ # TorBot VERSION
8
+ __VERSION = "1.2"
9
+ LOCALHOST = "127.0.0.1"
10
+ PORT = 9050
11
+
12
+
13
+ def connect(address, port):
14
+ """ Establishes connection to port
15
+
16
+ Assumes port is bound to localhost, if host that port is bound to changes
17
+ then change the port
18
+
19
+ Args:
20
+ address: address for port to bound to
21
+ port: Establishes connect to this port
22
+ """
23
+ socks.set_default_proxy(socks.PROXY_TYPE_SOCKS5, address, port)
24
+ socket.socket = socks.socksocket # Monkey Patch our socket to tor socket
25
+
26
+ def getaddrinfo(*args):
27
+ """
28
+ Overloads socket function for std socket library
29
+ Check socket.getaddrinfo() documentation to understand parameters.
30
+ Simple description below:
31
+ argument - explanation (actual value)
32
+ socket.AF_INET - the type of address the socket can speak to (IPV4)
33
+ sock.SOCK_STREAM - creates a stream connecton rather than packets
34
+ 6 - protocol being used is TCP
35
+ Last two arguments should be a tuple containing the address and port
36
+ """
37
+ return [(socket.AF_INET, socket.SOCK_STREAM, 6,
38
+ '', (args[0], args[1]))]
39
+ socket.getaddrinfo = getaddrinfo
40
+
41
+
42
+ def header():
43
+ """
44
+ Prints out header ASCII art
45
+ """
46
+
47
+ b_color = bcolors.Bcolors()
48
+ D3DSEC = b_color.FAIL + " D3DSEC " + b_color.WHITE
49
+ INS1DE = b_color.FAIL + " INS1DE " + b_color.WHITE
50
+
51
+ header = r"""
52
+ {WHITE}
53
+ ######################################################
54
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWMMMMMMMMMMMMM
55
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWMMMMMMMMMMMMMM
56
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXNWWWWWMMMMMMMMMM
57
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWX0KXXKKXWMMMMMMMMMMM
58
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNNKOkOOkOXWMMMMMMMMMMMMM
59
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMMNX0kdodoxKWMMMMMMMMMMMMMMM
60
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMW0doccloONMWWMMMMMMMMMMMMMM
61
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMKl;;:cxKWMMMMMMMMMMMMMMMMMM
62
+ MMMMMMMMMMMMMMMMMMMMMMWKOXNx;,,cONMMMMMMMMMMMMMMMMMMMM
63
+ MMMMMMMMMMMMMMMMMMMMMMMXdxKk:',lONMMMM{D3DSEC}MMMMMMMM
64
+ MMMMMMMMMMMMMMMMMMMMMMMMOo0NOdxc,kMMMM{INS1DE}MMMMMMMM
65
+ MMMMMMMMMMMMMMMMMMMMMMMMOcONOxkx;dWMMMMMMMMMMMMMMMMMMM
66
+ MMMMMMMMMMMMMMMMMMMMMMNkcdXXOkxkd:oXMMMMMMMMMMMMMMMMMM
67
+ MMMMMMMMMMMMMMMMMMMNOoclONNX00OkOxc:lkXWMMMMMMMMMMMMMM
68
+ MMMMMMMMMMMMMMMMN0olld0NWNNX0O00kxkxl:;ckXMWWMMMMMMMMM
69
+ MMMMMMMMMMMWMMNxccd0NNNNNXNXOkOK0dodxdo:,;o0WMMMMMMMMM
70
+ MMMMMMMMMMMMNk:ckXNNWNXXXXNXOOOOK0oloooooc,'oKMMMMMMMM
71
+ MMMMMMMMMMMXc;xXNNNXKXXXNNWKOO0Ok0x:clllllc:.,OWMMMMMM
72
+ MMMMMMMMMMX:;0WNNX00XNNNNNNKOO0KkkOc,ccccccc:.'OWMMMMM
73
+ MMMMMMMMMNl,ONNN0OXNNNNNXXNKOkOK0xkl':c::::::;.;KMMMMM
74
+ MMMMMMMMM0,lNWXO0NNNNXKKXXNXO0Ok0Oxl',:;;;;;;;..dMMMMM
75
+ MMMMMMMMMk,xWNOONNNX00XNNNWKOO0OkOxc'';;,,,,,,'.cMMMMM
76
+ MMMMMMMMMx,xWKkKWNXOKNWNNNX0xxOKxxx:..,,,,,''''.cMMMMM
77
+ MMMMMMMMM0,oWXkOWXOKNNNNN00Xkdx0kdd;..,'''''''..oMMMMM
78
+ MMMMMMMMMNl;0W0kKKkKWNNN0ONNOxdOOll,..'''......,0MMMMM
79
+ MMMMMMMMMMK::KN0kKOkNNWXk0WX0kdxkc:............xWMMMMM
80
+ MMMMMMMMMMMKl:kX0k0kONWNOONX0koxd:,..........'kWMMMMMM
81
+ MMMMMMMMMMMMNxccxOkkxkKWKx0NOoooc'..........lKWMMMMMMM
82
+ MMMMMMMMMMMMMWNklccclldk0OxOdcc;. .......;oKWWMMMMMMMM
83
+ MMMMMMMMMMMMMMMMWXOdl:::;cc;'... ..',:lx0NMMMMMMMMMMMM
84
+ MMMMMMMMMMMMMMMMMMMMMNKOkxddolloodk0XWMMMMMMMMMMMMMMMM
85
+ {FAIL} + {BOLD}
86
+ __ ____ ____ __ ______
87
+ / /_/ __ \/ __ \/ /_ ____/_ __/
88
+ / __/ / / / /_/ / __ \/ __ \/ /
89
+ / /_/ /_/ / _, _/ /_/ / /_/ / /
90
+ \__/\____/_/ |_/_____/\____/_/ V{VERSION}
91
+ {FAIL} + {On_Black}
92
+ #######################################################
93
+ # TorBot - A python Tor Crawler #
94
+ # GitHub : https://github.com/DedsecInside/TorBot #
95
+ # Help : use -h for help text #
96
+ #######################################################
97
+ {FAIL} + "LICENSE: GNU Public License" + {END}""".format(
98
+ D3DSEC=D3DSEC, INS1DE=INS1DE, FAIL=b_color.FAIL,
99
+ BOLD=b_color.BOLD, VERSION=__VERSION, END=b_color.ENDC,
100
+ On_Black=b_color.On_Black, WHITE=b_color.WHITE
101
+ )
102
+ print(header)
103
+
104
+
105
+ def main(conn=False, link=False):
106
+ if conn:
107
+ connect(LOCALHOST, PORT)
108
+
109
+ parser = argparse.ArgumentParser()
110
+ parser.add_argument("-v", "--version",
111
+ action="store_true",
112
+ help="Show current version of TorBot.")
113
+ parser.add_argument("--update",
114
+ action="store_true",
115
+ help="Update TorBot to the latest stable version")
116
+ parser.add_argument("-q", "--quiet",
117
+ action="store_true")
118
+ parser.add_argument("-u", "--url",
119
+ help="Specifiy a website link to crawl")
120
+ parser.add_argument("-s", "--save",
121
+ action="store_true",
122
+ help="Save results in a file")
123
+ parser.add_argument("-m", "--mail",
124
+ action="store_true",
125
+ help="Get e-mail addresses from the crawled sites")
126
+ parser.add_argument("-e", "--extension",
127
+ action='append',
128
+ dest='extension',
129
+ default=[],
130
+ help=' '.join(("Specifiy additional website extensions",
131
+ "to the list(.com , .org etc)")))
132
+ parser.add_argument("-l", "--live",
133
+ action="store_true",
134
+ help="Check if websites are live or not (slow)")
135
+ parser.add_argument("-i", "--info",
136
+ action="store_true",
137
+ help=' '.join(("Info displays basic info of the",
138
+ "scanned site, (very slow)")))
139
+ args = parser.parse_args()
140
+
141
+ link = args.url
142
+
143
+ # If flag is -v, --update, -q/--quiet then user only runs that operation
144
+ # because these are single flags only
145
+ if args.version:
146
+ print("TorBot Version:" + __VERSION)
147
+ exit()
148
+ if args.update:
149
+ updater.updateTor()
150
+ exit()
151
+ if not args.quiet:
152
+ header()
153
+ # If url flag is set then check for accompanying flag set. Only one
154
+ # additional flag can be set with -u/--url flag
155
+ if args.url:
156
+ print("Tor IP Address :", pagereader.get_ip())
157
+ html_content, response = pagereader.read_first_page(link)
158
+ # -m/--mail
159
+ if args.mail:
160
+ emails = getemails.getMails(html_content)
161
+ print(emails)
162
+ if args.save:
163
+ savefile.saveJson('Emails', emails)
164
+ # -i/--info
165
+ elif args.info:
166
+ info.executeAll(link, html_content, response)
167
+ if args.save:
168
+ print('Nothing to save.\n')
169
+ else:
170
+ # Golang library is now being used
171
+ links = go_linker.GetLinks(link, LOCALHOST, PORT, 15, 1)
172
+ return links
173
+ # links = getweblinks.get_links(soup=html_content, ext=args.extension, live=args.live)
174
+ if args.save:
175
+ savefile.saveJson("Links", links)
176
+ else:
177
+ print("usage: torBot.py [-h] [-v] [--update] [-q] [-u URL] [-s] [-m] [-e EXTENSION] [-l] [-i]")
178
+
179
+ print("\n\n")
180
+
181
+
182
+ if __name__ == '__main__':
183
+
184
+ try:
185
+ main(conn=True)
186
+
187
+ except KeyboardInterrupt:
188
+ print("Interrupt received! Exiting cleanly...")
EGG-INFO/top_level.txt ADDED
@@ -0,0 +1,2 @@
1
+ modules
2
+ tests
modules/__init__.py ADDED
File without changes
Binary file
modules/bcolors.py ADDED
@@ -0,0 +1,14 @@
1
+ class Bcolors:
2
+
3
+ def __init__(self):
4
+ self.HEADER = '\033[95m'
5
+ self.OKBLUE = '\033[94m'
6
+ self.OKGREEN = '\033[92m'
7
+ self.WARNING = '\033[93m'
8
+ self.FAIL = '\033[91m'
9
+ self.ENDC = '\033[0m'
10
+ self.BOLD = '\033[1m'
11
+ self.UNDERLINE = '\033[4m'
12
+ self.WHITE = '\033[97m'
13
+ self.On_Black = '\033[40m'
14
+ self.On_Red = '\033[41m'
modules/getemails.py ADDED
@@ -0,0 +1,41 @@
1
+ from modules.bcolors import Bcolors
2
+ from bs4 import BeautifulSoup
3
+
4
+
5
+ def getMails(soup):
6
+
7
+ """
8
+ Searches for <a href> tags for links then checks if link contains the
9
+ substring 'mailto' indicating that it's an email. If it is determined
10
+ to be an email then the link is split and the username is appeneded to
11
+ the list
12
+
13
+ Args:
14
+ soup: BeautifulSoup isntance that will be used for parsing
15
+
16
+ Returns:
17
+ emails: list of email IDs
18
+ """
19
+ b_colors = Bcolors()
20
+
21
+ if isinstance(type(soup), type(BeautifulSoup)):
22
+
23
+ emails = []
24
+ links = soup.find_all('a')
25
+ for ref in links:
26
+ url = ref.get('href')
27
+ if url and 'mailto' in url:
28
+ """Split email address on"""
29
+ email_addr = url.split(':')
30
+ if (len(email_addr) > 1):
31
+ emails.append(email_addr[1])
32
+
33
+ """Pretty print output as below"""
34
+ print ('')
35
+ print (b_colors.OKGREEN+'Mails Found - '+b_colors.ENDC+str(len(emails)))
36
+ print ('-------------------------------')
37
+
38
+ return emails
39
+
40
+ else:
41
+ raise('Method parameter is not of instance BeautifulSoup')
modules/getweblinks.py ADDED
@@ -0,0 +1,136 @@
1
+ import re
2
+ import requests
3
+ import tldextract
4
+
5
+ from modules import pagereader
6
+ from bs4 import BeautifulSoup
7
+ from modules.bcolors import Bcolors
8
+ from requests.exceptions import ConnectionError, HTTPError
9
+
10
+
11
+ def valid_url(url, extensions=False):
12
+ """Checks for any valid url using regular expression matching
13
+
14
+ Matches all possible url patterns with the url that is passed and
15
+ returns True if it is a url and returns False if it is not.
16
+
17
+ Args:
18
+ url: string representing url to be checked
19
+
20
+ Returns:
21
+ bool: True if valid url format and False if not
22
+ """
23
+ pattern = r"^https?:\/\/(www\.)?([a-z,A-Z,0-9]*)\.([a-z, A-Z]+)(.*)"
24
+ regex = re.compile(pattern)
25
+ if not extensions:
26
+ if regex.match(url):
27
+ return True
28
+ return False
29
+
30
+ parts = tldextract.extract(url)
31
+ valid_sites = list()
32
+ for ext in extensions:
33
+ if regex.match(url) and '.'+parts.suffix in ext:
34
+ valid_sites.append(url)
35
+ return valid_sites
36
+
37
+
38
+ def valid_onion_url(url):
39
+ """Checks for valid onion url using regular expression matching
40
+
41
+ Only matches onion urls
42
+
43
+ Args:
44
+ url: string representing url to be checked
45
+
46
+ Returns:
47
+ bool: True if valid onion url format, False if not
48
+ """
49
+ pattern = r"^https?:\/\/(www\.)?([a-z,A-Z,0-9]*)\.onion/(.*)"
50
+ regex = re.compile(pattern)
51
+ if regex.match(url):
52
+ return True
53
+ return False
54
+
55
+
56
+ def is_link_alive(link):
57
+ """Generator that yields links as they come
58
+
59
+ Uses head request because it uses less bandwith than get and timeout is
60
+ set to 10 seconds and then link is automatically declared as dead.
61
+
62
+ Args:
63
+ link: link to be tested
64
+ colors: object containing colors for link
65
+
66
+ Yields:
67
+ string: link with either no color or red which indicates failure
68
+ """
69
+
70
+ try:
71
+ resp = requests.head(link, timeout=10)
72
+ resp.raise_for_status()
73
+ return True
74
+ except (ConnectionError, HTTPError):
75
+ return False
76
+
77
+
78
+ def add_green(link):
79
+ colors = Bcolors()
80
+ return '\t' + colors.OKGREEN + link + colors.ENDC
81
+
82
+
83
+ def add_red(link):
84
+ colors = Bcolors()
85
+ return '\t' + colors.On_Red + link + colors.ENDC
86
+
87
+
88
+ def get_links(soup, ext=False, live=False):
89
+ """
90
+ Searches through all <a ref> (hyperlinks) tags and stores them in a
91
+ list then validates if the url is formatted correctly.
92
+
93
+ Args:
94
+ soup: BeautifulSoup instance currently being used.
95
+
96
+ Returns:
97
+ websites: List of websites that were found
98
+ """
99
+ b_colors = Bcolors()
100
+ if isinstance(soup, BeautifulSoup):
101
+ websites = []
102
+
103
+ links = soup.find_all('a')
104
+ for ref in links:
105
+ url = ref.get('href')
106
+ if ext:
107
+ if url and valid_url(url, ext):
108
+ websites.append(url)
109
+ else:
110
+ if url and valid_onion_url(url):
111
+ websites.append(url)
112
+
113
+ """Pretty print output as below"""
114
+ print(''.join((b_colors.OKGREEN,
115
+ 'Websites Found - ', b_colors.ENDC, str(len(websites)))))
116
+ print('------------------------------------')
117
+
118
+ if live:
119
+ for link in websites:
120
+ if is_link_alive(link):
121
+ coloredlink = add_green(link)
122
+ page = pagereader.read_page(link)
123
+ if page is not None and page.title is not None:
124
+ print_row(coloredlink, page.title.string)
125
+ else:
126
+ coloredlink = add_red(link)
127
+ print_row(coloredlink, "Not found")
128
+
129
+ return websites
130
+
131
+ else:
132
+ raise(Exception('Method parameter is not of instance BeautifulSoup'))
133
+
134
+
135
+ def print_row(url, description):
136
+ print("%-80s %-30s" % (url, description))
modules/go_get_urls.so ADDED
Binary file
modules/go_linker.py ADDED
@@ -0,0 +1,26 @@
1
+ import os.path
2
+
3
+ from ctypes import cdll, c_char_p, c_longlong, c_int, Structure
4
+
5
+ dll_path = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + "go_get_urls.so"
6
+ go_linker = cdll.LoadLibrary(dll_path)
7
+
8
+
9
+ class GoString(Structure):
10
+ _fields_ = [("p", c_char_p), ("n", c_longlong)]
11
+
12
+
13
+ go_linker.GetLinks.argtypes = [GoString, GoString, GoString, c_int, c_int]
14
+
15
+
16
+ def GetLinks(url, addr, port, timeout, extensions):
17
+
18
+ url = url.encode('utf-8')
19
+ addr = addr.encode('utf-8')
20
+ port = str(port).encode('utf-8')
21
+
22
+ go_linker.GetLinks(GoString(url, len(url)),
23
+ GoString(addr, len(addr)),
24
+ GoString(port, len(port)),
25
+ timeout,
26
+ extensions)
modules/info.py ADDED
@@ -0,0 +1,101 @@
1
+ import requests
2
+
3
+ from urllib.parse import urlsplit
4
+ from termcolor import cprint
5
+
6
+
7
+ def executeAll(target, soup, response):
8
+
9
+ try:
10
+ get_robots_txt(target)
11
+ except Exception:
12
+ cprint("No robots.txt file Found!""blue")
13
+ try:
14
+ get_dot_git(target)
15
+ except Exception:
16
+ cprint("Error !""red")
17
+ try:
18
+ get_dot_svn(target)
19
+ except Exception:
20
+ cprint("Error""red")
21
+ try:
22
+ get_dot_htaccess(target)
23
+ except Exception:
24
+ cprint("Error""red")
25
+ try:
26
+ get_webpage_description(soup)
27
+ except Exception:
28
+ cprint("Error""red")
29
+ try:
30
+ get_headers(response)
31
+ except Exception:
32
+ cprint("Error""red")
33
+
34
+
35
+ def get_headers(response):
36
+ print('''
37
+ RESPONSE HEADERS
38
+ __________________
39
+ ''')
40
+ for key, val in response.headers.items():
41
+ print('*', key, ':', val)
42
+
43
+
44
+ def get_robots_txt(target):
45
+ cprint("[*]Checking for Robots.txt"'yellow')
46
+ url = target
47
+ target = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
48
+ requests.get(target+"/robots.txt")
49
+ cprint(r'blue')
50
+
51
+
52
+ def get_dot_git(target):
53
+ cprint("[*]Checking for .git folder"'yellow')
54
+ url = target
55
+ target = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
56
+ req = requests.get(target+"/.git/")
57
+ r = req.status_code
58
+ if r == 200:
59
+ cprint("Alert!"'red')
60
+ cprint(".git folder exposed publicly"'red')
61
+ else:
62
+ print("NO .git folder found"'blue')
63
+
64
+
65
+ def get_dot_svn(target):
66
+ cprint("[*]Checking for .svn folder"'yellow')
67
+ url = target
68
+ target = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
69
+ req = requests.get(target+"/.svn/entries")
70
+ r = req.status_code
71
+ if r == 200:
72
+ cprint("Alert!"'red')
73
+ cprint(".SVN folder exposed publicly"'red')
74
+ else:
75
+ cprint("NO .SVN folder found"'blue')
76
+
77
+
78
+ def get_dot_htaccess(target):
79
+ cprint("[*]Checking for .htaccess"'yellow')
80
+ url = target
81
+ target = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
82
+ req = requests.get(target+"/.htaccess")
83
+ statcode = req.status_code
84
+ if statcode == 403:
85
+ cprint("403 Forbidden"'blue')
86
+ elif statcode == 200:
87
+ cprint("Alert!!"'blue')
88
+ cprint(".htaccess file found!"'blue')
89
+ else:
90
+ cprint("Status code"'blue')
91
+ cprint(statcode)
92
+
93
+
94
+ def get_webpage_description(soup):
95
+ cprint("[*]Checking for description meta tag"'yellow')
96
+ metatags = soup.find_all('meta')
97
+ for meta in metatags:
98
+ if meta.has_attr('name'):
99
+ attributes = meta.attrs
100
+ if attributes['name'] == 'description':
101
+ cprint("Page description: " + attributes['content'])
modules/pagereader.py ADDED
@@ -0,0 +1,109 @@
1
+ import requests
2
+
3
+ from bs4 import BeautifulSoup
4
+ from modules.bcolors import Bcolors
5
+ from requests.exceptions import ConnectionError, HTTPError, MissingSchema
6
+ from sys import exit
7
+
8
+
9
+ def connection_msg(site):
10
+ yield "Attempting to connect to {site}".format(site=site)
11
+
12
+
13
+ def read_first_page(site):
14
+ headers = {'User-Agent':
15
+ 'TorBot - Onion crawler | www.github.com/DedSecInside/TorBot'}
16
+ attempts_left = 3
17
+ err = " "
18
+ while attempts_left:
19
+ try:
20
+ if attempts_left == 3:
21
+ print(next(connection_msg(site)))
22
+ response = requests.get(site, headers=headers)
23
+ print("Connection successful.")
24
+ page = BeautifulSoup(response.text, 'html.parser')
25
+ return page, response
26
+ if attempts_left == 2:
27
+ print(next(connection_msg('https://'+site)))
28
+ response = requests.get('https://'+site, headers=headers)
29
+ print("Connection successful.")
30
+ page = BeautifulSoup(response.text, 'html.parser')
31
+ return page, response
32
+ if attempts_left == 1:
33
+ print(next(connection_msg('http://'+site)))
34
+ response = requests.get('http://'+site, headers=headers)
35
+ print("Connection successful.")
36
+ page = BeautifulSoup(response.text, 'html.parser')
37
+ return page, response
38
+ if not attempts_left:
39
+ msg = ''.join(("There has been an {err} while attempting to ",
40
+ "connect to {site}.")).format(err=err, site=site)
41
+ exit(msg)
42
+
43
+ except (HTTPError, MissingSchema, ConnectionError) as e:
44
+ attempts_left -= 1
45
+ err = e
46
+
47
+ if isinstance(err, HTTPError):
48
+ print ("There has been an HTTP error after three attempts.")
49
+ exit (1)
50
+ if isinstance(err, ConnectionError):
51
+ print("Got ConnectionError after three attempts... ",
52
+ "Please check if the TOR service is running or not.")
53
+ exit (1)
54
+
55
+
56
+ def read_page(site):
57
+ headers = {'User-Agent':
58
+ 'TorBot - Onion crawler | www.github.com/DedSecInside/TorBot'}
59
+ attempts_left = 3
60
+ err = " "
61
+ while attempts_left:
62
+ try:
63
+ if attempts_left == 3:
64
+ #print(next(connection_msg(site)))
65
+ response = requests.get(site, headers=headers)
66
+ #print("Connection successful.")
67
+ page = BeautifulSoup(response.text, 'html.parser')
68
+ return page
69
+ if attempts_left == 2:
70
+ #print(next(connection_msg('https://'+site)))
71
+ response = requests.get('https://'+site, headers=headers)
72
+ #print("Connection successful.")
73
+ page = BeautifulSoup(response.text, 'html.parser')
74
+ return page
75
+ if attempts_left == 1:
76
+ #print(next(connection_msg('http://'+site)))
77
+ response = requests.get('http://'+site, headers=headers)
78
+ #print("Connection successful.")
79
+ page = BeautifulSoup(response.text, 'html.parser')
80
+ return page
81
+ if not attempts_left:
82
+ msg = ''.join(("There has been an {err} while attempting to ",
83
+ "connect to {site}.")).format(err=err, site=site)
84
+ exit(msg)
85
+
86
+ except (HTTPError, MissingSchema, ConnectionError) as e:
87
+ attempts_left -= 1
88
+ err = e
89
+
90
+ if isinstance(err, HTTPError):
91
+ print("There has been an HTTP error after three attempts.")
92
+ exit (1)
93
+ if isinstance(err, ConnectionError):
94
+ print("There has been a connection error after three attempts.")
95
+ exit (1)
96
+
97
+ def get_ip():
98
+ """Returns users tor ip address
99
+
100
+ https://check.torproject.org/ tells you if you are using tor and it
101
+ displays your IP address which we scape and return
102
+ """
103
+
104
+ b_colors = Bcolors()
105
+ page = read_first_page('https://check.torproject.org/')[0]
106
+ pg = page.find('strong')
107
+ ip_addr = pg.renderContents()
108
+
109
+ return b_colors.WARNING+b_colors.BOLD+ip_addr.decode("utf-8")+b_colors.ENDC
modules/savefile.py ADDED
@@ -0,0 +1,24 @@
1
+ import json
2
+ import time
3
+
4
+
5
+ def saveJson(datatype, data):
6
+ """
7
+ Creates json file and stores json
8
+
9
+ Args:
10
+ datatype: the type of the object being passed
11
+ data = data that is being stored with object
12
+ """
13
+
14
+ timestr = time.strftime("%Y%m%d-%H%M%S")
15
+ file_name = "TorBot-Export-"+datatype+timestr+".json"
16
+ # Json File Creation
17
+ with open(file_name, "w+") as f:
18
+ # Store data in Json format
19
+ output = {datatype: data}
20
+ # Dump output to file
21
+ json.dump(output, f, indent=2)
22
+
23
+ print("\nData will be saved with a File Name :", file_name)
24
+ return file_name
modules/updater.py ADDED
@@ -0,0 +1,48 @@
1
+ import subprocess
2
+
3
+
4
+ def updateTor():
5
+
6
+ """
7
+ Currently updates Tor by calling terminal commands using subprocess
8
+ Not a great method and will be replaced in the future.
9
+
10
+ """
11
+
12
+ print("Checking for latest stable release")
13
+ isGit = subprocess.Popen(
14
+ ["git", "branch"],
15
+ stdout=subprocess.PIPE,
16
+ stderr=subprocess.STDOUT)
17
+ output = isGit.stdout.read()
18
+ branch = output[2:8].decode("utf-8")
19
+ print(branch)
20
+ if branch == 'master':
21
+ update = subprocess.Popen(
22
+ ["git", "pull", "origin", "master"],
23
+ stdout=subprocess.PIPE,
24
+ stderr=subprocess.STDOUT)
25
+ update_out = update.stdout.read()
26
+ if update_out[90:109].decode("utf-8") == 'Already up-to-date.':
27
+ print("TorBot is already up-to-date.")
28
+ else:
29
+ print("TorBot has succesfully updated to latest stable version.")
30
+ else:
31
+ subprocess.Popen(
32
+ ["git", "init"],
33
+ stdout=subprocess.PIPE,
34
+ stderr=subprocess.STDOUT)
35
+ subprocess.Popen(
36
+ ["git", "remote", "add", "origin",
37
+ "https://github.com/DedSecInside/TorBoT.git"],
38
+ stdout=subprocess.PIPE,
39
+ stderr=subprocess.STDOUT)
40
+ update = subprocess.Popen(
41
+ ["git", "pull", "origin", "dev"],
42
+ stdout=subprocess.PIPE,
43
+ stderr=subprocess.STDOUT)
44
+ update_out = update.stdout.read()
45
+ if update_out[90:109].decode("utf-8") == 'Already up-to-date.':
46
+ print("TorBot is already up-to-date.")
47
+ else:
48
+ print("TorBot has succesfully updated to latest stable version.")
tests/__init__.py ADDED
File without changes
@@ -0,0 +1,20 @@
1
+ import sys
2
+ import os
3
+
4
+ PACKAGE_PARENT = '..'
5
+ SCRIPT_DIR = os.path.dirname(os.path.realpath(
6
+ os.path.join(os.getcwd(), os.path.expanduser(__file__))))
7
+
8
+ sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
9
+
10
+ from modules import pagereader, getemails
11
+
12
+
13
+ def test_get_emails_successful():
14
+ soup = pagereader.read_first_page('https://www.helloaddress.com/')[0]
15
+ test_emails = ["hello@helloaddress.com"]
16
+ emails = getemails.getMails(soup)
17
+ assert emails == test_emails
18
+
19
+ if __name__ == '__main__':
20
+ test_get_emails_successful()
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python
2
+
3
+ import sys
4
+ import os
5
+ PACKAGE_PARENT = '..'
6
+ SCRIPT_DIR = os.path.dirname(os.path.realpath(
7
+ os.path.join(os.getcwd(), os.path.expanduser(__file__))))
8
+
9
+ sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
10
+ from modules import getweblinks, pagereader
11
+
12
+
13
+ def test_get_links_successful():
14
+ soup = pagereader.read_first_page('http://www.whatsmyip.net/')[0]
15
+ data = ['http://aff.ironsocket.com/SH7L',
16
+ 'http://aff.ironsocket.com/SH7L',
17
+ 'http://wsrs.net/',
18
+ 'http://cmsgear.com/']
19
+
20
+ result = getweblinks.get_links(soup, ext=['.com', '.net'])
21
+ assert result == data
22
+
23
+
24
+ if __name__ == '__main__':
25
+ test_get_links_successful()
@@ -0,0 +1,69 @@
1
+ import pytest
2
+ import requests
3
+ import requests_mock
4
+
5
+ from bs4 import BeautifulSoup
6
+ from requests.exceptions import HTTPError, MissingSchema, ConnectionError
7
+
8
+
9
+ @pytest.fixture
10
+ def test_read_first_page(site):
11
+
12
+ with requests_mock.Mocker() as m:
13
+ m.get('https://www.test.com', text='This is a dot com site.')
14
+ m.get('https://www.test.org', text='This is a dot org site.')
15
+ m.get('https://www.test.net', text='This is a dot net site.')
16
+ m.get('https://www.test.onion', text='This is a dot onion site.')
17
+
18
+ m.register_uri('GET', 'https://www.test.cannotbefound', exc=HTTPError)
19
+ m.register_uri('GET', 'http://www.test.cannotbefound', exc=HTTPError)
20
+
21
+ headers = {'User-Agent':
22
+ 'TorBot - Onion crawler | www.github.com/DedSecInside/TorBot'}
23
+ attempts_left = 3
24
+ err = " "
25
+
26
+ # Removed unnecessary code such as printing
27
+ while attempts_left:
28
+ try:
29
+ if attempts_left == 3:
30
+ response = requests.get(site, headers=headers)
31
+ page = BeautifulSoup(response.text, 'html.parser')
32
+ return str(page)
33
+ if attempts_left == 2:
34
+ response = requests.get('https://'+site, headers=headers)
35
+ page = BeautifulSoup(response.text, 'html.parser')
36
+ return str(page)
37
+ if attempts_left == 1:
38
+ response = requests.get('http://'+site, headers=headers)
39
+ page = BeautifulSoup(response.text, 'html.parser')
40
+ return str(page)
41
+ if not attempts_left:
42
+ raise err
43
+
44
+ except (HTTPError, MissingSchema, ConnectionError) as e:
45
+ err = e
46
+ attempts_left -= 1
47
+
48
+ raise err
49
+
50
+
51
+ def test_run():
52
+ urls = ['www.test.com', 'www.test.org', 'www.test.net', 'www.test.onion',
53
+ 'www.test.cannotbefound']
54
+
55
+ with pytest.raises(HTTPError):
56
+ for url in urls:
57
+ page = test_read_first_page(url)
58
+ if url[-4:] == '.com':
59
+ assert page == 'This is a dot com site.'
60
+ elif url[-4:] == '.org':
61
+ assert page == 'This is a dot org site.'
62
+ elif url[-4:] == '.net':
63
+ assert page == 'This is a dot net site.'
64
+ elif url[-6:] == '.onion':
65
+ assert page == 'This is a dot onion site.'
66
+
67
+
68
+ if __name__ == '__main__':
69
+ test_run()
@@ -0,0 +1,40 @@
1
+ import sys
2
+ import os
3
+ import json
4
+ PACKAGE_PARENT = '..'
5
+ SCRIPT_DIR = os.path.dirname(os.path.realpath(
6
+ os.path.join(os.getcwd(), os.path.expanduser(__file__))))
7
+
8
+ sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
9
+
10
+ from modules import savefile
11
+
12
+
13
+ def test_save_links_successful():
14
+ mock_data = ['http://aff.ironsocket.com/SH7L',
15
+ 'http://aff.ironsocket.com/SH7L',
16
+ 'http://wsrs.net/',
17
+ 'http://cmsgear.com/']
18
+ try:
19
+ file_name = savefile.saveJson('Links', mock_data)
20
+ mock_output = {'Links': mock_data}
21
+
22
+ with open('test_file.json', 'w+') as test_file:
23
+ json.dump(mock_output, test_file, indent=2)
24
+
25
+ os.chdir(os.getcwd())
26
+ assert os.path.isfile(file_name) is True
27
+ mock_file = open(file_name, 'r')
28
+ test_file = open('test_file.json', 'r')
29
+
30
+ mock_data = mock_file.read()
31
+ test_data = test_file.read()
32
+
33
+ finally:
34
+ os.remove(file_name)
35
+ os.remove('test_file.json')
36
+
37
+ assert mock_data == test_data
38
+
39
+ if __name__ == '__main__':
40
+ test_save_links_successful()