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
62
Windowsで関数フック
Windowsでフック用のライブラリを言語移植してる際に学んだこと。
ryoha
December 10, 2020
Tweet
Share
More Decks by ryoha
See All by ryoha
自由を求めてWindowsオーディオプログラミング
ryoha
0
320
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
216
8.6k
How To Stay Up To Date on Web Technology
chriscoyier
781
250k
Writing Fast Ruby
sferik
619
60k
Automating Front-end Workflow
addyosmani
1354
200k
Creatively Recalculating Your Daily Design Routine
revolveconf
209
11k
Code Review Best Practice
trishagee
54
15k
Build The Right Thing And Hit Your Dates
maggiecrowley
23
2k
VelocityConf: Rendering Performance Case Studies
addyosmani
319
23k
StorybookのUI Testing Handbookを読んだ
zakiyama
10
4.6k
Building Better People: How to give real-time feedback that sticks.
wjessup
353
18k
The Language of Interfaces
destraynor
151
23k
Side Projects
sachag
451
41k
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になれてないのもあってコード小さいのに読むのに丸一日かかった