Bitcoin Forum
November 13, 2024, 11:41:17 PM *
News: Check out the artwork 1Dq created to commemorate this forum's 15th anniversary
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Lost Password Recovery script PHP -aes-256-cbc Andreas Schilbach Bitcoin Wallet  (Read 1594 times)
blibble (OP)
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
December 04, 2013, 07:24:02 PM
 #1

I have created a script to recover encrypted private keys from Andreas Schilbach's Bitcoin Wallet app.  I have used it successfully on one backup file.  I have others I haven't managed to work out with this script but I think that is because I haven't a clue where to start with the password.  This is only a best guess type checker.  It will take a single password or an array of passwords and try common typos of each character.  It will also try changing every single character of every single typo as well.  lower case, upper case, all characters and numbers.  It probably needs improving to cover areas I've missed if anyone would like to help? as it may then help me.  It will probably be adaptable for cracking other wallets too with some changes to how it checks if it has been successful.  It borrows some of the logic from the script found here: https://bitcointalk.org/index.php?topic=85495.0

Script requires php with opensll enabled in php.ini and an encrypted bitcoin wallet string.

Usage, p.php?p=yourbestguessatpassword

or fill out the $guesses array at the top of the script

For more info about the wallet backup file:
http://bitcoin-wallet.googlecode.com/git/wallet/README

blibble (OP)
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
December 04, 2013, 07:31:34 PM
 #2

Code:

<?php

//script requires openssl in php.ini to be enabled

// set memory limit incase you have a long password
ini_set('memory_limit''2048M');

//decrypt this openssl aes-256-cbc base64 salted IV string
$encrypted_file "put the private key backup string your are trying to crack here";

//these will be tried if you don't fill out the form or add ?p=guess1 so you can try lots of guesses in one go
$guesses = array('guess1','guess2');

?>


<html>
<body>
<form action="" method="post">
  <input id="p" name="p" type="text" />
  <input type="button" value="submit" />
</form>

<?php

////////////////////////////////////////////////////////////////////////

