mirror of
https://github.com/mxrch/GHunt.git
synced 2026-10-18 05:40:31 +08:00
Bypassed name resolution even if target has 0 gmaps contribution
This commit is contained in:
+90
-32
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -1,6 +1,6 @@
|
||||
geopy
|
||||
httpx
|
||||
selenium-wire==2.1.2
|
||||
selenium-wire
|
||||
selenium
|
||||
imagehash
|
||||
pillow
|
||||
|
||||
Reference in New Issue
Block a user