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");
52 } elsif ( $tag->error =~ m/auth/ ) {
53 warn $tag->error,"\n";
55 # disconnect from reader so we can run mfoc
56 RFID::Libnfc::nfc_disconnect($r->{_pdi});
58 my $file = "cards/$uid.key";
60 warn "# finding keys for card $uid with: mfoc -O $file\n";
61 exec "mfoc -O $file" || die $!;
66 print STDERR "done\n";
68 # re-insert keys into dump
69 my $keys = $tag->{_keys} || die "can't find _keys";
70 foreach my $i ( 0 .. $#$keys ) {
71 my $o = $i * 0x40 + 0x30;
72 last if $o > length($card);
74 = substr($card, 0, $o) . $keys->[$i]->[0]
75 . substr($card, $o+6, 4) . $keys->[$i]->[1]
76 . substr($card, $o+16)
78 warn "sector $i keys re-inserted at $o\n";
81 my $md5 = md5_hex($card);
82 if ( glob "cards/$uid.$md5.*" ) {
83 warn "SKIPPING, same dump allready exits\n";
85 my $out_file = "cards/$uid.$md5";
86 write_file $out_file, $card;
87 print "$out_file ", -s $out_file, " bytes\n";
88 if ( ! -e "cards/$uid.key" ) {
89 symlink $out_file, "cards/$uid.key" || die "cards/$uid.key: $!";
90 warn "using keys as default for card $uid\n";
92 system "./mifare-mad.pl $out_file | vi -R -";