# Copyright 2007, 2008 "16 Systems, LLC" # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ################################################################################ # Find_SSNs a program written by Brad Tilley to find some # # social security numbers and some credit card numbers in files on computers. # ################################################################################ import getopt import getpass import os import os.path import re import sets import socket import sys import time import urllib import zipfile version_no = '3.3' release_date = 'Aug 25, 2008' # Release Notes # # 1. Added JCB, 13 digit Visa, Diners Club International and Diners Club Carte Blanche cards. # 2. Simplified regex to get any CCN with delimiters (spaces and dashes) anywhere. This may slightly # increase false positives, but will be more thorough and will get any sort of user defined segmentation or # card format. # 3. Added framework to re-implement PDF support in future releases. # 4. Added search path to null report. def get_ssa_info(mode='gui'): # Download the current areas to groups file and load it into a dictionary. socket.setdefaulttimeout(10) try: fp = urllib.urlopen("http://16systems.com/find_ssns/areas_groups.txt") lines = fp.readlines() fp.close() ag = {} for line in lines: line = line.strip().split() a,g = line[0], line[1] ag[a] = g #print ag #print len(ag) return ag except: if mode == 'nogui': sys.exit("Error - Cannot load SSA areas to groups information. Try again later.") else: app = wx.PySimpleApp() app.MainLoop() wx.MessageBox("Cannot load SSA areas to groups information. Try again later.", 'Find_SSNs %s - Error' %version_no, wx.ICON_ERROR) sys.exit() def cc_info(): # Load credit card information into a dictionary. Can be expanded to cover other credit cards so # long as the prefix is 1, 2, 3 or 4 digits in length. # card_prefix: [card_length, card_type] card_info = {} card_info['1800'] = [15, "JCB"] card_info['2131'] = [15, "JCB"] card_info['300'] = [14, "Diners CB"] card_info['301'] = [14, "Diners CB"] card_info['302'] = [14, "Diners CB"] card_info['303'] = [14, "Diners CB"] card_info['304'] = [14, "Diners CB"] card_info['305'] = [14, "Diners CB"] card_info['34'] = [15, "Amex"] card_info['35'] = [16, "JCB"] card_info['36'] = [14, "Diners Intl"] card_info['37'] = [15, "Amex"] card_info['385'] = [14, "Diners CB"] # Visa is a unique case card_info['4'] = [[13,16], "Visa"] card_info['51'] = [16, "MC"] card_info['52'] = [16, "MC"] card_info['53'] = [16, "MC"] card_info['54'] = [16, "MC"] card_info['55'] = [16, "MC or Diners US and CA"] card_info['6011'] = [16, "Discover"] card_info['65'] = [16, "Discover"] #print card_info return card_info def wait(msg, mode='gui'): if mode == 'gui': app = wx.PySimpleApp() app.MainLoop() wx.MessageBox(msg, 'Find_SSNs %s' %version_no) else: print msg def wait_msg(): # Create a file called 'wait_message.txt' in the same folder as the program # and your custom wait message will appear instead of the default. # This works in gui or non-gui mode. filename = 'wait_message.txt' if os.path.isfile(filename): fp = open(filename) msg = fp.read() fp.close() return msg else: msg = """There may be periods of inactivity in the program. Please be patient.""" return msg def status_msg(folder_to_scan): # Create a file called 'status_message.txt' in the same folder as the program # and your custom status message will appear instead of the default. # This only works in gui mode as no status message is needed for non-gui users. filename = 'status_message.txt' if os.path.isfile(filename): fp = open(filename) msg = fp.read() fp.close() return msg else: msg = """The selected folder will now be scanned for sensitive numbers. Would you like to continue?\n\n%s""" %(folder_to_scan) return msg def end_msg(path_to_results): # Create a file called 'end_message.txt' in the same folder as the program # and your custom end message will appear instead of the default. # This works in gui or non-gui mode. filename = 'end_message.txt' if os.path.isfile(filename): fp = open(filename) msg = fp.read() fp.close() return msg else: msg = """\nThe report 'Find_SSNs.html' is located here: %s Examine the report carefully. If suspect files were found, verify that they do indeed contain sensitive numbers. If they do and you no longer need them, please securely delete the files. If you need the files, please store them in a secure location and encrypt them.""" %(path_to_results) return msg def stop_or_go(msg, mode='gui'): # This function only works in gui mode. It is skipped when Find_SSNs is executed from a terminal. if mode == 'gui': app = wx.PySimpleApp() app.MainLoop() md = wx.MessageDialog(None, msg, 'Find_SSNs %s' %version_no, wx.YES_NO) response = md.ShowModal() #print response if response != wx.ID_YES: #print 'No' md.Destroy() sys.exit() md.Destroy() else: pass def signal_end(msg, mode='gui'): if mode == 'gui': app = wx.PySimpleApp() app.MainLoop() wx.MessageBox(msg, 'Find_SSNs %s' %version_no) else: print msg def get_user_input(mode='gui'): if mode == 'gui': app = wx.PySimpleApp() app.MainLoop() td = wx.DirDialog(None, "Find_SSNs %s - Select A Folder To Search" %version_no, ".", style=wx.DD_DEFAULT_STYLE) response = td.ShowModal() if response == wx.ID_OK: folder = td.GetPath() td.Destroy() #print folder #print type(folder) return str(folder) else: td.Destroy() sys.exit() else: pass def get_user_output(mode='gui'): if mode == 'gui': app = wx.PySimpleApp() app.MainLoop() td = wx.DirDialog(None, "Find_SSNs %s - Select A Folder To Save Results" %version_no, ".", style=wx.DD_DEFAULT_STYLE) response = td.ShowModal() if response == wx.ID_OK: folder = td.GetPath() td.Destroy() #print folder #print type(folder) return str(folder) else: td.Destroy() sys.exit() else: pass def get_search_choice(mode='gui'): # returns an int # -1 means user wants to cancel. # 0 means search for SSNs. # 1 means search for CCNs. # 2 means search both. if mode == 'gui': app = wx.PySimpleApp() app.MainLoop() i = wx.GetSingleChoiceIndex("Search For?", "Find_SSNs %s - Search For?" %version_no, ["U.S. Social Security Numbers", "Credit Card Numbers", "Both"]) if i == -1: sys.exit("User selected 'cancel' in get_search_choice function") else: #print i return i else: pass def create_files(path_to_results): # Hide all the output files (confuses many users) except for the main results file. # These files can be accessed should debugging be required. file_list = ['.Find_SSNs_exceptions.txt', '.Find_SSNs_skip.txt', '.Find_SSNs.txt', 'Find_SSNs.html'] # The win32 stuff will fail silently on non-Windows Systems try: import win32api, win32con except: pass for f in file_list: try: win32api.SetFileAttributes(os.path.join(path_to_results, f), win32con.FILE_ATTRIBUTE_NORMAL) except: pass create = open(os.path.join(path_to_results, f), 'w') create.close() if '.Find_SSNs' in f: try: win32api.SetFileAttributes(os.path.join(path_to_results, f), win32con.FILE_ATTRIBUTE_HIDDEN) except: pass return file_list def skip_file_extensions(): ext_skip_list = [] # Add file extensions that you don't want scanned here (all lower case): extensions = ['a', 'aac', 'api', 'arx', 'au', 'avi', 'ax', 'bin', 'bmp', 'c', 'cab', 'cache', 'com', 'config', 'cpl', 'deb', 'dectest', 'dll', 'dmp', 'eps', 'exe', 'fon', 'gif', 'gz', 'h', 'ico', 'inf', 'ini', 'iso', 'jar', 'jpeg', 'jpg', 'js', 'lib', 'lnk', 'm4a', 'm4p', 'manifest', 'mid', 'midi', 'mov', 'mp3', 'mpeg', 'mpg', 'msi', 'o', 'obe', 'ocx', 'otf', 'pl', 'plist', 'pm', 'png', 'ppd', 'psd', 'pst', 'py', 'pyc', 'pyd', 'pyo', 'pyw', 'rb', 'rpm', 'scr', 'so', 'svg', 'svn-base', 'sys', 'tar', 'tbl', 'tif', 'tiff', 'ttc', 'ttf', 'upp', 'wav', 'wave', 'wma', 'wmv', 'wmz', 'xpi', 'xpm'] # Allow users to add file extensions in a file to be skipped # filename = 'skip_extensions.txt' if os.path.isfile(filename): fp = open(filename) user_extensions = fp.readlines() fp.close() for user_extension in user_extensions: # Remove whitespace, dots and make lowercase. user_extension = user_extension.strip().strip('.').lower() if user_extension: extensions.append(user_extension) extensions = list(sets.Set(extensions)) else: pass # End of Allow users to add file extensions in a file to be skipped # # Skip .exe for ext in extensions: ext_skip_list.append('.' + ext) #print '.' + ext # Skip .ex_ for ext in extensions: if len(ext) == 3: #print '.' + ext[0:2] + '_' ext_skip_list.append('.' + ext[0:2] + '_') ext_skip_list.sort() #print ext_skip_list, len(ext_skip_list) return ext_skip_list def skip_files(): # Exclude these files from the scan. # Add file names you would like excluded here (all lower case): file_skip_list = ['.find_ssns_exceptions.txt', '.find_ssns.txt', 'find_ssns.html', '.find_ssns_skip.txt', 'find_ssns.pyw', 'find_ssns.exe', 'maxsize.txt'] # Allow users to add file names in a file to be skipped # filename = 'skip_files.txt' if os.path.isfile(filename): fp = open(filename) user_files = fp.readlines() fp.close() for user_file in user_files: user_file = user_file.strip().lower() if user_file: file_skip_list.append(user_file) file_skip_list = list(sets.Set(file_skip_list)) else: pass # End of Allow users to add file names in a file to be skipped # file_skip_list.sort() #print file_skip_list, len(file_skip_list) return file_skip_list def skip_folders(): # Exclude these folders from the scan. # Add folder names you would like excluded here (all lower case): folder_skip_list = ['dev', 'proc', 'sys'] # Allow users to add folder names to be skipped # filename = 'skip_folders.txt' if os.path.isfile(filename): fp = open(filename) user_folders = fp.readlines() fp.close() for user_folder in user_folders: user_folder = user_folder.strip().lower() if user_folder: folder_skip_list.append(user_folder) folder_skip_list = list(sets.Set(folder_skip_list)) else: pass folder_skip_list.sort() #print folder_skip_list, len(folder_skip_list) return folder_skip_list def numbers(both): # Return (Regex and search for value) for report # The Regular Expressions. We are only looking for strings like this: # 1. nnnnnnnnn 'nnn-nn-nnnn' 'nnn nn nnnn' SSN # 2. n(13,16) with dashes or spaces anywhere CCN # Search only SSNs if both == 0: nums = re.compile(r'\b\d{9}\b|\b\d{3}-\d{2}-\d{4}\b|\b\d{3} \d{2} \d{4}\b') search_for_value = 'SSNs' return (nums, search_for_value) # Search only CCNs if both == 1: nums = re.compile(r'\b(?:\d[ -]*){13,16}\b') search_for_value = 'CCNs' return (nums, search_for_value) # Search all regexs if both == 2: nums = re.compile(r'\b\d{9}\b|\b\d{3}-\d{2}-\d{4}\b|\b\d{3} \d{2} \d{4}\b|\b(?:\d[ -]*){13,16}\b') search_for_value = 'SSNs + CCNs' return (nums, search_for_value) def target_files(search_path, ext_skip_list, file_skip_list, folder_skip_list, path_to_results, mode='gui', maxsize=100000000): # Allow users to set maxsize of files to be searched. # Set dmaxsize (default maxsize) to equal 100MB. dmaxsize = maxsize if os.path.isfile('maxsize.txt'): fp = open('maxsize.txt') # Change maxsize to user specified number *IF* it's bigger than the default maxsize. try: usersize = int(fp.read().strip()) if usersize > dmaxsize: maxsize = usersize else: maxsize = dmaxsize # 'maxsize.txt' contains a non-numeric, fallback to dmaxsize. except ValueError: maxsize = dmaxsize fp.close() #print maxsize target_file_list = [] if mode == 'gui': pass else: print "Building file list... please wait." sk = open(os.path.join(path_to_results, '.Find_SSNs_skip.txt'), 'a') for root, dirs, files in os.walk(search_path): # Remove dirs from search. for d in dirs[:]: try: if d.lower() in folder_skip_list: dirs.remove(d) print >> sk, os.path.join(root, d), "\tParticular Folder" except Exception,e: er = open(os.path.join(path_to_results, '.Find_SSNs_exceptions.txt'), 'a') print >> er, e er.close() # Remove files from search. for f in files: try: file_size = os.stat(os.path.join(root,f))[6] ext = os.path.splitext(f) # Skip files larger than maxsize if file_size > maxsize: print >> sk, os.path.join(root,f), "\tToo Large" # Skip Symbolic Links (only works on POSIX systems, but does not harm Windows) # Requested by Luke Ward. elif os.path.islink(os.path.join(root,f)): print >> sk, os.path.join(root,f), "\tSymbolic Link" # Skip particular files elif f.lower() in file_skip_list: print >> sk, os.path.join(root,f), "\tParticular File" # Skip files that have certain extensions elif ext[1].lower() in ext_skip_list: print >> sk, os.path.join(root,f), "\tExtension Skipped" # Scan all other files else: target_file_list.append(os.path.join(root,f)) except Exception, e: er = open(os.path.join(path_to_results, '.Find_SSNs_exceptions.txt'), 'a') print >> er, e er.close() sk.close() return target_file_list, maxsize def hunt(target_file_list, path_to_results, reg_exp, search_for_value, mode='gui', mask=False): # Delimiters to be removed. bad = re.compile(r'[-\s.|]') tt_time = time.strftime("%a_%b_%d_%Y_%H_%M_%S_%p", time.localtime()) # The list of suspect files: suspect = [] ## # If 'mask.txt' is present, set mask to True. ## if os.path.isfile('mask.txt'): ## mask = True # Increase threshold to reduce false positives. # Set dthreshold (default threshold) to equal threshold threshold = 1 dthreshold = threshold if os.path.isfile('threshold.txt'): fp = open('threshold.txt') # Change threshold to user specified number. try: threshold = int(fp.read().strip()) # 'threshold.txt' contains a non-numeric, fallback to dthreshold. except ValueError: threshold = dthreshold fp.close() #print threshold results = open(os.path.join(path_to_results, 'Find_SSNs.html'), 'a') def validate(numbers, filename): details = open(os.path.join(path_to_results, '.Find_SSNs.txt'), 'a') #print numbers, filename def valid_ccn(ccn): ############################## Start # Author David Shaw (Luhn Algorithm) # Source http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/172845 # Modified slightly by Brad Tilley sumit = 0 num_digits = len(ccn) oddeven = num_digits & 1 for count in range(0, num_digits): digit = int(ccn[count]) if not (( count & 1 ) ^ oddeven ): digit = digit * 2 if digit > 9: digit = digit - 9 sumit = sumit + digit ############################### End if (sumit % 10) == 0: # Any card with 1 digit prefix if ccn[0] in cs.keys(): for k,v in cs.iteritems(): if ccn[0] == k and len(ccn) in v[0]: return (True, True) # Any card with 2 digit prefix elif ccn[:2] in cs.keys(): for k,v in cs.iteritems(): if ccn[:2] == k and len(ccn) == v[0]: return (True, True) # Any card with 3 digit prefix elif ccn[:3] in cs.keys(): for k,v in cs.iteritems(): if ccn[:3] == k and len(ccn) == v[0]: return (True, True) # Any card with 4 digit prefix elif ccn[:4] in cs.keys(): for k,v in cs.iteritems(): if ccn[:4] == k and len(ccn) == v[0]: return (True, True) # Obviously not a CC we're looking for, but note that there are other cards out there. else: #print ccn, "Not a credit card we're searching for." return (False, False) else: return (False, False) # End of valid_ccn def valid_ssn(area_number, group_number, serial_number): if group_number == '00': return (False, False) if serial_number == '0000': return (False, False) odd_one = [1,3,5,7,9] even_two = range(10, 100, 2) # (10-98 even only) even_three = [2,4,6,8] odd_four = range(11, 100, 2)# (11-99 odd only) if area_number in ag.keys(): for area, group in ag.iteritems(): # Look up area number to find max group number if area_number == area: # For little odds (odds between 1 and 9) if int(group) in odd_one: if int(group_number) in odd_one and int(group_number) <= int(group): #print '%s-%s-%s valid SSN' %(area_number, group_number, serial_number) return (True, True) else: return (False, False) # For big evens (evens between 10 and 98) elif int(group) in even_two: ok_areas = odd_one + [a for a in even_two if a <= int(group)] #print ok_areas if int(group_number) in ok_areas: #print '%s-%s-%s valid SSN' %(area_number, group_number, serial_number) return (True, True) else: return (False, False) # For little evens (evens between 2 and 8) elif int(group) in even_three: ok_areas = odd_one + even_two + [a for a in even_three if a <= int(group)] #print ok_areas if int(group_number) in ok_areas: #print '%s-%s-%s valid SSN' %(area_number, group_number, serial_number) return (True, True) else: return (False, False) # For big odds (odds between 11 and 99) elif int(group) in odd_four: ok_areas = odd_one + even_two + even_three + [a for a in odd_four if a <= int(group)] #print ok_areas if int(group_number) in ok_areas: #print '%s-%s-%s valid SSN' %(area_number, group_number, serial_number) return (True, True) else: return (False, False) else: pass else: # Bad area number. return (False, False) # End of valid_ssn() function. for number in numbers: #print number # Remove delimiters from numbers clean_number = re.sub(bad, "", number) #print clean_number # Validate CCNs if len(clean_number) > 9: is_it = valid_ccn(clean_number) if is_it[0] == True: if f not in suspect: suspect.append(f) print>> details, "\n\n", f, "\n", number else: suspect.append(f) print>> details, number else: pass # Validate SSNs else: digits = [clean_number[0:3], clean_number[3:5], clean_number[5:9]] is_it = valid_ssn(digits[0], digits[1], digits[2]) if is_it[0] == True: if f not in suspect: suspect.append(f) print>> details, "\n\n", f, "\n", number else: suspect.append(f) print>> details, number else: pass details.close() # End of validate() funtion. current_count = 0 if mode == 'gui': app = wx.PySimpleApp() app.MainLoop() # A progress dialog box (for Jeremy Sippel). dialog = wx.ProgressDialog ('Find_SSNs %s' %version_no, '', maximum = len(target_file_list), parent = None, style = wx.PD_AUTO_HIDE | wx.PD_ELAPSED_TIME | wx.PD_ESTIMATED_TIME) for f in target_file_list: try: # Determine if the file is a PDF file is_pdf = False fd = open(f, 'rb') # This reads '%PDF-1.' if it is present. pdf_header = fd.read(7) fd.close() #print pdf_header if pdf_header == '%PDF-1.': is_pdf = True #print f, "is a pdf file." except Exception, e: fp = open(os.path.join(path_to_results, '.Find_SSNs_exceptions.txt'), 'a') print >> fp, e fp.close() #print f current_count = current_count + 1 if mode == 'gui': # A progress dialog box (for Jeremy Sippel). dialog.Update(current_count, 'Searching file %s of %s' %(current_count, len(target_file_list))) else: print "Searching file %s of %s" %(current_count, len(target_file_list)) # Handle zip archives (zip, OOo XML and MS Office XML) if zipfile.is_zipfile(f): try: x = zipfile.ZipFile(f) zfiles = x.namelist() for zf in zfiles: data = x.read(zf) if data: search = reg_exp.findall(data) if search: #print search validate(search, f) x.close() except Exception, e: fp = open(os.path.join(path_to_results, '.Find_SSNs_exceptions.txt'), 'a') print >> fp, e fp.close() # Handle PDF files in the future elif is_pdf: ##print f, "is a pdf file." pass # Handle most other files. else: try: potential_ssns = [] target_file = open(f, 'rb') while 1: data = target_file.read(1048576) if data: search = reg_exp.findall(data) if search: potential_ssns += search else: break target_file.close() validate(potential_ssns, f) except Exception, e: fp = open(os.path.join(path_to_results, '.Find_SSNs_exceptions.txt'), 'a') print >> fp, e fp.close() if mode == 'gui': dialog.Destroy() # Write Report uniqueSet = list(sets.Set(suspect)) suspect_numbers = 0 for item in uniqueSet: if suspect.count(item) >= threshold: suspect_numbers += suspect.count(item) if suspect_numbers == 0: print>> results, '' print>> results, "" print>> results, "" print>> results, "'Find_SSNs %s'" %(version_no) print>> results, "" print>> results, "" print>> results, "

