5 use RFID::Libnfc::Reader;
6 use RFID::Libnfc::Constants;
8 use Digest::MD5 qw(md5_hex);
10 use Data::Dump qw(dump);
12 my $debug = $ENV{DEBUG} || 0;
13 my $keyfile = shift @ARGV;
15 my $r = RFID::Libnfc::Reader->new(debug => $debug);
17 printf ("Reader: %s\n", $r->name);
18 my $tag = $r->connect(IM_ISO14443A_106);
27 my $uid = sprintf "%02x%02x%02x%02x", unpack('C4', $tag->{_nai}->abtUid);
28 # @{ $tag->uid }; # FIXME this doesn't work with tags which have 00 in UID!
32 my $card_key_file = "cards/$uid.key";
33 $keyfile ||= $card_key_file;
36 warn "# loading keys from $keyfile";
37 $tag->load_keys($keyfile);
38 warn "## _keys = ", dump($tag->{_keys});
41 $tag->select if ($tag->can("select"));
45 print STDERR "reading blocks ";
46 for (my $i = 0; $i < $tag->blocks; $i++) {
47 if (my $data = $tag->read_block($i)) {
48 # if we are dumping an ultralight token,
49 # we receive 16 bytes (while a block is 4bytes long)
50 # so we can skip next 3 blocks
51 $i += 3 if ($tag->type eq "ULTRA");
54 } elsif ( $tag->error =~ m/auth/ ) {
55 warn $tag->error,"\n";
57 # disconnect from reader so we can run mfoc
58 RFID::Libnfc::nfc_disconnect($r->{_pdi});
60 my $file = "cards/$uid.keys";
62 warn "# finding keys for card $uid with: mfoc -O $file\n";
63 exec "mfoc -O $file" || die $!;
68 print STDERR "done\n";
70 # re-insert keys into dump
71 my $keys = $tag->{_keys} || die "can't find _keys";
72 foreach my $i ( 0 .. $#$keys ) {
73 my $o = $i * 0x40 + 0x30;
74 last if $o > length($card);
76 = substr($card, 0, $o) . $keys->[$i]->[0]
77 . substr($card, $o+6, 4) . $keys->[$i]->[1]
78 . substr($card, $o+16)
80 warn "sector $i keys re-inserted at $o\n";
83 if ( my $padding = 4096 - length($card) ) {
84 warn "add $padding bytes up to 4k dump (needed for keys loading)\n";
85 $card .= "\x00" x $padding;
88 my $md5 = md5_hex($card);
89 my $out_file = "cards/$uid.$md5";
91 warn "$out_file allready exists, SKIPING\n";
93 write_file $out_file, $card;
94 print "$out_file ", -s $out_file, " bytes key: $card_key_file\n";
95 if ( ! -e $card_key_file ) {
96 $out_file =~ s{^cards/}{} || die "can't strip directory from out_file";
97 symlink $out_file, $card_key_file || die "$card_key_file: $!";
98 warn "$card_key_file symlink created as default key for $uid\n";
100 $ENV{MAD} && system "./mifare-mad.pl $out_file | vi -R -";