From d2f9b1346fc5a3558072f14a118caac54c2da80b Mon Sep 17 00:00:00 2001 From: 0xtheM7 Date: Wed, 1 Apr 2026 15:40:08 +0545 Subject: [PATCH 1/4] Added opencode for free mode --- README.md | 20 +++++++++++++++++++- subrecongpt.py | 51 +++++++++++++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 736cc09..26912d5 100644 --- a/README.md +++ b/README.md @@ -14,17 +14,35 @@ pip install openai - An OpenAI API key. You can obtain this from the OpenAI website. + + +To install the free method without OpenAI, use the following command + +- Install the opencode + +```bash +curl -fsSL https://opencode.ai/install | bash +``` + ## Usage You can run the script from the command line like this: ```bash -chaos -d yourdomain.com | python subrecongpt.py --apikey YOUR_OPENAI_API_KEY +chaos -d yourdomain.com | python subrecongpt.py --mode openai --apikey YOUR_OPENAI_API_KEY ``` + Replace yourdomain.com with the domain you're investigating and YOUR_OPENAI_API_KEY with your actual OpenAI API key. This command will run Chaos on yourdomain.com, and then pipe the output into the Python script. The script will generate similar subdomains for each subdomain output by Chaos, and then attempt to resolve these new subdomains. + +When running without OpenAI, use the following command + +```bash +subfinder -d yourdomain.com | python3 subrecongpt-test.py +``` + ## Output For each input subdomain, the script will print out the AI's guesses for similar subdomains and whether each guess resolves: diff --git a/subrecongpt.py b/subrecongpt.py index 9ec539d..68cc4f2 100644 --- a/subrecongpt.py +++ b/subrecongpt.py @@ -3,29 +3,36 @@ import argparse import sys import time +from os import popen -def generate_subdomains(subdomain, domain, api_key): +def generate_subdomains(subdomain, domain, api_key=None, mode=None): openai.api_key = api_key - while True: # Continue trying until a successful API call is made - try: - response = openai.ChatCompletion.create( - model="gpt-3.5-turbo", - messages=[ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": f"Generate 5 subdomains similar to {subdomain}."}, - ], - ) - ai_generated_subdomains = [f"{sub}.{domain}" for sub in response['choices'][0]['message']['content'].strip().split('\n')] - - return ai_generated_subdomains - except openai.error.RateLimitError as e: - print("Rate limit exceeded. Sleeping for 20 seconds...") - time.sleep(20) # Sleep for 20 seconds and then try again - except Exception as e: - print(f"An unexpected error occurred: {e}") - raise e # If it's a different kind of error, raise it + if mode == 'openai': + print("Here") + while True: # Continue trying until a successful API call is made + try: + response = openai.ChatCompletion.create( + model="gpt-3.5-turbo", + messages=[ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": f"Generate 5 subdomains similar to {subdomain}."}, + ], + ) + ai_generated_subdomains = [f"{sub}.{domain}" for sub in response['choices'][0]['message']['content'].strip().split('\n')] + return ai_generated_subdomains + except openai.error.RateLimitError as e: + print("Rate limit exceeded. Sleeping for 20 seconds...") + time.sleep(20) # Sleep for 20 seconds and then try again + except Exception as e: + print(f"An unexpected error occurred: {e}") + raise e # If it's a different kind of error, raise it + else: + subdomains = popen(f"opencode run 'Generate exactly 10 subdomains based on \"{subdomain}\" and return full domain names like subdomain.{domain}. Do not return only the subdomain part. Output only one full domain per line, no explanations or extra text.'").read() + print(subdomains) + ai_generated_subdomains = [line.strip() for line in subdomains.splitlines() if line.strip()] + return ai_generated_subdomains def resolve_subdomains(subdomains): resolved_subdomains = [] @@ -44,7 +51,8 @@ def resolve_subdomains(subdomains): def main(): parser = argparse.ArgumentParser(description='AI-assisted subdomain discovery.') - parser.add_argument('--apikey', required=True, help='OpenAI API key.') + parser.add_argument('--apikey', required=False, help='OpenAI API key.') + parser.add_argument('--mode', required=False, help='AI selection mode.') args = parser.parse_args() lines = [line.strip() for line in sys.stdin] @@ -55,7 +63,8 @@ def main(): continue subdomain, domain = line.split('.', 1) # Split the line into subdomain and domain print(f"\nSubdomain = {subdomain}.{domain}") - new_subdomains = generate_subdomains(subdomain, domain, args.apikey) + new_subdomains = generate_subdomains(subdomain, domain, mode=args.mode, api_key=args.apikey ) + print(new_subdomains) print(f"Guesses: {', '.join([sub.split('.')[0] for sub in new_subdomains])}\n") resolved_subdomains = resolve_subdomains(new_subdomains) time.sleep(1) # Pause for 1 second From d4c93cb090b7110cd69c638a9ef5078ed514d912 Mon Sep 17 00:00:00 2001 From: Himansu Mahato <63031654+0xthem7@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:56:25 +0545 Subject: [PATCH 2/4] Update subrecongpt.py --- subrecongpt.py | 1 - 1 file changed, 1 deletion(-) diff --git a/subrecongpt.py b/subrecongpt.py index 68cc4f2..577ab18 100644 --- a/subrecongpt.py +++ b/subrecongpt.py @@ -64,7 +64,6 @@ def main(): subdomain, domain = line.split('.', 1) # Split the line into subdomain and domain print(f"\nSubdomain = {subdomain}.{domain}") new_subdomains = generate_subdomains(subdomain, domain, mode=args.mode, api_key=args.apikey ) - print(new_subdomains) print(f"Guesses: {', '.join([sub.split('.')[0] for sub in new_subdomains])}\n") resolved_subdomains = resolve_subdomains(new_subdomains) time.sleep(1) # Pause for 1 second From 350027268af7471c037bd80d9495f3c16e2b483d Mon Sep 17 00:00:00 2001 From: 0xtheM7 Date: Wed, 1 Apr 2026 15:58:37 +0545 Subject: [PATCH 3/4] Added opencode for free mode --- subdomains.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 subdomains.txt diff --git a/subdomains.txt b/subdomains.txt new file mode 100644 index 0000000..82177d3 --- /dev/null +++ b/subdomains.txt @@ -0,0 +1,10 @@ +bughxcazoqtj.vulnweb.com +bughxcazoqtj1.vulnweb.com +bughxcazoqtj2.vulnweb.com +bughxcazoqtj-dev.vulnweb.com +bughxcazoqtj-test.vulnweb.com +bughxcazoqtj-staging.vulnweb.com +bughxcazoqtj-prod.vulnweb.com +bughxcazoqtj-api.vulnweb.com +bughxcazoqtj-web.vulnweb.com +bughxcazoqtj-app.vulnweb.com \ No newline at end of file From d13d0f2e1e47862ec47ccb1b5739d223243ef14d Mon Sep 17 00:00:00 2001 From: 0xtheM7 Date: Wed, 1 Apr 2026 16:01:01 +0545 Subject: [PATCH 4/4] Added opencode for free mode --- subrecongpt.py | 1 - 1 file changed, 1 deletion(-) diff --git a/subrecongpt.py b/subrecongpt.py index 577ab18..890bcea 100644 --- a/subrecongpt.py +++ b/subrecongpt.py @@ -30,7 +30,6 @@ def generate_subdomains(subdomain, domain, api_key=None, mode=None): raise e # If it's a different kind of error, raise it else: subdomains = popen(f"opencode run 'Generate exactly 10 subdomains based on \"{subdomain}\" and return full domain names like subdomain.{domain}. Do not return only the subdomain part. Output only one full domain per line, no explanations or extra text.'").read() - print(subdomains) ai_generated_subdomains = [line.strip() for line in subdomains.splitlines() if line.strip()] return ai_generated_subdomains