function getTypos($str) {
    
$typosArr = array();
    
$strArr str_split($str);

    
$arr_prox = array();

   
//lower typos
    
$arr_prox['a'] = array('q''w''z''x','Q''W''Z''X');
    
$arr_prox['b'] = array('v''f''g''h''n','V''F''G''H''N');
    
$arr_prox['c'] = array('x''s''d''f''v','X''S''D''F''V');
    
$arr_prox['d'] = array('x''s''w''e''r''f''v''c','X''S''W''E''R''F''V''C');
    
$arr_prox['e'] = array('w''s''d''f''r''W''S''D''F''R');
    
$arr_prox['f'] = array('c''d''e''r''t''g''b''v''C''D''E''R''T''G''B''V');
    
$arr_prox['g'] = array('r''f''v''t''b''y''h''n','R''F''V''T''B''Y''H''N');
    
$arr_prox['h'] = array('b''g''t''y''u''j''m''n','B''G''T''Y''U''J''M''N');
    
$arr_prox['i'] = array('u''j''k''l''o''U''J''K''L''O');
    
$arr_prox['j'] = array('n''h''y''u''i''k''m','N''H''Y''U''I''K''M');
    
$arr_prox['k'] = array('u''j''m''l''o''U''J''M''L''O');
    
$arr_prox['l'] = array('p''o''i''k''m''P''O''I''K''M');
    
$arr_prox['m'] = array('n''h''j''k''l''N''H''J''K''L');
    
$arr_prox['n'] = array('b''g''h''j''m''B''G''H''J''M');
    
$arr_prox['o'] = array('i''k''l''p''I''K''L''P');
    
$arr_prox['p'] = array('o''l''O''L');
$arr_prox['q'] = array('w''a''1''W''A''1');
    
$arr_prox['r'] = array('e''d''f''g''t''E''D''F''G''T');
    
$arr_prox['s'] = array('q''w''e''z''x''c''Q''W''E''Z''X''C');
    
$arr_prox['t'] = array('r''f''g''h''y''R''F''G''H''Y');
    
$arr_prox['u'] = array('y''h''j''k''i''Y''H''J''K''I');
    
$arr_prox['v'] = array('c''f''g''b''C''F''G''B');      
    
$arr_prox['w'] = array('q''a''s''d''e''Q''A''S''D''E''1');
    
$arr_prox['x'] = array('z''a''s''d''c''Z''A''S''D''C');
    
$arr_prox['y'] = array('t''g''h''j''u''T''G''H''J''U');
    
$arr_prox['z'] = array('x''s''a''X''S''A');

//upper typos
$arr_prox['A'] = array('Q''W''Z''X','q''w''z''x');
    
$arr_prox['B'] = array('V''F''G''H''N','v''f''g''h''n');
    
$arr_prox['C'] = array('X''S''D''F''V','x''s''d''f''v');
    
$arr_prox['D'] = array('X''S''W''E''R''F''V''C','x''s''w''e''r''f''v''c');
    
$arr_prox['E'] = array('W''S''D''F''R''w''s''d''f''r');
    
$arr_prox['F'] = array('C''D''E''R''T''G''B''V''c''d''e''r''t''g''b''v');
    
$arr_prox['G'] = array('R''F''V''T''B''Y''H''N','r''f''v''t''b''y''h''n');
    
$arr_prox['H'] = array('B''G''T''Y''U''J''M''N','b''g''t''y''u''j''m''n');
    
$arr_prox['I'] = array('U''J''K''L''O''u''j''k''l''o');
    
$arr_prox['J'] = array('N''H''Y''U''I''K''M','n''h''y''u''i''k''m');
    
$arr_prox['K'] = array('U''J''M''L''O''u''j''m''l''o');
    
$arr_prox['L'] = array('P''O''I''K''M''p''o''i''k''m');
    
$arr_prox['M'] = array('N''H''J''K''L''n''h''j''k''l');
    
$arr_prox['N'] = array('B''G''H''J''M''b''g''h''j''m');
    
$arr_prox['O'] = array('I''K''L''P''i''k''l''p');
    
$arr_prox['P'] = array('O''L''o''l');
$arr_prox['Q'] = array('W''A''1''w''a''1');
    
$arr_prox['R'] = array('E''D''F''G''T''e''d''f''g''t');
    
$arr_prox['S'] = array('Q''W''E''Z''X''C''q''w''e''z''x''c');
    
$arr_prox['T'] = array('R''F''G''H''Y''r''f''g''h''y');
    
$arr_prox['U'] = array('Y''H''J''K''I''y''h''j''k''i');
    
$arr_prox['V'] = array('C''F''G''B''c''f''g''b');      
    
$arr_prox['W'] = array('Q''A''S''D''E''q''a''s''d''e' ,'1');
    
$arr_prox['X'] = array('Z''A''S''D''C''z''a''s''d''c');
    
$arr_prox['Y'] = array('T''G''H''J''U''t''g''h''j''u');
    
$arr_prox['Z'] = array('X''S''A''x''s''a');

//numbers typos
$arr_prox['1'] = array('q''w' ,'2');
    
$arr_prox['2'] = array('q''w''e''1''3');
    
$arr_prox['3'] = array('w''e''r''2''4');
    
$arr_prox['4'] = array('e''r''t''3''5');
    
$arr_prox['5'] = array('r''t''y''4''6');
    
$arr_prox['6'] = array('t''y''u''5''7');
    
$arr_prox['7'] = array('y''u''i''6''8');
    
$arr_prox['8'] = array('u''i''o''7''9');
    
$arr_prox['9'] = array('i''o''p''8''0');
    
$arr_prox['0'] = array('o''p''-''9');

//symbols (add others symbols and nearby keys if your password has them)
$arr_prox['.'] = array('?'',''l''L'';''/');
$arr_prox['_'] = array('0''-''=''[''p''P');

    foreach(
$strArr as $key=>$value) {
        
$temp $strArr;
        foreach (
$arr_prox[$value] as $proximity){
            
$temp[$key] = $proximity;
            
$typosArr[] = join(""$temp);
        }
    }   

    return 
array_unique($typosArr);
}

function 
scramble($passphrase) {
$characters " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

$list[] = "";

$list[] = $passphrase;

 
# transpose adjacent chars
 
for($i 0$i < (strlen($passphrase) - 1); $i++) {
  
$testphrase $passphrase;
  
$testphrase[$i] = $passphrase[$i+1];
  
$testphrase[$i+1] = $passphrase[$i];
  
$list[] = $testphrase;
}
 
 
# delete one char
 
for($i 0$i < (strlen($passphrase) - 1); $i++) {
  
$testphrase implode(array_slice(str_split($passphrase), 0$i)) . implode(array_slice(str_split($passphrase),$i+2,strlen($passphrase)-$i));
  
$list[] = $testphrase;
 }
 
 
# substitutute one char
 
for($i 0$i < (strlen($passphrase) - 1); $i++) {
  
for($y 0$y < (strlen($characters) - 1); $y++) {
  $testphrase $passphrase;
   
  $testphrase[$i] = $characters[$y];
   
  $list[] = $testphrase;
}
 }
 
# insert one char
 
for($i 0$i < (strlen($passphrase) + 1); $i++) {
   for(
$y 0$y < (strlen($characters) - 1); $y++) {
   
$testphrase $passphrase;
$testphrase substr_replace($testphrase$characters[$y], $i0);
   
$list[] = $testphrase;
   }
 }
 return 
array_unique($list);
}

