From 0619eda209a4897381c551e8a4cfad58486d7c0b Mon Sep 17 00:00:00 2001 From: maldevel Date: Sun, 20 Dec 2015 13:57:17 +0200 Subject: [PATCH] 1.6 release 1.6 release --- README.md | 41 ++--- geolocation/IpGeoLocationLib.py | 268 +++++++++++++++++++++++--------- ip2geolocation.py | 204 ++++++++++++++---------- utilities/MyExceptions.py | 39 +++++ 4 files changed, 379 insertions(+), 173 deletions(-) create mode 100644 utilities/MyExceptions.py diff --git a/README.md b/README.md index e1a7216..6e865d1 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,15 @@ Python 3.x **Features** --- -* Retrieve Geolocation of IP or Domain. -* Run program with no arguments to get your IP Geolocation. -* Retrieve Geolocation of multiple IPs or Domains loaded from file. Each target in new line. +* Retrieve IP or Domain Geolocation. +* Retrieve your own IP Geolocation. +* Retrieve Geolocation for IPs or Domains loaded from file. Each target in new line. * Define your own custom User Agent string. +* Select random User-Agent strings from file. Each User Agent string in new line. * Proxy support. -* Pick a random User-Agent string from file. Each User Agent string in new line. * Open IP geolocation in Google Maps using the default browser. * Export results to csv, xml and txt format. - **Geolocation Information** --- * ASN @@ -42,37 +41,41 @@ Python 3.x --- ``` $ ./ip2geolocation.py -h -usage: ip2geolocation.py [-h] [-t host] [-T file] [-u user-agent] [-U file] - [-r] [-g] [-x url] [--csv file] [--xml file] - [-e file] +usage: ip2geolocation.py [-h] [-m] [-t TARGET] [-T file] [-u User-Agent] [-r] + [-U file] [-g] [--no-print] [-v] [-x PROXY] [-e file] + [-ec file] [-ex file] -IPGeoLocation 1.5 +IPGeoLocation 1.6 Retrieve IP Geolocation information from http://ip-api.com optional arguments: -h, --help show this help message and exit - -t host, --target host + -m, --my-ip Get Geolocation info for my IP address. + -t TARGET, --target TARGET IP Address or Domain to be analyzed. -T file, --tlist file A list of IPs/Domains targets, each target in new line. - -u user-agent, --useragent user-agent - Set the User-Agent request header (default: IP2GeoLocation 1.5). + -u User-Agent, --user-agent User-Agent + Set the User-Agent request header (default: IP2GeoLocation 1.6). + -r Pick User-Agent strings randomly from a file. -U file, --ulist file A list of User-Agent strings, each string in new line. - -r Pick User-Agent strings randomly from a file. -g Open IP location in Google maps with default browser. - -x url, --proxy url Setup proxy server (example: http://127.0.0.1:8080). - --csv file Export results in CSV format. - --xml file Export results in XML format. + --no-print Do not print results to terminal. + -v, --verbose Enable verbose printing. + -x PROXY, --proxy PROXY + Setup proxy server (example: http://127.0.0.1:8080) -e file, --txt file Export results. + -ec file, --csv file Export results in CSV format. + -ex file, --xml file Export results in XML format. ``` **Examples** --- **Retrieve your IP Geolocation** -* ./ip2geolocation.py +* ./ip2geolocation.py -m **Retrieve IP Geolocation** * ./ip2geolocation.py -t x.x.x.x @@ -101,8 +104,8 @@ optional arguments: **Export results to TXT file** * ./ip2geolocation.py -t x.x.x.x -e /path/to/results.txt -**Retrieve IP Geolocation of multiple targets** +**Retrieve IP Geolocation for many targets** * ./ip2geolocation.py -T /path/to/targets/targets.txt -**Retrieve IP Geolocation of multiple targets and export to xml** +**Retrieve IP Geolocation for many targets and export results to xml** * ./ip2geolocation.py -T /path/to/targets/targets.txt --xml /path/to/results.xml diff --git a/geolocation/IpGeoLocationLib.py b/geolocation/IpGeoLocationLib.py index 3d2f978..f53c3a7 100644 --- a/geolocation/IpGeoLocationLib.py +++ b/geolocation/IpGeoLocationLib.py @@ -29,6 +29,8 @@ import os.path import random from time import sleep +from utilities import MyExceptions + class IpGeoLocationLib: """Retrieve IP Geolocation information from http://ip-api.com""" @@ -36,96 +38,168 @@ class IpGeoLocationLib: def __init__(self): self.URL = 'http://ip-api.com/json/{}' self.Proxy = request.ProxyHandler({}) - - - def GetInfo(self, target, userAgent, targetList=None, randomUserAgent=False, uAgentList=None, proxy=False): + self.RandomUA = False + self.UserAgentFile = None + self.UserAgents = None + self.TargetsFile = None + self.Targets = None + self.Verbose = False + self.NoPrint = False + + def GetInfo(self, target, userAgent, targetsFile=None, rUserAgent=False, userAgentFile=None, proxy=False, noprint=False, verbose=False): """Retrieve information""" - self.UserAgent = userAgent - - if randomUserAgent and uAgentList is not None: - userAgent = self.__pickRandomUserAgent(uAgentList) - if(userAgent): - self.UserAgent = userAgent - else: - print('Unable to pick a random User Agent string from file.') - return False + self.UserAgent = userAgent + self.RandomUA = rUserAgent + self.Verbose = verbose + self.NoPrint = noprint + try: + + if userAgentFile and os.path.isfile(userAgentFile) and os.access(userAgentFile, os.R_OK): + self.UserAgentFile = userAgentFile + if self.Verbose: + self.__print('Loading User-Agent strings from file..') + self.__loadUserAgents() + + if targetsFile and os.path.isfile(targetsFile) and os.access(targetsFile, os.R_OK): + self.TargetsFile = targetsFile - if proxy: - self.Proxy = request.ProxyHandler({'http':proxy.scheme + '://' + proxy.netloc}) - opener = request.build_opener(self.Proxy) - request.install_opener(opener) - - - if targetList is not None: - return self.__retrieveGeolocations(targetList) - else: - return self.__retrieveGeolocation(target)#my ip + if proxy: + self.Proxy = request.ProxyHandler({'http':proxy.scheme + '://' + proxy.netloc}) + opener = request.build_opener(self.Proxy) + request.install_opener(opener) + if self.Verbose: + self.__print('Proxy ({}) has been configured.'.format(proxy.scheme + '://' + proxy.netloc)) + + + if self.TargetsFile: + results = self.__retrieveGeolocations() + + return results + + else: + if self.Verbose: + self.__print('Retrieving target Geolocation..') + + result = self.__retrieveGeolocation(target) + + return result + + except MyExceptions.UserAgentFileEmptyError: + self.__printError("User-Agent strings file is empty!") + except MyExceptions.InvalidTargetError: + self.__printError('Please provide a valid Domain or IP address.') + except MyExceptions.TargetsFileEmptyError: + self.__printError('Targets file is empty!.') + except MyExceptions.UserAgentFileNotSpecifiedError: + self.__printError('User-Agent strings file has not been provided!.') + except MyExceptions.TargetsFileNotSpecifiedError: + self.__printError('Targets file has not been provided!.') + except: + self.__printError("An unexpected error occurred") + return False - def __retrieveGeolocations (self, targetsFile): - """Retrieve IP Geolocation for each target in the file list""" - try: - IpGeoLocObjs = [] - - if os.path.isfile(targetsFile) and os.access(targetsFile, os.R_OK): - targets = [line.strip() for line in open(targetsFile, 'r') if line.strip()] - - for target in targets: - IpGeoLocObjs.append(self.__retrieveGeolocation(target)) - if len(targets)>=150: - sleep(.500)#1/2 sec - ip-api will automatically ban any IP address doing over 150 requests per minute + def __retrieveGeolocations (self): + """Retrieve IP Geolocation for each target in the list""" + IpGeoLocObjs = [] + + if self.Verbose: + self.__print('Loading targets from file..') + + self.__loadTargets() - return IpGeoLocObjs - except: - return False + if self.Verbose: + self.__print('Retrieving targets Geolocations..') + + 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""" - try: - - if target is None: - query = 'My IP' - target='' - elif self.__isValidIPAddress(target): - query = target - else: - ip = self.__hostnameToIP(target)#domain? - if not ip: - print('Please provide a valid Domain or IP address.') - return False - query = target - target = ip + + if not target: + query = 'My IP' + target='' - req = request.Request(self.URL.format(target), data=None, headers={ - 'User-Agent':self.UserAgent - }) + elif self.__isValidIPAddress(target): + query = target - response = request.urlopen(req) + else: + ip = self.__hostnameToIP(target)#domain? + if not ip: + raise MyExceptions.InvalidTargetError() - if response.code == 200: - encoding = response.headers.get_content_charset() - return IpGeoLocation(query, json.loads(response.read().decode(encoding))) - else: - #print('Unable to contact service.') - return False - except: - return False + query = target + target = ip + + if self.RandomUA and self.UserAgentFile: + self.__pickRandomUserAgent() + + if self.Verbose: + self.__print('User-Agent string used: {}.'.format(self.UserAgent)) + req = request.Request(self.URL.format(target), data=None, headers={ + 'User-Agent':self.UserAgent + }) + + response = request.urlopen(req) + + if response.code == 200: + encoding = response.headers.get_content_charset() + if self.Verbose: + self.__print('Geolocation information has been retrieved.') - def __pickRandomUserAgent(self, userAgentFileList): - """Pick randomly a user agent string from a provided file""" - try: - if os.path.isfile(userAgentFileList) and os.access(userAgentFileList, os.R_OK): - lines = [line.strip() for line in open(userAgentFileList, 'r') if line.strip()] - return random.choice(lines) - return False - except: - return False + ipGeoLocObj = IpGeoLocation(query, json.loads(response.read().decode(encoding))) + + if not self.NoPrint: + self.__printIPGeoLocation(ipGeoLocObj) + + return ipGeoLocObj + + return False + + + def __loadUserAgents(self): + """Load user-agent strings from file""" + if not self.UserAgentFile: + raise MyExceptions.UserAgentFileNotSpecifiedError() + + self.UserAgents = [line.strip() for line in open(self.UserAgentFile, 'r') if line.strip()] + if self.Verbose: + self.__print('User-Agent strings loaded.') + + if len(self.UserAgents) == 0: + raise MyExceptions.UserAgentFileEmptyError() + + + def __loadTargets(self): + """Load targets from file""" + if not self.TargetsFile: + raise MyExceptions.TargetsFileNotSpecifiedError() + + self.Targets = [line.strip() for line in open(self.TargetsFile, 'r') if line.strip()] + if self.Verbose: + self.__print('Targets loaded.') + + if len(self.Targets) == 0: + raise MyExceptions.TargetsFileEmptyError() + + + def __pickRandomUserAgent(self): + """Pick randomly a user-agent string from list""" + if not self.UserAgents or len(self.UserAgents) == 0: + raise MyExceptions.UserAgentFileEmptyError() + + self.UserAgent = random.choice(self.UserAgents) def __hostnameToIP(self, hostname): @@ -143,4 +217,52 @@ def __isValidIPAddress(self, ip): return True except: return False - \ No newline at end of file + + + def __print(self, message, newLine=False): + if newLine: + print('{}\n'.format(message)) + else: + print('{}'.format(message)) + + + def __printError(self, message): + print('Error: {}\n'.format(message)) + + + def __printIPGeoLocation(self, ipGeoLocation): + print(""" + Target: {} + + IP: {} + ASN: {} + City: {} + Country: {} + Country Code: {} + ISP: {} + Latitude: {} + Longtitude: {} + Organization: {} + Region Code: {} + Region Name: {} + Timezone: {} + Zip Code: {} + Google Maps: {} + """.format(ipGeoLocation.Query, + ipGeoLocation.IP, + ipGeoLocation.ASN, + ipGeoLocation.City, + ipGeoLocation.Country, + ipGeoLocation.CountryCode, + ipGeoLocation.ISP, + ipGeoLocation.Latitude, + ipGeoLocation.Longtitude, + ipGeoLocation.Organization, + ipGeoLocation.Region, + ipGeoLocation.RegionName, + ipGeoLocation.Timezone, + ipGeoLocation.Zip, + ipGeoLocation.GoogleMapsLink + )#.encode('cp737', errors='replace').decode('cp737') + ) + \ No newline at end of file diff --git a/ip2geolocation.py b/ip2geolocation.py index a1fcf7c..f88a51f 100644 --- a/ip2geolocation.py +++ b/ip2geolocation.py @@ -32,7 +32,7 @@ import os.path -VERSION = '1.5' +VERSION = '1.6' def checkProxy(url): @@ -61,43 +61,17 @@ def checkFileWrite(filename): return filename else: raise argparse.ArgumentTypeError("Unable to write to {} file (Insufficient permissions).".format(filename)) - - -def printIPGeoLocation(ipGeoLocation): - print(""" - Target: {} - - IP: {} - ASN: {} - City: {} - Country: {} - Country Code: {} - ISP: {} - Latitude: {} - Longtitude: {} - Organization: {} - Region Code: {} - Region Name: {} - Timezone: {} - Zip Code: {} - Google Maps: {} - """.format(ipGeoLocation.Query, - ipGeoLocation.IP, - ipGeoLocation.ASN, - ipGeoLocation.City, - ipGeoLocation.Country, - ipGeoLocation.CountryCode, - ipGeoLocation.ISP, - ipGeoLocation.Latitude, - ipGeoLocation.Longtitude, - ipGeoLocation.Organization, - ipGeoLocation.Region, - ipGeoLocation.RegionName, - ipGeoLocation.Timezone, - ipGeoLocation.Zip, - ipGeoLocation.GoogleMapsLink - )#.encode('cp737', errors='replace').decode('cp737') - ) + + +def printInfo( message, newLine=False): + if newLine: + print('{}\n'.format(message)) + else: + print('{}'.format(message)) + + +def printError( message): + print('Error: {}\n'.format(message)) if __name__ == '__main__': @@ -106,47 +80,106 @@ def printIPGeoLocation(ipGeoLocation): Retrieve IP Geolocation information from http://ip-api.com """.format(VERSION), formatter_class=RawTextHelpFormatter) - #target - parser.add_argument('-t', '--target', metavar='host', 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 - parser.add_argument('-u', '--useragent', metavar='user-agent', 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.') + #pick target/s + parser.add_argument('-m', '--my-ip', + dest='myip', + action='store_true', + help='Get Geolocation info for my IP address.') - #misc - parser.add_argument('-r', help='Pick User-Agent strings randomly from a file.', action='store_true') - parser.add_argument('-g', help='Open IP location in Google maps with default browser.', action='store_true') + parser.add_argument('-t', '--target', + help='IP Address or Domain to be analyzed.') - #anon - parser.add_argument('-x', '--proxy', metavar='url', type=checkProxy, help='Setup proxy server (example: http://127.0.0.1:8080).') + parser.add_argument('-T', '--tlist', + metavar='file', + type=checkFileRead, + help='A list of IPs/Domains targets, each target in new line.') - #export - parser.add_argument('--csv', metavar='file', type=checkFileWrite, help='Export results in CSV format.') - parser.add_argument('--xml', metavar='file', type=checkFileWrite, help='Export results in XML format.') - parser.add_argument('-e', '--txt', metavar='file', type=checkFileWrite, help='Export results.') - args = parser.parse_args() + #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('-r', + action='store_true', + help='Pick User-Agent strings randomly from a file.') - if(args.target is not None and args.tlist is not None): - print("You can provide either a single target(-t) or a list of targets(-T). Not both!") - sys.exit(2) + 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('--no-print', + action='store_true', + help='Do not print results to terminal.') + + parser.add_argument('-v', '--verbose', + action='store_true', + help='Enable verbose printing.') + + + #anonymity options + parser.add_argument('-x', '--proxy', + type=checkProxy, + help='Setup proxy server (example: http://127.0.0.1:8080)') + + + #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() + + if len(sys.argv) == 1: + parser.print_help() + sys.exit(0) + + if(args.target and args.tlist): + printError("You can request Geolocation information either for a single target(-t) or a list of targets(-T). Not both!") + sys.exit(1) + + if(args.target and args.myip): + printError("You can request Geolocation information either for a single target(-t) or your own IP address. Not both!") + sys.exit(1) + if(args.tlist and args.myip): + printError("You can request Geolocation information either for a list of targets(-T) or your own IP address. Not both!") + sys.exit(1) - if(args.tlist is not None and args.g): - print("Google maps location is working only with single targets.") - sys.exit(3) + if(args.tlist and args.g): + printError("Google maps location is working only with single targets.") + sys.exit(2) - if(args.r and args.ulist is None): - print("You didn't provide a file with User-Agent strings, each string in a new line.") - sys.exit(4) + if(args.r and not args.ulist): + printError("You haven't provided a User-Agent strings file, each string in a new line.") + sys.exit(3) ipGeoLocRequest = IpGeoLocationLib() - result = ipGeoLocRequest.GetInfo(args.target, args.useragent, args.tlist, args.r, args.ulist, args.proxy) - + result = ipGeoLocRequest.GetInfo(args.target, args.uagent, args.tlist, args.r, args.ulist, args.proxy, args.no_print, args.verbose) IpGeoLocObj = None IpGeoLocObjs = None @@ -155,50 +188,59 @@ def printIPGeoLocation(ipGeoLocation): IpGeoLocObj = result elif type(result) is list: IpGeoLocObjs = result - + else: + printError("Retrieving IP Geolocation information failed.") + sys.exit(5) + if IpGeoLocObjs is not None: if args.csv: fileExporter = FileExporter() + if args.verbose: + printInfo('Saving results to {} csv file.'.format(args.csv)) if not fileExporter.ExportListToCSV(IpGeoLocObjs, args.csv): - print('Saving results to {} csv file failed.'.format(args.csv)) + printError('Saving results to {} csv file failed.'.format(args.csv)) if args.xml: fileExporter = FileExporter() + if args.verbose: + printInfo('Saving results to {} xml file.'.format(args.xml)) if not fileExporter.ExportListToXML(IpGeoLocObjs, args.xml): - print('Saving results to {} xml file failed.'.format(args.xml)) + printError('Saving results to {} xml file failed.'.format(args.xml)) if args.txt: fileExporter = FileExporter() + if args.verbose: + printInfo('Saving results to {} txt file.'.format(args.txt)) if not fileExporter.ExportListToTXT(IpGeoLocObjs, args.txt): - print('Saving results to {} txt file failed.'.format(args.txt)) - - print('IPGeoLocation {} - Results'.format(VERSION)) - for obj in IpGeoLocObjs: - if obj: - printIPGeoLocation(obj) - + printError('Saving results to {} txt file failed.'.format(args.txt)) + elif IpGeoLocObj is not None: if args.g: if type(IpGeoLocObj.Longtitude) == float and type(IpGeoLocObj.Latitude) == float: + if args.verbose: + printInfo('Opening Geolocation in browser..'.format(args.csv)) webbrowser.open(IpGeoLocObj.GoogleMapsLink) if args.csv: fileExporter = FileExporter() + if args.verbose: + printInfo('Saving results to {} csv file.'.format(args.csv)) if not fileExporter.ExportToCSV(IpGeoLocObj, args.csv): - print('Saving results to {} csv file failed.'.format(args.csv)) + printError('Saving results to {} csv file failed.'.format(args.csv)) if args.xml: fileExporter = FileExporter() + if args.verbose: + printInfo('Saving results to {} xml file.'.format(args.xml)) if not fileExporter.ExportToXML(IpGeoLocObj, args.xml): - print('Saving results to {} xml file failed.'.format(args.xml)) + printError('Saving results to {} xml file failed.'.format(args.xml)) if args.txt: fileExporter = FileExporter() + if args.verbose: + printInfo('Saving results to {} txt file.'.format(args.txt)) if not fileExporter.ExportToTXT(IpGeoLocObj, args.txt): - print('Saving results to {} txt file failed.'.format(args.txt)) + printError('Saving results to {} txt file failed.'.format(args.txt)) - print('IPGeoLocation {} - Results'.format(VERSION)) - printIPGeoLocation(IpGeoLocObj) - diff --git a/utilities/MyExceptions.py b/utilities/MyExceptions.py new file mode 100644 index 0000000..8fd7bf5 --- /dev/null +++ b/utilities/MyExceptions.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# encoding: UTF-8 + +""" + IPGeoLocation - Retrieve IP Geolocation information + Powered by http://ip-api.com + Copyright (C) 2015 @maldevel + + 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 . +""" + +__author__ = 'maldevel' + + +class UserAgentFileEmptyError(Exception): + pass + +class InvalidTargetError(Exception): + pass + +class TargetsFileEmptyError(Exception): + pass + +class TargetsFileNotSpecifiedError(Exception): + pass + +class UserAgentFileNotSpecifiedError(Exception): + pass \ No newline at end of file