OLIETの自由帳

All contents are Licensed under CC0

FeliCa総合入門記事(随時更新)

目的

この記事はFeliCaで何かしたい、けどなにがなんだか分からない!という方を対象に作られた入門記事(のつもり)です。

多分に独自研究が含まれていますが実際ほとんど独自に研究したものなので仕方がないです。

内容は随時更新します。

更新履歴

2022/07/26 公開

2022/08/09 気が向いたので更新

2023/01/07 明けましておめでとうござい更新

NFC

NFCとは

「Near Field Communication」の略で近距離無線通信規格の一つです。

NFCFeliCaの関係は重要ですが複雑ですので解説を他記事に委ねます

qiita.com

ja.wikipedia.org

www.sony.co.jp

NFCの種類

NFC-A,B,F,Vの4種類です。

Aは海外で主流なMifareとほぼ同一で、情報も多く安価で開発しやすいです。 ゲームセンターのカード等に使われています。

Bは日本では運転免許証やマイナンバーカード等の公的身分証等に使われています。 お堅い印象でエミュレートもできず手を出してはいけない気がします。

一度ちょっかいをかけたことがあります。

GitHub - OLIET2357/mynalock: マイナンバーカードをロックするAndroidアプリです

Fは日本で主流のFeliCa規格で、交通系ICカードや身分証等に使われています。

Vは回転寿司の皿にかざすと読めます。

FeliCa

FeliCa Lite-SとStandardの違い

FeliCaカードには現在Lite-SとStandardの二種類あります。

FeliCa Standardがその名の通り標準で、リーダがカードを認証する片側認証に加え、カードもリーダを認証する相互認証にも対応しています。なおこの手順は非公開です。

FeliCa Lite-Sはその廉価版で、生産停止したFeliCa Liteの完全上位互換です。手順が以下の「FeliCa Lite-Sユーザーズマニュアル」に公開されている片側認証にのみ対応しています。

ソニー株式会社 | FeliCa | 法人のお客様 | 技術情報

HCE-Fとその制限

Androidスマートフォンはバージョン7からハードウェアが対応していればFeliCaカードのように振る舞えるHCE-F(Host Card Emulation Type F)機能を搭載しています。

しかし基本的に既存のカードを偽造できないようになっています。機種によってはRoot化で解除できます。

アンドロイドアプリ 任意のFeliCaカードエミュレータ(要ROOT?) - OLIETの自由帳

ライセンス

ブランクのFeliCaカードを購入しても好き勝手システムコードを発行出来るわけでも暗号領域を読み書きできるわけでもなく、IDm・非暗号領域での認証や良くてLite-Sでの片側認証に終始してしまします。

FeliCa発行について - OLIETの自由帳

なぜなら発行や暗号通信をするには正当な導入事由を持った法人にしか卸さないであろう高額(噂)なリーダやSDKのライセンスが必要だからです。

ソニー株式会社 | FeliCa | 法人のお客様 | 製品情報 | ソフトウェア開発環境

リーダライタ

Sony製のPaSoRiFeliCaと相性が良いです。

それらを使うための公式のSDK以外にも多数のドライバが有志によって開発されています。

ほぼ全てのリーダはPC/SCという標準規格に対応しているため、共通のプログラムで最低限のこと(IDmを読むくらい)はできるはずですがあまり試したことはありません。

RC-S380 はいいぞ

RC-S380は読める書ける成れるの三拍子揃ったリーダライタエミュレータです。

既に生産終了しましたが中古で大量に出回っているため入手に困ることは無いでしょう。

nfcpyによりWindows,Mac,Linuxで読み書きエミュレートできます。

現状FeliCaカードをフルにエミュレートできるUSBリーダはこれだけです。

RC-S390 はサ終したけど一応読める

RC-S390の専用アプリは公開停止されましたが、復刻に成功しました。コマンドがRC-S380と一緒で良かったです。

RC-S390のnfcpy対応 - OLIETの自由帳

しかしRC-S380と違って現状FeliCaの読み取りしかできません。

これがハードウェア上の制限なのかソフトウェア・ファームウェア上の制限なのかは不明です。

RC-S320 は安いけど読み書きだけ

RC-S320秋葉原の端の方で百円、真ん中の方で二百円、平均五百円で売っています。読み書きだけならこれでできます。WindowsLinuxで動きます。

