第 6 章 新しい Windows への適応性に関する検討 67
6.3 x64 版 Windows の特徴
するケースは,既存のシステムコールやデータ構造に変更がある場合と,新しいもの が追加された場合の2つである.前者においては,変更前の実装から流用できる部分 が多いと考えられるため,少ない実装量で抑えられる.また,Alkanet のデータ構造 解釈機能の一部はシンボル情報を基に生成しているため,データ構造のバージョン間 の差が軽微であれば,この部分で吸収できる.後者については,基本的に新規に実装 する必要があるが,実際には既存の実装から流用できる部分が多く,実装量を軽減で きると考えられる.これは,Alkanetの対象とする挙動の範囲であれば,既に対応済 みのデータ構造を使うことが多いと考えられるためである.
また,x64版Windowsは,32ビットアプリケーションを動作させるために,WOW64 と呼ばれるエミュレーションレイヤを持つ.WOW64上で動作するアプリケーション から発行されるシステムコールは,通常のシステムコールとは発行に至るまでの処理 の流れが異なる場合がある.WOW64上で動作するマルウェアを観測可能とするため
には,WOW64上から発行されるシステムコールもトレース可能とする必要がある.
したがって,WOW64レイヤの実装を Windows のバージョンごとに確認し,それに あわせて(1),(2),(4)を拡張する必要がある.以下,本論文では,WOW64上で動作 するアプリケーションから発行されるシステムコールをWOW64システムコールと呼 称する.
6.3 x64 版 Windows の特徴
Alkanetは,これまでx86版 Windows XP Service Pack 3を対象としてきたが,現 在ではx64版のWindowsが主流となっている.x86版Windowsとは呼出規約やシス テムコール呼出しの流れ,PCRのマップ位置などが異なっている.6.2節で述べたよ うに,システムコールトレースを実現する上ではアーキテクチャの変更による影響が 大きい.本節では,x64版Windowsが持つ機能のうち,Alkanetを実現する上で特に 課題となりうる機能について述べる.
6.3.1 システムコール呼出しの流れ
x86版Windowsとx64版Windowsとでは,システムコールの呼出しの流れが異な る.図6.1に両者におけるシステムコールの処理の流れを示す.x86版Windowsでは,
4.3.1項でも示した通り,各システムコール個別のスタブ内部でKiFastSystemCallが
図 6.1 x86版Windowsとx64版Windowsのシステムコール呼出しの流れ
呼ばれ,sysenter命令が実行されていた.対象のシステムコール実行後は,sysexit命
令により,KiFastSystemCallRet を経由してスタブへと戻る.一方,x64版Windows では,各システムコールのスタブが直接syscall命令を用いてシステムコールを発行す る.システムコールのエントリポイントはKiSystemCall64であり,このアドレスは IA32 LSTAR MSRによって示される.システムコール実行後は,KiSystemServiceExit
より,sysret命令を用いて直接スタブへと戻る.
なお,システムコールの番号は,x86,x64とも32ビットの値であり,システムコー ルのスタブでEAXレジスタに設定される.
6.3.2 PCR のマップ位置
x86版Windowsにおいて,PCR は,Windows のカーネルモードにおいて各プロ
セッサのFS レジスタが指すセグメントの先頭に存在する.一方,x64版 Windowsに おけるPCRは,カーネルGSセグメントの先頭に存在する.x64アーキテクチャおけ るGSセグメントのベースアドレスはIA32 GS BASE MSRによって示される.また,
IA32 KERNEL GS BASEという退避用のMSRも存在し,これら2つのMSRでカー
6.3. x64版Windowsの特徴 71
図 6.2 swapgs命令によるGSベースアドレスの交換 [59]
ネルモードとユーザモード両方のGSセグメントのベースアドレスを保持している.
これらの MSRの値を交換するswapgs命令も用意されており,図6.2のようにユーザ モードとカーネルモードの処理を切り替える際に実行することで,両者のGSセグメ ントの切り替えを行うことができる.
6.3.3 システムコールの引数と戻り値
呼出規約は,関数呼び出し時のデータの受け渡しなどに関する規約である.x86版
Windowsでは,関数の引数を全てスタックに格納するstdcall呼出規約を用いていた.
一方,x64環境では,x64呼出規約[62]と呼ばれる新たな呼出規約を用いている.x64 呼出し規約では,第1引数から第4引数は,揮発性のRCX,RDX,R8,R9レジスタ に格納される.第5引数以降が格納されるスタックには,Home領域と呼ばれる第1引 数から第4引数までの領域も確保される.また,関数の戻り値はRAXレジスタに格 納される.
ただし,システムコールにおいては,syscall命令がRCXに戻りアドレスを保存する ため,RCXに与えられた第1引数は,システムコールのスタブ内で R10 レジスタに 退避される.syscall命令およびsysret命令はRSPレジスタを変更しないため,システ ムコールの出入り口におけるRSPレジスタはユーザモードのスタックを示している.
6.3.4 WOW64
x64版Windowsでは,32ビットアプリケーションを動作させるために,WOW64と
呼ばれるエミュレーションレイヤを持つ.WOW64上で動作するアプリケーションか ら発行されるシステムコールは,通常のシステムコールと処理の流れが異なる場合が ある.Windows 10 x64と Windows 7 x64 の実装を確認したところ,WOW64システ ムコールにおいて,システムコール番号や処理に差異が確認できた.以下,本論文で
図 6.3 x64版Windowsにおけるシステムコールの引数
は,WOW64内の ntdll.dllを,通常の64ビットアプリケーションが利用するntdll.dll と区別するため,シンボル情報で示されている wntdll.dllと呼称する.また,通常の 64ビットアプリケーションの動作環境を WOW64 と区別し,Win64 と呼称する.
WOW64は,x64版Windows において32ビットアプリケーションを動作可能にす
る.32ビットアプリケーションを動作させるプロセス(以下,WOW64プロセス)は,
はじめに wow64.dll,wow64cpu.dll,wow64win.dll,wntdll.dllなどのDLLをロードす
る.WOW64プロセスがシステムコールを発行するとき,上記のDLLがCPUの動作
モードをx86モードからx64モードへ切り替え,システムコールをエミュレーション する関数を実行する.Windows 7 x64では,wntdll.dll内のスタブが ECXレジスタに セットした値を基にエミュレーション用関数が決定されていた.一方,Windows 10 x64では,システムコール番号の32ビットのうち,使用されていなかった上位16ビッ トの値が利用される.
エミュレーション用の関数は多数存在するが,WOW64レイヤからシステムコール の発行に至るまでの流れは,図6.4に示すように,Win64側のスタブを経由するケー ス(1) と経由しないケース(2) の2通りに大別される.図6.4では,Windows 10 x64 おける上記の2つのケースの例を示す.
ケース(1)の場合,エミュレーション用の関数内でシステムコール番号に対応した
Win64側のスタブが呼び出され,64ビットアプリケーションと同様にシステムコールに
至る [63].図6.4のケース(1)に,NtCreateFileシステムコールの例を示す.WOW64 上にて当該システムコールが発行されると,最終的に ntdll.dll 内の NtCreateFile ス