<?php
// debug
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
});
$charset = "abcdefghijklmnopqrstuvwxyz0123456789";
$alphabet = PassCracker::createAlphabet($charset);
$hash = "e7806b130b429fc9b5890608a2c60675";
$cracker = new PassCracker(4, $alphabet, false);
$answer = $cracker->crack($hash);
echo $answer !== null ?
"Answer is $answer\n" :
"This time we're out of luck. Try googling: http://google.com/?q=$hash\n";
class PassCracker
{
private $length;
private $alphabet;
private $passwordIndexes;
private $passwordLetters;
public function __construct
($length, array $alphabet) {
$this->length = $length;
$this->alphabet = $alphabet;
}
public static function createAlphabet($string)
{
return preg_split("//u", $string, null, PREG_SPLIT_NO_EMPTY
); }
private function initCode()
{
$this->passwordIndexes = array_fill(0, $this->length, 0); $this->generatePassword();
}
private function generatePassword()
{
$this->passwordLetters = array_map(function ($index) { return $this->alphabet[$index];
}, $this->passwordIndexes);
}
public function crack($hash)
{
$this->initCode();
do {
$password = implode('', $this->passwordLetters); if (md5($password) == $hash) { return $password;
}
if (!$this->generateNextCode()) {
return null;
};
} while (true);
}
private function generateNextCode() {
$max = count($this->alphabet); for ($pos = $this->length - 1; $pos >= 0; $pos--) {
$newIndex = $this->passwordIndexes[$pos] = ($this->passwordIndexes[$pos] + 1) % $max;
$this->passwordLetters[$pos] = $this->alphabet[$newIndex];
if ($newIndex > 0) {
return true;
}
}
// No more tries
return false;
}
}
PD9waHAKCi8vIGRlYnVnCnNldF9lcnJvcl9oYW5kbGVyKGZ1bmN0aW9uICgkZXJybm8sICRlcnJzdHIsICRlcnJmaWxlLCAkZXJybGluZSApIHsKICAgIHRocm93IG5ldyBFcnJvckV4Y2VwdGlvbigkZXJyc3RyLCAkZXJybm8sIDAsICRlcnJmaWxlLCAkZXJybGluZSk7Cn0pOwoKJGNoYXJzZXQgPSAiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5IjsKJGFscGhhYmV0ID0gUGFzc0NyYWNrZXI6OmNyZWF0ZUFscGhhYmV0KCRjaGFyc2V0KTsKJGhhc2ggPSAiZTc4MDZiMTMwYjQyOWZjOWI1ODkwNjA4YTJjNjA2NzUiOwoKJGNyYWNrZXIgPSBuZXcgUGFzc0NyYWNrZXIoNCwgJGFscGhhYmV0LCBmYWxzZSk7CiRhbnN3ZXIgPSAkY3JhY2tlci0+Y3JhY2soJGhhc2gpOwplY2hvICRhbnN3ZXIgIT09IG51bGwgPyAKICAgICJBbnN3ZXIgaXMgJGFuc3dlclxuIiA6IAogICAgIlRoaXMgdGltZSB3ZSdyZSBvdXQgb2YgbHVjay4gVHJ5IGdvb2dsaW5nOiBodHRwOi8vZ29vZ2xlLmNvbS8/cT0kaGFzaFxuIjsKCmNsYXNzIFBhc3NDcmFja2VyCnsKICAgIHByaXZhdGUgJGxlbmd0aDsKICAgIHByaXZhdGUgJGFscGhhYmV0OwoKICAgIHByaXZhdGUgJHBhc3N3b3JkSW5kZXhlczsKICAgIHByaXZhdGUgJHBhc3N3b3JkTGV0dGVyczsKCiAgICBwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoJGxlbmd0aCwgYXJyYXkgJGFscGhhYmV0KQogICAgewogICAgICAgICR0aGlzLT5sZW5ndGggPSAkbGVuZ3RoOwogICAgICAgICR0aGlzLT5hbHBoYWJldCA9ICRhbHBoYWJldDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGNyZWF0ZUFscGhhYmV0KCRzdHJpbmcpCiAgICB7CiAgICAgICAgcmV0dXJuIHByZWdfc3BsaXQoIi8vdSIsICRzdHJpbmcsIG51bGwsIFBSRUdfU1BMSVRfTk9fRU1QVFkpOwogICAgfQoKICAgIHByaXZhdGUgZnVuY3Rpb24gaW5pdENvZGUoKQogICAgewogICAgICAgICR0aGlzLT5wYXNzd29yZEluZGV4ZXMgPSBhcnJheV9maWxsKDAsICR0aGlzLT5sZW5ndGgsIDApOwogICAgICAgICR0aGlzLT5nZW5lcmF0ZVBhc3N3b3JkKCk7CiAgICB9CgogICAgcHJpdmF0ZSBmdW5jdGlvbiBnZW5lcmF0ZVBhc3N3b3JkKCkKICAgIHsKICAgICAgICAkdGhpcy0+cGFzc3dvcmRMZXR0ZXJzID0gYXJyYXlfbWFwKGZ1bmN0aW9uICgkaW5kZXgpIHsKICAgICAgICAgICAgcmV0dXJuICR0aGlzLT5hbHBoYWJldFskaW5kZXhdOwogICAgICAgIH0sICR0aGlzLT5wYXNzd29yZEluZGV4ZXMpOwogICAgfQoKICAgIHB1YmxpYyBmdW5jdGlvbiBjcmFjaygkaGFzaCkKICAgIHsKICAgICAgICAkdGhpcy0+aW5pdENvZGUoKTsKICAgICAgICAkaGFzaCA9IG1iX3N0cnRvbG93ZXIodHJpbSgkaGFzaCkpOyAvLyBldmVyeXRoaW5nIG1pZ2h0IGhhcHBlbgoKICAgICAgICBkbyB7CgogICAgICAgICAgICAkcGFzc3dvcmQgPSBpbXBsb2RlKCcnLCAkdGhpcy0+cGFzc3dvcmRMZXR0ZXJzKTsKICAgICAgICAgICAgaWYgKG1kNSgkcGFzc3dvcmQpID09ICRoYXNoKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gJHBhc3N3b3JkOwogICAgICAgICAgICB9ICAgICAgICAgICAgCgogICAgICAgICAgICBpZiAoISR0aGlzLT5nZW5lcmF0ZU5leHRDb2RlKCkpIHsKICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICB9OwoKICAgICAgICB9IHdoaWxlICh0cnVlKTsKCiAgICB9CgogICAgcHJpdmF0ZSBmdW5jdGlvbiBnZW5lcmF0ZU5leHRDb2RlKCkgewogICAgICAgICRtYXggPSBjb3VudCgkdGhpcy0+YWxwaGFiZXQpOwogICAgICAgIGZvciAoJHBvcyA9ICR0aGlzLT5sZW5ndGggLSAxOyAkcG9zID49IDA7ICRwb3MtLSkgewoKICAgICAgICAgICAgJG5ld0luZGV4ID0gJHRoaXMtPnBhc3N3b3JkSW5kZXhlc1skcG9zXSA9ICgkdGhpcy0+cGFzc3dvcmRJbmRleGVzWyRwb3NdICsgMSkgJSAkbWF4OwogICAgICAgICAgICAkdGhpcy0+cGFzc3dvcmRMZXR0ZXJzWyRwb3NdID0gJHRoaXMtPmFscGhhYmV0WyRuZXdJbmRleF07CgogICAgICAgICAgICBpZiAoJG5ld0luZGV4ID4gMCkgewogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIE5vIG1vcmUgdHJpZXMKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9Cn0K