From 3964c4a504e9830f93efcbc60f2e925570c25544 Mon Sep 17 00:00:00 2001 From: sundowndev Date: Mon, 10 Dec 2018 16:22:38 +0100 Subject: [PATCH 1/8] Refactor to use Python3 using 2to3 --- phoneinfoga.py | 166 ++++++++++++++++++++++++------------------------- 1 file changed, 82 insertions(+), 84 deletions(-) diff --git a/phoneinfoga.py b/phoneinfoga.py index 6ad1b35..0014c7a 100644 --- a/phoneinfoga.py +++ b/phoneinfoga.py @@ -3,17 +3,17 @@ __version__ = '0.9-dev' def banner(): - print " ___ _ _____ __ " - print " / _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _ " - print " / /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |" - print " / ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |" - print " \/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|" - print " |___/ " - print " PhoneInfoga Ver. %s " % __version__ - print " Coded by Sundowndev " - print "\n" + print(" ___ _ _____ __ ") + print(" / _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _ ") + print(" / /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |") + print(" / ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |") + print(" \/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|") + print(" |___/ ") + print(" PhoneInfoga Ver. %s " % __version__) + print(" Coded by Sundowndev ") + print("\n") -print "\n \033[92m" +print("\n \033[92m") banner() import sys @@ -50,7 +50,7 @@ if not len(sys.argv) > 1: sys.exit(); if args.update: - print 'update' + print('update') sys.exit() try: @@ -66,10 +66,10 @@ try: from phonenumbers import geocoder from phonenumbers import timezone except KeyboardInterrupt: - print '\033[91m[!] Exiting.' + print('\033[91m[!] Exiting.') sys.exit() except: - print '\033[91m[!] Missing requirements. Try running pip install -r requirements.txt' + print('\033[91m[!] Missing requirements. Try running pip install -r requirements.txt') sys.exit() scanners = ['any', 'all', 'numverify', 'ovh'] @@ -116,9 +116,9 @@ def search(req, stop): 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 : %s' % URL - print '\n' + code_info + 'Need help ? Read https://github.com/sundowndev/PhoneInfoga#dealing-with-google-captcha' - token = raw_input('\nGOOGLE_ABUSE_EXEMPTION=') + 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 : %s' % URL) + 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) @@ -147,7 +147,7 @@ def search(req, stop): return links except: - print code_error + 'Request failed. Please retry or open an issue on GitHub.' + print(code_error + 'Request failed. Please retry or open an issue on GitHub.') def formatNumber(InputNumber): return re.sub("(?:\+)?(?:[^[0-9]*)", "", InputNumber) @@ -159,7 +159,7 @@ def localScan(InputNumber): global numberCountryCode global numberCountry - print code_info + 'Running local scan...' + print(code_info + 'Running local scan...') FormattedPhoneNumber = "+" + formatNumber(InputNumber) @@ -180,19 +180,19 @@ def localScan(InputNumber): localNumber = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace(numberCountryCode, '') internationalNumber = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL) - print code_result + 'International format: %s' % internationalNumber - print code_result + 'Local format: 0%s' % localNumber - print code_result + 'Country code: %s' % numberCountryCode - print code_result + 'Location: %s' % geocoder.description_for_number(PhoneNumberObject, "en") - print code_result + 'Carrier: %s' % carrier.name_for_number(PhoneNumberObject, 'en') - print code_result + 'Area: %s' % geocoder.description_for_number(PhoneNumberObject, 'en') + print(code_result + 'International format: %s' % internationalNumber) + print(code_result + 'Local format: 0%s' % localNumber) + print(code_result + 'Country code: %s' % numberCountryCode) + print(code_result + 'Location: %s' % geocoder.description_for_number(PhoneNumberObject, "en")) + print(code_result + 'Carrier: %s' % carrier.name_for_number(PhoneNumberObject, 'en')) + print(code_result + 'Area: %s' % geocoder.description_for_number(PhoneNumberObject, 'en')) for timezoneResult in timezone.time_zones_for_number(PhoneNumberObject): - print code_result + 'Timezone: %s' % (timezoneResult) + print(code_result + 'Timezone: %s' % (timezoneResult)) if phonenumbers.is_possible_number(PhoneNumberObject): - print code_info + 'The number is valid and possible.' + print(code_info + 'The number is valid and possible.') else: - print code_warning + 'The number is valid but might not be possible.' + print(code_warning + 'The number is valid but might not be possible.') def numverifyScan(): global number @@ -200,7 +200,7 @@ def numverifyScan(): if not args.scanner == 'numverify' and not args.scanner == 'all': return -1 - print code_info + 'Running Numverify.com scan...' + print(code_info + 'Running Numverify.com scan...') requestSecret = '' resp = requests.get('https://numverify.com/') @@ -210,9 +210,7 @@ def numverifyScan(): requestSecret = tag['value'] break; - apiKey = hashlib.md5() - apiKey.update(number + requestSecret) - apiKey = apiKey.hexdigest() + apiKey = hashlib.md5((number + requestSecret).encode('utf-8')).hexdigest() headers = { 'host': "numverify.com", @@ -232,27 +230,27 @@ def numverifyScan(): response = requests.request("GET", "https://numverify.com/php_helper_scripts/phone_api.php?secret_key=" + apiKey + "&number=" + 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).") + print((code_error + "An error occured while calling the API (bad request or wrong api key).")) return -1 data = json.loads(response.content) if data["valid"] == False: - print(code_error + "Error: Please specify a valid phone number. Example: +6464806649") + print((code_error + "Error: Please specify a valid phone number. Example: +6464806649")) sys.exit() InternationalNumber = '('+data["country_prefix"]+')' + data["local_format"] - print(code_result + "Number: (%s) %s") % (data["country_prefix"],data["local_format"]) - print(code_result + "Country: %s (%s)") % (data["country_name"],data["country_code"]) - print(code_result + "Location: %s") % data["location"] - print(code_result + "Carrier: %s") % data["carrier"] - print(code_result + "Line type: %s") % data["line_type"] + print((code_result + "Number: (%s) %s") % (data["country_prefix"],data["local_format"])) + print((code_result + "Country: %s (%s)") % (data["country_name"],data["country_code"])) + print((code_result + "Location: %s") % data["location"]) + print((code_result + "Carrier: %s") % data["carrier"]) + print((code_result + "Line type: %s") % data["line_type"]) if data["line_type"] == 'landline': - print(code_warning + "This is most likely a land line, but it can still be a fixed VoIP.") + print((code_warning + "This is most likely a land line, but it can still be a fixed VoIP.")) elif data["line_type"] == 'mobile': - print(code_warning + "This is most likely a mobile, but it can still be a VoIP.") + print((code_warning + "This is most likely a mobile, but it can still be a VoIP.")) def ovhScan(): global localNumber @@ -261,7 +259,7 @@ def ovhScan(): if not args.scanner == 'ovh' and not args.scanner == 'all': return -1 - print code_info + 'Running OVH scan...' + print(code_info + 'Running OVH scan...') querystring = { "country": numberCountry.lower() } @@ -279,10 +277,10 @@ 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: " + voip_number['number']) - print(code_result + "City: " + voip_number['city']) - print(code_result + "Zip code: " + voip_number['zipCode'] if voip_number['zipCode'] is not None else '') + print((code_info + "1 result found in OVH database")) + print((code_result + "Number range: " + voip_number['number'])) + print((code_result + "City: " + voip_number['city'])) + print((code_result + "Zip code: " + voip_number['zipCode'] if voip_number['zipCode'] is not None else '')) askForExit() def osintIndividualScan(): @@ -300,10 +298,10 @@ def osintIndividualScan(): else: dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) - print(code_info + "Searching for footprints on %s..." % dork['site']) + print((code_info + "Searching for footprints on %s..." % dork['site'])) for result in search(dorkRequest, stop=dork['stop']): if result: - print(code_result + "URL: " + result) + print((code_result + "URL: " + result)) else: return -1 @@ -320,10 +318,10 @@ def osintReputationScan(): else: dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) - print(code_info + "Searching for %s..." % dork['title']) + print((code_info + "Searching for %s..." % dork['title'])) for result in search(dorkRequest, stop=dork['stop']): if result: - print(code_result + "URL: " + result) + print((code_result + "URL: " + result)) def osintSocialMediaScan(): global number @@ -338,10 +336,10 @@ def osintSocialMediaScan(): else: dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) - print(code_info + "Searching for footprints on %s..." % dork['site']) + print((code_info + "Searching for footprints on %s..." % dork['site'])) for result in search(dorkRequest, stop=dork['stop']): if result: - print(code_result + "URL: " + result) + print((code_result + "URL: " + result)) def osintDisposableNumScan(): global number @@ -351,11 +349,11 @@ def osintDisposableNumScan(): for dork in dorks: dorkRequest = dork['request'].replace('$n', number) - print(code_info + "Searching for footprints on %s..." % dork['site']) + print((code_info + "Searching for footprints on %s..." % dork['site'])) for result in search(dorkRequest, stop=dork['stop']): if result: - print(code_result + "Result found: %s" % dork['site']) - print(code_result + "URL: " + result) + print((code_result + "Result found: %s" % dork['site'])) + print((code_result + "URL: " + result)) askForExit() def osintScan(): @@ -369,84 +367,84 @@ def osintScan(): if not args.osint: return -1 - print code_info + 'Running OSINT footprint reconnaissance...' + print(code_info + 'Running OSINT footprint reconnaissance...') # Whitepages - print(code_info + "Generating scan URL on 411.com...") - print code_result + "Scan URL: https://www.411.com/phone/%s" % internationalNumber.replace('+', '').replace(' ', '-') + print((code_info + "Generating scan URL on 411.com...")) + print(code_result + "Scan URL: https://www.411.com/phone/%s" % internationalNumber.replace('+', '').replace(' ', '-')) - askingCustomPayload = raw_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 = raw_input(code_info + 'Custom format: ') + customFormatting = input(code_info + 'Custom format: ') - print(code_info + '---- Web pages footprints ----') + print((code_info + '---- Web pages footprints ----')) - print(code_info + "Searching for footprints on web pages... (limit=5)") + print((code_info + "Searching for footprints on web pages... (limit=5)")) if customFormatting: req = '%s | intext:"%s" | intext:"%s" | intext:"%s"' % (number,number,internationalNumber,customFormatting) else: req = '%s | intext:"%s" | intext:"%s"' % (number,number,internationalNumber) for result in search(req, stop=5): if result: - print(code_result + "Result found: " + result) + print((code_result + "Result found: " + result)) # Documents - print(code_info + "Searching for documents... (limit=10)") + print((code_info + "Searching for documents... (limit=10)")) if customFormatting: req = 'intext:"%s" | intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber,customFormatting) else: req = 'intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber) for result in search('intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber), stop=10): if result: - print(code_result + "Result found: " + result) + print((code_result + "Result found: " + result)) - print(code_info + '---- Reputation footprints ----') + print((code_info + '---- Reputation footprints ----')) osintReputationScan() - print(code_info + "Generating URL on scamcallfighters.com...") - print code_result + 'http://www.scamcallfighters.com/search-phone-%s.html' % number + print((code_info + "Generating URL on scamcallfighters.com...")) + print(code_result + 'http://www.scamcallfighters.com/search-phone-%s.html' % number) - tmpNumAsk = raw_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 ----') + print((code_info + '---- Temporary number providers footprints ----')) - print(code_info + "Searching for phone number on tempophone.com...") + print((code_info + "Searching for phone number on tempophone.com...")) 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() osintDisposableNumScan() - print(code_info + '---- Social media footprints ----') + print((code_info + '---- Social media footprints ----')) osintSocialMediaScan() - print(code_info + '---- Phone books footprints ----') + print((code_info + '---- Phone books footprints ----')) if numberCountryCode == '+1': - print(code_info + "Generating URL on True People... ") - print code_result + 'https://www.truepeoplesearch.com/results?phoneno=%s' % internationalNumber.replace(' ', '') + print((code_info + "Generating URL on True People... ")) + print(code_result + 'https://www.truepeoplesearch.com/results?phoneno=%s' % internationalNumber.replace(' ', '')) osintIndividualScan() def askForExit(): if not args.output: - user_input = raw_input(code_info + "Continue scanning ? (y/N) ") + user_input = input(code_info + "Continue scanning ? (y/N) ") if user_input.lower() == 'y' or user_input.lower() == 'yes': return -1 else: - print code_info + "Good bye!" + print(code_info + "Good bye!") sys.exit() def scanNumber(InputNumber): - print code_title + "[!] ---- Fetching informations for %s ---- [!]" % formatNumber(InputNumber) + print(code_title + "[!] ---- Fetching informations for %s ---- [!]" % formatNumber(InputNumber)) localScan(InputNumber) @@ -457,16 +455,16 @@ def scanNumber(InputNumber): global numberCountry if not number: - print(code_error + "Error: number " + formatNumber(InputNumber) + " is not valid. Skipping.") + print((code_error + "Error: number " + formatNumber(InputNumber) + " is not valid. Skipping.")) sys.exit() numverifyScan() ovhScan() osintScan() - print code_info + "Scan finished." + print(code_info + "Scan finished.") - print '\n' + print('\n') try: if args.output: @@ -477,7 +475,7 @@ try: code_title = '' if args.osint: - print '\033[91m[!] OSINT scanner is not available using output option (sorry).' + print('\033[91m[!] OSINT scanner is not available using output option (sorry).') sys.exit() sys.stdout = args.output @@ -491,7 +489,7 @@ try: # Verify scanner option if not args.scanner in scanners: - print(code_error + "Error: scanner doesn't exists.") + print((code_error + "Error: scanner doesn't exists.")) sys.exit() if args.number: @@ -503,5 +501,5 @@ try: if args.output: args.output.close() except KeyboardInterrupt: - print(code_error + "Scan interrupted. Good bye!") + print((code_error + "Scan interrupted. Good bye!")) sys.exit() From f03061dd00b1f40616be662a3a32bfa762a60be2 Mon Sep 17 00:00:00 2001 From: sundowndev Date: Mon, 10 Dec 2018 16:23:36 +0100 Subject: [PATCH 2/8] Add argparse to requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index ada83e1..7969552 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ requests bs4 html5lib phonenumbers +argparse From aa0485ba9d329814b39571975868601d8a85479e Mon Sep 17 00:00:00 2001 From: sundowndev Date: Mon, 10 Dec 2018 16:24:09 +0100 Subject: [PATCH 3/8] Badges --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3616f0b..a9516b2 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ # PhoneInfoga +![](https://img.shields.io/badge/python-3.x-blue.svg) +![](https://img.shields.io/badge/license-MIT-brightgreen.svg) + Information gathering & OSINT reconnaissance tool for phone numbers. One of the most advanced tools to scan phone numbers using only free resources. The goal is to first gather basic information such as country, area, carrier and line type on any international phone numbers with a very good accuracy. Then try to determine the VoIP provider or search for footprints on search engines to try identify the owner. -**This tool requires python 2.x** - ## Features - Check if phone number exists and is possible @@ -38,7 +39,7 @@ Use `any` to disable this feature. Default value: `all` ```bash git clone https://github.com/sundowndev/PhoneInfoga cd ./PhoneInfoga -pip install -r requirements.txt +pip3 install -r requirements.txt ``` ## Usage From d50ed5d5765bc3f969bb8e3337ebb77975d18c77 Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 11 Dec 2018 09:54:38 +0100 Subject: [PATCH 4/8] Note about dealing with Google CAPTCHA --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a9516b2..a98fd65 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PhoneInfoga -![](https://img.shields.io/badge/python-3.x-blue.svg) -![](https://img.shields.io/badge/license-MIT-brightgreen.svg) +![](https://img.shields.io/badge/python-3.7-blue.svg) +![](https://img.shields.io/badge/license-MIT-blue.svg) Information gathering & OSINT reconnaissance tool for phone numbers. @@ -130,6 +130,8 @@ PhoneInfo use a workaround to handle Google bot detection. When running OSINT sc - Go to **Storage**, then **Cookies** - Copy the value of the *GOOGLE_ABUSE_EXEMPTION* cookie and paste it in the CLI +**Note: sometimes you'll need to refresh the page to get the cookie.** + ![](https://i.imgur.com/KkE1EM5.png) ## Custom formatting From 20495f102468cabf23cb81dc7fab379c43a7404b Mon Sep 17 00:00:00 2001 From: sundowndev Date: Tue, 11 Dec 2018 11:33:21 +0100 Subject: [PATCH 5/8] [Fix #7] Migrating to Python 3 Code refactor to migrate to Python 3. Using format() instead of %s, cleanup strings and dictionaries. Release v0.10-dev --- phoneinfoga.py | 108 +++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/phoneinfoga.py b/phoneinfoga.py index 0014c7a..2011198 100644 --- a/phoneinfoga.py +++ b/phoneinfoga.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 -__version__ = '0.9-dev' +__version__ = '0.10-dev' def banner(): print(" ___ _ _____ __ ") @@ -9,8 +9,8 @@ def banner(): print(" / ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |") print(" \/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|") print(" |___/ ") - print(" PhoneInfoga Ver. %s " % __version__) - print(" Coded by Sundowndev ") + print(" PhoneInfoga Ver. {}".format(__version__)) + print(" Coded by Sundowndev") print("\n") print("\n \033[92m") @@ -20,8 +20,12 @@ import sys import argparse import random +if sys.version_info[0] < 3: + print("\033[1m\033[93m(!) Please run the tool using Python 3") + sys.exit() + parser = argparse.ArgumentParser(description= - "Advanced information gathering tool for phone numbers (https://github.com/sundowndev/PhoneInfoga) version %s" % __version__, + "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, @@ -47,7 +51,7 @@ args = parser.parse_args() # If any param is passed, execute help command if not len(sys.argv) > 1: parser.print_help() - sys.exit(); + sys.exit() if args.update: print('update') @@ -74,7 +78,7 @@ except: scanners = ['any', 'all', 'numverify', 'ovh'] -uagent=[] +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") @@ -112,11 +116,11 @@ def search(req, stop): } try: - URL = 'https://www.google.com/search?tbs=li:1&q=%s&gws_rd=ssl' % (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 : %s' % URL) + 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') token = input('\nGOOGLE_ABUSE_EXEMPTION=') googleAbuseToken = '&google_abuse=' + token @@ -125,8 +129,8 @@ def search(req, stop): soup = BeautifulSoup(r.content, 'html.parser') results = soup.find("div", id="search").find_all("div", class_="g") - links=[] - counter=0 + links = [] + counter = 0 for result in results: counter += 1 @@ -140,7 +144,7 @@ def search(req, stop): url = re.sub(r'(?:\&sa\=)(?:.*)', '', url) url = re.sub(r'(?:\&rct\=)(?:.*)', '', url) - if re.match(r"^(/search\?q=)", url) is not None: + if re.match(r"^(?:\/search\?q\=)", url) is not None: url = 'https://google.com' + url links.append(url) @@ -174,20 +178,20 @@ def localScan(InputNumber): 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/%s' % 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) - print(code_result + 'International format: %s' % internationalNumber) - print(code_result + 'Local format: 0%s' % localNumber) - print(code_result + 'Country code: %s' % numberCountryCode) - print(code_result + 'Location: %s' % geocoder.description_for_number(PhoneNumberObject, "en")) - print(code_result + 'Carrier: %s' % carrier.name_for_number(PhoneNumberObject, 'en')) - print(code_result + 'Area: %s' % geocoder.description_for_number(PhoneNumberObject, 'en')) + 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 + 'Area: {}'.format(geocoder.description_for_number(PhoneNumberObject, 'en'))) for timezoneResult in timezone.time_zones_for_number(PhoneNumberObject): - print(code_result + 'Timezone: %s' % (timezoneResult)) + print(code_result + 'Timezone: {}'.format(timezoneResult)) if phonenumbers.is_possible_number(PhoneNumberObject): print(code_info + 'The number is valid and possible.') @@ -208,7 +212,7 @@ def numverifyScan(): for tag in soup.find_all("input", type="hidden"): if tag['name'] == "scl_request_secret": requestSecret = tag['value'] - break; + break apiKey = hashlib.md5((number + requestSecret).encode('utf-8')).hexdigest() @@ -227,7 +231,7 @@ def numverifyScan(): 'cache-control': "no-cache" } - response = requests.request("GET", "https://numverify.com/php_helper_scripts/phone_api.php?secret_key=" + apiKey + "&number=" + 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).")) @@ -239,18 +243,18 @@ def numverifyScan(): print((code_error + "Error: Please specify a valid phone number. Example: +6464806649")) sys.exit() - InternationalNumber = '('+data["country_prefix"]+')' + data["local_format"] + InternationalNumber = '({}){}'.format(data["country_prefix"], data["local_format"]) - print((code_result + "Number: (%s) %s") % (data["country_prefix"],data["local_format"])) - print((code_result + "Country: %s (%s)") % (data["country_name"],data["country_code"])) - print((code_result + "Location: %s") % data["location"]) - print((code_result + "Carrier: %s") % data["carrier"]) - print((code_result + "Line type: %s") % data["line_type"]) + 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"])) if data["line_type"] == 'landline': - print((code_warning + "This is most likely a land line, but it can still be a fixed VoIP.")) + print((code_warning + "This is most likely a landline, but it can still be a fixed VoIP number.")) elif data["line_type"] == 'mobile': - print((code_warning + "This is most likely a mobile, but it can still be a VoIP.")) + print((code_warning + "This is most likely a mobile number, but it can still be a VoIP number.")) def ovhScan(): global localNumber @@ -278,9 +282,9 @@ 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: " + voip_number['number'])) - print((code_result + "City: " + voip_number['city'])) - print((code_result + "Zip code: " + voip_number['zipCode'] if voip_number['zipCode'] is not None else '')) + 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 ''))) askForExit() def osintIndividualScan(): @@ -294,11 +298,11 @@ def osintIndividualScan(): for dork in dorks: if dork['dialCode'] is None or dork['dialCode'] == numberCountryCode: if customFormatting: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"%s"' % (customFormatting) + dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"{}"'.format(customFormatting) else: dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) - print((code_info + "Searching for footprints on %s..." % 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)) @@ -314,11 +318,11 @@ def osintReputationScan(): for dork in dorks: if customFormatting: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"%s"' % (customFormatting) + dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"{}"'.format(customFormatting) else: dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) - print((code_info + "Searching for %s..." % dork['title'])) + print((code_info + "Searching for {}...".format(dork['title']))) for result in search(dorkRequest, stop=dork['stop']): if result: print((code_result + "URL: " + result)) @@ -332,11 +336,11 @@ def osintSocialMediaScan(): for dork in dorks: if customFormatting: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"%s"' % (customFormatting) + dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"{}"'.format(customFormatting) else: dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) - print((code_info + "Searching for footprints on %s..." % 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)) @@ -349,10 +353,10 @@ def osintDisposableNumScan(): for dork in dorks: dorkRequest = dork['request'].replace('$n', number) - print((code_info + "Searching for footprints on %s..." % 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: %s" % dork['site'])) + print((code_result + "Result found: {}".format(dork['site']))) print((code_result + "URL: " + result)) askForExit() @@ -371,7 +375,7 @@ def osintScan(): # Whitepages print((code_info + "Generating scan URL on 411.com...")) - print(code_result + "Scan URL: https://www.411.com/phone/%s" % 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) ') @@ -382,9 +386,9 @@ def osintScan(): print((code_info + "Searching for footprints on web pages... (limit=5)")) if customFormatting: - req = '%s | intext:"%s" | intext:"%s" | intext:"%s"' % (number,number,internationalNumber,customFormatting) + req = '{} | intext:"{}" | intext:"{}" | intext:"{}"'.format(number,number,internationalNumber,customFormatting) else: - req = '%s | intext:"%s" | intext:"%s"' % (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)) @@ -392,10 +396,10 @@ def osintScan(): # Documents print((code_info + "Searching for documents... (limit=10)")) if customFormatting: - req = 'intext:"%s" | intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber,customFormatting) + req = 'intext:"{}" | intext:"{}" | intext:"{}" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt'.format(number,internationalNumber,customFormatting) else: - req = 'intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber) - for result in search('intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber), stop=10): + req = 'intext:"{}" | intext:"{}" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt'.format(number,internationalNumber) + for result in search('intext:"{}" | intext:"{}" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt'.format(number,internationalNumber), stop=10): if result: print((code_result + "Result found: " + result)) @@ -404,7 +408,7 @@ def osintScan(): osintReputationScan() print((code_info + "Generating URL on scamcallfighters.com...")) - print(code_result + 'http://www.scamcallfighters.com/search-phone-%s.html' % 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) ") @@ -429,7 +433,7 @@ def osintScan(): if numberCountryCode == '+1': print((code_info + "Generating URL on True People... ")) - print(code_result + 'https://www.truepeoplesearch.com/results?phoneno=%s' % internationalNumber.replace(' ', '')) + print(code_result + 'https://www.truepeoplesearch.com/results?phoneno={}'.format(internationalNumber.replace(' ', ''))) osintIndividualScan() @@ -444,7 +448,7 @@ def askForExit(): sys.exit() def scanNumber(InputNumber): - print(code_title + "[!] ---- Fetching informations for %s ---- [!]" % formatNumber(InputNumber)) + print(code_title + "[!] ---- Fetching informations for {} ---- [!]".format(formatNumber(InputNumber))) localScan(InputNumber) @@ -455,7 +459,7 @@ def scanNumber(InputNumber): global numberCountry if not number: - print((code_error + "Error: number " + formatNumber(InputNumber) + " is not valid. Skipping.")) + print((code_error + "Error: number {} is not valid. Skipping.".format(formatNumber(InputNumber)))) sys.exit() numverifyScan() @@ -501,5 +505,5 @@ try: if args.output: args.output.close() except KeyboardInterrupt: - print((code_error + "Scan interrupted. Good bye!")) + print(("\n" + code_error + "Scan interrupted. Good bye!")) sys.exit() From d911cd9b7e2da8eaa595a6b34c499e6145453855 Mon Sep 17 00:00:00 2001 From: sundowndev Date: Tue, 11 Dec 2018 12:01:52 +0100 Subject: [PATCH 6/8] Replace variables in dork requests --- phoneinfoga.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/phoneinfoga.py b/phoneinfoga.py index 2011198..7e1de92 100644 --- a/phoneinfoga.py +++ b/phoneinfoga.py @@ -287,6 +287,17 @@ def ovhScan(): 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 + global localNumber + + string = string.replace('$n', number) + string = string.replace('$i', internationalNumber) + string = string.replace('$l', localNumber) + + return string + def osintIndividualScan(): global number global internationalNumber @@ -298,9 +309,9 @@ def osintIndividualScan(): for dork in dorks: if dork['dialCode'] is None or dork['dialCode'] == numberCountryCode: if customFormatting: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"{}"'.format(customFormatting) + dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting) else: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + dorkRequest = replaceVariables(dork['request']) print((code_info + "Searching for footprints on {}...".format(dork['site']))) for result in search(dorkRequest, stop=dork['stop']): @@ -318,9 +329,9 @@ def osintReputationScan(): for dork in dorks: if customFormatting: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"{}"'.format(customFormatting) + dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting) else: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + dorkRequest = replaceVariables(dork['request']) print((code_info + "Searching for {}...".format(dork['title']))) for result in search(dorkRequest, stop=dork['stop']): @@ -336,9 +347,9 @@ def osintSocialMediaScan(): for dork in dorks: if customFormatting: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"{}"'.format(customFormatting) + dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting) else: - dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + dorkRequest = replaceVariables(dork['request']) print((code_info + "Searching for footprints on {}...".format(dork['site']))) for result in search(dorkRequest, stop=dork['stop']): @@ -351,7 +362,7 @@ def osintDisposableNumScan(): dorks = json.load(open('osint/disposable_num_providers.json')) for dork in dorks: - dorkRequest = dork['request'].replace('$n', number) + dorkRequest = replaceVariables(dork['request']) print((code_info + "Searching for footprints on {}...".format(dork['site']))) for result in search(dorkRequest, stop=dork['stop']): From 1f8cdb6cf4ca324ee36104be6ddd6311909a95f2 Mon Sep 17 00:00:00 2001 From: sundowndev Date: Tue, 11 Dec 2018 12:02:16 +0100 Subject: [PATCH 7/8] OSINT sources --- osint/individuals.json | 16 ++++++++++++++-- osint/reputation.json | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/osint/individuals.json b/osint/individuals.json index abd159c..7b8c8fa 100644 --- a/osint/individuals.json +++ b/osint/individuals.json @@ -1,13 +1,13 @@ [ { "site": "numinfo.net", - "request": "site:\"numinfo.net\" intext:\"$n\" | $i", + "request": "site:\"numinfo.net\" intext:\"$n\" | intext:\"$i\"", "dialCode": null, "stop": 2 }, { "site": "sync.me", - "request": "site:\"sync.me\" intext:\"$n\" | $i", + "request": "site:\"sync.me\" intext:\"$n\" | intext:\"$i\"", "dialCode": null, "stop": 1 }, @@ -16,5 +16,17 @@ "request": "site:\"whocallsyou.de\" intext:\"0$n\"", "dialCode": null, "stop": 1 + }, + { + "site": "pastebin.com", + "request": "site:\"pastebin.com\" intext:\"$n\" | intext:\"$i\"", + "dialCode": null, + "stop": 5 + }, + { + "site": "whycall.me", + "request": "site:\"whycall.me\" intext:\"$n\" | intext:\"$l\"", + "dialCode": null, + "stop": 1 } ] diff --git a/osint/reputation.json b/osint/reputation.json index 47726f0..8cc8e64 100644 --- a/osint/reputation.json +++ b/osint/reputation.json @@ -6,7 +6,7 @@ }, { "title": "phone fraud footprints", - "request": "intitle:\"Phone Fraud\" intext:\"$n\" | \"$n\"", + "request": "intitle:\"Phone Fraud\" intext:\"$n\" | intext:\"$i\"", "stop": 5 } ] From 47ceb86dd540d9f776e618567a3b6b79941025a9 Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 11 Dec 2018 13:42:44 +0100 Subject: [PATCH 8/8] License scan status --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a98fd65..0f2934b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PhoneInfoga -![](https://img.shields.io/badge/python-3.7-blue.svg) +![](https://img.shields.io/badge/python-3.x-blue.svg) ![](https://img.shields.io/badge/license-MIT-blue.svg) Information gathering & OSINT reconnaissance tool for phone numbers. @@ -141,3 +141,5 @@ Sometimes the phone number has footprints but is used with a different formattin ## License This tool is licensed under the GNU General Public License v3.0. + +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fsundowndev%2FPhoneInfoga.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fsundowndev%2FPhoneInfoga?ref=badge_large)