QIN2DIM / hcaptcha-challenger

🥂 Gracefully face hCaptcha challenge with MoE(ONNX) embedded solution.
https://docs.captchax.top/
GNU General Public License v3.0
1.49k stars 254 forks source link

[Note] You can close this instantly if you want, maight just be viable for some Testers #295

Closed Vinyzu closed 11 months ago

Vinyzu commented 1 year ago

This is a list of hCaptcha Sitekeys i found all arround the internet:

3b35d792-d035-4ea9-ad4e-61179582a5ee
3ceb8624-1970-4e6b-91d5-70317b70b651
28982ab4-aeef-4200-b9cc-28af1e23e377
ad252538-16a2-4618-a23c-51485c2c9622
a5f74b19-9e45-40e0-b45d-47ff91b7a6c2
28432475-d840-43fc-8b44-ccbf78ce90c2
ace50dd0-0d68-44ff-931a-63b670c7eed7
f5561ba9-8f1e-40ca-9b5b-a0b3f719ef34
91e4137f-95af-4bc9-97af-cdcedce21c8c
adafb813-8b5c-473f-9de3-485b4ad5aa09
c86d730b-300a-444c-a8c5-5312e7a93628
edc4ce89-8903-4906-80b1-7440ad9a69c8
9a5da798-adac-4c50-9c7e-79d9f92bd4c0
4c672d35-0701-42b2-88c3-78380b0db560
13257c82-e129-4f09-a733-2a7cb3102832
f1592dee-67b6-4670-9062-649933011aa2
a9b5fb07-92ff-493f-86fe-352a2803b3d0
8adc2f3e-e343-4ef9-bf6c-275a8a2818ab
50d5f7a9-8aed-4244-aea5-20a291951e93
c1ec07d4-a6a8-4e42-b8c7-f0de89453007
b364b1fd-e3d8-4d24-8c41-77a19604b00d
7734ec9b-f8cb-44b2-9fac-3a502cb4f1bf

Hope this helps someone! :D

Vinyzu commented 1 year ago

scraped_languages.txt

Also, here my scraped languages ;:D

263

Vinyzu commented 1 year ago

And, heres the Language Scraper Code with the Exploit:

import json
import hashlib
import math
import datetime
import base64
import urllib
import time
import random

import requests

def _n(req):
    # thank's h0nde for the following code
    x = "0123456789/:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

    req = req.split(".")

    req = {
        "header": json.loads(
            base64.b64decode(
                req[0] +
                "=======").decode("utf-8")),
        "payload": json.loads(
            base64.b64decode(
                req[1] +
                "=======").decode("utf-8")),
        "raw": {
            "header": req[0],
            "payload": req[1],
            "signature": req[2]}}

    def a(r):
        for t in range(len(r) - 1, -1, -1):
            if r[t] < len(x) - 1:
                r[t] += 1
                return True
            r[t] = 0
        return False

    def ix(r):
        t = ""
        for n in range(len(r)):
            t += x[r[n]]
        return t

    def o(r, e):
        n = e
        hashed = hashlib.sha1(e.encode())
        o = hashed.hexdigest()
        t = hashed.digest()
        e = None
        n = -1
        o = []
        for n in range(n + 1, 8 * len(t)):
            e = t[math.floor(n / 8)] >> n % 8 & 1
            o.append(e)
        a = o[:r]

        def index2(x, y):
            if y in x:
                return x.index(y)
            return -1
        return 0 == a[0] and index2(a, 1) >= r - 1 or -1 == index2(a, 1)

    def get():
        for e in range(25):
            n = [0 for i in range(e)]
            while a(n):
                u = req["payload"]["d"] + "::" + ix(n)
                if o(req["payload"]["s"], u):
                    return ix(n)

    result = get()
    hsl = ":".join([
        "1",
        str(req["payload"]["s"]),
        datetime.datetime.now().isoformat()[:19]
        .replace("T", "")
        .replace("-", "")
        .replace(":", ""),
        req["payload"]["d"],
        "",
        result
    ])
    return hsl

