How to use keyboard/mouse for PS4 part4 -challenge response-

How to use keyboard/mouse for PS4 part1 -Sniffing HCI-UART- - aki33524’s blog

How to use keyboard/mouse for PS4 part2 -How does Bluetooth work?- - aki33524’s blog

How to use keyboard/mouse for PS4 part3 -Btstack is GOD- - aki33524’s blog

DS4は非正規製品の流通を防ぐため、認証の機構を備えている。このパートではそれがどのような仕組みなのかを解説する。完全に理解したと思っているのに認証が通ってくれない。USB snifferが欲しい……

General

DS4の認証はChallenge-Responseベースである。1分に1回程度の割合でランダムなデータが送られて来て、それに対する適切なデータを送り返さなければPS4はそのコントローラーからの入力を無視するようになっている。

しかし解析Wikiでは「どうやらChallenge-Responseらしい」程度の情報しか載っておらず、実際に何が行われているのかはわからなかった。何故仕組みが分かっていないのに現在(デバイスを用いるとはいえ)コンバータが存在するかと言えば、「どうやらこのChallenge-ResponseはRelayしてパスすることが出来る」ということが分かっているからだった。

http://www.psdevwiki.com/ps4/DS4-BT#0xF0

http://www.psdevwiki.com/ps4/DS4-BT#0xF1

What are these data?

確かに、ファームウェアも読めないような認証の仕組みを明らかにするのは不可能に思える。しかし、暗号についての幾つかの知見があれば自然な類推で仕組みを明らかにすることが出来る。ここでは僕がどのようにして仕組みを知ったかを順に書いていく。冗長かも知れないが僕の実験の楽しさ(と苦しさ)の片鱗を味わってもらいたい。

さて、最初の取っ掛かりはWikiにあるPacket 0x0d is padded with zeros, except bytes 58 and 60 (both are 0x01).だった。こういう風に書かれると何のことだか分からないが、58-60byteが0x010001になっていると言われると暗号徒であれば察するところがあると思う。そう、0x010001とはRSAのeとして広く用いられている数である。

Challenge-ResponseでRSAが関係すると言われればまず間違い無く署名である。Challengeデータをコントローラーの内部にある秘密鍵で署名してResponseとして返す。これなら筋が通る。

eがResponseの中に入っているからにはもう1つの秘密鍵であるnも入っているはずである。実際にデータを見ると幾つかの連続したデータ列と0-paddingがある。具体的には16byteのデータ列1つ、256byteのデータ列3つ、そしてeがResponseに含まれるデータだった。

長さから考えて256byteのデータのどれかがnである。今度はこれを特定しよう。

まず、何回かのChallenge-Responseを眺めると2つの256byteの列は固定だった。ランダムなデータは間違い無くResponseデータであるし、公開鍵は変化することが無いのでこの内の1つがnである。残る列が何かと言えばこれはnを署名した列だと推測できる(そうでなければ公開鍵ごと偽造すれば簡単に破ることが出来る)。

どちらがnだろうか。これを確かめるのは簡単で、素因数分解をしてみれば良い。nは非常に大きな素数p, qの積からなるため小さい素因数を持たない。実際、片方の列は10000までの素因数を持たないにも関わらず、Miller-Rabin素数判定によって合成数であることが分かった。極めてn的な数である。

n, e, Challengeを手に入れたが、ここからどうやってChallengeを署名しているか特定する必要があった。これは幸いにも一般に署名に使われるPKCS1 PSSだった。Challengeをsha256でハッシュ化した後適切なパディングを施してd乗 mod nをする。

実際に得られたn, e, Challenge, Responseを使ってPKCS1 PSSでverifyすると通った。めでたい。

ところでn, e, nの署名(と思われるデータ)はペアリングをやり直しても不変だった。これはnの署名がLink KeyなどのPS4-DS4間で共有されるデータに依存しないことを意味する。

この考察から、Replayしても認証は上手く動くのである(と思っていた)。

Challenge-Response over USB

しかしここからが大変だった。

