「Binary Hacks Rebooted」について
このページは「Binary Hacks Rebooted」の著者の一人である荒田が管理する半公式(?)サポートページです。
公式リンク
O'Reilly Japan - Binary Hacks Rebooted
(出版社)
Binary Hacks Rebooted 低レイヤの世界を探検するテクニック89選 | Ohmsha
(購入リンクあり)
oreilly-japan/binary-hacks-rebooted: 『Binary Hacks Rebooted』のサポートリポジトリ
(サポートリポジトリ)
関連記事
「Binary Hacks Rebooted」が出ます | 雑記帳
詳細目次
本書に寄せて
クレジット
はじめに
1章 イントロダクション
#1 未知のバイナリの読み方
fileコマンド:ファイル形式を特定する
人力fileコマンドのやり方
まとめ
#2 アセンブリ入門
まとめ
#3 Hello, World!再訪
libcのシステムコールのラッパを使ったHello, World!
アセンブリ言語でのHello, World!
ELF HackのためのHello, World!
動的命令生成を使ったHello, World!
まとめ
2章 ELF Hack
#4 ELFファイルのセグメント
PT_INTERP
PT_LOAD
PT_DYNAMIC
PT_NOTEとPT_GNU_PROPERTY
PT_TLS
PT_GNU_EH_FRAME
PT_GNU_STACK
PT_GNU_RELRO
まとめ
#5 ld-linux.soの環境変数を利用する
LD_PRELOAD
LD_DEBUG
LD_AUDIT
まとめ
#6 共有ライブラリを検索するディレクトリ
共有ライブラリの検索の実例
ダイナミックリンカが共有ライブラリを検索するディレクトリ
セキュリティ実行モード
DT_RUNPATH
まとめ
#7 dlopenによるライブラリの実行時ロードとその応用テクニック
dlopenとdlsym
dlopen、dlsymを使ってみる
応用:既存のライブラリ関数をラップする
まとめ
#8 IFUNCを使って実行時に実装を切り替える
IFUNCの使用例
IFUNCのresolver functionが呼ばれるタイミング
まとめ
#9 ELFのハッシュテーブルのしくみ
DT_HASH
DT_GNU_HASH
2つのハッシュテーブルの比較
まとめ
#10 TLSのしくみを理解する
TLSアクセスモデル
各アクセスモデルの実際の動作
まとめ
#11 コアファイルを読む
コアファイルの構造
コアファイルの解析
まとめ
#12 補助ベクトルを使ってプロセスに情報を渡す
補助ベクトルの利用
補助ベクトルがプロセスに渡されるしくみ
参考文献
まとめ
#13 静的リンクとASLRの関係
静的リンクされたアプリケーションの作り方
静的リンクとASLR
まとめ
#14 soldを使って依存する共有ライブラリを後からリンクする
soldの使い方
soldのしくみ
まとめ
#15 glibcをHackする
glibcのソースコードを読む
glibcにパッチを当てる
まとめ
#16 patchelfでELFバイナリのフィールドを書き換える
PT_INTERPの編集
DT_RUNPATHの編集
参考文献
まとめ
#17 LIEFを使ってELFバイナリを書き換える
シンボルのリネーム
関数の差し替え
まとめ
#18 PT_NOTEを利用したバイナリパッチ
PT_NOTEタイプのプログラムヘッダの書き換え
参考文献
まとめ
#19 DWARF Expressionを実行する:DWARFⅠ
DWARFについて
四則演算用のひな型の準備
DWARF Expressionが実行できることの確認
まとめ
#20 DWARFで数式を評価する:DWARFⅡ
入力された数式の参照
与えられた数式の評価
まとめ
#21 DWARFで標準出力に出力する:DWARFⅢ
評価結果の出力
実世界における意義
参考文献
まとめ
3章 OS Hack
#22 実行可能ファイルとその起動方法
shebang
binfmt_misc
まとめ
#23 LinuxでHuge Pageを使う
Transparent Huge Page
明示的なHuge Pageの確保
まとめ
#24 CRIUを使ってプロセスを保存、再開する
CRIUの使い方
CRIUのしくみ
まとめ
#25 procfs / sysfsの基本を把握する
procfs
システム全体の情報に関するファイル
sysfs
まとめ
#26 用途に合わせたファイルシステムを選ぶ
Overlay Filesystem(OverlayFS)
Btrfs:Copy-On-Writeファイルシステム
EROFS:圧縮ファイルシステム
まとめ
#27 特定のプロセスに見せるファイルを差し替える
バインドマウントでファイルやディレクトリを一時的に置き換える
マウントネームスペースとバインドマウントで特定のプロセスにのみ置き換えを行う
OverlayFSを用いて、ファイルへの書き込みだけ別の場所へと置き換える
まとめ
#28 FUSEを使ってファイルシステムを自作する
FUSEとは?
FUSEのしくみ
ファイルシステムを自作してみる
パフォーマンス向上のコツ
まとめ
#29 特殊なメモリ領域vsyscallとvDSO
vsyscallの当初の用途
vsyscallのほかの用途
vDSO
まとめ
#30 KVMを使ってハイパーバイザを作成する
ハイパーバイザとは
KVMの概要
ゲストプログラムの準備
KVMのAPI
VMを実行する
実用的なハイパーバイザへの道
まとめ
#31 LinuxカーネルHack入門
Linuxカーネルを読む
Linuxカーネルをビルドする
ルートディスクイメージの作成
QEMUでLinuxシステムをブートする
まとめ
#32 Unikernel:アプリケーションをOSとして動かす
Unikernel/ライブラリOSとは
UnikraftでアプリケーションをUnikernelにする
まとめ
#33 UEFIとSecure Boot
Secure Boot
Secure Boot変数
まとめ
#34 GNUツールチェインで機械語ファイルを出力する
リンカスクリプトを使ってバイナリファイルを出力する
C言語に対応したリンカスクリプト
まとめ
#35 QEMU上で動くファームウェアを作る
PCのブート
QEMUを使ったファームウェアプログラミング
まとめ
#36 Chromebook上で自作のファームウェアを動かす
ChromebookのCCD
CCDを使ったファームウェア書き換え
Apollo Lakeを搭載したChromebook上でのファームウェアプログラミング
まとめ
4章 コンテナHack
#37 Linuxネームスペースでプロセスを分離する
Linuxネームスペース
PID/マウントネームスペースを作ってみる
まとめ
#38 cgroupでプロセスのリソースを管理する
cgroupの概要
cgroupの基本操作
メモリのコントロール
PIDのコントロール
I/Oのコントロール
まとめ
#39 chroot/pivot_rootでルートディレクトリを切り替える
chrootによるルートディレクトリの切り替え
pivot_rootによるルートファイルシステムの差し替え
まとめ
#40 一般ユーザーがrootのように振る舞う方法3選
setuidを設定する
必要なケーパビリティだけを付与する
ユーザーネームスペースの中でrootになる
まとめ
#41 rootlessコンテナの使い方とそのしくみ
rootlessコンテナとは
Podmanを使ってみる
rootlessコンテナのしくみ
まとめ
#42 ユーザーネームスペース内で各種のネームスペースを作成する
ユーザーネームスペースの制限
マウントネームスペースの制限
ネットワークネームスペースの制限
cgroupネームスペースの制限
まとめ
#43 /proc/PID/rootからコンテナ内のファイルに直接アクセスする
/proc/<PID>/rootを使ってみる
まとめ
5章 デバッガ・トレーサHack
#44 gdb Tips
コマンドを省略する
特定の状況でブレークする
ブレーク時に自動で処理する
さまざまな情報を取得する
環境設定
メモリの検索・操作
レコード
チェックポイント
便利に表示する
Python連携
プラグイン(.gdbinit)
gdbserver
まとめ
#45 rrを使ってRecord and Replayデバッグを行う
rrとは
rrを使ってみる
rrの原理としくみ
まとめ
#46 サニタイザで低レイヤのバグを見つける:サニタイザⅠ
サニタイザとは
サニタイザの種類
サニタイザを使ってみる
ほかのバグ検出方法との関係
まとめ
#47 Address Sanitizerのしくみ:サニタイザⅡ
Address Sanitizerが追加するコード
アセンブリを見てみる
まとめ
#48 Linuxパフォーマンス解析ことはじめ
可観測性ツールの分類
perfコマンド
まとめ
#49 ftraceを使ってカーネル内で起こっていることをトレースする
準備
関数コールグラフのトレース
関数トレーシングのしくみ
イベントトレーシング
ユーザースペースのイベントも記録する
trace-cmdを通じたトレーシング
まとめ
#50 eBPFを使ったトレーシング入門
eBPFとは
eBPFプログラミングのためのライブラリ
bpftraceを使ってみる
bpftraceの基本的な文法
まとめ
#51 DBIで実行命令をトレース・改変する
代表的なDBIツール
Fridaでトレースと改変を行う
まとめ
#52 Intel PTで高速にトレースを取得する
Intel PTのパケット
Intel PTで実行命令数を取得する
まとめ
6章 セキュリティHack
#53 seccompでプロセスの使えるシステムコールを制限する
seccompとは
seccompを使ったプログラムを書く
実アプリケーションでの使用例
まとめ
#54 Landlockで非特権プロセスサンドボックスを作る
Landlock
Landlockを使ったプログラムを書く
Landlockプログラムの動作を確認する
注意点:Landlockの制限
まとめ
#55 ASLR:不正なメモリアクセスに対するセキュリティ機構
Linuxユーザーランドプロセスに対するASLRの動作
Linuxユーザーランドプロセスに対するASLRの実装
ASLRを回避する攻撃手法
まとめ
#56 ROP:メモリ破壊を悪用するスタンダードな攻撃手法
Linuxユーザーランドでの一例
ROPの重要性
ROPへの対策
まとめ
#57 Intel CET:ROPに対するセキュリティ機構
Shadow Stackの詳細
Intel SDEでIntel CETを試す
まとめ
#58 Clang CFIによって不正な制御フローを検知する
関数ポインタの検査
クラスオブジェクトのポインタの検査
共有ライブラリを考慮したバージョン
まとめ
#59 スタックフレームの変化を観察する
素朴なスタックフレーム
フレームポインタの省略
Stack Smashing Protector(SSP)
Red zoneの利用
まとめ
#60 ファジングの概要と分類
ファザー(ファジングツール)の種別
代表的なファジングツール
まとめ
#61 グレイボックスファジングでバグや脆弱性を探す
プログラムをビルドしてAFL++でファジングする
グレイボックスファザーのしくみ
AFL++におけるプロセス間通信のしくみ
まとめ
#62 LibAFLでファザーを実装する
対象プログラムのビルド
愚直なファザーを実装する
まとめ
#63 LibAFLで実装したファザーを改良する
シードスケジューリングの改良
実行速度の改善
そのほかの改善
まとめ
#64 angrでシンボリック実行する
代表的なシンボリック実行ツール
angrでシンボリック実行する
シンボリック実行の難しさ
技術的な問題への対処
まとめ
#65 BadUSB:使用者を騙すUSBデバイス
実験
対策
まとめ
#66 Row Hammer:DRAMの脆弱性に対する攻撃手法
原理
コードの例
緩和策と発展形の攻撃
まとめ
#67 MeltdownとSpectre:CPUの脆弱性に対する攻撃手法
CPUの最適化技法
Meltdown
Spectre
影響を受けたCPUと対応
まとめ
7章 数値表現とデータ処理Hack
#68 整数表現の基礎知識
符号なし整数と2の補数による符号付き整数
レジスタと演算器のビット幅
エンディアン
まとめ
#69 さまざまな整数表現
任意精度数値型と多倍長表現
固定小数点数
可変長表現
まとめ
#70 浮動小数点数のビット列表現を理解する
浮動小数点数の基本(IEEE 754の基本)
浮動小数点数のビット列表現(2進)
浮動小数点数のビット列表現(10進)
まとめ
#71 浮動小数点例外
浮動小数点例外の種類
例外の状態フラグ
デフォルト以外の処理方法
まとめ
#72 浮動小数点数の丸め方を変える
5通りの丸め方
動的な指定
静的な指定
まとめ
#73 浮動小数点環境を触るコードに対するコンパイラの最適化と戦う
コンパイラの最適化によって意図通りに動かなくなる例
C標準のプラグマ
volatileの利用
インラインアセンブリの利用
まとめ
#74 NaNを深掘りする
signaling NaN
NaNのペイロードと伝播
RISC-Vの浮動小数点レジスタとNaN
まとめ
#75 浮動小数点数のアーキテクチャごとの差異に触れる
アンダーフローの判定のタイミング
FMAとinvalid operation例外
浮動小数点数から整数への変換
Armの代替動作(FEAT_AFP)
まとめ
#76 SIMD命令セットの基礎知識
x86/x86-64のSIMD命令
ARMのSIMD命令
コンパイラにSIMD命令を出力させる
サポートされる拡張命令セットを検出する
まとめ
#77 SIMD並列化したコードを書く
並列化コードを書く前に
コンパイラの自動並列化を利用する
OpenMP SIMDプラグマを使う
コンパイラのintrinsic関数を使う
SIMDラッパライブラリを使う
アセンブリを手書きする
JITライブラリを使う
まとめ
#78 SIMD命令を使ったさまざまなテクニック
SIMD命令を使ってstrlen関数を高速化する
SIMD命令を使ってVByteの展開を高速化する
まとめ
8章 言語処理系Hack
#79 NaNを活用して64ビット値にタグ付きの値を格納する
動的型付き言語での値の表現
NaN boxingの例
採用例
まとめ
#80 ucontext.hでコルーチンを実装する
ucontext.h
コルーチンを実装する
ucontext.hの問題点
スタックを持たないコルーチン
まとめ
#81 Profile Guided Optimization
PGOを使う一般的な手順
PGOを使う具体例
参考文献
まとめ
#82 LD_PRELOADを使ってメモリアロケータを入れ替える
さまざまなメモリアロケータ
LD_PRELOADを使ったメモリアロケータの入れ替え
メモリアロケータの自作
まとめ
#83 ABIと呼び出し規約を理解する
ABIがそろっていない場合に起こる現象の例
C言語のABI
C言語以外のABI
まとめ
#84 libffiで実行時までシグネチャがわからない関数を呼び出す
PythonのFFIを使ってみる
dlopen/dlsymを使った共有ライブラリのロード
アセンブリ言語による呼び出し規約の実装
libffiを使う
C++/Rustでライブラリを提供する
まとめ
#85 実行時に機械語を生成する
例:関数を部分適用する
メモリの実行許可
実行時生成された関数をperfで見えるようにする
発展
まとめ
#86 GCC/Clangの組み込み関数を利用する
ビット操作
コードが実行されないことをコンパイラに伝える
標準化された組み込み関数やマクロ
まとめ
組み込み関数のリファレンス
9章 そのほかのHack
#87 用語集
#88 Binary Hacksに必要なツール
コンパイラ・デバッガ
バイナリファイル関連のツール
OS関連のコマンド
そのほかのコマンド
#89 文献案内
書籍
インターネット