def _c(host, sitekey):
    r = requests.get(
        f"https://hcaptcha.com/checksiteconfig?host={host}&sitekey={sitekey}&sc=1&swa=1",
        headers={
            "Host": "hcaptcha.com",
            "Connection": "keep-alive",
            "sec-ch-ua": 'Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92',
            "Accept": "application/json",
            "sec-ch-ua-mobile": "?0",
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
            "Content-type": "application/json; charset=utf-8",
            "Origin": "https://newassets.hcaptcha.com",
            "Sec-Fetch-Site": "same-site",
            "Sec-Fetch-Mode": "cors",
            "Sec-Fetch-Dest": "empty",
            "Referer": "https://newassets.hcaptcha.com/",
            "Accept-Language": "en-US,en;q=0.9",
        },
    )
    return r.json()["c"]

def get_captcha(host, sitekey):
    c = _c(host, sitekey)
    c['type'] = 'hsl'

    data = {
        "sitekey": sitekey,
        "v": "b1129b9",
        "host": host,
        "n": _n(c["req"]),
        'motiondata': '{"st":1628923867722,"mm":[[203,16,1628923874730],[155,42,1628923874753],[137,53,1628923874770],[122,62,1628923874793],[120,62,1628923875020],[107,62,1628923875042],[100,61,1628923875058],[93,60,1628923875074],[89,59,1628923875090],[88,59,1628923875106],[87,59,1628923875131],[87,59,1628923875155],[84,56,1628923875171],[76,51,1628923875187],[70,47,1628923875203],[65,44,1628923875219],[63,42,1628923875235],[62,41,1628923875251],[61,41,1628923875307],[58,39,1628923875324],[54,38,1628923875340],[49,36,1628923875363],[44,36,1628923875380],[41,35,1628923875396],[40,35,1628923875412],[38,35,1628923875428],[38,35,1628923875444],[37,35,1628923875460],[37,35,1628923875476],[37,35,1628923875492]],"mm-mp":13.05084745762712,"md":[[37,35,1628923875529]],"md-mp":0,"mu":[[37,35,1628923875586]],"mu-mp":0,"v":1,"topLevel":{"st":1628923867123,"sc":{"availWidth":1680,"availHeight":932,"width":1680,"height":1050,"colorDepth":30,"pixelDepth":30,"availLeft":0,"availTop":23},"nv":{"vendorSub":"","productSub":"20030107","vendor":"Google Inc.","maxTouchPoints":0,"userActivation":{},"doNotTrack":null,"geolocation":{},"connection":{},"webkitTemporaryStorage":{},"webkitPersistentStorage":{},"hardwareConcurrency":12,"cookieEnabled":true,"appCodeName":"Mozilla","appName":"Netscape","appVersion":"5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36","platform":"MacIntel","product":"Gecko","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36","language":"en-US","languages":["en-US","en"],"onLine":true,"webdriver":false,"serial":{},"scheduling":{},"xr":{},"mediaCapabilities":{},"permissions":{},"locks":{},"usb":{},"mediaSession":{},"clipboard":{},"credentials":{},"keyboard":{},"mediaDevices":{},"storage":{},"serviceWorker":{},"wakeLock":{},"deviceMemory":8,"hid":{},"presentation":{},"userAgentData":{},"bluetooth":{},"managed":{},"plugins":["internal-pdf-viewer","mhjfbmdgcfjbbpaeojofohoefgiehjai","internal-nacl-plugin"]},"dr":"https://discord.com/","inv":false,"exec":false,"wn":[[1463,731,2,1628923867124],[733,731,2,1628923871704]],"wn-mp":4580,"xy":[[0,0,1,1628923867125]],"xy-mp":0,"mm":[[1108,233,1628923867644],[1110,230,1628923867660],[1125,212,1628923867678],[1140,195,1628923867694],[1158,173,1628923867711],[1179,152,1628923867727],[1199,133,1628923867744],[1221,114,1628923867768],[1257,90,1628923867795],[1272,82,1628923867811],[1287,76,1628923867827],[1299,71,1628923867844],[1309,68,1628923867861],[1315,66,1628923867877],[1326,64,1628923867894],[1331,62,1628923867911],[1336,60,1628923867927],[1339,58,1628923867944],[1343,56,1628923867961],[1345,54,1628923867978],[1347,53,1628923867994],[1348,52,1628923868011],[1350,51,1628923868028],[1354,49,1628923868045],[1366,44,1628923868077],[1374,41,1628923868094],[1388,36,1628923868110],[1399,31,1628923868127],[1413,25,1628923868144],[1424,18,1628923868161],[1436,10,1628923868178],[1445,3,1628923868195],[995,502,1628923871369],[722,324,1628923874673],[625,356,1628923874689],[523,397,1628923874705],[457,425,1628923874721]],"mm-mp":164.7674418604651},"session":[],"widgetList":["0a1l5c3yudk4"],"widgetId":"0a1l5c3yudk4","href":"https://discord.com/register","prev":{"escaped":false,"passed":false,"expiredChallenge":false,"expiredResponse":false}}',
        "hl": ["fr", "de"], # Heres where the exploit lies because of the list instead of just an string like "en"
        "c": json.dumps(c)
    }

    headers={
        "Host": "hcaptcha.com",
        "Connection": "keep-alive",
        "sec-ch-ua": 'Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92',
        "Accept": "application/json",
        "sec-ch-ua-mobile": "?0",
        "Content-length": str(len(data)),
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
        "Content-type": "application/x-www-form-urlencoded",
        "Origin": "https://newassets.hcaptcha.com",
        "Sec-Fetch-Site": "same-site",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Dest": "empty",
        "Referer": "https://newassets.hcaptcha.com/",
        "Accept-Language": "en-US,en;q=0.9"
    }

    return requests.post(f"https://hcaptcha.com/getcaptcha?s={sitekey}", data=urllib.parse.urlencode(data), headers=headers, timeout=30)