set_time_limit(0);
 
function 
getmicrotime() {
   list(
$usec$sec) = explode(" ",microtime());
   return ((float)
$usec + (float)$sec);

 
$original_time_start getmicrotime();
 
 
/**
   * decrypt AES 256
   *
   * @param string $password
   * @param data $edata
   * @return dencrypted data
   */
function decrypt($password$edata) {

    
$data base64_decode($edata);
    
$salt substr($data88);
    
$ct substr($data16);

    
/**
     * From https://github.com/mdp/gibberish-aes
     *
     * Number of rounds depends on the size of the AES in use
     * 3 rounds for 256
     *        2 rounds for the key, 1 for the IV
     * 2 rounds for 128
     *        1 round for the key, 1 round for the IV
     * 3 rounds for 192 since it's not evenly divided by 128 bits
     */
    
$rounds 3;
    
$data00 $password.$salt;
    
$md5_hash = array();
    
$md5_hash[0] = md5($data00true);
    
$result $md5_hash[0];
    for (
$i 1$i $rounds$i++) {
      
$md5_hash[$i] = md5($md5_hash[$i 1].$data00true);
        
$result .= $md5_hash[$i];
    }
    
$key substr($result032);
    
$iv  substr($result32,16);

      return 
openssl_decrypt($ct'aes-256-cbc'$keytrue$iv);
  } 
 
 
function 
check($password)
{
        global 
$encrypted_file$time_start;     
 
 
$decrypted_string decrypt($password$encrypted_file);
 
 
//echo $password . " : ";
 
if(substr$decrypted_string0) === "# KE" ) {
 
                echo 
"<br /><br /><h1 style='color:#00FF33'>" "FOUND MATCH, password: " $password "</h1>\n\n";
                
$time_end getmicrotime();
                
$time $time_end $time_start
                echo 
"Found in " $time " seconds\n";
                exit;
        }
}
 
 
function 
recurse($width$position$base_string)
{
        global 
$charset$str_length;
 
        for (
$i 0$i $str_length; ++$i) {
                if (
$position  $width 1) {
                        
recurse($width$position 1$base_string $charset[$i]);
                }
                
check($base_string $charset[$i]);
        }


}
echo 
"Target hash: " $encrypted_file "\n";
blibble (OP)
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
December 04, 2013, 07:37:52 PM
 #3

Code:
//typo code 

global $scrambled_typos;

$passphrase = @$_REQUEST['p'];

if(isset($_REQUEST['p'])){

$best_guesses = array($passphrase);

} else {


$best_guesses = $guesses;

// add all guesses
$scrambled_typos = array_unique($best_guesses);
}

foreach ($best_guesses as $guess) {

$time_start = getmicrotime();

$typos = getTypos($guess);

// for each typo of guesses
foreach ($typos as $typo) {

// add all typos
$scrambled_typos[] = $typo;

$scrambles = scramble($typo);

// for each scrambled typo of guesses
foreach ($scrambles as $scramble) {

// add all scrambeled typos
$scrambled_typos[] = $scramble;

}
}

echo "<br/>Checking: ".count($scrambled_typos)." passwords<br/>";
ob_flush();
flush();

foreach ($scrambled_typos as $try_this) {

check($try_this);
}

$time_check = getmicrotime();
     $time = $time_check - $time_start;
     echo "<br />" . "Runtime: " . $time . " seconds";

unset($scrambled_typos);

}


echo "<h1 style='color:#FF0000'>Execution complete, no password found\r\n</h2>";
  $time_check = getmicrotime();
     $time = $time_check - $original_time_start;
     echo "<br />" . "Runtime: " . $time . " seconds";


?>
</body>
</html>

Script is in 2 parts due to post character limit!
bitmagi
Newbie
*
Offline Offline

Activity: 26
Merit: 0


View Profile WWW
December 04, 2013, 10:49:01 PM
 #4

Hmm, php isn't really a good language for this kind of task.  I am betting one could probably find something written in C that would be exponentially faster.  Pretty cool though regardless.
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!