X-Git-Url: http://git.rot13.org/?p=perl-Mifare-MAD.git;a=blobdiff_plain;f=nfc-card-dumper.pl;h=37bee84d92f7a3a536711b07448edd6a97b73c82;hp=33b17cd662862b1952f4bb498480f51791ab9d96;hb=HEAD;hpb=0686bc57aa60b48d394819cbf6ab66b4af97f7ba diff --git a/nfc-card-dumper.pl b/nfc-card-dumper.pl index 33b17cd..37bee84 100755 --- a/nfc-card-dumper.pl +++ b/nfc-card-dumper.pl @@ -6,11 +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' ], + [ 'verify!', 'verify writes', { default => 1 } ], + [ 'debug|d', 'show debug dumps' ], + [ 'help|h', 'usage' ], +); +print $usage->text, exit if $opt->help; + my $debug = $ENV{DEBUG} || 0; -my $keyfile = shift @ARGV; +our $keyfile = shift @ARGV; +our ( $tag, $uid, $card_key_file ); + +sub write_card_dump; my $r = RFID::Libnfc::Reader->new(debug => $debug); if ($r->init()) { @@ -24,9 +37,9 @@ if ($r->init()) { exit -1; } - my $uid = sprintf "%02x%02x%02x%02x", @{ $tag->uid }; + $uid = sprintf "%02x%02x%02x%02x", @{ $tag->uid }; - my $card_key_file = "cards/$uid.key"; + $card_key_file = "cards/$uid.key"; $keyfile ||= $card_key_file; if ( -e $keyfile ) { @@ -39,7 +52,7 @@ if ($r->init()) { my $card; - print STDERR "$uid reading blocks "; + 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, @@ -54,7 +67,11 @@ if ($r->init()) { # disconnect from reader so we can run mfoc RFID::Libnfc::nfc_disconnect($r->{_pdi}); - my $file = "cards/$uid.keys"; + print "Dump this card with mfoc? [y] "; + my $yes = ; chomp $yes; + exit unless $yes =~ m/y/i || $yes eq ''; + + my $file = "cards/$uid.key"; unlink $file; warn "# finding keys for card $uid with: mfoc -O $file\n"; exec "mfoc -O $file" || die $!; @@ -64,6 +81,37 @@ if ($r->init()) { } print STDERR "done\n"; + my $out_file = write_card_dump $tag => $card; + + if ( $opt->write ) { + $card = read_file $opt->write; + foreach my $block ( 0 .. $tag->blocks ) { + my $offset = 0x10 * $block; + my $data = substr($card,$offset,0x10); + print STDERR "writing $uid block $block"; + $tag->write_block( $block, $data ); + if ( $opt->verify ) { + print STDERR " verify "; + my $verify = $tag->read_block( $block ); + print STDERR $verify eq $data ? "OK" : "ERROR"; + } + print STDERR "\n"; + } + print STDERR "done\n"; + unlink $card_key_file; + $out_file = write_card_dump $tag => $card; + } else { + # view dump + my $txt_file = $out_file; + $txt_file =~ s/\.mfd/.txt/ || die "can't change extension of $out_file to txt"; + system "./mifare-mad.pl $out_file > $txt_file"; + $ENV{MAD} && system "vi $txt_file"; + } +} + +sub write_card_dump { + my ( $tag, $card ) = @_; + # re-insert keys into dump my $keys = $tag->{_keys} || die "can't find _keys"; foreach my $i ( 0 .. $#$keys ) { @@ -83,21 +131,20 @@ if ($r->init()) { } my $md5 = md5_hex($card); - my $out_file = "cards/$uid.$md5"; + my $out_file = "cards/$uid.$md5.mfd"; if ( -e $out_file ) { warn "$out_file allready exists, not overwriting\n"; } else { write_file $out_file, $card; 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"; - } } - # view dump - system "./mifare-mad.pl $out_file > $out_file.txt"; - $ENV{MAD} && system "vi $out_file.txt"; -} + if ( ! -e $card_key_file ) { + my $source = $out_file; + $source =~ s{^cards/}{} || die "can't strip directory from out_file"; + symlink $source, $card_key_file || die "$card_key_file: $!"; + warn "$card_key_file symlink created as default key for $uid\n"; + } + return $out_file; +}