kobar9568のブログ

技術的なメモやその他諸々

Fire TV Stick (第3世代)にLineageOS 18.1 (Android 11)を焼いて純粋なAndroid TVとして使う

はじめに

  • Fire TV Stick (第3世代)に搭載されるSoCである、MediaTek MT8695の脆弱性をついてブートローダーをアンロックし、TWRPを起動することが出来るエクスプロイトがXDAで公開された

    • これにより、TWRPでシステム領域の書き換えが可能になった
  • バージョン7.2.7.3未満のファーム(FireOS)がインストールされている個体が前提となる

    • 以降のアップデートで脆弱性が塞がれ、通用しなくなった
  • 基本的にはXDAに記載された通りの内容になる

    • 一部、フロントのスクリプトの書き換えが必要な部分がある

大まかな手順

  1. 母艦からエクスプロイトを実行してブートローダーをアンロックする
  2. fastbootでTWRPを起動する
  3. 母艦からLineageOS 18.1とGAppsを内蔵ストレージへ転送する
  4. TWRPでストックのファームウェアをワイプする
  5. TWRPでLineageOSとGAppsをインストールする

TWRP起動後の操作は、母艦からadb shellでデバイスに入り、CLIのtwrpコマンドで操作する方法が一番楽。

準備するもの

1. エクスプロイト本体

forum.xda-developers.com

  • スレッド1番目の投稿のAttachments内、"kamakiri-sheldon-1.0.zip"
  • TWRPもこちらに含まれている

2. Fire TV Stick (第3世代)用のLineageOS 18.1ビルド

github.com

  • GitHubリポジトリのReleasesに"lineage-18.1-20220302-UNOFFICIAL-sheldon.zip"としてビルド済みのものが公開されている

3. Open GApps

opengapps.org

  • Google系アプリケーションをAndroid系OSに提供するパッケージ
    • 今回はARM, 11.0, tvminiのバリアントを選択する

4. 母艦となる適当なLinux

  • 無難で楽なのは、Ubuntu 21.10のLive USB辺り
  • USB3.0ポート(5V0.9Aのバスパワー)があれば、Fire TV Stickをバスパワーで起動しつつ母艦になれるので楽
  • VM環境だと失敗の報告が挙がっているので、物理で1台用意するのが無難

5. その他諸々

  • Fire TV Stick本体 (バージョン7.2.7.3未満)
  • microUSB-to-USB Type-Aケーブル (Fire TV Stick付属のもので十分)
  • HDMIを入力できる何か
    • 今回、すべての手順は母艦のコマンドラインからの操作で完結するので本体の映像出力無しでも作業は完了できるが、確認用にあると良い
      • 今回はUVCとして振る舞うHDMIのキャプボを使い、カメラアプリから様子を確認した

1. 環境構築

1-1. 必要なライブラリやツールのインストール

  • XDAでオススメされている通り、Ubuntuuniverseリポジトリを追加し、そちらで必要な物をインストールする
    • 試していないが、Python系はpipで入れつつ、別途adb fastboot辺りを準備しても問題無いとは思う
> sudo add-apt repository universe
> sudo apt install python3-serial python3-usb adb fastboot dos2unix

1-2. ModemManagerの無効化

  • エクスプロイトの実行にあたり、ModemManagerを無効化しておく必要がある
    • stopだけしておけば問題無さそうだが、念の為disableも入れておく
> sudo systemctl stop ModemManager
> sudo systemctl disable ModemManager

1-3. 必要な物のダウンロード

  • エクスプロイト本体・LineageOS・GAppsをダウンロードしておく
  • エクスプロイト本体のみ解凍しておく
    • TWRPを用いてインストールする後者2つについては、解凍しない

2. ブートローダのアンロック

sudo ./bootrom-step.sh
  • 以下のメッセージが表示されたことを確認する
[(実行時刻)] Waiting for device
  • Fire TV Stickを母艦に接続すると、自動でアンロックが開始される

