Skip to content
/ chan Public

soyjak added a new captcha o algo #280

@Mahkhmood8

Description

@Mahkhmood8

o algo

Activity

moffatman

moffatman commented on Oct 9, 2025

@moffatman
Owner

Too much work to support that site, the firewall is too powerful

Mahkhmood8

Mahkhmood8 commented on Oct 9, 2025

@Mahkhmood8
Author

Too much work to support that site, the firewall is too powerful

I managed to solve their PoW , using pure python

I even attemted wiping their catalog

they use very heavy fingerprinting , as for spammer point of view

one of the ways they ban users is fingerprinting , I managed to solve the issue by using

        const fingerPrintData = new FingerprintGenerator().getFingerprint({
            devices: ['desktop'],
            operatingSystems: ['windows'],
            browsers: [{ name: 'chrome' }]
        })
        console.log(fingerPrintData);```
(not having this line for example is autobanned )


my timezone was set to Israel, 
and they even hard code, when the timezone is in israle you get auto redirected to https://www.youtube.com/watch?v=vHSNZK4Je-Y
    const timezones = Intl.supportedValuesOf('timeZone');
    const randomTZ = timezones[Math.floor(Math.random() * timezones.length)];
    // await page.emulateTimezone("America/New_York");
evalutate cost of spamming, is 2$ in proxy bandwith , and maybe some electricity used, but I am a laptop user 

----
Side idea , you know like you can solve 4chan captchas? you can also do the same for users, 

like have some Puppeteer server cloud , load some of the html or whatever in the site, and output cookies or whatever -- or for this annotying `integrity-v2` 

lets be fair you can just, or get a cloud api , so anyone on the internet can request an intergrity v2 - is just run in a browser that isnt detected like ZenDrive or `rebrowser-puppeter-core` 

**consider what I learned about fingerprinting I have two ideas which I wont share here, that can easily make me give up** 
 
by far intergrity-v2 is very impressive 


// const results = await Promise.all(
//     Array.from({ length: 1 }, () =>
//         page.evaluate(() => ccall('x', 'string'))
//     )```
Image
import curl_cffi
import time
import random, requests
import base64
from argon2.low_level import hash_secret, Type
import traceback
from typing import List, Dict, Any, Optional


