2012-01-11 09:15:49

Что такое Hash Query? Если коротко, то это интерпретатор (или компилятор, если угодно) декларативного языка запросов на вычисление криптографических хэшей для строк и файлов. Hash Query умеет:

  • вычислять хэш строки
  • вычислять хэш файла, в том числе и его часть (задаваемой смещением и длиной)
  • восстанавливать строку по хэшу методом грубой силы (перебор по конечному словарю)
  • вычислять хэш для файлов в заданном каталоге, с поддержкой фильтрации файлов по размеру, имени, пути
  • проверять файл с использованием известного хэша (валидация файла)
  • искать файлы с использованием известного хэша всего файла или его части

Кроме того есть:

  • Оценка времени восстановления строки с использованием грубой силы
  • Вывод хэша в разном регистре
  • Поддержка запросов из файлов и из командной строки
  • Поддержка комментариев в файлах с запросами
  • Поддержка переменных

Поддерживается следующие типы хэшей:

  • MD5
  • MD4
  • SHA1
  • SHA256
  • SHA384
  • SHA512
  • Whirlpool
  • CRC32

Использование

hq [OPTION] ...

Доступные опции:

-f [ --file ] <путь> - Полный путь к файлу c запросами на языке Hash Query

-q [ --query ] <текст> - Текст запроса на языке Hash Query

-v [ --validate ] - Проверить синтаксис запроса. Не запускать никаких действий

-t [ --time ] - Показывать время вычисления хэша (по умолчанию отключено)

-l [ --lower ] - Выводить хэш в нижнем регистре

-? [ --help ] - Показать помощь

Язык Hash Query

Этот язык представляет собой простой декларативный LINQ (Language Integrated Queries) или SQL подобный язык. Целью создания языка было желание предоставить единый, унифицированный интерфейс для работы с криптографическими хэшами строк и файлов с некоторыми дополнительными плюшками вроде восстановления строк по хэшам, поиск файлов по хэшам и пр.

Основы синтаксиса

Все задания на работу с хэшами в языке представляют собой предложения разделенные точкой с запятой ";". Они могут передаваться компилятору или через командную строку (опция -q) или быть записанными в простом текстовом файле, который потом скармливается компилятору (опция -f). В файле может быть произвольное количество запросов, но не более 10 тыс. (по соображениям производительности).

Пробельные символы в запросах (переводы строк, табуляторы и пр.) не учитываются, за исключением тех, что находятся собственно в данных (строках в кавычках или апострофах).

Общий вид запросов

Все запросы имеют вид:

for … do …;

или

let var = 'value';

После for и do идут инструкции специфичные для каждой из категорий запроса (см. далее).

Точка с запятой в конце запроса обязательна, даже в случае единичного запроса.

В инструкциях могут встречаться строки определяемые пользователем (пути к файлам, каталогам, значения хэшей, собственно строки для вычисления по ним хэша). Строка должна быть как в апострофах (одиночных кавычках), так и в обычных кавычках (двойных кавычках). В запросах передаваемых через командную строку должны использоваться апострофы (понятно почему), в запросах из файлов можно использовать любые кавычки.

В инструкциях после for, но до do могут встречаться подвыражения let и where не являющиеся обязательными.

Инструкции, начинающиеся с let, определяют переменные, которые могут быть использованы в запросах.

Подвыражение let

Подвыражение let не является обязательным и может быть опущено. Также, могут быть опущены отдельные части выражения.

Подвыражение let содержит список инструкций с разделителем запятой идущих после ключевого слова let, порядок инструкций не имеет значения. Инструкция имеет следующий вид:

<переменная>.<имя атрибута> = <значение атрибута>

Переменная — это любая последовательность латинских букв и цифр, но начинаться она должна обязательно с буквы. Переменная должна быть задано до let.

Имя атрибута является одним из зарезервированных имен.

Значением атрибута является либо строка (в апострофах или кавычках), либо целое число.

Пример:

let s.md5 = '202CB962AC59075B964B07152D234B70', s.min = 3

Подвыражение where

Подвыражение where используется для задания условий, например для фильтрации файлов по некоторым признакам.

where cостоит из выражений вида:

<переменная>.<имя атрибута> <условный оператор> <значение>

идущих после ключевого слова where и соединенных операторами конъюнкции (логическое И) — and и дизъюнкции (логическое ИЛИ) — or, или другими словами после ключевого слова where должно быть булево выражение.

Переменная — это любая последовательность латинских букв и цифр, но начинаться она должна обязательно с буквы. Переменная должна быть задано до where.