普通、先述の認証はBluetooth通信で行われる。そこでBluetooth通信をMITMすることで認証をReplayしようと思っていた。 しかし実際に書くと分かるがBtstackを使って複数のコネクションを管理するのは極めて大変な作業である。加えて1つのBluetoothドングルではPS4とChallenge-Response Oracle用DS4と同時に繋ぐとパケットロスが生じる。ドングルを2つ用意するのも手だが、他の方法を考えた。

実は新しい基板のDS4はUSBでの通信に対応している。そしてその設定をするページには「USBケーブルを使って通信する場合マイクが使えなくなります」とと言った文言がある。これは実はとても示唆に富んでいる。何故なら、DS4において「音声信号は必ずBluetooth上でやり取りされる」からだ。これは@ka1l氏に基板の写真を見てもらった時に指摘されていて、つまりは物理的に不可能なようだ。

僕はこの時までずっとUSBで操作の入力だけやり取りして他の音声や認証情報はBluetoothを使うと信じていた。しかし、音声情報が使えないということは一切Bluetoothを使わない可能性が高いと考えられる。つまり、Challenge-ResponseをUSBで行うことが出来る可能性が高いと考えた。

実際、USBで通信する設定を有効にしたコントローラーのBluetooth通信のログを見ると一切パケットが流れていなかった。

幸いにもGET_REPORT/SET_REPORTはUSBのHIDにもある概念で(と言うよりBluetoothがUSBから輸入した?)、ReportIDなども一致した。少し逸れるがLinuxカーネルには何故かDS4用のドライバが入っており、これを無効にしなければcontrolでの通信が出来なかった(結局必要なかったがデバドラの仕組みを調べたりした)。

果たしてGET_REPORT/SET_REPORTの0xf0, 0xf1, 0xf2のデータを適切にUSBでやり取りすると、きちんと署名されたデータが返ってきた。勝利を確信した瞬間である。

What's wrong?

しかしここからも大変なのだ。

0xf0, 0xf1, 0xf2のデータ以外にもGET_REPORT/SET_REPORTには0x03, 0x04のデータがやり取りされている。PS4からDS4に32byteのデータを送信してDS4が40byte返す。これはランダムなデータで内容も分かっていない。全く重要で内容に見える。

http://www.psdevwiki.com/ps4/DS4-BT#0x03

http://www.psdevwiki.com/ps4/DS4-BT#0x04

ところがこのデータを返さなければChallenge-Response用の通信もロックされてタイムアウトしてしまう。しばらく考えたが結局何のデータなのか分からず、urandomで生成したデータを流したが(少なくともそれを流した瞬間には)問題無いように見えた。

何故このデータもreplayしないのかと思うだろう。それはDS4のUSB通信ではReportID 0x03が存在しないからだ。これに相当するデータがあるのかないのか、あるならどのIDでやり取りしているのか覗いてみたいがUSB Snifferは存外大変らしい(金で殴れば解決する)。

雑な0x03, 0x04のデータを流して今度こそ解決したかと思われた。認証はタイムアウトせず全てのデータが流れきった。しかし最後のデータが渡った瞬間に入力が無視された。明らかに認証でハネられている。

どうやら考え残しているところがあるようだ。

一番怪しいのは0x03, 0x04だが、他にも可能性はある。

コントローラーのBDADDRに偽装してみたがこれもダメだった。

認証時にLink Keyを用い無いと考えていたが、PKCS1 PSSはパディングに乱数値を入れるため、この箇所にLink Keyに依存した情報が入っているのかもしれない。そう考えて同じLink Keyを使っている2つのResponseに入っている乱数値を取り出してみたが異なる値だった。

どれか他のReport IDが0x03, 0x04の代わりをしているかと探ったがこれもダメだった。

かなり煮詰まっているので記事に書いた(記事に書くと何故か進捗が生まれるジンクス、内容を自分で整理出来るからだろうか)。

Demo

Responseを返し切るまでは入力が受理されるところ。

www.youtube.com