class MargeService:
    def __init__(self):
        self.base_url = "https://soyjak.st"
        self.mcchallenge_cookie = None

    def _create_session(self):
        session = curl_cffi.Session(impersonate="chrome133a")
        session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0'
        })

        return session

    def _human_delay(self, min_ms=100, max_ms=500):
        delay = random.uniform(min_ms/1000, max_ms/1000)
        time.sleep(delay)

    def _extract_hash_from_phc(self, phc_string):
        parts = phc_string.decode('utf-8').split('$')
        if len(parts) >= 6:
            hash_b64 = parts[-1]
            missing_padding = len(hash_b64) % 4
            if missing_padding:
                hash_b64 += '=' * (4 - missing_padding)
            return base64.b64decode(hash_b64)
        else:
            raise ValueError(f"Invalid PHC format: {phc_string}")

    def get_challenge(self, session):
        url = f"{self.base_url}/_challenge/pow"
        headers = {
            # 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0',
            'Accept': '*/*',
            'Accept-Language': 'en-US,en;q=0.5',
            'Accept-Encoding': 'identity',
            'Referer': f'{self.base_url}/',
            'Sec-Gpc': '1',
            'Sec-Fetch-Dest': 'empty',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-Site': 'same-origin',
            'Priority': 'u=4',
            'Te': 'trailers'
        }
        response = session.get(url, headers=headers)
        if response.status_code != 200:
            raise Exception(f"Failed to get challenge: {response.status_code}")
        return response.json()

    def solve_challenge(self, challenge):
        timestamp = challenge['Timestamp']
        difficulty = challenge['Difficulty']
        salt = challenge['Salt'].encode('utf-8')
        target_prefix = '0' * difficulty
        nonce = 0
        start_time = time.time()

        while True:
            password = f"{timestamp}:{nonce}".encode('utf-8')
            phc_result = hash_secret(
                secret=password,
                salt=salt,
                time_cost=2,
                memory_cost=4096,
                parallelism=1,
                hash_len=32,
                type=Type.ID
            )
            raw_hash = self._extract_hash_from_phc(phc_result)
            hash_hex = raw_hash.hex()

            if hash_hex.startswith(target_prefix):
                elapsed_time = time.time() - start_time
                return {
                    'nonce': str(nonce),
                    'hash_rate': nonce / elapsed_time if elapsed_time > 0 else 0
                }
            nonce += 1


    def solve_challenge_api(self, challenge, timeout=20):
        url = "https://84101bc73822.ngrok-free.app/solve" (using a back ende argon2id solver lol ,)

        payload = {
            "Timestamp": challenge['Timestamp'],
            "Difficulty": challenge['Difficulty'],
            "Salt": challenge['Salt']
        }
        
        try:
            response = requests.post(url, json=payload, timeout=timeout)
            
            if response.status_code == 200:
                result = response.json()
                print(f"Nonce: {result['nonce']}")
                print(f"Hash rate: {result['hash_rate']:.2f} H/s")
                return result
            else:
                print(f"Error: {response.json()}")
                return None
                
        except requests.exceptions.Timeout:
            print("Request timed out")
            return None


    def verify_solution(self, session, challenge, solution):
        url = f"{self.base_url}/_challenge/pow/verify"
        data = {
            'timestamp': challenge['Timestamp'],
            'salt': challenge['Salt'],
            'nonce': solution['nonce'],
            'signature': challenge['Signature'],
            'hashrate': str(solution['hash_rate'])
        }
        headers = {
            # 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0',
            'Accept': '*/*',
            'Accept-Language': 'en-US,en;q=0.5',
            'Accept-Encoding': 'identity',
            'Referer': f'{self.base_url}/',
            'Origin': self.base_url,
            'Sec-Gpc': '1',
            'Sec-Fetch-Dest': 'empty',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-Site': 'same-origin',
            'Priority': 'u=4',
            'Te': 'trailers'
        }
        response = session.post(url, data=data, headers=headers)
        if response.status_code != 200:
            raise Exception(f"Verification failed: {response.status_code}")

        # Extract cookie if verification successful
        if response.text.strip() == '1':
            for name, value in session.cookies.items():
                if name == '_____mcchallenge':
                    self.mcchallenge_cookie = value
                    print(f"saved challenge: {value[:20]}...")
                    break

        return response.text.strip() == '1'

    def solve_pow_if_needed(self, session):
        print("Solving PoW challenge...")
        challenge = self.get_challenge(session)
        print(challenge)
        # self._human_delay(2, 2)
        # solution = self.solve_challenge(challenge)
        solution = self.solve_challenge_api(challenge)
        print(solution)
        # self._human_delay(2, 200)
        success = self.verify_solution(session, challenge, solution)

        if success:
            print("PoW solved successfully")
            return True
        print("PoW failed")
        return False


def my_function():
    try:
        a = MargeService()
        e = a._create_session()


        # proxies = {
        #     "http": e_,
        #     "https": e_
        # }
        # # a.proxies = proxies
        # e.proxies.update(proxies)

        # EE = e.get("https://api.ipify.org?format=json")
        # print("IP:", EE.json())



        # # VVV= {'Timestamp': '1759263655', 'Difficulty': 3, 'Signature': 'cA2GvU4qxwGEQwz5voRDMAe2weogtE5BYKtNUXUOznA=', 'Salt': 'hmJWGKF9C6o='}
        # start_time = time.time()  # Start timer
        # result = a.solve_challenge(VVV)  # Solve the challenge
        # end_time = time.time()  # End timer

        # elapsed_time = end_time - start_time
        # print("Result:", result)
        # print("Time taken:", elapsed_time, "seconds")

        a.solve_pow_if_needed(e)

        # do_poll_jak(e)
        # print("Done poll")
        EE = e.get("https://soyjak.st/challenge-check.html")
        print(EE.text)
    except:
        raise


import concurrent.futures


start_time = time.time()  # Start timer

# Run the function 10 times concurrently
with concurrent.futures.ThreadPoolExecutor(max_workers=25) as executor:
    # Submit 10 tasks
    futures = [executor.submit(my_function) for _ in range(1)]
    
    # Wait for all to complete and get results
    results = [f.result() for f in futures]

end_time = time.time()  # End timer
elapsed_time = end_time - start_time
print("Time taken:", elapsed_time, "seconds")
# print(results)```
Mahkhmood8