f:id:kobar9568:20220320165940p:plain

  • なお、RuntimeError: downgrade failure, giving upが発生する場合は一部の処理をスキップするようフロントのスクリプトの書き換えが必要
    • 今回試した個体はこちらの書き換えが必要だった

f:id:kobar9568:20220320171504p:plain

vi modules/main.py

f:id:kobar9568:20220320171524p:plain

rpmb = dev.rpmb_read()
if rpmb != b"\x00" * 0x100:
    dev.reboot()
    raise RuntimeError("downgrade failure, giving up")

f:id:kobar9568:20220320172054p:plain

  • Fire TV StickのHDMI出力の方で、ブートロゴの左下にHACKED FASTBOOT modeの表示が出ていることを確認。これでブートローダのアンロックが完了した

3. TWRPの起動

  • 以下のシェルスクリプトを実行すると、fastboot boot recoveryとしてTWRPを送り込んで起動する
> ./fastboot-step.sh

f:id:kobar9568:20220320173119p:plain

f:id:kobar9568:20220320173225p:plain

  • TWRPの操作は母艦からadb shellでデバイスに入り、twrpコマンドで実施する

2. LineageOSのインストール

  • 先にLineageOSとGAppsをadb pushでデバイスに送り込みTWRPでそちらをインストールする

  • adb devicesで認識されていることを確認したのち、内蔵ストレージへadb pushで送り込む

f:id:kobar9568:20220320174440p:plain

  • adb shellでデバイスに入り、twrpコマンドでワイプを実施

f:id:kobar9568:20220320174557p:plain

f:id:kobar9568:20220320174627p:plain

  • 引き続き、twrp installで先程送り込んだ2つのファイルをインストールする

f:id:kobar9568:20220320174722p:plain

  • HDMIの方でも、TWRPのログを確認することが可能

f:id:kobar9568:20220320174755p:plain

  • 完了したら、adb shellの方でrebootを実施する

3. LineageOSの起動

  • 初回起動時はブートロゴで暫く掛かるが、起動を待つ

f:id:kobar9568:20220320174913p:plain

  • 付属のリモコンをペアリングし、後はAndroid TVとして使うことが可能

f:id:kobar9568:20220320175015p:plain

f:id:kobar9568:20220320175527p:plain

  • Android TVでも、デフォルトでホームに広告が出るらしい

f:id:kobar9568:20220320175127p:plain

所感

  • ブラックフライデーのセールで2台4000円で購入し、放置されていた端末を使った

    • おもちゃとして焼き変えてみたものの、UI/UXに関してはFireOSの方が優れている印象
      • 実験目的以外ではおすすめしない
  • Fire TV Stickは本体の裏面に技適ロゴが印刷されているので、今回の手順は特に法的な問題は無い

    • 端末によってはソフトウェア的に技適ロゴを表示するものもあり、そちらはファームの書き換えによって表示できなくなった場合は怪しい(アウト?)な気がする。勿論物理的な分解をすればアウト

coc-eslintとeslint@8.xの組み合わせが動かなかった話

本格的にTypeScriptの開発環境を整えようと色々していたのだが、coc-eslintが動いていないようだった。

f:id:kobar9568:20211114021240p:plain

JS界隈に詳しくないので、eslintをグローバルで入れてみたりWindows機とLinux機で試したりと色々していたが、:CocCommand eslint.showOutputChannelしてみると何やら不穏なエラーが出ている。
[Error - 2:20:01 AM] The eslint library loaded from (リポジトリルート)/node_modules/eslint/lib/api.js doesn't export a CLIEngine. You need at least eslint@1.0.0

原因はcoc-eslintとeslint@8.xの相性問題のようだった。
coc-eslintのissueによると、eslint@8.xのメジャーバージョンアップでcoc-eslintが依存していたAPIが削除されたことによる影響らしい。

Gitpodのissueでも言及されていた。

yarn remove eslintした後、yarn add eslint@7.32.0で無事lintが効くようになった。

f:id:kobar9568:20211114021258p:plain

Windows版のVimで句読点や全角スペースが入らなかった話とScoopで入れるのが良さそうという話