大量に購入して色々なカードを置き、出先でお手持ちのスマホにリレーするという使い方を構想しています。

RC-S620 (未所持)

RC-S620 は組み込みでUART通信のFeliCaリーダです。ある意味OSを選びませんが手間です。

少なくともFeliCaのポーリング応答をエミュレートできます。

ACR122U(FeliCaには不向き)

ACR122Uはチップセットにpn532を搭載し、PC/SCエスケープコマンドで直接通信ができます。

pn532のデータシートにはFeliCaのエミュレーションとの記述があるため、安価なACR122UでFeliCaのエミュレートができると期待しています。

FeliCa Card emulation

https://www.nxp.com/docs/en/nxp/data-sheets/PN532_C1.pdf

エミュレート

学生証・社員証エミュレートしたい(場合によってはできる)

身分証のエミュレートはIDmしか見ていない(バ先実話)とか、非暗号通信していた(大学実話)とかなら可能です。この世界は脆弱。

学生証のエミュレートについては今年四月に機密解除されます。

学生証エミュレートの奏功(簡易版) - OLIETの自由帳

Suicaエミュレートしたい(無理)

しっかりと相互認証して暗号通信してるのでSuicaのエミュレートは不可能です。 なお、いとも簡単に使えるおサイフケータイは専用のハードウェアを搭載しています。

コピーではなくパソコンにRC-S380を二台繋いで片方のリーダの上にカードを置いておき、FelicaRelay(公開停止中)でリレーすることは可能です。

これをスマホ二台やパソコンとスマホといった組み合わせで無線でリレーできれば便利なのですが難易度が高く挫折中です。

セキュリティ

非公開

セキュリティ関連のコマンドはほとんど非公開で、これは安全性のためとはいえケルクホフスの原理に反しています。

手順を公開して大量の暗号研究者に叩いて貰うのが現代の常識です。

インシデントがない

今のところFeliCaは長く守られ続けていて、Suicaが偽造されたなどといったニュースは寡聞にして聞きません。

そもそも、FeliCaは単なるインターフェースであって、高速化のために内部に情報を保持しているとは言え結局はサーバ管理のため一時的に残高等を偽造できたとしてもすぐに検出されるはずです。

それよりも前述した暗号化のなされていない身分証等のほうがよっぽど問題です。

FeliCaの安全性は確かだが平文通信じゃあね…

情報の少なさ

非暗号の基本的なコマンドは公開していますがセキュリティ関係のコマンドは「隠すことによるセキュリティ」に頼っていることを否めません。

暗号通信や中核のセキュアエレメントなどについてできるかぎり調査してみます。あなたは独りではありません。

SuicaのApple Walletへの追加時の通信(粗造)

なんとなくApple Walletに追加したらカードのSuica使えなくなった。

環境

iPhone 7

FelicaRelay RC-S380*2