Mahkhmood8 commented on Oct 9, 2025

@Mahkhmood8
Author

nodejs version

// margeService.js
const axios = require('axios');
const { wrapper } = require('axios-cookiejar-support');
const tough = require('tough-cookie');
const argon2 = require('argon2');

class MargeService {
  constructor() {
    this.baseUrl = 'https://soyjak.st';
    this.mcchallengeCookie = null;
  }

  _createSession() {
    // cookie jar + axios session (like requests.Session)
    const jar = new tough.CookieJar();
    const client = wrapper(axios.create({
      jar,
      withCredentials: true,
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0'
      },
      // do not follow more than default redirects - axios defaults are fine here
    }));

    // attach jar so other methods can inspect cookies
    client._cookieJar = jar;
    return client;
  }

  async _humanDelay(minMs = 100, maxMs = 500) {
    const delay = Math.random() * (maxMs - minMs) + minMs;
    return new Promise((resolve) => setTimeout(resolve, delay));
  }

  // Helper: If you ever need to parse PHC (argon2 encoded) to raw hash
  _extractHashFromPHC(phcString) {
    // phcString e.g. "$argon2id$v=19$m=4096,t=2,p=1$<salt_b64>$<hash_b64>"
    const parts = phcString.split('$');
    if (parts.length >= 6) {
      let hashB64 = parts[parts.length - 1];
      // fix padding
      const missingPadding = hashB64.length % 4;
      if (missingPadding) hashB64 += '='.repeat(4 - missingPadding);
      return Buffer.from(hashB64, 'base64');
    } else {
      throw new Error(`Invalid PHC format: ${phcString}`);
    }
  }

  async getChallenge(session) {
    const url = `${this.baseUrl}/_challenge/pow`;
    const headers = {
      'User-Agent': session.defaults.headers['User-Agent'],
      'Accept': '*/*',
      'Accept-Language': 'en-US,en;q=0.5',
      'Accept-Encoding': 'gzip, deflate, br',
      'Referer': `${this.baseUrl}/`,
      'Sec-Gpc': '1',
      'Sec-Fetch-Dest': 'empty',
      'Sec-Fetch-Mode': 'cors',
      'Sec-Fetch-Site': 'same-origin',
      'Priority': 'u=4',
      'Te': 'trailers'
    };

    const resp = await session.get(url, { headers });
    if (resp.status !== 200) {
      throw new Error(`Failed to get challenge: ${resp.status}`);
    }
    return resp.data; // assumed JSON
  }

  async solveChallenge(challenge) {
    const timestamp = challenge.Timestamp;
    const difficulty = challenge.Difficulty;
    // In original Python they used salt.encode('utf-8'), so we do same:
    const saltStr = challenge.Salt;
    const salt = Buffer.from(saltStr, 'utf8');
    const targetPrefix = '0'.repeat(difficulty);

    let nonce = 0;
    const startTime = Date.now() / 1000;

    while (true) {
      const passwordBuf = Buffer.from(`${timestamp}:${nonce}`, 'utf8');

      // Use argon2.hash with raw: true to get Buffer
      // Options mirror the Python call: time_cost=2, memory_cost=4096, parallelism=1, hash_len=32, type=ID
      const rawHash = await argon2.hash(passwordBuf, {
        salt,
        timeCost: 2,
        memoryCost: 4096,
        parallelism: 1,
        hashLength: 32,
        type: argon2.argon2id,
        raw: true
      }); // rawHash is a Buffer

      const hashHex = rawHash.toString('hex');

      if (hashHex.startsWith(targetPrefix)) {
        const elapsed = (Date.now() / 1000) - startTime;
        return {
          nonce: String(nonce),
          hashRate: elapsed > 0 ? nonce / elapsed : 0
        };
      }
      nonce += 1;

      // Optionally yield control every few iterations to be cooperative (not strictly necessary)
      if ((nonce & 0xfff) === 0) {
        // yield to event loop occasionally
        await new Promise((r) => setImmediate(r));
      }
    }
  }

  async verifySolution(session, challenge, solution) {
    const url = `${this.baseUrl}/_challenge/pow/verify`;
    const data = new URLSearchParams({
      timestamp: challenge.Timestamp,
      salt: challenge.Salt,
      nonce: solution.nonce,
      signature: challenge.Signature,
      hashrate: String(solution.hashRate)
    });

    const headers = {
      'User-Agent': session.defaults.headers['User-Agent'],
      'Accept': '*/*',
      'Accept-Language': 'en-US,en;q=0.5',
      'Accept-Encoding': 'gzip, deflate, br',
      'Referer': `${this.baseUrl}/`,
      'Origin': this.baseUrl,
      'Sec-Gpc': '1',
      'Sec-Fetch-Dest': 'empty',
      'Sec-Fetch-Mode': 'cors',
      'Sec-Fetch-Site': 'same-origin',
      'Priority': 'u=4',
      'Te': 'trailers',
      'Content-Type': 'application/x-www-form-urlencoded'
    };

    const resp = await session.post(url, data.toString(), { headers });
    if (resp.status !== 200) {
      throw new Error(`Verification failed: ${resp.status}`);
    }

    const body = (typeof resp.data === 'string') ? resp.data.trim() : String(resp.data).trim();

    if (body === '1') {
      // find cookie that contains '_____mcchallenge' in its name
      const jar = session._cookieJar;
      // jar.getCookies is callback-based; wrap with Promise
      const cookies = await new Promise((resolve, reject) => {
        jar.getCookies(this.baseUrl, (err, cookies) => {
          if (err) reject(err);
          else resolve(cookies || []);
        });
      });
      for (const c of cookies) {
        if (c.key && c.key.includes('_____mcchallenge')) {
          this.mcchallengeCookie = c.value;
          console.log(`saved challenge: ${this.mcchallengeCookie.substring(0, 20)}...`);
          break;
        }
      }
    }

    return body === '1';
  }

  async solvePowIfNeeded(session) {
    console.log('Solving PoW challenge...');
    const challenge = await this.getChallenge(session);
    console.log('Challenge received:', challenge);
    // await this._humanDelay(200, 200); // optional human-like delay
    const solution = await this.solveChallenge(challenge);
    // console.log('Solution found:', solution);
    // await this._humanDelay(2, 200);
    const success = await this.verifySolution(session, challenge, solution);

    if (success) {
      console.log('PoW solved successfully');
      return true;
    }
    console.log('PoW failed');
    return false;
  }
}


