torn-cracking

Cracking helper with CORS bypass and pattern identification

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         torn-cracking
// @namespace    torn-cracking
// @version      0.9
// @description  Cracking helper with CORS bypass and pattern identification
// @author       swrv [3069664]
// @match        *://www.torn.com/loader.php?sid=crimes*
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @license      mit
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @iconURL data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMTIwIDEyMCA5NjAgOTYwIj4KIDxwYXRoIGZpbGw9IiMzNTg0ZTQiIGQ9Im0xMjAgMzYwaDM2MHY3MjBoMjQwdi03MjBoMzYwdi0yNDBoLTk2MHoiLz4KPC9zdmc+Cg==
// ==/UserScript==

(function() {
  'use strict';

  let dbName = 'crackingDatabase';
  let storeName = 'wordsStores';
  let metadataStoreName = 'metadataStore';
  let wordsUrls = [
    'https://github.com/danielmiessler/SecLists/raw/master/Passwords/Common-Credentials/10-million-password-list-top-100000.txt',
    'https://github.com/danielmiessler/SecLists/raw/master/Passwords/Leaked-Databases/rockyou-75.txt',
    'https://github.com/danielmiessler/SecLists/raw/master/Miscellaneous/lang-english.txt',
  ];
  let workerScript = `
    self.onmessage = function(event) {
      let { pattern, words } = event.data;
      let regex = new RegExp('^' + pattern.replace(/\\*/g, '.').toLowerCase() + '$');
      let results = words.filter(word => regex.test(word.toLowerCase()));
      results = Array.from(new Set(results)); // Ensure unique results
      self.postMessage(results);
    };
  `;

  let processedPatterns = {};
  let isProcessing = false;

  function openDatabase() {
    return new Promise((resolve, reject) => {
      let request = indexedDB.open(dbName, 1);

      request.onupgradeneeded = function(event) {
        let db = event.target.result;
        if (!db.objectStoreNames.contains(storeName)) {
          let wordStore = db.createObjectStore(storeName, { keyPath: 'length' });
          wordStore.createIndex('words', 'words', { multiEntry: true });
        }
        if (!db.objectStoreNames.contains(metadataStoreName)) {
          db.createObjectStore(metadataStoreName, { keyPath: 'url' });
        }
      };

      request.onsuccess = function(event) {
        resolve(event.target.result);
      };

      request.onerror = function(event) {
        reject(event.target.errorCode);
      };
    });
  }

  function fetchWords() {
    return new Promise((resolve, reject) => {
      openDatabase().then(db => {
        let transaction = db.transaction(metadataStoreName, 'readonly');
        let store = transaction.objectStore(metadataStoreName);
        let metadataRequest = store.getAll();

        metadataRequest.onsuccess = function() {
          let metadata = metadataRequest.result;
          let urlsToFetch = wordsUrls.filter(url => !metadata.some(meta => meta.url === url));

          if (urlsToFetch.length === 0) {
            console.log('Words already cached. No need to fetch.');
            resolve();
            return;
          }

          let wordsByLength = {};
          let completedRequests = 0;

          urlsToFetch.forEach((url, index) => {
            console.log(`Fetching words from URL ${index + 1} of ${urlsToFetch.length}...`);
            GM_xmlhttpRequest({
              method: 'GET',
              url: url,
              onload: function(response) {
                let data = response.responseText;
                let newWords = data.split('\n').map(word => word.trim());
                newWords.forEach(word => {
                  let len = word.length;
                  if (!wordsByLength[len]) {
                    wordsByLength[len] = [];
                  }
                  wordsByLength[len].push(word);
                });
                console.log(`Completed fetching from URL ${index + 1}.`);

                completedRequests++;
                if (completedRequests === urlsToFetch.length) {
                  console.log('All URLs fetched. Storing words in IndexedDB...');
                  storeWords(db, wordsByLength, urlsToFetch).then(resolve).catch(reject);
                }
              },
              onerror: function(error) {
                console.error(`Error fetching URL ${index + 1}: `, error);
                reject(error);
              }
            });
          });
        };

        metadataRequest.onerror = function(event) {
          console.error('Error fetching metadata: ', event.target.errorCode);
          reject(event.target.errorCode);
        };
      }).catch(reject);
    });
  }

  function storeWords(db, wordsByLength, urls) {
    return new Promise((resolve, reject) => {
      let transaction = db.transaction([storeName, metadataStoreName], 'readwrite');
      let wordStore = transaction.objectStore(storeName);
      let metadataStore = transaction.objectStore(metadataStoreName);

      for (let length in wordsByLength) {
        wordStore.put({ length: parseInt(length), words: wordsByLength[length] });
      }
      urls.forEach(url => metadataStore.add({ url }));

      transaction.oncomplete = function() {
        console.log('Words stored in IndexedDB.');
        resolve();
      };

      transaction.onerror = function(event) {
        console.error('Error storing words: ', event.target.errorCode);
        reject(event.target.errorCode);
      };
    });
  }

  function findMatches(pattern, exactLength) {
    return new Promise((resolve, reject) => {
      openDatabase().then(db => {
        let transaction = db.transaction(storeName, 'readonly');
        let store = transaction.objectStore(storeName);
        let index = store.index('words');
        let request = store.get(exactLength);

        request.onsuccess = function(event) {
          let result = event.target.result;
          if (result) {
            let words = result.words;
            let workerBlob = new Blob([workerScript], { type: 'application/javascript' });
            let worker = new Worker(URL.createObjectURL(workerBlob));
            worker.onmessage = function(event) {
              resolve(event.data);
            };
            worker.postMessage({ pattern, words });
          } else {
            resolve([]);
          }
        };

        request.onerror = function(event) {
          reject(event.target.errorCode);
        };
      });
    });
  }

  function displayResults(results, element) {
    let resultsElement = $(element).find('.__results');
    if (resultsElement.length === 0) {
      resultsElement = $('<div class="__results" style="font-family:monospace;font-size:11px;padding:2px;background:black;color:white;text-align:center;position:absolute;z-index:999"></div>');
      $(element).prepend(resultsElement);
    }
    if (!results.length) {
      resultsElement.hide();
    } else {
      resultsElement.show();
      resultsElement.text(`${results.slice(0, 5).join(' ')}`);
    }
  }

  function identifyPatterns() {
    let patterns = [];
    $('.virtualItem___BLyAl').each(function(index) {
      let pattern = '';
      $(this).find('.charSlot___b_S9h').each(function() {
        let char = $(this).find('span').text().trim();
        if (char) {
          pattern += char.toLowerCase();
        } else {
          pattern += '*';
        }
      });
      if (pattern.includes('*') && !processedPatterns[`${pattern}-${index}`]) {
        patterns.push({ pattern, element: this, index });
        processedPatterns[`${pattern}-${index}`] = true;
      }
    });
    return patterns;
  }

  function processPatterns() {
    if (isProcessing) return;

    isProcessing = true;
    let patterns = identifyPatterns();

    (async function() {
      await Promise.all(patterns.map(async ({ pattern, element }) => {
        let results = await findMatches(pattern, pattern.length);
        displayResults(results, element);
      }));
      isProcessing = false;
    })();
  }

  // Initial execution
  (async function() {
    await fetchWords();
    setInterval(processPatterns, 1000);
  })();
})();