Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
z80-sans — Z80命令を逆アセンブルするOpenTypeフォント | Kitploit
ツール/GitHubGitHub/nevesnunes/z80-sans
リバースエンジニアリングファジングCTFハードウェアセキュリティバイナリ解析学習と教育
GitHubnevesnunes/z80-sans

z80-sans

Z80命令を逆アセンブルするOpenTypeフォント

リポジトリを見る
506332年前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

Z80 Sans

あなたのお気に入りの逆アセンブラは何ですか?私はフォントです:

https://github.com/user-attachments/assets/bb6ceb18-c2fd-40a9-be4f-202321a214d9

このフォントは、16進小文字のシーケンスを逆アセンブルされたZ80命令に変換します。OpenTypeのGlyph Substitution Table (GSUB)とGlyph Positioning Table (GPOS)を広範囲に利用しています。

試してみたいだけなら、./test/z80-sans.ttf にコピーがあります。

インストール

Debian GNU/Linux 12 でテスト済み。このDebianバージョンにはrubyバージョン3が付属していますが、fontcustomはrubyバージョン2向けに書かれており、それ以降のバージョンとは互換性がありません(例:構文エラー)。また、rubyのインストールには互換性のあるOpenSSLのバージョンが必要です。そのため、RVMを使用してrubyとOpenSSLのローカルインストールの両方を管理できます。

root@kitploit:~
apt install imagemagick potrace
pip install fonttools

git submodule update --init --recursive

# fontforge
(
cd ./modules/fontforge/
git checkout 4f4907d9541857b135bd0b361099e778325b4e28
git apply ../../resources/fontforge.diff
mkdir -p build
cd build
cmake -GNinja ..
ninja
ninja install
)

# woff2
(
cd ./modules/woff2/
make clean all
)

# fontcustom
rvm use 2.7
rvm pkg install openssl
rvm install 2.4 --with-openssl-dir=$HOME/.rvm/usr
gem update --system 3.3.22
(
export PATH=$PWD/modules/woff2/build:$PATH
cd ./modules/fontcustom/
git apply ../../resources/fontcustom.diff
gem build fontcustom.gemspec
gem install ./fontcustom-2.0.0.gem
)

実行

root@kitploit:~
cp ./resources/droid-sans-mono.ttf /tmp/base.ttf
./gen.py ./resources/instructions.json

.ttfフォントファイルは ~/.local/share/fonts/ にコピーされます。これは例えばLibreOfficeで使用されます。

設計

他の呪われたフォントと比較して、Z80 Sansには以下の課題があります:

  • 複数の文字をレンダリングする:すべての置換ルールを一文字ずつ手動で定義するのは非現実的なので、複数のリテラルを組み合わせたグリフ(例:CALLのようなニーモニック)を作成できます。ただし、これは次の点にも関係します...
  • 多数の組み合わせ:一部のZ80命令は16ビットアドレスやレジスタをオペランドとして取ることができ、単一の命令で最大 65536 * 7 = 458752 の組み合わせが可能です。
  • 順序が入れ替わったオペランド:例えば、レジスタとオフセットが16進バイトで一方の順序でエンコードされても、逆アセンブルでは別の順序で表示されるため、バックトラッキング/先読みルールが複雑になります。
  • リトルエンディアンのアドレス:最下位バイトの文字を最上位バイトより先にレンダリングする必要があります。
  • 符号付きオフセット:0x80..0xff の範囲のすべてのオフセットは、負の2の補数としてレンダリングする必要があります。

これらすべてはプログラムによる解決策を必要とします。fontcustomとImageMagickがグリフの生成を担当する一方で、ルックアップルールを記述する便利な方法は.fea形式のようです。しかし、fonttoolsの.ttx形式(基本的にxml)と統合する方法が見つかりませんでした。そこで、Noto Sans Monoの.ttxを直接編集するという最も低レベルの共通分母アプローチを取りました(ただし、グリフ形状はDroid Sans Monoから計算されています。これはFontForgeにパッチを当て始めたときに使用していたものだからです)。

再帰下降パーサーを使用してすべての可能なグリフを生成します。これは、エンコーディング内の式を評価するのに役立ちます(例:SET b,(IX+o) はビットと変位を取り、DD CB o C6+8*b としてエンコードされます)。これらのエンコーディングは、オペランドが取り得るすべての値に展開され、最終的に、展開された命令をレンダリングするために必要な各逆アセンブルグリフに1つ以上の16進バイトが関連付けられます。