// Example usage (keeps same flow as your Python script)
(async () => {
  try {
    const a = new MargeService();
    const session = a._createSession();

    // Solve PoW if needed
    await a.solvePowIfNeeded(session);

    // Then check challenge-check page (like the Python example)
    const checkResp = await session.get('https://soyjak.st/challenge-check.html');
    console.log(checkResp.data);
  } catch (err) {
    console.error('Error:', err && err.stack ? err.stack : err);
  }
})();
Mahkhmood8

Mahkhmood8 commented on Oct 9, 2025

@Mahkhmood8
Author

Too much work to support that site, the firewall is too powerful

The issue you are facing , is the intergity-v2 blocking either the embeded browser or just fingerprint-ban(aka someone on the CHAN-APP got banned, and got eveyrone using the service banned )

Mahkhmood8

Mahkhmood8 commented on Oct 9, 2025

@Mahkhmood8
Author

I am really saddne by it, because I was planning on making more powerful bot , using an antidetect browser,

the captchas are too aids to train an llm on tbh

i have done it before btw
https://github.com/8chanjikwatkinsQQQQQEdwardArthurKane/8coon-cooner/

Mahkhmood8

Mahkhmood8 commented on Oct 9, 2025

@Mahkhmood8
Author
Image

I hate this captcha :(

if I had the skillset, I would have coded a simple
"detect the pepe" , and just type "pepe" and cick the "pepe"

another approch is to train a laguage model and detect some of the text,

but I dont really have the dataset,,

also do not need an LLM to solve it ,,

you can just use the "color range" that they use for "pepe" ,
which is just two base images

anyways , for what cost? So they replace the captcha the moment you start bot them

i ruined the element of surprised, could have used make a lot of users the repost the same message that would drive the pedophile-jannies insane

Mahkhmood8

Mahkhmood8 commented on Oct 9, 2025

@Mahkhmood8
Author

@moffatman sorry for the new captcha thing ,

I should have making the posting more subtle , like mimking real users or whatever -- or ban evaders, not appear as bots :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @moffatman@Mahkhmood8

        Issue actions

          soyjak added a new captcha o algo · Issue #280 · moffatman/chan