अपडेट पर वापस जाएँ
New releaseSep 4, 2026

hate_crack v2.36.1

TrustedSec टीम द्वारा Hashcat के माध्यम से क्रैकिंग कार्यप्रणालियों को स्वचालित करने के लिए एक उपकरण।

साझा करें
  ___ ___         __             _________                       __
 /   |   \_____ _/  |_  ____     \_   ___ \____________    ____ |  | __
/    ~    \__  \\   __\/ __ \    /    \  \/\_  __ \__  \ _/ ___\|  |/ /
\    Y    // __ \|  | \  ___/    \     \____|  | \// __ \\  \___|    <
 \___|_  /(____  /__|  \___  >____\______  /|__|  (____  /\___  >__|_ \
       \/      \/          \/_____/      \/            \/     \/     \/

इंस्टॉलेशन

सोर्स से इंस्टॉल करना ही एकमात्र समर्थित तरीका है। hate_crack PyPI पर वितरित नहीं किया जाता: pip install hate-crack एक 0.0.0 प्लेसहोल्डर पर रिज़ॉल्व होता है जो जानबूझकर विफल होता है और वापस यहीं इंगित करता है। यह नाम केवल इसलिए रखा गया है ताकि कोई और इसके अंतर्गत मिलता-जुलता पैकेज प्रकाशित न कर सके — देखें packaging/pypi-placeholder/

1. hashcat इंस्टॉल करें

Hashcat इंस्टॉल होना चाहिए और आपके PATH में उपलब्ध होना चाहिए:

Ubuntu/Kali:```bash sudo apt-get install -y hashcat

macOS (Homebrew):```bash
brew install hashcat

या https://hashcat.net/hashcat/ से पहले से बना बाइनरी डाउनलोड करें और config.json में hcatPath को उसके स्थान पर सेट करें।

2. hate_crack डाउनलोड करें

सबमॉड्यूल के साथ क्लोन करें (hashcat-utils, princeprocessor, pcfg_cracker, Corporate_Masks, और वैकल्पिक रूप से omen के लिए आवश्यक):```bash git clone --recurse-submodules https://github.com/trustedsec/hate_crack.git cd hate_crack

यदि आपने सबमॉड्यूल के बिना क्लोन किया है, तो उन्हें इनिशियलाइज़ करें:```bash
git submodule update --init --recursive

फिर ज़रूरत पड़ने पर कॉन्फ़िगरेशन को कस्टमाइज़ करें। hate_crack दो कॉन्फ़िग फ़ाइलों का उपयोग करता है, जिनमें से प्रत्येक सेटिंग्स का एक अलग सेट रखती है:

  • config.json — wordlist पाथ, मास्क, नियम, ट्यूनिंग, potfile, hashcat पाथ, कैंडिडेट सीमाएँ, नोटिफ़िकेशन टॉगल, CLI प्रेफ़रेंस डिफ़ॉल्ट (35 सेटिंग्स)।
  • .env — केवल थर्ड-पार्टी इंटीग्रेशन सेटिंग्स: Hashview और Hashmob क्रेडेंशियल्स, Pushover क्रेडेंशियल्स, Ollama, और pipal (14 सेटिंग्स)। git द्वारा ट्रैक नहीं किया जाता, मोड 0600 पर बनाया जाता है।

यह विभाजन एक कारण से वहाँ है: .env वह फ़ाइल है जिसमें सीक्रेट्स हो सकते हैं। थर्ड-पार्टी सेवाओं के क्रेडेंशियल्स और कॉन्फ़िगरेशन अनट्रैक्ड, 0600 फ़ाइल में जाते हैं; hate_crack जो कुछ भी लोकली करता है वह config.json में रहता है, जिसे शेयर करना, diff करना और अपने नोट्स में चेक-इन करना सुरक्षित है। यही कारण है कि Pushover क्रेडेंशियल्स .env में हैं जबकि Pushover on/off टॉगल config.json में हैं — टॉगल लोकल प्रेफ़रेंस हैं, सीक्रेट्स नहीं।

प्रत्येक key का ठीक एक ही घर है। दूसरी फ़ाइल में रखी key को अनदेखा कर दिया जाता है, और hate_crack एक चेतावनी प्रिंट करता है जिसमें उस फ़ाइल का नाम होता है जिसमें वह belongs करती है। किसी भी key को एक बार के रन के लिए उसका environment variable export करके ओवरराइड किया जा सकता है। अधिकांश उपयोगकर्ता इस चरण को छोड़ सकते हैं क्योंकि डिफ़ॉल्ट पाथ out-of-the-box काम करते हैं।

config.json स्थायी और first-class है — यह deprecated नहीं है और इसके लिए कोई removal timeline नहीं है। केवल इंटीग्रेशन सेटिंग्स ही स्थानांतरित हुई हैं।

एकल config.json से अपग्रेड कर रहे हैं? hate_crack पहले रन पर इसे आपके लिए माइग्रेट कर देता है: इंटीग्रेशन सेटिंग्स को एक नई 0600 .env में कॉपी किया जाता है, फिर config.json से हटा दिया जाता है ताकि दोनों फ़ाइलें उन पर दावा न करें। यह प्रिंट करता है कि कौन सी keys स्थानांतरित हुईं (उनके मान कभी नहीं), और इसे छूने से पहले आपके मूल को config.json.pre-split.bak के रूप में सहेजता है। config.json में बाकी सब कुछ बिल्कुल वैसा ही छोड़ दिया जाता है, key क्रम सहित।

पहला रन: hate_crack आपके लिए दोनों फ़ाइलें बना देता है, इसलिए करने के लिए कुछ नहीं है। इसके बजाय .env को हाथ से सेट करने के लिए, ट्रैक किए गए टेम्पलेट को कॉपी करें:```bash cp .env.example .env chmod 600 .env

`.env.example` कमिट किया जाता है और हर क्रेडेंशियल कुंजी खाली के साथ भेजा जाता है। `.env` स्वयं **कभी** कमिट नहीं किया जाना चाहिए — यह gitignored है, इसके सामान्य बैकअप स्पेलिंग्स के साथ, और hate_crack इसे हमेशा मोड `0600` (केवल मालिक पढ़/लिख सकता है) पर बनाता है। `.env.example` स्कीमा से जनरेट किया जाता है; `hate_crack/config_schema.py` को बदलने के बाद इसे `uv run python -m hate_crack.config_writer` के साथ पुनः जनरेट करें।

### 3. निर्भरताएँ और hate_crack इंस्टॉल करें

सबसे आसान तरीका है `make` (या `make install`) चलाना, जो आपके OS का स्वतः पता लगाता है और इंस्टॉल करता है:
- बाहरी निर्भरताएँ (p7zip, transmission-daemon / transmission-remote)
- सबमॉड्यूल बनाता है (hashcat-utils, princeprocessor, pcfg_cracker, और वैकल्पिक रूप से omen) और केवल-डेटा Corporate_Masks मास्क सेट को चेकआउट करता है
- uv के माध्यम से Python निर्भरताएँ और `~/.local/bin/hate_crack` पर एक CLI शिम```bash
make

यह idempotent है - यह पहले से इंस्टॉल किए गए टूल्स को छोड़ देता है। साफ़ पुनःस्थापना के लिए बाध्य करने हेतु:```bash make reinstall

**या निर्भरताएँ मैन्युअल रूप से इंस्टॉल करें:**

### बाहरी निर्भरताएँ
ये कुछ डाउनलोड/निष्कर्षण प्रवाहों के लिए आवश्यक हैं:

- `7z`/`7za` (p7zip) — `.7z` संग्रहों को निकालने के लिए उपयोग किया जाता है।
- `transmission-daemon` / `transmission-remote` — Weakpass टोरेंट डाउनलोड करने के लिए उपयोग किया जाता है।

मैन्युअल इंस्टॉल कमांड:

Ubuntu/Kali:```bash
sudo apt-get update
sudo apt-get install -y p7zip-full transmission-daemon

macOS (Homebrew):```bash brew install p7zip transmission-cli # provides transmission-daemon and transmission-remote

फिर Python निर्भरताएँ और CLI shim इंस्टॉल करें:```bash
uv sync
mkdir -p ~/.local/bin
printf '#!/usr/bin/env bash\nset -euo pipefail\nexec uv run --directory %s python -m hate_crack "$@"\n' "$(pwd)" > ~/.local/bin/hate_crack
chmod +x ~/.local/bin/hate_crack

परियोजना संरचना

मुख्य लॉजिक अब hate_crack/ के अंतर्गत मॉड्यूल में विभाजित है:

  • hate_crack/cli.py: argparse सहायक और कॉन्फ़िग ओवरराइड।
  • hate_crack/api.py: Hashview, Weakpass, और Hashmob एकीकरण (डाउनलोड/मेनू/सहायक)।
  • hate_crack/attacks.py: मेनू हमला हैंडलर।
  • hate_crack/corpus_stats.py: पूरे-कोष के पासवर्ड आंकड़े जो LLM को कोष का वर्णन करने के लिए उपयोग किए जाते हैं।
  • hate_crack/plaintext.py: कोष पंक्ति से पासवर्ड पुनर्प्राप्त करता है (हैश-प्रीफ़िक्स हटाना, $HEX[...] डिकोडिंग); LLM मोड, corpus_stats, और rulegen द्वारा साझा किया जाता है।
  • hate_crack/llm.py: Atomic Agents के माध्यम से संरचित (JSON) LLM उम्मीदवार जनरेशन।
  • hate_crack/menu.py: साझा मेनू रेंडरर, जिसमें वैकल्पिक एरो-की नेविगेशन शामिल है।
  • hate_crack/noninteractive.py: स्क्रिप्टेड हमला सबकमांड के लिए डिस्पैचर।
  • hate_crack/notify/: अधिसूचना पैकेज (Pushover बैकएंड, प्रति-क्रैक टेलर)।
  • hate_crack/username_detect.py: hashcat के --username पर निर्णय लेने के लिए username:hash इनपुट फ़ाइलों का पता लगाता है।
  • hate_crack/formatting.py, hate_crack/progress.py: आउटपुट फ़ॉर्मेटिंग और प्रगति प्रदर्शन सहायक।
  • hate_crack/main.py: मुख्य CLI कार्यान्वयन।

शीर्ष-स्तरीय hate_crack.py मुख्य प्रवेश बिंदु बना हुआ है और इन मॉड्यूलों का समन्वय करता है।


संदर्भ और धन्यवाद

यह परियोजना कई बाहरी परियोजनाओं और सेवाओं पर निर्भर करती है और उनसे प्रेरित है। धन्यवाद:


उपयोग

make के साथ इंस्टॉल करने के बाद, hate_crack को कहीं से भी चलाएं:```bash hate_crack

or with arguments:

hate_crack <hash_file> <hash_type> [options]

वैकल्पिक रूप से, `uv` के माध्यम से चलाएँ:```bash
uv run hate_crack.py <hash_file> <hash_type>

टूल के रूप में चलाएँ (अनुशंसित)

रिपॉज़िटरी रूट से make का उपयोग करके इंस्टॉल करें - यह सबमॉड्यूल बनाता है और एसेट्स को बंडल करता है:```bash cd /path/to/hate_crack make hate_crack

`make install` कमांड `~/.local/bin/hate_crack` पर एक bash shim बनाता है जो रेपो डायरेक्टरी से चलता है, इसलिए कॉन्फ़िग और एसेट्स हमेशा मिल जाते हैं, चाहे आपकी वर्तमान वर्किंग डायरेक्टरी कोई भी हो।

कॉन्फ़िग इनमें भी खोजा जाता है:
- रेपो रूट और पैकेज डायरेक्टरी
- `~/.hate_crack`

**नोट:** `config.json` में `hcatPath` केवल hashcat बाइनरी लोकेशन के लिए है (वैकल्पिक यदि hashcat PATH में है)। Hate_crack एसेट्स (hashcat-utils, princeprocessor, pcfg_cracker, Corporate_Masks, omen) रिपॉज़िटरी डायरेक्टरी से लोड होते हैं और `make install` द्वारा स्वचालित रूप से बंडल कर दिए जाते हैं।

### स्क्रिप्ट के रूप में चलाएँ
स्क्रिप्ट `uv` shebang का उपयोग करती है। इसे निष्पादन योग्य बनाएँ और चलाएँ:```bash
chmod +x hate_crack.py
./hate_crack.py

आप सीधे Python का भी उपयोग कर सकते हैं:```bash python hate_crack.py

### गैर-इंटरैक्टिव / स्क्रिप्टेड उपयोग

स्वचालन के लिए आप मेनू को बायपास करते हुए सीधे एकल हमला शुरू कर सकते हैं। हमले का नाम पहला आर्ग्युमेंट है, इसके बाद हैश फ़ाइल और hashcat हैश प्रकार। इस मोड में प्रीप्रोसेसिंग प्रॉम्प्ट (कंप्यूटर-अकाउंट फ़िल्टरिंग, LM-प्रथम ब्रूट फ़ोर्स, डुप्लिकेट-अकाउंट डीडुप) स्वतः अपने डिफ़ॉल्ट स्वीकार कर लेते हैं। प्रक्रिया सफलता पर `0` और त्रुटि पर गैर-शून्य के साथ बाहर निकलती है (अनुपलब्ध हैश फ़ाइल, गैर-संख्यात्मक हैश प्रकार, अनुपलब्ध वर्डलिस्ट, या अज्ञात नियम फ़ाइलनाम)।```bash
# Quick crack: one wordlist + optional rule(s) from the rules directory
hate_crack quick hashes.txt 1000 --wordlist rockyou.txt --rules best64.rule

# Chain two rules in a single run
hate_crack quick hashes.txt 1000 --wordlist rockyou.txt --rules best64.rule+d3ad0ne.rule

# Run two rules as two separate passes
hate_crack quick hashes.txt 1000 --wordlist rockyou.txt --rules best64.rule d3ad0ne.rule

# Canned dictionary methodology (uses your configured wordlists)
hate_crack dict hashes.txt 1000

# Brute force lengths 1-8
hate_crack brute hashes.txt 1000 --min 1 --max 8

# Top-mask attack targeting ~4 hours
hate_crack topmask hashes.txt 1000 --target-time 4

समस्या निवारण

त्रुटि: अपडेट करते समय "would clobber existing tag"

एक पुराना क्लोन अपडेट करने से इनकार कर सकता है, जिसमें इस तरह की लंबी सूची दिखाई देती है:``` ! [rejected] v2.5.0 -> v2.5.0 (would clobber existing tag)

यह जुलाई 2026 से पहले बनाए गए क्लोन को प्रभावित करता है। प्रकाशित इतिहास को तब फिर से लिखा गया था ताकि कुछ ऐसी फ़ाइलें हटाई जा सकें जिन्हें कभी कमिट नहीं किया जाना चाहिए था, जिससे हर कमिट को एक नई ID मिली; इसलिए पुराने क्लोन के टैग उन ऑब्जेक्ट्स की ओर इशारा करते हैं जो यह रिपॉज़िटरी अब नहीं रखती, और git उस टैग को हटाने से इनकार करता है जो उसके पास पहले से है। आपके चेकआउट में कुछ भी गलत नहीं है और कोई क्रैकिंग डेटा जोखिम में नहीं है।

एक बार के रीसेट के साथ रिकवर करें। यह चेकआउट में स्थानीय कमिट और संपादनों को त्याग देता है, इसलिए यदि आपने git द्वारा ट्रैक की गई किसी चीज़ को अनुकूलित किया है (जैसा कि `config.json` के विपरीत, जो ट्रैक नहीं है), तो पहले इसे किसी ब्रांच में कमिट करें:```bash
cd /path/to/hate_crack
git fetch --tags --force origin
git checkout -B main origin/main
make install

--force यहाँ केवल टैग्स को अपडेट करता है; यह आपके कमिट्स को छू नहीं सकता। इसके बाद बिल्ट-इन अपडेटर सामान्य रूप से काम करता है। 2.18 से पहले के संस्करण यह रिकवरी स्वयं नहीं कर सकते थे, इसीलिए इसे एक बार हाथ से करना पड़ता है।

त्रुटि: बिल्ड डायरेक्टरी मौजूद नहीं है

यदि आपको इस तरह की त्रुटि दिखाई दे:``` Error: Build directory /opt/hashcat/hashcat-utils does not exist. Expected to find expander at /opt/hashcat/hashcat-utils/bin/expander.

इसका मतलब है कि hate_crack एसेट्स इंस्टॉल किए गए पैकेज में बंडल नहीं किए गए थे।

**पाथ्स को समझना:**
- config.json में `hcatPath` → **hashcat बाइनरी लोकेशन** को इंगित करता है (वैकल्पिक, PATH में हो सकता है)
- `hashcat-utils/` और `princeprocessor/` → `make install` द्वारा पैकेज में बंडल किए जाते हैं

**समाधान:**
Makefile का उपयोग करके पुनः इंस्टॉल करें, जो सबमॉड्यूल्स को बिल्ड करता है और टूल को इंस्टॉल करता है:```bash
cd /path/to/hate_crack  # the repository checkout
make install

डिफ़ॉल्ट कॉन्फ़िगरेशन (config.json.example):

अधिकांश उपयोगकर्ता बिना किसी अनुकूलन के डिफ़ॉल्ट का उपयोग कर सकते हैं:

  • hcatWordlists: ./wordlists (रेपो रूट या HOME/.hate_crack के सापेक्ष)
  • hcatOptimizedWordlists: ./optimized_wordlists (Quick Crack द्वारा उपयोग की जाने वाली डायरेक्टरी; यदि न मिले तो hcatWordlists पर वापस चला जाता है)
  • rules_directory: ./hashcat/rules (सबमॉड्यूल नियमों सहित)
  • hcatTuning: `` (खाली स्ट्रिंग - कोई डिफ़ॉल्ट ट्यूनिंग फ़्लैग नहीं)

उदाहरण config.json अनुकूलन:```json { "hcatPath": "/usr/local/bin", # Location of hashcat binary (optional, auto-detected from PATH) "hcatBin": "hashcat", # Hashcat binary name "hcatWordlists": "./wordlists", # Dictionary wordlist directory (relative or absolute) "rules_directory": "./hashcat/rules", # Rules directory (relative or absolute) "hcatTuning": "", # Additional hashcat flags (empty by default) ... }

**कॉन्फ़िगरेशन लोडिंग:**
- प्रत्येक key के लिए प्राथमिकता: `os.environ` > उस key की अपनी home फ़ाइल (`.env` या `config.json`) > built-in default
- अनुपलब्ध keys built-in defaults पर वापस चली जाती हैं; `config.json.example` हर `config.json` key को दस्तावेज़ित करता है
- दोनों फ़ाइलों को, एक-दूसरे से स्वतंत्र रूप से, इस क्रम में खोजा जाता है: **repo root**, फिर **installed package directory**, फिर **`~/.hate_crack`**। पहला मिलान जीतता है; यह सामान्य है कि दोनों फ़ाइलें अलग-अलग directories से आएँ।
- पहली बार चलाने पर, दोनों बनाई जाती हैं — `config.json`, `config.json.example` से, और `.env`, built-in defaults से। यदि कोई पुरानी `config.json` अभी भी integration keys रखती है, तो उन्हें नई `.env` में कॉपी कर दिया जाता है और hate_crack आपको बताता है कि किन्हें `config.json` से हटाना है; यह उस फ़ाइल को स्वयं कभी संपादित नहीं करता।
- हर बार चलाने पर, hate_crack उन दो फ़ाइलों को प्रिंट करता है जिन्हें उसने वास्तव में लोड किया:  ```
  [*] config.json: /home/you/.hate_crack/config.json
  [*] .env:        /home/you/.hate_crack/.env

किसी सेटिंग को डीबग करने से पहले उन दो पंक्तियों को पढ़ें जो "प्रभावी नहीं हो रही"। वे सर्च ऑर्डर में दो जालों की वजह से मौजूद हैं:

  • एक चेकआउट आपकी होम डायरेक्टरी से ऊपर होता है। रेपो रूट को पहले खोजा जाता है, इसलिए किसी भी चेकआउट में मौजूद .env या config.json जहाँ से आप टूल चलाते हैं, ~/.hate_crack में मौजूद फ़ाइल पर भारी पड़ता है — और किसी चेकआउट से टूल चलाना ही सबसे पहले वहाँ उन फ़ाइलों को बनाता है। अगर यह कभी किसी असली ~/.hate_crack कॉन्फ़िग को शैडो करता है, तो hate_crack अब तीसरी [!] पंक्ति के साथ दोनों पाथ बताता है — उस पंक्ति को "नीचे वाली फ़ाइल को अनदेखा किया जा रहा है" मानें, न कि दूसरे, समान रूप से मान्य कॉन्फ़िग के रूप में।
  • वर्तमान कार्यशील डायरेक्टरी कभी नहीं खोजी जाती। जिस डायरेक्टरी में आप संयोग से खड़े हैं, उसमें मौजूद .env को जानबूझकर अनदेखा किया जाता है: एंगेजमेंट डायरेक्टरियाँ ऐसी फ़ाइलों से भरी होती हैं जिन्हें किसी ने कॉन्फ़िगरेशन के रूप में इस्तेमाल करने का इरादा नहीं किया था। इसे रेपो रूट या ~/.hate_crack में रखें।

त्रुटि: merge with ref 'refs/heads/master' but no such ref was fetched

अगर आपको यह दिखे:``` Your configuration specifies to merge with the ref 'refs/heads/master' from the remote, but no such ref was fetched.

डिफ़ॉल्ट ब्रांच का नाम `master` से बदलकर `main` कर दिया गया है। इसे ठीक करें:```bash
git remote set-head origin -a
git branch -m master main
git branch --set-upstream-to=origin/main main
git pull

Makefile लक्ष्य

डिफ़ॉल्ट (पूर्ण इंस्टॉलेशन) - सबमॉड्यूल बनाता है, निर्भरताएँ इंस्टॉल करता है, और टूल इंस्टॉल करता है:```bash make

or explicitly:

make install

यह इडेम्पोटेंट है - यह पहले से इंस्टॉल किए गए टूल्स को छोड़ देता है।

**जबरन साफ़ पुनःस्थापन:**```bash
make reinstall

त्वरित अपडेट - सबमॉड्यूल्स को पुनः बनाता है और टूल को पुनः इंस्टॉल करता है (परिवर्तनों को पुल करने के बाद):```bash make update

**Uninstall** - OS निर्भरताएँ और टूल हटाता है:```bash
make uninstall

केवल hashcat-utils बनाएँ:```bash make hashcat-utils

**परीक्षण चलाएँ** - आवश्यकता पड़ने पर HATE_CRACK_SKIP_INIT को स्वचालित रूप से संभालता है:```bash
make test

कवरेज रिपोर्ट:```bash make coverage

**स्वच्छ बिल्ड/परीक्षण आर्टिफैक्ट्स:**```bash
make clean

विकास

विकास पर्यावरण सेट करना

प्रोजेक्ट को वैकल्पिक dev निर्भरताओं के साथ इंस्टॉल करें (linters और testing tools सहित):```bash make dev-install

### लिंटर और टाइप चेक चलाना

परिवर्तनों को पुश करने से पहले, इन जाँचों को स्थानीय रूप से चलाएँ। सब कुछ के लिए `make lint` का उपयोग करें, या अलग-अलग जाँचें चलाएँ:

**Ruff (लिंटिंग और फ़ॉर्मेटिंग):**```bash
make ruff
# or manually:
uv run ruff check hate_crack tests tools packaging hate_crack.py

स्वतः-ठीक मुद्दे:```bash uv run ruff format hate_crack tests tools packaging hate_crack.py uv run ruff check --fix hate_crack tests tools packaging hate_crack.py

**ty (टाइप चेकिंग):**```bash
make ty
# or manually:
uv run ty check hate_crack

सभी जाँचें एक साथ चलाएँ:```bash make lint

### परीक्षण चलाना

जब सबमॉड्यूल बिल्ड नहीं होते हैं तो परीक्षण स्वतः पहचान लेते हैं और `HATE_CRACK_SKIP_INIT=1` स्वतः सेट कर देते हैं।```bash
make test

या सीधे pytest चलाएँ:```bash uv run pytest -v

कवरेज के साथ:```bash
make coverage

या pytest के साथ:```bash uv run pytest --cov=hate_crack

### Git Hooks (prek)

Git hooks को [prek](https://github.com/j178/prek) (v0.3.3+) द्वारा प्रबंधित किया जाता है। hooks को इस प्रकार इंस्टॉल करें:```bash
prek install --hook-type pre-push --hook-type pre-commit

यह prek.toml में परिभाषित hooks को pre-commit local-repo TOML schema का उपयोग करके install करता है:

  • pre-push (local hooks): ruff, ruff-format, ty, pytest, pytest-lima, bandit
  • pre-commit (pre-commit/pre-commit-hooks से): trailing-whitespace, end-of-file-fixer, check-yaml, check-merge-conflict, check-added-large-files, detect-private-key

pre-commit auto-fixers फ़ाइलों को in place rewrite करते हैं, इसलिए उनके चलने के बाद फिर से re-stage करके commit करें।

नोट: prek 0.3.3 top level पर repos = [...] की अपेक्षा करता है। पुराना [hooks.<stage>] commands = [...] format समर्थित नहीं है।

Arrow-Key Menu Navigation

Menus डिफ़ॉल्ट रूप से classic numbered print() + input() selection का उपयोग करते हैं, जो पूर्ण multi-digit keys स्वीकार करता है।

simple-term-menu के माध्यम से arrow-key navigation सक्षम करने के लिए, HATE_CRACK_ARROW_MENU=1 सेट करें। उस mode में केवल single-digit shortcut keys काम करती हैं; 10 और उससे ऊपर numbered options तक arrow keys से पहुँचना होगा। Arrow-key mode के लिए TTY भी आवश्यक है, इसलिए जब output piped हो तो यह बंद रहता है।

Dev Dependencies

वैकल्पिक [dev] group में शामिल हैं:

  • ty - Static type checker
  • ruff - Fast Python linter और formatter
  • pytest - Testing framework
  • pytest-cov - Coverage reporting

Common options:

  • --download-hashview: Cracking से पहले Hashview से hashes download करें।
  • --hashview: Hashes, wordlists, और jobs प्रबंधित करने के लिए Interactive Hashview menu।
  • --hashview --help: Hashview command-line options दिखाएँ।
  • --weakpass: Weakpass से wordlists download करें।
  • --hashmob: Hashmob.net से wordlists download करें।
  • --hashmob-masks: Hashmob.net से masks download करें।
  • --download-torrent <FILENAME>: एक विशिष्ट Weakpass torrent file download करें।
  • --download-all-torrents: Cache से सभी उपलब्ध Weakpass torrents download करें।
  • --wordlists-dir <PATH> / --optimized-wordlists-dir <PATH>: Wordlist directories override करें।
  • --pipal-path <PATH>: Pipal path override करें।
  • --restore-potfile: Startup पर hashcat POT file से <hashfile>.out rebuild करें, किसी भी मौजूदा contents को बदलकर, फिर सामान्य menu में जारी रखें। इस flag के बिना POT lookup केवल तब चलता है जब .out पहले से मौजूद न हो। Menu option 93 confirmation prompt के साथ माँग पर वही काम करता है।
  • --maxruntime <SECONDS>: Max runtime override करें।
  • --bandrel-basewords <PATH>: Bandrel basewords file override करें।
  • --update: नवीनतम release पर update करें और reinstall करें। यदि checkout किसी अन्य branch पर है तो उसे main पर switch करता है, क्योंकि release tags वहीं रहते हैं।
  • --nightly: इसके बजाय nightly-dev branch से नवीनतम nightly पर update करें। Nightlies CI पास कर चुके हैं लेकिन किसी cut release का हिस्सा नहीं हैं। इसे --update --nightly भी लिखा जा सकता है।
  • --no-optimized-kernel (या --no-optimize): पूरे run के लिए hashcat को कभी -O पास न करें। config.json में optimizedKernelAttacks को override करता है और hcatTuning में डाले गए किसी भी -O को हटा देता है। Config में कुछ भी वापस नहीं लिखा जाता, इसलिए यह केवल इस run पर लागू होता है। Subcommand के साथ, इसे subcommand से पहले रखें: ./hate_crack.py --no-optimize quick hashes.txt 1000 --wordlist words.txt
  • --debug: Debug logging सक्षम करें (stderr पर लिखता है)।

Hashview Integration

hate_crack केंद्रीकृत hash प्रबंधन और distributed cracking के लिए Hashview के साथ integrate करता है।

Interactive Menu

Interactive Hashview menu access करें:```bash hate_crack.py --hashview

मेनू विकल्प:
- **(1) Upload Cracked Hashes** - वर्तमान सत्र से क्रैक किए गए परिणाम Hashview पर अपलोड करें
- **(2) Upload Wordlist** - Hashview पर एक वर्डलिस्ट फ़ाइल अपलोड करें
- **(3) Download Wordlist** - Hashview से एक वर्डलिस्ट डाउनलोड करें
- **Download Rule** - Hashview से एक रूल फ़ाइल डाउनलोड करें (प्लेनटेक्स्ट में डीकंप्रेस किया गया, `hashcat -r` के लिए तैयार)। एक के बजाय सूचीबद्ध प्रत्येक रूल डाउनलोड करने के लिए रूल ID प्रॉम्प्ट पर `a` (या `all`) दर्ज करें
- **Download All Rules** - Hashview द्वारा सूचीबद्ध प्रत्येक रूल फ़ाइल को एक ही बार में डाउनलोड करें; प्रति-रूल विफलताओं की रिपोर्ट की जाती है बिना शेष को रोके
- **(4) Download Left Hashes** - शेष अनक्रैक किए गए हैश डाउनलोड करें (क्रैकिंग के लिए स्विच करने का प्रॉम्प्ट करता है)
- **(5) Download Found Hashes** - क्लीयरटेक्स्ट पासवर्ड के साथ पहले से क्रैक किए गए हैश डाउनलोड करें (संदर्भ/विश्लेषण के लिए)
- **(6) Upload Hashfile and Create Job** - नई हैशफ़ाइल अपलोड करें और एक क्रैकिंग जॉब बनाएं
- **(99) Back to Main Menu** - मुख्य मेनू पर वापस जाएं

**महत्वपूर्ण: Download Found बनाम Download Left**
- **Download Left Hashes (4)**: अनक्रैक किए गए हैश डाउनलोड करता है जिन्हें क्रैक करने की आवश्यकता है। यदि उपलब्ध हों तो किसी भी पाए गए हैश के साथ स्वचालित रूप से मर्ज करता है, और क्रैकिंग के लिए इस हैशफ़ाइल पर स्विच करने का प्रॉम्प्ट करता है।
- **Download Found Hashes (5)**: पहले से क्रैक किए गए हैश को hash:cleartext प्रारूप में डाउनलोड करता है। ये संदर्भ के लिए हैं और इन्हें आगे क्रैक नहीं किया जा सकता। कोई स्विच प्रॉम्प्ट नहीं दिखाया जाता है।

#### कमांड-लाइन इंटरफ़ेस

Hashview संचालन कमांड-लाइन के माध्यम से भी किए जा सकते हैं:

क्रैक किए गए हैश अपलोड करें:```bash
hate_crack.py --hashview upload-cracked --file <output_file>.out --hash-type 1000

एक वर्डलिस्ट अपलोड करें:```bash hate_crack.py --hashview upload-wordlist --file .txt --name "My Wordlist"

एक रूल फ़ाइल डाउनलोड करें (`hashcat -r` के लिए तैयार, डीकंप्रेस्ड रूप में सहेजी गई):```bash
hate_crack.py --hashview download-rules --rules-id 4 --output best64.rule

बाएँ हैश डाउनलोड करें (क्रैकिंग के लिए अनक्रैक्ड हैश):```bash hate_crack.py --hashview download-left --customer-id 1 --hashfile-id 123

Download found hashes (already-cracked hashes with cleartext):```bash
hate_crack.py --hashview download-found --customer-id 1 --hashfile-id 123

हैशफ़ाइल अपलोड करें और जॉब बनाएं:```bash hate_crack.py --hashview upload-hashfile-job --file hashes.txt --customer-id 1
--hash-type 1000 --job-name "NTLM Crack Job" --hashfile-name "Domain Hashes"

#### कॉन्फ़िगरेशन

`.env` में Hashview क्रेडेंशियल्स सेट करें (ये इंटीग्रेशन सेटिंग्स हैं, इसलिए ये `config.json` में नहीं रहते):```
HASHVIEW_URL=https://hashview.example.com
HASHVIEW_API_KEY=your-api-key-here
HASHVIEW_VERIFY_TLS=true

HASHVIEW_VERIFY_TLS का डिफ़ॉल्ट मान true है: hate_crack Hashview सर्वर के TLS प्रमाणपत्र को सत्यापित करता है, और स्व-हस्ताक्षरित या आंतरिक-CA प्रमाणपत्र वाले Hashview से कनेक्ट करना तब तक विफल रहेगा जब तक उस प्रमाणपत्र पर भरोसा नहीं किया जाता (इसे अपने सिस्टम ट्रस्ट स्टोर में जोड़ें, या किसी ऐसे CA द्वारा जारी प्रमाणपत्र का उपयोग करें जिस पर आपका सिस्टम पहले से भरोसा करता है)। यदि यह संभव नहीं है, तो HASHVIEW_VERIFY_TLS=false सेट करें -- सत्यापन बंद होने पर hate_crack प्रत्येक प्रक्रिया शुरू होने पर होस्ट का नाम लेते हुए एक पंक्ति की चेतावनी प्रिंट करेगा, क्योंकि इसे अक्षम करने से स्पूफ़ किए गए सर्वर या कनेक्शन को इंटरसेप्ट करने वाले ऑन-पाथ हमलावर के विरुद्ध सुरक्षा हट जाती है।

LLM Configuration

LLM Attack (विकल्प 12) और Rosetta Mask Attack (विकल्प 23) अपने उम्मीदवारों को एक स्थानीय मॉडल से उत्पन्न करते हैं। .env में मॉडल, कॉन्टेक्स्ट विंडो, और रिक्वेस्ट टाइमआउट कॉन्फ़िगर करें:``` LLM_BACKEND=ollama OLLAMA_MODEL=qwen3:4b-instruct OLLAMA_NUM_CTX=8192 OLLAMA_TIMEOUT=300

**नीचे दी गई `OLLAMA_*` कुंजियाँ हर बैकएंड पर लागू होती हैं, केवल Ollama पर नहीं।** वे यह उपसर्ग इसलिए बनाए रखती हैं क्योंकि `OLLAMA_HOST` वही वेरिएबल है जिसे Ollama का अपना CLI पढ़ता है, और उनका नाम बदलने से हर मौजूदा `.env` टूट जाएगी बिना किसी कार्यात्मक लाभ के — एक vLLM या OpenAI-संगत सर्वर को भी वही host, model, timeout, context, और sampling knobs उन्हीं नामों के अंतर्गत चाहिए। `LLM_BACKEND` केवल यह चुनता है कि अनुरोध किस आकार में बनाया जाएगा।

- **`OLLAMA_MODEL`** — candidate generation के लिए उपयोग किया जाने वाला Ollama मॉडल (डिफ़ॉल्ट: `qwen3:4b-instruct`)। LLM attack structured (JSON) output का उपयोग करता है, इसलिए अच्छे tool/JSON समर्थन वाला मॉडल चुनें।
- **`OLLAMA_NUM_CTX`** — मॉडल के लिए context window का आकार (डिफ़ॉल्ट: `8192`)। corpus statistics शुरू होने से पहले यह `2048` था, जो इसे दिए जा रहे prompt को रखने के लिए बहुत छोटा था: 500 sampled plaintexts system prompt और response से पहले लगभग 2,000–3,500 tokens लेते हैं, इसलिए Ollama ने उस sample का एक हिस्सा चुपचाप काट दिया जिसे sampler ने पूरी फ़ाइल में सावधानी से फैलाया था।
- **`OLLAMA_TIMEOUT`** — हार मानने से पहले generation response की प्रतीक्षा करने के सेकंड (डिफ़ॉल्ट: `300`)। यदि पहले अनुरोध पर कोई बड़ा मॉडल अभी भी VRAM में लोड हो रहा है तो इसे बढ़ाएँ, अन्यथा यह timeout से अधिक हो सकता है; hate_crack timeout होने पर बीता हुआ समय और इस सेटिंग का नाम प्रिंट करता है।
- **`OLLAMA_MAX_SAMPLE_LINES`** — वह सीमा जिसके नीचे LLM modes literal plaintexts को भी prompt में चिपका देते हैं (डिफ़ॉल्ट: `500`)। ≤ 0 मानों को 500 माना जाता है।

  Corpus-व्युत्पन्न modes (**Wordlist**, **Cracked passwords**, **Pattern rules**) हमेशा *पूरे* corpus का सांख्यिकीय वर्णन करते हैं — baseword shares, masks, casing, lengths, trailing digits और symbols, years — बजाय उसका कोई टुकड़ा चिपकाने के। Aggregation सीमित है, इसलिए 120,000-password dump लगभग उतनी ही prompt जगह लेता है जितनी 500-line वाला। जब पूरा corpus इस सीमा के नीचे आता है, तो raw plaintexts भी शामिल किए जाते हैं, क्योंकि छोटे corpus को मॉडल से छिपाने में कोई लाभ नहीं है।

  यह पहले के उस व्यवहार को प्रतिस्थापित करता है जिसमें `ollamaMaxSampleLines` तक के समान रूप से फैले sample को चिपकाया जाता था। बड़े dump के sample से कोई frequency जानकारी नहीं मिलती थी: मॉडल उस baseword में अंतर नहीं कर सकता था जिसका उपयोग संगठन के 8% लोग करते हैं और उससे जिसका उपयोग एक व्यक्ति करता है, जो ठीक वही संकेत है जो किसी अनुमान को चलाने लायक बनाता है।
- **`OLLAMA_NO_CLOUD`** — जब `true` हो, तो तीनों LLM backends (Ollama, vLLM, या generic OpenAI-संगत सर्वर) में से किसी के लिए भी इस host से बाहर कुछ भी भेजने से इनकार करें। दो जाँचें इस एक सेटिंग से नियंत्रित होती हैं: Ollama `-cloud`-टैग वाले मॉडल (`gpt-oss:120b-cloud`, `deepseek-v3.1:671b-cloud`) को उसी local endpoint के माध्यम से ollama.com पर proxy करता है जिसका उपयोग local मॉडल करता है, इसलिए अनुरोध में कुछ भी अलग नहीं दिखता — इसे मॉडल नाम से अस्वीकार किया जाता है। कॉन्फ़िगर किया गया backend URL भी जाँचा जाता है: ऐसा गंतव्य जो loopback, private, या link-local नहीं है (और `localhost` या `.local`/`.internal`/`.lan`/`.localdomain` नाम नहीं है) उसे गंतव्य के आधार पर अस्वीकार किया जाता है, और ऐसा hostname जिसे यह जाँच resolve नहीं कर सकती, उसे भी अस्वीकार किया जाता है, fail-closed, बजाय किसी असत्यापनीय गंतव्य को जाने देने के। hate_crack के prompts में recovered plaintexts, corpus statistics, और client का नाम, industry, और location होते हैं, इसलिए कोई भी जाँच सक्रिय होने का अर्थ है कि अनुरोध बनाए जाने से पहले अस्वीकार कर दिया जाता है। डिफ़ॉल्ट `false` है, इसलिए जानबूझकर कॉन्फ़िगर किया गया cloud मॉडल या remote सर्वर काम करता रहता है; उन engagements के लिए इसे चालू करें जहाँ client डेटा host से बाहर नहीं जाना चाहिए।
- **`OLLAMA_AUTO_RESEARCH`** — जब `true` (डिफ़ॉल्ट), **Target info** mode कंपनी का नाम टाइप करते ही local मॉडल से industry, location, और parent company / acquisition history सुझाने के लिए कहता है, और उन्हें editable prompt defaults के रूप में प्रस्तुत करता है। हमेशा खाली prompts पाने के लिए इसे `false` पर सेट करें (धीमे मॉडल के साथ उपयोगी, क्योंकि research से attack शुरू होने से पहले एक अतिरिक्त round-trip लगता है)।
- **`OLLAMA_HOST`** — जहाँ कॉन्फ़िगर किया गया backend सुन रहा है। यह एक सादा `host:port` (`theplague.lan:11434`) या scheme के साथ पूरा URL (`https://ollama.example.com`) स्वीकार करता है; किसी भी तरह base URL का उपयोग से पहले normalization किया जाता है। डिफ़ॉल्ट `localhost:11434` है, जो Ollama का port है — एक vLLM या OpenAI-संगत सर्वर के लिए इसे उसके अपने port पर सेट करना आवश्यक है (vLLM आमतौर पर `:8000` पर सुनता है)। इसे `.env` में सेट करें, या एक बार के run के लिए उसे override करने हेतु इसे वास्तविक environment variable के रूप में export करें — यह वही वेरिएबल नाम है जिसे Ollama का अपना CLI पढ़ता है।
- **`LLM_BACKEND`** — किस OpenAI-संगत सर्वर से बात करनी है: `ollama` (डिफ़ॉल्ट), `vllm`, या generic के लिए `openai`। हर backend वही `/v1` chat-completions API बोलता है, इसलिए यह केवल उन दो request-shaping विवरणों का चयन करता है जिनमें वे भिन्न हैं: `ollama` को `options.num_ctx` मिलता है, और `vllm` को `chat_template_kwargs={"thinking": false}` — जिसके बिना reasoning parser चला रहा vLLM सर्वर पूरे structured response को `message.reasoning` में भेज देता है, `message.content` खाली छोड़ देता है, और JSON parsing तोड़ देता है। `openai` दोनों में से कोई नहीं भेजता, क्योंकि वहाँ `num_ctx` का कोई समतुल्य नहीं है। यह **नहीं** बदलता कि host, model, timeout, context, या sampling सेटिंग्स कहाँ से आती हैं — वे तीनों के लिए ऊपर दी गई `OLLAMA_*` कुंजियाँ हैं।
- **`LLM_API_KEY`** — कॉन्फ़िगर किए गए backend को भेजा जाने वाला credential। डिफ़ॉल्ट शाब्दिक `ollama` है, वह placeholder जिसे Ollama का अपना सर्वर अनदेखा करता है, इसलिए मौजूदा install के अनुरोध अपरिवर्तित रहते हैं; खाली मान उसी placeholder पर वापस जाता है क्योंकि OpenAI SDK `api_key=""` अस्वीकार करता है। यदि सर्वर एक लागू करता है तो इसे वास्तविक मान पर सेट करें — `--api-key` के साथ शुरू किया गया vLLM सर्वर अन्यथा 401 लौटाता है।
- LLM Attack का उपयोग करने से पहले सुनिश्चित करें कि Ollama चल रहा है और मॉडल pulled है (`ollama pull qwen3:4b-instruct`) — hate_crack अब अनुपस्थित मॉडलों को स्वतः pull नहीं करता।

attack तीन generation modes प्रदान करता है:

1. **Target info** — company / industry / location / parent company; मॉडल उन विवरणों से candidates निकालता है।

   कंपनी का नाम टाइप करने के बाद, hate_crack उसी local मॉडल से पूछता है कि वह उस संगठन के बारे में पहले से क्या जानता है और **Industry**, **Location**, और **Parent Company** prompts को उत्तरों से पहले भर देता है, जो कोष्ठकों में दिखाए जाते हैं:   ```
   Company name: Acme Rail Services

   [!] The values in parentheses below are the local model's GUESSES, not verified OSINT.
       Press Enter to accept, or type your own value to override.
   Industry (freight rail maintenance):
   Location (Omaha, Nebraska):
   Parent company / acquired by:

किसी सुझाव को स्वीकार करने के लिए Enter दबाएँ या उस पर टाइप करें। ये मान मॉडल की स्मृति हैं, OSINT नहीं — इन्हें एक प्रारंभिक बिंदु मानें, क्लाइंट के बारे में जानकारी नहीं। लुकअप केवल स्थानीय Ollama सर्वर का उपयोग करता है, इसलिए क्लाइंट का नाम कभी होस्ट नहीं छोड़ता; कोई वेब या तृतीय-पक्ष API कॉल नहीं होते। यदि मॉडल संगठन को नहीं पहचानता (छोटे क्लाइंट के लिए सामान्य स्थिति), तो यह कुछ भी नहीं लौटाता और आपको सादे खाली प्रॉम्प्ट मिलते हैं: ``` Company name: Acme Rail Services Industry: Location: Parent company / acquired by:

एक शोध विफलता — टाइमआउट, Ollama नहीं चल रहा, खाली उत्तर — हमले को कभी अवरुद्ध नहीं करती; यह बस खाली प्रॉम्प्ट्स पर वापस चला जाता है। शोध को पूरी तरह छोड़ने के लिए `ollamaAutoResearch` को `false` पर सेट करें।
2. **Wordlist** — एक नमूना wordlist से basewords प्राप्त करें।
3. **Cracked passwords** — इस सत्र में पहले से पुनर्प्राप्त plaintexts (`<hashfile>.out`) को मॉडल को वापस दें ताकि यह लक्ष्य संगठन के अपने पासवर्ड सम्मेलनों (basewords, seasons, years, suffixes, leetspeak) का अनुमान लगा सके और उसी शैली में *नए* उम्मीदवार उत्पन्न कर सके। यह विकल्प केवल तब सूचीबद्ध होता है जब कम से कम एक hash क्रैक हो चुका हो; पूरी फ़ाइल का विश्लेषण सांख्यिकीय रूप से ठीक Wordlist मोड की तरह किया जाता है (ऊपर `ollamaMaxSampleLines` देखें)।

#### PCFG Configuration

PCFG Attack (विकल्प 20) और PRINCE-LING Attack (विकल्प 21) `pcfg_cracker` सबमॉड्यूल का उपयोग करते हैं। इन्हें `config.json` में कॉन्फ़िगर करें:```json
{
"pcfgRuleset": "DEFAULT",
"pcfgMaxCandidates": 50000000,
"pcfgPrinceLingMaxCandidates": 10000000
}
  • pcfgRuleset — उपयोग किए जाने वाले प्रशिक्षित व्याकरण का नाम (डिफ़ॉल्ट: DEFAULT), जिसे pcfg_cracker/Rules/<name>/ में हल किया जाता है। pcfg_cracker के trainer.py से अपना स्वयं का प्रशिक्षित करें और इसे ruleset नाम पर सेट करें।
  • pcfgMaxCandidates — PCFG हमले के लिए pcfg_guesser.py द्वारा उत्सर्जित अधिकतम उम्मीदवार (डिफ़ॉल्ट: 50000000)।
  • pcfgPrinceLingMaxCandidates — कैश्ड PRINCE बेस वर्डलिस्ट में prince_ling.py द्वारा लिखे जाने वाले अधिकतम बेस शब्द (डिफ़ॉल्ट: 10000000)।

अनुकूलित कर्नेल (optimizedKernelAttacks)

hashcat का -O फ़्लैग अनुकूलित कर्नेल चुनता है, जो काफ़ी तेज़ होते हैं लेकिन उम्मीदवार की लंबाई को सीमित कर देते हैं (लगभग 31 अक्षर, कुछ मोड के लिए कम) और इससे लंबे किसी भी चीज़ को चुपचाप छोड़ देते हैं। config.json में optimizedKernelAttacks उन हमलों की सूची देता है जो -O के साथ चलते हैं; किसी हमले को पूर्ण-लंबाई कर्नेल के साथ चलाने के लिए सूची से हटा दें। config.json.example में दी गई सूची उस अंतर्निहित डिफ़ॉल्ट से मेल खाती है जो तब लागू होती है जब कोई config.json मौजूद न हो।

चार हमले इस सेटिंग का पालन करते हैं लेकिन डिफ़ॉल्ट रूप से अनुकूलित नहीं हैं, क्योंकि वे ऐसे उम्मीदवार देते हैं जो -O की सीमा से अधिक हो सकते हैं — इन्हें शामिल करने के लिए सूची में जोड़ें:

  • hcatNgramX, hcatOllama, hcatOmen, hcatLMtoNT

कॉन्फ़िग संपादित किए बिना एक बार के लिए हर जगह -O बंद करने के लिए, --no-optimized-kernel (संक्षिप्त रूप --no-optimize) पास करें। यह हर हमले के लिए सूची को ओवरराइड करता है और hcatTuning में लिखे गए -O को भी हटा देता है, जो अन्यथा सूची की परवाह किए बिना hashcat तक पहुँच जाता।

नामों का सटीक मिलान किया जाता है, और एक अपरिचित प्रविष्टि को अनदेखा करने के बजाय स्टार्टअप पर रिपोर्ट किया जाता है। ध्यान दें कि जो हमले किसी अन्य हमले को सौंपे जाते हैं, वे अपने नाम से नहीं बल्कि उस हमले द्वारा नियंत्रित होते हैं जिसे वे सौंपे जाते हैं: PRINCE-LING hcatPrince का अनुसरण करता है, जबकि Spoonman, Rosetta, और LLM पैटर्न-नियम मोड hcatQuickDictionary का अनुसरण करते हैं।

हमला कवरेज ट्रैकिंग (coverage_enabled)

एक लंबे एंगेजमेंट में एक ही हैश फ़ाइल पर कई सत्रों में घूमती हुई वर्डलिस्ट, रूल फ़ाइलों और मास्क सूचियों के सेट के साथ हमला किया जाता है, और पहले से कवर की गई ज़मीन को दोबारा चलाने में घंटों बर्बाद करना आसान है — खासकर जब एक ही रूल लाइन एक से अधिक रूल फ़ाइल में मौजूद हो। hate_crack रिकॉर्ड करता है कि उसने प्रत्येक हैश फ़ाइल के विरुद्ध पहले क्या चलाया है और ओवरलैप को छोड़ने की पेशकश करता है।

कवरेज प्रति प्रविष्टि, प्रति फ़ाइल नहीं रिकॉर्ड की जाती है: व्यक्तिगत रूल लाइनें और व्यक्तिगत .hcmask लाइनें, प्रत्येक उस वर्डलिस्ट के साथ जोड़ी गई जिसके विरुद्ध वह चली थी। यही कारण है कि यह पहचान सकता है कि आज आपके द्वारा चलाई जाने वाली कस्टम रूल फ़ाइल पिछले सप्ताह best64.rule द्वारा पहले से कवर किए गए 40 नियमों को दोहराती है, और यही कारण है कि एक नियम केवल उस विशिष्ट वर्डलिस्ट के लिए "कवर" होता है जिसके साथ उसे आज़माया गया था — एक अलग कोर्पस पर वही नियम पूरी तरह से अलग उम्मीदवार आज़माते हैं।

हैश फ़ाइल की पहचान उसकी सामग्री के sha256 द्वारा की जाती है, इसलिए कवरेज सत्रों के बीच इसका नाम बदलने या स्थानांतरित करने पर भी बनी रहती है। वर्डलिस्ट की पहचान भी उसी तरह की जाती है, डाइजेस्ट को आकार और mtime के विरुद्ध मेमोइज़ किया जाता है ताकि एक मल्टी-गीगाबाइट कोर्पस को हर हमले पर हैश करने के बजाय एक बार हैश किया जाए।

आपसे केवल तब संकेत मांगा जाता है जब वास्तव में छोड़ने के लिए कुछ हो:``` [*] Coverage: 40 of 45 rules in this Dictionary have already been run against this hash file. [?] Skip them and run only the 5 new rules? [Y/n]:

`Y` का उत्तर दें और hate_crack एक अस्थायी नियम फ़ाइल बनाता है जिसमें केवल बिना आज़माई गई प्रविष्टियाँ होती हैं; पूरी चीज़ वैसे भी चलाने के लिए `n` का उत्तर दें। यदि *प्रत्येक* प्रविष्टि दोहराव है तो आपसे पूछा जाता है कि क्या हमले को पूरी तरह छोड़ दिया जाए, इसलिए जानबूझकर कवर की गई ज़मीन को दोबारा चलाने के लिए कभी भी टूल को पुनः आरंभ करने की आवश्यकता नहीं होती।

जिन हमलों को कभी फ़िल्टर नहीं किया जाता, उन्हें भी चलाया गया के रूप में दर्ज किया जाता है, यही कारण है कि आप उत्तर दे सकते हैं "क्या मैंने इस लक्ष्य के विरुद्ध PRINCE पहले ही चला लिया है?"।

एक हमला जो एक साथ कई नियम फ़ाइलों का चयन करता है (Quick Crack, Loopback) किसी भी hashcat आह्वान से पहले, **पूरे बैच के लिए एक बार, शुरुआत में ही** छोड़ने का प्रश्न पूछता है। वह प्रश्न जानबूझकर सस्ता है — यह चयनित नियम फ़ाइलों में से किसी को भी नहीं पढ़ता या हैश नहीं करता, क्योंकि एक YOLO बैच लाखों पंक्तियों तक चल सकता है और हाँ/नहीं का उत्तर देने के लिए आपको उसका इंतज़ार नहीं करना चाहिए। यह स्टोर से केवल यह पूछता है कि क्या यह हमला इस हैश फ़ाइल के विरुद्ध **इनमें से किसी एक wordlist के साथ** पहले ही चल चुका है; प्रति-प्रविष्टि अंतर अभी भी आलसी रूप से होता है, एक बार में एक नियम फ़ाइल, और यह तय करता है कि वास्तव में क्या छोड़ा जाता है। इसलिए एक नया कॉर्पस कभी चिह्नित नहीं होता, भले ही उस पर के सभी नियम किसी भिन्न कॉर्पस के विरुद्ध चल चुके हों।

तीन जानबूझकर सीमाएँ:

- **कवरेज केवल तब दर्ज होती है जब hashcat keyspace समाप्त कर देता है** (exit 1)। ctrl-C या कोई त्रुटि कुछ भी दर्ज नहीं करती, और exit 0 भी नहीं — इसका अर्थ है कि प्रत्येक हैश क्रैक हो गया, जिसे hashcat keyspace पूरा किए *बिना* रिपोर्ट करता है, और अपवादात्मक "सभी हैश potfile प्रविष्टियों के रूप में मिले" स्थिति में एक भी उम्मीदवार आज़माए बिना। कम-रिकॉर्डिंग की लागत केवल बाद में एक अनावश्यक रन है।
- **गतिशील उम्मीदवार जनरेटर कभी फ़िल्टर नहीं किए जाते।** PRINCE, PCFG, OMEN, Markov brute force और LLM मोड में diff करने के लिए कोई निश्चित सेट नहीं होता, इसलिए उन्हें चलाया गया के रूप में लॉग किया जाता है और अन्यथा अकेला छोड़ दिया जाता है। श्रृंखलाबद्ध नियम फ़ाइलें (`-r a -r b`) प्रति प्रविष्टि के बजाय एक इकाई के रूप में ट्रैक की जाती हैं, क्योंकि hashcat दोनों फ़ाइलों का *कार्टेशियन गुणनफल* लागू करता है और किसी एकल पंक्ति को हटाना चुपचाप उसके द्वारा भाग लिए गए प्रत्येक संयोजन को हटा देगा।
- **`--loopback` रन दर्ज किए जाते हैं लेकिन कभी फ़िल्टर नहीं किए जाते।** hashcat ताज़ा क्रैक किए गए plaintexts को *अतिरिक्त* उम्मीदवारों के रूप में वापस फ़ीड करता है, इसलिए ऐसा रन पूरी wordlist और नियम सेट के साथ-साथ उन रीसाइकल किए गए plaintexts तक जो भी पहुँचता है, उसे आज़माता है। यह दोनों दिशाओं को असममित बनाता है: इसे दर्ज करना उचित है, इसलिए उसी wordlist और नियमों के बाद के सामान्य रन को सही ढंग से दोहराव के रूप में पहचाना जाता है, लेकिन दूसरे loopback रन में रीसाइकल करने के लिए अधिक क्रैक होते हैं और इसे कभी नहीं छोड़ा जाता।

इसे बंद करने के लिए `config.json` में `coverage_enabled` को `false` पर सेट करें, या एकल रन के लिए `--no-coverage` पास करें — जो न तो स्टोर से परामर्श करता है और न ही उसे अपडेट करता है।

#### कवरेज का निरीक्षण और रीसेट करना

मुख्य-मेनू विकल्प **85 — Attack Coverage** दिखाता है कि लोड की गई हैश फ़ाइल के विरुद्ध क्या चलाया गया है, उसका रन इतिहास, और इसे साफ़ कर सकता है। वही तीन क्रियाएँ स्क्रिप्ट करने योग्य हैं:```bash
# What has already been run against this hash file?
hate_crack coverage status --hashfile hashes.txt

# Every attack that has run against it, oldest first
hate_crack coverage history --hashfile hashes.txt

# Start over for this hash file only (prompts unless --yes)
hate_crack coverage forget --hashfile hashes.txt --yes

हैश फ़ाइल की पहचान उसकी सामग्री से होती है, इसलिए ये इस बात की परवाह किए बिना काम करते हैं कि उसे बाद में कहाँ स्थानांतरित किया गया है। forget केवल उसी एक लक्ष्य को प्रभावित करता है — स्टोर ~/.hate_crack/coverage/attack_coverage.sqlite3 में रहता है, और फ़ाइल को हटाने से प्रत्येक लक्ष्य की कवरेज रीसेट हो जाती है।

स्क्रिप्टेड रन

एक स्क्रिप्टेड हमला जिसे कवरेज पूरी तरह से छोड़ देता है, डिफ़ॉल्ट रूप से अभी भी 0 के साथ समाप्त होता है, इसलिए कवरेज सक्षम करने से किसी मौजूदा हार्नेस को विफल नहीं किया जा सकता। जब कुछ भी लॉन्च नहीं किया गया हो, तो इसके बजाय एग्ज़िट कोड 3 प्राप्त करने के लिए --exit-code-on-skip पास करें:```bash hate_crack --exit-code-on-skip hashes.txt dict

0 = ran, 1 = bad input, 2 = unknown command, 3 = everything was already covered

Exit 3 का मतलब है कि *कुछ भी* नहीं चला। एक पास जो आंशिक रूप से फ़िल्टर किया गया था — कुछ प्रविष्टियाँ छोड़ी गईं, कुछ आज़माई गईं — फिर भी `0` के साथ बाहर निकलता है, क्योंकि हमले ने वास्तव में काम किया।

### hashcat brain समर्थन (`brain_enabled`)

hashcat स्वयं एक "brain" के साथ आता है — एक छोटा सर्वर जिस पर एक चल रहा hashcat इंस्टेंस उम्मीदवार पासवर्ड स्ट्रीम करता है, ताकि उसी लक्ष्य के विरुद्ध दूसरा रन उन उम्मीदवारों को छोड़ सके जो पहले ही आज़माए जा चुके हैं। hate_crack इसे स्वचालित रूप से सक्रिय करता है, बिना किसी मेनू चरण की आवश्यकता के: जब भी यह किसी hash मोड के विरुद्ध हमला शुरू करने वाला होता है जिसे hashcat धीमा बताता है (bcrypt, scrypt, और अन्य KDF-समर्थित मोड, जहाँ hash स्वयं बाधा है न कि उम्मीदवार जनरेशन), तो यह एक स्थानीय brain सर्वर शुरू या पुनः उपयोग करता है और आपके लिए hashcat इनवोकेशन में `--brain-*` फ़्लैग जोड़ देता है। एक तेज़ मोड को अकेला छोड़ दिया जाता है, जब तक कि उसका मोड नंबर `brain_modes_force` में सूचीबद्ध न हो, और `brain_modes_exclude` में सूचीबद्ध मोड hashcat के अपने निर्णय की परवाह किए बिना कभी भी brain को सक्रिय नहीं करता — exclude हमेशा जीतता है।

**Brain हमला कवरेज जैसी चीज़ नहीं है, और दोनों पूरक हैं, अनावश्यक नहीं।** कवरेज (ऊपर) पूरे नियमों, मास्क लाइनों और वर्डलिस्टों के स्तर पर डी-डुप्लिकेट करता है — यह तय करता है कि सबसे पहले क्या लॉन्च करना है, इससे पहले कि hashcat कभी चले। Brain व्यक्तिगत उम्मीदवार पासवर्डों के स्तर पर डी-डुप्लिकेट करता है, और यह एक स्थायी सर्वर के माध्यम से करता है जो किसी भी एक hashcat इनवोकेशन से अधिक समय तक जीवित रहता है, इसलिए यह उस ओवरलैप को पकड़ता है जिसे कवरेज नहीं देख सकता: एक उम्मीदवार जो एक ही रन के भीतर दो अलग-अलग नियमों या दो अलग-अलग वर्डलिस्टों के माध्यम से पहुँचा जा सकता है, और — जैसा कि `tests/e2e/test_brain_e2e.py` में राउंड ट्रिप प्रदर्शित करता है — वही उम्मीदवार उसी लक्ष्य के विरुद्ध दूसरे, अलग hashcat रन में फिर से भेजे जाते हैं। दोनों को एक साथ बिना किसी टकराव के सक्षम किया जा सकता है।

`config.json` में सात कुंजियाँ इसे नियंत्रित करती हैं, सभी `brain_*` प्रीफ़िक्स के अंतर्गत: `brain_enabled` (मास्टर स्विच, डिफ़ॉल्ट रूप से चालू), `brain_host` (खाली का मतलब है कि hate_crack लूपबैक पर एक स्थानीय सर्वर प्रबंधित करता है; एक मान का मतलब है कि केवल उस होस्ट से कनेक्ट करें — hate_crack कभी भी ऐसा सर्वर नहीं बनाता जिसे प्रबंधित करने के लिए उसे न कहा गया हो), `brain_port` (डिफ़ॉल्ट `6863`), `brain_client_features` (`1` हैश्ड पासवर्ड, `2` हमला स्थितियाँ, `3` दोनों — `3` सबसे अधिक डी-डुप्लिकेट करता है लेकिन सर्वर को प्रति देखे गए उम्मीदवार पर लगभग 12 बाइट RAM का खर्च आता है), `brain_server_timer` (hashcat की अपनी सेटिंग कि सर्वर कितनी बार अपना `.ldmp`/`.admp` डंप डिस्क पर लिखता है, न्यूनतम 60 सेकंड, डिफ़ॉल्ट `300`), और `brain_modes_force` / `brain_modes_exclude` (कॉमा-सेपरेटेड hash-मोड नंबर जो hashcat के अपने धीमा/तेज़ निर्णय को ओवरराइड करते हैं, exclude को प्राथमिकता मिलती है)।

**स्वतः-उत्पन्न सर्वर का कोई आइडल टाइमआउट नहीं है।** `brain_server_timer` यह नियंत्रित नहीं करता कि यह कितने समय तक चालू रहता है — कुछ भी नियंत्रित नहीं करता; यह उस प्रक्रिया के जीवनकाल तक चलता है जिसने इसे उत्पन्न किया (या जब तक `shutdown()`/`atexit` इसे रोक न दे) और सत्र के प्रत्येक हमले में पुनः उपयोग किया जाता है। `300` के डिफ़ॉल्ट पर, इसका मतलब है कि जब तक hate_crack चल रहा है, हर पाँच मिनट में `~/.hate_crack/brain/` में एक डंप राइट होता है।

आठवीं कुंजी, `BRAIN_PASSWORD`, `config.json` के बजाय `.env` में रहती है क्योंकि यह एक साझा रहस्य है, इसलिए नहीं कि brain एक तृतीय-पक्ष एकीकरण है — इसका उपयोग केवल तब किया जाता है जब आप पहले से चला रहे रिमोट brain सर्वर से कनेक्ट करते हैं; स्वतः-उत्पन्न स्थानीय सर्वर प्रति सत्र अपना स्वयं का यादृच्छिक पासवर्ड उत्पन्न करता है और उसे किसी कॉन्फ़िगरेशन की आवश्यकता नहीं होती।

**brain पासवर्ड hashcat रन के जीवनकाल तक `ps` को दिखाई देता है,** क्योंकि hashcat इसे केवल कमांड-लाइन आर्गुमेंट के रूप में स्वीकार करता है — कोई एनवायरनमेंट-वेरिएबल रूप नहीं है। स्थानीय स्वतः-उत्पन्न सर्वर के लिए यह एक छोटी खिड़की है: पासवर्ड यादृच्छिक है और उस एक सत्र तक सीमित है, इसलिए कोई अन्य स्थानीय उपयोगकर्ता इसे केवल तभी देख सकता है जब कोई हमला वास्तव में चल रहा हो, और सत्र समाप्त होने के बाद यह बेकार है। साझा रिमोट brain सर्वर के पासवर्ड में ऐसी कोई कमी नहीं है — यह प्रत्येक इनवोकेशन पर समान मान होता है, मशीन पर किसी भी अन्य स्थानीय उपयोगकर्ता को तब तक दिखाई देता है जब तक उस सर्वर के विरुद्ध कोई भी hate_crack रन प्रगति पर है। साझा या मल्टी-टेनेंट हार्डवेयर पर तदनुसार व्यवहार करें।

`brain_enabled` की परवाह किए बिना एकल रन के लिए brain को अक्षम करने के लिए `--no-brain` पास करें, या इसे हर जगह बंद करने के लिए `config.json` में `brain_enabled` को `false` पर सेट करें।

**Brain `~/.hate_crack/brain/` में स्थिति रखता है** — प्रति hashcat संस्करण hashcat के अपने धीमा/तेज़ निर्णय का एक छोटा `slow_modes.json` कैश, साथ ही स्वतः-उत्पन्न सर्वर के लिए, उसकी `.ldmp`/`.admp` डंप फ़ाइलें। वे डंप उम्मीदवार-व्युत्पन्न सामग्री हैं: वे एक नए सर्वर को यह जानते हुए फिर से शुरू करने देते हैं कि किसी लक्ष्य के विरुद्ध पहले क्या आज़माया जा चुका है, जिसका एक एंगेजमेंट पर मतलब है कि क्लाइंट-व्युत्पन्न डेटा ऑपरेटर की होम डायरेक्टरी में तब तक जमा होता रहता है जब तक brain वहाँ कभी चला हो। ऊपर दिए गए कवरेज स्टोर की तरह, डायरेक्टरी को हटाने से brain रीसेट हो जाता है — पहले अस्वीकृत उम्मीदवार याद रखना बंद हो जाता है, उस डी-डुप्लिकेशन को खोने की कीमत पर जो उस डंप ने दर्शाया था। यदि brain ऐसा काम छोड़ रहा है जो उसे नहीं छोड़ना चाहिए (पिछले, भिन्न-दायरे वाले रन से एक पुराना डंप), तो यही समाधान है।

**`~/.hate_crack/brain/` को हटाना एक अनाथ सर्वर को साफ़ नहीं करता।** स्वतः-उत्पन्न सर्वर अपने स्वयं के सत्र में चलता है (`start_new_session=True`) ताकि यह बंद किए गए टर्मिनल या SIGHUP से बच जाए — केवल एक स्पष्ट kill, या इसे उत्पन्न करने वाली प्रक्रिया का साफ़-सुथरे ढंग से बाहर निकलना और उसके `atexit` हैंडलर का चलना, इसे रोकता है। एक अनाथ लूपबैक पोर्ट को पकड़े रहता है। डिफ़ॉल्ट खाली `BRAIN_PASSWORD` के साथ, आप इसे हर धीमे-मोड हमले पर `"[!] ... no brain server could be reached; running without candidate de-duplication"` के रूप में देखेंगे: अनाथ का पासवर्ड अल्पकालिक था और उसे उत्पन्न करने वाली प्रक्रिया के साथ समाप्त हो गया, इसलिए hate_crack उस पोर्ट को अपनाने से इनकार कर देता है जिस पर वह बैठा है, बजाय ऐसे पासवर्ड का अनुमान लगाने के जिसे सत्यापित नहीं किया जा सकता। इसे खोजें और रोकें:```bash
pgrep -f 'hashcat --brain-server'
kill <pid>

जिसके बाद अगला हमला हमेशा की तरह एक नया सर्वर spawn करता है।

Notifications (मेनू विकल्प 82)

hate_crack हमलों के पूरा होने पर Pushover push notifications भेज सकता है और, वैकल्पिक रूप से, जब अलग-अलग hashes crack होते हैं। सभी नियंत्रण मुख्य-मेनू विकल्प 82 — Notifications के अंतर्गत हैं:

  1. Toggle Pushover Notifications [ON/OFF] — मास्टर स्विच। config.json में notify_enabled के रूप में persist होता है।
  2. Toggle Per-Crack Notifications [ON/OFF] — जब ON हो, एक background tailer .out फ़ाइल को watch करता है और प्रत्येक crack के लिए एक notification push करता है (per-tick burst aggregation के साथ)। config.json में notify_per_crack_enabled के रूप में persist होता है। मास्टर स्विच OFF होने पर इसे enable नहीं किया जा सकता — पहले विकल्प 1 enable करें।
  3. Send Test Pushover Notification — एक canned push भेजता है ताकि आप पुष्टि कर सकें कि आपका Pushover token/user pair काम करता है। मास्टर स्विच OFF होने पर भी काम करता है।

Credentials .env में रहते हैं; शेष tuning knobs केवल config-file में config.json में हैं:

  • NOTIFY_PUSHOVER_TOKEN, NOTIFY_PUSHOVER_USER (.env में) — किसी भी push के fire होने के लिए आवश्यक। मेनू में कुछ भी इन्हें नहीं लिखता; .env स्वयं edit करें।
  • notify_attack_allowlist — attack names जो [y/N/always] prompt के बिना auto-consent होते हैं। जब आप always उत्तर देते हैं तो स्वचालित रूप से populate हो जाता है।
  • notify_suppress_in_orchestrators (default true) — Extensive Crack द्वारा chained individual attacks को silence करता है, जो इसके बजाय एक single summary fire करता है। प्रत्येक chained attack के लिए notification पाने के लिए इसे false पर सेट करें। अन्य मेनू entries जो कई passes चलाती हैं (उदाहरण के लिए multiple rule chains के साथ Quick Crack) orchestrators नहीं हैं और हमेशा प्रति pass notify करती हैं।
  • notify_max_cracks_per_burst (default 5), notify_poll_interval_seconds (default 5.0) — per-crack tailer tuning। burst aggregation logic के लिए hate_crack/notify/tailer.py देखें।

Wordlist Tools (मेनू विकल्प 80)

Wordlist Tools submenu hashcat-utils binaries द्वारा backed wordlist preprocessing utilities प्रदान करता है, साथ ही Hashmob.net और Weakpass से wordlist downloads। मुख्य मेनू में विकल्प 80 के माध्यम से access करें।

विकल्पBinaryयह क्या करता है
1len.binलंबाई के अनुसार filter करें - केवल min और max लंबाई के बीच के शब्द रखें
2req-include.binCharacter classes आवश्यक करें - केवल वे शब्द रखें जिनमें सभी आवश्यक character types हों
3req-exclude.binCharacter classes exclude करें - वे शब्द हटाएं जिनमें कोई भी excluded character type हो
4cutb.binSubstring निकालें - प्रत्येक शब्द से एक byte range काटें
5splitlen.binलंबाई के अनुसार split करें - प्रत्येक word length के लिए अलग फ़ाइलें बनाएं (output directory में 01-64 नाम की फ़ाइलें)
6rli.bin / rli2.binशब्द घटाएं - एक या अधिक अन्य फ़ाइलों में मौजूद entries हटाएं
7gate.binShard - कई machines पर distributed cracking के लिए प्रत्येक N-th शब्द निकालें
8-Wordlists optimize करें - dedupe करें और optimized wordlists directory के अंतर्गत per-length फ़ाइलों में split करें
9-Hashmob.net से wordlists download करें
10-Weakpass से wordlists download करें (BitTorrent के माध्यम से)

Character class mask bits (विकल्प 2 और 3 द्वारा उपयोग किए जाते हैं): 1=lowercase, 2=uppercase, 4=digit, 8=symbol, 16=other। मानों को जोड़ें: 7 = lowercase+uppercase+digit।

Sharding का उपयोग कैसे किया जाना चाहिए: sharding एक wordlist को N बराबर, non-overlapping भागों में split करता है ताकि काम कई machines या GPUs पर फैलाया जा सके। प्रत्येक भाग interleaved होता है (प्रत्येक N-th line), इसलिए प्रत्येक shard पूरी सूची का एक representative sample है, न कि एक contiguous front/back chunk — कोई भी single node केवल low-probability tail crack करने में नहीं फंसता।

विकल्प 7 एक बार चलाएं, इसे एक input wordlist, एक output base path, और एक shard count (N) दें। यह एक ही pass में सभी N भाग लिखता है, जिनके नाम zero-padded part numbers के साथ होते हैं (base.001, base.002, … base.00N तक)। प्रत्येक node पर एक भाग copy करें और उस node के hashcat run को उस पर point करें। single-GPU system पर sharding कोई speedup नहीं देता, लेकिन पूरी सूची के लिए commit करने से पहले quick triage pass के लिए एक single part अभी भी एक तेज़, representative sample है।

Automatic Update Checks

hate_crack startup पर GitHub में नए releases के लिए स्वचालित रूप से check कर सकता है। यह feature check_for_updates config option द्वारा नियंत्रित होता है:```json { "check_for_updates": true }

- **`check_for_updates`** — स्टार्टअप पर स्वचालित संस्करण जाँच सक्षम करें (डिफ़ॉल्ट: `true`)।
- सक्षम होने पर, hate_crack GitHub से नवीनतम रिलीज़ जानकारी प्राप्त करता है और यदि कोई अपडेट उपलब्ध हो तो सूचना प्रदर्शित करता है।
- जाँच अतुल्यकालिक रूप से चलती है और स्टार्टअप को अवरुद्ध नहीं करती। नेटवर्क त्रुटियाँ चुपचाप अनदेखी की जाती हैं।

##### अपडेट चैनल

| चैनल | फ़्लैग | स्रोत | आपको क्या मिलता है |
|---------|------|--------|--------------|
| Release | `--update` | `main` | नवीनतम कटी हुई रिलीज़। यह डिफ़ॉल्ट है और स्टार्टअप जाँच यही प्रस्तावित करती है। |
| Nightly | `--nightly` | `nightly-dev` | वह कार्य जो CI पास कर चुका है लेकिन अभी रिलीज़ नहीं हुआ है। |

संस्करण सामान्य semver का पालन करते हैं, बंप बैच में वास्तव में जो है उससे निकाला जाता है। दूसरा घटक **केवल फ़ीचर्स के लिए** बढ़ता है: किसी भी `feat` कमिट वाला चक्र `X.(Y+1).0` की ओर बढ़ रहा है, और केवल फ़िक्स, डॉक्स और चोर्स वाला चक्र `X.Y.(Z+1)` की ओर बढ़ रहा है।

`nightly-dev` उस संस्करण के लिए रिलीज़ कैंडिडेट्स को टैग करता है जिसकी ओर बैच बढ़ रहा है — `v2.20.1rc1`, `v2.20.1rc2`, … — और `main` में मर्ज करने पर वही लक्ष्य अपनी अंतिम रिलीज़ में पदोन्नत हो जाता है। कैंडिडेट्स वास्तविक PEP 440 प्री-रिलीज़ हैं, इसलिए वे दोनों सिरों पर सही क्रम में रहते हैं:

    2.20.0  <  2.20.1rc1  <  2.20.1rc2  <  2.20.1  <  2.21.0rc1  <  2.21.0

लक्ष्य चक्र के बीच में बदल सकता है: पहला `feat` लैंड होने पर इसे `X.Y.(Z+1)` से `X.(Y+1).0` में बदल देता है, और नए लक्ष्य के लिए कैंडिडेट नंबरिंग फिर से शुरू हो जाती है। संख्या हमेशा वही नाम देती है जो बैच आज शिप करेगा।

मेजर घटक कभी स्वचालित रूप से बंप नहीं होता — एक `!` सब्जेक्ट या `BREAKING CHANGE:` फ़ुटर एक फ़ीचर के रूप में गिना जाता है, क्योंकि स्वचालित मेजर एक गलत टाइप की गई सब्जेक्ट लाइन से एक अपरिवर्तनीय प्रकाशित रिलीज़ की दूरी पर होता है। मेजर एक स्पष्ट मानवीय कार्य है: इसे हाथ से टैग और पुश करें।

नीति `tools/next_version.py` में रहती है, जो दोनों टैगिंग वर्कफ़्लो द्वारा साझा की जाती है और `tests/test_next_version.py` में यूनिट-टेस्टेड है।

स्टार्टअप जाँच केवल रिलीज़ ही प्रस्तावित करती है, क्योंकि नाइटली बिल्ड कोई GitHub रिलीज़ प्रकाशित नहीं करते और जाँच GitHub के "latest release" एंडपॉइंट को पढ़ती है — इसलिए `check_for_updates` सक्षम करने पर आपको कभी नाइटली पर नहीं खींचेगा। अब दो चीज़ें चैनलों को अलग रखती हैं: वह, और यह तथ्य कि एक कैंडिडेट वास्तविक PEP 440 प्री-रिलीज़ है, इसलिए कच्चे संस्करण संख्याओं को रैंक करने वाला टूल भी इसे उस रिलीज़ से पुराना मानता है जो यह बनता है।

कोई भी फ़्लैग पहले आपके चेकआउट को संबंधित ब्रांच पर स्विच करता है (और यदि आपके पास अनकमिटेड परिवर्तन हैं तो ऐसा करने से मना कर देता है)। यदि आप नाइटली चला रहे हैं और रिलीज़ किए गए कोड पर वापस जाना चाहते हैं, तो `--update` आपको `main` पर वापस ले जाता है।

#### स्वचालित फ़ाउंड हैश मर्जिंग (केवल डाउनलोड लेफ़्ट)

लेफ़्ट हैश (अनक्रैक्ड हैश) डाउनलोड करते समय, hate_crack स्वचालित रूप से:
1. एक सहायक ऑपरेशन के रूप में Hashview से कोई भी फ़ाउंड (क्रैक्ड) हैश डाउनलोड करने का प्रयास करता है
2. फ़ाउंड हैश को स्थानीय `.out` फ़ाइलों के साथ मर्ज करता है (जैसे, `left_1_123.txt.out` या pwdump प्रारूप के लिए `left_1_123.nt.txt.out`)
3. डुप्लिकेट प्रविष्टियाँ हटाता है
4. मर्ज करने के बाद अस्थायी स्प्लिट फ़ाइलों को साफ़ करता है

यह सुनिश्चित करता है कि अनक्रैक्ड हैश के साथ काम करते समय आपके स्थानीय क्रैकिंग परिणाम Hashview के केंद्रीकृत डेटाबेस के साथ सिंक्रनाइज़ रहें।

**नोट:** डाउनलोड-फ़ाउंड विकल्प संदर्भ उद्देश्यों के लिए पहले से क्रैक किए गए हैश को अलग से डाउनलोड करता है और कोई मर्जिंग या क्रैकिंग के लिए प्रॉम्प्ट नहीं करता।

<hash_type> `hashcat --help` चलाकर प्राप्त किया जाता है

उदाहरण हैश: http://hashcat.net/wiki/doku.php?id=example_hashes```
$ hashcat --help |grep -i ntlm
   5500 | NetNTLMv1                                        | Network protocols
   5500 | NetNTLMv1 + ESS                                  | Network protocols
   5600 | NetNTLMv2                                        | Network protocols
   1000 | NTLM                                             | Operating-Systems

| -s | --server | Server URL (default: http://localhost:8080) | | -t | --token | Authentication token | | -o | --output | Output file path | | -f | --format | Output format: json, yaml, csv | | -v | --verbose | Enable verbose logging | | -q | --quiet | Suppress non-error output | | -h | --help | Show help message | | -V | --version | Show version information |

Environment Variables

VariableDescription
SCANNER_SERVER_URLServer URL
SCANNER_TOKENAuthentication token
SCANNER_OUTPUT_DIRDefault output directory
SCANNER_LOG_LEVELLog level: debug, info, warn, error
SCANNER_TIMEOUTRequest timeout in seconds

Examples

# Basic scan
scanner scan --target example.com

# Scan with custom output format
scanner scan --target example.com --format json --output results.json

# Scan multiple targets from file
scanner scan --input targets.txt --output results.csv --format csv

# Scan with authentication
scanner scan --target example.com --token "your-api-token"

# Verbose scan with custom server
scanner scan --target example.com --server https://scanner.example.com --verbose

Configuration File

The scanner supports a configuration file located at ~/.scanner/config.yaml:

server:
  url: "http://localhost:8080"
  timeout: 30

auth:
  token: "your-api-token"

output:
  format: "json"
  directory: "./results"

logging:
  level: "info"
  file: "./scanner.log"

Exit Codes

CodeDescription
0Success
1General error
2Invalid arguments
3Authentication failure
4Network error
5Scan timeout
$ ./hate_crack.py 1000

/ | _____ / | ____ _ ___ ____________ ____ | | __ / ~ __ \ / __ \ / \ /_ __ _ \ / | |/ / \ Y // __ | | \ / \ _| | // __ \ _| < ___| /(__ /| _ >______ /|__| ( /___ >|_
/ / /
___/ / / / / Version 2.0

-------------------------------------------------------------------
## परीक्षण

परीक्षण सूट अधिकतर ऑफ़लाइन है और mocks/fixtures का उपयोग करता है। लाइव नेटवर्क जाँच और
सिस्टम निर्भरता जाँच environment variables के माध्यम से opt-in हैं।

### स्थानीय रूप से परीक्षण चलाना```bash
# Run all tests
uv run pytest -v

# Run specific test
uv run pytest tests/test_hashview.py -v

आप make test के साथ पूरा सूट भी चला सकते हैं।

लाइव टेस्ट (ऑप्ट-इन)

लाइव जाँच सक्षम करने के लिए निम्नलिखित में से कोई भी सेट करें:

  • HASHMOB_TEST_REAL=1 — लाइव Hashmob कनेक्टिविटी/CLI मेनू जाँच
  • HASHVIEW_TEST_REAL=1 — लाइव Hashview CLI मेनू जाँच
  • WEAKPASS_TEST_REAL=1 — लाइव Weakpass CLI मेनू जाँच
  • HATE_CRACK_REQUIRE_DEPS=1 — यदि 7z, transmission-daemon, या transmission-remote अनुपस्थित हो तो विफल करें

लाइव Hashview अपलोड टेस्ट

लाइव Hashview अपलोड टेस्ट डिफ़ॉल्ट रूप से छोड़ दिया जाता है। इसे चलाने के लिए, पर्यावरण चर सेट करें और .env में वैध क्रेडेंशियल प्रदान करें:```bash HATE_CRACK_RUN_LIVE_TESTS=1 uv run pytest tests/test_upload_cracked_hashes.py -v

### स्थानीय Docker स्टैक के विरुद्ध लाइव Hashview परीक्षण

किसी दूरस्थ Hashview सर्वर पर लाइव परीक्षणों को इंगित करने के बजाय, आप सूट को एक स्थानीय [Hashview](https://github.com/hashview/hashview) Docker स्टैक स्पिन अप करने, उसे सीड करने, उसके विरुद्ध लाइव परीक्षण चलाने, और उसे टियर डाउन करने दे सकते हैं। `HASHVIEW_TEST_LOCAL=1` सेट करें और `HASHVIEW_REPO` को एक Hashview चेकआउट पर इंगित करें:```bash
HASHVIEW_TEST_LOCAL=1 HASHVIEW_REPO=~/projects/hashview \
  HATE_CRACK_SKIP_INIT=1 uv run pytest tests/test_hashview_cli_subcommands_subprocess.py -v

यह Hashview रेपो में docker compose को शुरू करता है, एक एडमिन API key, एक ग्राहक, एक hashfile, और क्रैक किया गया "effective task" डेटा सीड करता है, फिर उन HASHVIEW_* env vars को एक्सपोर्ट करता है जिन्हें टेस्ट पढ़ते हैं। उपयोगी env vars:

  • HASHVIEW_TEST_LOCAL=1 — लोकल स्टैक सक्षम करें (अन्यथा no-op)
  • HASHVIEW_REPO=<path> — Hashview चेकआउट (डिफ़ॉल्ट ~/projects/hashview)
  • HASHVIEW_KEEP=1 — सेशन के बाद कंटेनर चलते रहने दें (तेज़ पुनः-रन)
  • HASHVIEW_LOCAL_PORT=5000 — होस्ट पोर्ट जिस पर ऐप प्रकाशित होता है

hate_crack CLI HASHVIEW_URL / HASHVIEW_API_KEY environment variables का पालन करता है (उन दो keys वाले .env को ओवरराइड करते हुए), जिसके कारण सूट CLI को आपके सहेजे गए कॉन्फ़िगरेशन को संपादित किए बिना लोकल स्टैक की ओर इंगित कर सकता है।

एंड-टू-एंड इंस्टॉल टेस्ट (लोकल + Docker)

लोकल uv टूल इंस्टॉल + स्क्रिप्ट निष्पादन (एक अस्थायी HOME का उपयोग करता है):```bash HATE_CRACK_RUN_E2E=1 uv run pytest tests/test_e2e_local_install.py -v

Docker-आधारित एंड-टू-एंड इंस्टॉल/रन (`Dockerfile.test` के माध्यम से कैश्ड):```bash
HATE_CRACK_RUN_DOCKER_TESTS=1 uv run pytest tests/test_docker_script_install.py -v

Docker E2E परीक्षण rockyou का एक छोटा सबसेट भी डाउनलोड करता है और बाहरी टूल एकीकरण को मान्य करने के लिए एक बुनियादी hashcat क्रैक चलाता है।

Lima VM एंड-टू-एंड परीक्षण (केवल macOS):

पूर्वापेक्षाएँ: Lima और rsync इंस्टॉल होने चाहिए।```bash brew install lima

टेस्ट VM स्वचालित रूप से सभी Linux निर्भरताओं (hashcat, build-essential, curl, git, gzip, p7zip-full, transmission-daemon, ocl-icd-libopencl1, pocl-opencl-icd, uv) के साथ प्रोविज़न हो जाता है।```bash
HATE_CRACK_RUN_LIMA_TESTS=1 uv run pytest tests/test_lima_vm_install.py -v

यह परीक्षण macOS पर एक हल्के Linux VM के भीतर इंस्टॉलेशन और निष्पादन को मान्य करता है।

परीक्षण संरचना

  • tests/test_hashview.py: HashviewAPI क्लास के लिए मॉक किए गए API प्रतिक्रियाओं के साथ व्यापक परीक्षण सूट, जिसमें शामिल हैं:
    • ग्राहक सूची और डेटा सत्यापन
    • प्रमाणीकरण और प्राधिकरण परीक्षण
    • Hashfile अपलोड कार्यक्षमता
    • पूर्ण जॉब निर्माण वर्कफ़्लो

सभी परीक्षण मॉक किए गए API कॉल का उपयोग करते हैं, इसलिए वे Hashview सर्वर से कनेक्टिविटी के बिना चल सकते हैं।


(1) Quick Crack (2) Extensive Pure_Hate Methodology Crack (3) Brute Force Attack (4) Top Mask Attack (5) Fingerprint Attack (6) Combinator Attacks (7) Hybrid Attack (8) Pathwell Top 100 Mask Brute Force Crack (9) PRINCE Attack (10) Bandrel Methodology (11) Loopback Attack (12) LLM Attack (13) OMEN Attack (14) Ad-hoc Mask Attack (15) Markov Brute Force Attack (16) N-gram Attack (17) Permutation Attack (18) Random Rules Attack (19) Combipow Passphrase Attack (20) PCFG Attack (21) PRINCE-LING Attack (22) Spoonman Attack (23) Rosetta Attack (24) Corporate Masks Brute Force (25) Smart Mask Attack

(80) Wordlist Tools (81) Rule File Tools (82) Notifications (83) Mask Tools

(93) Regenerate .out from POT file (94) Hashview API (95) Analyze hashes with Pipal (96) Export Output to Excel Format (97) Display Cracked Hashes (98) Display README (99) Quit

Select a task:```

Option 94 — Hashview API is only listed when HASHVIEW_API_KEY is set in .env.

The YOLO, Middle, and Thorough Combinator attacks were previously at keys 10-12. They now live in the Combinator Attacks submenu (option 6) along with Combinator3 and CombinatorX.

Quick Crack

Runs a dictionary attack against wordlists in your hcatOptimizedWordlists directory (falls back to hcatWordlists if not configured) and optionally applies rules. Multiple rules can be selected by comma-separated list, and chains can be created with the '+' symbol. Pressing Enter at the wordlist prompt uses the configured optimized wordlists directory as the default.

Selecting a directory — including that default — expands to the wordlists directly inside it before hashcat runs. Subdirectories are not searched, matching hashcat's own behaviour for a directory in the dictionary position, and dot-files and .7z/.torrent/.out files are skipped, which hashcat would otherwise try to read. The candidates are the same either way; the expansion is what lets attack coverage track each wordlist separately, since a directory has no content fingerprint to key on. If the expansion finds nothing — an empty directory, or one holding only subdirectories or archives — the attack aborts rather than launching hashcat with no wordlist, which would put it in stdin mode and leave it reading the terminal.

आप कौन सा/से नियम चलाना चाहेंगे?
(1) best64.rule
(2) d3ad0ne.rule
(3) T0XlC.rule
(4) dive.rule
(99) YOLO...सभी नियम चलाएँ
आप जिन नियमों को चलाना चाहते हैं उनकी अल्पविराम से अलग की गई सूची दर्ज करें। नियमों को श्रृंखलाबद्ध रूप से चलाने के लिए + प्रतीक का उपयोग करें।
उदाहरण के लिए 1+1 best64.rule को दो बार श्रृंखलाबद्ध रूप से चलाएगा और 1,2 best64.rule और फिर d3ad0ne.rule को क्रमिक रूप से चलाएगा।
समझदारी से चुनें:```




#### Extensive Pure_Hate Methodology Crack
Runs several attack methods provided by Martin Bos (formerly known as pure_hate):
  * Brute Force Attack (7 characters)
  * Dictionary Attack
    * All wordlists in `hcatWordlists` with `best64.rule`
    * `rockyou.txt` with `d3ad0ne.rule`
    * `rockyou.txt` with `T0XlC.rule`
  * Top Mask Attack (Target Time = 4 Hours)
  * Fingerprint Attack
  * Smart Mask Attack
  * Combinator Attack
  * Hybrid Attack
  * Extra - Just For Good Measure
    - Runs a dictionary attack using `rockyou.txt` with chained `combinator.rule` and `InsidePro-PasswordsPro.rule` rules

#### Brute Force Attack
Brute forces all characters with the choice of a minimum and maximum password length.

#### Top Mask Attack
Uses StatsGen and MaskGen from PACK (https://thesprawl.org/projects/pack/) to perform a top mask attack using passwords already cracked for the current session.
Presents the user a choice of target cracking time to spend (default 4 hours).

#### Fingerprint Attack
https://hashcat.net/wiki/doku.php?id=fingerprint_attack

Runs a fingerprint attack using passwords already cracked for the current session. Expander substring length escalates automatically (7, 14, 21, ... up to the chosen ceiling), and an optional wordlist can be combined against the expanded fragments in addition to self-combination. Set `hcatFingerprintWordlist` in `config.json` to a default wordlist path so the prompt offers it instead of asking for a path every time; leave it as `""` to always ask (or skip).

#### Smart Mask Attack
Looks for literal "skeleton" patterns shared by 3+ already-cracked passwords for the current session -- e.g. a fixed stem like `CrawlingHorse` followed by a run of digits, or `ChangeMe2day` followed by digits and symbols drawn from a consistent charset. Every qualifying pattern runs against the full remaining hash list, so other accounts sharing a stem get swept up even though brute-forcing the stem itself was never tried.

Patterns with a fixed run at either end -- nearly all of them -- are grouped by mask and run as hybrid attacks (`-a 6` when the mask trails the stem, `-a 7` when it leads), with every pattern's literal stem a line in that group's wordlist. Dozens of patterns that vary the same way therefore become one hashcat pass over one wordlist rather than one mask line each. Whatever cannot be grouped that way -- variation at *both* ends, which leaves no fixed run to seed a wordlist with -- falls back to a single `-a 3` mask file, and has its charsets widened (up to `?a`) to compensate, as far as the guardrail below allows.

Prompts once, before the attack starts, for an optional per-pattern candidate-count guardrail (default 50,000,000,000; 0 disables it) that excludes any individual pattern whose keyspace is too large without blocking the rest.

#### Combinator Attack
https://hashcat.net/wiki/doku.php?id=combinator_attack

Runs a combinator attack using the "rockyou.txt" wordlist.

#### Hybrid Attack
https://hashcat.net/wiki/doku.php?id=hybrid_attack

* Runs sixteen hybrid passes per wordlist, cheapest first. Each mask length
  from 1 to 4 is tried appended and then prepended, first over `?s?d` and then
  over `?a`, and a single ctrl-C abandons the whole attack rather than only the
  current pass.
  - Hybrid Wordlist + Mask - ?s?d wordlists/rockyou.txt ?1
  - Hybrid Mask + Wordlist - ?s?d ?1 wordlists/rockyou.txt
  - ... the same for ?1?1, ?1?1?1 and ?1?1?1?1
  - Hybrid Wordlist + Mask - wordlists/rockyou.txt ?a
  - Hybrid Mask + Wordlist - ?a wordlists/rockyou.txt
  - ... the same for ?a?a, ?a?a?a and ?a?a?a?a

  `?a` is every printable character, so the second group is a superset of the
  first plus letters and roughly 24x the work at the longest mask — over
  rockyou.txt those passes alone are ~1.2e15 candidates, about ten hours for
  NTLM on hardware doing 32 GH/s. That is why the cheap `?s?d` group runs first
  and why the attack as a whole is time-bounded:

  - `hcatHybridMaxRuntime` in `config.json`, in seconds, default `3600`, is the
    time the **whole attack** may spend — not the time one pass may spend. All
    sixteen passes share one deadline, and each is handed whatever is left of it
    as hashcat's `--runtime`. Any pass the budget does not reach is reported
    rather than skipped quietly. Set it to `0` for no limit, which runs every
    pass to exhaustion.

  Within each group the order is by mask length across every wordlist rather
  than all lengths of one wordlist and then the next, so a budget that runs out
  has still given every wordlist its cheap passes.

  Each pass declares what it covers to the attack-coverage store, so a repeat
  hybrid against the same hash file offers to skip the passes already run. A
  pass that runs out of budget is not recorded, so it will be retried.
  Wordlist entries may be glob patterns or directories; both are expanded
  before hashcat runs, a directory into the wordlists directly inside it.
  Subdirectories are not searched, matching hashcat's own behaviour, and
  dot-files and `.7z`/`.torrent`/`.out` files are skipped — a Weakpass
  download leaves archives in the wordlists directory and hashcat would
  otherwise try to read them.

#### Pathwell Top 100 Mask Brute Force Crack
Runs a brute force attack using the top 100 masks from KoreLogic:
https://blog.korelogic.com/blog/2014/04/04/pathwell_topologies

#### PRINCE Attack
https://hashcat.net/events/p14-trondheim/prince-attack.pdf

Runs a PRINCE attack using wordlists/rockyou.txt

#### YOLO Combinator Attack
Runs a continuous combinator attack using random wordlists from the configured wordlists directory for the left and right sides.

#### Middle Combinator Attack
https://jeffh.net/2018/04/26/combinator_methods/

Runs a modified combinator attack adding a middle character mask:
wordlists/rockyou.txt + masks + worklists/rockyou.txt

Where the masks are some of the most commonly used separator characters:
2 4 <space> - _ , + . &

#### Thorough Combinator Attack
https://jeffh.net/2018/04/26/combinator_methods/

* Runs many rounds of different combinator attacks with the rockyou list.
  - Standard Combinator attack: rockyou.txt + rockyou.txt
  - Middle Combinator attack: rockyou.txt + ?n + rockyou.txt
  - Middle Combinator attack: rockyou.txt + ?s + rockyou.txt
  - End Combinator attack: rockyou.txt + rockyou.txt + ?n
  - End Combinator attack: rockyou.txt + rockyou.txt + ?s
  - Hybrid middle/end attack: rockyou.txt + ?n + rockyou.txt + ?n
  - Hybrid middle/end attack: rockyou.txt + ?s + rockyou.txt + ?s


#### Bandrel Methodology

Prompts for comma-separated names and creates a pseudo hybrid attack by capitalizing the first letter and adding up to six additional characters at the end. Each word is limited to a total of five minutes.

  - Built-in common words (seasons, months) included as a customizable `config.json` entry (`bandrel_common_basedwords`)
  - The default five-minute time limit is customizable via `bandrelmaxruntime` in `config.json`

#### Loopback Attack
https://hashcat.net/wiki/doku.php?id=loopback_attack

Uses hashcat's loopback mode to feed cracked passwords from the current session back into the attack pipeline with rules applied. This generates new password candidates based on variations of already-cracked passwords, which is particularly effective for finding related passwords that follow similar patterns.

* Prompts for rule selection to apply to the loopback candidates
* Uses an empty wordlist with the --loopback flag to process previously cracked passwords
* Automatically downloads Hashmob rules if no rules are available locally

#### LLM Attack
Uses a local LLM — Ollama by default, or a vLLM / OpenAI-compatible server via `LLM_BACKEND` — to generate password candidates for a capture-the-flag scenario. Prompts for the fake company name, industry, location, and parent company / acquisition history, then sends these details to the configured LLM model to produce likely password candidates using industry terms and company name permutations. The generated candidates are fed into a hashcat wordlist+rules attack.

* Requires a running server at `OLLAMA_HOST` (default: `http://localhost:11434`, Ollama's port; override in `.env` or the environment) already serving the model — hate_crack does not auto-pull
* Candidate generation uses structured (JSON) output via Atomic Agents, so pick a model with good schema adherence (default: `qwen3:4b-instruct`)
* Configurable backend, model, context window, request timeout, and sample size via `.env` (see [LLM Configuration](#llm-configuration))
* Prompts for target company name, industry, location, and parent company / acquisition history. The industry, location, and parent company prompts are pre-filled with the local model's guesses about the named organization (editable, and clearly labelled as guesses rather than verified OSINT); disable with `ollamaAutoResearch: false`
* Alternatively derives basewords from a sample **wordlist**, or from the **cracked passwords** of the current session (`<hashfile>.out`) so the model mirrors the target organization's own password conventions and produces new candidates in that style (only offered once something has been cracked)
* A live spinner with an elapsed-seconds counter runs during generation, and requests are bounded by `ollamaTimeout` so a model stuck loading into VRAM reports a timeout instead of hanging

**Pattern rules mode** (option 4 in the LLM submenu) takes the same shape as the [Spoonman Attack](#spoonman-attack) — a baseword list run through a rule file, both derived from one corpus — but infers each side with the model instead of extracting it. Spoonman is exact and therefore bounded: its basewords all appear in the corpus and its rules only reproduce transformations the corpus already shows. This asks the model to generalize on both axes, so it can name the *word families* behind a sample (the company and its products, site names, local sports teams, seasons, mascots) and write decorations the corpus does not contain.

* Pattern source is either the current session's cracked passwords (offered first, and only once something has been cracked, since those reveal the target's real conventions) or a sample wordlist
* **You are not asked to pick a rule file.** The model writes one, from the same corpus statistics — a stock rule file encodes the internet's habits, and the point of spending a model round trip is to encode *this* organization's
* Basewords are normalized to lowercase letters only, discarding anything under 3 characters, so the generated rules supply case, digits, and punctuation exactly once

Read more

श्रेणियाँ