X-Git-Url: http://git.rot13.org/?p=perl-Mifare-MAD.git;a=blobdiff_plain;f=nfc-card-dumper.pl;h=b1e780a3f7791c25c27464f9d61fb8eebcc3beb3;hp=143ac042190f9c925fe1d9e6a51ab00b1fddda4f;hb=714e6862c419bfb0ad4ee284403e3333afefc387;hpb=d332b2f993ccf58f6e54705a3647922665b6d61e diff --git a/nfc-card-dumper.pl b/nfc-card-dumper.pl index 143ac04..b1e780a 100755 --- a/nfc-card-dumper.pl +++ b/nfc-card-dumper.pl @@ -6,15 +6,24 @@ use RFID::Libnfc::Reader; use RFID::Libnfc::Constants; use File::Slurp; use Digest::MD5 qw(md5_hex); +use Getopt::Long::Descriptive; use Data::Dump qw(dump); +my ($opt,$usage) = describe_options( + '%c %c [dump_with_keys]', + [ 'write=s', 'write dump to card' ], + [ 'debug|d', 'show debug dumps' ], + [ 'help|h', 'usage' ], +); +print $usage->text, exit if $opt->help; + my $debug = $ENV{DEBUG} || 0; my $keyfile = shift @ARGV; my $r = RFID::Libnfc::Reader->new(debug => $debug); if ($r->init()) { - printf ("Reader: %s\n", $r->name); + warn "reader: %s\n", $r->name; my $tag = $r->connect(IM_ISO14443A_106); if ($tag) { @@ -24,24 +33,22 @@ if ($r->init()) { exit -1; } - my $uid = sprintf "%02x%02x%02x%02x", unpack('C4', $tag->{_nai}->abtUid); - # @{ $tag->uid }; # FIXME this doesn't work with tags which have 00 in UID! - - warn "UID: $uid\n"; + my $uid = sprintf "%02x%02x%02x%02x", @{ $tag->uid }; - $keyfile ||= "cards/$uid.key"; + my $card_key_file = "cards/$uid.key"; + $keyfile ||= $card_key_file; if ( -e $keyfile ) { warn "# loading keys from $keyfile"; $tag->load_keys($keyfile); - warn "## _keys = ", dump($tag->{_keys}); + warn "## _keys = ", dump($tag->{_keys}) if $debug; } $tag->select if ($tag->can("select")); my $card; - print STDERR "reading"; + print STDERR "reading $uid blocks "; for (my $i = 0; $i < $tag->blocks; $i++) { if (my $data = $tag->read_block($i)) { # if we are dumping an ultralight token, @@ -56,7 +63,11 @@ if ($r->init()) { # disconnect from reader so we can run mfoc RFID::Libnfc::nfc_disconnect($r->{_pdi}); - my $file = "cards/$uid.key"; + print "Dump this card with mfoc? [y] "; + my $yes = ; chomp $yes; + exit unless $yes =~ m/y/i || $yes eq ''; + + my $file = "cards/$uid.keys"; unlink $file; warn "# finding keys for card $uid with: mfoc -O $file\n"; exec "mfoc -O $file" || die $!; @@ -76,27 +87,41 @@ if ($r->init()) { . substr($card, $o+6, 4) . $keys->[$i]->[1] . substr($card, $o+16) ; - warn "sector $i keys re-inserted at $o\n"; + warn "# sector $i keys re-inserted at $o\n" if $debug; } if ( my $padding = 4096 - length($card) ) { - warn "add $padding bytes up to 4k dump (needed for keys loading)\n"; + warn "# add $padding bytes up to 4k dump (needed for keys loading)\n" if $debug; $card .= "\x00" x $padding; } my $md5 = md5_hex($card); - if ( glob "cards/$uid.$md5.*" ) { - warn "SKIPPING, same dump allready exits\n"; + my $out_file = "cards/$uid.$md5"; + if ( -e $out_file ) { + warn "$out_file allready exists, not overwriting\n"; } else { - my $out_file = "cards/$uid.$md5"; write_file $out_file, $card; - print "$out_file ", -s $out_file, " bytes\n"; - if ( ! -e "cards/$uid.key" ) { - symlink $out_file, "cards/$uid.key" || die "cards/$uid.key: $!"; - warn "using keys as default for card $uid\n"; + warn "$out_file ", -s $out_file, " bytes key: $card_key_file\n"; + if ( ! -e $card_key_file ) { + $out_file =~ s{^cards/}{} || die "can't strip directory from out_file"; + symlink $out_file, $card_key_file || die "$card_key_file: $!"; + warn "$card_key_file symlink created as default key for $uid\n"; + } + } + + if ( $opt->write ) { + my $card = read_file $opt->write; + print STDERR "writing $uid block "; + foreach my $block ( 0 .. $tag->blocks ) { + my $offset = 0x10 * $block; + $tag->write_block( $block, substr($card,$offset,0x10) ); + print STDERR "$block "; } - $ENV{MAD} && system "./mifare-mad.pl $out_file | vi -R -"; + print STDERR "done\n"; } + # view dump + system "./mifare-mad.pl $out_file > $out_file.txt"; + $ENV{MAD} && system "vi $out_file.txt"; }