Bypassed name resolution even if target has 0 gmaps contribution

This commit is contained in:
mxrch
2021-03-20 18:38:52 +01:00
parent 02847dba66
commit b3b01bcc6d
6 changed files with 171 additions and 52 deletions
+90 -32
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
import json
from time import time
from os.path import isfile
from pathlib import Path
from ssl import SSLError
@@ -45,31 +46,19 @@ def get_authorization_source(cookies):
return None
def save_tokens(auth, gdoc_token, hangouts_token, cookies):
def save_tokens(hangouts_auth, gdoc_token, hangouts_token, internal_token, internal_auth, cookies):
''' save tokens to file '''
output = {
"auth": auth,
"keys": {"gdoc": gdoc_token, "hangouts": hangouts_token},
"hangouts_auth": hangouts_auth, "internal_auth": internal_auth,
"keys": {"gdoc": gdoc_token, "hangouts": hangouts_token, "internal": internal_token},
"cookies": cookies
}
with open(config.data_path, 'w') as f:
f.write(json.dumps(output))
def get_hangouts_tokens(cookies, driverpath):
''' gets auth and hangout token '''
tmprinter = TMPrinter()
chrome_options = get_chrome_options_args(config.headless)
options = {
'connection_timeout': None # Never timeout, otherwise it floods errors
}
tmprinter.out("Starting browser...")
driver = webdriver.Chrome(
executable_path=driverpath, seleniumwire_options=options,
chrome_options=chrome_options
)
driver.header_overrides = config.headers
def get_hangouts_tokens(driver, cookies, tmprinter):
''' gets auth and hangouts token '''
tmprinter.out("Setting cookies...")
driver.get("https://hangouts.google.com/robots.txt")
@@ -82,7 +71,7 @@ def get_hangouts_tokens(cookies, driverpath):
tmprinter.out("Waiting for the /v2/people/me/blockedPeople request, it "
"can takes a few minutes...")
try:
req = driver.wait_for_request('/v2/people/me/blockedPeople', timeout=120)
req = driver.wait_for_request('/v2/people/me/blockedPeople', timeout=config.browser_waiting_timeout)
tmprinter.out("Request found !")
driver.close()
tmprinter.out("")
@@ -91,17 +80,67 @@ def get_hangouts_tokens(cookies, driverpath):
exit("\n[!] Selenium TimeoutException has occured. Please check your internet connection, proxies, vpns, et cetera.")
auth_token = req.headers["Authorization"]
hangouts_auth = req.headers["Authorization"]
hangouts_token = req.url.split("key=")[1]
return (auth_token, hangouts_token)
return (hangouts_auth, hangouts_token)
def drive_interceptor(request):
global internal_auth
if request.url.endswith(('.woff2', '.css', '.png', '.jpeg', '.svg', '.gif')):
request.abort()
elif request.path != "/drive/my-drive" and "Accept" in request.headers and \
any([x in request.headers["Accept"] for x in ["image", "font-woff"]]):
request.abort()
if "authorization" in request.headers and "_" in request.headers["authorization"] and \
request.headers["authorization"]:
internal_auth = request.headers["authorization"]
def get_internal_tokens(driver, cookies, tmprinter):
""" Extract the mysterious Authorization header used for
the Internal People API and some Drive requests"""
global internal_auth
internal_auth = ""
tmprinter.out("Setting cookies...")
driver.get("https://drive.google.com/robots.txt")
for k, v in cookies.items():
driver.add_cookie({'name': k, 'value': v})
start = time()
tmprinter.out("Fetching Drive homepage...")
driver.request_interceptor = drive_interceptor
driver.get("https://drive.google.com/drive/my-drive")
body = driver.page_source
internal_token = body.split("client-channel.google.com")[0][::-1].split(',')[4][::-1].strip('"')
tmprinter.out(f"Waiting for the authorization header, it "
"can takes a few minutes...")
while True:
if internal_auth:
tmprinter.clear()
break
elif time() - start > config.browser_waiting_timeout:
tmprinter.clear()
exit("[-] Timeout while fetching the Internal tokens.\nPlease increase the timeout in config.py or try again.")
del driver.request_interceptor
return internal_auth, internal_token
if __name__ == '__main__':
driverpath = get_driverpath()
driverpath = get_driverpath()
cookies_from_file = get_saved_cookies()
tmprinter = TMPrinter()
cookies = {"SID": "", "SSID": "", "APISID": "", "SAPISID": "", "HSID": "", "CONSENT": config.default_consent_cookie}
new_cookies_entered = False
@@ -113,7 +152,7 @@ if __name__ == '__main__':
if not cookies[name]:
cookies[name] = input(f"{name} => ").strip().strip('\"')
else:
# in case user wants to enter new cookies (for example: for new account)
# in case user wants to enter new cookies (example: for new account)
html = get_authorization_source(cookies_from_file)
valid = False
if html:
@@ -131,7 +170,7 @@ if __name__ == '__main__':
exit("Please put valid cookies. Exiting...")
# validate cookies
# Validate cookies
if new_cookies_entered or not cookies_from_file:
html = get_authorization_source(cookies)
if html:
@@ -141,13 +180,27 @@ if __name__ == '__main__':
if not new_cookies_entered:
cookies = cookies_from_file
choice = input("Do you want to generate new Google Docs "
"and Hangouts tokens ? (Y/n) ").lower()
choice = input("Do you want to generate new tokens ? (Y/n) ").lower()
if choice != "y":
exit()
print("Generating the Google Docs and Hangouts token...\n")
# get Google Docs token
# Start the extraction process
# We first initialize the browser driver
chrome_options = get_chrome_options_args(config.headless)
options = {
'connection_timeout': None # Never timeout, otherwise it floods errors
}
tmprinter.out("Starting browser...")
driver = webdriver.Chrome(
executable_path=driverpath, seleniumwire_options=options,
chrome_options=chrome_options
)
driver.header_overrides = config.headers
print("Extracting the tokens...\n")
# Extracting Google Docs token
trigger = '\"token\":\"'
if trigger not in html:
exit("[-] I can't find the Google Docs token in the source code...\n")
@@ -155,9 +208,14 @@ if __name__ == '__main__':
gdoc_token = html.split(trigger)[1][:100].split('"')[0]
print("Google Docs Token => {}".format(gdoc_token))
# get Google Hangouts token
auth_token, hangouts_token = get_hangouts_tokens(cookies, driverpath)
print("Authorization Token => {}".format(auth_token))
print("Hangouts Token => {}".format(hangouts_token))
# Extracting Internal People API tokens
internal_auth, internal_token = get_internal_tokens(driver, cookies, tmprinter)
print(f"Internal APIs Token => {internal_token}")
print(f"Internal APIs Authorization => {internal_auth}")
save_tokens(auth_token, gdoc_token, hangouts_token, cookies)
# Extracting Hangouts tokens
auth_token, hangouts_token = get_hangouts_tokens(driver, cookies, tmprinter)
print(f"Hangouts Authorization => {auth_token}")
print(f"Hangouts Token => {hangouts_token}")
save_tokens(auth_token, gdoc_token, hangouts_token, internal_token, internal_auth, cookies)
+1
View File
@@ -14,6 +14,7 @@ ytb_hunt_always = True # if True, search the Youtube channel everytime
gmaps_radius = 30 # in km. The radius distance to create groups of gmaps reviews.
gdocs_public_doc = "1jaEEHZL32t1RUN5WuZEnFpqiEPf_APYKrRBG9LhLdvE" # The public Google Doc to use it as an endpoint, to use Google's Search.
data_path = "resources/data.txt"
browser_waiting_timeout = 120
# Profile pictures options
write_profile_pic = True
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
import sys
import os
from pathlib import Path
from lib.utils import *
from modules.email import email_hunt
# from modules.doc import doc_hunt
if __name__ == "__main__":
# We change the current working directory to allow using GHunt from anywhere
os.chdir(Path(__file__).parents[0])
modules = ["email"]
if len(sys.argv) <= 1 or sys.argv[1].lower() not in modules:
print("Please choose a module.\n")
print("Available modules :")
for module in modules:
print(f"- {module}")
exit()
module = sys.argv[1].lower()
if len(sys.argv) >= 3:
data = sys.argv[2]
else:
data = None
if module == "email":
email_hunt(data)
+24 -2
View File
@@ -23,6 +23,8 @@ class TMPrinter():
else:
text += (" " * (self.max_len - len(text)))
print(text, end='\r')
def clear(self):
print(" " * self.max_len, end="\r")
def within_docker():
return Path('/.dockerenv').is_file()
@@ -41,13 +43,33 @@ def is_email_google_account(httpx_client, auth, cookies, email, hangouts_token):
req = httpx_client.post(host + url, data=body.format(email), headers=headers, cookies=cookies)
data = json.loads(req.text)
#pprint(data)
#pprint(data); exit()
if not "matches" in data:
exit("[-] This email address does not belong to a Google Account.")
return data
def get_account_name(httpx_client, gaiaID):
def get_account_name(httpx_client, gaiaID, internal_auth, internal_token, cookies, config):
# New method
req_headers = {
"Origin": "https://drive.google.com",
"authorization": internal_auth,
"Host": "people-pa.clients6.google.com"
}
headers = {**config.headers, **req_headers}
url = f"https://people-pa.clients6.google.com/v2/people?person_id={gaiaID}&request_mask.include_container=PROFILE&request_mask.include_container=DOMAIN_PROFILE&request_mask.include_field.paths=person.metadata.best_display_name&core_id_params.enable_private_names=true&key={internal_token}"
req = httpx_client.get(url, headers=headers)
data = json.loads(req.text)
try:
name = data["personResponse"][0]["person"]["metadata"]["bestDisplayName"]["displayName"]
except KeyError:
pass # We fallback on the classic method
else:
return name
# Classic method, but requires the target to have at least 1 GMaps contribution
req = httpx_client.get(f"https://www.google.com/maps/contrib/{gaiaID}")
gmaps_source = req.text
match = re.search(r'<meta content="Contributions by (.*?)" itemprop="name">', gmaps_source)
+22 -17
View File
@@ -21,33 +21,34 @@ from lib.photos import gpics
from lib.utils import *
import lib.calendar as gcalendar
if __name__ == "__main__":
def email_hunt(email):
banner()
# We change the current working directory to allow using GHunt from anywhere
os.chdir(Path(__file__).parents[0])
if len(sys.argv) <= 1:
exit("Please put an email address.")
if not email:
exit("Please give a valid email.\nExample : larry@google.com")
if not isfile(config.data_path):
exit("Please generate cookies and tokens first.")
exit("Please generate cookies and tokens first, with the check_and_gen.py script.")
email = sys.argv[1]
auth = ""
hangouts_auth = ""
hangouts_token = ""
cookies = ""
internal_auth = ""
internal_token = ""
cookies = {}
with open(config.data_path, 'r') as f:
out = json.loads(f.read())
auth = out["auth"]
hangouts_auth = out["hangouts_auth"]
hangouts_token = out["keys"]["hangouts"]
internal_auth = out["internal_auth"]
internal_token = out["keys"]["internal"]
cookies = out["cookies"]
client = httpx.Client(cookies=cookies, headers=config.headers)
data = is_email_google_account(client, auth, cookies, email,
data = is_email_google_account(client, hangouts_auth, cookies, email,
hangouts_token)
is_within_docker = within_docker()
@@ -65,7 +66,7 @@ if __name__ == "__main__":
infos = data["people"][gaiaID]
# get name
name = get_account_name(client, gaiaID)
name = get_account_name(client, gaiaID, internal_auth, internal_token, cookies, config)
if name:
print(f"Name : {name}")
else:
@@ -95,10 +96,14 @@ if __name__ == "__main__":
print("\n[-] Default profile picture")
# last edit
timestamp = int(infos["metadata"]["lastUpdateTimeMicros"][:-3])
last_edit = datetime.utcfromtimestamp(timestamp).strftime("%Y/%m/%d %H:%M:%S (UTC)")
print(f"\nLast profile edit : {last_edit}\n"
f"\nEmail : {email}\nGoogle ID : {gaiaID}\n")
try:
timestamp = int(infos["metadata"]["lastUpdateTimeMicros"][:-3])
last_edit = datetime.utcfromtimestamp(timestamp).strftime("%Y/%m/%d %H:%M:%S (UTC)")
print(f"\nLast profile edit : {last_edit}")
except KeyError:
last_edit = None
print(f"\nLast profile edit : Not found")
print(f"\nEmail : {email}\nGoogle ID : {gaiaID}\n")
# is bot?
profile_pic = infos["photo"][0]["url"]
+1 -1
View File
@@ -1,6 +1,6 @@
geopy
httpx
selenium-wire==2.1.2
selenium-wire
selenium
imagehash
pillow