概要

  • 公式のインストーラで入れたVimで、句読点や全角スペースが入らなかった。(ファイルを読み込んだ場合表示はされる)
  • 取り敢えずScoopで入れたVimでは問題は発生せず
  • Vimのビルドオプションによって変わるっぽい?
  • 他にも、Powerlineの表示が崩れる問題もScoopで入れたVimでは発生せず

句読点や全角スペースが入らない

インサートモードからの入力でも、ヤンクしたものを貼り付けても、:set pasteした上でWindows Terminalからペーストしても入らない。
ペーストした文字列に句読点や全角スペースが含まれていた場合は抜け落ちてしまう。
公式のインストーラ版で発生し、Scoopで入れたものでは発生しなかった。

Powerlineの表示崩れ

ステータスライン右下の改行コード部の左側に、1つ不要な矢印が表示される表示崩れがあった。(SSが残っていなかった為、画像加工したもの)

f:id:kobar9568:20210712000943p:plain

これはファイルを開いていない状態でのみ発生し、何かファイルを開くと発生しない。
この問題も、公式のインストーラ版で発生し、Scoopで入れたものでは発生しなかった。

WindowsVimを使う

  • 最近であればWSLを通して使うのが一般的だと思う。
  • (特にプラグイン等でモダンにカスタマイズしている場合)Windows版で使おうとするのは割と茨の道
  • Scoop版を使った上で、細かい部分を調整してやると意外とWindowsでも快適にVimが使える

f:id:kobar9568:20210711235022p:plain

  • VimWindows Terminalに限らず、個人的に使っている設定等はdotfilesリポジトリで公開しているので、何か参考になるものがあれば。

Docker 20.03.2以降、デフォルト設定ではIPv6のポートが公開されなくなったっぽい(2021-03-05時点)

忙しい人向け

  • Docker 20.10.2の仕様変更で、インストール直後のデフォルト状態ではIPv6のポートがマッピングされなくなった。
  • 2021-03-05時点では、IPv6アドレッシング等のインフラを変えたくない場合はDocker 20.10.1を使う
    • 2021-03-04にリリースされたDocker 20.10.5時点で、この仕様変更はロールバック等はされていない。
  • ざっとissueを眺めた感じ、仕様変更と別に、IPv6のポートフォワード周りに問題が生じてるのかも?(未検証)

    • コンテナにユニークローカルユニキャストアドレス(ULA)を割り当てて、DockerホストのアドレスをNAPT(NAT66)で使った環境とかだと問題が起きてるのかもしれない?(未検証)
      • グローバルユニキャストをコンテナに回してくる、IPv6の考えとしてはあるべき構成も試してないのでこちらも不明
  • 動向はmobyのこの辺のissueを追ってると良さそう

以下色々試してた時の日記

問題発生

  • ESXiの導入とともにDockerホストもそちらに仮想マシンとして移設し、暫く運用していた。
  • Dockerに載せているMinecraftサーバーにIPv6で繋ごうとした友人から、繋がらないとの話があった。IPv4では問題なし。
  • 最初はAAAAを疑ったのだが、これは問題無し。経路中のルータのIPv6ファイアウォールsh access-listsで確認したが問題無くマッチしている。
  • おかしいと思って確認したところ、同一セグメントからもIPv6では繋がらない事が発覚。 グローバルユニキャストもリンクローカルもダメ。

パケットの調査

  • 取り敢えずパケットを取ってみたところ、クライアントからのTCP 3way-handshakeのSYNのパケットが出た後、サーバーが即RST,ACKを返して仮想回線の確立を拒否し、クライアントが接続要求を再送し、RSTを送りつけられる…という動きをしていた。
    • L3でのリーチャビリティはあるが、ポートが空いていない時に明示的に通信を切る動作。Webサービス(Dynmap)にブラウザで繋ごうとするとConnection refusedとなる。
    • 実際にICMPv6は通っており、ping6は成功していた。
  • IPv4では問題無くサービスが動作しており、IPv6のみこの現象が起きていた。

