Сергей Попов
Администратор
- 30.12.2015
- 6 231
- 6 971
- Специализация
- OSINT
- Веб-безопасность
- Статус верификации
- ✓ Verified
Около 800 тысяч MD5-хешей в секунду на одном ядре CPU - столько выдаёт Python-скрипт с
hashlib. hashcat на GPU обходит эту цифру на четыре порядка (проверяется командой hashcat -b -m 0). И всё же написать хешкрекер на Python стоит - не ради конкуренции с hashcat, а для случаев, когда 450+ встроенных алгоритмов (по данным hashcat.net) не покрывают нужную схему хеширования. CTF crypto-таски с кастомным md5(salt + sha1(password)), проприетарные форматы из реверса приложений, нестандартные salt-схемы - тут самописный инструмент даёт flag быстрее, чем ковыряние в hashcat-модулях. Проверено на собственных нервах.Хешкрекер своими руками: место в цепочке атаки
В классификации MITRE ATT&CK крекинг хешей - техника Password Cracking (T1110.002, тактика Credential Access). Типичная цепочка на пентесте: сначала получаем хеши через OS Credential Dumping (T1003) - дамп/etc/shadow, SAM-базы, NTDS.dit - затем офлайн-подбор пароля по хешу. Результат - учётные данные для lateral movement.Для стандартных задач (NTLM, MD5, SHA-256, bcrypt, WPA-хендшейки) hashcat - безоговорочный лидер: оптимизированные ядра, in-kernel rule engine, поддержка распределённого крекинга через overlay, автоматический тюнинг. Но написать hashcracker руками оправдано в нескольких сценариях:
- CTF crypto/misc - задача с нестандартной хеш-функцией, которой нет в hashcat
- Реверс проприетарного формата - приложение использует самодельную KDF
- Обучение - разобраться, как работает перебор паролей на уровне байтов
- Автоматизация - интеграция крекера в пайплайн пентест-инструментов без вызова внешних процессов
Брутфорс хешей на Python: однопоточная версия
Окружение: Python 3.8+, модульhashlib (стандартная библиотека), 2+ ГБ RAM. Работает на любой ОС без дополнительных зависимостей. Для GPU-раздела ниже понадобится NVIDIA GPU с CUDA Toolkit или AMD с ROCm.Логика тупая до неприличия: генерируем все комбинации символов заданной длины, считаем хеш каждого кандидата и сравниваем с целевым:
Python:
import hashlib, itertools, string, time
# Проверка: hashlib.md5(b'abc123').hexdigest() == 'e99a18c428cb38d5f260853678922e03'
target = "e99a18c428cb38d5f260853678922e03" # md5("abc123")
charset = string.ascii_lowercase + string.digits
start = time.time()
for length in range(1, 7):
for candidate in itertools.product(charset, repeat=length):
word = "".join(candidate)
if hashlib.md5(word.encode()).hexdigest() == target:
print(f"Found: {word} in {time.time()-start:.2f}s")
exit()
Почему threading не работает для перебора
GIL (Global Interpreter Lock) в CPython блокирует параллельное выполнение Python-байткода на нескольких ядрах. Модульthreading не ускорит CPU-bound задачу - потоки конкурируют за один lock. Кто первый раз на это натыкается - обычно удивляется: «Я же 8 потоков запустил, почему скорость та же?» Для параллельного перебора паролей нужен multiprocessing: отдельные процессы с изолированной памятью, каждый со своим интерпретатором.Многопоточный брутфорс Python с multiprocessing
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
деградирует при большом смещении (O(start_idx) на пропуск) - и это ловушка, на которую попадают многие. Заявленные ниже цифры достижимы лишь с генерацией кандидата по индексу через модульную арифметику. С такой оптимизацией 8 performance-ядер дают примерно 7x прирост (не идеальные 8x из-за IPC-overhead). На том же i7-12700 с 8 ядрами: порядка 6 млн MD5 h/s.
Для сравнения: hashcat на CPU использует OpenCL runtime (PoCL или Intel CPU Runtime) как интерфейс к векторизованным SIMD-ядрам (AVX2/AVX-512), написанным вручную под каждый алгоритм, - это даёт сотни миллионов MD5 h/s. Python вызывает C-реализацию OpenSSL через
hashlib, но накладные расходы интерпретатора и строковые операции съедают производительность. Разница - два порядка, и это только CPU.Что ещё можно выжать без GPU:
hashlibчерезupdate()вместо пересоздания объекта каждый раз - экономит аллокации- Генерация кандидатов в C через
ctypesили Cython - убирает Python-overhead на строки multiprocessing.shared_memory(Python 3.8+) для передачи результата без pickle-сериализации
Хешкрекер на Golang: горутины против Python-процессов
Go решает проблему GIL в лоб: горутины - легковесные потоки, которые рантайм автоматически распределяет по ядрам CPU. Создание горутины обходится в ~8 КБ стека; Python multiprocessing создаёт полноценные ОС-процессы (fork с copy-on-write на Linux, реальный overhead памяти ниже полной копии, но IPC/pickle-сериализация и GIL-обход через отдельные интерпретаторы добавляют ощутимые накладные расходы). Хеш считается через стандартный пакетcrypto/md5 - без интерпретатора, с компиляцией в нативный код.Типичная архитектура Go-крекера: producer генерирует кандидатов и кладёт в
chan string, пул горутин-workers забирает из канала, считает хеши и сравнивает. При нахождении совпадения - результат уходит в отдельный канал, context.Cancel() останавливает остальных.| Параметр | Python multiprocessing | Go goroutines |
|---|---|---|
| Накладные расходы | Fork процесса (CoW), pickle IPC | ~8 КБ стека на горутину |
| MD5 h/s на 8 ядрах | ~6 млн | ~25–35 млн |
| GPU-ускорение | PyOpenCL / PyCUDA | Нет зрелых библиотек |
| Скорость разработки | Быстрая (itertools, hashlib) | Средняя (ручной keyspace) |
| Деплой | Нужен Python-рантайм | Один статический бинарник |
Go-версия обходит Python в 4–6 раз на CPU за счёт отсутствия интерпретатора и прямого вызова
crypto/md5. Для CTF-задач с ограниченным keyspace (6–8 символов) этого часто хватает за глаза. Для длинных паролей и стандартных алгоритмов - всё равно hashcat.Практический вывод: Go - хороший выбор для кастомных крекеров, которые должны работать на серверах без GPU (CI/CD, автоматизация пентеста). На CTF обычно достаточно Python - скорость разработки важнее скорости перебора. 30 строк на Python за 5 минут бьют 150 строк на Go за полчаса, если keyspace влезает.
GPU ускорение брутфорса: CUDA, OpenCL и пределы самописного кода
GPU - массово-параллельная архитектура: тысячи ядер, каждое считает хеш независимо. hashcat использует нативные CUDA- и OpenCL-ядра, написанные на C с ассемблерными вставками и оптимизированные под каждый алгоритм.Из документации hashcat.net: для NVIDIA GPU нужен CUDA Toolkit, для AMD на Linux - ROCm, на Windows - HIP SDK. Intel GPU работают через Intel Graphics Compute Runtime (NEO). CPU-крекинг - через Intel CPU Runtime for OpenCL или PoCL.
Можно ли получить GPU-ускорение из Python? Через PyOpenCL или PyCUDA - да. Но придётся написать OpenCL-ядро хеш-функции на C: несколько сотен строк с ручным управлением GPU-буферами, синхронизацией и подбором workgroup-размеров. Отладка GPU-кода - отдельный квест, который хочется пройти ровно один раз в жизни. Самописное ядро MD5 на PyOpenCL выдаст ориентировочно 1–5 млрд h/s в зависимости от GPU и качества кода (грубая оценка без привязки к конкретной модели). hashcat на RTX 4090 показывает ~50 млрд MD5 h/s, на RTX 3060 - ~5 млрд h/s. Разрыв варьируется от нескольких раз до порядка величины - hashcat выигрывает за счёт in-kernel rule engine, markov-chains для оптимизации keyspace и автоматического тюнинга workload.
Когда GPU-ускорение не даёт ожидаемого прироста
- bcrypt, scrypt, Argon2 - алгоритмы намеренно memory-hard, GPU не даёт линейного масштабирования. Собственно, для того их и придумали.
- Кастомные хеш-схемы - OpenCL-ядро придётся писать с нуля
- Малый keyspace - overhead на компиляцию ядра и копирование данных host↔device может превысить время самого перебора
- Отсутствие GPU - на CTF-площадке или VPS без видеокарты GPU-ускорение бесполезно
Сравнение с hashcat: trade-off таблица
| Критерий | Python/Go крекер | hashcat |
|---|---|---|
| MD5, CPU | 6–35 млн h/s | Сотни млн h/s (SIMD) |
| MD5, GPU | 1–5 млрд h/s (PyOpenCL, оценка) | ~5–50+ млрд h/s (зависит от GPU) |
| Алгоритмы | Любые (пишешь сам) | 450+ встроенных |
| Кастомные схемы | Полная гибкость | Только через модули |
| Распределённый крекинг | Реализация с нуля | Через overlay |
| Restore/resume | Реализация с нуля | Встроено |
| Rule engine | Реализация с нуля | In-kernel |
| Время на разработку | 15–60 минут | 0 |
Числа для Python/Go - оценочные, получены на i7-12700 / 8 ядер. Для hashcat запустите
hashcat -b -m 0 (MD5) или hashcat -b -m 1400 (SHA-256) - встроенный бенчмарк покажет реальную производительность на вашем железе.Когда написать хешкрекер на Python - правильный выбор
- CTF crypto/misc - кастомная схема хеширования, отсутствующая в hashcat
- Модификация логики - частичный перебор с ограничениями (известна часть пароля, нестандартная маска)
- Пайплайн - крекер как часть автоматизации на Python/Go без вызова внешних процессов
- Обучение - понять параллельные вычисления, GIL, разницу CPU vs GPU на практике
Когда не стоит изобретать велосипед
Для NTLM, MD5, SHA-256, bcrypt, WPA на стандартных словарях (rockyou, SecLists) -hashcat -m 1000 -a 0 hashes.txt rockyou.txt и не мучаться. hashcat оптимизирован годами, поддерживает restore сессий, thermal watchdog и автотюнинг. Самописный хешкрекер - не альтернатива hashcat для продакшн-пентеста: взлом хешей python-скриптом оправдан только когда стандартный инструментарий не покрывает задачу.Большинство гайдов по крекингу хешей сводятся к «поставь hashcat, запусти rockyou, жди». Для 95% рутинных задач это работает. Проблема в другом - такой подход формирует привычку не думать о механике. Когда на CTF или пентесте попадается нестандартный формат, человек теряется. Не потому что задача сложная, а потому что ни разу не писал перебор руками.
На соревнованиях видел неоднократно: команда тратит час на адаптацию hashcat к кастомной KDF, когда 30 строк Python решили бы задачу за 10 минут. Понимание того, как
multiprocessing делит keyspace, зачем GPU нужны тысячи потоков и почему bcrypt специально медленный - это не академическое знание. Это инструмент, который позволяет оценить, где hashcat подходит, а где быстрее написать скрипт.Обратная сторона: вкладывать время в GPU-ускорение самописного крекера через PyOpenCL почти всегда неоправданно. Разница с hashcat остаётся в разы, а сложность кода растёт нелинейно. Эти часы лучше потратить на отработку полной цепочки credential access - от дампа хешей до lateral movement - на живом стенде. WAPT - для тех, кому writeup'ов мало и нужны лабы с прогрессией до OSCP-стандарта.