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 $keyfile = shift @ARGV;
14 my $r = RFID::Libnfc::Reader->new(debug => 1);
16 printf ("Reader: %s\n", $r->name);
17 my $tag = $r->connect(IM_ISO14443A_106);
26 my $uid = sprintf "%02x%02x%02x%02x", unpack('C4', $tag->{_nai}->abtUid);
27 # @{ $tag->uid }; # FIXME this doesn't work with tags which have 00 in UID!
31 $keyfile ||= "cards/$uid.key";
34 warn "# loading keys from $keyfile";
35 $tag->load_keys($keyfile);
36 warn "## _keys = ", dump($tag->{_keys});
39 $tag->select if ($tag->can("select"));
43 print STDERR "reading";
44 for (my $i = 0; $i < $tag->blocks; $i++) {
45 if (my $data = $tag->read_block($i)) {
46 # if we are dumping an ultralight token,
47 # we receive 16 bytes (while a block is 4bytes long)
48 # so we can skip next 3 blocks
49 $i += 3 if ($tag->type eq "ULTRA");
56 print STDERR "done\n";
58 # re-insert keys into dump
59 my $keys = $tag->{_keys} || die "can't find _keys";
60 foreach my $i ( 0 .. $#$keys ) {
61 my $o = $i * 0x40 + 0x30;
62 last if $o > length($card);
64 = substr($card, 0, $o) . $keys->[$i]->[0]
65 . substr($card, $o+6, 4) . $keys->[$i]->[1]
66 . substr($card, $o+16)
68 warn "sector $i keys re-inserted at $o\n";
71 my $md5 = md5_hex($card);
72 if ( glob "cards/$uid.md5.*" ) {
73 warn "SKIPPING, same dump allready exits\n";
76 my $out_file = "cards/$uid.$md5";
77 write_file $out_file, $card;
78 print "$out_file ", -s $out_file, " bytes\n";
79 if ( ! -e "cards/$uid.key" ) {
80 symlink $out_file, "cards/$uid.key" || die "cards/$uid.key: $!";
81 warn "using keys as default for card $uid\n";
83 system "./mifare-mad.pl $out_file | vi -R -";