Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Windowsで関数フック
Search
ryoha
December 10, 2020
0
66
Windowsで関数フック
Windowsでフック用のライブラリを言語移植してる際に学んだこと。
ryoha
December 10, 2020
Tweet
Share
More Decks by ryoha
See All by ryoha
自由を求めてWindowsオーディオプログラミング
ryoha
0
420
Featured
See All Featured
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Side Projects
sachag
452
42k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
29
2k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Visualization
eitanlees
146
15k
BBQ
matthewcrist
85
9.4k
GitHub's CSS Performance
jonrohan
1031
460k
The World Runs on Bad Software
bkeepers
PRO
66
11k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.6k
Transcript
Windowsで関数フック @ryoha
自己紹介 • 電気電子系学部二年 • 趣味 ◦ ビジュアルノベルゲーム ◦ プログラミング ▪
Web フロント ▪ デスクトップアプリ ▪ たまにWeb サーバー • 好きなプログラミング言語はTypeScript • 好きなOSはWindows • 最近はminhookというCのライブラリのRust移植をしようとしてる ◦ 今日の話はこれ
関数フックって? • > プログラム中の特定の箇所に、利用者が独自の処理を追加できるように する仕組み (Wikipedia フックのページより) • ユーザーが非公式のパッチを作るときに使ったりする ◦
英語のツールを日本語化したり ◦ 利用規約は読もう どうやってやるんだろう?っていうのが今日の話
基本に立ち返って 1. ノイマン型コンピュータでは記憶領域(メモリ)に命令を読み込み位置か ら逐次実行 2. メモリに乗ってる命令は機械語(これはアセンブリと一対一対応) 3. そのメモリ部分を書き換えたらいいじゃん!
もう少し細かい実装方針 • じゃあ割り込ませたい処理(機械語)をその部分に挿入して今までのは 後ろにずらしたらいいやろw ◦ 当然これじゃダメ ◦ 割り当てられてない部分のメモリを書き換えると関係ない処理に影響が出るか も •
だからフックしたい処理の冒頭を割り込ませたい処理へのJMP命令に 書き換えればいい • そして割り込ませたい処理が終わったら元の状態に戻して、削った冒 頭部分を実行した後フックしたい処理にもどればいい
立ちはばかるアドレス指定の話 • x86モードでは指定できるメモリアドレスはアドレス空間全体をカバーしてる • 厄介なのがx64モードでRIP相対アドレッシングで指定できるアドレスは、ア ドレス空間全体に対して狭い範囲に限られる ◦ -2GB ~ +2GB
しか指定できない つまりx64モードだと削った冒頭部分でRIP相対アドレッシングでアドレス指定し てたら元の冒頭部分が実行できないため近くに配置する必要がある。
リレー関数・トランポリン関数 • 割り込ませたい処理が長いとそれだけフック部分の近くに割り当てるのが 難しい • ライブラリとして提供することを考えたとき ◦ わざわざフック部分の近くに割り当ててもらうのは使い勝手が悪い ◦ フック冒頭の部分を処理に組み込んでもらうのは使い勝手が悪い
みたいな理由でリレー関数とトランポリン関数を導入します リレー関数は割り込ませたい処理にジャンプさせ、トランポリン関数はフックした い処理の冒頭部分を代行してその続きに戻らせます
1. 冒頭を削ってリレー関数にジャンプ 2. 割り込ませたい処理にジャンプ 3. おわったらもどる 4. 削った冒頭部分の処理をして削った部分の先に戻る
メインで使う具体的なWin32api • VirtualAlloc ◦ メモリ位置を指定してその近くにメモリ割り当てをしてもらう • VirtualProtect ◦ メモリのアクセス保護を変更する関数 •
FlushInstructionCache ◦ メモリを書き換えてもキャッシュに残ってたら意味がないからキャッシュを更新する
参考にしたサイト • IA-32 インテル® アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル 中巻 A:命令セット・リファレンス A-M ◦ 日本語 ◦
神 ◦ https://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_Dev_ Man_Vol2A_i.pdf • 移植元のCのライブラリ ◦ ドキュメント MinHook - The Minimalistic x86/x64 API Hooking Library - CodeProject ◦ 今日話した概念的なのは大体ここに乗ってる ◦ Cになれてないのもあってコード小さいのに読むのに丸一日かかった