WindowsでASLR(Address Space Layout Randomization)を確認してみる。
ASLR(Address Space Layout Randomization)とは、OSがプロセスをロードするときに、ランダムな場所にモジュールを配置するセキュリティ機能です。実際はモジュールだけじゃなく、スタックやヒープなどもランダマイズされたりします。
ASLRはWindowsにも当然実装されており、それらを迂回して脆弱性を利用する攻撃手法が日々研究されています(参考:DEP/ASLR bypass without ROP/JIT)。日本語で解説されてる資料もありますね(→http://www.slideshare.net/SatoshiMimura/apasec-2013-ropjit-depaslr)。
Windows(Vista以降)のばあい、PEヘッダの DllCharacteristics にて0x0040(IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)フラグがオンになっているモジュールがASLR対象になります(参考:MSDN)。
typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; (省略) DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; ■ココ DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
たとえばデバッガで実行ファイルをロードした際、IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASEがオフなら、0x00401000以降にEXEモジュールがあるのですが、これがオンだと毎回ランダムなアドレスになります。Visual C++ 2010 Express版では、メニューからプロジェクト⇒プロパティ⇒リンカ⇒詳細設定にてオンオフを設定できます。
「たのしいバイナリの歩き方」でも1~2章辺りで、ではメモリアドレス00401000へ進んでください、みたいなくだりがありますが、これはASLRがオフになってる前提だったりします。もしASLRがオンだとまったく別の場所にモジュールがロードされているので、探さなければなりません(なので1~2章のサンプルプログラムはEXEに限りすべてASLRオフになっています)。
ASLRはモジュール単位で行われるため、同じプロセス内でもランダマイズされるモジュールとされないモジュールが存在します。そしてROP(Return Oriented Programming)はランダマイズされないモジュール内に存在するガジェットを利用して行われるわけです。