torn-cracking

Cracking helper with CORS bypass and pattern identification

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==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);
  })();
})();