迷走

  • 私の環境ではESXiホストにしているマシン(普通の自作パソコンを流用)のオンボードNICRealtek RTL8111Gであり、これはESXi 7.0に対応しておらず、インストールすることが出来ない。
  • その為、USB3.0 to EthernetのチップであるASIX AX88179を搭載したUSBNICであるELECOM EDC-GUA3-Bを使っていた。
    • flingsで公開されているドライバを組み込んだイメージをインストールしたもので、ネットワーク周りは不安を抱えていた。
      • この為、ESXi側のどこかで起きた問題だろうと考えてしまい、問題の本質から離れてしまった。

発見

  • Dockerホストとしている仮想マシンでDockerに載せずに直接動かしているSSHにはIPv6で繋がることに気付き、漸くDockerの問題もしくは相性問題を疑い始める。
  • 一旦VMware Workstation Playerに構築したUbuntu ServerにDockerをインストールし、テストした所問題が再現した。
  • この時点でDockerとVMware系の仮想化との相性問題を疑い、物理マシンで試してみると、こちらでも再現。

  • そして色々と調べているうちに、Docker-proxyとIPv6の問題として仕様変更についてのissueを見つけた。

結論

  • 今までの環境では取り敢えずDockerをインストールしたそのままの状態でも、ホストにIPv6アドレスが割り当てられていればIPv4IPv6の双方でポートをコンテナに転送してくれていた。

  • 今回の仕様変更でその仕様が潰されたので、少なくともNAT64を使わずにULA+NAT66を使うか、ちゃんとグローバルユニキャストをコンテナまで回してくるインフラを整えてIPv6のあるべき姿にするべきなんだと思う

    • とはいっても色々面倒くさい… Dockerホストの側でその辺集約したいという感じが結構ある
      • もしくはプロキシ?
  • 正直その辺の使用を良く理解せずに、デフォルトでNAT64掛けてくれてるからそのままで良いやと使っていたが、ちゃんと考え直さないとなぁとなった。

ESXi 7.0上のLinuxからUSB赤外線リモコンアドバンスを使った話

忙しい人向け

この記事に倣い、USBアービトレータの設定でADIR01Pのパススルーを許可するように設定し、ブートオプションでADIR01PがVMkernelにHIDデバイスとして認識されることを防ぐことで仮想マシンへパススルー可能となる。
なお、記事では最初に仮想マシンの設定ファイル(vmx)を直接編集してデバイスを追加する手順があるが、ここは不要だった。 vmxを編集していない仮想マシンでも、ESXiに対する設定2つを行えばパススルー設定を行うことが出来た。

概要

ビット・トレード・ワンUSB赤外線リモコンアドバンス ADIR01P(以下 ADIR01P)をESXi 7.0上のLinuxから扱った話。

ADIR01PはUSBインターフェースを持つ学習リモコンで、非公式のUNIX/Linux向けのコマンドラインプログラムであるbto_ir_advanced_cmdが公開されており、これを利用していた。
自宅鯖をESXiに移行するタイミングで、他のデバイスと同じ様にADIR01Pも仮想マシンにパススルーしようとしたのだが、少し面倒な手順を踏む必要があった。

面倒な理由

ESXi Shell(に限らず)でlsusb -vするとわかるのだが、ADIR01PはHIDクラスのキーボードやマウスとして振る舞う様にそれらをInterfaceとして実装しており、ESXiはHIDクラスのデバイスをパススルーすることが出来ない。

f:id:kobar9568:20210217041349p:plain
f:id:kobar9568:20210217041602p:plain
f:id:kobar9568:20210217041615p:plain

USBホストコントローラごと引き渡してみる(失敗)

ESXiで仮想マシンにHIDクラスのデバイスを引き渡したい場合、USBホストコントローラごと引き渡すという手法がよく取られるらしい。
PCIやPCIeのUSB拡張カードでUSBホストコントローラを増設し、PCIeデバイスとしてUSBホストコントローラを仮想マシンにパススルーすることでVMからHIDデバイスを扱える。
VMとしてWindowsを使ってゲーム機を作る人がゲームコントローラやマウス・キーボードを渡す時によく使われる手法らしい。