Suica (残高200円、券面番号JE806 F200 3120 8008

結果

relay.pyfor _ in range(1):を適当に大きな数に変えた

v2.3から継続してエミュレートする-cオプションに対応しました。

python relay.py -t 1

D:\Projects\FelicaRelay>python relay.py -t 1
TIMEOUT CARD     1.0 s
TIMEOUT READER   1.0 s
Scanning Devices...
DEVICE CARD      usb:001:003
DEVICE READER    usb:001:005
target_r 212F sensf_res=0101120312B91C960B053143454682B7FF0003
Tag Type3Tag 'FeliCa Standard (RC-S???)' ID=01120312B91C960B PMM=053143454682B7FF SYS=0003
Request System Code
0003 fe00 86a7
Polling to ffff
idm pmm sys
<> {"idm": "01120312b91c960b", "pmm": "053143454682b7ff", "sys": "0003"}
sensf_res 0101120312b91c960b053143454682b7ff0003
Emulator Start
target_e 212F sensf_req=00FFFF0000 sensf_res=0101120312B91C960B053143454682B7FF0003 tt3_cmd=0C01120312B91C960B
Initial Response
<< 0a0c01120312b91c960b
>> 110d01120312b91c960b030003fe0086a7
<< 0d0201120312b91c960b010a18
>> 0d0301120312b91c960b010300
<< 060000030000
>> 120101120312b91c960b053143454682b7ff
Exchange Finished
target_r 212F sensf_res=0101120312B91C960B053143454682B7FF0003
Tag Type3Tag 'FeliCa Standard (RC-S???)' ID=01120312B91C960B PMM=053143454682B7FF SYS=0003
Request System Code
0003 fe00 86a7
Polling to ffff
idm pmm sys
<> {"idm": "01120312b91c960b", "pmm": "053143454682b7ff", "sys": "0003"}
sensf_res 0101120312b91c960b053143454682b7ff0003
Emulator Start
target_e 212F sensf_req=00FFFF0000 sensf_res=0101120312B91C960B053143454682B7FF0003 tt3_cmd=0C01120312B91C960B
Initial Response
<< 0a0c01120312b91c960b
>> 110d01120312b91c960b030003fe0086a7
<< 060000030100
>> 140101120312b91c960b053143454682b7ff0003
<< 110201120312b91c960b03081148114818
>> 110301120312b91c960b03030003000300
Exchange Finished
target_r 212F sensf_res=0101120312B91C960B053143454682B7FF0003
Tag Type3Tag 'FeliCa Standard (RC-S???)' ID=01120312B91C960B PMM=053143454682B7FF SYS=0003
Request System Code
0003 fe00 86a7
Polling to ffff
idm pmm sys
<> {"idm": "01120312b91c960b", "pmm": "053143454682b7ff", "sys": "0003"}
sensf_res 0101120312b91c960b053143454682b7ff0003
Emulator Start
target_e 212F sensf_req=00FFFF0000 sensf_res=0101120312B91C960B053143454682B7FF0003 tt3_cmd=0C01120312B91C960B
Initial Response
<< 0a0c01120312b91c960b
>> 110d01120312b91c960b030003fe0086a7
<< 060000030000
>> 120101120312b91c960b053143454682b7ff
<< 333201120312b91c960b14ffff0000480088001008c8080c09081048108c10081148114818c80040000008c00f0010c0170018
>> 5e3301120312b91c960b00004114030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300ffff030003000300030003000300
<< 344001120312b91c960b000cffff480088001008c8080c09081048108c100811481148186ceb0f7fb15b9f70b45915caf62521d8
>> 2e4101120312b91c960b4274e05c846633c27b0264795051cb3deb87214b464509fd5d0d981c1d8d03e1e82c2480
<< 1a4201120312b91c960b35990f3b8d27ffc6839debcdc42f4e08
>> 1c43000003140896e5b343a4b0d79c3076abf014ad25ead90c70e1bf
<< 25440200a6df682331a7a1ba80507fe408dbfc3c53952197fb40f32231635b6ff2949da699
>> cf4503008afe466eb01ab1029f46d97121a470e11cb1e051ffc7d476848bf50a54da2916aaa5311f62790aa34863bd5fdc632d40c6aa21099cc0ace956dda56c954a1b080226743ecfb0cd722e3b439cf578a9f263b1f5dcc28549c6584594334981f4da27a7580f80fd2b9c677c7f9e4ed3e9a7bd2acd74457e5e4f14d2bbb61bfe2facbf2007553412fe90ead51b6b5e4f20cd2e4483734a15b47df0e1c673eef1fd5c4fd193f63becdfb65668f181763288495b6e3a9ad6cfdbfcd347794bd54f3b6b7f9a165a3ca48dde3cea69
<< 254404008c44ef46eaeb89bb6c4cfcb78fb287adeb32e381016ffb2fb5ff0de8efcc6b6025
>> cf4505005423e57d625a602ec7400f3b5fbf1b496ac181dbf3a970af7383eb0984a5a57405920ed22142df076877bba6f73d311f884d667e6d0138757797eb8808a2c8691270836212c8147aebe8b1c290c337b4424b03b8164e13c73aced50aac17afdd1527044c4685b34cebfb7f43bf3960ad3bc8c4cca89cca9b9300320edcf474811e21bb8cb8c36bf7bd94cae0a30b0bf60c866e74234866202d66c400d6e3623bfc49061e130487dd625b12ce8adf306830e53ba575c53299a96799b8b53ee1cb659ad1d3e4747a4dc09c4c
<< 15440600fb53c79cf4e6d4ea92367b41a6a8645234
>> 4f450700dd08877b2f8b498aa60a7778e85b5d997d13f047f44ff1da971f722768daf974f099952492c91a4a483be7374ec3481bfabaf230e3b60580e78bb2ce5357c970d23c6adb6877c9643721a9
Exchange Finished
target_r 212F sensf_res=0101120312B91C960B053143454682B7FF0003
Tag Type3Tag 'FeliCa Standard (RC-S???)' ID=01120312B91C960B PMM=053143454682B7FF SYS=0003
Request System Code
0003 fe00 86a7
Polling to ffff
idm pmm sys
<> {"idm": "01120312b91c960b", "pmm": "053143454682b7ff", "sys": "0003"}
sensf_res 0101120312b91c960b053143454682b7ff0003
Emulator Start
target_e 212F sensf_req=00FFFF0000 sensf_res=0101120312B91C960B053143454682B7FF0003 tt3_cmd=0C01120312B91C960B
Initial Response
<< 0a0c01120312b91c960b
>> 110d01120312b91c960b030003fe0086a7
<< 0d0201120312b91c960b010a18
>> 0d0301120312b91c960b010300
<< 060000030000
>> 120101120312b91c960b053143454682b7ff
Exchange Finished
target_r 212F sensf_res=0101120312B91C960B053143454682B7FF0003
Tag Type3Tag 'FeliCa Standard (RC-S???)' ID=01120312B91C960B PMM=053143454682B7FF SYS=0003
Request System Code
0003 fe00 86a7
Polling to ffff
idm pmm sys
<> {"idm": "01120312b91c960b", "pmm": "053143454682b7ff", "sys": "0003"}
sensf_res 0101120312b91c960b053143454682b7ff0003
Emulator Start
target_e 212F sensf_req=00FFFF0000 sensf_res=0101120312B91C960B053143454682B7FF0003 tt3_cmd=0C01120312B91C960B
Initial Response
<< 0a0c01120312b91c960b
>> 110d01120312b91c960b030003fe0086a7
<< 060000030000
>> 120101120312b91c960b053143454682b7ff
<< 333201120312b91c960b14ffff0000480088001008c8080c09081048108c10081148114818c80040000008c00f0010c0170018
>> 5e3301120312b91c960b00004114030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300030003000300ffff030003000300030003000300
<< 344001120312b91c960b000cffff480088001008c8080c09081048108c100811481148181438f01dc25041e8d1ad09946a113ef0
>> 2e4101120312b91c960bb1f1a0ce144265aec488f847e61d245519b50928e7a9481658832d83c13e9cfda6c8efbb
<< 1a4201120312b91c960b792ca4cf3f46208264b95d2b60df8505
>> 1c4300008c081816ae3e6f234e89ce9189b139fb75bb425a98286936
<< 254402005e74b93b71b84bb94a914cfd31259df42e6503562395fd83f60260d9e96bffd070
>> cf45030067625c7f6bed6bf379a0bfe8bf0741cd85e54e715fa8ca49ee79cb3f3e36ac26b377255a603c29731983f73e4554fe6d1cc2dc2fe261e1b3f6531c4dfdc74f3524f684a96c5c6337160c889610e7ba8b3d92b4210b82fd87af260e58c040f0f3c26e0cbf1125b8f865cd212c9b8e372865c5fde53fa6261a23fc960c890f99f474732f0eb6ad10aa09de01b469946ffc390477b273335fd490057006b35c79dbc2f38c60144d239abc81e24b2dc8d9575650975c0fd137160236c645f5deda113ba0f0e36bfb6c93437496
<< 25440400bdf064938c9c50ad5f368867260ae95a610f4c816d85399fc95a26a73893c738ce
>> cf450500a0775d035e159cf7c9c3dbfc00b0de85acbfdb7413aa72a6db843ecd34ccaef98f8c3ff6a9674f61c3071eab88b3c8b09a7d14c7f6b5499fdc610f944edfa67bb023fd695efd5d77a0c62b46d60453f2769ff771546c9798a40d2eac8e21b45b33b18a5956a94542082405a81b342dbfb269bf7c0d2ba43b918f721c03dd313d9c71d44bbdb204a147dc0f97a4e609d6d5b0a7f64faf454a936723bc655ef08aa6df2b027ac2538a5cc46688fe19baa0da53cadaf011b343e0d43877da5d935c491b7c026e676f6dbd90b1
<< 154406007b92cf83288ce8498964a085f771f843be
>> 4f450700bea933b8cb4146c5c92f993f727bf19f0972c83659d32b2f3741696bb1cc92f3b7fe866338dcb581d48af1413331015b894eed609bf4d020a78fcc5dbe6de75475497676998fa1107853ab
<< 314609001043fbc9f4b4686f7d1b0c3d9f491a3ad06c1275a987b3ce1344752824379e189f189fd3e783882ac346c02709
>> 0e470a003d681e84b1ed404ce5f0
<< 25440c00287f09c9c0ac790c6e42af5d6b34b168148f01b750b9e5d36760dab0a97c10e1da
>> cf450d00ade0cde1339eca13fc43f2e8c4ce6a4e864e7f881d809d1d79b15077d891ae1c02d3f1e1c258ecc60528ea1481c4705a2b4e61b2c6a338b643a1f3334676cf6ad0236ba1f500a8238af00d415af4988498c6557755f56d764031d7aed352c1df10feea859b6b8d51fda46a18bcf67a3d71b3917bd3bf2473b65586ed3cb8e58970f1820055b3619def8b60c68cf8ec21c1c97105aa067da3ab4244ad206c83e7dce38b489193b397fb59a951fa293a50550fcc84fb5124ad02f863479b172697dd0469cd0a2ab0e3a1d180
<< 25440e00c79cc41b2ac954b3b2e30cbe91fef9376b854a32f1b82ae94352e1f35586d7ea7a
>> cf450f00b8bd3c989379299ec1000f8116920ee03ab2f35e22a1fc6293d7bae790d577f141ad90bdca0695ec0288347b1f7ed4c690ae5647af22479eb3084cc16462729ad11a8763ea1e63103c8c285372003e6b910afd6a1390d8a0015cb71939b3cbdc6136be0608d8367a09aedf15867a591b89439b30cf042b851551fe374a819e6cd2a2a02870e2adb1bf6cc8135b5f351b3dac330adcae6cf36fc8f05cbd2f46e5d66736d6cfce21984612857bc08481a3e3814bfef4b81c5931e58177f1a4ba3312e402f40da97dec9b54b6
<< 154410004a090a6a5696e9e20ad9ecf015c7d52aba
>> 4f4511004416b2d1dec0eefd7d7e4c8755d68ee8bd38768c91eb3263437b30422688617ca67ab69acf379ec05bff88f9533e6344ef90cfadb1a2822f16c46530bd255881a70ab07d017810bdb4c64c
Exchange Finished
target_r 212F sensf_res=0101120312B91C960B053143454682B7FF0003
Tag Type3Tag 'FeliCa Standard (RC-S???)' ID=01120312B91C960B PMM=053143454682B7FF SYS=0003
Request System Code
0003 fe00 86a7
Polling to ffff
idm pmm sys
<> {"idm": "01120312b91c960b", "pmm": "053143454682b7ff", "sys": "0003"}
sensf_res 0101120312b91c960b053143454682b7ff0003
Emulator Start

考察

FeliCaカードユーザーズマニュアル抜粋版によればAES暗号方式を使用しているのが分かる。

カードの情報を全部吸い取った後カードを無効化する処理を行っていると推測される。

FelicaRelayの--ignore-write-v2オプションを用いればカードを生かしたまま移行したりできるかもしれない。できませんでした。

FeliCa発行について

はじめに

FeliCa技術はSonyの独壇場です。

Web上で検索してもまとまった情報を得るのは難しく、特に根幹に関わる発行についてはベールに覆われています。

これから調べる方に少しでも役に立つように調べた結果をまとめておきます。

また、電話での問い合わせが主なので参考文献はありません。これはおそらくわざとだと思っています。

発行の種類

工場出荷状態のブランクカードにシステムコードを割り振る1次発行と

1次発行したカードにデータを書き込む・編集する2次発行があります。

1次発行

1次発行は不可逆ですがシステムコードを追加することはできます。

Sonyに申請してシステムコードとエリア鍵を取得しなければなりません。

システムコードFE00はパブリック領域で、そこに書き込むカードは市販品のRC-S100などではない分割カードが必要だそうです。

DNP富士フイルムなど7社ほどのみが製造しています。

2次発行

2次発行はエリア鍵さえあればパブリック領域でも編集できます。

値段は5万円ほどだそうです。

FCF

直接は関係ないですがパブリック領域を用いるFCFカードというものがあります。

FCFフォーラムに登録すれば(有償)発行鍵とフォーマットを開示されます。

発行鍵はともかく、フォーマットは複数人のデータを突き合わせれば判るほど単純なものです。

Linux バイナリを指定日時として起動(フックとパッチ)

TL;DR

とっっっても健全な目的でLinuxバイナリを指定した日時として起動する必要に駆られ、2つの相反する方法を見つけました。

わかりやすく言えばLinux版RunAsDateのような感じです。 *1

対応しているのは64bit ELFバイナリのみです。*2

またかなり実験的なツールなので動作は期待しないでください。

github.com

使い方(自動)

sudo apt install bbe -y

chmod +x tm.sh

./tm.sh バイナリ [UNIX時刻]

使い方(手動)

64bitELFバイナリにfileコマンドを実行して

ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, ...

のように動的リンクならフックをします。

ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, ...

のように静的リンクならパッチをあてます。

フック

qiita.com

こちらの記事を全面的に参考にしました。

makeしてできたhook.soをプリロードさせます。

env LD_PRELOAD=./hook.so ./TARGET_BINARY

日付はデフォルトでUNIXエポック(1970/1/1)になっていますので、変更したいならhook.cretを特定のUNIX時間に書き換えてmakeし直してください。

パッチ

こっちの方法はオリジナルです。

まずバイナリ版のsedと言えるbbeをインストールします。

sudo apt install bbe -y

aptがないならソースからビルドします。

bbe - Browse Files at SourceForge.net

実行権限を付与してpatcher.shを実行します。

chmod +x patcher.sh

./patcher.sh TARGET_BINARY

生成されたTARGET_BINARY_patchedを実行します。

運が良ければうまくいきます。*3

t=time(NULL)には対応していますがtime(&t)には対応していません。使わないからヨシッ

時刻を指定したい場合はpatcher.shを以下のように書き換えパッチし直してください。

NEW=' 48 C7 C0 XX XX XX XX C3'

XXは指定したいUNIX時間のリトルエンディアンです。

大文字小文字は区別しませんが先頭の空白は必須です。

沿革

まずは逆アセンブラを見ます。

IDA Freewareを使用しました。

f:id:oliet:20220110050147p:plain
time

静的リンクされてればtime(2)関数が出てきます。ストリップされていても形は一緒です。

0xC9=201番のシステムコールを呼び出しています。

mov eax, 0C9h
syscall

Syscall Number for x86-64 linux (A)

x86_64 LInux Syscall Reference | Adam Hacks

調べてみると案の定(システムコールの)timeです。(というかコメントに書いてありました)

よってここを指定時刻を返すように書き換えればよいのですが、最初のmov rax, cs:_dl_vdso_timeのバイナリが毎回異なるのでその下の

push rbp
mov rbp, rdi
test rax rax
jz short loc_xxxxxx

の部分を即値を代入してreturnする以下のアセンブリに書き換えています。

mov rax, 0

time-machine/patcher.sh at main · OLIET2357/time-machine · GitHub

書き換えに使うのはjzの途中までなのですが、ジャンプは相対位置指定なのでここ以降のバイナリは毎回一緒です。

4byte即値代入なので2038年以降は使えませんね。

その場合でも領域にはまだまだ余裕はある上都合よくこれ以降のバイト列は毎回同一なので、より多く書き換えるようにすればよいだけです。

参考までに8バイトのmov rax,48 B8です。テストはしていません。

最終行でシステムコール呼び出しにC3を付けたバイナリも置換しているのは、システムコールを呼ぶだけの以下のような関数を呼ぶバイナリがあったので付けています。

mov eax, 0C9h
syscall
retn

こちらはこれ以降に余裕がないので64bit対応は少し難しいかもしれません。

*1:一応自動化したもののどちらの方法も引数等ではなくコンパイルOR再パッチが必要なのであちらほど手軽ではありませんが

*2:フックは32bitでも他アーキテクチャでも動くでしょうが

*3:後述のバイトパターンに頼った不安定な方法ですし、自身のハッシュ値でも見ていたら終わりです。