#!/usr/bin/perl # This program reads the phone directory of a GSM11.11 SIM card and # prints out its contents in a human readable format. It is based on # another Perl script from Ludovic ROUSSEAU # That you can obtain at the following URL: # http://ludovic.rousseau.free.fr/softwares/SIM-1.0.tar.gz # # Copyright (C) 2001 - Lionel VICTOR, 2003 Ludovic ROUSSEAU # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # $Id: gsm_directory.pl,v 1.7 2006-08-12 17:35:53 rousseau Exp $ use warnings; use strict; use Carp; use Chipcard::PCSC; use Chipcard::PCSC::Card; use Getopt::Std; use Term::ReadKey; my %options; my $hContext = new Chipcard::PCSC(); my $hCard; my $RecvData; my $nRecordsLength; my $PIN; die ("Could not create PCSC object: $Chipcard::PCSC::errno\n") unless defined $hContext; sub gsmrecord_to_ascii { my $gsmrecord = shift; my $out_string = ''; my $delta = $#$gsmrecord-27; my $i; if ($$gsmrecord[0] != 0xFF) { for $i (0..14+$delta-1) { if ($$gsmrecord[$i] != 0xFF) { $out_string.=chr($$gsmrecord[$i]) } else { $out_string.=' '; } } my $phone_length = $$gsmrecord[14] - 2; if ($phone_length > 0) { my $digit; $out_string .= '-> '; for $i (16+$delta..$#$gsmrecord) { $digit = $$gsmrecord[$i]&0x0F; $out_string .= sprintf ("%01X", $digit) if ($digit!=0x0F); $digit = ($$gsmrecord[$i]&0xF0)>>4; $out_string .= sprintf ("%01X", $digit) if ($digit!=0x0F); } } else { $out_string.= "null or invalid phone"; } } return $out_string; } sub pin_to_array { my $pin = shift; my @array; confess ("PIN code must not exceed 8 bytes.") unless (length $pin <= 8); $pin =~ s/(.)/$1 /g; @array = split / /, $pin; @array = map (ord, @array); # Pad the array with 0xFF up to 8 bytes while ($#array < 7) { push @array, 0xFF; } return @array; } getopt ('hvr:', \%options); if (exists $options{h}) { #TODO print "TODO: usage -v verbose -r reader -h help"; } if (exists $options{r}) { $hCard = new Chipcard::PCSC::Card ($hContext, $options{r}); die ("Can't allocate PCSCCard object: $Chipcard::PCSC::errno\n") unless defined $hCard; print STDERR "Using given card reader: $options{r}\n" if exists $options{'v'}; } else { my @readers_list = $hContext->ListReaders (); die ("Can't get readers list: $Chipcard::PCSC::errno\n") unless defined $readers_list[0]; print STDERR "No reader given: using $readers_list[0]\n" if exists $options{v}; $hCard = new Chipcard::PCSC::Card ($hContext, $readers_list[0]); die ("Can't allocate PCSCCard object: $Chipcard::PCSC::errno\n") unless defined $hCard; } # Select MF (3F00) print STDERR "Selecting Master File (3F00)\n" if exists $options{v}; $RecvData = $hCard->Transmit([0xA0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00]); die ("Can't communicate: $Chipcard::PCSC::errno\n") unless defined $RecvData; die ("Can't select MF: SW = [ ".Chipcard::PCSC::array_to_ascii($RecvData)." ]") unless $$RecvData[0] == 0x9F; # Select DF Telecom (7F10) print STDERR "Selecting Telecom Directory (3F00/7F10)\n" if exists $options{v}; $RecvData = $hCard->Transmit([0xA0, 0xA4, 0x00, 0x00, 0x02, 0x7F, 0x10]); die ("Can't communicate: $Chipcard::PCSC::errno\n") unless defined $RecvData; die ("Can't select DF Telecom: SW = [ ".Chipcard::PCSC::array_to_ascii($RecvData)." ]") unless $$RecvData[0] == 0x9F; # Select EF_ADN (6F3A) (Abbreviated Dialing Numbers) print STDERR "Selecting Abbreviated Dialing Numbers File (3F00/7F10/6F3A)\n" if exists $options{v}; $RecvData = $hCard->Transmit([0xA0, 0xA4, 0x00, 0x00, 0x02, 0x6F, 0x3A]); die ("Can't communicate: $Chipcard::PCSC::errno\n") unless defined $RecvData; die ("Can't select EF_ADN: SW = [ ".Chipcard::PCSC::array_to_ascii($RecvData)." ]") unless $$RecvData[0] == 0x9F; # Get Response (get informations about EF_ADN) # The last SW gives the length of available bytes: # 9F xx means there are xx bytes waiting print STDERR "Getting ADN Records length\n" if exists $options{v}; $nRecordsLength = $$RecvData[1]; $RecvData = $hCard->Transmit([0xA0, 0xC0, 0x00, 0x00, $nRecordsLength]); die ("Can't communicate: $Chipcard::PCSC::errno\n") unless defined $RecvData; die ("Can't retrieve records length: SW = [ ".Chipcard::PCSC::array_to_ascii($RecvData)." ]") unless $$RecvData[$nRecordsLength] == 0x90; # Extract record length from the response $nRecordsLength = $$RecvData[$nRecordsLength-1]; print STDERR "Records are $nRecordsLength bytes long\n" if exists $options{v}; # Asks the user for his/her PIN code print STDOUT "Please insert your PIN code:"; ReadMode 'noecho'; $PIN = ReadLine 0; ReadMode 'normal'; chomp $PIN; print STDOUT "\n"; # Submitting PIN code to the card print STDERR "Submitting PIN code\n" if exists $options{v}; $RecvData = $hCard->Transmit([0xA0, 0x20, 0x00, 0x01, 0x08, pin_to_array($PIN)]); die ("Can't communicate: $Chipcard::PCSC::errno\n") unless defined $RecvData; die ("Can't access file (wrong PIN code ?): SW = [ ".Chipcard::PCSC::array_to_ascii($RecvData)." ]") unless $$RecvData[0] == 0x90; # Get phone records my $i; my @SW; print STDERR "Getting records\n" if exists $options{v}; for $i (1..255) { $RecvData = $hCard->Transmit([0xA0, 0xB2, $i, 0x04, $nRecordsLength]); die ("Can't communicate: $Chipcard::PCSC::errno\n") unless defined $RecvData; # pop the status word out of the retrieved bytes $SW[1] = pop @$RecvData; $SW[0] = pop @$RecvData; # Ignore referencing errors (record out of range, file # empty, etc...) but die if anything else bad occurs. die ("Can't read from EF_ADN: SW = [ ".sprintf ("%02X %02X",$SW[0],$SW[1])." ]\n") if ($SW[0] != 0x94 && $SW[0] != 0x90); # Exit if the status word is not 90xx last if $SW[0] != 0x90; # TODO:remove that it is only debug... # TODO: format that and print phone record... print "SLOT $i: ".gsmrecord_to_ascii($RecvData)."\n"; #print "[ ".Chipcard::PCSC::array_to_ascii($RecvData)." ] [".Chipcard::PCSC::array_to_ascii(\@SW)."]\n"; } print STDERR "Reseting the card\n" if exists $options{v}; $hCard->Disconnect($Chipcard::PCSC::SCARD_RESET); # End of File