pySim-shell

pySim-shell is an interactive command line shell for all kind of interactions with SIM cards.

The interactive shell provides command for

  • navigating the on-card filesystem hierarchy

  • authenticating with PINs such as ADM1

  • CHV/PIN management (VERIFY, ENABLE, DISABLE, UNBLOCK)

  • decoding of SELECT response (file control parameters)

  • reading and writing of files and records in raw, hex-encoded binary format

  • for some files where related support has been developed:

  • decoded reading (display file data in JSON format)

  • decoded writing (encode from JSON to binary format, then write)

By means of using the python cmd2 module, various useful features improve usability:

  • history of commands (persistent across restarts)

  • output re-direction to files on your computer

  • output piping through external tools like ‘grep’

  • tab completion of commands and SELECT-able files/directories

  • interactive help for all commands

Running pySim-shell

pySim-shell has a variety of command line arguments to control

  • which transport to use (how to use a reader to talk to the SIM card)

  • whether to automatically verify an ADM pin (and in which format)

  • whether to execute a start-up script

interactive SIM card shell

usage: pySim-shell [-h] [-d DEV] [-b BAUD] [-p PCSC] [--modem-device DEV]
                   [--modem-baud BAUD] [--osmocon PATH] [--script PATH]
                   [--csv FILE] [--card_handler FILE]
                   [-a PIN_ADM1 | -A PIN_ADM1_HEX]

Serial Reader

-d, --device

Serial Device for SIM access

Default: “/dev/ttyUSB0”

-b, --baud

Baud rate used for SIM access

Default: 9600

PC/SC Reader

-p, --pcsc-device

PC/SC reader number to use for SIM access

AT Command Modem Reader

--modem-device

Serial port of modem for Generic SIM Access (3GPP TS 27.007)

--modem-baud

Baud rate used for modem port

Default: 115200

OsmocomBB Reader

--osmocon

Socket path for Calypso (e.g. Motorola C1XX) based reader (via OsmocomBB)

General Options

--script

script with pySim-shell commands to be executed automatically at start-up

--csv

Read card data from CSV file

--card_handler

Use automatic card handling machine

-a, --pin-adm

ADM PIN used for provisioning (overwrites default)

-A, --pin-adm-hex

ADM PIN used for provisioning, as hex string (16 characters long)

cmd2 basics

FIXME

ISO7816 commands

This category of commands relates to commands that originate in the ISO 7861-4 specifications, most of them have a 1:1 resemblance in the specification.

select

The select command is used to select a file, either by its FID, AID or by its symbolic name.

Try select with tab-completion to get a list of all current selectable items:

pySIM-shell (MF)> select
..                2fe2              a0000000871004    EF.ARR            MF
2f00              3f00              ADF.ISIM          EF.DIR
2f05              7f10              ADF.USIM          EF.ICCID
2f06              7f20              DF.GSM            EF.PL
2f08              a0000000871002    DF.TELECOM        EF.UMPC

Use select with a specific FID or name to select the new file.

This will

  • output the [JSON decoded, if possible] select response

  • change the prompt to the newly selected file

  • enable any commands specific to the newly-selected file

pySIM-shell (MF)> select ADF.USIM
{
    "file_descriptor": {
        "file_descriptor_byte": {
            "shareable": true,
            "file_type": "df",
            "structure": "no_info_given"
        }
    },
    "df_name": "A0000000871002FFFFFFFF8907090000",
    "proprietary_info": {
        "uicc_characteristics": "71",
        "available_memory": 101640
    },
    "life_cycle_status_int": "operational_activated",
    "security_attrib_compact": "00",
    "pin_status_template_do": "90017083010183018183010A83010B"
}
pySIM-shell (MF/ADF.USIM)>

status

The status command [re-]obtains the File Control Template of the currently-selected file and print its decoded output.

Example:

pySIM-shell (MF/ADF.ISIM)> status
{
    "file_descriptor": {
        "file_descriptor_byte": {
            "shareable": true,
            "file_type": "df",
            "structure": "no_info_given"
        },
        "record_len": null,
        "num_of_rec": null
    },
    "file_identifier": "ff01",
    "df_name": "a0000000871004ffffffff8907090000",
    "proprietary_information": {
        "uicc_characteristics": "71",
        "available_memory": 101640
    },
    "life_cycle_status_integer": "operational_activated",
    "security_attrib_compact": "00",
    "pin_status_template_do": {
        "ps_do": "70",
        "key_reference": 11
    }
}

change_chv

Change PIN code to a new PIN code