OpenTypeの機能に関する優れた参考文献はいくつかありますが、それらは高レベルで書かれているか、.fea形式です。

  • OpenType Feature File Specification | afdko
  • GSUB — Glyph Substitution Table (OpenType 1.9.1) - Typography | Microsoft Learn
  • Fonts and Layout for Global Scripts
  • GitHub - brew/opentype-feature-intro: An introduction to OpenType features for type designers.
  • Features, part 3: advanced contextual alternates | Glyphs
  • Opentype subtitution many by many (different number) - Glyphs Forum

それらを.ttxに変換する方法はあまり明確ではないため、結局、Noto Sansファミリー全体を変換し、昔ながらの「例から学ぶ」というブルートフォースアプローチを使用しました。これは、.ttxから.ttfへの変換時に、fonttoolsで検証されないいくつかの前提条件(例えば、コンテキスト連鎖置換のクラス定義には、クラス値が "1" のカバレッジグリフが少なくとも1つ必要)により、多くの暗黙の失敗があるため、思った以上に楽しいものです。

ほとんどの課題は、コンテキスト連鎖ルールで解決されました。アドレスを処理するために、範囲 0..f 内の各ニブルは異なるグリフでエンコードされ、スペース文字を使用して複数の置換を一度に1文字ずつ作成しました。変位には追加の符号付きバリアントもあります。これにより、数字用のグリフは合計 (4 + 2) * 16 個になります。これだけで、フォントファイルを65536グリフの制限内に抑えるのに十分でした。

最悪だったのはもちろん、順序が入れ替わったオペランドです。しかし、これらは命令内でのバリエーションの数が限られているため、曖昧にエンコードされたプレフィックスを持つ命令と同じ戦略でカバーできます。例えば、

root@kitploit:~
["SET b,(IX+o)", "DD CB o C6+8*b"],
["SET b,(IY+o)", "FD CB o C6+8*b"],

は、以下のルックアップルールと同じルールでカバーされます:

root@kitploit:~
["SRA (IX+o)", "DD CB o 2E"],
["SRA (IY+o)", "FD CB o 2E"],
["SRL (IX+o)", "DD CB o 3E"],
["SRL (IY+o)", "FD CB o 3E"],

Z80 ISAの興味深い特性として、ビットとレジスタには最大8つのバリエーションがあり、これらの順序が入れ替わったケースにはオフセットとこれらの特定のオペランドの1つだけが含まれます。そのため、ビットやレジスタをリテラルとしてエンコードできます。十分な先読みがあれば、最後の16進バイトまで一致させ、各ケースに専用のルックアップを作成できます。最後のリテラルは、サフィックスグリフに一致する合字を生成することで削減できます。最終結果は、これらのケースに対して数十の追加の生成ルックアップになりました(これらはおそらくグループ化して数を減らすことができます)。

既知の問題

  • 元の命令セットのすべてが逆アセンブルされるはずですが、一部の命令には軽微なグリッチがあります:
    • LD (IX+o),r は LD (IX+o r), とレンダリングされます。
    • SET b,(IX+o) は SET b,(IX+o)) とレンダリングされます。
  • "CTF品質" のコード😅。

今後の作業

FontForgeでは、コマンド GenerateFeatureFile() と MergeFeature() を使用したスクリプト可能な機能修正がサポートされています(The Terrible Secret of OpenType Glyph Substitution - Ansuz - mskala's home page で簡単に紹介されています)。私は.ttxベースの実装を行った後にこれに気付きましたが、.ttxファイルをいじる必要を避けることができたかもしれません。

より複雑な命令セットの場合、制約が少ない代替アプローチとして、フォントシェイパーを使用する方法があります。いくつかの例:

  • fuglede/llama.ttf: A font for writing tiny stories;
  • hsfzxjy/handwriter.ttf: Handwriting synthesis with Harfbuzz WASM.;

クレジット

  • Droid Sans Mono と Noto Sans Mono をZ80 Sansのベースとして使用しました。
  • ./resources/instructions.json は maziac/z80-instruction-set から改変しました。
  • GSUB置換のインスピレーション:
    • Font with Built-In Syntax Highlighting;
    • Fontemon、特に "How I did it";
    • Addition Font;
    • Sans Bullshit Sans;

ライセンス

  • Droid Sans Mono は Apache Licence の下にあります。
  • Noto Sans Mono は Open Font License の下にあります。
  • ./resources/instructions.json は GNU Lesser General Public License version 3 の下にあります。
  • その他のファイルは MIT License の下にあります。
ツールをダウンロード