はじめに
ふとしたときになにかしらのプロセスのメモリを読みたくなることってあると思います。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
を使ったお手軽なやり方ではだめだったというだけなので「どうしてもメモリが読みたい!」という人は他の手段をとればいくらかやりようはあると思います。くれぐれも悪いことはしないようにされないように気を付けていきたいものですね。
参考ページ