usage: change_chv [-h] [--pin-nr PIN_NR] pin_code new_pin_code

Positional Arguments

pin_code

PIN code digits “PIN1” or “PIN2” to get PIN code from external data source

new_pin_code

PIN code digits “PIN1” or “PIN2” to get PIN code from external data source

Named Arguments

--pin-nr

PUK Number, 1=PIN1, 2=PIN2 or custom value (decimal)

Default: 1

disable_chv

Disable PIN code using specified PIN code

usage: disable_chv [-h] [--pin-nr PIN_NR] pin_code

Positional Arguments

pin_code

PIN code digits, “PIN1” or “PIN2” to get PIN code from external data source

Named Arguments

--pin-nr

PIN Number, 1=PIN1, 2=PIN2 or custom value (decimal)

Default: 1

enable_chv

Enable PIN code using specified PIN code

usage: enable_chv [-h] [--pin-nr PIN_NR] pin_code

Positional Arguments

pin_code

PIN code digits, “PIN1” or “PIN2” to get PIN code from external data source

Named Arguments

--pin-nr

PIN Number, 1=PIN1, 2=PIN2 or custom value (decimal)

Default: 1

unblock_chv

Unblock PIN code using specified PUK code

usage: unblock_chv [-h] [--pin-nr PIN_NR] puk_code new_pin_code

Positional Arguments

puk_code

PUK code digits “PUK1” or “PUK2” to get PUK code from external data source

new_pin_code

PIN code digits “PIN1” or “PIN2” to get PIN code from external data source

Named Arguments

--pin-nr

PUK Number, 1=PIN1, 2=PIN2 or custom value (decimal)

Default: 1

verify_chv

Verify (authenticate) using specified CHV (PIN) code, which is how the specifications

call it if you authenticate yourself using the specified PIN. There usually is at least PIN1 and PIN2.

usage: verify_chv [-h] [--pin-nr PIN_NR] pin_code

Positional Arguments

pin_code

PIN code digits, “PIN1” or “PIN2” to get PIN code from external data source

Named Arguments

--pin-nr

PIN Number, 1=PIN1, 2=PIN2 or custom value (decimal)

Default: 1

deactivate_file

Deactivate the currently selected file. This used to be called INVALIDATE in TS 11.11.

activate_file

Activate the specified EF. This used to be called REHABILITATE in TS 11.11 for classic

SIM. You need to specify the name or FID of the file to activate.

usage: activate_file [-h] NAME

Positional Arguments

NAME

File name or FID of file to activate

open_channel

Open a logical channel.

usage: open_channel [-h] chan_nr

Positional Arguments

chan_nr

Channel Number

Default: 0

close_channel

Close a logical channel.

usage: close_channel [-h] chan_nr

Positional Arguments

chan_nr

Channel Number

Default: 0

suspend_uicc

This command allows you to perform the SUSPEND UICC command on the card. This is a relatively recent power-saving addition to the UICC specifications, allowing for suspend/resume while maintaining state, as opposed to a full power-off (deactivate) and power-on (activate) of the card.

The pySim command just sends that SUSPEND UICC command and doesn’t perform the full related sequence including the electrical power down.

Perform the SUSPEND UICC command. Only supported on some UICC.

usage: suspend_uicc [-h] [--min-duration-secs MIN_DURATION_SECS]
                    [--max-duration-secs MAX_DURATION_SECS]

Named Arguments

--min-duration-secs

Proposed minimum duration of suspension

Default: 60

--max-duration-secs

Proposed maximum duration of suspension

Default: 86400

pySim commands

Commands in this category are pySim specific; they do not have a 1:1 correspondence to ISO 7816 or 3GPP commands. Mostly they will operate either only on local (in-memory) state, or execute a complex sequence of card-commands.

desc

Display human readable file description for the currently selected file.

dir

Show a listing of files available in currently selected DF or MF

usage: dir [-h] [--fids] [--names] [--apps] [--all]

Named Arguments

--fids

Show file identifiers

Default: False

--names

Show file names

Default: False

--apps

Show applications

Default: False

--all

Show all selectable identifiers and names

Default: False

Example:

pySIM-shell (MF)> dir
MF
3f00
 ..          ADF.USIM    DF.SYSTEM   EF.DIR      EF.UMPC
 ADF.ARA-M   DF.EIRENE   DF.TELECOM  EF.ICCID    MF
 ADF.ISIM    DF.GSM      EF.ARR      EF.PL
14 files

export

Export files to script that can be imported back later

usage: export [-h] [--filename FILENAME] [--json]

Named Arguments

