@@ -0,0 +0,0 @@ name: CI |
+0
-0
@@ -0,0 +0,0 @@ export interface GetTokenOptions { |
+0
-0
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ /// <reference types="node" /> |
+0
-0
@@ -0,0 +0,0 @@ "use strict"; |
+18
-14
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const crypto_1 = require("crypto"); | ||
| const alphabet = "abcdefghijklmnopqrstuvwxyz"; | ||
| let md5 = (0, crypto_1.createHash)("md5"); | ||
| function encrypt(data, key) { | ||
@@ -8,10 +10,11 @@ let salt = ""; | ||
| let dx = Buffer.alloc(0); | ||
| // Generate salt, as 8 random lowercase letters | ||
| salt = String.fromCharCode(...Array(8).fill(0).map(_ => Math.floor(Math.random() * 26) + 97)); | ||
| // Our final key and iv come from the key and salt being repeatedly hashed | ||
| // dx = md5(md5(md5(key + salt) + key + salt) + key + salt) | ||
| // For each round of hashing, we append the result to salted, resulting in a 96 character string | ||
| // The first 64 characters are the key, and the last 32 are the iv | ||
| salt = Array(8) | ||
| .fill(0) | ||
| .map((v) => alphabet[Math.floor(Math.random() * alphabet.length)]) | ||
| .join(""); // 8 random letters | ||
| data = | ||
| data + | ||
| Array(17 - (data.length % 16)).join(String.fromCharCode(16 - (data.length % 16))); // Padding (pkcs7?) | ||
| for (let x = 0; x < 3; x++) { | ||
| dx = (0, crypto_1.createHash)("md5") | ||
| dx = md5 | ||
| .update(Buffer.concat([ | ||
@@ -24,6 +27,6 @@ Buffer.from(dx), | ||
| salted += dx.toString("hex"); | ||
| md5 = (0, crypto_1.createHash)("md5"); | ||
| } | ||
| let aes = (0, crypto_1.createCipheriv)("aes-256-cbc", Buffer.from(salted.substring(0, 64), "hex"), // Key | ||
| Buffer.from(salted.substring(64, 64 + 32), "hex") // IV | ||
| ); | ||
| let aes = (0, crypto_1.createCipheriv)("aes-256-cbc", Buffer.from(salted, "hex").slice(0, 32), Buffer.from(salted, "hex").slice(32, 32 + 16)); | ||
| aes.setAutoPadding(false); | ||
| return JSON.stringify({ | ||
@@ -37,8 +40,9 @@ ct: aes.update(data, null, "base64") + aes.final("base64"), | ||
| let data = JSON.parse(rawData); | ||
| // We get our decryption key by doing the inverse of the encryption process | ||
| let dk = Buffer.concat([Buffer.from(key), Buffer.from(data.s, "hex")]); | ||
| let arr = [Buffer.from((0, crypto_1.createHash)("md5").update(dk).digest()).toString("hex")]; | ||
| let md5 = (0, crypto_1.createHash)("md5"); | ||
| let arr = [Buffer.from(md5.update(dk).digest()).toString("hex")]; | ||
| let result = arr[0]; | ||
| for (let x = 1; x < 3; x++) { | ||
| arr.push(Buffer.from((0, crypto_1.createHash)("md5") | ||
| md5 = (0, crypto_1.createHash)("md5"); | ||
| arr.push(Buffer.from(md5 | ||
| .update(Buffer.concat([Buffer.from(arr[x - 1], "hex"), dk])) | ||
@@ -48,3 +52,3 @@ .digest()).toString("hex")); | ||
| } | ||
| let aes = (0, crypto_1.createDecipheriv)("aes-256-cbc", Buffer.from(result.substring(0, 64), "hex"), Buffer.from(data.iv, "hex")); | ||
| let aes = (0, crypto_1.createDecipheriv)("aes-256-cbc", Buffer.from(result, "hex").slice(0, 32), Buffer.from(data.iv, "hex")); | ||
| return aes.update(data.ct, "base64", "utf8") + aes.final("utf8"); | ||
@@ -51,0 +55,0 @@ } |
+2
-32
@@ -1,2 +0,2 @@ | ||
| declare const baseFingerprint: { | ||
| declare function getFingerprint(canvasFp?: string, randomCanvasFp?: boolean): { | ||
| DNT: string; | ||
@@ -16,3 +16,3 @@ L: string; | ||
| PK: string; | ||
| CFP: string; | ||
| CFP: string | boolean; | ||
| FR: boolean; | ||
@@ -27,33 +27,4 @@ FOS: boolean; | ||
| }; | ||
| declare function getFingerprint(): { | ||
| DNT: string; | ||
| L: string; | ||
| D: number; | ||
| PR: number; | ||
| S: number[]; | ||
| AS: number[]; | ||
| TO: number; | ||
| SS: boolean; | ||
| LS: boolean; | ||
| IDB: boolean; | ||
| B: boolean; | ||
| ODB: boolean; | ||
| CPUC: string; | ||
| PK: string; | ||
| CFP: string; | ||
| FR: boolean; | ||
| FOS: boolean; | ||
| FB: boolean; | ||
| JSF: string[]; | ||
| P: string[]; | ||
| T: (number | boolean)[]; | ||
| H: number; | ||
| SWF: boolean; | ||
| }; | ||
| declare function prepareF(fingerprint: any): string; | ||
| declare function prepareFe(fingerprint: any): any[]; | ||
| declare function getEnhancedFingerprint(fp: typeof baseFingerprint, ua: string, opts: any): { | ||
| key: string; | ||
| value: any; | ||
| }[]; | ||
| declare const _default: { | ||
@@ -63,4 +34,3 @@ getFingerprint: typeof getFingerprint; | ||
| prepareFe: typeof prepareFe; | ||
| getEnhancedFingerprint: typeof getEnhancedFingerprint; | ||
| }; | ||
| export default _default; |
+307
-126
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const murmur_1 = require("./murmur"); | ||
| const crypto_1 = require("crypto"); | ||
| const pngjs_1 = require("pngjs"); | ||
| const baseFingerprint = { | ||
@@ -92,5 +91,7 @@ DNT: "unknown", | ||
| P: [ | ||
| "Chrome PDF Plugin::Portable Document Format::application/x-google-chrome-pdf~pdf", | ||
| "Chrome PDF Viewer::::application/pdf~pdf", | ||
| "Native Client::::application/x-nacl~,application/x-pnacl~", | ||
| 'Chrome PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf', | ||
| 'Chromium PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf', | ||
| 'Microsoft Edge PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf', | ||
| 'PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf', | ||
| 'WebKit built-in PDF::Portable Document Format::application/pdf~pdf,text/pdf~pdf' | ||
| ], | ||
@@ -102,17 +103,241 @@ T: [0, false, false], | ||
| const languages = [ | ||
| "af", "af-ZA", "ar", "ar-AE", "ar-BH", "ar-DZ", "ar-EG", "ar-IQ", "ar-JO", "ar-KW", "ar-LB", "ar-LY", "ar-MA", "ar-OM", "ar-QA", "ar-SA", | ||
| "ar-SY", "ar-TN", "ar-YE", "az", "az-AZ", "az-AZ", "be", "be-BY", "bg", "bg-BG", "bs-BA", "ca", "ca-ES", "cs", "cs-CZ", "cy", | ||
| "cy-GB", "da", "da-DK", "de", "de-AT", "de-CH", "de-DE", "de-LI", "de-LU", "dv", "dv-MV", "el", "el-GR", "en", "en-AU", "en-BZ", | ||
| "en-CA", "en-CB", "en-GB", "en-IE", "en-JM", "en-NZ", "en-PH", "en-TT", "en-US", "en-ZA", "en-ZW", "eo", "es", "es-AR", "es-BO", "es-CL", | ||
| "es-CO", "es-CR", "es-DO", "es-EC", "es-ES", "es-ES", "es-GT", "es-HN", "es-MX", "es-NI", "es-PA", "es-PE", "es-PR", "es-PY", "es-SV", "es-UY", | ||
| "es-VE", "et", "et-EE", "eu", "eu-ES", "fa", "fa-IR", "fi", "fi-FI", "fo", "fo-FO", "fr", "fr-BE", "fr-CA", "fr-CH", "fr-FR", | ||
| "fr-LU", "fr-MC", "gl", "gl-ES", "gu", "gu-IN", "he", "he-IL", "hi", "hi-IN", "hr", "hr-BA", "hr-HR", "hu", "hu-HU", "hy", | ||
| "hy-AM", "id", "id-ID", "is", "is-IS", "it", "it-CH", "it-IT", "ja", "ja-JP", "ka", "ka-GE", "kk", "kk-KZ", "kn", "kn-IN", | ||
| "ko", "ko-KR", "kok", "kok-IN", "ky", "ky-KG", "lt", "lt-LT", "lv", "lv-LV", "mi", "mi-NZ", "mk", "mk-MK", "mn", "mn-MN", | ||
| "mr", "mr-IN", "ms", "ms-BN", "ms-MY", "mt", "mt-MT", "nb", "nb-NO", "nl", "nl-BE", "nl-NL", "nn-NO", "ns", "ns-ZA", "pa", | ||
| "pa-IN", "pl", "pl-PL", "ps", "ps-AR", "pt", "pt-BR", "pt-PT", "qu", "qu-BO", "qu-EC", "qu-PE", "ro", "ro-RO", "ru", "ru-RU", | ||
| "sa", "sa-IN", "se", "se-FI", "se-FI", "se-FI", "se-NO", "se-NO", "se-NO", "se-SE", "se-SE", "se-SE", "sk", "sk-SK", "sl", "sl-SI", | ||
| "sq", "sq-AL", "sr-BA", "sr-BA", "sr-SP", "sr-SP", "sv", "sv-FI", "sv-SE", "sw", "sw-KE", "syr", "syr-SY", "ta", "ta-IN", "te", | ||
| "te-IN", "th", "th-TH", "tl", "tl-PH", "tn", "tn-ZA", "tr", "tr-TR", "tt", "tt-RU", "ts", "uk", "uk-UA", "ur", "ur-PK", | ||
| "uz", "uz-UZ", "uz-UZ", "vi", "vi-VN", "xh", "xh-ZA", "zh", "zh-CN", "zh-HK", "zh-MO", "zh-SG", "zh-TW", "zu", "zu-ZA" | ||
| "af", | ||
| "af-ZA", | ||
| "ar", | ||
| "ar-AE", | ||
| "ar-BH", | ||
| "ar-DZ", | ||
| "ar-EG", | ||
| "ar-IQ", | ||
| "ar-JO", | ||
| "ar-KW", | ||
| "ar-LB", | ||
| "ar-LY", | ||
| "ar-MA", | ||
| "ar-OM", | ||
| "ar-QA", | ||
| "ar-SA", | ||
| "ar-SY", | ||
| "ar-TN", | ||
| "ar-YE", | ||
| "az", | ||
| "az-AZ", | ||
| "az-AZ", | ||
| "be", | ||
| "be-BY", | ||
| "bg", | ||
| "bg-BG", | ||
| "bs-BA", | ||
| "ca", | ||
| "ca-ES", | ||
| "cs", | ||
| "cs-CZ", | ||
| "cy", | ||
| "cy-GB", | ||
| "da", | ||
| "da-DK", | ||
| "de", | ||
| "de-AT", | ||
| "de-CH", | ||
| "de-DE", | ||
| "de-LI", | ||
| "de-LU", | ||
| "dv", | ||
| "dv-MV", | ||
| "el", | ||
| "el-GR", | ||
| "en", | ||
| "en-AU", | ||
| "en-BZ", | ||
| "en-CA", | ||
| "en-CB", | ||
| "en-GB", | ||
| "en-IE", | ||
| "en-JM", | ||
| "en-NZ", | ||
| "en-PH", | ||
| "en-TT", | ||
| "en-US", | ||
| "en-ZA", | ||
| "en-ZW", | ||
| "eo", | ||
| "es", | ||
| "es-AR", | ||
| "es-BO", | ||
| "es-CL", | ||
| "es-CO", | ||
| "es-CR", | ||
| "es-DO", | ||
| "es-EC", | ||
| "es-ES", | ||
| "es-ES", | ||
| "es-GT", | ||
| "es-HN", | ||
| "es-MX", | ||
| "es-NI", | ||
| "es-PA", | ||
| "es-PE", | ||
| "es-PR", | ||
| "es-PY", | ||
| "es-SV", | ||
| "es-UY", | ||
| "es-VE", | ||
| "et", | ||
| "et-EE", | ||
| "eu", | ||
| "eu-ES", | ||
| "fa", | ||
| "fa-IR", | ||
| "fi", | ||
| "fi-FI", | ||
| "fo", | ||
| "fo-FO", | ||
| "fr", | ||
| "fr-BE", | ||
| "fr-CA", | ||
| "fr-CH", | ||
| "fr-FR", | ||
| "fr-LU", | ||
| "fr-MC", | ||
| "gl", | ||
| "gl-ES", | ||
| "gu", | ||
| "gu-IN", | ||
| "he", | ||
| "he-IL", | ||
| "hi", | ||
| "hi-IN", | ||
| "hr", | ||
| "hr-BA", | ||
| "hr-HR", | ||
| "hu", | ||
| "hu-HU", | ||
| "hy", | ||
| "hy-AM", | ||
| "id", | ||
| "id-ID", | ||
| "is", | ||
| "is-IS", | ||
| "it", | ||
| "it-CH", | ||
| "it-IT", | ||
| "ja", | ||
| "ja-JP", | ||
| "ka", | ||
| "ka-GE", | ||
| "kk", | ||
| "kk-KZ", | ||
| "kn", | ||
| "kn-IN", | ||
| "ko", | ||
| "ko-KR", | ||
| "kok", | ||
| "kok-IN", | ||
| "ky", | ||
| "ky-KG", | ||
| "lt", | ||
| "lt-LT", | ||
| "lv", | ||
| "lv-LV", | ||
| "mi", | ||
| "mi-NZ", | ||
| "mk", | ||
| "mk-MK", | ||
| "mn", | ||
| "mn-MN", | ||
| "mr", | ||
| "mr-IN", | ||
| "ms", | ||
| "ms-BN", | ||
| "ms-MY", | ||
| "mt", | ||
| "mt-MT", | ||
| "nb", | ||
| "nb-NO", | ||
| "nl", | ||
| "nl-BE", | ||
| "nl-NL", | ||
| "nn-NO", | ||
| "ns", | ||
| "ns-ZA", | ||
| "pa", | ||
| "pa-IN", | ||
| "pl", | ||
| "pl-PL", | ||
| "ps", | ||
| "ps-AR", | ||
| "pt", | ||
| "pt-BR", | ||
| "pt-PT", | ||
| "qu", | ||
| "qu-BO", | ||
| "qu-EC", | ||
| "qu-PE", | ||
| "ro", | ||
| "ro-RO", | ||
| "ru", | ||
| "ru-RU", | ||
| "sa", | ||
| "sa-IN", | ||
| "se", | ||
| "se-FI", | ||
| "se-FI", | ||
| "se-FI", | ||
| "se-NO", | ||
| "se-NO", | ||
| "se-NO", | ||
| "se-SE", | ||
| "se-SE", | ||
| "se-SE", | ||
| "sk", | ||
| "sk-SK", | ||
| "sl", | ||
| "sl-SI", | ||
| "sq", | ||
| "sq-AL", | ||
| "sr-BA", | ||
| "sr-BA", | ||
| "sr-SP", | ||
| "sr-SP", | ||
| "sv", | ||
| "sv-FI", | ||
| "sv-SE", | ||
| "sw", | ||
| "sw-KE", | ||
| "syr", | ||
| "syr-SY", | ||
| "ta", | ||
| "ta-IN", | ||
| "te", | ||
| "te-IN", | ||
| "th", | ||
| "th-TH", | ||
| "tl", | ||
| "tl-PH", | ||
| "tn", | ||
| "tn-ZA", | ||
| "tr", | ||
| "tr-TR", | ||
| "tt", | ||
| "tt-RU", | ||
| "ts", | ||
| "uk", | ||
| "uk-UA", | ||
| "ur", | ||
| "ur-PK", | ||
| "uz", | ||
| "uz-UZ", | ||
| "uz-UZ", | ||
| "vi", | ||
| "vi-VN", | ||
| "xh", | ||
| "xh-ZA", | ||
| "zh", | ||
| "zh-CN", | ||
| "zh-HK", | ||
| "zh-MO", | ||
| "zh-SG", | ||
| "zh-TW", | ||
| "zu", | ||
| "zu-ZA", | ||
| ]; | ||
@@ -138,31 +363,70 @@ let screenRes = [ | ||
| // Get fingerprint | ||
| function getFingerprint() { | ||
| let fingerprint = { ...baseFingerprint }; // Create a copy of the base fingerprint | ||
| function getFingerprint(canvasFp, randomCanvasFp) { | ||
| var _a; | ||
| let fingerprint = Object.assign({}, baseFingerprint); // Create a copy of the base fingerprint | ||
| // Randomization time! | ||
| fingerprint["DNT"] = "unknown"; | ||
| fingerprint["DNT"] = "unknown"; //Math.round(Math.random()); | ||
| fingerprint["L"] = languages[Math.floor(Math.random() * languages.length)]; | ||
| fingerprint["D"] = [8, 24][Math.floor(Math.random() * 2)]; | ||
| fingerprint["PR"] = Math.round(Math.random() * 100) / 100 * 2 + 0.5; | ||
| fingerprint["S"] = randomScreenRes(); | ||
| fingerprint["AS"] = fingerprint.S; | ||
| fingerprint["TO"] = (Math.floor(Math.random() * 24) - 12) * 60; | ||
| fingerprint["SS"] = Math.random() > 0.5; | ||
| fingerprint["LS"] = Math.random() > 0.5; | ||
| fingerprint["IDB"] = Math.random() > 0.5; | ||
| fingerprint["B"] = Math.random() > 0.5; | ||
| fingerprint["ODB"] = Math.random() > 0.5; | ||
| fingerprint["CPUC"] = "unknown"; | ||
| fingerprint["PK"] = "Win32"; | ||
| fingerprint["CFP"] = "canvas winding:yes~canvas fp:data:image/png;base64," + (0, crypto_1.randomBytes)(128).toString("base64"); | ||
| fingerprint["D"] = [24, 32][Math.floor(Math.random() * 2)]; // common value only: 24bit/32bit | ||
| fingerprint["PR"] = [1, 1.25, 1.5, 1.75][Math.floor(Math.random() * 4)]; // common value only: 1, 1.25, 1.5, 1.75 | ||
| fingerprint["S"] = randomScreenRes().map(x => x / fingerprint["PR"]); // change screen res to match pixel ratio | ||
| fingerprint["AS"] = fingerprint["S"]; //[fingerprint["S"][0], fingerprint["S"][1] - 40] | ||
| fingerprint["TO"] = (Math.floor(Math.random() * 24) - 12) * 60; // timezone SHOULD be based on current IP | ||
| fingerprint["SS"] = true; //Math.random() > 0.5; | ||
| fingerprint["LS"] = true; //Math.random() > 0.5; | ||
| fingerprint["IDB"] = true; //Math.random() > 0.5; | ||
| fingerprint["B"] = false; // IE-only signature, SHOULD NOT EXIST //Math.random() > 0.5; | ||
| fingerprint["ODB"] = true; // WebSQL, MUST be disabled after November 7, 2023 (Chromium 119). Might TODO base on UA. //Math.random() > 0.5; | ||
| fingerprint["CPUC"] = "unknown"; /*["68K", "Alpha", "PPC", "x86", "Other", "unknown"][ | ||
| Math.floor(Math.random() * 5) | ||
| ];*/ | ||
| fingerprint["PK"] = "Win32"; // This SHOULD be based on User Agent. | ||
| /*[ | ||
| "HP-UX", | ||
| "Mac68K", | ||
| "MacPPC", | ||
| "SunOS", | ||
| "Win16", | ||
| "Win32", | ||
| "WinCE", | ||
| ][Math.floor(Math.random() * 7)];*/ | ||
| let rdCanvas; | ||
| if (typeof randomCanvasFp === "undefined" || randomCanvasFp) { | ||
| // attempt to randomize canvas fingerprint by generating a random 300x150 PNG image | ||
| let png = new pngjs_1.PNG({ | ||
| height: 150, | ||
| width: 300, | ||
| }); | ||
| for (let y = 0; y < png.height; y++) { | ||
| for (let x = 0; x < png.width; x++) { | ||
| let idx = (png.width * y + x) << 2; | ||
| png.data[idx] = Math.floor(Math.random() * 256); | ||
| png.data[idx + 1] = Math.floor(Math.random() * 256); | ||
| png.data[idx + 2] = Math.floor(Math.random() * 256); | ||
| png.data[idx + 3] = 0xFF; | ||
| } | ||
| } | ||
| var buffer = pngjs_1.PNG.sync.write(png, { | ||
| colorType: 6, | ||
| bitDepth: 8 | ||
| }); | ||
| rdCanvas = `data:image/png;base64,${buffer.toString("base64")}`; | ||
| } | ||
| fingerprint["CFP"] = (_a = canvasFp !== null && canvasFp !== void 0 ? canvasFp : rdCanvas) !== null && _a !== void 0 ? _a : false; // We CAN randomize data, block canvas fingerprinting, or BYOP | ||
| /*`canvas winding:yes~canvas fp:data:image/png;base64,${Buffer.from( | ||
| Math.random().toString() | ||
| ).toString("base64")}`;*/ //canvasFp || ''; // Canvas Fingerprint | ||
| fingerprint["FR"] = false; // Fake Resolution | ||
| fingerprint["FOS"] = false; // Fake Operating System | ||
| fingerprint["FB"] = false; // Fake Browser | ||
| fingerprint["JSF"] = fingerprint["JSF"].filter(() => Math.random() > 0.5); | ||
| fingerprint["P"] = fingerprint["P"].filter(() => Math.random() > 0.5); | ||
| fingerprint["T"] = [ | ||
| // Standard Windows fonts | ||
| fingerprint["JSF"] = ['Arial', 'Arial Black', 'Arial Narrow', 'Book Antiqua', 'Bookman Old Style', 'Calibri', 'Cambria', 'Cambria Math', 'Century', 'Century Gothic', 'Century Schoolbook', 'Comic Sans MS', 'Consolas', 'Courier', 'Courier New', 'Garamond', 'Georgia', 'Helvetica', 'Impact', 'Lucida Bright', 'Lucida Calligraphy', 'Lucida Console', 'Lucida Fax', 'Lucida Handwriting', 'Lucida Sans', 'Lucida Sans Typewriter', 'Lucida Sans Unicode', 'Microsoft Sans Serif', 'Monotype Corsiva', 'MS Gothic', 'MS PGothic', 'MS Reference Sans Serif', 'MS Sans Serif', 'MS Serif', 'Palatino Linotype', 'Segoe Print', 'Segoe Script', 'Segoe UI', 'Segoe UI Light', 'Segoe UI Semibold', 'Segoe UI Symbol', 'Tahoma', 'Times', 'Times New Roman', 'Trebuchet MS', 'Verdana', 'Wingdings', 'Wingdings 2', 'Wingdings 3']; //fingerprint["JSF"].filter(() => Math.random() > 0.5); | ||
| //fingerprint["P"] = fingerprint["P"].filter(() => Math.random() > 0.5); | ||
| let randomizeTouch = Math.random() > 0.5; | ||
| fingerprint["T"] = randomizeTouch ? [ | ||
| Math.floor(Math.random() * 8), | ||
| Math.random() > 0.5, | ||
| Math.random() > 0.5, | ||
| ]; | ||
| fingerprint["H"] = 2 ** Math.floor(Math.random() * 6); | ||
| false, | ||
| false //Math.random() > 0.5, | ||
| ] : [0, false, false]; // Touch Support [maxTouchPoints, touchEvent emit support, is touchStart listened] | ||
| fingerprint["H"] = Math.pow(2, Math.floor(Math.random() * 3)); | ||
| fingerprint["SWF"] = fingerprint["SWF"]; // RIP Flash | ||
@@ -219,84 +483,2 @@ return fingerprint; | ||
| } | ||
| let baseEnhancedFingerprint = { | ||
| "webgl_extensions": "ANGLE_instanced_arrays;EXT_blend_minmax;EXT_color_buffer_half_float;EXT_disjoint_timer_query;EXT_float_blend;EXT_frag_depth;EXT_shader_texture_lod;EXT_texture_compression_bptc;EXT_texture_compression_rgtc;EXT_texture_filter_anisotropic;EXT_sRGB;KHR_parallel_shader_compile;OES_element_index_uint;OES_fbo_render_mipmap;OES_standard_derivatives;OES_texture_float;OES_texture_float_linear;OES_texture_half_float;OES_texture_half_float_linear;OES_vertex_array_object;WEBGL_color_buffer_float;WEBGL_compressed_texture_s3tc;WEBGL_compressed_texture_s3tc_srgb;WEBGL_debug_renderer_info;WEBGL_debug_shaders;WEBGL_depth_texture;WEBGL_draw_buffers;WEBGL_lose_context;WEBGL_multi_draw", | ||
| "webgl_extensions_hash": "58a5a04a5bef1a78fa88d5c5098bd237", | ||
| "webgl_renderer": "WebKit WebGL", | ||
| "webgl_vendor": "WebKit", | ||
| "webgl_version": "WebGL 1.0 (OpenGL ES 2.0 Chromium)", | ||
| "webgl_shading_language_version": "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)", | ||
| "webgl_aliased_line_width_range": "[1, 1]", | ||
| "webgl_aliased_point_size_range": "[0.125, 8192]", | ||
| "webgl_antialiasing": "yes", | ||
| "webgl_bits": "8,8,24,8,8,0", | ||
| "webgl_max_params": "16,32,8192,261,8192,16,8192,32,32,16,256", | ||
| "webgl_max_viewport_dims": "[8192, 8192]", | ||
| "webgl_unmasked_vendor": "Google Inc.", | ||
| "webgl_unmasked_renderer": "Google SwiftShader", | ||
| "webgl_vsf_params": "23,127,127,23,127,127,23,127,127", | ||
| "webgl_vsi_params": "0,31,30,0,31,30,0,31,30", | ||
| "webgl_fsf_params": "23,127,127,23,127,127,23,127,127", | ||
| "webgl_fsi_params": "0,31,30,0,31,30,0,31,30", | ||
| "webgl_hash_webgl": null, | ||
| "user_agent_data_brands": "Not/A)Brand,Google Chrome,Chromium", | ||
| "user_agent_data_mobile": null, | ||
| "navigator_connection_downlink": null, | ||
| "navigator_connection_downlink_max": null, | ||
| "network_info_rtt": null, | ||
| "network_info_save_data": false, | ||
| "network_info_rtt_type": null, | ||
| "screen_pixel_depth": 24, | ||
| "navigator_device_memory": 0.5, | ||
| "navigator_languages": "en-US,fr-BE,fr,en-BE,en", | ||
| "window_inner_width": 0, | ||
| "window_inner_height": 0, | ||
| "window_outer_width": 2195, | ||
| "window_outer_height": 1195, | ||
| "browser_detection_firefox": false, | ||
| "browser_detection_brave": false, | ||
| "audio_codecs": "{\"ogg\":\"probably\",\"mp3\":\"probably\",\"wav\":\"probably\",\"m4a\":\"maybe\",\"aac\":\"probably\"}", | ||
| "video_codecs": "{\"ogg\":\"probably\",\"h264\":\"probably\",\"webm\":\"probably\",\"mpeg4v\":\"\",\"mpeg4a\":\"\",\"theora\":\"\"}", | ||
| "media_query_dark_mode": true, | ||
| "headless_browser_phantom": false, | ||
| "headless_browser_selenium": false, | ||
| "headless_browser_nightmare_js": false, | ||
| "document__referrer": "https://www.roblox.com/", | ||
| "window__ancestor_origins": [ | ||
| "https://www.roblox.com", | ||
| ], | ||
| "window__tree_index": [ | ||
| 0 | ||
| ], | ||
| "window__tree_structure": "[[]]", | ||
| "window__location_href": "https://roblox-api.arkoselabs.com/v2/1.5.4/enforcement.cd12da708fe6cbe6e068918c38de2ad9.html#476068BF-9607-4799-B53D-966BE98E2B81", | ||
| "client_config__sitedata_location_href": "https://www.roblox.com/arkose/iframe", | ||
| "client_config__surl": "https://roblox-api.arkoselabs.com", | ||
| "client_config__language": null, | ||
| "navigator_battery_charging": true, | ||
| "audio_fingerprint": (124.04347527516074 + Math.random() * 0.001 - 0.0005).toString(), | ||
| }; | ||
| function getEnhancedFingerprint(fp, ua, opts) { | ||
| let fingerprint = { ...baseEnhancedFingerprint }; | ||
| fingerprint.webgl_extensions = fingerprint.webgl_extensions.split(";").filter(_ => Math.random() > 0.5).join(";"); | ||
| fingerprint.webgl_extensions_hash = (0, murmur_1.default)(fingerprint.webgl_extensions, 0); | ||
| fingerprint.screen_pixel_depth = fp.D; | ||
| fingerprint.navigator_languages = fp.L; | ||
| fingerprint.window_outer_height = fp.S[0]; | ||
| fingerprint.window_outer_width = fp.S[1]; | ||
| fingerprint.window_inner_height = fp.S[0]; | ||
| fingerprint.window_inner_width = fp.S[1]; | ||
| fingerprint.screen_pixel_depth = fp.D; | ||
| fingerprint.browser_detection_firefox = !!ua.match(/Firefox\/\d+/); | ||
| fingerprint.browser_detection_brave = !!ua.match(/Brave\/\d+/); | ||
| fingerprint.media_query_dark_mode = Math.random() > 0.9; | ||
| fingerprint.webgl_hash_webgl = (0, murmur_1.default)(Object.entries(fingerprint).filter(([k, v]) => k.startsWith("webgl_") && k != "webgl_hash_webgl").map(([k, v]) => v).join(","), 0); | ||
| fingerprint.client_config__language = opts.language || null; | ||
| fingerprint.window__location_href = `${opts.surl}/v2/${opts.pkey}/1.5.4/enforcement.${(0, crypto_1.randomBytes)(16).toString("hex")}.html`; | ||
| if (opts.site) { | ||
| fingerprint.document__referrer = opts.site; | ||
| fingerprint.window__ancestor_origins = [opts.site]; | ||
| fingerprint.client_config__sitedata_location_href = opts.site; | ||
| } | ||
| fingerprint.client_config__surl = opts.surl || "https://client-api.arkoselabs.com"; | ||
| return Object.entries(fingerprint).map(([k, v]) => ({ key: k, value: v })); | ||
| } | ||
| exports.default = { | ||
@@ -306,3 +488,2 @@ getFingerprint, | ||
| prepareFe, | ||
| getEnhancedFingerprint, | ||
| }; |
+0
-0
@@ -0,0 +0,0 @@ /// <reference types="node" /> |
+0
-0
@@ -0,0 +0,0 @@ "use strict"; |
+0
-0
| export * from "./api"; | ||
| export * from "./session"; |
+0
-0
@@ -0,0 +0,0 @@ "use strict"; |
+0
-0
| declare var x64hash128: (t: any, r: any) => string; | ||
| export default x64hash128; |
+0
-0
@@ -0,0 +0,0 @@ "use strict"; |
+0
-0
@@ -0,0 +0,0 @@ import { GetTokenResult } from "./api"; |
+0
-0
@@ -0,0 +0,0 @@ "use strict"; |
+0
-0
@@ -0,0 +0,0 @@ interface TimestampData { |
+0
-0
@@ -0,0 +0,0 @@ "use strict"; |
+0
-0
@@ -0,0 +0,0 @@ Copyright (c) 2023 noahcoolboy |
+30
-41
| { | ||
| "name": "ebic", | ||
| "version": "1.0.5", | ||
| "description": "Ebic Condos packages", | ||
| "author": "Diego Miguel", | ||
| "license": "MIT", | ||
| "keywords": [ | ||
| "condo captcha" | ||
| ], | ||
| "main": "lib/index.js", | ||
| "types": "lib/index.d.ts", | ||
| "scripts": { | ||
| "build": "rimraf lib && tsc", | ||
| "test": "node test/test.js", | ||
| "benchmark": "node test/benchmark.js", | ||
| "roblox": "node test/roblox.js" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^17.0.42", | ||
| "@types/pngjs": "^6.0.1", | ||
| "rimraf": "^3.0.2", | ||
| "typescript": "^4.7.4" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/badaimweeb/funcaptcha.git" | ||
| }, | ||
| "dependencies": { | ||
| "http2-wrapper": "^2.2.0", | ||
| "pngjs": "^7.0.0", | ||
| "socks": "^2.7.1", | ||
| "undici": "^5.22.1", | ||
| "windmouse": "^1.0.5" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/badaimweeb/funcaptcha/issues" | ||
| }, | ||
| "homepage": "https://github.com/badaimweeb/funcaptcha#readme", | ||
| "directories": { | ||
| "lib": "lib", | ||
| "test": "test" | ||
| } | ||
| "name": "ebic", | ||
| "version": "1.0.7", | ||
| "description": "A library used to interact with funcaptchas.", | ||
| "author": "noahcoolboy", | ||
| "license": "MIT", | ||
| "keywords": [ | ||
| "funcaptcha" | ||
| ], | ||
| "main": "lib/index.js", | ||
| "types": "lib/index.d.ts", | ||
| "scripts": { | ||
| "build": "rimraf lib && tsc", | ||
| "test": "node test/test.js", | ||
| "benchmark": "node test/benchmark.js", | ||
| "roblox": "node test/roblox.js" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^17.0.42", | ||
| "@types/pngjs": "^6.0.1", | ||
| "rimraf": "^3.0.2", | ||
| "typescript": "^4.7.4" | ||
| }, | ||
| "repository": "github:badaimweeb/funcaptcha", | ||
| "dependencies": { | ||
| "http2-wrapper": "^2.2.0", | ||
| "pngjs": "^7.0.0", | ||
| "socks": "^2.7.1", | ||
| "undici": "^5.22.1", | ||
| "windmouse": "^1.0.5" | ||
| } | ||
| } |
+0
-0
@@ -0,0 +0,0 @@ # funcaptcha |
+0
-0
@@ -0,0 +0,0 @@ import request from "./http"; |
+0
-0
@@ -0,0 +0,0 @@ import request from "./http"; |
+23
-13
@@ -9,2 +9,5 @@ import { createHash, createCipheriv, createDecipheriv } from "crypto"; | ||
| const alphabet = "abcdefghijklmnopqrstuvwxyz"; | ||
| let md5 = createHash("md5"); | ||
| function encrypt(data: string, key: string): string { | ||
@@ -15,11 +18,14 @@ let salt = ""; | ||
| // Generate salt, as 8 random lowercase letters | ||
| salt = String.fromCharCode(...Array(8).fill(0).map(_ => Math.floor(Math.random() * 26) + 97)) | ||
| salt = Array(8) | ||
| .fill(0) | ||
| .map((v) => alphabet[Math.floor(Math.random() * alphabet.length)]) | ||
| .join(""); // 8 random letters | ||
| data = | ||
| data + | ||
| Array(17 - (data.length % 16)).join( | ||
| String.fromCharCode(16 - (data.length % 16)) | ||
| ); // Padding (pkcs7?) | ||
| // Our final key and iv come from the key and salt being repeatedly hashed | ||
| // dx = md5(md5(md5(key + salt) + key + salt) + key + salt) | ||
| // For each round of hashing, we append the result to salted, resulting in a 96 character string | ||
| // The first 64 characters are the key, and the last 32 are the iv | ||
| for (let x = 0; x < 3; x++) { | ||
| dx = createHash("md5") | ||
| dx = md5 | ||
| .update( | ||
@@ -35,2 +41,3 @@ Buffer.concat([ | ||
| salted += dx.toString("hex"); | ||
| md5 = createHash("md5"); | ||
| } | ||
@@ -40,5 +47,6 @@ | ||
| "aes-256-cbc", | ||
| Buffer.from(salted.substring(0, 64), "hex"), // Key | ||
| Buffer.from(salted.substring(64, 64 + 32), "hex") // IV | ||
| Buffer.from(salted, "hex").slice(0, 32), | ||
| Buffer.from(salted, "hex").slice(32, 32 + 16) | ||
| ); | ||
| aes.setAutoPadding(false); | ||
@@ -55,11 +63,13 @@ return JSON.stringify({ | ||
| // We get our decryption key by doing the inverse of the encryption process | ||
| let dk = Buffer.concat([Buffer.from(key), Buffer.from(data.s, "hex")]); | ||
| let arr = [Buffer.from(createHash("md5").update(dk).digest()).toString("hex")]; | ||
| let md5 = createHash("md5"); | ||
| let arr = [Buffer.from(md5.update(dk).digest()).toString("hex")]; | ||
| let result = arr[0]; | ||
| for (let x = 1; x < 3; x++) { | ||
| md5 = createHash("md5"); | ||
| arr.push( | ||
| Buffer.from( | ||
| createHash("md5") | ||
| md5 | ||
| .update(Buffer.concat([Buffer.from(arr[x - 1], "hex"), dk])) | ||
@@ -74,3 +84,3 @@ .digest() | ||
| "aes-256-cbc", | ||
| Buffer.from(result.substring(0, 64), "hex"), | ||
| Buffer.from(result, "hex").slice(0, 32), | ||
| Buffer.from(data.iv, "hex") | ||
@@ -77,0 +87,0 @@ ); |
+344
-134
@@ -1,5 +0,28 @@ | ||
| import x64hash128 from "./murmur"; | ||
| import { randomBytes } from "crypto"; | ||
| import { PNG } from "pngjs"; | ||
| const baseFingerprint = { | ||
| const baseFingerprint: { | ||
| DNT: string; | ||
| L: string; | ||
| D: number; | ||
| PR: number; | ||
| S: number[]; | ||
| AS: number[]; | ||
| TO: number; | ||
| SS: boolean; | ||
| LS: boolean; | ||
| IDB: boolean; | ||
| B: boolean; | ||
| ODB: boolean; | ||
| CPUC: string; | ||
| PK: string; | ||
| CFP: string | boolean; | ||
| FR: boolean; | ||
| FOS: boolean; | ||
| FB: boolean; | ||
| JSF: string[]; | ||
| P: string[]; | ||
| T: (number | boolean)[]; | ||
| H: number; | ||
| SWF: boolean; | ||
| } = { | ||
| DNT: "unknown", // Do not track On/Off | Previous Value: 1 | ||
@@ -91,8 +114,10 @@ L: "en-US", // Browser language | ||
| "Wingdings 3", | ||
| ], // Available fonts | ||
| ], // Checked fonts | ||
| P: [ | ||
| "Chrome PDF Plugin::Portable Document Format::application/x-google-chrome-pdf~pdf", | ||
| "Chrome PDF Viewer::::application/pdf~pdf", | ||
| "Native Client::::application/x-nacl~,application/x-pnacl~", | ||
| ], // Plugins | ||
| 'Chrome PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf', | ||
| 'Chromium PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf', | ||
| 'Microsoft Edge PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf', | ||
| 'PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf', | ||
| 'WebKit built-in PDF::Portable Document Format::application/pdf~pdf,text/pdf~pdf' | ||
| ], // Plugins (standard and CONSTANT) | ||
| T: [0, false, false], // Touch screen (maxTouchPoints, TouchEvent event listener support, ontouchstart support) | ||
@@ -104,17 +129,241 @@ H: 24, // Cpu threads | ||
| const languages = [ | ||
| "af", "af-ZA", "ar", "ar-AE", "ar-BH", "ar-DZ", "ar-EG", "ar-IQ", "ar-JO", "ar-KW", "ar-LB", "ar-LY", "ar-MA", "ar-OM", "ar-QA", "ar-SA", | ||
| "ar-SY", "ar-TN", "ar-YE", "az", "az-AZ", "az-AZ", "be", "be-BY", "bg", "bg-BG", "bs-BA", "ca", "ca-ES", "cs", "cs-CZ", "cy", | ||
| "cy-GB", "da", "da-DK", "de", "de-AT", "de-CH", "de-DE", "de-LI", "de-LU", "dv", "dv-MV", "el", "el-GR", "en", "en-AU", "en-BZ", | ||
| "en-CA", "en-CB", "en-GB", "en-IE", "en-JM", "en-NZ", "en-PH", "en-TT", "en-US", "en-ZA", "en-ZW", "eo", "es", "es-AR", "es-BO", "es-CL", | ||
| "es-CO", "es-CR", "es-DO", "es-EC", "es-ES", "es-ES", "es-GT", "es-HN", "es-MX", "es-NI", "es-PA", "es-PE", "es-PR", "es-PY", "es-SV", "es-UY", | ||
| "es-VE", "et", "et-EE", "eu", "eu-ES", "fa", "fa-IR", "fi", "fi-FI", "fo", "fo-FO", "fr", "fr-BE", "fr-CA", "fr-CH", "fr-FR", | ||
| "fr-LU", "fr-MC", "gl", "gl-ES", "gu", "gu-IN", "he", "he-IL", "hi", "hi-IN", "hr", "hr-BA", "hr-HR", "hu", "hu-HU", "hy", | ||
| "hy-AM", "id", "id-ID", "is", "is-IS", "it", "it-CH", "it-IT", "ja", "ja-JP", "ka", "ka-GE", "kk", "kk-KZ", "kn", "kn-IN", | ||
| "ko", "ko-KR", "kok", "kok-IN", "ky", "ky-KG", "lt", "lt-LT", "lv", "lv-LV", "mi", "mi-NZ", "mk", "mk-MK", "mn", "mn-MN", | ||
| "mr", "mr-IN", "ms", "ms-BN", "ms-MY", "mt", "mt-MT", "nb", "nb-NO", "nl", "nl-BE", "nl-NL", "nn-NO", "ns", "ns-ZA", "pa", | ||
| "pa-IN", "pl", "pl-PL", "ps", "ps-AR", "pt", "pt-BR", "pt-PT", "qu", "qu-BO", "qu-EC", "qu-PE", "ro", "ro-RO", "ru", "ru-RU", | ||
| "sa", "sa-IN", "se", "se-FI", "se-FI", "se-FI", "se-NO", "se-NO", "se-NO", "se-SE", "se-SE", "se-SE", "sk", "sk-SK", "sl", "sl-SI", | ||
| "sq", "sq-AL", "sr-BA", "sr-BA", "sr-SP", "sr-SP", "sv", "sv-FI", "sv-SE", "sw", "sw-KE", "syr", "syr-SY", "ta", "ta-IN", "te", | ||
| "te-IN", "th", "th-TH", "tl", "tl-PH", "tn", "tn-ZA", "tr", "tr-TR", "tt", "tt-RU", "ts", "uk", "uk-UA", "ur", "ur-PK", | ||
| "uz", "uz-UZ", "uz-UZ", "vi", "vi-VN", "xh", "xh-ZA", "zh", "zh-CN", "zh-HK", "zh-MO", "zh-SG", "zh-TW", "zu", "zu-ZA" | ||
| "af", | ||
| "af-ZA", | ||
| "ar", | ||
| "ar-AE", | ||
| "ar-BH", | ||
| "ar-DZ", | ||
| "ar-EG", | ||
| "ar-IQ", | ||
| "ar-JO", | ||
| "ar-KW", | ||
| "ar-LB", | ||
| "ar-LY", | ||
| "ar-MA", | ||
| "ar-OM", | ||
| "ar-QA", | ||
| "ar-SA", | ||
| "ar-SY", | ||
| "ar-TN", | ||
| "ar-YE", | ||
| "az", | ||
| "az-AZ", | ||
| "az-AZ", | ||
| "be", | ||
| "be-BY", | ||
| "bg", | ||
| "bg-BG", | ||
| "bs-BA", | ||
| "ca", | ||
| "ca-ES", | ||
| "cs", | ||
| "cs-CZ", | ||
| "cy", | ||
| "cy-GB", | ||
| "da", | ||
| "da-DK", | ||
| "de", | ||
| "de-AT", | ||
| "de-CH", | ||
| "de-DE", | ||
| "de-LI", | ||
| "de-LU", | ||
| "dv", | ||
| "dv-MV", | ||
| "el", | ||
| "el-GR", | ||
| "en", | ||
| "en-AU", | ||
| "en-BZ", | ||
| "en-CA", | ||
| "en-CB", | ||
| "en-GB", | ||
| "en-IE", | ||
| "en-JM", | ||
| "en-NZ", | ||
| "en-PH", | ||
| "en-TT", | ||
| "en-US", | ||
| "en-ZA", | ||
| "en-ZW", | ||
| "eo", | ||
| "es", | ||
| "es-AR", | ||
| "es-BO", | ||
| "es-CL", | ||
| "es-CO", | ||
| "es-CR", | ||
| "es-DO", | ||
| "es-EC", | ||
| "es-ES", | ||
| "es-ES", | ||
| "es-GT", | ||
| "es-HN", | ||
| "es-MX", | ||
| "es-NI", | ||
| "es-PA", | ||
| "es-PE", | ||
| "es-PR", | ||
| "es-PY", | ||
| "es-SV", | ||
| "es-UY", | ||
| "es-VE", | ||
| "et", | ||
| "et-EE", | ||
| "eu", | ||
| "eu-ES", | ||
| "fa", | ||
| "fa-IR", | ||
| "fi", | ||
| "fi-FI", | ||
| "fo", | ||
| "fo-FO", | ||
| "fr", | ||
| "fr-BE", | ||
| "fr-CA", | ||
| "fr-CH", | ||
| "fr-FR", | ||
| "fr-LU", | ||
| "fr-MC", | ||
| "gl", | ||
| "gl-ES", | ||
| "gu", | ||
| "gu-IN", | ||
| "he", | ||
| "he-IL", | ||
| "hi", | ||
| "hi-IN", | ||
| "hr", | ||
| "hr-BA", | ||
| "hr-HR", | ||
| "hu", | ||
| "hu-HU", | ||
| "hy", | ||
| "hy-AM", | ||
| "id", | ||
| "id-ID", | ||
| "is", | ||
| "is-IS", | ||
| "it", | ||
| "it-CH", | ||
| "it-IT", | ||
| "ja", | ||
| "ja-JP", | ||
| "ka", | ||
| "ka-GE", | ||
| "kk", | ||
| "kk-KZ", | ||
| "kn", | ||
| "kn-IN", | ||
| "ko", | ||
| "ko-KR", | ||
| "kok", | ||
| "kok-IN", | ||
| "ky", | ||
| "ky-KG", | ||
| "lt", | ||
| "lt-LT", | ||
| "lv", | ||
| "lv-LV", | ||
| "mi", | ||
| "mi-NZ", | ||
| "mk", | ||
| "mk-MK", | ||
| "mn", | ||
| "mn-MN", | ||
| "mr", | ||
| "mr-IN", | ||
| "ms", | ||
| "ms-BN", | ||
| "ms-MY", | ||
| "mt", | ||
| "mt-MT", | ||
| "nb", | ||
| "nb-NO", | ||
| "nl", | ||
| "nl-BE", | ||
| "nl-NL", | ||
| "nn-NO", | ||
| "ns", | ||
| "ns-ZA", | ||
| "pa", | ||
| "pa-IN", | ||
| "pl", | ||
| "pl-PL", | ||
| "ps", | ||
| "ps-AR", | ||
| "pt", | ||
| "pt-BR", | ||
| "pt-PT", | ||
| "qu", | ||
| "qu-BO", | ||
| "qu-EC", | ||
| "qu-PE", | ||
| "ro", | ||
| "ro-RO", | ||
| "ru", | ||
| "ru-RU", | ||
| "sa", | ||
| "sa-IN", | ||
| "se", | ||
| "se-FI", | ||
| "se-FI", | ||
| "se-FI", | ||
| "se-NO", | ||
| "se-NO", | ||
| "se-NO", | ||
| "se-SE", | ||
| "se-SE", | ||
| "se-SE", | ||
| "sk", | ||
| "sk-SK", | ||
| "sl", | ||
| "sl-SI", | ||
| "sq", | ||
| "sq-AL", | ||
| "sr-BA", | ||
| "sr-BA", | ||
| "sr-SP", | ||
| "sr-SP", | ||
| "sv", | ||
| "sv-FI", | ||
| "sv-SE", | ||
| "sw", | ||
| "sw-KE", | ||
| "syr", | ||
| "syr-SY", | ||
| "ta", | ||
| "ta-IN", | ||
| "te", | ||
| "te-IN", | ||
| "th", | ||
| "th-TH", | ||
| "tl", | ||
| "tl-PH", | ||
| "tn", | ||
| "tn-ZA", | ||
| "tr", | ||
| "tr-TR", | ||
| "tt", | ||
| "tt-RU", | ||
| "ts", | ||
| "uk", | ||
| "uk-UA", | ||
| "ur", | ||
| "ur-PK", | ||
| "uz", | ||
| "uz-UZ", | ||
| "uz-UZ", | ||
| "vi", | ||
| "vi-VN", | ||
| "xh", | ||
| "xh-ZA", | ||
| "zh", | ||
| "zh-CN", | ||
| "zh-HK", | ||
| "zh-MO", | ||
| "zh-SG", | ||
| "zh-TW", | ||
| "zu", | ||
| "zu-ZA", | ||
| ]; | ||
@@ -142,34 +391,82 @@ | ||
| // Get fingerprint | ||
| function getFingerprint() { | ||
| function getFingerprint(canvasFp?: string, randomCanvasFp?: boolean) { | ||
| let fingerprint = { ...baseFingerprint }; // Create a copy of the base fingerprint | ||
| // Randomization time! | ||
| fingerprint["DNT"] = "unknown"; | ||
| fingerprint["DNT"] = "unknown"; //Math.round(Math.random()); | ||
| fingerprint["L"] = languages[Math.floor(Math.random() * languages.length)]; | ||
| fingerprint["D"] = [8, 24][ | ||
| fingerprint["D"] = [24, 32][ | ||
| Math.floor(Math.random() * 2) | ||
| ]; | ||
| fingerprint["PR"] = Math.round(Math.random() * 100) / 100 * 2 + 0.5; | ||
| fingerprint["S"] = randomScreenRes(); | ||
| fingerprint["AS"] = fingerprint.S; | ||
| fingerprint["TO"] = (Math.floor(Math.random() * 24) - 12) * 60; | ||
| fingerprint["SS"] = Math.random() > 0.5; | ||
| fingerprint["LS"] = Math.random() > 0.5; | ||
| fingerprint["IDB"] = Math.random() > 0.5; | ||
| fingerprint["B"] = Math.random() > 0.5; | ||
| fingerprint["ODB"] = Math.random() > 0.5; | ||
| fingerprint["CPUC"] = "unknown"; | ||
| fingerprint["PK"] = "Win32" | ||
| fingerprint["CFP"] = "canvas winding:yes~canvas fp:data:image/png;base64," + randomBytes(128).toString("base64"); | ||
| ]; // common value only: 24bit/32bit | ||
| fingerprint["PR"] = [1, 1.25, 1.5, 1.75][ | ||
| Math.floor(Math.random() * 4) | ||
| ]; // common value only: 1, 1.25, 1.5, 1.75 | ||
| fingerprint["S"] = randomScreenRes().map(x => x / fingerprint["PR"]); // change screen res to match pixel ratio | ||
| fingerprint["AS"] = fingerprint["S"]; //[fingerprint["S"][0], fingerprint["S"][1] - 40] | ||
| fingerprint["TO"] = (Math.floor(Math.random() * 24) - 12) * 60; // timezone SHOULD be based on current IP | ||
| fingerprint["SS"] = true; //Math.random() > 0.5; | ||
| fingerprint["LS"] = true; //Math.random() > 0.5; | ||
| fingerprint["IDB"] = true; //Math.random() > 0.5; | ||
| fingerprint["B"] = false; // IE-only signature, SHOULD NOT EXIST //Math.random() > 0.5; | ||
| fingerprint["ODB"] = true; // WebSQL, MUST be disabled after November 7, 2023 (Chromium 119). Might TODO base on UA. //Math.random() > 0.5; | ||
| fingerprint["CPUC"] = "unknown"; /*["68K", "Alpha", "PPC", "x86", "Other", "unknown"][ | ||
| Math.floor(Math.random() * 5) | ||
| ];*/ | ||
| fingerprint["PK"] = "Win32" // This SHOULD be based on User Agent. | ||
| /*[ | ||
| "HP-UX", | ||
| "Mac68K", | ||
| "MacPPC", | ||
| "SunOS", | ||
| "Win16", | ||
| "Win32", | ||
| "WinCE", | ||
| ][Math.floor(Math.random() * 7)];*/ | ||
| let rdCanvas: string; | ||
| if (typeof randomCanvasFp === "undefined" || randomCanvasFp) { | ||
| // attempt to randomize canvas fingerprint by generating a random 300x150 PNG image | ||
| let png = new PNG({ | ||
| height: 150, | ||
| width: 300, | ||
| }); | ||
| for (let y = 0; y < png.height; y++) { | ||
| for (let x = 0; x < png.width; x++) { | ||
| let idx = (png.width * y + x) << 2; | ||
| png.data[idx] = Math.floor(Math.random() * 256); | ||
| png.data[idx + 1] = Math.floor(Math.random() * 256); | ||
| png.data[idx + 2] = Math.floor(Math.random() * 256); | ||
| png.data[idx + 3] = 0xFF; | ||
| } | ||
| } | ||
| var buffer = PNG.sync.write(png, { | ||
| colorType: 6, | ||
| bitDepth: 8 | ||
| }); | ||
| rdCanvas = `data:image/png;base64,${buffer.toString("base64")}`; | ||
| } | ||
| fingerprint["CFP"] = canvasFp ?? rdCanvas ?? false; // We CAN randomize data, block canvas fingerprinting, or BYOP | ||
| /*`canvas winding:yes~canvas fp:data:image/png;base64,${Buffer.from( | ||
| Math.random().toString() | ||
| ).toString("base64")}`;*/ //canvasFp || ''; // Canvas Fingerprint | ||
| fingerprint["FR"] = false; // Fake Resolution | ||
| fingerprint["FOS"] = false; // Fake Operating System | ||
| fingerprint["FB"] = false; // Fake Browser | ||
| fingerprint["JSF"] = fingerprint["JSF"].filter(() => Math.random() > 0.5); | ||
| fingerprint["P"] = fingerprint["P"].filter(() => Math.random() > 0.5); | ||
| fingerprint["T"] = [ | ||
| // Standard Windows fonts | ||
| fingerprint["JSF"] = ['Arial', 'Arial Black', 'Arial Narrow', 'Book Antiqua', 'Bookman Old Style', 'Calibri', 'Cambria', 'Cambria Math', 'Century', 'Century Gothic', 'Century Schoolbook', 'Comic Sans MS', 'Consolas', 'Courier', 'Courier New', 'Garamond', 'Georgia', 'Helvetica', 'Impact', 'Lucida Bright', 'Lucida Calligraphy', 'Lucida Console', 'Lucida Fax', 'Lucida Handwriting', 'Lucida Sans', 'Lucida Sans Typewriter', 'Lucida Sans Unicode', 'Microsoft Sans Serif', 'Monotype Corsiva', 'MS Gothic', 'MS PGothic', 'MS Reference Sans Serif', 'MS Sans Serif', 'MS Serif', 'Palatino Linotype', 'Segoe Print', 'Segoe Script', 'Segoe UI', 'Segoe UI Light', 'Segoe UI Semibold', 'Segoe UI Symbol', 'Tahoma', 'Times', 'Times New Roman', 'Trebuchet MS', 'Verdana', 'Wingdings', 'Wingdings 2', 'Wingdings 3']; //fingerprint["JSF"].filter(() => Math.random() > 0.5); | ||
| //fingerprint["P"] = fingerprint["P"].filter(() => Math.random() > 0.5); | ||
| let randomizeTouch = Math.random() > 0.5; | ||
| fingerprint["T"] = randomizeTouch ? [ | ||
| Math.floor(Math.random() * 8), | ||
| Math.random() > 0.5, | ||
| Math.random() > 0.5, | ||
| ]; | ||
| fingerprint["H"] = 2 ** Math.floor(Math.random() * 6); | ||
| false, //Math.random() > 0.5, | ||
| false //Math.random() > 0.5, | ||
| ] : [0, false, false]; // Touch Support [maxTouchPoints, touchEvent emit support, is touchStart listened] | ||
| fingerprint["H"] = 2 ** Math.floor(Math.random() * 3); | ||
| fingerprint["SWF"] = fingerprint["SWF"]; // RIP Flash | ||
@@ -210,2 +507,3 @@ | ||
| } | ||
| return fe; | ||
@@ -232,89 +530,2 @@ } | ||
| let baseEnhancedFingerprint = { | ||
| "webgl_extensions": "ANGLE_instanced_arrays;EXT_blend_minmax;EXT_color_buffer_half_float;EXT_disjoint_timer_query;EXT_float_blend;EXT_frag_depth;EXT_shader_texture_lod;EXT_texture_compression_bptc;EXT_texture_compression_rgtc;EXT_texture_filter_anisotropic;EXT_sRGB;KHR_parallel_shader_compile;OES_element_index_uint;OES_fbo_render_mipmap;OES_standard_derivatives;OES_texture_float;OES_texture_float_linear;OES_texture_half_float;OES_texture_half_float_linear;OES_vertex_array_object;WEBGL_color_buffer_float;WEBGL_compressed_texture_s3tc;WEBGL_compressed_texture_s3tc_srgb;WEBGL_debug_renderer_info;WEBGL_debug_shaders;WEBGL_depth_texture;WEBGL_draw_buffers;WEBGL_lose_context;WEBGL_multi_draw", | ||
| "webgl_extensions_hash": "58a5a04a5bef1a78fa88d5c5098bd237", | ||
| "webgl_renderer": "WebKit WebGL", | ||
| "webgl_vendor": "WebKit", | ||
| "webgl_version": "WebGL 1.0 (OpenGL ES 2.0 Chromium)", | ||
| "webgl_shading_language_version": "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)", | ||
| "webgl_aliased_line_width_range": "[1, 1]", | ||
| "webgl_aliased_point_size_range": "[0.125, 8192]", | ||
| "webgl_antialiasing": "yes", | ||
| "webgl_bits": "8,8,24,8,8,0", | ||
| "webgl_max_params": "16,32,8192,261,8192,16,8192,32,32,16,256", | ||
| "webgl_max_viewport_dims": "[8192, 8192]", | ||
| "webgl_unmasked_vendor": "Google Inc.", | ||
| "webgl_unmasked_renderer": "Google SwiftShader", | ||
| "webgl_vsf_params": "23,127,127,23,127,127,23,127,127", | ||
| "webgl_vsi_params": "0,31,30,0,31,30,0,31,30", | ||
| "webgl_fsf_params": "23,127,127,23,127,127,23,127,127", | ||
| "webgl_fsi_params": "0,31,30,0,31,30,0,31,30", | ||
| "webgl_hash_webgl": null, // TODO | ||
| "user_agent_data_brands": "Not/A)Brand,Google Chrome,Chromium", | ||
| "user_agent_data_mobile": null, | ||
| "navigator_connection_downlink": null, | ||
| "navigator_connection_downlink_max": null, | ||
| "network_info_rtt": null, | ||
| "network_info_save_data": false, | ||
| "network_info_rtt_type": null, | ||
| "screen_pixel_depth": 24, | ||
| "navigator_device_memory": 0.5, | ||
| "navigator_languages": "en-US,fr-BE,fr,en-BE,en", | ||
| "window_inner_width": 0, | ||
| "window_inner_height": 0, | ||
| "window_outer_width": 2195, | ||
| "window_outer_height": 1195, | ||
| "browser_detection_firefox": false, | ||
| "browser_detection_brave": false, | ||
| "audio_codecs": "{\"ogg\":\"probably\",\"mp3\":\"probably\",\"wav\":\"probably\",\"m4a\":\"maybe\",\"aac\":\"probably\"}", | ||
| "video_codecs": "{\"ogg\":\"probably\",\"h264\":\"probably\",\"webm\":\"probably\",\"mpeg4v\":\"\",\"mpeg4a\":\"\",\"theora\":\"\"}", | ||
| "media_query_dark_mode": true, | ||
| "headless_browser_phantom": false, | ||
| "headless_browser_selenium": false, | ||
| "headless_browser_nightmare_js": false, | ||
| "document__referrer": "https://www.roblox.com/", | ||
| "window__ancestor_origins": [ | ||
| "https://www.roblox.com", | ||
| ], | ||
| "window__tree_index": [ | ||
| 0 | ||
| ], | ||
| "window__tree_structure": "[[]]", | ||
| "window__location_href": "https://roblox-api.arkoselabs.com/v2/1.5.4/enforcement.cd12da708fe6cbe6e068918c38de2ad9.html#476068BF-9607-4799-B53D-966BE98E2B81", | ||
| "client_config__sitedata_location_href": "https://www.roblox.com/arkose/iframe", | ||
| "client_config__surl": "https://roblox-api.arkoselabs.com", | ||
| "client_config__language": null, | ||
| "navigator_battery_charging": true, | ||
| "audio_fingerprint": (124.04347527516074 + Math.random() * 0.001 - 0.0005).toString(), | ||
| } | ||
| function getEnhancedFingerprint(fp: typeof baseFingerprint, ua: string, opts: any) { | ||
| let fingerprint = { ...baseEnhancedFingerprint }; | ||
| fingerprint.webgl_extensions = fingerprint.webgl_extensions.split(";").filter(_ => Math.random() > 0.5).join(";"); | ||
| fingerprint.webgl_extensions_hash = x64hash128(fingerprint.webgl_extensions, 0); | ||
| fingerprint.screen_pixel_depth = fp.D; | ||
| fingerprint.navigator_languages = fp.L; | ||
| fingerprint.window_outer_height = fp.S[0]; | ||
| fingerprint.window_outer_width = fp.S[1]; | ||
| fingerprint.window_inner_height = fp.S[0]; | ||
| fingerprint.window_inner_width = fp.S[1]; | ||
| fingerprint.screen_pixel_depth = fp.D; | ||
| fingerprint.browser_detection_firefox = !!ua.match(/Firefox\/\d+/) | ||
| fingerprint.browser_detection_brave = !!ua.match(/Brave\/\d+/) | ||
| fingerprint.media_query_dark_mode = Math.random() > 0.9; | ||
| fingerprint.webgl_hash_webgl = x64hash128(Object.entries(fingerprint).filter(([k, v]) => k.startsWith("webgl_") && k != "webgl_hash_webgl").map(([k, v]) => v).join(","), 0); | ||
| fingerprint.client_config__language = opts.language || null; | ||
| fingerprint.window__location_href = `${opts.surl}/v2/${opts.pkey}/1.5.4/enforcement.${randomBytes(16).toString("hex")}.html` | ||
| if (opts.site) { | ||
| fingerprint.document__referrer = opts.site; | ||
| fingerprint.window__ancestor_origins = [opts.site]; | ||
| fingerprint.client_config__sitedata_location_href = opts.site; | ||
| } | ||
| fingerprint.client_config__surl = opts.surl || "https://client-api.arkoselabs.com"; | ||
| return Object.entries(fingerprint).map(([k, v]) => ({ key: k, value: v })); | ||
| } | ||
| export default { | ||
@@ -324,3 +535,2 @@ getFingerprint, | ||
| prepareFe, | ||
| getEnhancedFingerprint, | ||
| }; |
+0
-0
@@ -0,0 +0,0 @@ import * as http2 from "http2-wrapper"; |
+0
-0
| export * from "./api"; | ||
| export * from "./session"; |
+0
-0
@@ -0,0 +0,0 @@ // MurmurHash3 related functions |
+26
-3
@@ -154,7 +154,30 @@ import { GetTokenResult } from "./api"; | ||
| getEmbedUrl(): string { | ||
| // infer game version from rawToken | ||
| let gameVersion = "1.12.1"; | ||
| if (this.tokenRaw) { | ||
| gameVersion = this.tokenRaw.challenge_url_cdn.match(/ec-game-core\/bootstrap\/(.*)\/standard/)?.[1] ?? gameVersion; | ||
| } | ||
| let ti = this.tokenInfo; | ||
| let newQuery = { | ||
| session: ti.token, | ||
| r: ti.r, | ||
| meta: ti.meta, | ||
| metabgclr: ti.metabgclr, | ||
| metaiconclr: ti.metaiconclr, | ||
| maintxtclr: ti.maintxtclr, | ||
| guitextcolor: ti.guitextcolor, | ||
| pk: ti.pk, | ||
| at: ti.at, | ||
| ag: ti.ag, | ||
| cdn_url: ti.cdn_url, | ||
| lurl: ti.lurl, | ||
| surl: ti.surl, | ||
| smurl: ti.smurl, | ||
| theme: "default" | ||
| } | ||
| //https://client-api.arkoselabs.com/fc/assets/ec-game-core/game-core/1.12.0/standard/index.html | ||
| return `${this.tokenInfo.surl}/fc/assets/ec-game-core/game-core/1.12.0/standard/index.html?${util.constructFormData( | ||
| this.tokenInfo | ||
| )}`; | ||
| return `${this.tokenInfo.surl}/fc/assets/ec-game-core/game-core/${gameVersion}/standard/index.html?${util.constructFormData(newQuery)}`; | ||
| } | ||
| } |
+0
-0
@@ -0,0 +0,0 @@ import fingerprint from "./fingerprint"; |
@@ -0,0 +0,0 @@ let fun = require("../lib"); |
+0
-0
@@ -0,0 +0,0 @@ // Optional test for roblox detection |
+0
-0
@@ -0,0 +0,0 @@ const fun = require("../lib"); |
+0
-0
@@ -0,0 +0,0 @@ { |
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
Unidentified License
LicenseSomething that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Unidentified License
LicenseSomething that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
173206
1.35%4606
9.25%1
Infinity%1
Infinity%4
33.33%