From 31eb7425c648c689f002d6f910b525e02e99f578 Mon Sep 17 00:00:00 2001 From: sundowndev Date: Mon, 14 Jan 2019 10:29:09 +0100 Subject: [PATCH] no-ansi option & minor refactor --- phoneinfoga.py | 186 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 60 deletions(-) diff --git a/phoneinfoga.py b/phoneinfoga.py index e36846b..f953ff8 100644 --- a/phoneinfoga.py +++ b/phoneinfoga.py @@ -15,6 +15,7 @@ except: print('[!] Missing requirements. Try running python3 -m pip install -r requirements.txt') sys.exit() + def banner(): print(" ___ _ _____ __ ") print(" / _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _ ") @@ -26,14 +27,14 @@ def banner(): print(" Coded by Sundowndev") print("\n") + banner() if sys.version_info[0] < 3: print("\033[1m\033[93m(!) Please run the tool using Python 3" + Style.RESET_ALL) sys.exit() -parser = argparse.ArgumentParser(description= - "Advanced information gathering tool for phone numbers (https://github.com/sundowndev/PhoneInfoga) version {}".format(__version__), +parser = argparse.ArgumentParser(description="Advanced information gathering tool for phone numbers (https://github.com/sundowndev/PhoneInfoga) version {}".format(__version__), usage='%(prog)s -n [options]') parser.add_argument('-n', '--number', metavar='number', type=str, @@ -54,12 +55,17 @@ parser.add_argument('--osint', action='store_true', parser.add_argument('-u', '--update', action='store_true', help='Update the project') +parser.add_argument('--no-ansi', action='store_true', + help='Disable colored output') + args = parser.parse_args() + def resetColors(): if not args.output: print(Style.RESET_ALL) + # Reset text color at exit atexit.register(resetColors) @@ -108,16 +114,19 @@ if args.update: print('Actual version: {}'.format(__version__)) # Fetching last github tag - new_version = json.loads(requests.get('https://api.github.com/repos/sundowndev/PhoneInfoga/tags').content)[0]['name'] + new_version = json.loads(requests.get( + 'https://api.github.com/repos/sundowndev/PhoneInfoga/tags').content)[0]['name'] print('Last version: {}'.format(new_version)) - osintFiles = ['disposable_num_providers.json', 'individuals.json', 'reputation.json', 'social_medias.json'] + osintFiles = ['disposable_num_providers.json', + 'individuals.json', 'reputation.json', 'social_medias.json'] try: print('[*] Updating OSINT files') for file in osintFiles: - url = 'https://raw.githubusercontent.com/sundowndev/PhoneInfoga/master/osint/{}'.format(file) + url = 'https://raw.githubusercontent.com/sundowndev/PhoneInfoga/master/osint/{}'.format( + file) output_directory = 'osint/{}'.format(file) download_file(url, output_directory) @@ -137,23 +146,30 @@ scanners = ['any', 'all', 'numverify', 'ovh'] uagent = [] uagent.append("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14") -uagent.append("Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:26.0) Gecko/20100101 Firefox/26.0") -uagent.append("Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3") -uagent.append("Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)") +uagent.append( + "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:26.0) Gecko/20100101 Firefox/26.0") +uagent.append( + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3") +uagent.append( + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)") uagent.append("Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.7 (KHTML, like Gecko) Comodo_Dragon/16.1.1.0 Chrome/16.0.912.63 Safari/535.7") -uagent.append("Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)") -uagent.append("Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.1) Gecko/20090718 Firefox/3.5.1") -uagent.append("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0") +uagent.append( + "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)") +uagent.append( + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.1) Gecko/20090718 Firefox/3.5.1") +uagent.append( + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0") -number = '' # Full number format -localNumber = '' # Local number format -internationalNumber = '' # International number format -numberCountryCode = '' # Dial code; e.g:"+33" -numberCountry = '' # Country; e.g:France +number = '' # Full number format +localNumber = '' # Local number format +internationalNumber = '' # International number format +numberCountryCode = '' # Dial code; e.g:"+33" +numberCountry = '' # Country; e.g:France googleAbuseToken = '' customFormatting = '' + def search(req, stop): global googleAbuseToken global uagent @@ -173,12 +189,14 @@ def search(req, stop): } try: - URL = 'https://www.google.com/search?tbs=li:1&q={}&gws_rd=ssl'.format(req) + URL = 'https://www.google.com/search?tbs=li:1&q={}&gws_rd=ssl'.format( + req) r = s.get(URL + googleAbuseToken, headers=headers) while r.status_code == 503: print(code_warning + 'You are temporary blacklisted from Google search. Complete the captcha at the following URL and copy/paste the content of GOOGLE_ABUSE_EXEMPTION cookie : {}'.format(URL)) - print('\n' + code_info + 'Need help ? Read https://github.com/sundowndev/PhoneInfoga#dealing-with-google-captcha') + print('\n' + code_info + + 'Need help ? Read https://github.com/sundowndev/PhoneInfoga#dealing-with-google-captcha') token = input('\nGOOGLE_ABUSE_EXEMPTION=') googleAbuseToken = '&google_abuse=' + token r = s.get(URL + googleAbuseToken, headers=headers) @@ -210,9 +228,11 @@ def search(req, stop): except: print(code_error + 'Request failed. Please retry or open an issue on GitHub.') + def formatNumber(InputNumber): return re.sub("(?:\+)?(?:[^[0-9]*)", "", InputNumber) + def localScan(InputNumber): global number global localNumber @@ -232,20 +252,26 @@ def localScan(InputNumber): if not phonenumbers.is_valid_number(PhoneNumberObject): return False - number = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace('+', '') - numberCountryCode = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL).split(' ')[0] + number = phonenumbers.format_number( + PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace('+', '') + numberCountryCode = phonenumbers.format_number( + PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL).split(' ')[0] - countryRequest = json.loads(requests.request('GET', 'https://restcountries.eu/rest/v2/callingcode/{}'.format(numberCountryCode.replace('+', ''))).content) + countryRequest = json.loads(requests.request( + 'GET', 'https://restcountries.eu/rest/v2/callingcode/{}'.format(numberCountryCode.replace('+', ''))).content) numberCountry = countryRequest[0]['alpha2Code'] - localNumber = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace(numberCountryCode, '') - internationalNumber = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL) + localNumber = phonenumbers.format_number( + PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace(numberCountryCode, '') + internationalNumber = phonenumbers.format_number( + PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL) print(code_result + 'International format: {}'.format(internationalNumber)) print(code_result + 'Local format: 0{}'.format(localNumber)) print(code_result + 'Country code: {}'.format(numberCountryCode)) print(code_result + 'Location: {}'.format(geocoder.description_for_number(PhoneNumberObject, "en"))) - print(code_result + 'Carrier: {}'.format(carrier.name_for_number(PhoneNumberObject, 'en'))) + print(code_result + + 'Carrier: {}'.format(carrier.name_for_number(PhoneNumberObject, 'en'))) print(code_result + 'Area: {}'.format(geocoder.description_for_number(PhoneNumberObject, 'en'))) for timezoneResult in timezone.time_zones_for_number(PhoneNumberObject): print(code_result + 'Timezone: {}'.format(timezoneResult)) @@ -255,6 +281,7 @@ def localScan(InputNumber): else: print(code_warning + 'The number is valid but might not be possible.') + def numverifyScan(): global number @@ -288,7 +315,8 @@ def numverifyScan(): 'cache-control': "no-cache" } - response = requests.request("GET", "https://numverify.com/php_helper_scripts/phone_api.php?secret_key={}&number={}".format(apiKey, number), data="", headers=headers) + response = requests.request( + "GET", "https://numverify.com/php_helper_scripts/phone_api.php?secret_key={}&number={}".format(apiKey, number), data="", headers=headers) if response.content == "Unauthorized" or response.status_code != 200: print((code_error + "An error occured while calling the API (bad request or wrong api key).")) @@ -300,10 +328,13 @@ def numverifyScan(): print((code_error + "Error: Please specify a valid phone number. Example: +6464806649")) sys.exit() - InternationalNumber = '({}){}'.format(data["country_prefix"], data["local_format"]) + InternationalNumber = '({}){}'.format( + data["country_prefix"], data["local_format"]) - print((code_result + "Number: ({}) {}").format(data["country_prefix"],data["local_format"])) - print((code_result + "Country: {} ({})").format(data["country_name"],data["country_code"])) + print((code_result + + "Number: ({}) {}").format(data["country_prefix"], data["local_format"])) + print((code_result + + "Country: {} ({})").format(data["country_name"], data["country_code"])) print((code_result + "Location: {}").format(data["location"])) print((code_result + "Carrier: {}").format(data["carrier"])) print((code_result + "Line type: {}").format(data["line_type"])) @@ -313,6 +344,7 @@ def numverifyScan(): elif data["line_type"] == 'mobile': print((code_warning + "This is most likely a mobile number, but it can still be a VoIP number.")) + def ovhScan(): global localNumber global numberCountry @@ -322,14 +354,15 @@ def ovhScan(): print(code_info + 'Running OVH scan...') - querystring = { "country": numberCountry.lower() } + querystring = {"country": numberCountry.lower()} headers = { 'accept': "application/json", 'cache-control': "no-cache" } - response = requests.request("GET", "https://api.ovh.com/1.0/telephony/number/detailedZones", data="", headers=headers, params=querystring) + response = requests.request( + "GET", "https://api.ovh.com/1.0/telephony/number/detailedZones", data="", headers=headers, params=querystring) data = json.loads(response.content) @@ -339,11 +372,14 @@ def ovhScan(): for voip_number in data: if voip_number['number'] == askedNumber: print((code_info + "1 result found in OVH database")) - print((code_result + "Number range: {}".format(voip_number['number']))) + print( + (code_result + "Number range: {}".format(voip_number['number']))) print((code_result + "City: {}".format(voip_number['city']))) - print((code_result + "Zip code: {}".format(voip_number['zipCode'] if voip_number['zipCode'] is not None else ''))) + print((code_result + "Zip code: {}".format( + voip_number['zipCode'] if voip_number['zipCode'] is not None else ''))) askForExit() + def replaceVariables(string): global number global internationalNumber @@ -355,6 +391,7 @@ def replaceVariables(string): return string + def osintIndividualScan(): global number global internationalNumber @@ -366,17 +403,20 @@ def osintIndividualScan(): for dork in dorks: if dork['dialCode'] is None or dork['dialCode'] == numberCountryCode: if customFormatting: - dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting) + dorkRequest = replaceVariables( + dork['request']) + ' | intext:"{}"'.format(customFormatting) else: dorkRequest = replaceVariables(dork['request']) - print((code_info + "Searching for footprints on {}...".format(dork['site']))) + print( + (code_info + "Searching for footprints on {}...".format(dork['site']))) for result in search(dorkRequest, stop=dork['stop']): if result: print((code_result + "URL: " + result)) else: return -1 + def osintReputationScan(): global number global internationalNumber @@ -386,7 +426,8 @@ def osintReputationScan(): for dork in dorks: if customFormatting: - dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting) + dorkRequest = replaceVariables( + dork['request']) + ' | intext:"{}"'.format(customFormatting) else: dorkRequest = replaceVariables(dork['request']) @@ -395,6 +436,7 @@ def osintReputationScan(): if result: print((code_result + "URL: " + result)) + def osintSocialMediaScan(): global number global internationalNumber @@ -404,15 +446,18 @@ def osintSocialMediaScan(): for dork in dorks: if customFormatting: - dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting) + dorkRequest = replaceVariables( + dork['request']) + ' | intext:"{}"'.format(customFormatting) else: dorkRequest = replaceVariables(dork['request']) - print((code_info + "Searching for footprints on {}...".format(dork['site']))) + print( + (code_info + "Searching for footprints on {}...".format(dork['site']))) for result in search(dorkRequest, stop=dork['stop']): if result: print((code_result + "URL: " + result)) + def osintDisposableNumScan(): global number @@ -421,13 +466,15 @@ def osintDisposableNumScan(): for dork in dorks: dorkRequest = replaceVariables(dork['request']) - print((code_info + "Searching for footprints on {}...".format(dork['site']))) + print( + (code_info + "Searching for footprints on {}...".format(dork['site']))) for result in search(dorkRequest, stop=dork['stop']): if result: print((code_result + "Result found: {}".format(dork['site']))) print((code_result + "URL: " + result)) askForExit() + def osintScan(): global number global localNumber @@ -443,9 +490,11 @@ def osintScan(): # Whitepages print((code_info + "Generating scan URL on 411.com...")) - print(code_result + "Scan URL: https://www.411.com/phone/{}".format(internationalNumber.replace('+', '').replace(' ', '-'))) + print(code_result + "Scan URL: https://www.411.com/phone/{}".format( + internationalNumber.replace('+', '').replace(' ', '-'))) - askingCustomPayload = input(code_info + 'Would you like to use an additional format for this number ? (y/N) ') + askingCustomPayload = input( + code_info + 'Would you like to use an additional format for this number ? (y/N) ') if askingCustomPayload == 'y' or askingCustomPayload == 'yes': customFormatting = input(code_info + 'Custom format: ') @@ -454,9 +503,11 @@ def osintScan(): print((code_info + "Searching for footprints on web pages... (limit=5)")) if customFormatting: - req = '{} | intext:"{}" | intext:"{}" | intext:"{}"'.format(number,number,internationalNumber,customFormatting) + req = '{} | intext:"{}" | intext:"{}" | intext:"{}"'.format( + number, number, internationalNumber, customFormatting) else: - req = '{} | intext:"{}" | intext:"{}"'.format(number,number,internationalNumber) + req = '{} | intext:"{}" | intext:"{}"'.format( + number, number, internationalNumber) for result in search(req, stop=5): if result: print((code_result + "Result found: " + result)) @@ -464,9 +515,11 @@ def osintScan(): # Documents print((code_info + "Searching for documents... (limit=10)")) if customFormatting: - req = '[ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt | ext:xls && intext:"{}"]'.format(customFormatting) + req = '[ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt | ext:xls && intext:"{}"]'.format( + customFormatting) else: - req = '[ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt | ext:xls && intext:"{}" | intext:"{}"]'.format(number,internationalNumber) + req = '[ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt | ext:xls && intext:"{}" | intext:"{}"]'.format( + number, internationalNumber) for result in search(req, stop=10): if result: print((code_result + "Result found: " + result)) @@ -476,20 +529,24 @@ def osintScan(): osintReputationScan() print((code_info + "Generating URL on scamcallfighters.com...")) - print(code_result + 'http://www.scamcallfighters.com/search-phone-{}.html'.format(number)) + print(code_result + + 'http://www.scamcallfighters.com/search-phone-{}.html'.format(number)) - tmpNumAsk = input(code_info + "Would you like to search for temporary number providers footprints ? (Y/n) ") + tmpNumAsk = input( + code_info + "Would you like to search for temporary number providers footprints ? (Y/n) ") if tmpNumAsk.lower() != 'n' and tmpNumAsk.lower() != 'no': print((code_info + '---- Temporary number providers footprints ----')) - + try: print((code_info + "Searching for phone number on tempophone.com...")) - response = requests.request("GET", "https://tempophone.com/api/v1/phones") + response = requests.request( + "GET", "https://tempophone.com/api/v1/phones") data = json.loads(response.content) for voip_number in data['objects']: if voip_number['phone'] == formatNumber(number): - print((code_result + "Found a temporary number provider: tempophone.com")) + print( + (code_result + "Found a temporary number provider: tempophone.com")) askForExit() except: print((code_error + "Unable to reach tempophone.com API. Skipping.")) @@ -504,10 +561,12 @@ def osintScan(): if numberCountryCode == '+1': print((code_info + "Generating URL on True People... ")) - print(code_result + 'https://www.truepeoplesearch.com/results?phoneno={}'.format(internationalNumber.replace(' ', ''))) + print(code_result + 'https://www.truepeoplesearch.com/results?phoneno={}'.format( + internationalNumber.replace(' ', ''))) osintIndividualScan() + def askForExit(): if not args.output: user_input = input(code_info + "Continue scanning ? (y/N) ") @@ -518,8 +577,10 @@ def askForExit(): print(code_info + "Good bye!") sys.exit() + def scanNumber(InputNumber): - print(code_title + "[!] ---- Fetching informations for {} ---- [!]".format(formatNumber(InputNumber))) + print(code_title + + "[!] ---- Fetching informations for {} ---- [!]".format(formatNumber(InputNumber))) localScan(InputNumber) @@ -539,22 +600,18 @@ def scanNumber(InputNumber): print(code_info + "Scan finished.") - print('\n' + Style.RESET_ALL) + if not args.no_ansi and not args.output: + print('\n' + Style.RESET_ALL) + else: + print('\n') try: - if args.output: + if args.no_ansi or args.output: code_info = '[*] ' code_warning = '(!) ' code_result = '[+] ' code_error = '[!] ' code_title = '' - - if args.osint: - print('\033[91m[!] OSINT scanner is not available using output option (sorry).') - sys.exit() - - sys.stdout = args.output - banner() else: code_info = Fore.RESET + Style.BRIGHT + '[*] ' code_warning = Fore.YELLOW + Style.BRIGHT + '(!) ' @@ -562,6 +619,15 @@ try: code_error = Fore.RED + Style.BRIGHT + '[!] ' code_title = Fore.YELLOW + Style.BRIGHT + if args.output: + if args.osint: + print( + '\033[91m[!] OSINT scanner is not available using output option (sorry).') + sys.exit() + + sys.stdout = args.output + banner() + # Verify scanner option if not args.scanner in scanners: print((code_error + "Error: scanner doesn't exists."))