Repository: AbirHasan2005/OPRecon
Branch: master
Commit: da8c95230fdd
Files: 21
Total size: 78.0 KB
Directory structure:
gitextract_p879nsh0/
├── README.md
├── files/
│ ├── RESOURCES.md
│ ├── core/
│ │ ├── FileExporter.py
│ │ ├── IpGeoLocation.py
│ │ ├── IpGeoLocationLib.py
│ │ ├── Logger.py
│ │ ├── Menu.py
│ │ ├── MyExceptions.py
│ │ ├── Utils.py
│ │ └── __init__.py
│ ├── examples/
│ │ └── input.txt
│ ├── ipgeolocation.py
│ ├── osint/
│ │ ├── disposable_num_providers.json
│ │ ├── individuals.json
│ │ ├── reputation.json
│ │ └── social_medias.json
│ ├── phoneinfoga.py
│ └── tracker.py
├── requirements.txt
├── run.sh
└── update.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# OPRecon v1.8-BETA
Using this you can find informations via PhoneInFoga(In-Built), Find location via IP Address & website link via IPGeoLocation(In-Built) and Phone Number Tracker(Made by @AbirHasan2005). Phone Number Tracker will give you IP Address using phone number. For more information join my Telegram Group.
## Telegram Group: http://t.me/linux_repo
Join Telegram Group for help and Feedback.
## Social Sites:
- Twitter: https://twitter.com/AbirHasan2005 [Only Follow]
- Instagram: https://instagram.com/AbirHasan2005 [Only Follow]
- Facebook: https://facebook.com/AbirHasan2005 [Only Follow]
- GitHub: https://github.com/AbirHasan2005
- Telegram Group: http://t.me/linux_repo [Chat]