--filename

only export specific file

--json

export as JSON (less reliable)

Default: False

Please note that export works relative to the current working directory, so if you are in MF, then the export will contain all known files on the card. However, if you are in ADF.ISIM, only files below that ADF will be part of the export.

Furthermore, it is strongly advised to first enter the ADM1 pin (verify_adm) to maximize the chance of having permission to read all/most files.

tree

Display a tree of the card filesystem. It is important to note that this displays a tree of files that might potentially exist (based on the card profile). In order to determine if a given file really exists on a given card, you have to try to select that file.

Example:

pySIM-shell (MF)> tree --help
EF.DIR                    2f00 Application Directory
EF.ICCID                  2fe2 ICC Identification
EF.PL                     2f05 Preferred Languages
EF.ARR                    2f06 Access Rule Reference
EF.UMPC                   2f08 UICC Maximum Power Consumption
DF.TELECOM                7f10 None
  EF.ADN                  6f3a Abbreviated Dialing Numbers
...

verify_adm

Verify the ADM (Administrator) PIN specified as argument. This is typically needed in order to get write/update permissions to most of the files on SIM cards.

Currently only ADM1 is supported.

reset

Perform card reset and display the card ATR.

intro

[Re-]Display the introductory banner

equip

Equip pySim-shell with a card; particularly useful if the program was started before a card was present, or after a card has been replaced by the user while pySim-shell was kept running.

bulk_script

Run script on multiple cards (bulk provisioning)

usage: bulk_script [-h] [--halt_on_error] [--tries TRIES]
                   [--on_stop_action ON_STOP_ACTION]
                   [--pre_card_action PRE_CARD_ACTION]
                   script_path

Positional Arguments

script_path

path to the script file

Named Arguments

--halt_on_error

stop card handling if an exeption occurs

Default: False

--tries

how many tries before trying the next card

Default: 2

--on_stop_action

commandline to execute when card handling has stopped

--pre_card_action

commandline to execute before actually talking to the card

echo

Echo (print) a string on the console

usage: echo [-h] string

Positional Arguments

string

string to echo on the shell

apdu

Linear Fixed EF commands

These commands become enabled only when your currently selected file is of Linear Fixed EF type.

read_record

Read one or multiple records from a record-oriented EF

usage: read_record [-h] [--count COUNT] record_nr

Positional Arguments

record_nr

Number of record to be read

Named Arguments

--count

Number of records to be read, beginning at record_nr

Default: 1

read_record_decoded

Read + decode a record from a record-oriented EF

usage: read_arr_record [-h] [--oneline] record_nr

Positional Arguments

record_nr

Number of record to be read

Named Arguments

--oneline

No JSON pretty-printing, dump as a single line

Default: False

read_records

Read all records from a record-oriented EF

usage: read_records [-h]

read_records_decoded

Read + decode all records from a record-oriented EF

usage: read_arr_records [-h] [--oneline]

Named Arguments

--oneline

No JSON pretty-printing, dump as a single line

Default: False

update_record

Update (write) data to a record-oriented EF

usage: update_record [-h] record_nr data

Positional Arguments

record_nr

Number of record to be read

data

Data bytes (hex format) to write

update_record_decoded

Encode + Update (write) data to a record-oriented EF

usage: update_record_decoded [-h] [--json-path JSON_PATH] record_nr data

Positional Arguments

record_nr

Number of record to be read

data

Abstract data (JSON format) to write

Named Arguments

--json-path

JSON path to modify specific element of record only

edit_record_decoded

Edit the JSON representation of one record in an editor.

usage: edit_record_decoded [-h] record_nr

Positional Arguments

record_nr

Number of record to be edited

This command will read the selected record, decode it to its JSON representation, save that JSON to a temporary file on your computer, and launch your configured text editor.

You may then perform whatever modifications to the JSON representation, save + leave your text editor.

Afterwards, the modified JSON will be re-encoded to the binary format, and the result written back to the record on the SIM card.

This allows for easy interactive modification of records.

decode_hex

Decode command-line provided hex-string as if it was read from the file.

usage: decode_hex [-h] [--oneline] HEXSTR

Positional Arguments

HEXSTR

Hex-string of encoded data to decode

Named Arguments

--oneline

No JSON pretty-printing, dump as a single line

Default: False

Transparent EF commands

These commands become enabled only when your currently selected file is of Transparent EF type.

read_binary

Read binary data from a transparent EF

usage: read_binary [-h] [--offset OFFSET] [--length LENGTH]

Named Arguments

--offset

Byte offset for start of read

Default: 0

--length

Number of bytes to read

read_binary_decoded

Read + decode data from a transparent EF

usage: read_binary_decoded [-h] [--oneline]

Named Arguments

--oneline

No JSON pretty-printing, dump as a single line

Default: False

update_binary

Update (Write) data of a transparent EF

usage: update_binary [-h] [--offset OFFSET] data

Positional Arguments

data

Data bytes (hex format) to write

Named Arguments

--offset

Byte offset for start of read

Default: 0

update_binary_decoded

Encode + Update (Write) data of a transparent EF

usage: update_binary_decoded [-h] [--json-path JSON_PATH] data

Positional Arguments

data

Abstract data (JSON format) to write

Named Arguments

--json-path

JSON path to modify specific element of file only

In normal operation, update_binary_decoded needs a JSON document representing the entire file contents as input. This can be inconvenient if you want to keep 99% of the content but just toggle one specific parameter. That’s where the JSONpath support comes in handy: You can specify a JSONpath to an element inside the document as well as a new value for tat field:

Th below example demonstrates this by modifying the ofm field within EF.AD:

pySIM-shell (MF/ADF.USIM/EF.AD)> read_binary_decoded
{
    "ms_operation_mode": "normal",
    "specific_facilities": {
        "ofm": true
    },
    "len_of_mnc_in_imsi": 2
}
pySIM-shell (MF/ADF.USIM/EF.AD)> update_binary_decoded --json-path specific_facilities.ofm false
pySIM-shell (MF/ADF.USIM/EF.AD)> read_binary_decoded
{
    "ms_operation_mode": "normal",
    "specific_facilities": {
        "ofm": false
    },
    "len_of_mnc_in_imsi": 2
}

edit_binary_decoded

This command will read the selected binary EF, decode it to its JSON representation, save that JSON to a temporary file on your computer, and launch your configured text editor.

You may then perform whatever modifications to the JSON representation, save + leave your text editor.

Afterwards, the modified JSON will be re-encoded to the binary format, and the result written to the SIM card.

This allows for easy interactive modification of file contents.

decode_hex

Decode command-line provided hex-string as if it was read from the file.

usage: decode_hex [-h] [--oneline] HEXSTR

Positional Arguments

HEXSTR

Hex-string of encoded data to decode

Named Arguments

--oneline

No JSON pretty-printing, dump as a single line

Default: False

BER-TLV EF commands

BER-TLV EFs are files that contain BER-TLV structured data. Every file can contain any number of variable-length IEs (DOs). The tag within a BER-TLV EF must be unique within the file.

The commands below become enabled only when your currently selected file is of BER-TLV EF type.

retrieve_tags

Retrieve a list of all tags present in the currently selected file.

retrieve_data

Retrieve (Read) data from a BER-TLV EF

usage: retrieve_data [-h] tag

Positional Arguments

tag

BER-TLV Tag of value to retrieve

set_data

Set (Write) data for a given tag in a BER-TLV EF

usage: set_data [-h] tag data

Positional Arguments

tag

BER-TLV Tag of value to set

data

Data bytes (hex format) to write

del_data

Delete data for a given tag in a BER-TLV EF

usage: delete_data [-h] tag

Positional Arguments

tag

BER-TLV Tag of value to set

USIM commands

authenticate

Perform Authentication and Key Agreement (AKA).

usage: authenticate [-h] rand autn

Positional Arguments

rand

Random challenge

autn

Authentication Nonce

terminal_profile

Send a TERMINAL PROFILE command to the card.

This is used to inform the card about which optional features the terminal (modem/phone) supports, particularly in the context of SIM Toolkit, Proactive SIM and OTA. You must specify a hex-string with the encoded terminal profile you want to send to the card.

usage: terminal_profile [-h] PROFILE

Positional Arguments

PROFILE

Hexstring of encoded terminal profile

envelope

Send an ENVELOPE command to the card. This is how a

variety of information is communicated from the terminal (modem/phone) to the card, particularly in the context of SIM Toolkit, Proactive SIM and OTA.

usage: envelope [-h] PAYLOAD

Positional Arguments

PAYLOAD

Hexstring of encoded payload to ENVELOPE

envelope_sms

Send an ENVELOPE(SMS-PP-Download) command to the card.

This emulates a terminal (modem/phone) having received a SMS with a PID of ‘SMS for the SIM card’. You can use this command in the context of testing OTA related features without a modem/phone or a cellular netwokr.

usage: envelope_sms [-h] TPDU

Positional Arguments

TPDU