Условный оператор — это один из следующий операторов:

  • == (равно)
  • != (не равно)
  • > (больше)
  • < (меньше)
  • >= (больше или равно)
  • <= (меньше или равно)
  • ~ (соответствует регулярному выражению)
  • !~ (не соответствует регулярному выражению)

Для группировки частей выражения (изменения порядка выполнения условных операторов) могут быть использованы круглые скобки.

Пример:

where (f.md5 == '202CB962AC59075B964B07152D234B70' and f.limit == 100) or (f.offset == 10 and f.md4 == 'C58CDA49F00748A3BC0FCFA511D516CB')

Категории запросов

Все запросы можно разделить на 5 категорий:

  1. Определение переменных
  2. Запросы на вычисление хэша строки
  3. Запросы на восстановление строки по её хэшу
  4. Запросы на вычисление хэша отдельных файлов
  5. Запросы на вычисление хэша файлов в заданном каталоге

Определение переменных

Данные запросы нужны для определения переменных, ссылаться на которые можно в других запросах. Это нужно, например, для устранения дублирования одних и тех же данных, в случае если их по смыслу необходимо использовать в разных местах.

Запросы имеют следующий вид:

let <переменная> = '<строка>';

На определенную в этом запросе переменную, точнее данные, определяемые этой переменной, можно ссылаться в других запросах.

Запросы на вычисление хэша строки

Запросы имеют следующий вид:

for string '<строка>' do <хэш>;

Хэш может принимать одно из следующих значений (регистр имеет значение):

  • md5
  • md4
  • sha1
  • sha256
  • sha384
  • sha512
  • whirlpool
  • crc32

Запросы на восстановление строки по её хэшу

Общий вид запроса такой:

for string <переменная> from hash '<значение хэша>' [let …] do crack <хэш>;

Здесь хэш является одним из поддерживаемых типов хэшей (см. предыдущий раздел), значение хэша.

Подвыражение let используется для управления параметрами восстановления строки, а именно:

  1. словарь (атрибут dict)
  2. минимальная длина (атрибут min)
  3. максимальная длина (атрибут max)

Запросы на вычисление хэша отдельных файлов

Общий вид запроса:

for file f from '<путь к файлу>' [let …] do <хэш|validate>;

Такие запросы предназначены либо для вычисления хэша отдельных файлов, либо для валидации файлов по хэшу, что определяется видом инструкции do.

Подвыражение let используется для определения той части файла, по которой производится валидация или для которой вычисляется хэш. Если опущено, то используется весь файл целиком. Атрибуты могут быть следующие:

  1. Хэш (атрибут md5|md4|sha1|sha256|sha384|sha512|whirlpool|crc32) — имеет смысл только при валидации файла.
  2. Смещение относительно начала файла в байтах (атрибут offset)
  3. Размер данных для которых вычисляется хэш в байтах (атрибут limit)

Хэш может принимать одно из следующих значений (регистр имеет значение):

  • md5
  • md4
  • sha1
  • sha256
  • sha384
  • sha512
  • whirlpool
  • crc32

Запросы на вычисление хэша файлов в заданном каталоге

Общий вид запроса:

for file f from dir '<каталог>' [where ...] do <хэш|find> [withsubs];

Такие запросы предназначены либо для вычисления хэша файлов в каталоге(ах) — после do идет хэш, либо для поиска файлов (по хэшам) — после do идет ключевое слово find.

Подвыражение where используется для фильтрации файлов. Допустимые атрибуты:

  1. Имя файла (атрибут name)
  2. Полный путь к файлу включая имя (атрибут path)
  3. Размер файла в байтах (атрибут size)
  4. Хэш (атрибут md5|md4|sha1|sha256|sha384|sha512|whirlpool|crc32) — имеет смысл только при поиске файла.
  5. Смещение относительно начала файла в байтах (атрибут offset)
  6. Размер данных для которых вычисляется хэш в байтах (атрибут limit)

Опция withsubs задействует вложенные каталоги (по умолчанию выключена).

Для фильтрации файлов по имени и/или пути могут быть использованы Perl совместимые регулярные выражения (PCRE). Для фильтрации файлов по регулярным выражениям используются условные операторы ~ и !~.

Хэш может принимать одно из следующих значений (регистр имеет значение):

  • md5
  • md4
  • sha1
  • sha256
  • sha384
  • sha512
  • whirlpool
  • crc32

Формальная грамматика языка

// Определения парсера

prog
	: statement+ | EOF
	;

     
statement
    :   expr NEWLINE
    | NEWLINE
    ;

expr:
	FOR (expr_string | expr_hash | expr_dir | expr_file) | expr_vardef
    ;
	
