10
0
Fork 0

SIMdata (diplay SIM info) begins integration in softSIM

This commit is contained in:
Kevin Redon 2011-05-09 15:06:10 +02:00
parent 2612bb3d6c
commit 04a8046367
2 changed files with 463 additions and 29 deletions

View File

@ -20,11 +20,14 @@ Copyright (C) 2011 Kevin "tsaitgaist" Redon kevredon@mail.tsaitgaist.info
# this programm will create a client which can be used to test servers
require 'sap/client'
require 'lib/apdu'
require 'info_client'
#=============
#== default ==
#=============
# client use (demo,info)
@type = "demo"
# which IO to use (tcp,unix,bt)
@socket = "tcp"
# tcp port
@ -58,8 +61,9 @@ def print_help
puts ""
puts "options :"
puts " --help,-h\t\tprint this help"
puts " --type,-t client\tclient type : demo,info (default #{@type})"
puts " --socket,-s type\tsocket type : tcp,unix,bt (default #{@socket})"
puts " --tcp,-t port\t\ttcp port (default #{@port})"
puts " --tcp,-p port\t\ttcp port (default #{@port})"
puts " --host,-l host\t\ttcp host (default #{@host})"
puts " --unix,-u file\t\tunix socket (default #{@unix})"
puts " --bluetooth,-s rfcomm\tbluetooth rfcomm serial port (default #{@bt ? @bt : 'self discovery'})"
@ -77,6 +81,9 @@ while arg=ARGV.shift do
when "--help","-h"
print_help
exit 0
when "--type","-t"
param = ARGV.shift
@type = param if param
when "--socket","-s"
param = ARGV.shift
@socket = param if param
@ -125,38 +132,47 @@ else
raise "please defined which socket to use"
end
# create client
@client = Client.new(io)
@client.start
@client.connect
case @type
when "demo"
# create client
@client = Client.new(io)
@client.start
@client.connect
# get ATR
atr = @client.atr
puts atr ? "ATR : #{atr.to_hex_disp}" : "could not get ATR"
# get ATR
atr = @client.atr
puts atr ? "ATR : #{atr.to_hex_disp}" : "could not get ATR"
# get IMSI
imsi = read_ef([MF,DF_GSM,EF_IMSI])
# byte 1 is the length of the IMSI
imsi_length = imsi[0]
imsi = imsi[1,imsi_length]
# first nibble is for parity check (not done)
imsi = imsi.nibble_str[1..-1]
puts "IMSI : "+imsi
# get IMSI
imsi = read_ef([MF,DF_GSM,EF_IMSI])
# byte 1 is the length of the IMSI
imsi_length = imsi[0]
imsi = imsi[1,imsi_length]
# first nibble is for parity check (not done)
imsi = imsi.nibble_str[1..-1]
puts "IMSI : "+imsi
# run A38 algo
# the rands
rands = []
4.times do |i|
rands << [(i<<4)+i]*16
# run A38 algo
# the rands
rands = []
4.times do |i|
rands << [(i<<4)+i]*16
end
# the results
puts "some KCs (RAND SRES Kc) :"
rands.each do |r|
response = a38(r)
puts " - #{r.to_hex_disp.gsub(' ','')} #{response[0,4].to_hex_disp.gsub(' ','')} #{response[4..-1].to_hex_disp.gsub(' ','')}"
end
@client.disconnect
when "info"
@client = Info.new(io)
@client.display
@client.close
else
raise "please defined which type to use"
end
# the results
puts "some KCs (RAND SRES Kc) :"
rands.each do |r|
response = a38(r)
puts " - #{r.to_hex_disp.gsub(' ','')} #{response[0,4].to_hex_disp.gsub(' ','')} #{response[4..-1].to_hex_disp.gsub(' ','')}"
end
@client.disconnect
# close client_io
io.close

418
src/info_client.rb Normal file
View File