## How to use:
- Compatible with:
- Linux(Desktop)
- Termux(Android)
- Requirements:
- Python3
- pip3
- Git
- pip packages:
- termcolor
- colorama
- requests
- bs4
- html5lib
- phonenumbers
- argparse
- urllib3
- Commands:
```
git clone https://github.com/AbirHasan2005/OPRecon
cd OPRecon
python3 -m pip install -r requirements.txt
chmod +x *
bash run.sh
```
[](https://paypal.me/AbirHasan2005)
================================================
FILE: files/RESOURCES.md
================================================
### Inderstanding phone numbers
http://whitepages.fr/phonesystem/
https://support.twilio.com/hc/en-us/articles/223183008-Formatting-International-Phone-Numbers
https://en.wikipedia.org/wiki/National_conventions_for_writing_telephone_numbers
### Open data
https://api.ovh.com/console/#/telephony
https://countrycode.org/
http://www.countryareacode.net/en/
http://directory.didww.com/area-prefixes
http://hs3x.com/
http://www.numinfo.net/
# Data sources
Both free and premium resources are included. Be careful, the listing of a data source here does not mean it has been verified or is used in the tool. Data might be false. Use it as an OSINT framework.
### Reputation / fraud
scamcallfighters.com
signal-arnaques.com
### Disposable numbers
receive-sms-online.com
receive-sms-now.com
hs3x.com
twilio.com
freesmsverification.com
freeonlinephone.org
sms-receive.net
smsreceivefree.com
receive-a-sms.com
receivefreesms.com
freephonenum.com
receive-smss.com
receivetxt.com
temp-mails.com
receive-sms.com
receivesmsonline.net
receivefreesms.com
sms-receive.net
pinger.com (=> textnow.com)
receive-a-sms.com
k7.net
kall8.com
faxaway.com
receivesmsonline.com
receive-sms-online.info
sellaite.com
getfreesmsnumber.com
smsreceiving.com
smstibo.com
catchsms.com
freesmscode.com
smsreceiveonline.com
smslisten.com
sms.sellaite.com
### Individuals
Facebook
True People
Fast People
Background Check
Pipl
Spytox
Makelia
IvyCall
PhoneSearch
411
USPhone
WP Plus
Thats Them
True Caller
Sync.me
WhoCallsMe
ZabaSearch
DexKnows
WeLeakInfo
OK Caller
SearchBug
numinfo.net
### Google dork examples
`insubject:"+XXXXXXXXX" | insubject:"+XXXXX" | insubject:"XXXXX XXX XXX`
`insubject:"XXXXXXXXX" | intitle:"XXXXXXXXX"`
`intext:"XXXXXXXXX" 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:html`
`site:"hs3x.com" intext:"+XXXXXXXXX"`
`site:signal-arnaques.com intext:"XXXXXXXXX" intitle:" | Phone Fraud"`
================================================
FILE: files/core/FileExporter.py
================================================
#!/usr/bin/env python3
# encoding: UTF-8
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
import csv
from xml.etree import ElementTree as etree
from collections import OrderedDict
class FileExporter:
def __init__(self):
pass
def ExportListToCSV(self, ipGeoLocObjs, filename):
return self.__ExportToCSV(ipGeoLocObjs, filename)
def ExportToCSV(self, ipGeoLocObj, filename):
return self.__ExportToCSV([ipGeoLocObj], filename)
def ExportListToXML(self, ipGeoLocObjs, filename):
return self.__ExportToXML(ipGeoLocObjs, filename)
def ExportToXML(self, ipGeoLocObj, filename):
return self.__ExportToXML([ipGeoLocObj], filename)
def ExportListToTXT(self, ipGeoLocObjs, filename):
return self.__ExportToTXT(ipGeoLocObjs, filename)
def ExportToTXT(self, ipGeoLocObj, filename):
return self.__ExportToTXT([ipGeoLocObj], filename)
def __ExportToTXT(self, ipGeoLocObjs, filename):
try:
with open(filename, 'w') as txtfile:
txtfile.write('Results IPGeolocation\n')
for ipGeoLocObj in ipGeoLocObjs:
if ipGeoLocObj:
txtfile.write('Target: {}\n'.format(ipGeoLocObj.Query))
txtfile.write('IP: {}\n'.format(ipGeoLocObj.IP))
txtfile.write('ASN: {}\n'.format(ipGeoLocObj.ASN))
txtfile.write('City: {}\n'.format(ipGeoLocObj.City))
txtfile.write('Country: {}\n'.format(ipGeoLocObj.Country))
txtfile.write('Country Code: {}\n'.format(ipGeoLocObj.CountryCode))
txtfile.write('ISP: {}\n'.format(ipGeoLocObj.ISP))
txtfile.write('Latitude: {}\n'.format(ipGeoLocObj.Latitude))
txtfile.write('Longtitude: {}\n'.format(ipGeoLocObj.Longtitude))
txtfile.write('Organization: {}\n'.format(ipGeoLocObj.Organization))
txtfile.write('Region: {}\n'.format(ipGeoLocObj.Region))
txtfile.write('Region Name: {}\n'.format(ipGeoLocObj.RegionName))
txtfile.write('Timezone: {}\n'.format(ipGeoLocObj.Timezone))
txtfile.write('Zip: {}\n'.format(ipGeoLocObj.Zip))
txtfile.write('Google Maps: {}\n'.format(ipGeoLocObj.GoogleMapsLink))
txtfile.write('\n')
return True
except:
return False
def __ExportToXML(self, ipGeoLocObjs, filename):
try:
root = etree.Element('Results')
for ipGeoLocObj in ipGeoLocObjs:
if ipGeoLocObj:
orderedData = OrderedDict(sorted(ipGeoLocObj.ToDict().items()))
self.__add_items(etree.SubElement(root, 'IPGeolocation'),
((key.replace(' ', ''), value) for key, value in orderedData.items()))
tree = etree.ElementTree(root)
tree.write(filename, xml_declaration=True, encoding='utf-8')
return True
except:
return False
def __ExportToCSV(self, ipGeoLocObjs, filename):
try:
with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=';', quoting=csv.QUOTE_MINIMAL)
writer.writerow(['Results', 'IPGeolocation'])
for ipGeoLocObj in ipGeoLocObjs:
if ipGeoLocObj:
writer.writerow(['Target', ipGeoLocObj.Query])
writer.writerow(['IP', ipGeoLocObj.IP])
writer.writerow(['ASN', ipGeoLocObj.ASN])
writer.writerow(['City', ipGeoLocObj.City])
writer.writerow(['Country', ipGeoLocObj.Country])
writer.writerow(['Country Code', ipGeoLocObj.CountryCode])
writer.writerow(['ISP', ipGeoLocObj.ISP])
writer.writerow(['Latitude', ipGeoLocObj.Latitude])
writer.writerow(['Longtitude', ipGeoLocObj.Longtitude])
writer.writerow(['Organization', ipGeoLocObj.Organization])
writer.writerow(['Region', ipGeoLocObj.Region])
writer.writerow(['Region Name', ipGeoLocObj.RegionName])
writer.writerow(['Timezone', ipGeoLocObj.Timezone])
writer.writerow(['Zip', ipGeoLocObj.Zip])
writer.writerow(['Google Maps', ipGeoLocObj.GoogleMapsLink])
writer.writerow([])
return True
except:
return False
def __add_items(self, root, items):
for name, text in items:
elem = etree.SubElement(root, name)
elem.text = text
================================================
FILE: files/core/IpGeoLocation.py
================================================
#!/usr/bin/env python3
# encoding: UTF-8
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
class IpGeoLocation:
"""Represents an IP Geolocation information object"""
def __init__(self, query, jsonData = None):
self.Query = query
self.ASN = '-'
self.City = '-'
self.Country = '-'
self.CountryCode = '-'
self.ISP = '-'
self.Latitude = 0.0
self.Longtitude = 0.0
self.Organization = '-'
self.IP = '0.0.0.0'
self.Region = '-'
self.RegionName = '-'
self.Status = '-'
self.Timezone = '-'
self.Zip = '-'
self.GoogleMapsLink = ''
if jsonData != None:
if type(jsonData) is dict:
if 'as' in jsonData:
self.ASN = jsonData['as']
if 'city' in jsonData:
self.City = jsonData['city']
if 'country' in jsonData:
self.Country = jsonData['country']
if 'countryCode' in jsonData:
self.CountryCode = jsonData['countryCode']
if 'isp' in jsonData:
self.ISP = jsonData['isp']
if 'lat' in jsonData:
self.Latitude = jsonData['lat']
if 'lon' in jsonData:
self.Longtitude = jsonData['lon']
if 'org' in jsonData:
self.Organization = jsonData['org']
if 'query' in jsonData:
self.IP = jsonData['query']
if 'region' in jsonData:
self.Region = jsonData['region']
if 'regionName' in jsonData:
self.RegionName = jsonData['regionName']
if 'status' in jsonData:
self.Status = jsonData['status']
if 'timezone' in jsonData:
self.Timezone = jsonData['timezone']
if 'zip' in jsonData:
self.Zip = jsonData['zip']
if type(self.Latitude) == float and type(self.Longtitude) == float:
self.GoogleMapsLink = 'http://www.google.com/maps/place/{0},{1}/@{0},{1},16z'.format(self.Latitude, self.Longtitude)
def ToDict(self):
#self.__dict__.
return {'Target':self.Query, 'IP':self.IP, 'ASN':self.ASN, 'City':self.City,
'Country':self.Country, 'Country Code':self.CountryCode, 'ISP':self.ISP,
'Latitude':str(self.Latitude), 'Longtitude':str(self.Longtitude),
'Organization':self.Organization, 'Region':self.Region,
'Region Name':self.RegionName, 'Timezone':self.Timezone,
'Zip':self.Zip, 'Google Maps':self.GoogleMapsLink
}
================================================
FILE: files/core/IpGeoLocationLib.py
================================================
#!/usr/bin/env python3
# encoding: UTF-8
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
from core.Utils import Utils
import json, random, os
from core.MyExceptions import *
from core.IpGeoLocation import IpGeoLocation
from time import sleep
from core.FileExporter import FileExporter
from urllib.parse import urlparse
from urllib import request
class IpGeoLocationLib:
"""Retrieve IP Geolocation information from http://ip-api.com"""
def __init__(self, target, logger, noprint=False, nolog=False, verbose=False):
self.URL = 'http://ip-api.com'
self.RequestURL = self.URL + '/json/{}'
self.BOLD = '\033[1m'
self.Proxy = None
self.UserAgentFile = None
self.UserAgents = None
self.Proxies = None
self.TargetsFile = None
self.ProxiesFile = None
self.Targets = None
self.NoPrint = noprint
self.Target = target
self.Logger = logger
self.Utils = Utils(nolog, verbose)
def GetInfo(self, userAgent, targetsFile=None,
userAgentFile=None, proxy=False, proxiesFile=None,
exportToCSVFile=None, exportToXMLFile=None,
exportToTXTFile=None, googleMaps=False):
"""Retrieve information"""
self.UserAgent = userAgent
try:
#check proxies file and load it
if proxiesFile and os.path.isfile(proxiesFile) and os.access(proxiesFile, os.R_OK):
self.ProxiesFile = proxiesFile
self.Logger.Print('Loading Proxies from file {}..'.format(self.ProxiesFile))
self.__loadProxies()
#check user-agent strings file and load it
if userAgentFile and os.path.isfile(userAgentFile) and os.access(userAgentFile, os.R_OK):
self.UserAgentFile = userAgentFile
self.Logger.Print('Loading User-Agent strings from file {}..'.format(self.UserAgentFile))
self.__loadUserAgents()
#check targets file and load it
if targetsFile and os.path.isfile(targetsFile) and os.access(targetsFile, os.R_OK):
self.TargetsFile = targetsFile
self.Logger.Print('Loading targets from file {}..'.format(self.TargetsFile))
self.__loadTargets()
#check if proxy valid and configure connection
if proxy:
self.__configureProxy(proxy)
#retrieve information
results = None
if self.TargetsFile:
results = self.__retrieveGeolocations()
else:
results = self.__retrieveGeolocation(self.Target)
#export information
if exportToCSVFile and not os.path.exists(exportToCSVFile) and os.access(os.path.dirname(exportToCSVFile), os.W_OK):
self.__exportResultsToCSV(results, exportToCSVFile)
if exportToXMLFile and not os.path.exists(exportToXMLFile) and os.access(os.path.dirname(exportToXMLFile), os.W_OK):
self.__exportResultsToXML(results, exportToXMLFile)
if exportToTXTFile and not os.path.exists(exportToTXTFile) and os.access(os.path.dirname(exportToTXTFile), os.W_OK):
self.__exportResultsToTXT(results, exportToTXTFile)
#open location in Google Maps with default browser
if googleMaps and type(results) is IpGeoLocation:
self.Utils.openLocationInGoogleMaps(results)
return True
except UserAgentFileEmptyError:
self.Logger.PrintError("User-Agent strings file is empty!")
except InvalidTargetError:
self.Logger.PrintError('Please provide a valid Domain or IP address!')
except TargetsFileEmptyError:
self.Logger.PrintError('Targets file is empty!')
except UserAgentFileNotSpecifiedError:
self.Logger.PrintError('User-Agent strings file has not been provided!')
except TargetsFileNotSpecifiedError:
self.Logger.PrintError('Targets file has not been provided!')
except ProxyServerNotReachableError:
self.Logger.PrintError('Proxy server not reachable!')
except ProxiesFileNotSpecifiedError:
self.Logger.PrintError('Proxies file has not been provided!')
except ProxiesFileEmptyError:
self.Logger.PrintError('Proxies file is empty!')
except InvalidProxyUrlError:
self.Logger.PrintError('Proxy URL is not valid!')
except Exception as error:
self.Logger.PrintError('An unexpected error occurred {}!'.format(error))
return False
def __checkProxyUrl(self, url):
"""Check if proxy url is valid"""
url_checked = urlparse(url)
if (url_checked.scheme not in ('http', 'https')) | (url_checked.netloc == ''):
return False
return url_checked
def __configureProxy(self, proxy):
#proxy = self.__checkProxyUrl(proxy)
#if not proxy:
# raise MyExceptions.InvalidProxyUrlError()
self.Utils.checkProxyConn(self.URL, proxy.netloc)
self.Proxy = proxy
proxyHandler = request.ProxyHandler({'http':proxy.scheme + '://' + proxy.netloc})
opener = request.build_opener(proxyHandler)
request.install_opener(opener)
self.Logger.Print('Proxy ({}) has been configured.'.format(proxy.scheme + '://' + proxy.netloc))
def __exportResultsToCSV(self, objToExport, csvFile):
"""Export results to csv file"""
fileExporter = FileExporter()
self.Logger.Print('Saving results to {} CSV file.'.format(csvFile))
success = False
if type(objToExport) is IpGeoLocation:
success = fileExporter.ExportToCSV(objToExport, csvFile)
elif type(objToExport) is list:
success = fileExporter.ExportListToCSV(objToExport, csvFile)
if not success:
self.Logger.PrintError('Saving results to {} CSV file failed.'.format(csvFile))
def __exportResultsToXML(self, objToExport, xmlFile):
"""Export results to xml file"""
fileExporter = FileExporter()
self.Logger.Print('Saving results to {} XML file.'.format(xmlFile))
success = False
if type(objToExport) is IpGeoLocation:
success = fileExporter.ExportToXML(objToExport, xmlFile)
elif type(objToExport) is list:
success = fileExporter.ExportListToXML(objToExport, xmlFile)
if not success:
self.Logger.PrintError('Saving results to {} XML file failed.'.format(xmlFile))
def __exportResultsToTXT(self, objToExport, txtFile):
"""Export results to text file"""
fileExporter = FileExporter()
self.Logger.Print('Saving results to {} text file.'.format(txtFile))
success = False
if type(objToExport) is IpGeoLocation:
success = fileExporter.ExportToTXT(objToExport, txtFile)
elif type(objToExport) is list:
success = fileExporter.ExportListToTXT(objToExport, txtFile)
if not success:
self.Logger.PrintError('Saving results to {} text file failed.'.format(txtFile))
def __retrieveGeolocations (self):
"""Retrieve IP Geolocation for each target in the list"""
IpGeoLocObjs = []
for target in self.Targets:
IpGeoLocObjs.append(self.__retrieveGeolocation(target))
if len(self.Targets)>=150:
sleep(.500) #1/2 sec - ip-api will automatically ban any IP address doing over 150 requests per minute
return IpGeoLocObjs
def __retrieveGeolocation(self, target):
"""Retrieve IP Geolocation for single target"""
if not target:
query = 'My IP'
target=''
elif self.Utils.isValidIPAddress(target):
query = target
else:
ip = self.Utils.hostnameToIP(target)#domain?
if not ip:
raise InvalidTargetError()
query = target
target = ip
#pick random user-agent string
if self.UserAgentFile:
self.__pickRandomUserAgent()
#pick random proxy connection
if self.ProxiesFile:
self.__pickRandomProxy()
self.Logger.Print('Retrieving {} Geolocation..'.format(query))
req = request.Request(self.RequestURL.format(target), data=None, headers={
'User-Agent':self.UserAgent
})
response = request.urlopen(req)
if response.code == 200:
self.Logger.Print('User-Agent used: {}'.format(self.UserAgent))
encoding = response.headers.get_content_charset()
ipGeoLocObj = IpGeoLocation(query, json.loads(response.read().decode(encoding)))
self.Logger.Print('Geolocation information has been retrieved for {}({}).'.format(query, ipGeoLocObj.IP))
if not self.NoPrint:
self.Logger.PrintIPGeoLocation(ipGeoLocObj)
return ipGeoLocObj
return False
def __loadProxies(self):
"""Load proxies from file"""
if not self.ProxiesFile:
raise ProxiesFileNotSpecifiedError()
self.Proxies = [line.strip() for line in open(self.ProxiesFile, 'r') if line.strip()]
self.Logger.Print('{} Proxies loaded.'.format(len(self.Proxies)))
if len(self.Proxies) == 0:
raise ProxiesFileEmptyError()
def __loadUserAgents(self):
"""Load user-agent strings from file"""
if not self.UserAgentFile:
raise UserAgentFileNotSpecifiedError()
self.UserAgents = [line.strip() for line in open(self.UserAgentFile, 'r') if line.strip()]
self.Logger.Print('{} User-Agent strings loaded.'.format(len(self.UserAgents)))
if len(self.UserAgents) == 0:
raise UserAgentFileEmptyError()
def __loadTargets(self):
"""Load targets from file"""
if not self.TargetsFile:
raise TargetsFileNotSpecifiedError()
self.Targets = [line.strip() for line in open(self.TargetsFile, 'r') if line.strip()]
self.Logger.Print('{} Targets loaded.'.format(len(self.Targets)))
if len(self.Targets) == 0:
raise TargetsFileEmptyError()
def __pickRandomProxy(self):
"""Pick randomly a proxy from the list"""
if not self.Proxies or len(self.Proxies) == 0:
raise ProxiesFileEmptyError()
self.__configureProxy(random.choice(self.Proxies))
def __pickRandomUserAgent(self):
"""Pick randomly a user-agent string from the list"""
if not self.UserAgents or len(self.UserAgents) == 0:
raise UserAgentFileEmptyError()
self.UserAgent = random.choice(self.UserAgents)
================================================
FILE: files/core/Logger.py
================================================
#!/usr/bin/env python3
# encoding: UTF-8
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
from datetime import datetime
import os
from termcolor import colored
from sys import platform as _platform
if _platform == 'win32':
import colorama
colorama.init()
def Red(value):
return colored(value, 'red', attrs=['bold'])
def Green(value):
return colored(value, 'green', attrs=['bold'])
class Logger:
def __init__(self, nolog=False, verbose=False):
self.NoLog = nolog
self.Verbose = verbose
def WriteLog(self, messagetype, message):
filename = '{}.log'.format(datetime.strftime(datetime.now(), "%Y%m%d"))
path = os.path.join('.', 'logs', filename)
with open(path, 'a') as logFile:
logFile.write('[{}] {} - {}\n'.format(messagetype, datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S"), message))
def PrintError(self, message):
"""Print/Log error message"""
if not self.NoLog:
self.WriteLog('ERROR', message)
print('[{}] {}'.format(Red('ERROR'), message))
def PrintResult(self, title, value):
"""print result to terminal"""
print('{}: {}'.format(title, Green(value)))
def Print(self, message):
"""print/log info message"""
if not self.NoLog:
self.WriteLog('INFO', message)
if self.Verbose:
print('[{}] {}'.format(Green('**'), message))
def PrintIPGeoLocation(self, ipGeoLocation):
"""print IP Geolocation information to terminal"""
self.PrintResult('\nTarget', ipGeoLocation.Query)
self.PrintResult('IP', ipGeoLocation.IP)
self.PrintResult('ASN', ipGeoLocation.ASN)
self.PrintResult('City', ipGeoLocation.City)
self.PrintResult('Country', ipGeoLocation.Country)
self.PrintResult('Country Code', ipGeoLocation.CountryCode)
self.PrintResult('ISP', ipGeoLocation.ISP)
self.PrintResult('Latitude', str(ipGeoLocation.Latitude))
self.PrintResult('Longtitude', str(ipGeoLocation.Longtitude))
self.PrintResult('Organization', ipGeoLocation.Organization)
self.PrintResult('Region Code', ipGeoLocation.Region)
self.PrintResult('Region Name', ipGeoLocation.RegionName)
self.PrintResult('Timezone', ipGeoLocation.Timezone)
self.PrintResult('Zip Code', ipGeoLocation.Zip)
self.PrintResult('Google Maps', ipGeoLocation.GoogleMapsLink)
print()
#.encode('cp737', errors='replace').decode('cp737')
================================================
FILE: files/core/Menu.py
================================================
#!/usr/bin/env python3
# encoding: UTF-8
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
__twitter__ = '@maldevel'
__version__ = '2.0.4'
__year__ = '2015-2016'
from argparse import RawTextHelpFormatter
import argparse, os
from urllib.parse import urlparse
from core.Logger import Red
banner = """
{0}
{1} Retrieve IP Geolocation information from ip-api.com
{1} Copyright (c) {2} {3} ({4})
{1} ip-api.com service will automatically ban any IP addresses doing over 150 requests per minute.
""".format(Red('IPGeolocation ' + __version__), Red('--['), __year__, __author__, __twitter__)
def checkFileRead(filename):
"""Check if file exists and we have access to read it"""
if os.path.isfile(filename) and os.access(filename, os.R_OK):
return filename
else:
raise argparse.ArgumentTypeError("Invalid {} file (File does not exist, insufficient permissions or it's not a file).".format(filename))
def checkFileWrite(filename):
"""Check if we can write to file"""
if os.path.isfile(filename):
raise argparse.ArgumentTypeError("File {} already exists.".format(filename))
elif os.path.isdir(filename):
raise argparse.ArgumentTypeError("Folder provided. Please provide a file.")
elif os.access(os.path.dirname(filename), os.W_OK):
return filename
else:
raise argparse.ArgumentTypeError("Unable to write to {} file (Insufficient permissions).".format(filename))
def checkProxyUrl(url):
"""Check if proxy url is valid"""
url_checked = urlparse(url)
if (url_checked.scheme not in ('http', 'https')) | (url_checked.netloc == ''):
raise argparse.ArgumentTypeError('Invalid {} Proxy URL (example: http://127.0.0.1:8080).'.format(url))
return url_checked
parser = argparse.ArgumentParser(description=banner, formatter_class=RawTextHelpFormatter)
#pick target/s
parser.add_argument('-m', '--my-ip',
dest='myip',
action='store_true',
help='Get Geolocation info for my IP address.')
parser.add_argument('-t', '--target',
help='IP Address or Domain to be analyzed.')
parser.add_argument('-T', '--tlist',
metavar='file',
type=checkFileRead,
help='A list of IPs/Domains targets, each target in new line.')
#user-agent configuration
parser.add_argument('-u', '--user-agent',
metavar='User-Agent',
dest='uagent',
default='IP2GeoLocation {}'.format(__version__),
help='Set the User-Agent request header (default: IP2GeoLocation {}).'.format(__version__))
parser.add_argument('-U', '--ulist',
metavar='file',
type=checkFileRead,
help='A list of User-Agent strings, each string in new line.')
#misc options
parser.add_argument('-g',
action='store_true',
help='Open IP location in Google maps with default browser.')
parser.add_argument('--noprint',
action='store_true',
help='IPGeolocation will print IP Geolocation info to terminal. It is possible to tell IPGeolocation not to print results to terminal with this option.')
parser.add_argument('-v', '--verbose',
action='store_true',
help='Enable verbose output.')
parser.add_argument('--nolog',
action='store_true',
help='IPGeolocation will save a .log file. It is possible to tell IPGeolocation not to save those log files with this option.')
#anonymity options
parser.add_argument('-x', '--proxy',
type=checkProxyUrl,
help='Setup proxy server (example: http://127.0.0.1:8080)')
parser.add_argument('-X', '--xlist',
metavar='file',
type=checkFileRead,
help='A list of proxies, each proxy url in new line.')
#export options
parser.add_argument('-e', '--txt',
metavar='file',
type=checkFileWrite,
help='Export results.')
parser.add_argument('-ec', '--csv',
metavar='file',
type=checkFileWrite,
help='Export results in CSV format.')
parser.add_argument('-ex', '--xml',
metavar='file',
type=checkFileWrite,
help='Export results in XML format.')
args = parser.parse_args()
================================================
FILE: files/core/MyExceptions.py
================================================
#!/usr/bin/env python3
# encoding: UTF-8
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
class UserAgentFileEmptyError(Exception):
pass
class InvalidTargetError(Exception):
pass
class TargetsFileEmptyError(Exception):
pass
class TargetsFileNotSpecifiedError(Exception):
pass
class UserAgentFileNotSpecifiedError(Exception):
pass
class ProxyServerNotReachableError(Exception):
pass
class ProxiesFileNotSpecifiedError(Exception):
pass
class ProxiesFileEmptyError(Exception):
pass
class InvalidProxyUrlError(Exception):
pass
================================================
FILE: files/core/Utils.py
================================================
#!/usr/bin/env python3
# encoding: UTF-8
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
import webbrowser, ipaddress, socket
from sys import platform as _platform
from subprocess import call
from urllib import request
from core import MyExceptions
from core.Logger import Logger
class Utils:
def __init__(self, nolog=False, verbose=False):
self.Logger = Logger(nolog, verbose)
def openLocationInGoogleMaps(self, ipGeolObj):
"""Open IP Geolocation in Google Maps with default browser"""
if type(ipGeolObj.Longtitude) == float and type(ipGeolObj.Latitude) == float:
self.Logger.Print('Opening Geolocation in browser..')
if _platform == 'cygwin':
call(['cygstart', ipGeolObj.GoogleMapsLink])
elif _platform == 'win32' or _platform == 'linux' or _platform == 'linux2':
webbrowser.open(ipGeolObj.GoogleMapsLink)
else:
self.Logger.PrintError('-g option is not available on your platform.')
def hostnameToIP(self, hostname):
"""Resolve hostname to IP address"""
try:
return socket.gethostbyname(hostname)
except:
return False
def isValidIPAddress(self, ip):
"""Check if ip is a valid IPv4/IPv6 address"""
try:
ipaddress.ip_address(ip)
return True
except:
return False
def checkProxyConn(self, url, proxy):
"""check proxy connectivity"""
check = True
self.Logger.Print('Testing proxy {} connectivity..'.format(proxy))
try:
req = request.Request(url)
req.set_proxy(proxy, 'http')
request.urlopen(req)
except:
check = False
if check == True:
self.Logger.Print('Proxy server is reachable.')
else:
raise MyExceptions.ProxyServerNotReachableError()
================================================
FILE: files/core/__init__.py
================================================
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
================================================
FILE: files/examples/input.txt
================================================
+856 20 99 453 217
+59172768361
+32474123456
+1 (541) 754-3010
+86 591 2284 8571
+7 496 4819375
39172768361
================================================
FILE: files/ipgeolocation.py
================================================
#!/usr/bin/env python3
# encoding: UTF-8
"""
This file is part of IPGeoLocation tool.
Copyright (C) 2015-2016 @maldevel
https://github.com/maldevel/IPGeoLocation
IPGeoLocation - Retrieve IP Geolocation information
Powered by http://ip-api.com
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 .
For more see the file 'LICENSE' for copying permission.
"""
__author__ = 'maldevel'
import sys, os
from core.IpGeoLocationLib import IpGeoLocationLib
from core.Logger import Logger
from core.Menu import parser,args,banner
def main():
# no args provided
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
logsDir = os.path.join(os.getcwd(), 'logs')
#resultsDir = os.path.join(os.getcwd(), 'results')
if not os.path.exists(logsDir):
os.mkdir(logsDir)
#if not os.path.exists(resultsDir):
# os.mkdir(resultsDir)
logger = Logger(args.nolog, args.verbose)
#single target or multiple targets
if(args.target and args.tlist):
logger.PrintError("You can request Geolocation information either for a single target(-t) or a list of targets(-T). Not both!", args.nolog)
sys.exit(2)
#my ip address or single target
if(args.target and args.myip):
logger.PrintError("You can request Geolocation information either for a single target(-t) or your own IP address. Not both!", args.nolog)
sys.exit(3)
#multiple targets or my ip address
if(args.tlist and args.myip):
logger.PrintError("You can request Geolocation information either for a list of targets(-T) or your own IP address. Not both!", args.nolog)
sys.exit(4)
#single target and google maps only allowed
if(args.tlist and args.g):
logger.PrintError("Google maps location is working only with single targets.", args.nolog)
sys.exit(5)
#specify user-agent or random
if(args.uagent and args.ulist):
logger.PrintError("You can either specify a user-agent string or let IPGeolocation pick random user-agent strings for you from a file.", args.nolog)
sys.exit(6)
#specify proxy or random
if(args.proxy and args.xlist):
logger.PrintError("You can either specify a proxy or let IPGeolocation pick random proxy connections for you from a file.", args.nolog)
sys.exit(7)
#init lib
ipGeoLocRequest = IpGeoLocationLib(args.target, logger, args.noprint)
print(banner)
#retrieve information
if not ipGeoLocRequest.GetInfo(args.uagent, args.tlist,
args.ulist, args.proxy, args.xlist,
args.csv, args.xml, args.txt, args.g):
logger.PrintError("Retrieving IP Geolocation information failed.")
sys.exit(8)
if __name__ == '__main__':
main()
================================================
FILE: files/osint/disposable_num_providers.json
================================================
[
{
"site": "hs3x.com",
"request": "site:\"hs3x.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "receive-sms-now.com",
"request": "site:\"receive-sms-now.com\" intext:\"$n\"",
"stop": 1
},
{
"site": "smslisten.com",
"request": "site:\"smslisten.com\" intext:\"$n\"",
"stop": 1
},
{
"site": "smsnumbersonline.com",
"request": "site:\"smsnumbersonline.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "freesmscode.com",
"request": "site:\"freesmscode.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "catchsms.com",
"request": "site:\"catchsms.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "smstibo.com",
"request": "site:\"smstibo.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "smsreceiving.com",
"request": "site:\"smsreceiving.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "getfreesmsnumber.com",
"request": "site:\"getfreesmsnumber.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "sellaite.com",
"request": "site:\"sellaite.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "receive-sms-online.info",
"request": "site:\"receive-sms-online.info\" intext:\"+$n\"",
"stop": 1
},
{
"site": "receivesmsonline.com",
"request": "site:\"receivesmsonline.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "receive-a-sms.com",
"request": "site:\"receive-a-sms.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "sms-receive.net",
"request": "site:\"sms-receive.net\" intext:\"+$n\"",
"stop": 1
},
{
"site": "receivefreesms.com",
"request": "site:\"receivefreesms.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "receive-sms.com",
"request": "site:\"receive-sms.com\" intext:\"+$n\"",
"stop": 1
},
{
"site": "receivetxt.com",
"request": "site:\"receivetxt.com\" $n",
"stop": 1
},
{
"site": "freephonenum.com",
"request": "site:\"freephonenum.com\" intext:\"$n\"",
"stop": 1
},
{
"site": "freesmsverification.com",
"request": "site:\"freesmsverification.com\" $n",
"stop": 1
},
{
"site": "receive-sms-online.com",
"request": "site:\"receive-sms-online.com\" intext:\"$n\"",
"stop": 1
},
{
"site": "smslive.co",
"request": "site:\"smslive.co\" intext:\"$n\"",
"stop": 1
}
]
================================================
FILE: files/osint/individuals.json
================================================
[
{
"site": "numinfo.net",
"request": "site:\"numinfo.net\" intext:\"$n\" | intext:\"$i\"",
"dialCode": null,
"stop": 2
},
{
"site": "sync.me",
"request": "site:\"sync.me\" intext:\"$n\" | intext:\"$i\"",
"dialCode": null,
"stop": 1
},
{
"site": "whocallsyou.de",
"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
}
]
================================================
FILE: files/osint/reputation.json
================================================
[
{
"title": "reputation report on whosenumber.info",
"request": "site:\"whosenumber.info\" intext:\"$n\" intitle:\"who called\"",
"stop": 1
},
{
"title": "phone fraud footprints",
"request": "intitle:\"Phone Fraud\" intext:\"$n\" | intext:\"$i\"",
"stop": 5
}
]
================================================
FILE: files/osint/social_medias.json
================================================
[
{
"site": "facebook.com",
"request": "site:\"facebook.com\" intext:\"$i\" | intext:\"$n\"",
"stop": 5
},
{
"site": "twitter.com",
"request": "site:\"twitter.com\" intext:\"$i\" | intext:\"$n\"",
"stop": 5
},
{
"site": "linkedin.com",
"request": "site:\"linkedin.com\" intext:\"$i\" | intext:\"$n\"",
"stop": 5
},
{
"site": "instagram.com",
"request": "site:\"instagram.com\" intext:\"$i\" | intext:\"$n\"",
"stop": 5
}
]
================================================
FILE: files/phoneinfoga.py
================================================
#!/usr/bin/env python3
__version__ = 'v2.3.8-BETA'
try:
import sys
from colorama import Fore, Style
import atexit
import argparse
import random
except KeyboardInterrupt:
print('[!] Exiting.')
sys.exit()
except:
print('\033[91m[!] Missing requirements.\033[92m')
sys.exit()
def banner():
print("\033[92m ___ _ _____ __ ")
print(" / _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _ ")
print(" / /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |")
print(" / ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |")
print(" \/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|")
print(" |___/ ")
print(" PhoneInfoga version {}".format(__version__))
print(" Coded by Charon IV")
print(" Modified by @AbirHasan2005")
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__),
usage='%(prog)s -n [options]')
parser.add_argument('-n', '--number', metavar='number', type=str,
help='The phone number to scan (E164 or international format)')
parser.add_argument('-i', '--input', metavar="input_file", type=argparse.FileType('r'),
help='Phone number list to scan (one per line)')
parser.add_argument('-o', '--output', metavar="output_file", type=argparse.FileType('w'),
help='Output to save scan results')
parser.add_argument('-s', '--scanner', metavar="scanner", default="all", type=str,
help='The scanner to use')
parser.add_argument('--osint', action='store_true',
help='Use OSINT reconnaissance')
parser.add_argument('-u', '--update', action='store_true',
help='Update the project(Not Working)')
args = parser.parse_args()
def resetColors():
if not args.output:
print(Style.RESET_ALL)
# Reset text color at exit
atexit.register(resetColors)
# If any param is passed, execute help command
if not len(sys.argv) > 1:
parser.print_help()
sys.exit()
try:
import time
import hashlib
import json
import re
import requests
import urllib3
from bs4 import BeautifulSoup
import html5lib
import phonenumbers
from phonenumbers import carrier
from phonenumbers import geocoder
from phonenumbers import timezone
except KeyboardInterrupt:
print('\033[91m[!] Exiting.')
sys.exit()
except:
print('\033[91m[!] Missing requirements.\033[92m')
sys.exit()
requests.packages.urllib3.disable_warnings()
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'HIGH:!DH:!aNULL'
try:
requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += 'HIGH:!DH:!aNULL'
except AttributeError:
# no pyopenssl support used / needed / available
pass
if args.update:
def download_file(url, target_path):
response = requests.get(url, stream=True)
handle = open(target_path, "wb")
for chunk in response.iter_content(chunk_size=512):
if chunk: # filter out keep-alive new chunks
handle.write(chunk)
print('Updating PhoneInfoga...')
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']
print('Last version: {}'.format(new_version))
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)
output_directory = 'osint/{}'.format(file)
download_file(url, output_directory)
print('[*] Updating python script')
url = 'https://raw.githubusercontent.com/sundowndev/PhoneInfoga/master/phoneinfoga.py'
output_directory = 'phoneinfoga.py'
download_file(url, output_directory)
except:
print('Update failed. Try using git pull.')
sys.exit()
print('The tool was successfully updated.')
sys.exit()
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 (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")
number = '' # Full number format
localNumber = '' # Local number format
internationalNumber = '' # International numberformat
numberCountryCode = '' # Dial code; e.g:"+33"
numberCountry = '' # Country; e.g:France
googleAbuseToken = ''
customFormatting = ''
def search(req, stop):
global googleAbuseToken
global uagent
chosenUserAgent = random.choice(uagent)
s = requests.Session()
headers = {
'User-Agent': chosenUserAgent,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-us,en;q=0.5',
'Accept-Encoding': 'gzip,deflate',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Keep-Alive': '115',
'Connection': 'keep-alive',
'Cookie': 'Cookie: CGIC=Ij90ZXh0L2h0bWwsYXBwbGljYXRpb24veGh0bWwreG1sLGFwcGxpY2F0aW9uL3htbDtxPTAuOSwqLyo7cT0wLjg; CONSENT=YES+RE.fr+20150809-08-0; 1P_JAR=2018-11-28-14; NID=148=aSdSHJz71rufCokaUC93nH3H7lOb8E7BNezDWV-PyyiHTXqWK5Y5hsvj7IAzhZAK04-QNTXjYoLXVu_eiAJkiE46DlNn6JjjgCtY-7Fr0I4JaH-PZRb7WFgSTjiFqh0fw2cCWyN69DeP92dzMd572tQW2Z1gPwno3xuPrYC1T64wOud1DjZDhVAZkpk6UkBrU0PBcnLWL7YdL6IbEaCQlAI9BwaxoH_eywPVyS9V; SID=uAYeu3gT23GCz-ktdGInQuOSf-5SSzl3Plw11-CwsEYY0mqJLSiv7tFKeRpB_5iz8SH5lg.; HSID=AZmH_ctAfs0XbWOCJ; SSID=A0PcRJSylWIxJYTq_; APISID=HHB2bKfJ-2ZUL5-R/Ac0GK3qtM8EHkloNw; SAPISID=wQoxetHBpyo4pJKE/A2P6DUM9zGnStpIVt; SIDCC=ABtHo-EhFAa2AJrJIUgRGtRooWyVK0bAwiQ4UgDmKamfe88xOYBXM47FoL5oZaTxR3H-eOp7-rE; OTZ=4671861_52_52_123900_48_436380; OGPC=873035776-8:; OGP=-873035776:;'
}
try:
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')
token = input('\nGOOGLE_ABUSE_EXEMPTION=')
googleAbuseToken = '&google_abuse=' + token
r = s.get(URL + googleAbuseToken, headers=headers)
soup = BeautifulSoup(r.content, 'html.parser')
results = soup.find("div", id="search").find_all("div", class_="g")
links = []
counter = 0
for result in results:
counter += 1
if int(counter) > int(stop):
break
url = result.find("a").get('href')
url = re.sub(r'(?:\/url\?q\=)', '', url)
url = re.sub(r'(?:\/url\?url\=)', '', url)
url = re.sub(r'(?:\&sa\=)(?:.*)', '', url)
url = re.sub(r'(?:\&rct\=)(?:.*)', '', url)
if re.match(r"^(?:\/search\?q\=)", url) is not None:
url = 'https://google.com' + url
links.append(url)
return links
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
global internationalNumber
global numberCountryCode
global numberCountry
print(code_info + 'Running local scan ...')
FormattedPhoneNumber = "+" + formatNumber(InputNumber)
try:
PhoneNumberObject = phonenumbers.parse(FormattedPhoneNumber, None)
except:
return False
else:
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]
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: {}'.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: {}'.format(timezoneResult))
if phonenumbers.is_possible_number(PhoneNumberObject):
print(code_info + 'The number is valid and possible.')
else:
print(code_warning + 'The number is valid but might not be possible.')
def numverifyScan():
global number
if not args.scanner == 'numverify' and not args.scanner == 'all':
return -1
print(code_info + 'Running Numverify.com scan ...')
requestSecret = ''
resp = requests.get('https://numverify.com/')
soup = BeautifulSoup(resp.text, "html5lib")
for tag in soup.find_all("input", type="hidden"):
if tag['name'] == "scl_request_secret":
requestSecret = tag['value']
break
apiKey = hashlib.md5((number + requestSecret).encode('utf-8')).hexdigest()
headers = {
'host': "numverify.com",
'connection': "keep-alive",
'content-length': "49",
'accept': "application/json",
'origin': "https://numverify.com",
'x-requested-with': "XMLHttpRequest",
'user-agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
'referer': "https://numverify.com/",
'accept-encoding': "gzip, deflate, br",
'accept-language': "en-US,en;q=0.9,fr;q=0.8,la;q=0.7,es;q=0.6,zh-CN;q=0.5,zh;q=0.4",
'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)
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)."))
return -1
data = json.loads(response.content)
if data["valid"] == False:
print((code_error + "Error: Please specify a valid phone number. Example: +6464806649"))
sys.exit()
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 + "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 landline, but it can still be a fixed VoIP number."))
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
if not args.scanner == 'ovh' and not args.scanner == 'all':
return -1
print(code_info + 'Running OVH scan...')
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)
data = json.loads(response.content)
if isinstance(data, list):
askedNumber = "0" + localNumber.replace(localNumber[-4:], 'xxxx')
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 + "City: {}".format(voip_number['city'])))
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
global numberCountryCode
global customFormatting
dorks = json.load(open('osint/individuals.json'))
for dork in dorks:
if dork['dialCode'] is None or dork['dialCode'] == numberCountryCode:
if customFormatting:
dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting)
else:
dorkRequest = replaceVariables(dork['request'])
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
global customFormatting
dorks = json.load(open('osint/reputation.json'))
for dork in dorks:
if customFormatting:
dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting)
else:
dorkRequest = replaceVariables(dork['request'])
print((code_info + "Searching for {}...".format(dork['title'])))
for result in search(dorkRequest, stop=dork['stop']):
if result:
print((code_result + "URL: " + result))
def osintSocialMediaScan():
global number
global internationalNumber
global customFormatting
dorks = json.load(open('osint/social_medias.json'))
for dork in dorks:
if customFormatting:
dorkRequest = replaceVariables(dork['request']) + ' | intext:"{}"'.format(customFormatting)
else:
dorkRequest = replaceVariables(dork['request'])
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
dorks = json.load(open('osint/disposable_num_providers.json'))
for dork in dorks:
dorkRequest = replaceVariables(dork['request'])
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
global internationalNumber
global numberCountryCode
global numberCountry
global customFormatting
if not args.osint:
return -1
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/{}".format(internationalNumber.replace('+', '').replace(' ', '-')))
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: ')
print((code_info + '---- Web pages footprints ----'))
print((code_info + "Searching for footprints on web pages ... (limit=5)"))
if customFormatting:
req = '{} | intext:"{}" | intext:"{}" | intext:"{}"'.format(number,number,internationalNumber,customFormatting)
else:
req = '{} | intext:"{}" | intext:"{}"'.format(number,number,internationalNumber)
for result in search(req, stop=5):
if result:
print((code_result + "Result found: " + result))
# Documents
print((code_info + "Searching for documents ... (limit=10)"))
if 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:"{}" | 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))
print((code_info + '---- Reputation footprints ----'))
osintReputationScan()
print((code_info + "Generating URL on scamcallfighters.com ..."))
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) ")
if tmpNumAsk.lower() != 'n' and tmpNumAsk.lower() != 'no':
print((code_info + '---- Temporary number providers footprints ----'))
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"))
askForExit()
osintDisposableNumScan()
print((code_info + '---- Social media footprints ----'))
osintSocialMediaScan()
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={}'.format(internationalNumber.replace(' ', '')))
osintIndividualScan()
def askForExit():
if not args.output:
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!")
sys.exit()
def scanNumber(InputNumber):
print(code_title + "[!] ---- Fetching informations for {} ---- [!]".format(formatNumber(InputNumber)))
localScan(InputNumber)
global number
global localNumber
global internationalNumber
global numberCountryCode
global numberCountry
if not number:
print((code_error + "\033[91mError: number {} is not valid.\n\033[92mFor help join Telegram Group:\033[96m http://t.me/linux_repo\n\n\033[91mSkipping ...\033[92m".format(formatNumber(InputNumber))))
sys.exit()
numverifyScan()
ovhScan()
osintScan()
print(code_info + "Scan finished!")
print('\n' + Style.RESET_ALL)
try:
if 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).\033[92m')
sys.exit()
sys.stdout = args.output
banner()
else:
code_info = Fore.RESET + Style.BRIGHT + '[*] '
code_warning = Fore.YELLOW + Style.BRIGHT + '(!) '
code_result = Fore.GREEN + Style.BRIGHT + '[+] '
code_error = Fore.RED + Style.BRIGHT + '[!] '
code_title = Fore.YELLOW + Style.BRIGHT
# Verify scanner option
if not args.scanner in scanners:
print((code_error + "Error: scanner doesn't exists."))
sys.exit()
if args.number:
scanNumber(args.number)
elif args.input:
for line in args.input.readlines():
scanNumber(line)
if args.output:
args.output.close()
except KeyboardInterrupt:
print(("\n" + code_error + "Scan interrupted. Good bye!"))
sys.exit()
================================================
FILE: files/tracker.py
================================================
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import requests
import json
import time
import urllib
import os
class color:
PURPLE = '\033[95m'
CYAN = '\033[96m'
DARKCYAN = '\033[36m'
BLUE = '\033[94m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
END = '\033[0m'
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
class config:
key = "2dfa8e4851add96619e675427cdb72f1" #go to https://numverify.com/ and sign up if if get error. This API token is mine so after 100 use of this token this tool will not work. So you have to wait for next update or ask at my Telegram Group: http://t.me/linux_repo
def banner():
os.system('clear')
print (color.BLUE + """
████████╗██████╗ █████╗ ██████╗██╗ ██╗███████╗██████╗
╚══██╔══╝██╔══██╗██╔══██╗██╔════╝██║ ██╔╝██╔════╝██╔══██╗
██║ ██████╔╝███████║██║ █████╔╝ █████╗ ██████╔╝
██║ ██╔══██╗██╔══██║██║ ██╔═██╗ ██╔══╝ ██╔══██╗
██║ ██║ ██║██║ ██║╚██████╗██║ ██╗███████╗██║ ██║
╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
Version: 1.6-DEV by @AbirHasan2005
""" + color.END)
def main():
banner()
if len(sys.argv) == 2:
number = sys.argv[1]
api = "http://apilayer.net/api/validate?access_key=" + config.key + "&number=" + number + "&country_code=&format=1"
output = requests.get(api)
content = output.text
obj = json.loads(content)
country_code = obj['country_code']
country_name = obj['country_name']
location = obj['location']
carrier = obj['carrier']
line_type = obj['line_type']
print (color.BLUE + "[+] " + color.END + "Phone number information gathering")
print ("--------------------------------------")
time.sleep(0.2)
if country_code == "":
print (" - Getting Country [ " + color.RED + "FAILED " + color.END + "] ")
else:
print (" - Getting Country [ " + color.GREEN + "OK " + color.END + "]")
time.sleep(0.2)
if country_name == "":
print (" - Getting Country Name [ " + color.RED + "FAILED " + color.END + "]")
else:
print (" - Getting Country Name [ " + color.GREEN + "OK " + color.END + "]")
time.sleep(0.2)
if location == "":
print (" - Getting Location [ " + color.RED + "FAILED " + color.END + "]")
else:
print (" - Getting Location [ " + color.GREEN + "OK " + color.END + "]")
time.sleep(0.2)
if carrier == "":
print (" - Getting Carrier [ " + color.RED + "FAILED " + color.END + "]")
else:
print (" - Getting Carrier [ " + color.GREEN + "OK " + color.END + "]")
time.sleep(0.2)
if line_type == None:
print (" - Getting Device [ " + color.RED + "FAILED " + color.END + "]")
else:
print (" - Getting Device [ " + color.GREEN + "OK " + color.END + "]")
print ("")
print (color.BLUE + "[+] " + color.END + "Information Output")
print ("--------------------------------------")
print (" - Phone number: " +str(number))
print (" - Country: " +str(country_code))
print (" - Country Name: " +str(country_name))
print (" - Location: " +str(location))
print (" - Carrier: " +str(carrier))
print (" - Device: " +str(line_type))
else:
print ("[TRACKER] Usage:")
print ("./%s " % (sys.argv[0]))
print ("./%s +13213707446" % (sys.argv[0]))
main()
================================================
FILE: requirements.txt
================================================
termcolor
colorama
requests
bs4
html5lib
phonenumbers
argparse
urllib3
================================================
FILE: run.sh
================================================
#!/bin/bash
# This script was coded by @AbirHasan2005
# Please give me credits if you us any codes from here.
# Telegram Group: http://t.me/linux_repo
# GitHub: https://github.com/AbirHasan2005
# If you find any problem in this script than please report to my Telegram Group.
clear
banner() {
printf "\n\e[1;92m"
printf "\n\e[1;92m░█▀█░█▀█░█▀▄░█▀▀░█▀▀░█▀█░█▀█"
printf "\n\e[1;92m░█░█░█▀▀░█▀▄░█▀▀░█░░░█░█░█░█"
printf "\n\e[1;92m░▀▀▀░▀░░░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀░▀ \e[1;95mv1.8-BETA\n"
printf "\n\e[1;92m Coded by \e[1;94m@AbirHasan2005\n\n\e[1;92m"
}
dependencies() {
command -v git > /dev/null 2>&1 || { echo >&2 "Package GIT is not installed ... Aborting ..."; exit 1; }
command -v python3 > /dev/null 2>&1 || { echo >&2 "Package Python3 is not installed ... Aborting ..."; exit 1; }
}
script() {
printf "\n\e[1;92m[\e[1;93m01\e[1;92m] Find information via phone number\n[\e[1;93m02\e[1;92m] Find location via IP Address/Website Link\n[\e[1;93m03\e[1;92m] Phone Number Tracker (Recommanded to find IP Address)\n[\e[1;93m04\e[1;92m] Exit"
read -p $'\n\n\e[1;92m[\e[0m\e[1;77m*\e[0m\e[1;92m]\e[1;93m Choose an option: \e[1;93m' option
if [[ $option == 1 || $option == 01 ]]; then
printf "\n\nEnter your phone number in international format ...\n"
read -p $'\n\n\e[1;92m[\e[0m\e[1;77m*\e[0m\e[1;92m]\e[1;93m Enter Number: \e[1;92m' optiona
printf "\n\e[1;92m This process will take a few moments ...\n\n\e[1;92m"
sleep 2.9
python3 files/phoneinfoga.py -n $optiona
printf "\n\n\e[1;92mNOTE: If you get any problem while using this tool than please report to\nTelegram Group: \e[1;96mhttp://t.me/linux_repo\e[1;92m\n"
script
elif [[ $option == 2 || $option == 02 ]]; then
printf "\n\n\e[1;92mEnter IP Address or website link to find location ...\nExample: 198.235.36.25\n google.com \e[1;91m[Don't enter \e[1;96mhttp://\e[1;91m]"
read -p $'\n\n\e[1;92m[\e[0m\e[1;77m*\e[0m\e[1;92m]\e[1;93m Enter: \e[1;92m' optionb
printf "\n\e[1;92m Please wait ...\n\n\e[1;92m"
sleep 3
python3 files/ipgeolocation.py -t $optionb
printf "\n\n\e[1;92mNOTE: If you get any problem while using this tool than please report to\nTelegram Group: \e[1;96mhttp://t.me/linux_repo\e[1;92m\n"
script
elif [[ $option == 3 || $option == 03 ]]; then
printf "\n\nEnter your phone number in international format ...\n"
read -p $'\n\n\e[1;92m[\e[0m\e[1;77m*\e[0m\e[1;92m]\e[1;93m Enter Number: \e[1;92m' optionc
python3 files/tracker.py $optionc
printf "\n\n\e[1;92mNOTE: If you get any problem while using this tool than please report to\nTelegram Group: \e[1;96mhttp://t.me/linux_repo\e[1;92m\n"
script
elif [[ $option == 4 || $option == 04 ]]; then
printf "\n\n\e[1;92m Join Telegram Group for feedback:\e[1;96m http://t.me/linux_repo\e[1;92m\n"
exit 1
else
printf "\n\n\e[1;91mCommand not found!\e[1;92m\n"
printf "\n\n\e[1;92mNOTE: If you get any problem while using this tool than please report to\nTelegram Group: \e[1;96mhttp://t.me/linux_repo\e[1;92m\n"
fi
}
banner
dependencies
script
================================================
FILE: update.sh
================================================
#!/bin/bash
# Update Script for OPRecon v2.1-Stable
# Script created by @AbirHasan2005
dependencies() {
command -v git > /dev/null 2>&1 || { echo >&2 "Package GIT is not installed ... Unable to update ..."; exit 1; }
}
script() {
clear
printf "\n \e[1;92mUpdating \e[1;94mOPRecon\e[1;92m ...\n\n"
sleep 1.5
cd ..
rm -rf OPRecon
git clone https://github.com/AbirHasan2005/OPRecon
cd OPRecon
chmod +x run.sh
printf "\n\e[1;92mRestarting ...\n\e[0m"
bash run.sh
cd ..
}
dependencies
script