Brute Force PHP Script
August 22, 2008
Last weekend I came across this site, Hack This Site!. I've been able to breeze through the Basic missions for the most part, and the Javascript missions, seriously? It's pretty interesting and I know there are many other sites out there that I'm looking forward to trying out once I get far enough with this one.
I came across one mission where I had to crack a hashed password. I was feeling ambitious enough to go ahead and write a brute force script to tackle the task. I messed around an entire day trying to figure out the right combination of nested-loops to solve the problem. I came to the realization that probably the only practical way of solving this algorithm was recursion, which I had very limited experience in doing. So I started searching the web and finally came across a brute force python script written by Robert Green. I ported it over to PHP, and in a matter of seconds I was moving on to the next mission.
<?php
/*
* Thanks to Robert Green for this script he wrote in python
* http://www.rbgrn.net/blog/2007/09/how-to-write-a-brute-force-password-cracker.html
* I took what we wrote and ported this to PHP
*
* This script was written for PHP 5, but should work with
* PHP 4 if the hash() function is replaced with md5() or something else
*/
#########################################################
/* Configuration */
// this is the hash we are trying to crack
define('HASH', '098f6bcd4621d373cade4e832627b4f6');
// algorithm of hash
// see http://php.net/hash_algos for available algorithms
define('HASH_ALGO', 'md5');
// max length of password to try
define('PASSWORD_MAX_LENGTH', 4);
// available characters to try for password
// uncomment additional charsets for more complex passwords
$charset = 'abcdefghijklmnopqrstuvwxyz';
//$charset .= '0123456789';
//$charset .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
//$charset .= '~`!@#$%^&*()-_\/\'";:,.+=<>? ';
#########################################################
$charset_length = strlen($charset);
function check($password)
{
if (hash(HASH_ALGO, $password) == HASH) {
echo 'FOUND MATCH, password: '.$password."\r\n";
exit;
}
}
function recurse($width, $position, $base_string)
{
global $charset, $charset_length;
for ($i = 0; $i < $charset_length; ++$i) {
if ($position < $width - 1) {
recurse($width, $position + 1, $base_string . $charset[$i]);
}
check($base_string . $charset[$i]);
}
}
echo 'target hash: '.HASH."\r\n";
recurse(PASSWORD_MAX_LENGTH, 0, '');
echo "Execution complete, no password found\r\n";
?>

10 Comments
How could this script be modified to work on a site where there are two intput boxes name: and number, the number filed is 6 characters but can only be from 000000 to 999999? Any suggestions???
cool
Question ,
its too late to reply
but i think this script will not work good at website because there would be loop at user browser
Certainly running this through the browser would not be a good idea. If you wanted to run this through a browser, you would have to do something more advanced, where this script is "forked" or run by another script which actually runs the page.
You could then refresh the page and continously check if the script was finished yet. Or even better, something like a progress bar displayed to the user and continously updated using AJAX.
A single call to:
recurse(PASSWORD_MAX_LENGTH, 0, '');
would be more efficient because as the code exists now you are checking all passwords length 1 PASSWORD_MAX_LENGTH -1 times, all passwords length 2 PASSWORD_MAX_LENGTH -2 times, etc
If you have the script display all the passwords attempted, you can see that recurse(2, 0, ''); will also try all passwords of length 1.
@Bryan: Thanks for the comment, that does indeed seem to be more efficient. I'll update the code!
@Covi: Thanks for pointing that out. I'll update the code!
I am not sure how I feel about this script... Maybe I am not seeing the order of execution correctly, but it looks to me that this first checks 'aaaa', proceeding to 'aaab', until it gets to 'aaa?', followed by 'aaa '. After which it tries 'aaa', 'aab' .. 'aa?', 'aa ', until it works it's way back to testing single chars from 'a' to a single whitespace. Then it switches to 'baaa' and continues...
I am sure there is a simpler way to explain this, but it just seems inefficient.
First, passwords are rarely this simplistic. Usually, they must be above a certain number of chars, but below another number. Then special characters usually have a few requirements (the password can neither start nor end with a special char). And finally, a password usually can only have a certain number of special chars, and/or special chars can not be next to each-other.
I know this may seem like a lot of extra processing, but when you consider the literally BILLIONS of passwords this saves you from testing, it is worth it...
Without looking back at the way the code works, you are probably right Mike. This was not made to be robust, but was made to crack a simple MD5 hash over at hackthissite.org
Hi,
I'm trying to convert this into a C++ version, I have it working, however I have come across the problem that mine check many more permutations than necessary. I have copied the logic exactly and rather than receiving output such as:
aaab
aaacaaadaaaeaaafaaagaaahI am getting
aaaa
aaaabaaaabcaaaabcdaaaabcdeaaaabcdefaaaabcdefgaaaabcdefghetc, please could you try to explain the logic on how it does not go above 4? I tried working it out on paper, but the recursion itself is extremely confusing to write down!
Optimize ur script:
Exp:
<code>$strLenght = strlen($charset);for ($i = 0; $i < $strLenght; ++$i) { [...]}</code>;)posted by Covi @ Sep 16, 2008 09:26 PM EDT