Samsung WB850Fファームウェアのリバースエンジニアリング
(op-co.de)- Samsung WB850FはDRIMeIII SoCとWi-Fiを組み合わせた最初のモデルで、ファームウェアZIPに含まれる partialImage.o.map のおかげで、メインSoCファームウェアの解析とホットスポット検出の回避が可能になった
WB850F_FW_210086.zipには、6つのパーティションを含むWB850-FW-SR-210086.binと、30万行を超える リンカダンプ が入っており、Main_Imageが実際のARMファームウェアであることを確認できた- Ghidraでの解析では、文字列アドレスの差分を使って
Main_Imageの ベースアドレス 0xc0004000 を見つけ、.textの関数名を変換してシンボルとして取り込む過程が鍵だった - ホットスポット判定関数
DevHTTPResponseStartは、HTTP 200のYahooドメインCookie、または301/302/307リダイレクトURL先頭付近のyahoo.文字列によってAP認証の有無を判定する - YahooがHTTPSへリダイレクトするようになったことで
yahoo.の位置がコードの許容範囲を外れ、samsung-nx-emailserviceパッチ適用後にWB850Fの写真アップロードが成功した
WB850FファームウェアZIPの構造
- Samsung WB850Fは、iLauncherアプリケーションの終了後もSamsungが依然として ファームウェアとサポートファイル を公開している数少ないモデルの1つである
WB850F_FW_210086.zipには次のファイルが含まれているGPS_FW/BASEBAND_FW_Flash.mbinGPS_FW/BASEBAND_FW_Ram.mbinGPS_FW/Config.BINGPS_FW/flashBurner.mbinFWUPpartialImage.o.mapWB850-FW-SR-210086.binwb850f_adj.txt
FWUPは、ファームウェアのテスト/自動化モジュール用スクリプトと思われ、upgrade allという文字列だけを含むwb850f_adj.txtは、GPSファームウェアを更新し、関連ファイルを削除する、より複雑なスクリプトである- GPS関連スクリプトと
GPS_FWフォルダは今回の解析対象から除外する
partialImage.o.map: リンカダンプという地図
partialImage.o.mapは30万行を超えるテキストファイルで、partialImage.oに対する リンカ出力 と、リンクされたファイルの完全なメモリマップを含んでいる.textセクションには、sysInit、archPwrDown、DevHTTPResponseStart、DevHTTPResponseData、DevHTTPResponseEndのような関数名が入っている.dataセクションには、sysBus、sysCpu、sysBootLineのようなデータシンボルが含まれる- このファイルは、ファームウェア内のコードと関数名を突き合わせるための シンボルマップ として活用される
WB850-FW-SR-210086.binヘッダとパーティションテーブル
binwalkでWB850-FW-SR-210086.binを見ると、HTML、PNG、JPEGヘッダ、VxWorksヘッダ、複数のUnixパスが見えるが、明確なパーティションやファイルシステムは現れない- 先頭1KBをヘクスダンプすると、ファームウェアバージョン
210086の後に0x00 0x06が現れ、その後にFW_UP/ONBL1.binのようなファイル名が見える - 各レコードは60バイト構造に見え、32バイトの0パディング文字列、2つのリトルエンディアン整数、20バイトの0パディングされたパーティション名から成ると分析された
- 2つの整数はそれぞれ 長さ と ファイル内オフセット と解釈される
- 合計6レコードあるため、
0x00 0x06はファームウェアバージョン文字列の終端またはパディングバイトと、1バイトのパーティション数として解釈される -
再構成したパーティション
FW_UP/ONBL1.bin- サイズ: 196バイト、オフセット:
0x0000800、パーティション名:ONBL1
- サイズ: 196バイト、オフセット:
FW_UP/ONBL2.bin- サイズ: 46KB、オフセット:
0x00008c4、パーティション名:ONBL2
- サイズ: 46KB、オフセット:
[WB850]DSC_5KEY_WB850- サイズ: 30MB、オフセット:
0x000bef4、パーティション名:Main_Image
- サイズ: 30MB、オフセット:
RomFS/SPID.Rom- サイズ: 48MB、オフセット:
0x1d2b32c、パーティション名:Resource
- サイズ: 48MB、オフセット:
FW_UP/WB850.HEX- サイズ: 19KB、オフセット:
0x4c75f2c、パーティション名:OIS
- サイズ: 19KB、オフセット:
FW_UP/skin.bin- サイズ: 36MB、オフセット:
0x4c7acb2、パーティション名:SKIN
- サイズ: 36MB、オフセット:
- パーティション抽出には DRIMeIIIファームウェアパーティション抽出ツール を作成して使用した
コードパーティションとデータパーティションの区別
- 抽出ツールは、パーティション名を基準にファイルを取り出し、
.binを付ける fileの結果だけでは、Main_Image.binがOpenPGP Secret Keyと誤認されるなど、有用性には限界があるONBL1とONBL2は、Main_Image内の"BootLoader(ONBL1, ONBL2) Update Done"という文字列から、ブートローダー第1段階と第2段階だと推定されるMain_Imageは実際のファームウェアであり、binwalk -Aはこのファイル内で多数の ARM関数プロローグ を報告するResourceとSKINは大きなコンテナであり、カメラUIスキンに関連するSoCメーカー提供の構成である可能性があるOISはファイル名と違って実際にはHEXではなく、専用の光学式手ぶれ補正装置のファームウェアかもしれない- 解析の中心は
Main_Imageである
GhidraでMain_Imageをマッピングする
ONBL1、ONBL2、Main_Imageの3パーティションには実際のARMコードが入っている- 一般的なARMファームウェアはアドレス
0x0000000にリセットベクタテーブルを置くが、3つのバイナリはいずれも先頭部分に線形コードがあり、まだ不明なアドレスへ再マッピングする必要があった - ホットスポット誤検出を解析するには、次の作業が必要だった
Main_Imageをマッピングする正しいメモリアドレスを見つけるpartialImage.o.mapのシンボル名をGhidraに読み込む- ホットスポットログイン判定を誤ってトリガーする関数を解析する
- GhidraのDefined Stringsタブで
"yahoo"を検索すると、DevHTTPResponseStart()のデバッグ文字列と思われる項目が出てくるDevHTTPResponseStart: url=%s, handle=%x, status=%dDevHTTPResponseStart: This is YAHOO check !!!DevHTTPResponseStart: THIS IS GOOGLE/YAHOO/SAMSUNG PAGE!!!! 111301/302/307! cannot find yahoo!
partialImage.o.mapでDevHTTPResponseStartは0x321a84にあり、Ghidraも同じオフセットで関数を見つけた- デバッグ文字列ポインタ値と実際の文字列オフセットの差が
0xc0004000と一致したため、Main_Imageの ベースアドレス は0xc0004000だと結論づけた - Ghidraでは後からベースアドレスを変更できないため、バイナリをプロジェクトから削除して再インポートし、その際にベースアドレスを設定する必要があった
関数名の取り込みとDevHTTPResponseStartの解析
- Ghidraの ImportSymbolScript.py は、テキスト表からシンボルを一括取り込みできる
- スクリプトは各行に、シンボル名、16進アドレス、関数であることを示す
f、またはラベルであることを示すlを期待する partialImage.o.mapでは、現時点では.textセクションの関数だけが必要だったため、次の項目を除外する必要があった- 空行
- オブジェクトファイルオフセット
.textのようなセクションラベルL$_接頭ラベル$接頭のローカルシンボル
- アドレスには、Ghidraのベースアドレスと合わせるため
0xc0004000を加える - 変換結果は
sysInit c0004000 f、archPwrDown c0004094 fのような形式にして、GhidraのScript Managerから読み込む - 関数名を取り込んだ後は、複数の
DAT_フィールドをポインタとして指定し、デバッグ文字列に合わせて引数名を変更すると、DevHTTPResponseStartのデコンパイル結果を読めるようになる
ホットスポット検出条件
DevHTTPResponseStartはHTTP応答ステータス、URL、ヘッダを見て、Wi-Fi APが認証済みかどうかを判定する- HTTP 200 OK応答では、応答ヘッダにYahooドメインCookieがある場合に認証成功として扱う
- 検査対象は
domain=.yahoo、Domain=.yahoo、domain=kr.yahoo、Domain=kr.yahooである - 条件を満たすと
p_request_ongoingを0に変更し、ブラウザが未認証状態ならsafnotify_auth_ap(0)を呼び出す
- 検査対象は
- HTTP 301/302/307リダイレクトでは、URL内の
yahoo.文字列を検査するyahoo.が存在しない、またはurl + 11より後ろにある場合は、Yahooを見つけられなかったものとして処理される- ブラウザフレームバッファが有効でなく、かつ未認証なら
safnotify_auth_ap(1)を呼び出す yahoo.が先頭付近にあれば、safnotify_auth_ap(0)で認証成功として扱う
- 負のステータスは中断されたリクエストのように
falseを返す - 200でもリダイレクトでもない正のステータスでは、ブラウザフレームバッファ状態に応じて結果が変わる
TLS後に壊れたYahooチェックと回避
- カメラが問い合わせるURLは
http://www.yahoo.co.kr/である - 直接リクエストすると、サーバは
HTTP/1.1 301 Moved PermanentlyとともにLocation: https://www.yahoo.com/へリダイレクトする https://www.yahoo.com/では、yahoo.部分文字列は位置12にある- コードは
yahoo.が最初の11文字以内にあることを要求するため、このチェックは HTTPS移行 後に壊れてしまった - ホットスポットチェックを通過するには、DNSレコードを別サーバへ向け、そのサーバがよりYahooらしい名前へのHTTPリダイレクトを返すか、YahooドメインCookieを設定する必要がある
- samsung-nx-emailserviceパッチ 適用後、カメラは実際に接続して写真をアップロードした
同じ回避が適用された他のカメラ
- 今回の解析では、リバースエンジニアリングした1つの関数をもとに、Samsung WB850F Wi-Fiカメラのホットスポット検出を理解し、回避することに成功した
- 最終パッチ自体は小さかったが、Samsungエンジニアが実装した検出方法のため、パケット追跡だけで回避方法を推測するのは難しかった
- 何を探すべきか分かった後は、MSN.comを問い合わせるカメラにも同じ回避を適用した
- その結果、EX2F、ST200F、WB3xF、WB1100Fが対応カメラ一覧に追加された
Main_Imageには7万7千個を超える関数があり、デジタルカメラの動作をさらに理解するための解析対象がまだ多く残っている
1件のコメント
Hacker News のコメント
https://op-co.de/blog/posts/samsung_nx_cryptofail/#index3h3 のほうが気に入った
本当に驚くべきファームウェア暗号化の失敗事例
すごい作業だ。リバースエンジニアリングの方法をチュートリアルにしてみるつもりはあるのか気になる
ググりやすい部分だけ省略しただけ
欲しいのは、カメラのボタンでdSLR写真を撮ったら、少ししてその画像が Apple Photos に入っている、ただそれだけ
スマートフォンがコンシューマー向けカメラ市場をほぼ消し去ってしまい、需要が足りないのだろう。プロジェクトのアイデアとしては、ESP32 を SD カードの中に押し込む方法を探ること
携帯電話、タブレット、Webサイトにも接続できるが、アプリやサービスが必要。カメラから直接 FTP で送るドキュメント: https://gdlp01.c-wss.com/gds/5/0300024975/01/eos5d-mk4-wff-i... 113ページ。リンクは EOS 5D Mark IV (WG) Wi-Fi (Wireless Communication) Function Instruction Manual
残念ながら10年前の機種で、中古市場でも珍しい
Wi-Fi や Bluetooth でペアリングでき、望めば iPad からカメラをリモート操作して画面も見られる