Last active
October 4, 2017 20:35
-
-
Save aminamid/68d0fe65ffd5bcac1687 to your computer and use it in GitHub Desktop.
decode fftp pw
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use strict; | |
use warnings; | |
use Crypt::CBC; | |
use Crypt::Rijndael; | |
use Digest::SHA1 qw(sha1); | |
sub main() { | |
# FFFTPのパスワードを入力 | |
my $ffftp_password = prompt('FFFTP Password'); | |
my $tmp_password = ''; | |
if ( $ffftp_password =~ /^0A/ ) { | |
# 従来のパスワード形式 | |
$ffftp_password =~ s/^0A//; | |
$tmp_password = decode_password_original($ffftp_password); | |
} | |
elsif ( $ffftp_password =~ /^0C/ ) { | |
# マスターパスワードありの形式(AES) | |
$ffftp_password =~ s/^0C//; | |
$tmp_password = decode_password3($ffftp_password); | |
} | |
else { | |
# 従来のパスワード形式 | |
$tmp_password = decode_password_original($ffftp_password); | |
} | |
my $password = ( split( /\x00/, $tmp_password ) )[0]; | |
print $password, "\n"; | |
} | |
sub prompt { | |
my ( $msg, $default ) = @_; | |
print "$msg "; | |
if ( defined($default) and $default ne '' ) { | |
print "[$default]"; | |
} | |
print ": "; | |
my $value = <STDIN>; | |
$value =~ tr/\r\n//d; | |
if ( defined($default) and $default ne '' and $value eq '' ) { | |
$value = $default; | |
} | |
return $value; | |
} | |
sub decode_password_original { | |
my $ffftp_password = $_[0]; | |
my $idx = 0; | |
my $tmp_password = ''; | |
while ( $idx < length($ffftp_password) ) { | |
my $ord = ord( substr( $ffftp_password, $idx, 1 ) ); | |
my $ord2 = ord( substr( $ffftp_password, $idx + 1, 1 ) ); | |
my $rnd = ( $ord >> 4 ) & 0x03; | |
my $ch = ( $ord & 0x0F | ( $ord2 & 0x0F ) << 4 ); | |
$ch <<= 8; | |
if ( ( $ord & 0x01 ) != 0 ) { | |
$idx++; | |
} | |
$idx += 2; | |
$ch >>= $rnd; | |
$ch = ( $ch & 0xFF ) | ( ( $ch >> 8 ) & 0xFF ); | |
$tmp_password .= chr($ch); | |
} | |
$tmp_password .= "\x00"; | |
return $tmp_password; | |
} | |
sub decode_password3 { | |
my $ffftp_password = $_[0]; | |
my @ffftp_password = split( /:/, $ffftp_password, 2 ); | |
my $iv = pack( 'H*', $ffftp_password[0] ); | |
my $key = prompt('Master Password'); | |
my $aes_key = create_aes_key($key); | |
my $cipher = Crypt::CBC->new( | |
{ key => $aes_key, | |
key_size => length($aes_key), | |
literal_key => 1, | |
cipher => 'Rijndael', | |
iv => $iv, | |
padding => 'standard', | |
prepend_iv => 0, | |
header => 'none', | |
} | |
); | |
my $tmp_password = $cipher->decrypt( pack( 'H*', $ffftp_password[1] ) ); | |
return $tmp_password; | |
} | |
sub create_aes_key() { | |
my $key = $_[0]; | |
my $hash_key = sha1( $key . '>g^r=@N7=//z<[`:' ) | |
. sha1( $key . 'VG77dO1#EyC]$|C@' ); | |
my $key_index = 0; | |
my $res_index = 0; | |
my $aes_key = ''; | |
while ( $res_index < 8 ) { | |
my $ord | |
= ord( substr( $hash_key, $res_index * 4, 1 ) ) * 256**3 | |
+ ord( substr( $hash_key, $res_index * 4 + 1, 1 ) ) * 256**2 | |
+ ord( substr( $hash_key, $res_index * 4 + 2, 1 ) ) * 256**1 | |
+ ord( substr( $hash_key, $res_index * 4 + 3, 1 ) ) * 256**0; | |
for ( my $byte_offset = 0; $byte_offset < 4; $byte_offset++ ) { | |
$aes_key .= chr( ( $ord >> ( $byte_offset * 8 ) ) & 0xFF ); | |
} | |
$res_index++; | |
} | |
return $aes_key; | |
} | |
main(); | |
exit; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment