「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
#!/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