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版では、メニューからプロジェクト⇒プロパティ⇒リンカ⇒詳細設定にてオンオフを設定できます。

f:id:b07c00:20130801235810p:plain

 「たのしいバイナリの歩き方」でも1~2章辺りで、ではメモリアドレス00401000へ進んでください、みたいなくだりがありますが、これはASLRがオフになってる前提だったりします。もしASLRがオンだとまったく別の場所にモジュールがロードされているので、探さなければなりません(なので1~2章のサンプルプログラムはEXEに限りすべてASLRオフになっています)。

 ASLRはモジュール単位で行われるため、同じプロセス内でもランダマイズされるモジュールとされないモジュールが存在します。そしてROP(Return Oriented Programming)はランダマイズされないモジュール内に存在するガジェットを利用して行われるわけです。