Implex-ltd / hcaptcha-reverse

Reverse engineered hcaptcha.
92 stars 28 forks source link

how to decode octet-stream? #4

Closed dr3adx closed 4 months ago

dr3adx commented 4 months ago

From what I've seen newer chrome versions (or maybe its version unrelated and is related to hcaptcha js code) send octet-stream encoded body data while solving hcaptcha and hcaptcha replies with octet-stream body. How can we decode the octet stream?

zxcvqwerasdf commented 4 months ago

It's about /getcaptcha/ request?

dr3adx commented 4 months ago

Yes, /getcaptcha and /checkcaptcha

On Sat, Jul 6, 2024, 10:23 PM PudgeCarry @.***> wrote:

It's about /getcaptcha/ request?

— Reply to this email directly, view it on GitHub https://github.com/Implex-ltd/hcaptcha-reverse/issues/4#issuecomment-2211796695, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBR55CGJQAH67HWSNCYWSTZLADXTAVCNFSM6AAAAABKHHSP72VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMJRG44TMNRZGU . You are receiving this because you authored the thread.Message ID: @.***>

zxcvqwerasdf commented 4 months ago

I opened hcaptcha.js in debugger, then set bp on line (15062)

Eo(new Uint8Array(e)).then((function(t) {

after some code there is

then((function(t) {
                e(po.decode(t))
            }

and after this code

                "./codec-base": 9,
                "./read-core": 22,
                "./write-core": 25
            }],
            11: [function(t, e, i) {
                function n(t) {
                    if (!(this instanceof n))
                        return new n(t);
                    if (t && (this.options = t,
                    t.codec)) {
                        var e = this.codec = t.codec;
                        e.bufferish && (this.bufferish = e.bufferish)
                    }
                }
                i.DecodeBuffer = n;
                var o = t("./read-core").preset;
                t("./flex-buffer").FlexDecoder.mixin(n.prototype),
                n.prototype.codec = o,
                n.prototype.fetch = function() {
                    return this.codec.decode(this)
                }
            }

I didn't get what the codec is here, but after some processing you will get to image

So, how it's works:

  1. parse response data as Uint8Array (byte array), then something happening (because after processing, count of bytes is decreasing), then i.ToString()
                i.toString = function(t, e, i) {
                    var n = this
                      , o = 0 | e;
                    i || (i = n.length);
                    for (var r = "", s = 0; o < i; )
                        (s = n[o++]) < 128 ? r += String.fromCharCode(s) : (192 == (224 & s) ? s = (31 & s) << 6 | 63 & n[o++] : 224 == (240 & s) ? s = (15 & s) << 12 | (63 & n[o++]) << 6 | 63 & n[o++] : 240 == (248 & s) && (s = (7 & s) << 18 | (63 & n[o++]) << 12 | (63 & n[o++]) << 6 | 63 & n[o++]),
                        s >= 65536 ? (s -= 65536,
                        r += String.fromCharCode(55296 + (s >>> 10), 56320 + (1023 & s))) : r += String.fromCharCode(s));
                    return r
                }

    t is "utf-8", e is indexFrom, t is indexTo

It remains only to find out what happens between the raw http response and the call to .toString with indexes

dr3adx commented 4 months ago

I opened hcaptcha.js in debugger, then set bp on line (15062)

Eo(new Uint8Array(e)).then((function(t) {

after some code there is

then((function(t) {
                e(po.decode(t))
            }

and after this code

                "./codec-base": 9,
                "./read-core": 22,
                "./write-core": 25
            }],
            11: [function(t, e, i) {
                function n(t) {
                    if (!(this instanceof n))
                        return new n(t);
                    if (t && (this.options = t,
                    t.codec)) {
                        var e = this.codec = t.codec;
                        e.bufferish && (this.bufferish = e.bufferish)
                    }
                }
                i.DecodeBuffer = n;
                var o = t("./read-core").preset;
                t("./flex-buffer").FlexDecoder.mixin(n.prototype),
                n.prototype.codec = o,
                n.prototype.fetch = function() {
                    return this.codec.decode(this)
                }
            }

I didn't get what the codec is here, but after some processing you will get to image

So, how it's works:

  1. parse response data as Uint8Array (byte array), then something happening (because after processing, count of bytes is decreasing), then i.ToString()
                i.toString = function(t, e, i) {
                    var n = this
                      , o = 0 | e;
                    i || (i = n.length);
                    for (var r = "", s = 0; o < i; )
                        (s = n[o++]) < 128 ? r += String.fromCharCode(s) : (192 == (224 & s) ? s = (31 & s) << 6 | 63 & n[o++] : 224 == (240 & s) ? s = (15 & s) << 12 | (63 & n[o++]) << 6 | 63 & n[o++] : 240 == (248 & s) && (s = (7 & s) << 18 | (63 & n[o++]) << 12 | (63 & n[o++]) << 6 | 63 & n[o++]),
                        s >= 65536 ? (s -= 65536,
                        r += String.fromCharCode(55296 + (s >>> 10), 56320 + (1023 & s))) : r += String.fromCharCode(s));
                    return r
                }

t is "utf-8", e is indexFrom, t is indexTo

It remains only to find out what happens between the raw http response and the call to .toString with indexes

yeah i came to some findings since the time i posted this, do u have discord or telegram so we can discuss this further?

zxcvqwerasdf commented 4 months ago

Change Accept header to application/json

dr3adx commented 4 months ago

Change Accept header to application/json

thats not the solution its very easily detected, because browser that supports arraybuffer will never request json response, give me your discord/telegram so we can talk properly

zxcvqwerasdf commented 4 months ago

Change Accept header to application/json

thats not the solution its very easily detected, because browser that supports arraybuffer will never request json response, give me your discord/telegram so we can talk properly

It's working for now. Also after any error hcaptcha start requesting json instead of octet without any problem. I think it's because of backward compatibility, sended friend request in discord to dr3adx username.

dr3adx commented 4 months ago

Change Accept header to application/json

thats not the solution its very easily detected, because browser that supports arraybuffer will never request json response, give me your discord/telegram so we can talk properly

It's working for now. Also after any error hcaptcha start requesting json instead of octet without any problem. I think it's because of backward compatibility, sended friend request in discord to dr3adx username.

this is my discord: --

kekeds commented 3 months ago

dm https://t.me/kokandg if you want to buy whole reverse for the request encryption!!

yk303 commented 2 months ago

Author

did you find solution for that?