expr_vardef:
	LET ID ASSIGN_OP STRING
	;

expr_string:
	STR source DO hash_clause
	;

expr_hash:
	STR id FROM HASH source let_clause? DO brute_force_clause
	;

expr_dir
	: FILE id FROM DIR source let_clause? where_clause? DO ( hash_clause WITHSUBS? | FIND WITHSUBS? )
	;

expr_file
	: FILE id FROM source (let_clause)? DO ( hash_clause | VALIDATE )
	;

source : STRING;
 
id : ID;

attr_clause : ID DOT attr ;

attr : str_attr | int_attr ;

hash_clause
    : MD5 | MD4 | SHA1 | SHA256 | SHA384 | SHA512 | CRC32 | WHIRLPOOL
    ;
    
brute_force_clause
	: CRACK hash_clause 
	;

let_clause
	: LET assign (COMMA assign)*
	;

where_clause
	: WHERE! boolean_expression
    ;

boolean_expression
	: conditional_or_expression
	;

conditional_or_expression
	: conditional_and_expression (OR conditional_and_expression)*
	;

conditional_and_expression
	: not_expression (AND not_expression)* 
	;

not_expression
	: exclusive_or_expression
	| NOT_OP exclusive_or_expression
	;

exclusive_or_expression
	:	relational_expr
	|	OPEN_BRACE boolean_expression CLOSE_BRACE
	;

relational_expr
	: ID DOT 
	( relational_expr_str
	| relational_expr_int
	)
	;

relational_expr_str
	:	str_attr (EQUAL | NOTEQUAL | MATCH | NOTMATCH) (STRING | ID)
	;

relational_expr_int
	:	int_attr (EQUAL | NOTEQUAL | GE | LE | LEASSIGN | GEASSIGN) INT
	;

assign 
	: ID DOT ( str_attr ASSIGN_OP STRING | str_attr ASSIGN_OP ID | int_attr ASSIGN_OP INT )
	;
 
str_attr : NAME_ATTR | PATH_ATTR | DICT_ATTR | MD5 | MD4 | SHA1 | SHA256 | SHA384 | SHA512 | CRC32 | WHIRLPOOL ; 

int_attr : SIZE_ATTR | LIMIT_ATTR | OFFSET_ATTR | MIN_ATTR | MAX_ATTR ; 

// Определения лексера

NAME_ATTR :	'name';

PATH_ATTR :	'path' ;

DICT_ATTR :	'dict' ;

SIZE_ATTR :	'size' ;

LIMIT_ATTR :	'limit' ;

OFFSET_ATTR : 'offset' ;

MIN_ATTR : 'min' ;

MAX_ATTR : 'max' ;

CRACK :	'crack' ;

WHERE :	'where' ;

OR: 'or' ;

AND: 'and' ;

NOT_OP: 'not' ;

FOR: 'for' ;

FROM: 'from' ;

DO: 'do' ;

FIND: 'find' ;

WITHSUBS : 'withsubs' ;
VALIDATE : 'validate' ;

LET	: 'let' ;

DIR	:	'dir' ;
FILE	:	'file' ;
HASH	:	'hash' ;
STR	:	'string' ;

MD5: 'md5';	
SHA1: 'sha1' ;
SHA256: 'sha256' ;
SHA384: 'sha384' ;
SHA512: 'sha512' ;
MD4: 'md4' ;
CRC32: 'crc32' ;
WHIRLPOOL: 'whirlpool' ;

fragment
STRING1 : '\'' ( options {greedy=false;} : ~('\u0027' | '\u000A' | '\u000D'))* '\'' ;

fragment
STRING2 : '"'  ( options {greedy=false;} : ~('\u0022' | '\u000A' | '\u000D'))* '"' ;

STRING : STRING1 | STRING2 ;

ID : ID_START ID_PART* ;

fragment
ID_START : '_' | 'A'..'Z' | 'a'..'z' ;

fragment
ID_PART : ID_START | '0'..'9' ;

INT :   '0'..'9'+ ;
ASSIGN_OP : ASSIGN;

NEWLINE: ';';
WS  :   (' '|'\t'| EOL )+ ;
DOT	: '.' ;
COMMA: ',' ;	
OPEN_BRACE : '(';
CLOSE_BRACE : ')';

COMMENT : ('#' | '/' '/') ~(EOL)* CR? (LF | EOF);

fragment
EOL : LF | CR ;

fragment
LF :	'\n' ;

fragment
CR :	'\r' ;
 
PLUS:	'+' ;

EQUAL:	ASSIGN ASSIGN ;
NOTEQUAL:	NOT ASSIGN ;