@ -0,0 +1,418 @@
#!/usr/bin/env ruby
=begin
This file is part of softSIM.
softSIM 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 3 of the License, or
(at your option) any later version.
softSIM 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 sofSIM. If not, see <http://www.gnu.org/licenses/>.
Copyright (C) 2011 Kevin "tsaitgaist" Redon kevredon@mail.tsaitgaist.info
=end
# this programm will display information stored in the SIM
require 'sap/client'
require 'lib/apdu'
#=============
#== methods ==
#=============
class Info
include APDU
# provide the IO to the SAP server
def initialize(io)
@client = Client.new(io)
@client.start
@client.connect
end
# tell APDU methods how to send
def transmit_apdu(apdu)
return @client.apdu(apdu)
end
# display the information stored on the SIM
def display
# get the ATR
puts "ATR : #{@client.atr.to_hex_disp}"
end
def close
@client.disconnect
end
end
=begin
# verify CHV1
while chv_enabled? do
print "enter PIN : "
pin = gets.chomp
# pin is between 4 and 8 digits
unless pin.length>=4 and pin.length<=8 and pin.gsub(/\d/,"").length==0 then
puts "PIN has 4 to 8 digits"
redo
end
# encode pin in T.50 on 8 bytes
chv = [0xFF]*8
pin.length.times do |i|
chv[i]=0x30+pin[i,1].to_i
end
# select DF_GSM
cd [MF,DF_GSM]
# verify CHV1
begin
transmit(CHV1+chv)
break
rescue
puts "PIN wrong"
end
end
# get ICCID
iccid = read_ef([MF,EF_ICCID])
# get rid of the padding
iccid = iccid.nibble_str(true)
puts "ICCID : "+iccid
# get IMSI
imsi = read_ef([MF,DF_GSM,EF_IMSI])
# byte 1 is the length of the IMSI
imsi_length = imsi[0]
imsi = imsi[1,imsi_length]
# first nibble is for parity check (not done)
imsi = imsi.nibble_str[1..-1]
puts "IMSI : "+imsi
# service provider name
begin
spn = read_ef([MF,DF_GSM,EF_SPN])
spn_str = "service provider name : "
if spn==[0xff]*spn.length then
spn_str += "empty"
else
name = spn[1..-1]
name.collect!{|b| b==0xff ? nil : b}.compact!
spn_str += "name #{alphabet(name)}, "
spn_str += "display off the registered PLMN "
spn_str += spn[0]&0x01==0 ? "not required" : "required"
name = spn[1..-1]
name.collect!{|b| b==0xff ? nil : b}.compact!
spn_str += ", name #{alphabet(name)} #{spn.to_hex_disp}"
end
puts spn_str
rescue
puts "no service provider name"
end
# get MSISDN
begin
msisdns = read_ef([MF,DF_TELECOM,EF_MSISDN])
msisdn_str = ""
msisdns.each do |msisdn|
next if msisdn==[0xff]*msisdn.length
msisdn_str += " - "
alpha_id = msisdn[0,msisdn.length-14]
msisdn_str += "aplha identifier : #{alphabet(alpha_id)}"
#msisdn_str += ", BCD number/SSC length : #{msisdn[-14]}"
npi = case msisdn[-13]&0xf
when 0
"unknown"
when 1
"ISDN/telephony"
when 3
"data"
when 4
"telex"
when 5
"private"
else
"reserved"
end
msisdn_str += ", "
msisdn_str += "numbering plan identifier : #{npi}"
ton = case (msisdn[-13]>>4)&0x7
when 0
"unknown"
when 1
"international"
when 2
"national"
when 3
"network specific"
when 4
"short code"
else
"reserved"
end
msisdn_str += ", "
msisdn_str += "type of number : #{ton}"
number = msisdn[-12,msisdn[-14]-1].nibble_str(true)
number.gsub!(/[Aa]/,"*")
number.gsub!(/[Bb]/,"#")
number.gsub!(/[Cc]/," ")
number.gsub!(/[Dd]/,"§")
number.gsub!(/[Ee]/,"1")
msisdn_str += ", "
msisdn_str += "number : #{number}"
msisdn_str += ", capability in EF_CCP #{msisdn[-2]}" unless msisdn[-2]==0xff
msisdn_str += ", entension in EF_EXT #{msisdn[-1]}" unless msisdn[-1]==0xff
msisdn_str += "\n"
end
if msisdn_str.length>0 then
puts "MSISIDN :"
puts msisdn_str
else
puts "MSISDN empty"
end
rescue
puts "no MSISDN"
end
# get PLMsel
plmn = read_ef([DF_GSM,EF_PLMNSEL])
# transform to MCC MNC
print "PLMN selector : "
plmns = ""
(plmn.length/3).times do |i|
mcc = plmn[3*i,2].nibble_str(true)
mnc = plmn[3*i+2,1].nibble_str
plmns += "#{mcc} #{mnc}," unless mcc=="" and mnc=="ff"
end
puts plmns[0..-2]
# get higher priority PLMN search period
hpplmn = read_ef([MF,DF_GSM,EF_HPPLMN])
puts "higher priority PLMN search period : #{hpplmn[0]*6} min"
# get FPLMN
plmn = read_ef([MF,DF_GSM,EF_FPLMN])
# transform to MCC MNC
if plmn[0,3]==[0xff]*3 then
puts "no forbidden PLMN"
else
print "forbidden PLMN : "
plmns = ""
(plmn.length/3).times do |i|
mcc = plmn[3*i,2].nibble_str(true)
mnc = plmn[3*i+2,1].nibble_str
plmns += "#{mcc} #{mnc}," unless mcc=="" and mnc=="ff"
end
puts plmns[0..-2]
end
# get PLMNwAcT
begin
plmn = read_ef([MF,DF_GSM,EF_PLMNWACT])
# transform to MCC MNC
print "user controlled PLMN : "
plmns = ""
(plmn.length/5).times do |i|
mcc = plmn[3*i,2].nibble_str(true)
mnc = plmn[3*i+2,1].nibble_str
plmns += "#{mcc} #{mnc}," unless mcc=="" and mnc=="ff"
end
puts plmns[0..-2]
rescue
puts "no user controlled PLMN"
end
# get OPLMNwAcT
begin
plmn = read_ef([MF,DF_GSM,EF_OPLMNWACT])
# transform to MCC MNC
print "operator controlled PLMN : "
plmns = ""
(plmn.length/5).times do |i|
mcc = plmn[3*i,2].nibble_str(true)
mnc = plmn[3*i+2,1].nibble_str
plmns += "#{mcc} #{mnc}," unless mcc=="" and mnc=="ff"
end
puts plmns[0..-2]
rescue
puts "no operator controlled PLMN"
end
# access control class
acc = read_ef([MF,DF_GSM,EF_ACC])
puts "access control class :"
acc=acc[1]+(acc[0]<<8)
16.times do |b|
next if b==10
text = (acc>>b)&0x01==1 ? "allocated" : "not allocted"
puts " - ACC #{b} : #{text}"
end
# get Kc
kc = read_ef([MF,DF_GSM,EF_KC])
puts "Kc [seq.] : #{kc[0,8].to_hex_disp} [#{kc[8]}]"
# run A38 algo
# the rands
rands = []
16.times do |i|
rands << [(i<<4)+i]*16
end
# the results
puts "some KCs (RAND SRES Kc) :"
rands.each do |r|
response = a38(r)
puts " - #{r.to_hex_disp.gsub(' ','')} #{response[0,4].to_hex_disp.gsub(' ','')} #{response[4..-1].to_hex_disp.gsub(' ','')}"
end
# get the phase EFPhase
phase = read_ef([MF,DF_GSM,EF_PHASE])
case phase[0]
when 0
puts "phase : 1"
when 2
puts "phase : 2"
when 3
puts "phase : 2 and PROFILE DOWNLOAD required"
else
puts "phase : unkown"
end
# get EFsst
SERVICES = [
"CHV1 disable function",
"Abbreviated Dialling Numbers (ADN)",
"Fixed Dialling Numbers (FDN)",
"Short Message Storage (SMS)",
"Advice of Charge (AoC)",
"Capability Configuration Parameters (CCP)",
"PLMN selector",
"RFU",
"MSISDN",
"Extension1",
"Extension2",
"SMS Parameters",
"Last Number Dialled (LND)",
"Cell Broadcast Message Identifier",
"Group Identifier Level 1",
"Group Identifier Level 2",
"Service Provider Name",
"Service Dialling Numbers (SDN)",
"Extension3",
"RFU",
"VGCS Group Identifier List (EFVGCS and EFVGCSS)",
"VBS Group Identifier List (EFVBS and EFVBSS)",
"enhanced Multi-Level Precedence and Pre-emption Service",
"Automatic Answer for eMLPP",
"Data download via SMS-CB",
"Data download via SMS-PP",
"Menu selection",
"Call control",
"Proactive SIM",
"Cell Broadcast Message Identifier Ranges",
"Barred Dialling Numbers (BDN)",
"Extension4",
"De-personalization Control Keys",
"Co-operative Network List",
"Short Message Status Reports",
"Network's indication of alerting in the MS",
"Mobile Originated Short Message control by SIM",
"GPRS",
"Image (IMG)",
"SoLSA (Support of Local Service Area)",
"USSD string data object supported in Call Control",
"RUN AT COMMAND command",
"User controlled PLMN Selector with Access Technology",
"Operator controlled PLMN Selector with Access Technology",
"HPLMN Selector with Access Technology",
"CPBCCH Information",
"Investigation Scan",
"Extended Capability Configuration Parameters",
"MExE",
"Reserved and shall be ignored",
"PLMN Network Name",
"Operator PLMN List",
"Mailbox Dialling Numbers",
"Message Waiting Indication Status",
"Call Forwarding Indication Status",
"Service Provider Display Information",
"Multimedia Messaging Service (MMS)",
"Extension 8",
"MMS User Connectivity Parameters"]
puts "SIM service table :"
sst = read_ef([MF,DF_GSM,EF_SST])
sst.each_index do |i|
(0..4).each do |j|
service_nb = i*4+j
service = SERVICES[service_nb]
service = "unknown" unless service
if ((sst[i]>>(j*2))&0x01)==0x01 then
service_alloc = "allocated"
else
service_alloc = "not allocated"
end
if ((sst[i]>>(j*2+1))&0x01)==0x01 then
service_act = "activated"
else
service_act = "not activated"
end
puts " - #{service_nb+1} #{service} : #{service_alloc}, #{service_act}"
end
end
# get the phase
ad = read_ef([MF,DF_GSM,EF_AD])
puts "administration data :"
ms = " - MS operation mode : "
ms += case ad[0]
when 0x00
"normal operation"
when 0x80
"type approval operations"
when 0x01
"normal operation + specific facilities"
when 0x81
"type approval operations + specific facilities"
when 0x02
"maintenance (off line)"
when 0x04
"cell test operation"
end
puts ms
ofm = " - OFM (Operational Feature Monitor) : "
ofm += ad[2]&0x01==0x00 ? "disabled" : "enabled"
puts ofm
if ad.length>3 then
puts " - length of MNC in the IMSI : #{ad[3]}"
end
# location information
loci = read_ef([MF,DF_GSM,EF_LOCI])
puts "location informtion :"
puts " - TMSI : #{loci[0,4].to_hex_disp.gsub(' ','')}"
puts " - LAI : #{loci[4,5].to_hex_disp.gsub(' ','')}"
puts " - TMSI TIME : #{loci[9]==0 ? 'infinite' : (loci[9]*6).to_s+' min'}"
status = " - location update status : "
status += case loci[9]&0x7
when 0
"updated"
when 1
"not updated"
when 2
"PLMN not allowed"
when 3
"location area not allowed"
else
"reserved"
end
puts status
=end