Win32とWin64でのカーネルモードへの移行

アプリケーション・プログラムがシステムコールをすると、(処理内容にもよりますが)OS内部ではCPUをカーネルモードに切り替えて処理を行います。デバッガを使って、この流れを見てみましょう。

(本記事の初稿は2004年です。64ビットCPUが普及した現在でも有用な内容と思われるので、そのままの内容で公開します。)

■ネイティブAPI

本題に入る前に、ネイティブAPIの説明をします。Win32アプリケーションプログラムはUSER32, KERNEL32, GDI32のDLLで公開されているAPIをコールすることでシステムを呼び出します。これらのDLLがシステム内部をコールしてくれるわけです。ただしKERNEL32は直接Windowsのカーネルを呼び出すことをしません。なぜなら、WindowsNT/2000/XPはWin32専用に作られているわけではないからです。Win32以外のサブシステム、POSIXサブシステム、OS/2サブシステム、INTERIXサブシステムなどの元ではWin32以外のアプリケーションプログラムも動作させることが可能です。(WindowsXPではPOSIXサブシステム、OS/2サブシステムが廃止されましたが。)

KERNEL32は(Win32専用ではない汎用的な)APIをコールし、このAPI内部でカーネルを呼び出しています。この汎用的なAPIをネイティブAPIと呼びます。このネイティブAPIを実装・公開しているのはNTDLLというDLLです。なおUSER32, GDI32は提供する機能がWin32に特化したものであるため、直接カーネル(NTOSKRNL.EXE, WIN32K.SYSなど)を呼び出します。

NTDLL.DLLの提供するネイティブAPIについて知らなくてもプログラミングする際に困ることはありませんが、概要がわかるとWindowsの内部動作をより深く理解でき、プログラミングするのが楽しくなります。

■プログラム

ネイティブAPI/カーネルモード移行箇所の調査に使うプログラムのソースコードです。(nativeapi.c menu.h menu.rc)Visual Studioを用いてビルドします。ビルド時の注意事項です。(1)DEBUGビルドすること。(2)コンソールアプリではなく、GUIアプリとしてビルド。(リンカの設定は/SUBSYSTEM:WINDOWS)(3)リンカでデバッグ情報の生成(/DEBUG, /PDB)を有効にしておくこと。(4)シンボル「_DEBUG」を定義しておくこと。

// ネイティブAPI/カーネルモード移行箇所の調査をするためのプログラム(Win32/Win64共用)
// (コンソールアプリではなく)GUIアプリとしてビルドすること。
// (RELEASEビルドではなく)DEBUGビルドし、デバッガ内から実行すること。
// 単独で実行するとデバッガが起動するか「不正な処理をしました」になる。

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include "menu.h"

LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);

TCHAR title[]=TEXT("ネイティブAPI/カーネルモード移行箇所の調査");
TCHAR szWinName[]=TEXT("NativeAPI");

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
                   LPSTR lpszArgs, int nWinMode)
{
HWND hwnd;
MSG  msg;
WNDCLASSEX wcl;

wcl.cbSize=sizeof(WNDCLASSEX);
wcl.hInstance=hThisInst;
wcl.lpszClassName=szWinName;
wcl.lpfnWndProc=WindowFunc;
wcl.style=0;

wcl.hIcon=LoadIcon(NULL, IDI_APPLICATION);
wcl.hIconSm=NULL;
wcl.hCursor=LoadCursor(NULL, IDC_ARROW);

wcl.lpszMenuName=TEXT("MyMenu");
wcl.cbClsExtra=0;
wcl.cbWndExtra=0;

wcl.hbrBackground=(HBRUSH) GetStockObject(WHITE_BRUSH);

if(!RegisterClassEx(&wcl)) return 0;

hwnd=CreateWindow(
 szWinName,
 title,
 WS_OVERLAPPEDWINDOW,
 CW_USEDEFAULT,
 CW_USEDEFAULT,
 CW_USEDEFAULT,
 CW_USEDEFAULT,
 NULL,
 NULL,
 hThisInst,
 NULL
);

ShowWindow(hwnd, nWinMode);
UpdateWindow(hwnd);

while(GetMessage(&msg, NULL, 0, 0))
{
 TranslateMessage(&msg);
 DispatchMessage(&msg);
} // END of while()

return (int)msg.wParam;

} // END of WinMain()


LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message,
                            WPARAM wParam, LPARAM lParam)
{
TCHAR messtr[256];
LPBYTE baseadr=0x0;
MEMORY_BASIC_INFORMATION mbi;
HDC hdc;


switch(message){

 case WM_COMMAND:
   switch(LOWORD(wParam)) {
     case IDM_KERNEL32:
       _tcscpy(messtr, TEXT("Click OK to break before VirtualQuery() function.(KERNEL32)"));
       MessageBox(hwnd, messtr, title, MB_ICONEXCLAMATION|MB_OK);
#ifdef _DEBUG
       DebugBreak();
#endif
       VirtualQuery(baseadr, &mbi, sizeof(mbi));
       _tcscpy(messtr, TEXT("VirtualQuery() was executed.(KERNEL32)"));
       MessageBox(hwnd, messtr, title, MB_ICONINFORMATION|MB_OK);
       break;
     case IDM_GDI32:
       _tcscpy(messtr, TEXT("Click OK to break before Ellipse() function.(GDI32)"));
       MessageBox(hwnd, messtr, title, MB_ICONEXCLAMATION|MB_OK);
       hdc=GetDC(hwnd);
       SelectObject(hdc, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
       SelectObject(hdc, (HPEN)GetStockObject(BLACK_PEN));
#ifdef _DEBUG
       DebugBreak();
#endif
       Ellipse(hdc, 10, 10, 60, 60);
       InvalidateRect(hwnd, NULL, 1);
       ReleaseDC(hwnd, hdc);
       _tcscpy(messtr, TEXT("Ellipse() was executed.(GDI32)"));
       MessageBox(hwnd, messtr, title, MB_ICONINFORMATION|MB_OK);
       break;
     case IDM_USER32:
       _tcscpy(messtr, TEXT("Click OK to break before GetDC() function.(USER32)"));
       MessageBox(hwnd, messtr, title, MB_ICONEXCLAMATION|MB_OK);
#ifdef _DEBUG
       DebugBreak();
#endif
       hdc=GetDC(hwnd);
       SelectObject(hdc, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
       SelectObject(hdc, (HPEN)GetStockObject(BLACK_PEN));
       Ellipse(hdc, 10, 10, 60, 60);
       InvalidateRect(hwnd, NULL, 1);
       ReleaseDC(hwnd, hdc);
       _tcscpy(messtr, TEXT("GetDC() was executed.(USER32)"));
       MessageBox(hwnd, messtr, title, MB_ICONINFORMATION|MB_OK);
       break;
     case IDM_EXIT:
       PostQuitMessage(0);
       break;
   } // END of switch()
   break;
 case WM_DESTROY:
   PostQuitMessage(0);
   break;
 default:
   return DefWindowProc(hwnd, message, wParam, lParam);
} // END of switch()
return 0;

} // END of WindowFunc()

#define   IDM_KERNEL32   101
#define   IDM_GDI32      102
#define   IDM_USER32     103
#define   IDM_EXIT       104

#include "menu.h"

MyMenu MENU
{
  POPUP "INT3(&I)"
  {
     MENUITEM "KERNEL32 function(&K)", IDM_KERNEL32
     MENUITEM "GDI32 function(&G)",    IDM_GDI32
     MENUITEM "USER32 function(&U)",   IDM_USER32
     MENUITEM SEPARATOR
     MENUITEM "Exit(&X)", IDM_EXIT
  }

}

ビルドしたら、そのEXEファイルをデバッガ(windbg)内から実行します。Visual Studioのデバッガではなくwindbgを使うのは、32-bitアプリだけでなく64-bitアプリについても調べるためです。(本稿執筆時のVisual Studio 2005 betaは64ビットプロセスのデバッグができない。(=64ビットプロセスにアタッチできない。))プルダウンメニュー「INT3」を開くと、「KERNEL32 function」「GDI32 function」「USER32 function」が並んでおり、例えば「KERNEL32 function」を選択すると、メッセージボックスが現れ「Click OK to break before VirtualQuery() function.(KERNEL32)」と表示されます。OKボタンを押すとデバッガに制御が移るので、そこからステップ実行することで、VirtualQuery()がどのような手順で実行されるのかを眺めることができるわけです。「GDI32 function」「USER32 function」についても同様です。

■Win32(ネイティブ)の場合

まずWin32(ネイティブ)について見てみましょう。以下、WindowsXP Professional SP2+Pentium4(Northwood)の環境で実行します。windbgの「File -> Open Executable…」でEXEファイルを開くとCommandウィンドウが開くので、「0:000>」プロンプトの所に「g」と入力してENTERキーを押します。するとnativeapi.exeのウィンドウが表示されるので、プルダウンメニューから「KERNEL32 function」「GDI32 function」「USER32 function」のいずれかを選択します。メッセージボックスが表示されたら、OKボタンを押します。デバッガに制御が移り「0:000>」プロンプトが表示されたのを確認したら、ステップ実行していきます。(F11キーもしくはF8キーを押すか、「0:000>」プロンプトの所に「t」と入力してENTERキーを押す。)最初はKERNEL32のfunctionです。

VirtualQuery()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.3.0017.0
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi\Debug\nativeapi.exe
Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00400000 0047d000   nativeapi.exe
ModLoad: 7c940000 7c9dd000   ntdll.dll
ModLoad: 7c800000 7c931000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 77cf0000 77d7f000   C:\WINDOWS\system32\USER32.dll
ModLoad: 77ed0000 77f16000   C:\WINDOWS\system32\GDI32.dll
(658.e64): Break instruction exception - code 80000003 (first chance)
eax=00251eb4 ebx=7ffda000 ecx=00000007 edx=00000080 esi=00251f48 edi=00251eb4
eip=7c941230 esp=0012fb20 ebp=0012fc94 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c941230 cc               int     3
0:000> g
ModLoad: 762e0000 762fd000   C:\WINDOWS\system32\IMM32.DLL

... 途中省略

ModLoad: 770d0000 7715c000   C:\WINDOWS\system32\oleaut32.dll
(658.e64): Break instruction exception - code 80000003 (first chance)
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c941230 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
7c941230 cc               int     3
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c941231 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint+0x1:
7c941231 c3               ret
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00424480 esp=0012fac0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
*** WARNING: Unable to verify checksum for nativeapi.exe
nativeapi!WindowFunc+0xd0:
00424480 3bf4             cmp     esi,esp
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00422bae esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!ILT+2985(__RTC_CheckEsp):
00422bae e9dd1d0000       jmp     nativeapi!_RTC_CheckEsp (00424990)
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00424990 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!_RTC_CheckEsp:
00424990 7501             jnz   nativeapi!_RTC_CheckEsp+0x3 (00424993) [br=0]
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00424992 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!_RTC_CheckEsp+0x2:
00424992 c3               ret
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00424487 esp=0012fac0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!WindowFunc+0xd7:
00424487 8bf4             mov     esi,esp
0:000> t
eax=0012fba0 ebx=00000000 ecx=00000000 edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c80b859 esp=0012fab0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!VirtualQuery:
7c80b859 8bff             mov     edi,edi
0:000> t
eax=0012fba0 ebx=00000000 ecx=00000000 edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c80b85b esp=0012fab0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!VirtualQuery+0x2:
7c80b85b 55               push    ebp

... 途中省略

0:000> t
eax=0012fba0 ebx=00000000 ecx=00000000 edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c80b869 esp=0012fa9c ebp=0012faac iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!VirtualQuery+0x10:
7c80b869 e8baffffff       call    kernel32!VirtualQueryEx (7c80b828)
0:000> t
eax=0012fba0 ebx=00000000 ecx=00000000 edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c80b828 esp=0012fa98 ebp=0012faac iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!VirtualQueryEx:
7c80b828 8bff             mov     edi,edi

... 途中省略

0:000> t
eax=0012faa8 ebx=00000000 ecx=00000000 edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c80b83f esp=0012fa7c ebp=0012fa94 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!VirtualQueryEx+0x17:
7c80b83f ff15bc12807c      call dword ptr [kernel32!_imp__NtQueryVirtualMemory (7c8012bc)]
                           {ntdll!ZwQueryVirtualMemory (7c94e213)}
                           ds:0023:7c8012bc=7c94e213
0:000> t
eax=0012faa8 ebx=00000000 ecx=00000000 edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c94e213 esp=0012fa78 ebp=0012fa94 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!ZwQueryVirtualMemory:
7c94e213 b8b2000000       mov     eax,0xb2
0:000> t
eax=000000b2 ebx=00000000 ecx=00000000 edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c94e218 esp=0012fa78 ebp=0012fa94 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!ZwQueryVirtualMemory+0x5:
7c94e218 ba0003fe7f       mov     edx,0x7ffe0300
0:000> t
eax=000000b2 ebx=00000000 ecx=00000000 edx=7ffe0300 esi=0012fac0 edi=0012fcd8
eip=7c94e21d esp=0012fa78 ebp=0012fa94 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!ZwQueryVirtualMemory+0xa:
7c94e21d ff12 call dword ptr [edx]{ntdll!KiFastSystemCall (7c94eb8b)}
              ds:0023:7ffe0300=7c94eb8b
0:000> t
eax=000000b2 ebx=00000000 ecx=00000000 edx=7ffe0300 esi=0012fac0 edi=0012fcd8
eip=7c94eb8b esp=0012fa74 ebp=0012fa94 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCall:
7c94eb8b 8bd4             mov     edx,esp
0:000> t
eax=000000b2 ebx=00000000 ecx=00000000 edx=0012fa74 esi=0012fac0 edi=0012fcd8
eip=7c94eb8d esp=0012fa74 ebp=0012fa94 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCall+0x2:
7c94eb8d 0f34             sysenter
0:000> t
eax=00000000 ebx=00000000 ecx=00000001 edx=ffffffff esi=0012fac0 edi=0012fcd8
eip=7c94e21f esp=0012fa78 ebp=0012fa94 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!ZwQueryVirtualMemory+0xc:
7c94e21f c21800           ret     0x18
0:000> t
eax=00000000 ebx=00000000 ecx=00000001 edx=ffffffff esi=0012fac0 edi=0012fcd8
eip=7c80b845 esp=0012fa94 ebp=0012fa94 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!VirtualQueryEx+0x1d:
7c80b845 85c0             test    eax,eax

KERNEL32のVirtualQuery()を呼ぶとVirtualQueryEx()が呼び出され、さらにNTDLLのZwQueryVirtualMemory()が呼び出されてから、NTDLLのKiFastSystemCall()内のsysenter命令を用いてカーネルモードに移行しているのがわかります。次はGDI32のfunctionです。

Ellipse()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.3.0017.0
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi\Debug\nativeapi.exe
Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00400000 0047d000   nativeapi.exe
ModLoad: 7c940000 7c9dd000   ntdll.dll
ModLoad: 7c800000 7c931000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 77cf0000 77d7f000   C:\WINDOWS\system32\USER32.dll
ModLoad: 77ed0000 77f16000   C:\WINDOWS\system32\GDI32.dll
(738.36c): Break instruction exception - code 80000003 (first chance)
eax=00251eb4 ebx=7ffda000 ecx=00000007 edx=00000080 esi=00251f48 edi=00251eb4
eip=7c941230 esp=0012fb20 ebp=0012fc94 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c941230 cc               int     3
0:000> g
ModLoad: 762e0000 762fd000   C:\WINDOWS\system32\IMM32.DLL

... 途中省略

ModLoad: 770d0000 7715c000   C:\WINDOWS\system32\oleaut32.dll
(738.36c): Break instruction exception - code 80000003 (first chance)
eax=01b00017 ebx=00000000 ecx=00550000 edx=7601068d esi=0012fac0 edi=0012fcd8
eip=7c941230 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
7c941230 cc               int     3
0:000> t
eax=01b00017 ebx=00000000 ecx=00550000 edx=7601068d esi=0012fac0 edi=0012fcd8
eip=7c941231 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint+0x1:
7c941231 c3               ret
0:000> t
eax=01b00017 ebx=00000000 ecx=00550000 edx=7601068d esi=0012fac0 edi=0012fcd8
eip=00424586 esp=0012fac0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
*** WARNING: Unable to verify checksum for nativeapi.exe
nativeapi!WindowFunc+0x1d6:
00424586 3bf4             cmp     esi,esp
0:000> t
eax=01b00017 ebx=00000000 ecx=00550000 edx=7601068d esi=0012fac0 edi=0012fcd8
eip=00422bae esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!ILT+2985(__RTC_CheckEsp):
00422bae e9dd1d0000       jmp     nativeapi!_RTC_CheckEsp (00424990)
0:000> t
eax=01b00017 ebx=00000000 ecx=00550000 edx=7601068d esi=0012fac0 edi=0012fcd8
eip=00424990 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!_RTC_CheckEsp:
00424990 7501             jnz   nativeapi!_RTC_CheckEsp+0x3 (00424993) [br=0]
0:000> t
eax=01b00017 ebx=00000000 ecx=00550000 edx=7601068d esi=0012fac0 edi=0012fcd8
eip=00424992 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!_RTC_CheckEsp+0x2:
00424992 c3               ret
0:000> t
eax=01b00017 ebx=00000000 ecx=00550000 edx=7601068d esi=0012fac0 edi=0012fcd8
eip=0042458d esp=0012fac0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!WindowFunc+0x1dd:
0042458d 8bf4             mov     esi,esp
0:000> t
eax=7601068d ebx=00000000 ecx=00550000 edx=7601068d esi=0012fac0 edi=0012fcd8
eip=77edc83b esp=0012faa8 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
GDI32!Ellipse:
77edc83b 8bff             mov     edi,edi

... 途中省略

0:000> t
eax=7ffdf000 ebx=7601068d ecx=00550000 edx=7601068d esi=00010000 edi=0012fcd8
eip=77edc8b6 esp=0012fa84 ebp=0012faa4 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
GDI32!Ellipse+0xa4:
77edc8b6 e80c000000       call    GDI32!NtGdiEllipse (77edc8c7)
0:000> t
eax=7ffdf000 ebx=7601068d ecx=00550000 edx=7601068d esi=00010000 edi=0012fcd8
eip=77edc8c7 esp=0012fa80 ebp=0012faa4 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
GDI32!NtGdiEllipse:
77edc8c7 b880100000       mov     eax,0x1080
0:000> t
eax=00001080 ebx=7601068d ecx=00550000 edx=7601068d esi=00010000 edi=0012fcd8
eip=77edc8cc esp=0012fa80 ebp=0012faa4 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
GDI32!NtGdiEllipse+0x5:
77edc8cc ba0003fe7f       mov     edx,0x7ffe0300
0:000> t
eax=00001080 ebx=7601068d ecx=00550000 edx=7ffe0300 esi=00010000 edi=0012fcd8
eip=77edc8d1 esp=0012fa80 ebp=0012faa4 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
GDI32!NtGdiEllipse+0xa:
77edc8d1 ff12 call dword ptr [edx]{ntdll!KiFastSystemCall (7c94eb8b)}
              ds:0023:7ffe0300=7c94eb8b
0:000> t
eax=00001080 ebx=7601068d ecx=00550000 edx=7ffe0300 esi=00010000 edi=0012fcd8
eip=7c94eb8b esp=0012fa7c ebp=0012faa4 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCall:
7c94eb8b 8bd4             mov     edx,esp
0:000> t
eax=00001080 ebx=7601068d ecx=00550000 edx=0012fa7c esi=00010000 edi=0012fcd8
eip=7c94eb8d esp=0012fa7c ebp=0012faa4 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCall+0x2:
7c94eb8d 0f34             sysenter
0:000> t
eax=00000001 ebx=7601068d ecx=00000001 edx=ffffffff esi=00010000 edi=0012fcd8
eip=77edc8d3 esp=0012fa80 ebp=0012faa4 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
GDI32!NtGdiEllipse+0xc:
77edc8d3 c21400           ret     0x14
0:000> t
eax=00000001 ebx=7601068d ecx=00000001 edx=ffffffff esi=00010000 edi=0012fcd8
eip=77edc8bb esp=0012fa98 ebp=0012faa4 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
GDI32!Ellipse+0xa9:
77edc8bb 5f               pop     edi

GDI32のEllipse()を呼ぶとGDI32内のNtGdiEllipse()が呼び出され、NTDLLのKiFastSystemCall()内のsysenter命令を用いてカーネルモードに移行しているのがわかります。(NTDLLのその他のルーチンがコールされていないことに注意。)最後にUSER32のfunctionです。

GetDC()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.3.0017.0
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi\Debug\nativeapi.exe
Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00400000 0047d000   nativeapi.exe
ModLoad: 7c940000 7c9dd000   ntdll.dll
ModLoad: 7c800000 7c931000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 77cf0000 77d7f000   C:\WINDOWS\system32\USER32.dll
ModLoad: 77ed0000 77f16000   C:\WINDOWS\system32\GDI32.dll
(9d0.970): Break instruction exception - code 80000003 (first chance)
eax=00251eb4 ebx=7ffdd000 ecx=00000007 edx=00000080 esi=00251f48 edi=00251eb4
eip=7c941230 esp=0012fb20 ebp=0012fc94 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c941230 cc               int     3
0:000> g
ModLoad: 762e0000 762fd000   C:\WINDOWS\system32\IMM32.DLL

... 途中省略

ModLoad: 770d0000 7715c000   C:\WINDOWS\system32\oleaut32.dll
(9d0.970): Break instruction exception - code 80000003 (first chance)
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c941230 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
7c941230 cc               int     3
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=7c941231 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint+0x1:
7c941231 c3               ret
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00424653 esp=0012fac0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
*** WARNING: Unable to verify checksum for nativeapi.exe
nativeapi!WindowFunc+0x2a3:
00424653 3bf4             cmp     esi,esp
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00422bae esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!ILT+2985(__RTC_CheckEsp):
00422bae e9dd1d0000       jmp     nativeapi!_RTC_CheckEsp (00424990)
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00424990 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!_RTC_CheckEsp:
00424990 7501             jnz   nativeapi!_RTC_CheckEsp+0x3 (00424993) [br=0]
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=00424992 esp=0012fabc ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!_RTC_CheckEsp+0x2:
00424992 c3               ret
0:000> t
eax=00000001 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=0042465a esp=0012fac0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!WindowFunc+0x2aa:
0042465a 8bf4             mov     esi,esp
0:000> t
eax=0075053e ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=77cf8697 esp=0012fab8 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
USER32!NtUserGetDC:
77cf8697 b891110000       mov     eax,0x1191
0:000> t
eax=00001191 ebx=00000000 ecx=7c95056d edx=00150608 esi=0012fac0 edi=0012fcd8
eip=77cf869c esp=0012fab8 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
USER32!NtUserGetDC+0x5:
77cf869c ba0003fe7f       mov     edx,0x7ffe0300
0:000> t
eax=00001191 ebx=00000000 ecx=7c95056d edx=7ffe0300 esi=0012fac0 edi=0012fcd8
eip=77cf86a1 esp=0012fab8 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
USER32!NtUserGetDC+0xa:
77cf86a1 ff12 call dword ptr [edx]{ntdll!KiFastSystemCall (7c94eb8b)}
              ds:0023:7ffe0300=7c94eb8b
0:000> t
eax=00001191 ebx=00000000 ecx=7c95056d edx=7ffe0300 esi=0012fac0 edi=0012fcd8
eip=7c94eb8b esp=0012fab4 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCall:
7c94eb8b 8bd4             mov     edx,esp
0:000> t
eax=00001191 ebx=00000000 ecx=7c95056d edx=0012fab4 esi=0012fac0 edi=0012fcd8
eip=7c94eb8d esp=0012fab4 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCall+0x2:
7c94eb8d 0f34             sysenter
0:000> t
eax=b0010cba ebx=00000000 ecx=00000001 edx=ffffffff esi=0012fac0 edi=0012fcd8
eip=77cf86a3 esp=0012fab8 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
USER32!NtUserGetDC+0xc:
77cf86a3 c20400           ret     0x4
0:000> t
eax=b0010cba ebx=00000000 ecx=00000001 edx=ffffffff esi=0012fac0 edi=0012fcd8
eip=00424666 esp=0012fac0 ebp=0012fcd8 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
nativeapi!WindowFunc+0x2b6:
00424666 3bf4             cmp     esi,esp

USER32のNtUserGetDC()を呼び出すと()、そのままNTDLLのKiFastSystemCall()内のsysenter命令を用いてカーネルモードに移行しているのがわかります。(NTDLLのその他のルーチンがコールされていないことに注意。)

上記例ではsysenter命令を用いてカーネルモードへ移行していますが、sysenterはPentiumIIで導入された命令です。それ以前のCPU(Pentium, Pentium PROなど)で動作するWindowsNT 4.0/2000などではソフトウェア割り込み(int 2E)を使ってカーネルモードに移行します。WindowsXPのNTDLL.DLLにもKiIntSystemCall()という名前でint 2Eを用いたカーネルモード移行ルーチンが残っています。(Die Windows HistoryにWindowsXPをPentiumで動作させている例が載っているのを見ると、おそらくこうした場合に使われているものと推測される。)

■Win32(WOW64)の場合

Win32(WOW64)について調べます。本題に入る前にWOW64について見ておきます。WOW64とは64-bit版Windows上でWin32アプリを実行するためのエミュレーション層を指します。主として3つのDLL(WOW64.DLL WOW64WIN.DLL WOW64CPU.DLL)から構成されます。WOW64.DLLとWOW64WIN.DLLがWIN32アプリのシステムコールをintercept(横取り)して64-bitのシステムコールに置き換えて実行します。WOW64.DLLが横取りした分についてはNTDLL.DLL(64-bit native)経由でNTOSKRNL.EXE(64-bit native)がコールされ、WOW64WIN.DLLが横取りした分については直接WIN32K.SYS(64-bit native)がコールされます。WOW64CPU.DLLはCPUのモード切替を担当します。(MSDNの資料には「WOW64CPU.DLLはx64では不要」と記述されているが、x64プロセッサの32-bitから64-bitへの切り替えはWOW64CPU.DLLで行われており、必須であるものと思われる。)

以下、WindowsXP Professional x64 Edition(RC1)+Athlon64(NewCastle)の環境で実行します。windbgはVersion 6.4.4.4(x64版-beta)を使います。最初はKERNEL32のfunctionです。

VirtualQuery()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.4.0004.4
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi\Debug\nativeapi.exe
Symbol search path is: SRV*C:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00000000`00400000 00000000`0047d000   nativeapi.exe
ModLoad: 00000000`77ea0000 00000000`77ff3000   ntdll.dll
ModLoad: 00000000`77b70000 00000000`77bb6000   C:\WINDOWS\system32\wow64.dll
ModLoad: 00000000`77b20000 00000000`77b69000   C:\WINDOWS\system32\wow64win.dll
ModLoad: 00000000`77b10000 00000000`77b19000   C:\WINDOWS\system32\wow64cpu.dll
(70.73c): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> g
ModLoad: 00000000`77ce0000 00000000`77e92000   NOT_AN_IMAGE
ModLoad: 00000000`7d4d0000 00000000`7d5d0000   NOT_AN_IMAGE
ModLoad: 00000000`7d5e0000 00000000`7d6f0000   C:\WINDOWS\syswow64\ntdll32.dll
ModLoad: 00000000`77ce0000 00000000`77e92000   NOT_AN_IMAGE
ModLoad: 00000000`77bc0000 00000000`77ccf000   NOT_AN_IMAGE
ModLoad: 00000000`7d4d0000 00000000`7d5d0000   C:\WINDOWS\syswow64\kernel32.dll
ModLoad: 00000000`7d940000 00000000`7da10000   C:\WINDOWS\syswow64\USER32.dll
ModLoad: 00000000`7d810000 00000000`7d8a0000   C:\WINDOWS\syswow64\GDI32.dll
(70.73c): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll32!DbgBreakPoint:
00000000`7d5f002d cc      int     3
0:000:x86> g
ModLoad: 00000000`7dee0000 00000000`7df40000   C:\WINDOWS\syswow64\IMM32.DLL

... 途中省略

ModLoad: 00000000`75810000 00000000`758d0000   C:\WINDOWS\syswow64\USERENV.dll
(70.73c): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll32!DbgBreakPoint:
00000000`7d5f002d cc      int     3
0:000:x86> t
ntdll32!DbgBreakPoint+0x1:
00000000`7d5f002e c3      ret
0:000:x86> t
*** WARNING: Unable to verify checksum for nativeapi.exe
*** ERROR: Module load completed but symbols could not be loaded for nativeapi.exe
nativeapi+0x24480:
00000000`00424480 3bf4    cmp     esi,esp
0:000:x86> t
nativeapi+0x24482:
00000000`00424482 e827e7ffff call nativeapi+0x22bae (00422bae)
0:000:x86> t
nativeapi+0x22bae:
00000000`00422bae e9dd1d0000 jmp  nativeapi+0x24990 (00424990)
0:000:x86> t
nativeapi+0x24990:
00000000`00424990 7501    jnz     nativeapi+0x24993 (00424993)         [br=0]
0:000:x86> t
nativeapi+0x24992:
00000000`00424992 c3      ret
0:000:x86> t
nativeapi+0x24487:
00000000`00424487 8bf4    mov     esi,esp
0:000:x86> t
nativeapi+0x24489:
00000000`00424489 6a1c    push    0x1c
0:000:x86> t
nativeapi+0x2448b:
00000000`0042448b 8d85c8feffff lea eax,[ebp-0x138] ss:002b:00000000`002cfb78=cccccccc
0:000:x86> t
nativeapi+0x24491:
00000000`00424491 50      push    eax
0:000:x86> t
nativeapi+0x24492:
00000000`00424492 8b8decfeffff mov ecx,[ebp-0x114] ss:002b:00000000`002cfb9c=00000000
0:000:x86> t
nativeapi+0x24498:
00000000`00424498 51      push    ecx
0:000:x86> t
nativeapi+0x24499:
00000000`00424499 ff1558b34700 call dword ptr [nativeapi+0x7b358 (0047b358)]
                               {kernel32!VirtualQuery (7d4eac15)}
                               ds:002b:00000000`0047b358=7d4eac15
0:000:x86> t
kernel32!VirtualQuery:
00000000`7d4eac15 8bff    mov     edi,edi
0:000:x86> t
kernel32!VirtualQuery+0x2:
00000000`7d4eac17 55      push    ebp
0:000:x86> t
kernel32!VirtualQuery+0x3:
00000000`7d4eac18 8bec    mov     ebp,esp

... 途中省略

0:000:x86> t
kernel32!VirtualQuery+0x10:
00000000`7d4eac25 e8baffffff call kernel32!VirtualQueryEx (7d4eabe4)
0:000:x86> t
kernel32!VirtualQueryEx:
00000000`7d4eabe4 8bff    mov     edi,edi
0:000:x86> t
kernel32!VirtualQueryEx+0x2:
00000000`7d4eabe6 55      push    ebp
0:000:x86> t
kernel32!VirtualQueryEx+0x3:
00000000`7d4eabe7 8bec    mov     ebp,esp

... 途中省略

0:000:x86> t
kernel32!VirtualQueryEx+0x17:
00000000`7d4eabfb ff15e0024e7d call dword ptr [kernel32!_imp__NtQueryVirtualMemory (7d4e02e0)]
                               {ntdll32!NtQueryVirtualMemory (7d5fcac6)}
                               ds:002b:00000000`7d4e02e0=7d5fcac6
0:000:x86> t
ntdll32!NtQueryVirtualMemory:
00000000`7d5fcac6 b820000000 mov  eax,0x20

... 途中省略

0:000:x86> t
ntdll32!ZwQueryVirtualMemory+0xb:
00000000`7d5fcad1 64ff15c0000000 call dword ptr fs:[000000c0] fs:0053:00000000`000000c0=????????
0:000:x86> t
wow64cpu!X86SwitchTo64BitMode:
00000000`77b11870 ea2c38b1773300 jmp 0033:wow64cpu!CpupReturnFromSimulatedCode (77b1382c)
0:000:x86> t
wow64cpu!CpupReturnFromSimulatedCode:
00000000`77b1382c 67448b0424      mov r8d,[esp] ss:00000000`002cfa4c=7d5fcad8

... 途中省略

0:000> t
wow64cpu!CpupReturnFromSimulatedCode+0x22:
00000000`77b1384e 448bda           mov     r11d,edx
0:000> t
wow64cpu!TurboDispatchJumpAddressStart:
00000000`77b13851 41ff24cf 
0:000> t
wow64cpu!ServiceNoTurbo:
00000000`77b13855 4189b5a4000000 mov [r13+0xa4],esi ds:00000000`0012ef54=00976ab0

... 途中省略

0:000> t
wow64cpu!ServiceNoTurbo+0x22:
00000000`77b13877 ff15f3d7ffff call qword ptr [wow64cpu!_imp_Wow64SystemServiceEx (0000000077b11070)]
                               ds:00000000`77b11070=0000000077b767b0
0:000> t
wow64!Wow64SystemServiceEx:
00000000`77b767b0 4c8bdc           mov     r11,rsp

... 途中省略

0:000> t
wow64!Wow64SystemServiceEx+0xd3:
00000000`77b76883 41ffd4 call r12 {wow64!whNtQueryVirtualMemory (0000000077b820c0)}
0:000> t
wow64!whNtQueryVirtualMemory:
00000000`77b820c0 488bc4           mov     rax,rsp

... 途中省略

0:000> t
wow64!whNtQueryVirtualMemory+0x3f:
00000000`77b820ff e8bc86ffff call wow64!Wow64ShallowThunkSIZE_T32TO64 (0000000077b7a7c0)
0:000> t
wow64!Wow64ShallowThunkSIZE_T32TO64:
00000000`77b7a7c0 4885d2           test    rdx,rdx

... 途中省略

0:000> t
wow64!Wow64ShallowThunkSIZE_T32TO64+0x15:
00000000`77b7a7d5 c20000           ret     0x0
0:000> t
wow64!whNtQueryVirtualMemory+0x44:
00000000`77b82104 85ff             test    edi,edi

... 途中省略

0:000> t
wow64!whNtQueryVirtualMemory+0xfb:
00000000`77b821bb e870fdffff call wow64!whNtQueryVirtualMemory_MemoryBasicInformation (0000000077b81f30)
0:000> t
wow64!whNtQueryVirtualMemory_MemoryBasicInformation:
00000000`77b81f30 488bc4           mov     rax,rsp

... 途中省略

0:000> t
wow64!whNtQueryVirtualMemory_MemoryBasicInformation+0xbc:
00000000`77b81fec ff1546f2feff call qword ptr [wow64!_imp_NtQueryVirtualMemory (0000000077b71238)]
                               ds:00000000`77b71238=0000000077ef2f90
0:000> t
ntdll!ZwQueryVirtualMemory:
00000000`77ef2f90 4c8bd1           mov     r10,rcx
0:000> t
ntdll!NtQueryVirtualMemory+0x3:
00000000`77ef2f93 b820000000       mov     eax,0x20
0:000> t
ntdll!NtQueryVirtualMemory+0x8:
00000000`77ef2f98 0f05             syscall
0:000> t
ntdll!NtQueryVirtualMemory+0xa:
00000000`77ef2f9a c3               ret
0:000> t
wow64!whNtQueryVirtualMemory_MemoryBasicInformation+0xc2:
00000000`77b81ff2 4c8ba42498000000 mov r12,[rsp+0x98] ss:00000000`0012e4d8=000000000012e4e0

まず冒頭のModLoadの行にご注目ください。仮想アドレス空間にロードされたDLLが列挙されています。64ビットネイティブなDLLとして、NTDLL.DLL WOW64.DLL WOW64WIN.DLL WOW64CPU.DLLがロードされています。さらにWIN32アプリがコールしてくるスタブルーチンとしてのKERNEL32.DLL USER32.DLL GDI32.DLLもロードされており、KERNEL32.DLLがネイティブAPIコールのために使うNTDLL32.DLLもロードされています。

KERNEL32のVirtualQuery()をコールすると、VirtualQueryEx()がコールされ、NTDLL32NtQueryVirtualMemory()、ZwQueryVirtualMemory()がコールされます。32-bit版Windowsであればここでカーネルモードへ移行するところでしょうが、そうはならずにセグメント間CALL命令(call dword ptr fs:[000000c0])でWOW64に制御を移します。最初にWOW64CPU.DLLのX86SwitchTo64BitModeで32-bit mode(Compatibility mode)から64-bit modeに移行します。その後はWOW64CPU内のいくつかのルーチン、WOW64のwhNtQueryVirtualMemory(),whNtQueryVirtualMemory_MemoryBasicInformation()などを実行した後に(64ビットネイティブな)NTDLLのNtQueryVirtualMemory()、ZwQueryVirtualMemory()がコールされ(エントリーポイントはどちらも同じ)、ここでようやくsyscall命令を用いてカーネルモードへ移行します。(KiFastSystemCall()をコールするのではなく、直接syscall命令を実行している点に注意。)

GDI32のfunctionについても見てみます。

Ellipse()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.4.0004.4
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi\Debug\nativeapi.exe
Symbol search path is: SRV*C:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00000000`00400000 00000000`0047d000   nativeapi.exe
ModLoad: 00000000`77ea0000 00000000`77ff3000   ntdll.dll
ModLoad: 00000000`77b70000 00000000`77bb6000   C:\WINDOWS\system32\wow64.dll
ModLoad: 00000000`77b20000 00000000`77b69000   C:\WINDOWS\system32\wow64win.dll
ModLoad: 00000000`77b10000 00000000`77b19000   C:\WINDOWS\system32\wow64cpu.dll
(51c.1d8): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> g
ModLoad: 00000000`77ce0000 00000000`77e92000   NOT_AN_IMAGE
ModLoad: 00000000`7d4d0000 00000000`7d5d0000   NOT_AN_IMAGE
ModLoad: 00000000`7d5e0000 00000000`7d6f0000   C:\WINDOWS\syswow64\ntdll32.dll
ModLoad: 00000000`77ce0000 00000000`77e92000   NOT_AN_IMAGE
ModLoad: 00000000`77bc0000 00000000`77ccf000   NOT_AN_IMAGE
ModLoad: 00000000`7d4d0000 00000000`7d5d0000   C:\WINDOWS\syswow64\kernel32.dll
ModLoad: 00000000`7d940000 00000000`7da10000   C:\WINDOWS\syswow64\USER32.dll
ModLoad: 00000000`7d810000 00000000`7d8a0000   C:\WINDOWS\syswow64\GDI32.dll
(51c.1d8): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll32!DbgBreakPoint:
00000000`7d5f002d cc      int     3
0:000:x86> g
ModLoad: 00000000`7dee0000 00000000`7df40000   C:\WINDOWS\syswow64\IMM32.DLL

... 途中省略

ModLoad: 00000000`75810000 00000000`758d0000   C:\WINDOWS\syswow64\USERENV.dll
(51c.1d8): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll32!DbgBreakPoint:
00000000`7d5f002d cc      int     3
0:000:x86> t
ntdll32!DbgBreakPoint+0x1:
00000000`7d5f002e c3      ret
0:000:x86> t
*** WARNING: Unable to verify checksum for nativeapi.exe
*** ERROR: Module load completed but symbols could not be loaded for nativeapi.exe
nativeapi+0x24586:
00000000`00424586 3bf4    cmp     esi,esp
0:000:x86> t
nativeapi+0x24588:
00000000`00424588 e821e6ffff call nativeapi+0x22bae (00422bae)
0:000:x86> t
nativeapi+0x22bae:
00000000`00422bae e9dd1d0000 jmp  nativeapi+0x24990 (00424990)
0:000:x86> t
nativeapi+0x24990:
00000000`00424990 7501    jnz     nativeapi+0x24993 (00424993)         [br=0]
0:000:x86> t
nativeapi+0x24992:
00000000`00424992 c3      ret
0:000:x86> t
nativeapi+0x2458d:
00000000`0042458d 8bf4    mov     esi,esp
0:000:x86> t
nativeapi+0x2458f:
00000000`0042458f 6a3c    push    0x3c
0:000:x86> t
nativeapi+0x24591:
00000000`00424591 6a3c    push    0x3c
0:000:x86> t
nativeapi+0x24593:
00000000`00424593 6a0a    push    0xa
0:000:x86> t
nativeapi+0x24595:
00000000`00424595 6a0a    push    0xa
0:000:x86> t
nativeapi+0x24597:
00000000`00424597 8b85bcfeffff mov eax,[ebp-0x144] ss:002b:00000000`002cfb6c=fc0104f3
0:000:x86> t
nativeapi+0x2459d:
00000000`0042459d 50      push    eax
0:000:x86> t
nativeapi+0x2459e:
00000000`0042459e ff15dcb24700 call dword ptr [nativeapi+0x7b2dc (0047b2dc)] {GDI32!Ellipse (7d82cc68)}
                               ds:002b:00000000`0047b2dc=7d82cc68
0:000:x86> t
GDI32!Ellipse:
00000000`7d82cc68 8bff    mov     edi,edi

... 途中省略

0:000:x86> t
GDI32!Ellipse+0xaa:
00000000`7d82cca7 e80c000000 call GDI32!NtGdiEllipse (7d82ccb8)
0:000:x86> t
GDI32!NtGdiEllipse:
00000000`7d82ccb8 b888110000 mov  eax,0x1188

... 途中省略

0:000:x86> t
GDI32!NtGdiEllipse+0xe:
00000000`7d82ccc6 64ff15c0000000 call dword ptr fs:[000000c0] fs:0053:00000000`000000c0=???????? 
0:000:x86> t
wow64cpu!X86SwitchTo64BitMode:
00000000`77b11870 ea2c38b1773300 jmp 0033:wow64cpu!CpupReturnFromSimulatedCode (77b1382c)
0:000:x86> t
wow64cpu!CpupReturnFromSimulatedCode:
00000000`77b1382c 67448b0424      mov r8d,[esp] ss:00000000`002cfa54=7d82cccd

... 途中省略

0:000> t
wow64cpu!CpupReturnFromSimulatedCode+0x22:
00000000`77b1384e 448bda           mov     r11d,edx
0:000> t
wow64cpu!TurboDispatchJumpAddressStart:
00000000`77b13851 41ff24cf jmp qword ptr [r15+rcx*8]{wow64cpu!ServiceNoTurbo (0000000077b13855)}
                           ds:00000000`77b13590=0000000077b13855
0:000> t
wow64cpu!ServiceNoTurbo:
00000000`77b13855 4189b5a4000000 mov [r13+0xa4],esi ds:00000000`0012ef54=0096d200

... 途中省略

0:000> t
wow64cpu!ServiceNoTurbo+0x22:
00000000`77b13877 ff15f3d7ffff call qword ptr [wow64cpu!_imp_Wow64SystemServiceEx (0000000077b11070)]
                               ds:00000000`77b11070=0000000077b767b0
0:000> t
wow64!Wow64SystemServiceEx:
00000000`77b767b0 4c8bdc           mov     r11,rsp

... 途中省略

0:000> t
wow64!Wow64SystemServiceEx+0xd3:
00000000`77b76883 41ffd4 call r12 {wow64win!whNtGdiEllipse (0000000077b49f00)}
0:000> t
wow64win!whNtGdiEllipse:
00000000`77b49f00 4883ec38         sub     rsp,0x38

... 途中省略

0:000> t
wow64win!ZwGdiEllipse+0x3:
00000000`77b571f3 b888110000       mov     eax,0x1188
0:000> t
wow64win!ZwGdiEllipse+0x8:
00000000`77b571f8 0f05             syscall
0:000> t
wow64win!ZwGdiEllipse+0xa:
00000000`77b571fa c3               ret
0:000> t
wow64win!whNtGdiEllipse+0x21:
00000000`77b49f21 4883c438         add     rsp,0x38
0:000> t
wow64win!whNtGdiEllipse+0x25:
00000000`77b49f25 c3               ret
0:000> t
wow64!Wow64SystemServiceEx+0xd6:
00000000`77b76886 8bd8             mov     ebx,eax

GDI32のEllipse()をコールすると、NtGdiEllipse()がコールされます。32-bit版Windowsであればここで直接カーネルモードへ移行しますが、そうはならずにセグメント間CALL命令(call dword ptr fs:[000000c0])でWOW64に制御を移します。最初にWOW64CPU.DLLのX86SwitchTo64BitModeで32-bit mode(Compatibility mode)から64-bit modeに移行します。その後はWOW64CPU内のいくつかのルーチン、WOW64WINのwhNtGdiEllipse(),ZwGdiEllipse()をコールし(どちらもエントリーポイントは同じ)、ここでようやくsyscall命令を用いてカーネルモードへ移行します。(NTDLLのルーチンをコールしていない点に注意。)

最後にUSER32のfunctionについて見てみます。

GetDC()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.4.0004.4
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi\Debug\nativeapi.exe
Symbol search path is: SRV*C:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00000000`00400000 00000000`0047d000   nativeapi.exe
ModLoad: 00000000`77ea0000 00000000`77ff3000   ntdll.dll
ModLoad: 00000000`77b70000 00000000`77bb6000   C:\WINDOWS\system32\wow64.dll
ModLoad: 00000000`77b20000 00000000`77b69000   C:\WINDOWS\system32\wow64win.dll
ModLoad: 00000000`77b10000 00000000`77b19000   C:\WINDOWS\system32\wow64cpu.dll
(fc.72c): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> g
ModLoad: 00000000`77ce0000 00000000`77e92000   NOT_AN_IMAGE
ModLoad: 00000000`7d4d0000 00000000`7d5d0000   NOT_AN_IMAGE
ModLoad: 00000000`7d5e0000 00000000`7d6f0000   C:\WINDOWS\syswow64\ntdll32.dll
ModLoad: 00000000`77ce0000 00000000`77e92000   NOT_AN_IMAGE
ModLoad: 00000000`77bc0000 00000000`77ccf000   NOT_AN_IMAGE
ModLoad: 00000000`7d4d0000 00000000`7d5d0000   C:\WINDOWS\syswow64\kernel32.dll
ModLoad: 00000000`7d940000 00000000`7da10000   C:\WINDOWS\syswow64\USER32.dll
ModLoad: 00000000`7d810000 00000000`7d8a0000   C:\WINDOWS\syswow64\GDI32.dll
(fc.72c): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll32!DbgBreakPoint:
00000000`7d5f002d cc      int     3
0:000:x86> g
ModLoad: 00000000`7dee0000 00000000`7df40000   C:\WINDOWS\syswow64\IMM32.DLL

... 途中省略

ModLoad: 00000000`75810000 00000000`758d0000   C:\WINDOWS\syswow64\USERENV.dll
(fc.72c): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll32!DbgBreakPoint:
00000000`7d5f002d cc      int     3
0:000:x86> t
ntdll32!DbgBreakPoint+0x1:
00000000`7d5f002e c3      ret
0:000:x86> t
*** WARNING: Unable to verify checksum for nativeapi.exe
*** ERROR: Module load completed but symbols could not be loaded for nativeapi.exe
nativeapi+0x24653:
00000000`00424653 3bf4    cmp     esi,esp
0:000:x86> t
nativeapi+0x24655:
00000000`00424655 e854e5ffff call nativeapi+0x22bae (00422bae)
0:000:x86> t
nativeapi+0x22bae:
00000000`00422bae e9dd1d0000 jmp  nativeapi+0x24990 (00424990)
0:000:x86> t
nativeapi+0x24990:
00000000`00424990 7501    jnz     nativeapi+0x24993 (00424993)         [br=0]
0:000:x86> t
nativeapi+0x24992:
00000000`00424992 c3      ret
0:000:x86> t
nativeapi+0x2465a:
00000000`0042465a 8bf4    mov     esi,esp
0:000:x86> t
nativeapi+0x2465c:
00000000`0042465c 8b4508 mov eax,[ebp+0x8] ss:002b:00000000`002cfcb8=00190196
0:000:x86> t
nativeapi+0x2465f:
00000000`0042465f 50      push    eax
0:000:x86> t
nativeapi+0x24660:
00000000`00424660 ff15f8b44700 call dword ptr [nativeapi+0x7b4f8 (0047b4f8)]
                               {USER32!NtUserGetDC (7d958cc0)}
                               ds:002b:00000000`0047b4f8=7d958cc0
0:000:x86> t
USER32!NtUserGetDC:
00000000`7d958cc0 b80a100000 mov  eax,0x100a

... 途中省略

0:000:x86> t
USER32!NtUserGetDC+0xe:
00000000`7d958cce 64ff15c0000000 call dword ptr fs:[000000c0] fs:0053:00000000`000000c0=????????
0:000:x86> t
wow64cpu!X86SwitchTo64BitMode:
00000000`77b11870 ea2c38b1773300 jmp 0033:wow64cpu!CpupReturnFromSimulatedCode (77b1382c)
0:000:x86> t
wow64cpu!CpupReturnFromSimulatedCode:
00000000`77b1382c 67448b0424      mov r8d,[esp] ss:00000000`002cfa8c=7d958cd5

... 途中省略

0:000> t
wow64cpu!CpupReturnFromSimulatedCode+0x22:
00000000`77b1384e 448bda           mov     r11d,edx
0:000> t
wow64cpu!TurboDispatchJumpAddressStart:
00000000`77b13851 41ff24cf jmp qword ptr [r15+rcx*8]{wow64cpu!Thunk1ArgSp (0000000077b13cde)}
                           ds:00000000`77b135a8=0000000077b13cde
0:000> t
wow64cpu!Thunk1ArgSp:
00000000`77b13cde 4d6313       movsxd r10,[r11] ds:00000000`002cfa94=00190196
0:000> t
wow64cpu!Thunk1ArgSp+0x3:
00000000`77b13ce1 eb4b             jmp  wow64cpu!Thunk0Arg (0000000077b13d2e)
0:000> t
wow64cpu!Thunk0Arg:
00000000`77b13d2e e83d000000 call wow64cpu!CpupSyscallStub (0000000077b13d70)
0:000> t
wow64cpu!CpupSyscallStub:
00000000`77b13d70 0f05             syscall
0:000> t
wow64cpu!CpupSyscallStub+0x2:
00000000`77b13d72 c3               ret
0:000> t
wow64cpu!Thunk0Arg+0x5:
00000000`77b13d33 4d89b42480140000 mov [r12+0x1480],r14 ds:00000000`7efdc480=0000000000000000

USER32のNtUserGetDC()をコールすると、いくつかの処理をした後にセグメント間CALL命令(call dword ptr fs:[000000c0])でWOW64に制御を移します。最初にWOW64CPU.DLLのX86SwitchTo64BitModeで32-bit mode(Compatibility mode)から64-bit modeに移行します。WOW64CPU内のいくつかのルーチンを実行した後に
WOW64CPU内のCpupSyscallStub()をコールし、ここでsyscall命令を用いてカーネルモードへ移行します。
(NTDLLのルーチンをコールしていない点に注意。)

■Win64の場合

最後にWin64について調べます。システムコール時の流れはWin32(ネイティブ)の場合と大体同じです。

Win32(WOW64)の場合と同様にWindowsXP Professional x64 Edition(RC1)+Athlon64(NewCastle)の環境で実行します。windbgはVersion 6.4.4.4(x64版-beta)を使います。最初はKERNEL32のfunctionです。

VirtualQuery()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.4.0004.4
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi64\Debug\nativeapi.exe
Symbol search path is: SRV*C:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00000000`00400000 00000000`0040f000   nativeapi.exe
ModLoad: 00000000`77ea0000 00000000`77ff3000   ntdll.dll
ModLoad: 00000000`77ce0000 00000000`77e92000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 00000000`77bc0000 00000000`77ccf000   C:\WINDOWS\system32\USER32.dll
ModLoad: 000007ff`7fc80000 000007ff`7fd17000   C:\WINDOWS\system32\GDI32.dll
(19c.6e8): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> g
ModLoad: 000007ff`7d3d0000 000007ff`7d409000   C:\WINDOWS\system32\IMM32.DLL

... 途中省略

ModLoad: 000007ff`7c550000 000007ff`7c654000   C:\WINDOWS\system32\USERENV.dll
(19c.6e8): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> t
ntdll!DbgBreakPoint+0x1:
00000000`77ef4051 c3               ret
0:000> t
*** WARNING: Unable to verify checksum for nativeapi.exe
*** ERROR: Module load completed but symbols could not be loaded for nativeapi.exe
nativeapi+0x12a8:
00000000`004012a8 41b830000000     mov     r8d,0x30
0:000> t
nativeapi+0x12ae:
00000000`004012ae 488d942440010000 lea rdx,[rsp+0x140] ss:00000000`0012fc20=fffff80000000000
0:000> t
nativeapi+0x12b6:
00000000`004012b6 488b4c2430 mov rcx,[rsp+0x30] ss:00000000`0012fb10=0000000000000000
0:000> t
nativeapi+0x12bb:
00000000`004012bb ff15976d0000 call qword ptr [nativeapi+0x8058 (0000000000408058)]
                               ds:00000000`00408058=0000000077cec3e0
0:000> t
kernel32!VirtualQuery:
00000000`77cec3e0 4883ec38         sub     rsp,0x38

... 途中省略

0:000> t
kernel32!VirtualQuery+0x20:
00000000`77cec400 ff15ba51ffff call qword ptr [kernel32!_imp_NtQueryVirtualMemory (0000000077ce15c0)]
                               ds:00000000`77ce15c0=0000000077ef2f90
0:000> t
ntdll!ZwQueryVirtualMemory:
00000000`77ef2f90 4c8bd1           mov     r10,rcx
0:000> t
ntdll!ZwQueryVirtualMemory+0x3:
00000000`77ef2f93 b820000000       mov     eax,0x20
0:000> t
ntdll!ZwQueryVirtualMemory+0x8:
00000000`77ef2f98 0f05             syscall
0:000> t
ntdll!ZwQueryVirtualMemory+0xa:
00000000`77ef2f9a c3               ret
0:000> t
kernel32!VirtualQuery+0x26:
00000000`77cec406 85c0             test    eax,eax

冒頭のModLoadの行を見ると、仮想アドレス空間にロードされているDLLのファイル名はWin32(ネイティブ)の場合と
同じであることがわかります。(混乱しそうですが、64-bit版WindowsでのNTDLL.DLL system32ディレクトリ内のKERNEL32.DLL GDI32.DLL USER32.DLL はすべて64ビットネイティブなDLLです。)KERNEL32のVirtualQuery()をコールするとNTDLLのZwQueryVirtualMemory()がコールされ、そこでsyscall命令を用いてカーネルモードへ移行しています。次はGDI32です。

Ellipse()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.4.0004.4
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi64\Debug\nativeapi.exe
Symbol search path is: SRV*C:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00000000`00400000 00000000`0040f000   nativeapi.exe
ModLoad: 00000000`77ea0000 00000000`77ff3000   ntdll.dll
ModLoad: 00000000`77ce0000 00000000`77e92000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 00000000`77bc0000 00000000`77ccf000   C:\WINDOWS\system32\USER32.dll
ModLoad: 000007ff`7fc80000 000007ff`7fd17000   C:\WINDOWS\system32\GDI32.dll
(708.348): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> g
ModLoad: 000007ff`7d3d0000 000007ff`7d409000   C:\WINDOWS\system32\IMM32.DLL

... 途中省略

ModLoad: 000007ff`7c550000 000007ff`7c654000   C:\WINDOWS\system32\USERENV.dll
(708.348): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> t
ntdll!DbgBreakPoint+0x1:
00000000`77ef4051 c3               ret
0:000> t
*** WARNING: Unable to verify checksum for nativeapi.exe
*** ERROR: Module load completed but symbols could not be loaded for nativeapi.exe

... 途中省略

0:000> t
nativeapi+0x139d:
00000000`0040139d ff155d6c0000 call qword ptr [nativeapi+0x8000 (0000000000408000)]
                               ds:00000000`00408000=000007ff7fcd13c0
0:000> t
GDI32!Ellipse:
000007ff`7fcd13c0 4883ec68         sub     rsp,0x68

... 途中省略

0:000> t
GDI32!Ellipse+0x13c:
000007ff`7fcd14fc e85fbdfdff       call GDI32!NtGdiEllipse (000007ff7fcad260)
0:000> t
GDI32!NtGdiEllipse:
000007ff`7fcad260 4c8bd1           mov     r10,rcx
0:000> t
GDI32!ZwGdiEllipse+0x3:
000007ff`7fcad263 b888110000       mov     eax,0x1188
0:000> t
GDI32!ZwGdiEllipse+0x8:
000007ff`7fcad268 0f05             syscall
0:000> t
GDI32!ZwGdiEllipse+0xa:
000007ff`7fcad26a c3               ret
0:000> t
GDI32!Ellipse+0x13f:
000007ff`7fcd1501 4c8b6c2438 mov r13,[rsp+0x38] ss:00000000`0012faa8=0000000000000001

GDI32のEllipse()をコールすると、GDI32内のNtGdiEllipse()、ZwGdiEllipse()がコールされ(どちらもエントリーポイントは同じ)、ここで直接syscall命令を用いてカーネルモードへ移行します。(NTDLLのルーチンをコールしていない点に注意。)最後にUSER32です。

GetDC()呼び出し時の実行内容

Microsoft (R) Windows Debugger  Version 6.4.0004.4
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\nativeapi\nativeapi64\Debug\nativeapi.exe
Symbol search path is: SRV*C:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00000000`00400000 00000000`0040f000   nativeapi.exe
ModLoad: 00000000`77ea0000 00000000`77ff3000   ntdll.dll
ModLoad: 00000000`77ce0000 00000000`77e92000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 00000000`77bc0000 00000000`77ccf000   C:\WINDOWS\system32\USER32.dll
ModLoad: 000007ff`7fc80000 000007ff`7fd17000   C:\WINDOWS\system32\GDI32.dll
(2d4.56c): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> g
ModLoad: 000007ff`7d3d0000 000007ff`7d409000   C:\WINDOWS\system32\IMM32.DLL

... 途中省略

ModLoad: 000007ff`7c550000 000007ff`7c654000   C:\WINDOWS\system32\USERENV.dll
(2d4.56c): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00000000`77ef4050 cc               int     3
0:000> t
ntdll!DbgBreakPoint+0x1:
00000000`77ef4051 c3               ret
0:000> t
*** WARNING: Unable to verify checksum for nativeapi.exe
*** ERROR: Module load completed but symbols could not be loaded for nativeapi.exe
nativeapi+0x143c:
00000000`0040143c 488b8c24a0010000 mov rcx,[rsp+0x1a0]
                                   ss:00000000`0012fc80=00000000002901da
0:000> t
nativeapi+0x1444:
00000000`00401444 ff15ce6d0000 call qword ptr [nativeapi+0x8218 (0000000000408218)]
                               ds:00000000`00408218=0000000077be1e60
0:000> t
USER32!ZwUserGetDC:
00000000`77be1e60 4c8bd1           mov     r10,rcx
0:000> t
USER32!ZwUserGetDC+0x3:
00000000`77be1e63 b80a100000       mov     eax,0x100a
0:000> t
USER32!ZwUserGetDC+0x8:
00000000`77be1e68 0f05             syscall
0:000> t
USER32!ZwUserGetDC+0xa:
00000000`77be1e6a c3               ret
0:000> t
nativeapi+0x144a:
00000000`0040144a 4889842470010000 mov [rsp+0x170],rax
                                   ss:00000000`0012fc50=000000000012fd88

USER32のZwUserGetDC()をコールすると、いくつかの処理をした後にsyscall命令を用いてカーネルモードへ移行します。(NTDLLのルーチンをコールしていない点に注意。)

起草日:2004年1月2日(日)(www.marbacka.net内の別のサイトで公開)
最終更新日:2017年2月19日(日)

スポンサーリンク