fragment
ASSIGN:	'=' ;
fragment
NOT:	'!' ;

GE:	'>' ;
LE:	'<' ;
MATCH:	'~' ;
NOTMATCH : NOT MATCH ;
LEASSIGN : LE ASSIGN;
GEASSIGN : GE ASSIGN;

Примеры

Вычисление SHA1 хэша для строки 123

for string '123' do sha1;

Вычисление MD5 хэша для файла

for file f from 'file.txt' do md5;

Вычисление SHA384 хэша для части файла (первый килобайт)

for file f from 'file.txt' let f.limit = 1024 do sha384;

Вычисление SHA256 хэша части файла (один килобайт с пропуском первых 512 байт)

for file f from 'file.txt' let f.limit = 1024, f.offset = 512 do sha256;

Валидация файла по его MD4 хэшу

for file f from 'file.txt' let f.md4 = 'C58CDA49F00748A3BC0FCFA511D516CB' do validate;

Вычисление SHA512 хэша всех файлов каталога c:\dir

for file f from dir 'c:\dir' do sha512;

Вычисление Whirlpool хэша всех файлов каталога c:\dir а также всех его подкаталогов

for file f from dir 'c:\dir' do whirlpool withsubs;

Вычисление CRC32 суммы всех exe файлов каталога c:\dir

for file f from dir 'c:\dir' where f.name ~ '.*exe$' do crc32;

Вычисление MD5 хэша всех файлов каталога c:\dir кроме файлов с расширением tmp

for file f from dir 'c:\dir' where f.name !~ '.*tmp$' do md5;

Вычисление MD5 хэша всех exe и dll файлов каталога c:\dir

for file f from dir 'c:\dir' where f.name ~ '.*exe$' or f.name ~ '.*dll$' do md5;

Вычисление MD5 хэша всех exe файлов каталога c:\dir исключая те из них, которые начинаются с bad

for file f from dir 'c:\dir' where f.name !~ '^bad.*' do md5;

Поиск файла на диске C:\ по известному MD4 хэшу

for file f from dir 'c:\' where f.md4 == 'C58CDA49F00748A3BC0FCFA511D516CB' do find withsubs;

Восстановление строки по её MD4 хэшу используя словарь по умолчанию

for string s from hash '3689CA24BF71B39B6612549D87DCEA68' do crack md4;

Восстановление строки по её MD4 хэшу используя свой словарь

for string s from hash '3689CA24BF71B39B6612549D87DCEA68' let s.dict = '0123456789' do crack md4;

Восстановление строки по её MD4 хэшу используя свой словарь сокращенная форма (одни цифры)

for string s from hash '3689CA24BF71B39B6612549D87DCEA68' let s.dict = '0-9' do crack md4;

Восстановление строки по её MD4 хэшу используя свой словарь сокращенная форма (одни буквы в нижнем регистре)

for string s from hash '3689CA24BF71B39B6612549D87DCEA68' let s.dict = 'a-z' do crack md4;

Восстановление строки по её MD4 хэшу используя свой словарь сокращенная форма (цифры, буквы в нижнем и верхнем регистрах)

for string s from hash '3689CA24BF71B39B6612549D87DCEA68' let s.dict = '0-9a-zA-Z' do crack md4;

Восстановление строки по её MD4 хэшу используя свой словарь и определенные длины строки

for string s from hash '3689CA24BF71B39B6612549D87DCEA68' let s.dict = '0123456789', s.min = 2, s.max = 6 do crack md4;

Использование файлов с запросами

Создайте текстовый файл queries.hq, например со следующим содержимым:

# string query - this is comment
for string '123' 
do sha1;

# file query  - this is comment
for file f 
from dir 'c:\dir' 
where f.name !~ '^bad.*' 
do md5;

Далее запустите компилятор указав ему на этот файл:

hq.exe -f queries.hq

Будет выполнено 2 запроса из файла

Использование переменных

Переменные удобны чтобы не дублировать одни и те же данные много раз при использовании их в разных запросах. Например:

# query that calculates md5 and sha1 for some files in a directory

let path = 'c:\dir';
let mask = '^bad.*';

for file f 
from dir path 
where f.name !~ mask 
do md5;

for file f 
from dir path 
where f.name !~ mask 
do sha1;

Загружать из

ВАЖНО: загружать уже нужно новый хэш-калькулятор 3. 0 т. к. старый не работал на 32-разрядной системе. Все что описано тут, применимо и к версии. 3. 0

2012-01-11 09:15:49  soft hacking noweb md5 sha1 tool hash
comments powered by Disqus