if __name__ == '__main__':
    BAD_CODE = {
        'а': 'a',
        'е': 'e',
        'e': 'e',
        'i': 'i',
        'і': 'i',
        'ο': 'o',
        'с': 'c',
        'ԁ': 'd',
        'ѕ': 's',
        'һ': 'h',
        'у': 'y',
        'р': 'p',
        'ー': '一',
        '土': '士',
        '&#39;': "'"
    }

    host, sitekeys = 'accounts.hcaptcha.com', open("sitekeys.txt").read().splitlines()
    scraped = {}
    with open('scraped.json', encoding='utf8') as f:
        scraped = json.loads(f.read())

    # Printing out all the Languages
    for i in range(100):
        sitekey = random.choice(sitekeys)
        try:
            langs = get_captcha(host, sitekey).json()['requester_question']
            for lang in langs:
                for c in BAD_CODE:
                    langs[lang] = langs[lang].replace(c, BAD_CODE[c])

            eng = langs['en']
            if eng not in scraped:
                print(f"\33[32m[+] New Quest: {eng} (Sitekey: {sitekey}) \033[0m")
                del langs['en']
                scraped[eng] = langs
            else:
                print(f"\33[33m[-] Replicate Quest: {eng} (Sitekey: {sitekey})\033[0m")
        except Exception as e:
            # Waiting some time if you get ratelimited
            print(f"\33[31m[!] Getting Ratelimited... (Sitekey: {sitekey})\033[0m")
            time.sleep(10)

    with open('scraped.json', 'w', encoding='utf8') as fp:
        json.dump(scraped, fp, ensure_ascii=False, indent=2, sort_keys=True)
Vinyzu commented 1 year ago

Also Credits to @MaxAndolini For Helping with some of the code