当初はこれに倣い、Amazonで安かったUSB3.0x4ポートのPCIe x1拡張カードを増設してそこにADIR01Pを挿し、USBホストコントローラごとパススルーした。
しかし実際にこの環境でbto_ir_advanced_cmdを使ってみると赤外線の受信開始と受信停止は出来たものの、データの取得や赤外線パターンの送信を行おうとするとerror -3と関数の戻り値がそのまま表示されるような厄介なエラーになってしまい、ソースをチラッと見たのだがlibusbを通したUSBデバイスとの会話でエラーが出ているようで、私の知識ではよくわからなかった。

仮想マシンからlsusbしてみると22ea:003aのデバイスUSB2.0のハブとして表示されており、ネイティブで繋いだ場合はデバイスの説明に何も表示されないのでその違いが気になった。

ESXiの方で無理矢理なんとかする(成功)

↑の手法はbto_ir_advanced_cmdの情報の少なさと、私がソースを理解してパッチを作れるだけの知識が無いので別の手法を調べたところ、ESXiに認識されつつもパススルーを制限しているHIDデバイスの制限を解除することでパススルーを可能とする手法があった。
安定性面などで推奨されるものでは無さそうだが、一旦これで運用してみることとした。

まずは先程設定したUSBホストコントローラのパススルーを無効に設定し、
基本的にはこの記事の内容でESXi Shellから設定を行い、ホストを再起動。
その後、仮想マシンの設定からUSBデバイスの追加を行うと、無事ADIR01Pが追加できるようになった。
f:id:kobar9568:20210217042738p:plain
仮想マシンを起動して操作を試したが、今度は問題無く赤外線送信を行うことが出来た。また、Dockerからも問題なく扱えた。 暫くこれで運用してみて、様子を見ようと思う。

BitTradeOne 赤外線リモコンアドバンス ADIR01P

BitTradeOne 赤外線リモコンアドバンス ADIR01P

  • 発売日: 2015/08/07
  • メディア: Personal Computers
ちなみにUSB3.0のボードはlspciで見たところ、VIA Technologies, Inc.VL805 USB 3.0 Host Controllerがホストコントローラとして載っていた。 今回は別の手法を取ったが、ESXiで使う用の安いボードとして良さそう。ペリフェラル電源が不要なので取り回しが良い。

Windowsで最高のターミナルエミュレータを求めて三千里

はじめに

ターミナルエミュレータで試行錯誤してみたので、スクラムチームで行っているDX/PX向上デーのネタも兼ねて書き残しておく。
私は普段使いのマシンがWindowsで、開発機としてGUIの入ったUbuntuも愛用している。メインマシンからUbuntu(若しくはUbuntu Server)にSSHして開発することが多い。
一昔前はWindows向けのターミナルエミュレータの選択肢があまり無く、conhost.exeか(純粋なターミナルエミュレータではないが)Cmder、Tera Term・PuTTYあたりが候補だったと認識している。
最近では色々とモダンなものが出てきているが、Mac並に快適に使いたいと思い色々と試してみた。

以下、2020-09-29時点の内容。

Windows Terminal

  • UWPアプリ
  • TrueColor対応
  • フォントウエイト bold非対応
  • フォントのフォールバック先は指定不可
    • 但し、レジストリの編集等で変更できるかもしれない
      • (2020-10-10追記): フォントリンクはGDIの話であり、Windows TerminalはDirectWriteベースらしいので、少なくとも思っていた方法では解決しなかった。

備考

  • 対応OSはWindowsのみ
  • フォントの合字(リガチャ)を明示的に有効/無効にできない

Hyper Terminal

備考

  • そこそこの頻度で描画の不具合が起こり、定期的なFull reloadが必要
  • SSH先でウインドウを閉じた場合にクラッシュする不具合がある
  • フォントの合字(リガチャ)にはプラグインで対応

