634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published by
637 | the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | xcavator
2 | ========
3 | A network data locater using credentials obtained during penetration tests.
4 |
5 | Xcavator is a tool that scans a range of IP addresses for services that host files (FTP, FTPS and SMB at the moment) and for
6 | given credentials it will try to download everything it can and scan within the files for interesting strings.
7 |
8 | Another mode is to download only those files that their filenames match a RegEx.
9 |
10 | Developed by Nikos Laleas, nikos d0t laleas at nccgroup d0t com
11 |
12 | Released under AGPL. See LICENSE for more information.
13 |
14 | Prerequisites
15 | -------------
16 | Python 3.3 and [[https://pypi.python.org/pypi/pysmb | pysmb]]
17 |
18 | Options
19 | -------
20 | All the necessary parameters are picked up from a config file witch is created and populated on the first run.
21 |
22 | #####Config file example
23 |
24 | [SMB]
25 | user = h4x0r
26 | pass = 123456
27 | regex = \bpassword\b
28 | port = 445
29 | range = 192.168.1.1-192.168.1.15, 10.10.10.0/24
30 |
31 |
32 | There are also additional optional arguments:
33 |
34 |
35 | -h, --help show this help message and exit
36 |
37 | -c CONFIG, --config CONFIG Config file (Default: xcavator.conf)
38 |
39 | -t TIMEOUT, --timeout TIMEOUT Timeout in seconds (Default: 2s)
40 |
41 | -s, --search Search mode. Searches recursively for filenames
42 | matching RegEx instead of downloading everything
43 | (Default: downloads everything and scans for strings)
44 |
45 | -v, --verbose Verbosity level. More "v"s, more detail. (Default: Prints basic info)
46 |
47 |
48 | Adding new protocols
49 | --------------------
50 | In order to support new protocols you need to create a file named protocolname_proto.py in the 'protocols' directory. Have a look at 'sample_proto.py'.
51 | Finally, edit the 'xcavator.py' and add the protocol name and the default port to the correspondent lists.
--------------------------------------------------------------------------------
/protocols/ftp_proto.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3.3
2 | # Released as open source by NCC Group Plc - http://www.nccgroup.com/
3 | # Developed by Nikos Laleas, nikos dot laleas at nccgroup dot com
4 | # https://github.com/nccgroup/xcavator
5 | # Released under AGPL. See LICENSE for more information
6 |
7 | from ftplib import FTP
8 | from xcavator import convert_bytes
9 | import ftplib
10 | import os
11 |
12 |
13 | def startProtocol(port, user, passwd, ip, regex, target_path, args):
14 | global num_files, size, mirror, verbose, timeout
15 | num_files = 0
16 | size = 0
17 | mirror = args.search
18 | verbose = args.verbose
19 | timeout = args.timeout
20 | try:
21 | print(70*'#')
22 | print('Trying FTP server: %s:%s' %(ip, port))
23 | host = FTP()
24 | host.connect(str(ip), int(port), timeout)
25 | host.login(user, passwd)
26 | #target_path=os.path.join(destination, str(ip))
27 | #makedir(target_path)
28 | print('Connected... Downloading files...\n')
29 | files = downloadFTPFiles(target_path, host, regex)
30 | print('%i files (%s) downloaded... Closing connection...' % (files, convert_bytes(size)))
31 | host.close()
32 | except ftplib.all_errors as err:
33 | print (err)
34 |
35 |
36 | def makedir(path):
37 | if os.path.isdir(path):
38 | return
39 | dirname = os.path.dirname(path)
40 | if dirname: makedir(dirname)
41 | os.mkdir(path, 0o777)
42 |
43 |
44 | def downloadFTPFiles(destination, host, regex):
45 | global num_files, size
46 | pwd = host.pwd()
47 | if destination and not os.path.isdir(destination):
48 | try:
49 | makedir(destination)
50 | except os.error as err:
51 | if verbose > 0: print(err)
52 | return
53 | subdirs = []
54 | listing = []
55 | host.retrlines('LIST', listing.append)
56 | for line in listing:
57 | prop = line.split(None, 8)
58 | if len(prop) < 6: continue
59 | filename = prop[-1].lstrip()
60 | #is symlink?
61 | if (prop[0][0]) is 'l': continue
62 | if filename is ('.' or '..'): continue
63 | #is directory?
64 | if (prop[0][0]) is 'd':
65 | subdirs.append(filename)
66 | continue
67 | fullname = os.path.join(destination, filename)
68 | tempname = os.path.join(destination, filename+'.tmp')
69 | try:
70 | os.unlink(tempname)
71 | except os.error:
72 | pass
73 | try:
74 | fp = open(tempname, 'wb')
75 | except IOError as err:
76 | if verbose > 0: print ("Can't create %r: %s" % (tempname, err))
77 | continue
78 | fullpath=''
79 | if pwd is not '/': fullpath = '%s/%s' %(pwd, filename)
80 | else: fullpath = '/%s' % filename
81 | try:
82 | if not mirror:
83 | if verbose > 2: print('Checking file: %r' % fullpath)
84 | if regex.match(filename):
85 | if verbose > 2: print('***Found match...')
86 | filesize = host.size(filename)
87 | if verbose > 1: print('Downloading file: %s.....[%s]' % (fullpath, convert_bytes(filesize)))
88 | host.retrbinary('RETR ' + filename, fp.write, 8*1024)
89 | size += filesize
90 | num_files+=1
91 | else:
92 | if verbose > 2: print('No match...')
93 | fp.close()
94 | os.remove(tempname)
95 | else:
96 | filesize = host.size(filename)
97 | if verbose > 1: print('Downloading file: %s.....[%s]' % (fullpath, convert_bytes(filesize)))
98 | host.retrbinary('RETR ' + filename, fp.write, 8*1024)
99 | size += filesize
100 | num_files+=1
101 | except ftplib.error_perm as err:
102 | if verbose > 1: print ('%s: %s' %(fullpath, err))
103 | fp.close()
104 | os.remove(tempname)
105 | continue
106 | fp.close()
107 | try:
108 | os.unlink(fullname)
109 | except os.error:
110 | pass
111 | try:
112 | os.rename(tempname, fullname)
113 | except os.error:
114 | continue
115 |
116 | for subdir in subdirs:
117 | localsub = os.path.join(destination, subdir)
118 | pwd = host.pwd()
119 | try:
120 | if verbose > 2: print('Changing current directory to: %r' % (pwd+subdir))
121 | host.cwd(subdir)
122 | except ftplib.error_perm as err:
123 | if verbose > 0: print('%s\n%s' %(subdir, err))
124 | continue
125 | else:
126 | downloadFTPFiles(localsub, host, regex)
127 | host.cwd('..')
128 | if host.pwd() != pwd:
129 | break
130 | #Delete empty directories
131 | try: os.rmdir(localsub)
132 | except OSError: pass
133 | return num_files
134 |
--------------------------------------------------------------------------------
/protocols/ftps_proto.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3.3
2 | # Released as open source by NCC Group Plc - http://www.nccgroup.com/
3 | # Developed by Nikos Laleas, nikos dot laleas at nccgroup dot com
4 | # https://github.com/nccgroup/xcavator
5 | # Released under AGPL. See LICENSE for more information
6 |
7 | from ftplib import FTP_TLS
8 | from xcavator import convert_bytes
9 | import ftplib
10 | import os
11 |
12 |
13 | def startProtocol(port, user, passwd, ip, regex, target_path, args):
14 | global num_files, size, mirror, verbose, timeout
15 | num_files = 0
16 | size = 0
17 | mirror = args.search
18 | verbose = args.verbose
19 | timeout = args.timeout
20 | try:
21 | print(70*'#')
22 | print('Trying FTPS server: %s:%s' %(ip, port))
23 | host = FTP_TLS(str(ip), timeout = timeout)
24 | host.login(user, passwd)
25 | host.prot_p()
26 | print('Connected... Downloading files...\n')
27 | files = downloadFTPFiles(target_path, host, regex)
28 | print('%i files (%s) downloaded... Closing connection...' % (files, convert_bytes(size)))
29 | host.close()
30 | except ftplib.all_errors as err:
31 | print (err)
32 |
33 |
34 | def makedir(path):
35 | if os.path.isdir(path):
36 | return
37 | dirname = os.path.dirname(path)
38 | if dirname: makedir(dirname)
39 | os.mkdir(path, 0o777)
40 |
41 |
42 | def downloadFTPFiles(destination, host, regex):
43 | global num_files, size
44 | pwd = host.pwd()
45 | if destination and not os.path.isdir(destination):
46 | try:
47 | makedir(destination)
48 | except os.error as err:
49 | if verbose > 0: print(err)
50 | return
51 | subdirs = []
52 | listing = []
53 | host.retrlines('LIST', listing.append)
54 | for line in listing:
55 | prop = line.split(None, 8)
56 | if len(prop) < 6: continue
57 | filename = prop[-1].lstrip()
58 | #is symlink?
59 | if (prop[0][0]) is 'l': continue
60 | if filename is ('.' or '..'): continue
61 | #is directory?
62 | if (prop[0][0]) is 'd':
63 | subdirs.append(filename)
64 | continue
65 | fullname = os.path.join(destination, filename)
66 | tempname = os.path.join(destination, filename+'.tmp')
67 | try:
68 | os.unlink(tempname)
69 | except os.error:
70 | pass
71 | try:
72 | fp = open(tempname, 'wb')
73 | except IOError as err:
74 | if verbose > 0: print ("Can't create %r: %s" % (tempname, err))
75 | continue
76 | fullpath=''
77 | if pwd is not '/': fullpath = '%s/%s' %(pwd, filename)
78 | else: fullpath = '/%s' % filename
79 | try:
80 | if not mirror:
81 | if verbose > 2: print('Checking file: %r' % fullpath)
82 | if regex.match(filename):
83 | if verbose > 2: print('***Found match...')
84 | filesize = host.size(filename)
85 | if verbose > 1: print('Downloading file: %s.....[%s]' % (fullpath, convert_bytes(filesize)))
86 | host.retrbinary('RETR ' + filename, fp.write, 8*1024)
87 | size += filesize
88 | num_files+=1
89 | else:
90 | if verbose > 2: print('No match...')
91 | fp.close()
92 | os.remove(tempname)
93 | else:
94 | filesize = host.size(filename)
95 | if verbose > 1: print('Downloading file: %s.....[%s]' % (fullpath, convert_bytes(filesize)))
96 | host.retrbinary('RETR ' + filename, fp.write, 8*1024)
97 | size += filesize
98 | num_files+=1
99 | except ftplib.error_perm as err:
100 | if verbose > 1: print ('%s: %s' %(fullpath, err))
101 | fp.close()
102 | os.remove(tempname)
103 | continue
104 | fp.close()
105 | try:
106 | os.unlink(fullname)
107 | except os.error:
108 | pass
109 | try:
110 | os.rename(tempname, fullname)
111 | except os.error:
112 | continue
113 |
114 | for subdir in subdirs:
115 | localsub = os.path.join(destination, subdir)
116 | pwd = host.pwd()
117 | try:
118 | if verbose > 2: print('Changing current directory to: %r' % (pwd+subdir))
119 | host.cwd(subdir)
120 | except ftplib.error_perm as err:
121 | if verbose > 0: print('%s\n%s' %(subdir, err))
122 | continue
123 | else:
124 | downloadFTPFiles(localsub, host, regex)
125 | host.cwd('..')
126 | if host.pwd() != pwd:
127 | break
128 | #Delete empty directories
129 | try: os.rmdir(localsub)
130 | except OSError: pass
131 | return num_files
132 |
--------------------------------------------------------------------------------
/protocols/sample_proto.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3.3
2 |
3 |
4 | #str port Service port
5 | #str user Username for the service
6 | #str passwd Password
7 | #IPv4Address ip Target IP
8 | #SRE_Pattern regex Compiled RegEx
9 | #str target_path Current working directory: project_name\{IP address}
10 | #Namespace args Optional arguments
11 |
12 | def startProtocol(port, user, passwd, ip, regex, target_path, args):
13 | global mirror, verbose, timeout
14 | mirror = args.search
15 | verbose = args.verbose
16 | timeout = args.timeout
17 | print("Your code here")
--------------------------------------------------------------------------------
/protocols/smb_proto.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3.3
2 | # Released as open source by NCC Group Plc - http://www.nccgroup.com/
3 | # Developed by Nikos Laleas, nikos dot laleas at nccgroup dot com
4 | # https://github.com/nccgroup/xcavator
5 | # Released under AGPL. See LICENSE for more information
6 |
7 | import os
8 | from sys import stdout
9 | from xcavator import convert_bytes
10 | from smb import smb_structs
11 | from smb.SMBConnection import SMBConnection
12 |
13 |
14 | def startProtocol(port, user, passwd, ip, regex, target_path, args):
15 | global mirror, verbose, timeout
16 | mirror = args.search
17 | verbose = args.verbose
18 | timeout = args.timeout
19 | serverName = '*'
20 | conn = []
21 | direct = True
22 | if port != '445':
23 | serverName = input("SMB over TCP is used by default on port 445.\nIf you prefer NetBIOS instead, you need to provide the NetBIOS name of the remote machine: ")
24 | direct = False
25 | try:
26 | conn = SMBConnection(user, passwd, 'noone', serverName, use_ntlm_v2 = True, is_direct_tcp = direct)
27 | stdout.write("Trying SMB server: %s......" % str(ip))
28 | stdout.flush()
29 | conn.connect(str(ip), int(port), timeout = timeout)
30 | print("[Connected]")
31 | shares(target_path, conn, regex)
32 | conn.close()
33 | except OSError as err:
34 | print("[No connection]")
35 | if verbose > 0: print(err.message)
36 | conn.close()
37 | pass
38 |
39 |
40 | def makedir(path):
41 | if os.path.isdir(path):
42 | return
43 | os.mkdir(path, 0o777)
44 |
45 |
46 | def shares(targetPath, conn, regex):
47 | global num_files, size
48 | shareList = conn.listShares()
49 | num_files = 0
50 | size = 0
51 | if verbose == 0: print("Downloading files...")
52 | for r in shareList:
53 | if targetPath and not os.path.isdir(os.path.join(targetPath, r.name)):
54 | try:
55 | makedir(os.path.join(targetPath, r.name))
56 | except os.error as err:
57 | if verbose > 0: print(err)
58 | return
59 |
60 | downloadSMBFiles("\\", os.path.join(targetPath,r.name), conn, regex, r.name)
61 | print('%i files (%s) downloaded. Closing connection...' % (num_files, convert_bytes(size)))
62 |
63 |
64 | def downloadSMBFiles(smbpath, projPath, conn, regex, share):
65 | global num_files, size
66 | cwd = ""
67 | if smbpath[:1] is "\\": cwd = (smbpath[1:]) #trim first \
68 | cwd = os.path.join(projPath,cwd)
69 | if cwd and not os.path.isdir(cwd):
70 | try:
71 | makedir(cwd)
72 | except os.error as err:
73 | if verbose > 0: print(err)
74 | return
75 |
76 |
77 | subdirs = []
78 | try:
79 | listing = conn.listPath(share, smbpath)
80 | for l in listing:
81 | filename = l.filename
82 | if l.isDirectory:
83 | if filename is ".": continue
84 | if filename == "..": continue #Using 'is' didn't work
85 | subdirs.append(filename)
86 | continue
87 | else:
88 | relativeRemotePath = os.path.join(smbpath, l.filename)
89 | relativeLocalPath = os.path.join(share, relativeRemotePath[1:])
90 | tempname = relativeLocalPath+'.tmp'
91 | try:
92 | os.unlink(tempname)
93 | except os.error:
94 | pass
95 | try:
96 | fp = open(tempname, 'wb')
97 | except IOError as err:
98 | if verbose > 0: print ("Can't create %r: %s" % (tempname, err))
99 | continue
100 | try:
101 | if not mirror:
102 | if verbose > 2: print('Checking file: %r' % relativeRemotePath)
103 | if regex.match(filename):
104 | print('***Found match...***')
105 | if verbose > 0: print("Downloading file: %s.....[%s]" % (relativeRemotePath, convert_bytes(l.file_size)))
106 | file_attributes, filesize = conn.retrieveFile(share, relativeRemotePath, fp)
107 | fp.close()
108 | size += filesize
109 | num_files+=1
110 | else:
111 | if verbose > 2: print('Not matched...')
112 | fp.close()
113 | os.remove(tempname)
114 | else:
115 | if verbose > 1: print("Downloading file: %s.....[%s]" % (relativeRemotePath, convert_bytes(l.file_size)))
116 | try:
117 | file_attributes, filesize = conn.retrieveFile(share, relativeRemotePath, fp)
118 | size += filesize
119 | fp.close()
120 | except smb_structs.OperationFailure as err:
121 | if verbose > 1: print(err.message)
122 | fp.close()
123 | os.remove(tempname)
124 | continue
125 | num_files+=1
126 | except OSError as err:
127 | if verbose > 0: print ('%s: %s' %(relativeRemotePath, err))
128 | fp.close()
129 | os.remove(tempname)
130 | continue
131 | try:
132 | os.unlink(relativeRemotePath)
133 | except os.error:
134 | pass
135 | try:
136 | os.rename(tempname, relativeLocalPath)
137 | except os.error:
138 | continue
139 |
140 | for subdir in subdirs:
141 | localsub = os.path.join(cwd, subdir)
142 | newdest = smbpath+subdir+"\\"
143 | if verbose > 2: print('Changing current directory to: %s' % (share+newdest))
144 | downloadSMBFiles(newdest, projPath, conn, regex, share)
145 |
146 | #Delete empty directories
147 | try: os.rmdir(localsub)
148 | except OSError: pass
149 |
150 | return num_files
151 |
152 | except smb_structs.OperationFailure as err:
153 | #print(err)
154 | return
155 |
156 |
157 |
--------------------------------------------------------------------------------
/xcavator.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3.3
2 | # Released as open source by NCC Group Plc - http://www.nccgroup.com/
3 | # Developed by Nikos Laleas, nikos dot laleas at nccgroup dot com
4 | # https://github.com/nccgroup/xcavator
5 | # Released under AGPL. See LICENSE for more information
6 |
7 | import os
8 | import re
9 | import ipaddress
10 | import configparser
11 | import sys
12 | import time
13 | import mmap
14 | import argparse
15 |
16 |
17 |
18 | #Add your own protocols to the list
19 | protocols = ['ftp', 'smb', 'ftps']
20 |
21 | #Also add the default port
22 | default_port = ['21', '139', '990']
23 |
24 | num_files = 0
25 | conf = ''
26 | timeout = 0
27 | verbose = 0
28 | mirror = True
29 |
30 |
31 | def main():
32 | print("+"+58*"-"+"+")
33 | print(" _ _ _ ")
34 | print(" ( ) ( ) ( )_ ")
35 | print(" `\\`\\/'/' ___ _ _ _ _ _ _ | ,_) _ _ __ ")
36 | print(" > < /'___) /'_` )( ) ( ) /'_` )| | /'_`\\ ( '__) ")
37 | print(" /'/\\`\\ ( (___ ( (_| || \\_/ |( (_| || |_ ( (_) )| | ")
38 | print(" (_) (_)`\\____)`\\__,_)`\\___/'`\\__,_)`\\__)`\\___/'(_) ")
39 | print("\n"+"+"+58*"-"+"+"+"\n")
40 |
41 | args = parseArgs()
42 | if os.path.isfile(conf):
43 | print ('Using existing configuration...')
44 | read_conf(args)
45 | else:
46 | print ('Config not found. Creating new...')
47 | create_new_conf(args)
48 |
49 | def parseArgs():
50 | global conf, timeout, verbose, mirror
51 | parser = argparse.ArgumentParser()
52 | parser.add_argument('-c', '--config', type = str, default = 'xcavator.conf', help = 'Config file (Default: xcavator.conf)')
53 | parser.add_argument('-t', '--timeout', type = float, default = 2, help = 'Timeout in seconds (Default: 2s)')
54 | parser.add_argument('-s', '--search', default = True, action = 'store_false', help = 'Search mode. Searches recursively for filenames matching RegEx instead of downloading everything (Default: downloads everything and scans for strings)')
55 | parser.add_argument('-v', '--verbose', default = 0, action = 'count', help = 'Verbosity level. More "v"s, more detail. (Default: Prints basic info)')
56 | args = parser.parse_args()
57 | conf = args.config
58 | timeout = args.timeout
59 | verbose = args.verbose
60 | mirror = args.search
61 | return args
62 |
63 | def create_new_conf(args):
64 | prot = input('Protocol (e.g. ftp): ')
65 |
66 | while prot.lower() not in protocols:
67 | prot = input('Invalid protocol. Try again: ')
68 |
69 | port = input('Port [' + default_port[protocols.index(prot)] + ']: ')
70 | if port is '': port = default_port[protocols.index(prot)]
71 | user = input('Username [anonymous]: ')
72 | passwd = input('Password [anonymous]: ')
73 | if user is '':
74 | user = 'anonymous'
75 | if passwd is '': passwd = 'anonymous'
76 | ip_range = input('IP range: ')
77 | ip_range_exp = validate_ip_range(ip_range)
78 | while True:
79 | if ip_range_exp:
80 | break
81 | else:
82 | ip_range = input('Try again: ')
83 | ip_range_exp = validate_ip_range(ip_range)
84 | regex = input('Regex: ')
85 | compregex= ""
86 | while True:
87 | try:
88 | compregex = re.compile(regex)
89 | break
90 | except re.error as err:
91 | print('RegEx error: %s' %err)
92 | regex = input('Try again: ')
93 | parser = configparser.ConfigParser()
94 | parser[prot.upper()] = {'PORT': port,
95 | 'User': user,
96 | 'Pass': passwd,
97 | 'Range': ip_range,
98 | 'RegEx': regex}
99 |
100 | with open(conf, 'w') as configfile:
101 | parser.write(configfile)
102 | process_request(prot.lower(), port, user, passwd, ip_range_exp, compregex, args)
103 |
104 |
105 |
106 | def read_conf(args):
107 | parser = configparser.ConfigParser()
108 | parser.read(conf)
109 | sections = parser.sections()
110 | prot = sections[0]
111 | if prot.lower() not in protocols:
112 | print ('Protocol not supported. Edit the configuration or delete it to create a new one.')
113 | sys.exit()
114 | port = parser[prot]['port']
115 | if port is '':
116 | print ('Port not specified. Using default.')
117 | port = default_port[protocols.index(prot)]
118 | user = parser[prot]['user']
119 | passwd = parser[prot]['pass']
120 | if user is '':
121 | user = 'anonymous'
122 | if passwd is '':
123 | passwd = 'anonymous'
124 | ip_range = parser[prot] ['range']
125 | ip_range = validate_ip_range(ip_range)
126 | if not ip_range:
127 | print ('IP address range not valid. Edit the configuration or delete it to create a new one.')
128 | sys.exit()
129 | regex = parser[prot]['regex']
130 | try:
131 | regex = re.compile(regex)
132 | except re.error as err:
133 | print('RegEx error: %s' %err)
134 | sys.exit()
135 | process_request(prot.lower(), port, user, passwd, ip_range, regex, args)
136 |
137 |
138 |
139 | def validate_ip_range(iprange):
140 | iprange = iprange.replace(" ","")
141 | iprange = iprange.split(',')
142 | ip_list=[]
143 |
144 | for ip in iprange:
145 | try:
146 | i=ipaddress.ip_address(ip)
147 | if i:
148 | ip_list.append(i)
149 | except ValueError:
150 | try:
151 | i=ipaddress.ip_network(ip)
152 | if i:
153 | for x in i.hosts():
154 | ip_list.append(x)
155 | except ValueError:
156 | if ip.find('-')==-1:
157 | print('Invalid range or IP address -> ', ip)
158 | return None
159 | else:
160 | temp=ip.split('-')
161 | for t in temp:
162 | try:
163 | ipaddress.ip_address(t)
164 | except ValueError:
165 | print('Invalid syntax -> ', t)
166 | return None
167 | if ipaddress.ip_address(temp[0])>ipaddress.ip_address(temp[1]) :
168 | print('Invalid syntax -> ' + temp[0] + ' is higher than ' + temp[1])
169 | return None
170 | else:
171 | x=ipaddress.ip_address(temp[0])
172 | while x <= ipaddress.ip_address(temp[1]):
173 | ip_list.append(x)
174 | x+=1
175 | return ip_list
176 |
177 |
178 |
179 | def process_request(prot, port, user, passwd, ip_range, regex, args):
180 | try:
181 | projPath = 'scan_%4d-%02d-%02d_%02d.%02d.%02d' % time.localtime()[0:6]
182 | print('Creating project directory...: %s' % projPath)
183 | makedir(projPath)
184 | projPath=os.path.join(os.getcwd(), projPath)
185 | prot = prot+'_proto'
186 | temp = __import__('protocols', fromlist = [prot])
187 | prot = getattr(temp, prot)
188 | for ip in ip_range:
189 | target_path=os.path.join(projPath, str(ip))
190 | makedir(target_path)
191 | os.chdir(target_path)
192 | prot.startProtocol(port, user, passwd, ip, regex, target_path, args)
193 | #globals()[prot + '_func'](port, user, passwd, ip, regex, projPath)
194 | try:
195 | os.chdir(projPath)
196 | os.rmdir(target_path)
197 | except OSError as err:
198 | pass
199 | if mirror: scanFiles(regex, projPath)
200 | except KeyError:
201 | print ('Method %s not implemented' % prot)
202 | sys.exit()
203 |
204 |
205 | def scanFiles(regex, projPath):
206 | print('Scanning files...')
207 | regex = str.encode(regex.pattern)
208 | for curdir, dirs, files in os.walk(projPath):
209 | for file in files:
210 | try:
211 | filepath = os.path.join(curdir, file)
212 | if verbose > 2: print('Scanning file: %s' % filepath)
213 | size = os.stat(filepath).st_size
214 | f = open(filepath)
215 | data = mmap.mmap(f.fileno(), size, access=mmap.ACCESS_READ)
216 | f.close()
217 | newfile = ''
218 | counter = 1
219 | for m in re.finditer(regex, data):
220 | if newfile is not file:
221 | print('\n'+70*'='+'\nFile: %s' % filepath)
222 | print(70*'=')
223 | newfile = file
224 | print('%d. Match: %s at offset: 0x%0.8x' % (counter ,m.group(0), m.start()))
225 | counter += 1
226 | except ValueError as err:
227 | if verbose > 2: print('Error: %s' % err)
228 | continue
229 | if counter > 1: print(70*'-'+'\n')
230 | print("Done.")
231 |
232 |
233 | def makedir(path):
234 | if os.path.isdir(path):
235 | return
236 | dirname = os.path.dirname(path)
237 | if dirname: makedir(dirname)
238 | os.mkdir(path, 0o777)
239 |
240 |
241 | def convert_bytes(bytes):
242 | bytes = float(bytes)
243 | if bytes >= 1099511627776:
244 | terabytes = bytes / 1099511627776
245 | size = '%.2fTB' % terabytes
246 | elif bytes >= 1073741824:
247 | gigabytes = bytes / 1073741824
248 | size = '%.2fGB' % gigabytes
249 | elif bytes >= 1048576:
250 | megabytes = bytes / 1048576
251 | size = '%.2fMB' % megabytes
252 | elif bytes >= 1024:
253 | kilobytes = bytes / 1024
254 | size = '%.2fKB' % kilobytes
255 | else:
256 | size = '%.2fb' % bytes
257 | return size
258 |
259 | if __name__ == '__main__':
260 | main()
261 |
--------------------------------------------------------------------------------