Talk:Sony Update Downloads
From Exploitee.rs
I worked on expanding the pad a bit. Here's the script I use.
#!/usr/bin/perl
use strict;
package abliss;
my $start = shift;
open HEX, "<./history/other/RfHid_v0156_2010091601_NL.hex" or die;
open OUT, ">>pad.bin";
open IN, "<pad.bin";
my @files = (
"./history/NBL/batch_sync-vfat.sh",
"./history/board_conf.sh",
"./history/other/check_spectra1_20100929.sh",
"./history/other/factory_reset_conditional_keepremote_20101012.sh",
"./history/other/format_sda_20100514.sh");
my @fds;
for (my $i = 0; $i <= $#files; $i++) {
open (my $fd, $files[$i]) or die "can't open " . $files[$i];
push(@fds, $fd);
}
my @contents;
my $hexbyte;
my @hexchars = qw(0 1 2 3 4 5 6 7 8 9 A B C D E F :);
push(@hexchars, "\r");
push(@hexchars, "\n");
my @output = ();
our $xorbyte;
while (read(HEX, $hexbyte, 1)) {
for (my $i = 0; $i <= $#files; $i++) {
my $char;
if (read($fds[$i], $char, 1)) {
$contents[$i] .= $char;
if (length($contents[$i]) > 30) {
$contents[$i] = substr($contents[$i], 1);
}
}
}
if ($start-- > 0) {
my $char;
read(IN, $char, 1);
$xorbyte = ord($char);
} else {
for (my $j = 0; $j <= $#hexchars; $j++) {
$xorbyte = ord($hexbyte) ^ ord($hexchars[$j]);
my $choices = "";
my $ok = 1;
for (my $i = 0; $i <= $#files; $i++) {
my $neword = (ord(substr($contents[$i],length($contents[$i]) - 1)) ^ $xorbyte);
if ($neword > 127 ||
($neword < 32 &&
$neword != 9 && # tab
$neword != 10 && # LF
$neword != 13 # CR
)) {
$ok = 0;
#printf "==== %2d ====\n%s\n", $j, xorlastbyte($contents[$i]);
last;
}
}
if ($ok) {
printf "==== %2d ====\n%s\n", $j, join("\n--\n", map {xorlastbyte($_)} @contents);
}
}
my $answer = <STDIN>;
chomp $answer;
if ($answer eq "q") {
close OUT;
die;
}
$xorbyte = ord($hexbyte) ^ ord($hexchars[$answer]);
print OUT chr($xorbyte);
}
@contents = map {xorlastbyte($_)} @contents;
}
sub xorlastbyte {
my $content = shift;
if ($content) {
my @chars = split(//, $content);
$chars[-1] = chr(ord($chars[-1])^ $xorbyte);
return join('', @chars);
}
}
Here's my pad, 134 chars:
00000000 38 cf 4f aa 7a 8a 2e 3e 2b 41 82 9a ad 31 e9 dc |8.O.z..>+A...1..|
00000010 ef 47 2f 0b 26 76 12 fe 5f 5b 58 e1 10 18 7d e6 |.G/.&v.._[X...}.|
00000020 ad 92 1b 91 8e 90 69 f7 8a 9b 68 d8 98 58 fa 95 |......i...h..X..|
00000030 63 81 d6 5f 04 7d 29 8b 09 cf b9 21 b8 d9 df dd |c.._.})....!....|
00000040 c4 7e 71 d9 3f 35 ea 7b 0d ec 7f d1 a3 76 64 88 |.~q.?5.{.....vd.|
00000050 a5 8e 27 49 60 c0 a0 bc 77 54 31 e3 d6 6a bf e5 |..'I`...wT1..j..|
00000060 1b 42 25 da a3 97 b8 e1 ba 54 13 5b 68 31 da ff |.B%......T.[h1..|
00000070 1c 5c 15 46 4e 32 f1 76 50 e0 4e f3 ab 9a 28 bb |.\.FN2.vP.N...(.|
00000080 b5 cf 2f 50 24 45 |../P$E|
I checked the checksums in the .hex file and they all validate so far.
Catrane 2011.02.11: Nice work, Abliss. It sounds like we're running similar approaches. Here's my script. It prints one line for each byte, listing all the possibilities. I then do a human search for anything that looks predictable and work it by hand. The 756 byte key I posted was also verified using the .hex checksums in addition to visual inspection. The typos in the code make visual inspection a little tricky.
#!/usr/bin/perl
use strict;
use warnings;
use IO::File;
my @files = ();
my @filters = ();
my @rules = ();
my %ruleinfo = ();
my $files_left = 0;
#my $textfilter = "[[:print:]\x0a\x0b\t\n\r\f ]";
my $textfilter = "[[:print:]\x0a\t ]";
my $intelhexfilter = "[0-9A-F:\x0d\x0a]";
my $knownmasks = "";
if ( -f 'knownmasks' )
{
$knownmasks = `cat knownmasks`;
}
sub checkRules
{
my ($rule,$char) = @_;
if ( "text" eq $ruleinfo{$rule}{'type'} )
{
} elsif ( "intelhex" eq $ruleinfo{$rule}{'type'} ) {
if ( $ruleinfo{$rule}{'is_colon'} )
{
return 0 unless ( ":" eq $char );
}
if ( $ruleinfo{$rule}{'was_colon'} > 0 )
{
return 0 if ( ($ruleinfo{$rule}{'was_colon'} < 12) && ("\x0a" eq $char) );
return 0 if ( ($ruleinfo{$rule}{'was_colon'} < 11) && (("\x0a" eq $char) || ("\x0d" eq $char)) );
return 0 if ( ":" eq $char );
}
return 0 if ( ( ":" eq $char ) && ! $ruleinfo{$rule}{'was_maybe_0a'} );
return 0 if ( ( "\x0a" eq $char ) && ! $ruleinfo{$rule}{'was_maybe_0d'} );
}
return 1;
}
sub advanceRules
{
my ($rule,$options) = @_;
if ( "text" eq $ruleinfo{$rule}{'type'} )
{
} elsif ( "intelhex" eq $ruleinfo{$rule}{'type'} ) {
my $is_nr = ( $options =~ m/^\\[nr]\\[nr]$/ );
# 0d0a == \r\n
my $is_maybe_0d = ( $options =~ m/\\r/ );
my $is_maybe_0a = ( $options =~ m/\\n/ );
if ( $ruleinfo{$rule}{'was_colon'} )
{
$ruleinfo{$rule}{'was_colon'}++;
if ( $ruleinfo{$rule}{'was_colon'} > 12 )
{
$ruleinfo{$rule}{'was_colon'} = 0;
}
}
if ( $ruleinfo{$rule}{'is_colon'} )
{
$ruleinfo{$rule}{'is_colon'} = 0;
$ruleinfo{$rule}{'was_colon'} = 1;
} elsif ( $ruleinfo{$rule}{'was_nr'} ) {
$ruleinfo{$rule}{'is_colon'} = $is_nr;
}
$ruleinfo{$rule}{'was_nr'} = $is_nr;
$ruleinfo{$rule}{'was_maybe_0d'} = $is_maybe_0d;
$ruleinfo{$rule}{'was_maybe_0a'} = $is_maybe_0a;
}
}
while ( my $filter = shift )
{
if ( "text" eq $filter )
{
push(@filters,$textfilter);
push(@rules,$files_left);
$ruleinfo{$files_left}{'type'} = "text";
} elsif ( "intelhex" eq $filter ) {
push(@filters,$intelhexfilter);
push(@rules,$files_left);
$ruleinfo{$files_left}{'type'} = "intelhex";
$ruleinfo{$files_left}{'is_colon'} = 1; # First must be colon.
$ruleinfo{$files_left}{'was_colon'} = 0;
$ruleinfo{$files_left}{'was_nr'} = 1; # Make like normal colon setup.
$ruleinfo{$files_left}{'was_maybe_0d'} = 0;
$ruleinfo{$files_left}{'was_maybe_0a'} = 1; # Make like normal colon setup.
} elsif ( "test_text" eq $filter ) {
my $counter = 0;
my $fh = IO::File->new("< ".shift) or die "Unable to open file.\n";
while ( defined( my $char = getc($fh) ) )
{
die "failed test at index $counter.\n" unless ( $char =~ m/$textfilter/ );
$counter++;
}
print "test passed.\n";
exit;
} elsif ( "test_intelhex" eq $filter ) {
my $counter = 0;
my $fh = IO::File->new("< ".shift) or die "Unable to open file.\n";
while ( defined( my $char = getc($fh) ) )
{
die "failed test at index $counter.\n" unless ( $char =~ m/$intelhexfilter/ );
$counter++;
}
print "test passed.\n";
exit;
} else {
die "Invalid filter '$filter'.\n";
}
my $file = shift;
die "Missing filename parameter.\n" unless defined $file;
die "File '$file' does not exist.\n" unless ( -f $file );
my $fh = IO::File->new("< $file") or die "Unable to open file '$file'.\n";
push(@files,$fh);
$files_left++;
}
while ( $files_left )
{
my @options = ("\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07","\x08","\x09","\x0a","\x0b","\x0c","\x0d","\x0e","\x0f",
"\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17","\x18","\x19","\x1a","\x1b","\x1c","\x1d","\x1e","\x1f",
"\x20","\x21","\x22","\x23","\x24","\x25","\x26","\x27","\x28","\x29","\x2a","\x2b","\x2c","\x2d","\x2e","\x2f",
"\x30","\x31","\x32","\x33","\x34","\x35","\x36","\x37","\x38","\x39","\x3a","\x3b","\x3c","\x3d","\x3e","\x3f",
"\x40","\x41","\x42","\x43","\x44","\x45","\x46","\x47","\x48","\x49","\x4a","\x4b","\x4c","\x4d","\x4e","\x4f",
"\x50","\x51","\x52","\x53","\x54","\x55","\x56","\x57","\x58","\x59","\x5a","\x5b","\x5c","\x5d","\x5e","\x5f",
"\x60","\x61","\x62","\x63","\x64","\x65","\x66","\x67","\x68","\x69","\x6a","\x6b","\x6c","\x6d","\x6e","\x6f",
"\x70","\x71","\x72","\x73","\x74","\x75","\x76","\x77","\x78","\x79","\x7a","\x7b","\x7c","\x7d","\x7e","\x7f",
"\x80","\x81","\x82","\x83","\x84","\x85","\x86","\x87","\x88","\x89","\x8a","\x8b","\x8c","\x8d","\x8e","\x8f",
"\x90","\x91","\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\x9a","\x9b","\x9c","\x9d","\x9e","\x9f",
"\xa0","\xa1","\xa2","\xa3","\xa4","\xa5","\xa6","\xa7","\xa8","\xa9","\xaa","\xab","\xac","\xad","\xae","\xaf",
"\xb0","\xb1","\xb2","\xb3","\xb4","\xb5","\xb6","\xb7","\xb8","\xb9","\xba","\xbb","\xbc","\xbd","\xbe","\xbf",
"\xc0","\xc1","\xc2","\xc3","\xc4","\xc5","\xc6","\xc7","\xc8","\xc9","\xca","\xcb","\xcc","\xcd","\xce","\xcf",
"\xd0","\xd1","\xd2","\xd3","\xd4","\xd5","\xd6","\xd7","\xd8","\xd9","\xda","\xdb","\xdc","\xdd","\xde","\xdf",
"\xe0","\xe1","\xe2","\xe3","\xe4","\xe5","\xe6","\xe7","\xe8","\xe9","\xea","\xeb","\xec","\xed","\xee","\xef",
"\xf0","\xf1","\xf2","\xf3","\xf4","\xf5","\xf6","\xf7","\xf8","\xf9","\xfa","\xfb","\xfc","\xfd","\xfe","\xff");
my $options_left = 256;
if ( $knownmasks =~ s/^(..)\n// )
{
my $knownmask = $1;
if ( $knownmask =~ m/[0-9a-f]{2}/i )
{
my $val;
eval('$val = "\\x'.$knownmask.'";');
$options[0] = $val;
$options_left = 1;
}
}
my @filechars = ();
for ( my $i = 0; $i < $files_left; $i++ )
{
my $char = getc($files[$i]);
if ( defined($char) )
{
$filechars[$i] = $char;
my $filter = $filters[$i];
for ( my $x = 0; $x < $options_left; $x++ )
{
#print "$x vs $options_left\n";
# print "char is $char\n";
# print "option is $options[$x]\n";
my $realchar = $char ^ $options[$x];
unless ( ($realchar =~ m/$filter/) && checkRules($rules[$i],$realchar) )
{
splice(@options,$x,1);
$x--;
$options_left--;
}
}
} else {
$files[$i]->close;
splice(@files,$i,1);
splice(@filters,$i,1);
splice(@rules,$i,1);
$i--;
$files_left--;
}
}
last unless $files_left;
die "Failed to solve.\n" unless $options_left;
for ( my $i = 0; $i < $files_left; $i++ )
{
my $options = "";
for ( my $x = 0; $x < $options_left; $x++ )
{
my $realchar = $filechars[$i] ^ $options[$x];
$realchar = "\\t" if ( $realchar eq "\t" );
$realchar = "\\r" if ( $realchar eq "\r" );
$realchar = "\\n" if ( $realchar eq "\n" );
#$realchar = "\\v" if ( $realchar eq "\v" );
$realchar = "\\v" if ( $realchar eq "\x0b" );
$realchar = "\\a" if ( $realchar eq "\x0a" );
$realchar = "\\f" if ( $realchar eq "\f" );
$realchar = "\\s" if ( $realchar eq " " );
$options .= $realchar;
}
print $options."\n" unless $i;
advanceRules($rules[$i],$options);
}
}
print "Done\n";