VS Code Integrated Terminal

  • Electron製
  • TrueColor対応
  • フォントウエイト bold対応
  • フォントのフォールバック先に好きなフォントを指定可能

備考

  • そもそもターミナルエミュレータではない
  • VSCode側のカラーテーマに引っ張られる
  • フォントの合字(リガチャ)を明示的に有効/無効にできる

スタイルをVS Codeに近づける

  • 私はVS CodeEditor: Line HeightEditor: Letter Spacingは特に弄らず、初期値のまま使っている。
    使うフォントによって適切な設定は変わってくると思うが、今の所初期値で見やすいと感じている。
    • Integrated Terminalや他2つのターミナルでも同じスタイルで使いたいと思っているが、デフォルトだと気持ち詰め気味になっている。
    • 取り敢えずElectron系ターミナルでは前者を1.12に、後者を1に設定したが、フォントやフォントサイズによっても変わってくるのでいい感じに調整したい。

総評

  • 現時点で、Windowsにおいて最も快適なターミナルエミュレータWindows Terminalだと思う
    • 開発も盛んに進んでいて、今後の進展にも期待
  • Hyperは恐らくMac OSをメインターゲットとしており、Windowsでは微妙な感じ

  • 完成度の高いクロスプラットフォームのターミナルエミュレータを使い、すべてのOSで全く同じ環境を使う…というのは現時点では難しそう

    • どちらにせよSSHするのであれば、現時点では見た目の差異を我慢してでも適したものを使う感じで行こうと思っている

WindowsからSSHした先でtmuxを上げると変なエスケープシーケンスが表示される件とその対処

忙しい人向け

  • Windows 10 1803以降に標準機能として組み込まれているOpenSSH Client (Win32-OpenSSH)が悪さをしている
    • 2020-09-08時点で、恐らくWindowsのバージョンに関係無くOpenSSH_for_Windows_7.7p1が入っている
  • GitHubからv8.1.0.0p1-Beta以降を落としてきて使うことで回避可能

症状

WindowsからSSHした先のUbuntuでtmuxを上げると変なエスケープシーケンスが表示される。

f:id:kobar9568:20200908202228p:plain

ホスト名やユーザ名は青で伏せているが、プロンプトの前に^[[?1;0c⏎という文字が、プロンプトの後ろに[?1;0cという文字が表示されている。
ターミナルエミュレータを変えても再現し、UbuntuAndroid (Termux)からSSHした場合は再現しなかった。 bash, fish等シェルを変えると表示内容が変わるが、エスケープシーケンスが表示されることに変わりはない。

この時点で色々と調べたがこれといった情報が無く、TODOとしていた。

別の症状に気づいた

Shift + Tabも効かない。

f:id:kobar9568:20200908203222p:plain

[~ が文字として送信されてしまい、シェルやLanguage Serverの補完を選択する際、前に戻ろうとすると補完が閉じてしまう。

手がかり発見

Windows Terminalのリポジトリに投稿されたissueを発見した。
https://github.com/microsoft/terminal/issues/6769#issuecomment-653985047
これによると、Win32-OpenSSHがキー入力をキャッチして余計な処理をしてしまうらしい。
また、Win32-OpenSSH 8.1以降ではこの点が修正されているらしい。

どちらの問題も解決

とのことで、早速2020-09-08時点で最新のv8.1.0.0p1-Betaをダウンロードし、このsshバイナリからSSHで繋いでみたところ、
tmuxを上げた際の変な文字列が表示される問題も、Shift + Tabが効かない問題も解決した。

GUIの設定アプリからオプション機能として追加できるOpenSSH Clientは、2020-09-08時点でOpenSSH_for_Windows_7.7p1だった。

f:id:kobar9568:20200908205224p:plain

一度GUIからアンインストールして入れ直しても特にアップデートされるようなことは無かった為、こちらから入れるのではなく、GitHubのReleasesから落としてきたバイナリを使うべきだろう。 補完がまともに使えないのは流石にキツい。