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
67
Windowsで関数フック
Windowsでフック用のライブラリを言語移植してる際に学んだこと。
ryoha
December 10, 2020
Tweet
Share
More Decks by ryoha
See All by ryoha
自由を求めてWindowsオーディオプログラミング
ryoha
0
450
Featured
See All Featured
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
4
450
The Cult of Friendly URLs
andyhume
78
6.2k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.3k
Docker and Python
trallard
44
3.3k
How to train your dragon (web standard)
notwaldorf
91
5.9k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
46
2.4k
Writing Fast Ruby
sferik
628
61k
The World Runs on Bad Software
bkeepers
PRO
67
11k
Why Our Code Smells
bkeepers
PRO
336
57k
We Have a Design System, Now What?
morganepeng
51
7.4k
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になれてないのもあってコード小さいのに読むのに丸一日かかった