diff --git a/geolocation/IpGeoLocationLib.py b/geolocation/IpGeoLocationLib.py index 24da81b..960800b 100644 --- a/geolocation/IpGeoLocationLib.py +++ b/geolocation/IpGeoLocationLib.py @@ -22,13 +22,17 @@ __author__ = 'maldevel' -import json, ipaddress, socket, os.path, random, platform +import json, ipaddress, socket, os.path, random, webbrowser from urllib import request from geolocation.IpGeoLocation import IpGeoLocation from utilities.Logger import Logger from time import sleep from utilities import MyExceptions from libraries.colorama import Fore, Style +from utilities.FileExporter import FileExporter +from subprocess import call +from sys import platform as _platform + class IpGeoLocationLib: """Retrieve IP Geolocation information from http://ip-api.com""" @@ -52,7 +56,9 @@ def __init__(self): def GetInfo(self, target, userAgent, targetsFile=None, rUserAgent=False, userAgentFile=None, proxy=False, noprint=False, verbose=False, - nolog=False): + nolog=False, exportToCSVFile=None, + exportToXMLFile=None, exportToTXTFile=None, + googleMaps=False): """Retrieve information""" self.UserAgent = userAgent @@ -63,16 +69,19 @@ def GetInfo(self, target, userAgent, targetsFile=None, try: + #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.__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.__print('Loading targets from file {}..'.format(self.TargetsFile)) self.__loadTargets() + #read proxy settings, check if valid and configure connection if proxy: self.__checkProxy(proxy.netloc) self.Proxy = request.ProxyHandler({'http':proxy.scheme + '://' + proxy.netloc}) @@ -80,12 +89,30 @@ def GetInfo(self, target, userAgent, targetsFile=None, request.install_opener(opener) self.__print('Proxy ({}) has been configured.'.format(proxy.scheme + '://' + proxy.netloc)) + #retrieve information + results = None if self.TargetsFile: - return self.__retrieveGeolocations() + results = self.__retrieveGeolocations() else: - return self.__retrieveGeolocation(target) + results = self.__retrieveGeolocation(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) + + if googleMaps and type(results) is IpGeoLocation: + self.__openLocationInGoogleMaps(results) + + return True + except MyExceptions.UserAgentFileEmptyError: self.__printError("User-Agent strings file is empty!") except MyExceptions.InvalidTargetError: @@ -102,7 +129,66 @@ def GetInfo(self, target, userAgent, targetsFile=None, self.__printError("An unexpected error occurred") return False + + + def __openLocationInGoogleMaps(self, ipGeolObj): + """Open IP Geolocation in Google Maps with default browser""" + if type(ipGeolObj.Longtitude) == float and type(ipGeolObj.Latitude) == float: + self.__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.__printError('-g option is not available on your platform.') + def __exportResultsToCSV(self, objToExport, csvFile): + """Export results to csv file""" + fileExporter = FileExporter() + self.__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.__printError('Saving results to {} CSV file failed.'.format(csvFile)) + + + def __exportResultsToXML(self, objToExport, xmlFile): + """Export results to xml file""" + fileExporter = FileExporter() + self.__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.__printError('Saving results to {} XML file failed.'.format(xmlFile)) + + + def __exportResultsToTXT(self, objToExport, txtFile): + """Export results to text file""" + fileExporter = FileExporter() + self.__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.__printError('Saving results to {} text file failed.'.format(txtFile)) + def __retrieveGeolocations (self): """Retrieve IP Geolocation for each target in the list""" @@ -212,32 +298,36 @@ def __isValidIPAddress(self, ip): def __print(self, message): + """print/log info message""" if not self.NoLog: Logger.WriteLog('INFO', message) if self.Verbose: - if platform.system() == 'Windows': + if _platform == 'win32': print('[*] {}'.format(message)) else: print('[' + Fore.GREEN + '*' + Style.RESET_ALL + '] {}'.format(message)) def __printResult(self, title, value): - if platform.system() == 'Windows': - print('{}: {}'.format(title, value)) - else: - print(title + ': ' + self.BOLD + Fore.GREEN + value + Style.RESET_ALL) + """print result to terminal""" + if _platform == 'win32': + print('{}: {}'.format(title, value)) + else: + print(title + ': ' + self.BOLD + Fore.GREEN + value + Style.RESET_ALL) def __printError(self, message): + """print/log error message""" if not self.NoLog: Logger.WriteLog('ERROR', message) - if platform.system() == 'Windows': + if _platform == 'win32': print('[ERROR] {}'.format(message)) else: print('[' + Fore.RED + 'ERROR' + Style.RESET_ALL + '] {}'.format(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) @@ -258,6 +348,7 @@ def __printIPGeoLocation(self, ipGeoLocation): def __checkProxy(self, proxy): + """check proxy connectivity""" check = True self.__print('Testing proxy {} connectivity..'.format(proxy)) diff --git a/ip2geolocation.py b/ip2geolocation.py index a0dec50..4a30d9c 100644 --- a/ip2geolocation.py +++ b/ip2geolocation.py @@ -21,17 +21,14 @@ """ __author__ = 'maldevel' -__version__ = '1.8' +__version__ = '1.9' -import argparse, sys, webbrowser, os.path +import argparse, sys, os.path from argparse import RawTextHelpFormatter from geolocation.IpGeoLocationLib import IpGeoLocationLib -from geolocation.IpGeoLocation import IpGeoLocation -from utilities.FileExporter import FileExporter from utilities.Logger import Logger from urllib.parse import urlparse from libraries.colorama import Fore, Style -from subprocess import call from sys import platform as _platform @@ -61,20 +58,10 @@ def checkFileWrite(filename): return filename else: raise argparse.ArgumentTypeError("Unable to write to {} file (Insufficient permissions).".format(filename)) - - -def printInfo( message): - if not args.nolog: - Logger.WriteLog('INFO', message) - - if args.verbose: - if _platform == 'win32': - print('[*] {}'.format(message)) - else: - print('[' + Fore.GREEN + '*' + Style.RESET_ALL + '] {}'.format(message)) def printError(message): + """Print/Log error message""" if not args.nolog: Logger.WriteLog('ERROR', message) @@ -168,99 +155,43 @@ def printError(message): args = parser.parse_args() + # no args provided if len(sys.argv) == 1: parser.print_help() - sys.exit(0) + sys.exit(1) + #single target or multiple targets 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) + sys.exit(2) + #my ip address or single target 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) + sys.exit(3) + #multiple targets or my ip address 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) + sys.exit(4) + #single target and google maps if(args.tlist and args.g): printError("Google maps location is working only with single targets.") - sys.exit(2) + sys.exit(5) + #pick random user-agent string without user-agent strings list 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) + sys.exit(6) + #init lib ipGeoLocRequest = IpGeoLocationLib() - result = ipGeoLocRequest.GetInfo(args.target, args.uagent, args.tlist, - args.r, args.ulist, args.proxy, - args.noprint, args.verbose, args.nolog) - - IpGeoLocObj = None - IpGeoLocObjs = None - if type(result) is IpGeoLocation: - IpGeoLocObj = result - elif type(result) is list: - IpGeoLocObjs = result - else: + #retrieve information + if not ipGeoLocRequest.GetInfo(args.target, args.uagent, args.tlist, + args.r, args.ulist, args.proxy, + args.noprint, args.verbose, args.nolog, + args.csv, args.xml, args.txt, args.g): printError("Retrieving IP Geolocation information failed.") - sys.exit(5) - - - if args.csv: - fileExporter = FileExporter() - printInfo('Saving results to {} CSV file.'.format(args.csv)) - success = False - - if IpGeoLocObjs: - success = fileExporter.ExportListToCSV(IpGeoLocObjs, args.csv) - elif IpGeoLocObj: - success = fileExporter.ExportToCSV(IpGeoLocObj, args.csv) - - if not success: - printError('Saving results to {} CSV file failed.'.format(args.csv)) - - - if args.xml: - fileExporter = FileExporter() - printInfo('Saving results to {} XML file.'.format(args.xml)) - success = False - - if IpGeoLocObjs: - success = fileExporter.ExportListToXML(IpGeoLocObjs, args.xml) - elif IpGeoLocObj: - success = fileExporter.ExportToXML(IpGeoLocObj, args.xml) - - if not success: - printError('Saving results to {} XML file failed.'.format(args.xml)) - - - if args.txt: - fileExporter = FileExporter() - printInfo('Saving results to {} text file.'.format(args.txt)) - success = False - - if IpGeoLocObjs: - success = fileExporter.ExportListToTXT(IpGeoLocObjs, args.txt) - elif IpGeoLocObj: - success = fileExporter.ExportToTXT(IpGeoLocObj, args.txt) - - if not success: - printError('Saving results to {} text file failed.'.format(args.txt)) - - - if args.g: - if type(IpGeoLocObj.Longtitude) == float and type(IpGeoLocObj.Latitude) == float: - - printInfo('Opening Geolocation in browser..'.format(args.csv)) - - if _platform == 'cygwin': - call(['cygstart', IpGeoLocObj.GoogleMapsLink]) - - elif _platform == 'win32' or _platform == 'linux' or _platform == 'linux2': - webbrowser.open(IpGeoLocObj.GoogleMapsLink) - - else: - printError('-g option is not available on your platform.') + sys.exit(6)