はじめに
ふとしたときになにかしらのプロセスのメモリを読みたくなることってあると思います。Windowsの場合Win32APIで用意されているReadProcessMemoryを呼び出すことで動作中の別プロセスのメモリを読み取ることができます。これを使うことでいろいろできそう!と思ったのです。
プログラムの概要
処理の流れを簡単にまとめると、
-
CreateToolhelp32Snapshotを用いて実行中のプロセス一覧のスナップショットを取得 -
Process32FirstとProcess32Nextでスナップショットからプロセスを一つずつ取り出せるので目的の名前のプロセスを探す -
OpenProcessに目的のプロセスのProcessIDを渡してハンドラを取得 - 取得したハンドラを
ReadProcessMemoryに渡してメモリ読み放題
と、なるはずでした。
問題点その1
いざ実行してみたところOpenProcessでエラーを吐かれてしまいました。GetLastErrorを呼び出してエラーコードを見ると0x5のERROR_ACCESS_DENIEDとのこと。つまり権限がないということでした。調べるとデバッグ権限SeDebugPrivilegeが有効でないといけないとのことなのですが、通常のユーザはそもそもデバッグ権限を持っていないのでAdjustTokenPrivilegesを呼び出しても権限の変更はできません。当然実行プロセスにもデバッグ権限を持たせることはできません。
仕方がないのでadminユーザで実行することでユーザの権限問題を解決。
問題点その2
ユーザ権限問題が解決したことでとりあえずchrome.exeなどいくつかのプログラムは実行中プロセスのメモリを読み取ることができるようになりました。しかし、相変わらずいくつかのプロセスではOpenProcessでアクセス拒否されてしまいました。結論を述べてしまうと、外部プロセスからのアクセスを許可しない設定で立てられたプロセスにはアクセスできないということでした。例えばWindowsのシステムプロセスなどは常にアクセスを拒否されます。また、プロセスを立てる際にBuildExplicitAccessWithNameAを呼び出してACE:Access Control Entryを設定することで外部プロセスからのアクセスを拒否できるようになります。
最後に
思ったようにいかなくて残念な一方、アクセスの拒否設定ができなければいくらでも悪いことができてしまうことになるので考えてみれば当然の話でした。もっとも、Win32APIを使ったお手軽なやり方ではだめだったというだけなので「どうしてもメモリが読みたい!」という人は他の手段をとればいくらかやりようはあると思います。くれぐれも悪いことはしないようにされないように気を付けていきたいものですね。
参考ページ