mirror of
https://github.com/Ekultek/Zeus-Scanner.git
synced 2026-03-11 08:55:51 +00:00
added the ability to search multiple pages of Google (issue #4)
This commit is contained in:
parent
008ee37362
commit
94dac1c2bc
4 changed files with 132 additions and 22 deletions
|
|
@ -22,7 +22,7 @@ except NameError:
|
||||||
# clone link
|
# clone link
|
||||||
CLONE = "https://github.com/ekultek/zeus-scanner.git"
|
CLONE = "https://github.com/ekultek/zeus-scanner.git"
|
||||||
# current version <major.minor.commit.patch ID>
|
# current version <major.minor.commit.patch ID>
|
||||||
VERSION = "1.0.26"
|
VERSION = "1.0.27"
|
||||||
# colors to output depending on the version
|
# colors to output depending on the version
|
||||||
VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30}
|
VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30}
|
||||||
# version string formatting
|
# version string formatting
|
||||||
|
|
@ -381,3 +381,22 @@ def fix_log_file(logfile=get_latest_log_file(CURRENT_LOG_FILE_PATH)):
|
||||||
with open(logfile, "a+") as fixed:
|
with open(logfile, "a+") as fixed:
|
||||||
for line in retval.split("\n"):
|
for line in retval.split("\n"):
|
||||||
fixed.write(line + "\n")
|
fixed.write(line + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
def write_to_log_file(data_to_write, path, filename):
|
||||||
|
create_dir(path.format(os.getcwd()))
|
||||||
|
full_file_path = "{}/{}".format(
|
||||||
|
path.format(os.getcwd()), filename.format(len(os.listdir(path.format(
|
||||||
|
os.getcwd()
|
||||||
|
))) + 1)
|
||||||
|
)
|
||||||
|
with open(full_file_path, "a+") as log:
|
||||||
|
if isinstance(data_to_write, list):
|
||||||
|
for item in data_to_write:
|
||||||
|
item = item.strip()
|
||||||
|
log.write(str(item) + "\n")
|
||||||
|
logger.info(set_color(
|
||||||
|
"successfully wrote found items to '{}'...".format(full_file_path)
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
log.write(data_to_write + "\n")
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@ python-nmap==0.6.1
|
||||||
whichcraft==0.4.1
|
whichcraft==0.4.1
|
||||||
pyvirtualdisplay==0.2.1
|
pyvirtualdisplay==0.2.1
|
||||||
lxml==3.7.3
|
lxml==3.7.3
|
||||||
|
google-api-python-client==1.6.4
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,23 @@ import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
try:
|
try:
|
||||||
from urllib import unquote
|
import urllib2
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from urllib.parse import unquote
|
import urllib as urllib2
|
||||||
|
|
||||||
|
try:
|
||||||
|
from urllib import (
|
||||||
|
unquote,
|
||||||
|
quote
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
from urllib.parse import (
|
||||||
|
unquote,
|
||||||
|
quote
|
||||||
|
)
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
import google as google_api
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
from pyvirtualdisplay import Display
|
from pyvirtualdisplay import Display
|
||||||
from selenium.webdriver.common.keys import Keys
|
from selenium.webdriver.common.keys import Keys
|
||||||
|
|
@ -20,7 +32,8 @@ from lib.settings import (
|
||||||
URL_QUERY_REGEX,
|
URL_QUERY_REGEX,
|
||||||
URL_REGEX,
|
URL_REGEX,
|
||||||
shutdown,
|
shutdown,
|
||||||
create_dir,
|
URL_LOG_PATH,
|
||||||
|
write_to_log_file,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -160,21 +173,17 @@ def get_urls(query, url, verbose=False, warning=True, user_agent=None, proxy=Non
|
||||||
|
|
||||||
|
|
||||||
def parse_search_results(
|
def parse_search_results(
|
||||||
query, url, verbose=False, dirname="{}/log/url-log", filename="url-log-{}.log", **kwargs):
|
query, url_to_search, verbose=False, **kwargs):
|
||||||
"""
|
"""
|
||||||
Parse a webpage from Google for URL's with a GET(query) parameter
|
Parse a webpage from Google for URL's with a GET(query) parameter
|
||||||
"""
|
"""
|
||||||
exclude = "google" or "webcache" or "youtube"
|
exclude = "google" or "webcache" or "youtube"
|
||||||
splitter = "&"
|
splitter = "&"
|
||||||
|
retval = set()
|
||||||
create_dir(dirname.format(os.getcwd()))
|
query_url = None
|
||||||
full_file_path = "{}/{}".format(
|
|
||||||
dirname.format(os.getcwd()), filename.format(len(os.listdir(dirname.format(
|
|
||||||
os.getcwd()
|
|
||||||
))) + 1)
|
|
||||||
)
|
|
||||||
|
|
||||||
def __get_headers():
|
def __get_headers():
|
||||||
|
proxy_string, user_agent = None, None
|
||||||
try:
|
try:
|
||||||
proxy_string = kwargs.get("proxy")
|
proxy_string = kwargs.get("proxy")
|
||||||
except:
|
except:
|
||||||
|
|
@ -223,7 +232,7 @@ def parse_search_results(
|
||||||
"attempting to gather query URL..."
|
"attempting to gather query URL..."
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
query_url = get_urls(query, url, verbose=verbose, user_agent=user_agent, proxy=proxy_string)
|
query_url = get_urls(query, url_to_search, verbose=verbose, user_agent=user_agent, proxy=proxy_string)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "WebDriverException" in str(e):
|
if "WebDriverException" in str(e):
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
|
|
@ -241,12 +250,12 @@ def parse_search_results(
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"URL successfully gathered, searching for GET parameters..."
|
"URL successfully gathered, searching for GET parameters..."
|
||||||
))
|
))
|
||||||
|
|
||||||
logger.info(set_color(proxy_string_info))
|
logger.info(set_color(proxy_string_info))
|
||||||
req = requests.get(query_url, proxies=proxy_string)
|
req = requests.get(query_url, proxies=proxy_string)
|
||||||
logger.info(set_color(user_agent_info))
|
logger.info(set_color(user_agent_info))
|
||||||
req.headers.update(headers)
|
req.headers.update(headers)
|
||||||
found_urls = URL_REGEX.findall(req.text)
|
found_urls = URL_REGEX.findall(req.text)
|
||||||
retval = set()
|
|
||||||
for urls in list(found_urls):
|
for urls in list(found_urls):
|
||||||
for url in list(urls):
|
for url in list(urls):
|
||||||
url = unquote(url)
|
url = unquote(url)
|
||||||
|
|
@ -267,16 +276,45 @@ def parse_search_results(
|
||||||
"found a total of {} URL's with a GET parameter...".format(len(retval))
|
"found a total of {} URL's with a GET parameter...".format(len(retval))
|
||||||
))
|
))
|
||||||
if len(retval) != 0:
|
if len(retval) != 0:
|
||||||
|
file_path = write_to_log_file(retval, URL_LOG_PATH, "url-log-{}.log")
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"saving found URL's under '{}'...".format(full_file_path)
|
"found URL's have been saved to '{}'...".format(file_path)
|
||||||
))
|
))
|
||||||
with open(full_file_path, "a+") as log:
|
|
||||||
for url in list(retval):
|
|
||||||
log.write(url + "\n")
|
|
||||||
else:
|
else:
|
||||||
logger.critical(set_color(
|
logger.critical(set_color(
|
||||||
"did not find any usable URL's with the given query '{}' "
|
"did not find any usable URL's with the given query '{}' "
|
||||||
"using search engine '{}'...".format(query, url), level=50
|
"using search engine '{}'...".format(query, url_to_search), level=50
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
return list(retval) if len(retval) != 0 else None
|
return list(retval) if len(retval) != 0 else None
|
||||||
|
|
||||||
|
|
||||||
|
def search_multiple_pages(query, link_amount, verbose=False):
|
||||||
|
logger.warning(set_color(
|
||||||
|
"multiple pages will be searched using Google's API client, searches may be blocked after a certain "
|
||||||
|
"amount of time...", level=30
|
||||||
|
))
|
||||||
|
results, limit, found, index = set(), link_amount, 0, google_api.search(query)
|
||||||
|
while limit > 0:
|
||||||
|
results.add(next(index))
|
||||||
|
limit -= 1
|
||||||
|
found += 1
|
||||||
|
|
||||||
|
retval = set()
|
||||||
|
for url in results:
|
||||||
|
if URL_REGEX.match(url) and URL_QUERY_REGEX.match(url):
|
||||||
|
if verbose:
|
||||||
|
logger.debug(set_color(
|
||||||
|
"found '{}'...".format(url), level=10
|
||||||
|
))
|
||||||
|
retval.add(url)
|
||||||
|
|
||||||
|
logger.info(set_color(
|
||||||
|
"a total of {} links found out of requested {}...".format(
|
||||||
|
len(retval), link_amount
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
|
write_to_log_file(list(retval), URL_LOG_PATH, "url-log-{}.log")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
56
zeus.py
56
zeus.py
|
|
@ -46,7 +46,7 @@ from lib.settings import (
|
||||||
NMAP_MAN_PAGE_URL,
|
NMAP_MAN_PAGE_URL,
|
||||||
SQLMAP_MAN_PAGE_URL,
|
SQLMAP_MAN_PAGE_URL,
|
||||||
get_true_url,
|
get_true_url,
|
||||||
fix_log_file
|
fix_log_file,
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
@ -111,6 +111,13 @@ if __name__ == "__main__":
|
||||||
engines.add_option("-A", "--search-engine-aol", dest="useAOL", action="store_true",
|
engines.add_option("-A", "--search-engine-aol", dest="useAOL", action="store_true",
|
||||||
help="Use AOL as the search engine")
|
help="Use AOL as the search engine")
|
||||||
|
|
||||||
|
search_items = optparse.OptionGroup(parser, "Search options",
|
||||||
|
"Arguments that will control the search criteria")
|
||||||
|
search_items.add_option("-L", "--links", dest="amountToSearch", type=int, metavar="HOW-MANY-LINKS",
|
||||||
|
help="Specify how many links to try and search on Google")
|
||||||
|
search_items.add_option("-M", "--multi", dest="searchMultiplePages", action="store_true",
|
||||||
|
help="Search multiple pages of Google")
|
||||||
|
|
||||||
# obfuscation options
|
# obfuscation options
|
||||||
anon = optparse.OptionGroup(parser, "Anonymity arguments",
|
anon = optparse.OptionGroup(parser, "Anonymity arguments",
|
||||||
"Arguments that help with anonymity and hiding identity")
|
"Arguments that help with anonymity and hiding identity")
|
||||||
|
|
@ -141,6 +148,7 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
parser.add_option_group(mandatory)
|
parser.add_option_group(mandatory)
|
||||||
parser.add_option_group(attacks)
|
parser.add_option_group(attacks)
|
||||||
|
parser.add_option_group(search_items)
|
||||||
parser.add_option_group(anon)
|
parser.add_option_group(anon)
|
||||||
parser.add_option_group(engines)
|
parser.add_option_group(engines)
|
||||||
parser.add_option_group(misc)
|
parser.add_option_group(misc)
|
||||||
|
|
@ -391,7 +399,7 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# use a personal dork as the query
|
# use a personal dork as the query
|
||||||
if opt.dorkToUse is not None:
|
if opt.dorkToUse is not None and not opt.searchMultiplePages:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"starting dork scan with query '{}'...".format(opt.dorkToUse)
|
"starting dork scan with query '{}'...".format(opt.dorkToUse)
|
||||||
))
|
))
|
||||||
|
|
@ -423,6 +431,50 @@ if __name__ == "__main__":
|
||||||
auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch
|
auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# search multiple pages of Google
|
||||||
|
elif opt.dorkToUse is not None and opt.searchMultiplePages:
|
||||||
|
if opt.amountToSearch is None:
|
||||||
|
logger.fatal(set_color(
|
||||||
|
"did not specify amount of links to find...", level=50
|
||||||
|
))
|
||||||
|
shutdown()
|
||||||
|
link_amount_to_search = opt.amountToSearch
|
||||||
|
logger.info(set_color(
|
||||||
|
"searching Google using dork '{}' for a total of {} links...".format(opt.dorkToUse, opt.amountToSearch)
|
||||||
|
))
|
||||||
|
if proxy_to_use:
|
||||||
|
logger.warning(set_color(
|
||||||
|
"proxy not implemented for multiple page searching...", level=30
|
||||||
|
))
|
||||||
|
try:
|
||||||
|
search.search_multiple_pages(opt.dorkToUse, link_amount_to_search, verbose=opt.runInVerbose)
|
||||||
|
except Exception as e:
|
||||||
|
if "Error 400" in str(e):
|
||||||
|
logger.fatal(set_color(
|
||||||
|
"failed to connect to search engine...".format(e), level=50
|
||||||
|
))
|
||||||
|
elif "Error 503" in str(e):
|
||||||
|
logger.fatal(set_color(
|
||||||
|
"Google has blocked your IP address from doing anymore searches via API, "
|
||||||
|
"you can still search using headless browsers (-d <DORK>)...", level=50
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
logger.exception(set_color(
|
||||||
|
"failed with unexpected error '{}'...".format(e), level=50
|
||||||
|
))
|
||||||
|
shutdown()
|
||||||
|
|
||||||
|
urls_to_use = get_latest_log_file(URL_LOG_PATH)
|
||||||
|
if opt.runSqliScan or opt.runPortScan or opt.intelCheck or opt.adminPanelFinder or opt.runXssScan:
|
||||||
|
with open(urls_to_use) as urls:
|
||||||
|
for url in urls.readlines():
|
||||||
|
__run_attacks(
|
||||||
|
url.strip(),
|
||||||
|
sqlmap=opt.runSqliScan, nmap=opt.runPortScan, intel=opt.intelCheck, xss=opt.runXssScan,
|
||||||
|
admin=opt.adminPanelFinder, given_path=opt.givenSearchPath,
|
||||||
|
auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch
|
||||||
|
)
|
||||||
|
|
||||||
# use a file full of dorks as the queries
|
# use a file full of dorks as the queries
|
||||||
elif opt.dorkFileToUse is not None:
|
elif opt.dorkFileToUse is not None:
|
||||||
with open(opt.dorkFileToUse) as dorks:
|
with open(opt.dorkFileToUse) as dorks:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue