「Raspberry Pi 3にPaSoRiを接続してSuicaカードをダンプする」でSuicaカードの内容をダンプしましたが、同じプログラムでEdyカードをダンプしようとしても、次のように「unable to create a memory dump」のエラーメッセージが表示され、ダンプできませんでした。SuicaカードとEdyカードのデータ構成が違っているのがどうも原因のようです。
$ python suica.py Type3Tag 'FeliCa Standard (RC-S962)' ID=0114B38F1112E00A PMM=0120220427674EFF SYS=811D unable to create a memory dump
このため、nfcpyを使用してPython言語でEdyカードをダンプするプログラムを作成しました。
Edyカードのダンプアプリの作成
Edyカードのダンプアプリ「edy.py」は、Edyカードが持つサービスをすべて列挙し、パスワードなしで読み込めるブロックは、そのブロックをすべてダンプするプログラムです。
- サービスコードは 16 ビットの値で、上位 10 ビットがサービス番号、下位 6 ビットが属性値です。 サービスコードは 16 ビット値のため、0 から 0x10000 までを調べれば、すべてのサービスを網羅できます。
- nfc.tag.tt3.ServiceCode(i >> 6, i & 0x3f) は、16 ビットの整数 i から ServiceCode オブジェクトを生成します。 i >> 6 で上位 10 ビットの番号、i & 0x3f で下位 6 ビットの属性を取り出します。
- tag.request_service は複数のサービスを一度に指定します。check_servicesメソッドで n 個の ServiceCode のリストを作り、request_service メソッドに渡しています。
- サービスは、サービス番号「services[i].number」とサービスの属性「services[i].attribute」をパラメータにしたdump_serviceメソッドで取得します。
- サービスごとにdump_serviceメソッドを使って、ブロックの内容をダンプします。
edy.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys sys.path.insert( 1 , os.path.split(sys.path[ 0 ])[ 0 ]) import nfc def check_services(tag, start, n): services = [nfc.tag.tt3.ServiceCode(i >> 6 , i & 0x3f ) for i in xrange (start, start + n)] versions = tag.request_service(services) for i in xrange (n): if versions[i] = = 0xffff : continue print services[i], versions[i] # ブロック0番の内容を16進数で出力する sc = nfc.tag.tt3.ServiceCode(services[i].number, services[i].attribute) dumpdata = tag.dump_service(sc) print type (dumpdata) print len (dumpdata) for item in dumpdata: print " %s" % item def connected(tag): # タグのIDなどを出力する print tag if isinstance (tag, nfc.tag.tt3.Type3Tag): try : n = 32 for i in xrange ( 0 , 0x10000 , n): check_services(tag, i, n) except Exception as e: print "error: %s" % e else : print "error: tag isn't Type3Tag" # タッチ時のハンドラを設定して待機する clf = nfc.ContactlessFrontend( 'usb' ) clf.connect(rdwr = { 'on-connect' : connected}) |
Edyカードのダンプアプリの実行
次のようにedy.pyを起動し、RC-S380にEdyカードをかざすと、次のようにEdyカードがダンプされます。
$ python edy.py Type3Tag 'FeliCa Standard (RC-S962)' ID=0114B38F1112E00A PMM=0120220427674EFF SYS=811D Service Code 0000h (Service 0 Type 000000b) 10 Service Code 1000h (Service 64 Type 000000b) 1 0 Service Code 1008h (Service 64 Random RW with key) 1 0 Service Code 100Bh (Service 64 Random RO w/o key) 0 3 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 0005: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| Service Code 1108h (Service 68 Random RW with key) 1 0 Service Code 110Bh (Service 68 Random RO w/o key) 0 3 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 0005: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| Service Code 1208h (Service 72 Random RW with key) 1 0 Service Code 120Bh (Service 72 Random RO w/o key) 0 3 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 0005: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| Service Code 2000h (Service 128 Type 000000b) 1 0 Service Code 2008h (Service 128 Random RW with key) 1 0 Service Code 200Bh (Service 128 Random RO w/o key) 0 3 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 0005: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| Service Code 2108h (Service 132 Random RW with key) 1 0 Service Code 210Bh (Service 132 Random RO w/o key) 0 3 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 0005: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| Service Code FFFFh (Service 1023 Type 111111b) 1 0