|
|
|
| Ответ 012 на задачу N 4.
С условиями задачи можно ознакомится по ссылке.
Наверное, это наглость с моей стороны - отправлять второе решение.
Но уж больно кривым смотрится первое по сравнению с ним.
Этот вариант находит все пароли сразу быстрее, чем первый находил один.
<html>
<body>
<form>
Char set: <input name=set value=abcdefghijklmnopqrstuvwxyz size=30 />
<br>Max chars: <input name=depth value=4 size=2 />
<br>Md5 hashes list:
<textarea cols=35 rows=5 name=hashlist /
>ee11cbb19052e40b07aac0ca060c23ee
dd97813dd40be87559aaefed642c3fbb
8dbc672497bdc46f88e864bb1121232c
3e10f8c809242d3a0f94c18e7addb866
7fa3b767c460b54a2be4d49030b349c7
a6105c0a611b41b08f1209506350279e
865c0c0b4ab0e063e5caa3387c1a8741
d41d8cd98f00b204e9800998ecf8427e
</textarea>
<br><input type=submit /> </form>
<?php
//----------------------------------------------------------------------
// поиск паролей для известных md5-хешей
// метод: прямой перебор строк символов заданного алфавита ограниченной длины
// строки строятся рекурсивно. Для увеличения производительности некоторые
// статические параметры определены глобально
//----------------------------------------------------------------------
global $hashlist, $tries, $set, $setlen, $start_time;
//----------------------------------------------------------------------
// result($hash, $res) заносит в отчет успешно найденный пароль $res,
// выносит хеш $hash из ключей массива $hashlist
// Возвращается число еще не найденных ключей
// глобальные параметры:
// $hashlist - массив искомый хешей (в ключах)
// $tries - счетчик попыток
// $start_time - время начала перебора (для статистики)
function result($hash, $res)
{
global $hashlist, $tries;
global $start_time;
unset($hashlist[$hash]);
$elapsed = sprintf('%.3f', mytime() - $start_time);
echo("<tr><td>$hash</td><td>$res</td><td>$tries</td><td>$elapsed</td></tr>
");
return count($hashlist);
}
//----------------------------------------------------------------------
// trypass рекурсивно пытается найти строку состоящую из $prefix
// и $width символов из набора $set, md5 которой присутствует среди ключей
// массива $hashlist. Успех регистрируется вызовом функции result.
//
// Возвращается 0, если все пароли нашлись, и не 0 в противном случае.
// корневой вызов:
// trypass("", длина пароля)
// глобальные параметры:
// $hash - искомый хеш
// $tries - счетчик попыток
// $set - строка с символами алфавита
// $setlen- её длина (опять же ради скорости)
//----------------------------------------------------------------------
function trypass($prefix, $width)
{
global $hashlist, $tries, $set, $setlen;
// самый глубокий (листовой) слой рекурсии расписан руками,
// поскольку проверки на глубину все равно оказались нужны
//(иначе не обеспечить обход множества паролей в ширину, а не в глубину.
//В глубину же пароли искать смысл невелик, поскольку на практике
//реальная его длина неизвестна, и искать надо от короткого к длинному.)
if(--$width <= 0) // листовой слой
for($i = 0; $i < $setlen; $i++)
{
++$tries; // еще одна попытка
$res = $prefix.$set{$i};
$rm5 = md5($res);
if(isset($hashlist[$rm5]))
return result($rm5, $res);
}
else // нелистовые слои
for($i = 0; $i < $setlen; $i++)
if(trypass($prefix.$set{$i}, $width) == 0)
return 0; // проверим и вернемся, если хеши кончились
return -1; // на этом уровне не нашли
}
function mytime() //обложка для вещественного time
{ //(ибо get_as_float работает лишь с 5 версии PHP)
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
if( isset($_REQUEST['hashlist'])
&& isset($_REQUEST['depth'])
&& isset($_REQUEST['set']) )
{
$set = $_REQUEST['set']; // строка с алфавитом
$setlen = strlen($set); // и его размер
$hash = explode(" ", trim($_REQUEST['hashlist']));
$hashlist = array(); // переносим строки хешей в ключи массива $haslist
foreach($hash as $v) $hashlist[trim($v)] = 0;
// формируем заголовок отчета
echo("<table><tr><td>hash</td><td>res</td><td>tries</td><td>elapsed</td></tr>
");
$start_time = mytime(); // засекаем время,
$tries = 1; // сбрасываем счетчик
// и отдельно проверяем случай пустого пароля
if(isset($hashlist['d41d8cd98f00b204e9800998ecf8427e'])) // === md5('')
result('d41d8cd98f00b204e9800998ecf8427e', '');
// далее ищем пароли длины от 1 до предельной
for($width = 1; $width <= $_REQUEST['depth']; ++$width)
if(trypass('',$width)==0) // и если нашли все пароли
break; // останавливаем поиск
$delta_time = mytime() - $start_time;
$elapsed = sprintf('%.3f', $delta_time); //считаем статистику
$pwd_per_sec = $tries/$delta_time;
$speed = sprintf('%.1f', $tries/$elapsed);
echo("</table>
Total passwords checked: $tries<br>"
."Time elapsed: $elapsed s<br>Check speed: $speed s<br>");
if(count($hashlist)) // если найдены не все
{ // выводим оставшиеся хеши
echo( "Unable to detect plaintext {$_REQUEST['depth']} chars length "
." with md5 hashes:<br>");
foreach($hashlist as $k => $v) echo( " '$k'<br>");
}
}
?>
</body>
</html>
|
http://www.softtime.ru/info/task.php?id_article=74 | |
|
|
|
|
|
|
|
для: SoftTime
(07.02.2006 в 19:34)
| | Немного громоздко, зато очень функционально и удобно, проверяется случай пустого пароля, нет вложенных циклов и обрабатываются все пароли в куче. Юзабилити и настройка скрипта - высший класс. | |
|
|
|