Find_SSNs %s

" %(version_no) print>> results, "Host ", host, " | " print>> results, ip, " | " print>> results, tt_time, " | " print>> results, "Total Suspect Numbers ", suspect_numbers, " | " print>> results, "Threshold ", threshold, " | " print>> results, "Max File Size ", ms, " | " print>> results, "Search For ", search_for_value, "

" print>> results, "Search Path ", search_path, "

" print>> results, "

No Sensitive Numbers Were Found During This Scan

" print>> results, "
End of report" print>> results, "" print>> results, "" else: print>> results, '' print>> results, "" print>> results, "" print>> results, "'Find_SSNs %s'" %(version_no) print>> results, "" print>> results, '' print>> results, "" print>> results, "" print>> results, "

Find_SSNs %s

" %(version_no) print>> results, "Host ", host, " | " print>> results, ip, " | " print>> results, tt_time, " | " print>> results, "Total Suspect Numbers ", suspect_numbers, " | " print>> results, "Threshold ", threshold, " | " print>> results, "Max File Size ", ms, " | " print>> results, "Search For ", search_for_value, "

" print>> results, "Search Path ", search_path, "

" print>> results, "" print>> results, "" print>> results, "" print>> results, "" print>> results, "" print>> results, "" for item in uniqueSet: if suspect.count(item) >= threshold: #print item print>> results, "" %(suspect.count(item)) print>> results, "" %os.path.splitext(item)[1] print>> results, '' %(item, item) print>> results, "
Suspect Number CountFile ExtensionFile Path
%s%s%s
" print>> results, "
End of report" print>> results, "" print>> results, "" results.close() # End of hunt() function. # Run Program ok_options = 'p:P:o:O:sScCaA' usage = '\nOn Linux, Unix and Mac:\nNo GUI: python Find_SSNs.pyw -p /path/of/search -o /path/of/output -s|-c|-a \nGUI: python Find_SSNs.pyw\n\nOn Windows:\nNo GUI: Find_SSNs.exe -p c:\path\of\search -o c:\path\of\output -s|-c|-a\nGUI: Find_SSNs.exe\n' try: options, arguments = getopt.getopt(sys.argv[1:], ok_options) #print options, arguments except getopt.GetoptError, e: #print e # They gave the wrong option on the cmd line. # The script only accepts -p sys.exit(usage) ################# if options: #print options # Make sure cmd line looks exactly like this: # Find_SSNs -p|-P /path -o|-O /path -s|-S|-c|-C|-a|-A if len(options) !=3: sys.exit(usage) if options[0][0] not in ['-p', '-P']: sys.exit(usage) if options[1][0] not in ['-o', '-O']: sys.exit(usage) if options[2][0] not in ['-s', '-S', '-c', '-C', '-a', '-A']: sys.exit(usage) mode = 'nogui' wait(wait_msg(), mode) # Test the search path to ensure it is valid. if os.path.isdir(options[0][1].strip()): # It's a good path, but can this user read it? if os.access(options[0][1].strip(), os.R_OK): search_path = options[0][1].strip() else: sys.exit("You cannot read '%s'" % options[0][1].strip()) else: sys.exit("'%s' is not a valid path." % options[0][1].strip()) # Test the output path to ensure it is valid. if os.path.isdir(options[1][1].strip()): # It's a good path, but can this user write to it? if os.access(options[1][1].strip(), os.W_OK): path_to_results = options[1][1].strip() else: sys.exit("You cannot write to '%s'" % options[1][1].strip()) else: sys.exit("'%s' is not a valid path." % options[1][1].strip()) # Determine what they wish to search for if options[2][0].lower() == '-s': search_for = 0 ns, sfv = numbers(search_for) if options[2][0].lower() == '-c': search_for = 1 ns, sfv = numbers(search_for) if options[2][0].lower() == '-a': search_for = 2 ns, sfv = numbers(search_for) else: mode = 'gui' import wx print "Find_SSNs... Do not close this window." wait(wait_msg(), mode) search_for = get_search_choice(mode) search_path = get_user_input(mode) path_to_results = get_user_output(mode) ns, sfv = numbers(search_for) ################## ag = get_ssa_info(mode) cs = cc_info() try: ip = "%s" %socket.gethostbyname(socket.gethostname()) except Exception, e: ip = "%s" %e try: host = "%s" %socket.gethostname() except Exception, e: host = "%s" %e stop_or_go(status_msg(search_path), mode) create_files(path_to_results) the_files, ms = target_files(search_path, skip_file_extensions(), skip_files(), skip_folders(), path_to_results, mode) hunt(the_files, path_to_results, ns, sfv, mode) signal_end(end_msg(path_to_results), mode)