Japanese

Exploring the x64
村上 純一
執行役員 先端技術研究部長
(株)フォティーンフォティ技術研究所
自己紹介
• 村上 純一
–
–
–
–
(株)フォティーンフォティ技術研究所
カーネルモードでのWindows、Linuxにおける開発
セキュリティ脆弱性分析、マルウェア解析、P2P解析等
講演活動
• Black Hat 2008 US and Japan, AVAR 2009,
RSA Conference(2009-)
– セキュリティ&プログラミングキャンプ講師(2006-)
2
はじめに & 目標
• IA64
• Linux, *BSD, Mac, etc.
 x86で利用される様々なテクニックがx64ではどの
ようになっているかを明確にする
難易度
3
環境
•
•
•
•
Windows 7 x64 Edition
Visual Studio 2008
Windbg
IDA Pro Advanced
– Standard Editionは、x64未対応
4
アジェンダ
•
•
•
•
Windows x64
ABI(Application Binary Interface)
API Hooking
Code Injection
5
Windows x64
• Native x64 およびWoW64
• 仮想メモリ空間
– 2^64 = 16 Exa Byte ( Exa: 10^18)
– 実際には、最大16TBに制限されている
• ファイル・レジストリリフレクション
• 64-bit用の追加API
– IsWow64Process, GetNativeSystemInfo, etc.
6
x86 – プロセスメモリ空間
0x0
0x0
ユーザー空間
0x00400000
実行モジュール
0x7fffffff
(2GB)
カーネル
MSVCR90.dll
kernel32.dll
0xffffffff
(4GB)
0x7fffffff
ntdll.dll
7
x64 – プロセスメモリ空間
0x0
2GB
ユーザー空間
0x7ff`ffffffff
(8TB)
カーネル
0xfff`ffffffff
(16TB)
・
・
・
x 4096(0x7ff`ffffffff
/ 0x7fffffff )
・
・
・
・
2GB
・
・
・
x 4096
・
・
・
・
8
x64 – プロセスメモリ空間
0x0
0x0
ユーザー空間
MSVCR90.dll
kernel32.dll
ntdll.dll
0x7fffffff
0x1`40000000
0x7ff`ffffffff
(8TB)
実行モジュール
/DYNAMICBASE:NO
カーネル
0xfff`ffffffff
(16TB)
0x7fff`fffffff
KERNELBASE.dll
9
WoW64 – プロセスメモリ空間
0x0
0x0
x 4096
ユーザープロセス
0x7ff`ffffffff
(8TB)
0x00400000
C:¥Windows¥System32¥ntdll.dll
実行モジュール
wow64cpu
wow64win
wow64
C:¥Windows¥SysWOW64¥ntdll.dll
カーネル
kernel32.dll
kernelbase.dll
ntdll.dll
ntdll32.dll
0xfff`ffffffff
(16TB)
0x7fffffff
10
ABI
•
•
•
•
•
バイナリ形式
レジスタ
呼び出し規約
例外処理
システムコール(x64, WoW64)
11
バイナリ形式 = PE32+
• 基本的な構造は、概ねPE32と同様
• IMAGE_NT_HEADERS.FileHeader.Machine
– 0x014c => x86
– 0x8664 => x64
12
バイナリ形式
• 次のフィールドサイズが64-bitsに拡張されている
– IMAGE_NT_HEADERS.IMAGE_OPTIONAL_HEADER
• ImageBase
• SizeOfStackReserve
• SizeOfStackCommit
• SizeOfHeapReserve
• SizeOfHeapCommit
13
レジスタ
x86(32-bits)
x64(64-bits)
EAX
RAX
R8
ECX
RCX
R9
EDX
RDX
R10
EBX
RBX
R11
ESI
RSI
R12
EDI
RDI
R13
ESP
RSP
R14
EBP
RBP
R15
EIP
RIP
14
呼び出し規約
• 始めの4つの引数は、RCX, RDX, R8, R9レジスタを利用して渡
される(5つ目以降は、スタック経由)
• 呼び出し側がスタック上にレジスタ・ホーム・スペースを確保
• 返り値は、x86同様RAXレジスタ経由で返却される
• リーフ関数・非リーフ関数
– リーフ関数:スタックを一切利用しない関数
– PE32+は、非リーフ関数の情報を例外ディレクトリに保存している
• レジスタの揮発性
– 揮発レジスタ:RAX, RCX, RDX, R8-R11
– 不揮発レジスタを関数内で変更する場合は、スタックを利用して保
存・復元を行う必要がある
15
呼び出し規約
Low
rsp
rsp
rsp
int foo(int a, int b, int c, int d, int e)
{
int x = 0;
x
retaddr
rcx (home)
rdx (home)
mov
[rsp+20h],5
movx =dword
ptr [rsp+20h],r9d
a + b + c + d + e * 2;
mov
r9d,4
movreturn
dword
x; ptr [rsp+18h],r8d
} mov
r8d,3 ptr [rsp+10h],edx
mov dword
mov
edx,2 ptr [rsp+8h],ecx
mov dword
int main(void)
sub rsp,30h
sub ecx,1
rsp,8h
{ mov
rc;
callintfoo
r8 (home)
rc = foo(1, 2, 3, 4, 5);
printf("%d¥n", rc);
r9 (home)
5th parameter
rsp
rc
return rc;
}
High
16
例外処理
• テーブルベースでの処理
– x86で利用されていたリンクリストでの管理は廃止
参考) x86での例外処理
17
例外ディレクトリ及びRUNTIME_FUNCTION構造体
PE32+
Data Directory
DOS Header
Export Table
DOS stub
Import Table
NT FileHeader
Resource Table
NT Optional Header
Exception Table
Section Header
・
・
・
Section A
Section B
Section C
Import Address Table
・
・
・
struct _RUNTIME_FUNCTION {
ULONG BeginAddress;
ULONG EndAddress;
ULONG UnwindData;
}
RUNTIME_FUNCTION_ENTRY
RUNTIME_FUNCTION_ENTRY
RUNTIME_FUNCTION_ENTRY
・
・
・
18
dumpbin /unwindinfo
Begin
End
Info
Function Name
00000000 00001000 00001041 000022D4
Unwind version: 1
Unwind flags: None
Size of prologue: 0x16
Count of codes: 1
Unwind codes:
16: ALLOC_SMALL, size=0x18
foo
0000000C 00001050 00001095 000022DC
Unwind version: 1
Unwind flags: None
Size of prologue: 0x04
Count of codes: 1
Unwind codes:
04: ALLOC_SMALL, size=0x48
main
19
RUNTIME_FUNCTION.UnwindData
typedef struct _UNWIND_INFO {
UBYTE Version
: 3;
#define UNW_FLAG_NHANDLER 0x0
UBYTE Flags
: 5;
#define UNW_FLAG_EHANDLER 0x1
UBYTE SizeOfProlog;
#define UNW_FLAG_UHANDLER 0x2
UBYTE CountOfCodes;
#define UNW_FLAG_CHAININFO 0x4
UBYTE FrameRegister : 4;
UBYTE FrameOffset
: 4;
UNWIND_CODE UnwindCode[1];
union {
// If (Flags & UNW_FLAG_EHANDLER)
OPTIONAL ULONG ExceptionHandler;
// Else if (Flags & UNW_FLAG_CHAININFO)
OPTIONAL ULONG FunctionEntry;
};
// If (Flags & UNW_FLAG_EHANDLER)
OPTIONAL ULONG ExceptionData[];
} UNWIND_INFO, *PUNWIND_INFO;
cf. http://www.osronline.com/article.cfm?article=469
20
ExceptionData
typedef struct _SCOPE_TABLE {
ULONG Count;
struct
{
ULONG BeginAddress;
ULONG EndAddress;
ULONG HandlerAddress;
ULONG JumpTarget;
} ScopeRecord[1];
} SCOPE_TABLE, *PSCOPE_TABLE;
cf. http://www.osronline.com/article.cfm?article=469
21
try/except
int main(void)
{
int x = 0;
__try {
printf("%d¥n", 100/x);
printf("foo¥n");
printf("bar¥n");
printf("baz¥n");
} __except(EXCEPTION_EXECUTE_HANDLER) {
printf("catch!¥n");
}
return 0;
}
22
try/except
Name main
Unwind version: 1
Unwind flags: EHANDLER
Size of prologue: 0x04
Count of codes: 1
Unwind codes
04: ALLOC_SMALL, size=0x28
Handler:0000165C __C_specific_handler
Count of scope table entries: 1
Begin 00001004
End
00001046
Handler 00000001
Target 00001046
140001000
140001004
140001009
14000100A
14000100C
14000100E
140001010
140001017
14000101D
140001024
14000102A
140001031
140001037
14000103E
140001044
sub
mov
cdq
xor
idiv
mov
lea
call
lea
call
lea
call
lea
call
jmp
rsp,28h
eax,64h
140001046
14000104D
140001053
140001054
140001056
14000105A
lea
call
nop
xor
add
ret
rcx,[400021D0h]
qword ptr [40002130h]
ecx,ecx
eax,ecx
edx,eax
rcx,[400021B0h]
qword ptr [40002130h]
rcx,[400021B4h]
qword ptr [40002130h]
rcx,[400021BCh]
qword ptr [40002130h]
rcx,[400021C4h]
qword ptr [40002130h]
0000000140001054
eax,eax
rsp,28h
23
例外ディレクトリの効用
• 実行ファイル内の非リーフ関数を列挙可能
• 非リーフ関数それぞれについて:
– 例外処理の情報を取得可能
– スタック及び不揮発レジスタの用途を把握可能
24
システムコール x86
int 0x2e or sysenter
・
・
・
MSR[176h]
IDTR
KiSystemService
IDT
other
interrupt
handlers
SDT
(ntoskrnl.exe)
SSDT
・
・
・
SDT Shadow
(win32k.sys)
Nt* APIs
Nt* APIs
(User/GDI)
SSDT
25
システムコール x64
実行モジュール
CreateFileW
kernel32.dll
CreateFileWImplementation
(CreateFileW)
kernelbase.dll
CreateFileW
ntdll.dll
mov
r10,rcx
mov
eax,52h
syscall
ret
nop
dword ptr [rax+rax]
NtCreateFile
26
システムコール WoW64
実行モジュール
CreateFileW
kernel32.dll
CreateFileWImplementation
(CreateFileW)
kernelbase.dll
CreateFileW
ntdll32.dll
NtCreateFile
mov
xor
lea
call
add
ret
eax,52h
ecx,ecx
edx,[esp+4]
dword ptr fs:[0C0h]
esp,4
2Ch
27
fs:[0C0h]
• FSレジスタは、TEB(Thread Environment Block) のアドレスを保持
0:000:x86> dt _TEB
dbgbreak!_TEB
+0x000 NtTib
: _NT_TIB
(snip)
+0x02c ThreadLocalStoragePointer
: Ptr32 Void
0:000:x86>
dd fs:[0C0h]
+0x030 ProcessEnvironmentBlock
: Ptr32
_PEB 00000000
0053:000000c0
738c2320 00000411
00000000
+0x034 LastErrorValue
: Uint4B
↑
+0x038 CountOfOwnedCriticalSections : Uint4B
X86SwitchTo64BitMode
+0x03c CsrClientThread : Ptr32 Void
+0x040 Win32ThreadInfo : Ptr32 Void
+0x044 User32Reserved
: [26] Uint4B
+0x0ac UserReserved
: [5] Uint4B
+0x0c0 WOW32Reserved
: Ptr32 Void
28
Systemcall WoW64
call fs:[0C0h]
jmp
0033:CpupReturnFromSimulatedCode
wow64cpu.dll
X86SwitchTo64BitMode
CpupReturnFromSimulatedCode
TurboDispatchJumpAddressEnd
wow64.dll
Wow64SystemServiceEx
29
GDT (超約)
仮想メモリ空間
0x0
seg. A
• 仮想メモリ空間をセグメントとして管理
• カーネルコード、カーネルデータ
• ユーザコード、ユーザデータ等
GDT
seg. B
seg. C
ID
seg.
base
limit
type
0x00
A
0x0
0x3f
RW
0x08
B
0x40
0x7f
RE
0x10
C
0x0
0xff
RE
セグメントセレクタ
0xff
30
Windows 7(x64)でのGDTダンプ結果
kd> dg 0x00 0x60
P Si Gr Pr Lo
Sel
Base
Limit
Type
l ze an es ng
---- ----------------- ----------------- ---------- - -- -- -- -0000
00000000`00000000
00000000`00000000
<Reserved>
0 NbUser
By NpDS
Nl
Kernel
CS(x64), Kernel
DS
User
CS(x86),
0008 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl
0010 00000000`00000000 00000000`00000000 Code RE Ac 0 Nb By P Lo
0018 00000000`00000000 00000000`ffffffff Data RW Ac 0 Bg Pg P Nl
0020 00000000`00000000 00000000`ffffffff Code RE
3 Bg Pg P Nl
0028 00000000`00000000 00000000`ffffffff Data RW Ac 3 Bg Pg P Nl
0030 00000000`00000000 00000000`00000000 Code RE Ac 3 Nb By P Lo
0038 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl
0040 00000000`00b9b080 00000000`00000067
TSS32
Busy 0 Nb By P Nl
User
CS(x64)
0048 00000000`0000ffff 00000000`0000f800 <Reserved> 0 Nb By Np Nl
0050 ffffffff`fffe0000 00000000`00003c00 Data RW Ac 3 Bg By P Nl
0058 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl
0060 00000000`00000000 00000000`ffffffff Code RE
0 Bg Pg P Nl
Flags
-------00000000
00000000
0000029b
00000c93
00000cfa
00000cf3
000002fb
00000000
0000008b
00000000
000004f3
00000000
00000c9a
31
GDT[0x30]の内容
•
•
•
•
•
ベース: 0x000`00000000
リミット: 0x000`00000000
タイプ: CODE, Read, Execute and Accessed
特権レベル: 3(ユーザーモード)
L (64-bitコードセグメント) flag: 1
32
システムコール WoW64
wow64.dll
Wow64SystemServiceEx
whNtCreateFile
mov
r10,rcx
mov
eax,52h
syscall
ret
ntdll.dll
NtCreateFile
33
システムコール WoW64 (return to x86)
ntdll.dll
NtCreateFile
0:000> dd r14
00000000`0008ec70 77330056 00000023 0008ed30 00000000
wow64.dll
whNtCreateFile
↑
↑
offset
User Code(x86)
Wow64SystemServiceEx
wow64cpu.dll
TurboDispatchJumpAddressEnd
CpuSimulate
mov
mov
mov
mov
mov
mov
jmp
dword ptr
r8d,2Bh
ss,r8w
esp,dword
r9d,dword
dword ptr
fword ptr
[r14+4],23h
ptr [r13+0C8h]
ptr [r13+0BCh]
[r14],r9d
[r14]
34
デモ: WoW64からのx64 APIの直接呼出し
• x86からx64への遷移
– jmp 0033:XXXXXXXX
• API呼び出し
– rax: システムコール番号
– rdx: 引数リストのアドレス
– syscall
• x64からx86への遷移
– call 0023:XXXXXXXX
35
API Hooking
• IAT Hooking
– x86と同様の手法で実現可能
• Code Hooking
36
Code Hooking
• 基本的な方法は、x86と同じ
• ただし実装の詳細に若干の差異有り
mov
push
mov
ret
push
nop
sub
nop
…
…
edi,edi
hookfunc
ebp,esp
ebp
esp,0xc
対象API
…
…
…
jmp trampoline
フック関数
mov
push
mov
sub
jmp
edi,edi
ebp
ebp,esp
esp,8h
XXXXXXXX
トランポリンコード
37
REXプレフィックス
• 0x40~0x4E
– x86: INC 、DEC 命令
– x64: REX プレフィックス(レジスタ拡張)
• 例) 0x48,0xB8,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88
x86:
48
B8 11 22 33 44
55
66 77 88
dec
mov
push
ja
eax
eax,44332211h
ebp
00004E9F
x64:
48 B8 11 22 33 44 55 66 77 88 mov
rax,8877665544332211h
38
Code Hooking
フック関数
00000000779811E4
00000000779811EE
00000000779811EF
00000000779811F2
mov
push
ret
…
rax,7FFFFFA0028h
rax
000007FFFFFA0034
000007FFFFFA0038
000007FFFFFA003B
000007FFFFFA0042
000007FFFFFA0043
000007FFFFFA004D
000007FFFFFA0051
sub
xor
cmp
push
mov
xchg
ret
書換えた元のコード
rsp,38h
r11d,r11d
dword ptr [7FFFFFC0F8Ch],r11d
rax
rax,779811F2h
rax,qword ptr [rsp]
フックした関数への復帰先
39
Code Injection
•
•
•
•
WoW64 からWoW64ヘのインジェクション
x64からx64へのインジェクション
WoW64 から x64へのインジェクション
x64 からWoW64ヘのインジェクション
(Fail CreateRemoteThead API)
x64環境は、x86マルウェアへの魔除けになるか?
40
まとめ
•
•
•
•
Windows x64
ABI(Application Binary Interface)
API Hooking
Code Injection
41
Special thanks
• Toshiaki Ishiyama@FFR
• Satoshi Tanda@FFR
42