diff --git a/humanoidReqHandler.js b/humanoidReqHandler.js index c51270c..610c0b9 100644 --- a/humanoidReqHandler.js +++ b/humanoidReqHandler.js @@ -5,7 +5,7 @@ const Response = require("./response"); class HumanoidReqHandler { - constructor(ignoreHttpErrors = true) { + constructor() { this.cookieJar = rpn.jar() this._userAgentList = fs.readFileSync(__dirname + "/ua.text").toString().split("\n"); this.UA = this._getRandomUA(); // Set UserAgent @@ -67,7 +67,6 @@ class HumanoidReqHandler { // Send the request let res = await rpn(url, currConfig); - console.log(res) return new Response( res.statusCode, res.statusMessage,res.headers, diff --git a/index.js b/index.js index afff87e..9144025 100644 --- a/index.js +++ b/index.js @@ -5,8 +5,8 @@ const HumanoidReqHandler = require("./humanoidReqHandler") class Humanoid extends HumanoidReqHandler { // TODO: Implement c'tor params: autoRetry=false, maxRetries=3 - constructor(ignoreHttpErrors=true) { - super(ignoreHttpErrors) + constructor() { + super() this._getRandomTimeout = () => Math.floor(Math.random() * (7000 - 5000 + 1)) + 5000; this.timeout = undefined; // this.autoRetry = autoRetry; @@ -40,25 +40,34 @@ class Humanoid extends HumanoidReqHandler { } } - async sendRequestAndSolve(url, method=undefined, headers=undefined, ignoreNoChallenge=false) { - } - + // async sendRequestAndSolve(url, method=undefined, headers=undefined, ignoreNoChallenge=false) { + // } + // async get(url, queryString=undefined, headers=undefined) { + return await this.sendRequest(url, "GET", queryString, headers) } - async post(url, postBody=undefined, headers=undefined) { + async post(url, postBody=undefined, headers=undefined, dataType=undefined) { + return await this.sendRequest(url, "POST", postBody, headers, dataType) } async sendRequest(url, method=undefined, data=undefined, headers=undefined, dataType=undefined) { let response = await super.sendRequest(url, method, data, headers, dataType); + console.log(`Got ${response.statusCode}`) if (response.statusCode === 503 && this.isChallengeInResponse(response.body)) { - return await this._bypassJSChallenge(response); + let challengeResponse = await this._bypassJSChallenge(response); + // Session is definitely challenged + challengeResponse.isSessionChallenged = true; + // If we got a 200, mark challenge and solved and return + challengeResponse.isChallengeSolved = challengeResponse.statusCode === 200; + return challengeResponse; } + return response; } async _bypassJSChallenge(response) { let {...solution} = Solver.solveChallenge(response); - let timeout = Solver._extractTimeoutFromScript(response.data) || this._getRandomTimeout(); + let timeout = Solver._extractTimeoutFromScript(response.body) || this._getRandomTimeout(); if (![solution.vc, solution.pass, solution.answer, solution.origin].every(elem => !!elem)) { throw Error(`Failed to Extract one or more necessary values. Values obtained: @@ -74,11 +83,13 @@ class Humanoid extends HumanoidReqHandler { headers["Referer"] = response.origin; // Examine this and continue - let responseForChal = await this.sendRequest(answerUrl, "GET", answerObj, headers) - + return await this.sendRequest(answerUrl, "GET", answerObj, headers); } } } let humanoid = new Humanoid(); -humanoid.sendRequest("https://canyoupwn.me/") \ No newline at end of file +humanoid.sendRequest("https://canyoupwn.me/") + .then(res => { + console.log(res) + }) diff --git a/solver.js b/solver.js index a35e3b7..94b4bbe 100644 --- a/solver.js +++ b/solver.js @@ -7,7 +7,7 @@ class Solver { static _extractTimeoutFromScript(html) { let $ = cheerio.load(html); - let script = $("script"); + let script = $("script").html(); let match = script.match(/,\s[0-9]0{3}\);/g); if (match) { match = match[0].replace(/,|\s|\)|;/g, ""); @@ -45,39 +45,49 @@ class Solver { for (let ans of answerMutations) { let operator = ans.slice(0,2); let expr = ans.slice(3); - currResult = Solver._operateOnResult(operator, expr, currResult); + currResult = this._operateOnResult(operator, expr, currResult); } return currResult; } + static _parseChallenge(matches) { + // Perform the necessary parsing on both challenge parts + let [challengeInit, challengeMutations] = [...matches]; + // Perform the necessary parsing + challengeInit = challengeInit.replace(/[;}]/g, ""); + challengeMutations = challengeMutations + .split(";") + .map(s => s.match(/(.=.)?(\(\(!\+).*/g)) + .filter(s => s !== null) + .map(s => s[0]) + + return challengeInit, challengeMutations; + } + + static _matchChallengeFromScript(script) { + let testMatches = script.match(/(.=\+)?(\(\(!\+).*/g); // Match the challenge part + if (testMatches.length === 2) { + return testMatches; + } + throw Error("Failed to match JS challenge with Regular Expressions") + } + static solveChallenge(response) { - // TODO: We need the length of the URL without the protocol or forward slash - // TODO: Origin == Referer, Host == t.length to add to the answer - let {html, host, origin} = {html: response.data, host: response.host, origin: response.origin}; - let answerDeclaration, answerMutations, answer; - let script = Solver._extractChallengeFromHTML(html); - let [vc, pass] = [...Solver._extractInputValuesFromHTML(html)]; + let {html, host, origin} = {html: response.body, host: response.host, origin: response.origin}; + let script = this._extractChallengeFromHTML(html); + let [vc, pass] = [...this._extractInputValuesFromHTML(html)]; try { // Parse only the actual math challenge parts from the script tag and assign them - let testMatches = script.match(/(.=\+)?(\(\(!\+).*/g); // Match the challenge part - if (testMatches.length === 2) { - [answerDeclaration, answerMutations] = [...testMatches]; - // Perform the necessary parsing - answerDeclaration = answerDeclaration.replace(/[;}]/g, ""); - answerMutations = answerMutations - .split(";") - .map(s => s.match(/(.=.)?(\(\(!\+).*/g)) - .filter(s => s !== null) - .map(s => s[0]) - answer = Solver._buildAnswer(answerMutations, safeEval(answerDeclaration)); - answer = parseFloat(answer.toFixed(10)) + host.length; - return {vc: vc, pass: pass, answer: answer, origin: origin} - } + let challengeMatches = this._matchChallengeFromScript(script); + let [challengeInit, challengeMutations] = this._parseChallenge(challengeMatches); + let answer = this._buildAnswer(challengeMutations, safeEval(challengeInit)); + answer = parseFloat(answer.toFixed(10)) + host.length; + + return {vc: vc, pass: pass, answer: answer, origin: origin} } catch (err) { throw Error(`Could not solve or parse JavaScript challenge. Caused due to error:\n${err}`); } - throw Error("Failed to match JS challenge with Regular Expressions") } } diff --git a/tests.js b/tests.js index 762366f..e69de29 100644 --- a/tests.js +++ b/tests.js @@ -1,20 +0,0 @@ -const request = require("request-promise-native"); -const tough = require("tough-cookie"); -const Cookie = tough.Cookie; - -let cookieJar = request.jar() - -options = { - jar: cookieJar, - resolveWithFullResponse: true -} - -async function roflol() { - await request("http://localhost:5000/setc", options) - console.log(cookieJar) - cookieJar = request.jar() - console.log(cookieJar) - // await request("http://localhost:5000/setc", options) -} - -roflol() \ No newline at end of file