Hexstring of encoded SMS TPDU

ARA-M commands

The ARA-M commands exist to manage the access rules stored in an ARA-M applet on the card.

ARA-M in the context of SIM cards is primarily used to enable Android UICC Carrier Privileges, please see https://source.android.com/devices/tech/config/uicc for more details on the background.

aram_get_all

Obtain and decode all access rules from the ARA-M applet on the card.

NOTE: if the total size of the access rules exceeds 255 bytes, this command will fail, as it doesn’t yet implement fragmentation/reassembly on rule retrieval. YMMV

pySIM-shell (MF/ADF.ARA-M)> aram_get_all
[
    {
        "ResponseAllRefArDO": [
            {
                "RefArDO": [
                    {
                        "RefDO": [
                            {
                                "AidRefDO": "ffffffffffff"
                            },
                            {
                                "DevAppIdRefDO": "e46872f28b350b7e1f140de535c2a8d5804f0be3"
                            }
                        ]
                    },
                    {
                        "ArDO": [
                            {
                                "ApduArDO": {
                                    "generic_access_rule": "always"
                                }
                            },
                            {
                                "PermArDO": {
                                    "permissions": "0000000000000001"
                                }
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

aram_get_config

Perform Config handshake with ARA-M applet: Tell it our version and retrieve its version.

NOTE: Not supported in all ARA-M implementations.

aram_store_ref_ar_do

Perform STORE DATA [Command-Store-REF-AR-DO] to store a (new) access rule.

usage: aram_store_ref_ar_do [-h] --device-app-id DEVICE_APP_ID
                            [--aid AID | --aid-empty] [--pkg-ref PKG_REF]
                            [--apdu-never | --apdu-always | --apdu-filter APDU_FILTER]
                            [--nfc-always | --nfc-never]
                            [--android-permissions ANDROID_PERMISSIONS]

Named Arguments

--device-app-id

Identifies the specific device application that the rule appplies to. Hash of Certificate of Application Provider, or UUID. (20/32 hex bytes)

--aid

Identifies the specific SE application for which rules are to be stored. Can be a partial AID, containing for example only the RID. (5-16 hex bytes)

--aid-empty

No specific SE application, applies to all applications

Default: False

--pkg-ref

Full Android Java package name (up to 127 chars ASCII)

--apdu-never

APDU access is not allowed

Default: False

--apdu-always

APDU access is allowed

Default: False

--apdu-filter

APDU filter: 4 byte CLA/INS/P1/P2 followed by 4 byte mask (8 hex bytes)

--nfc-always

NFC event access is allowed

Default: False

--nfc-never

NFC event access is not allowed

Default: False

--android-permissions

Android UICC Carrier Privilege Permissions (8 hex bytes)

For example, to store an Android UICC carrier privilege rule for the SHA1 hash of the certificate used to sign the CoIMS android app of Supreeth Herle (https://github.com/herlesupreeth/CoIMS_Wiki) you can use the following command:

pySIM-shell (MF/ADF.ARA-M)> aram_store_ref_ar_do --aid FFFFFFFFFFFF --device-app-id E46872F28B350B7E1F140DE535C2A8D5804F0BE3 --android-permissions 0000000000000001 --apdu-always

aram_delete_all

This command will request deletion of all access rules stored within the ARA-M applet. Use it with caution, there is no undo. Any rules later intended must be manually inserted again using aram_store_ref_ar_do

cmd2 settable parameters

cmd2 has the concept of settable parameters which act a bit like environment variables in an OS-level shell: They can be read and set, and they will influence the behavior somehow.

conserve_write

If enabled, pySim will (when asked to write to a card) always first read the respective file/record and verify if the to-be-written value differs from the current on-card value. If not, the write will be skipped. Writes will only be performed if the new value is different from the current on-card value.

If disabled, pySim will always write irrespective of the current/new value.

json_pretty_print

This parameter determines if generated JSON output should (by default) be pretty-printed (multi-line output with indent level of 4 spaces) or not.

The default value of this parameter is ‘true’.

debug

If enabled, full python back-traces will be displayed in case of exceptions

apdu_trace

Boolean variable that determines if a hex-dump of the command + response APDU shall be printed.

numeric_path

Boolean variable that determines if path (e.g. in prompt) is displayed with numeric FIDs or string names.

pySIM-shell (MF/EF.ICCID)> set numeric_path True
numeric_path - was: False
now: True
pySIM-shell (3f00/2fe2)> set numeric_path False
numeric_path - was: True
now: False
pySIM-shell (MF/EF.ICCID)> help set