330 likes | 1k Views
WoW64 Internal Architecture. Samer Arafeh Software Design Engineer Windows Base OS Kernel samera @ microsoft.com Microsoft Corporation. Agenda. What is WoW64? WoW64 Process Address Space Layout WoW64 Registry Management WoW64 File System Redirection 32-bit I/O on 64-bit Windows
E N D
WoW64 Internal Architecture Samer Arafeh Software Design Engineer Windows Base OS Kernel samera @ microsoft.com Microsoft Corporation
Agenda • What is WoW64? • WoW64 Process Address Space Layout • WoW64 Registry Management • WoW64 File System Redirection • 32-bit I/O on 64-bit Windows • 32/64 Inter-op Issues • WoW64 Platform-Specific Support • Debugging a WoW64 Process • Discussion
What Is WoW64? • 32-bit Windows emulation layer on 64-bit Windows • Installed as part of 64-bit Windows • Binary compatibility with 32-bit Windows applications is the prime goal • 64-bit Windows system setup installs and registers 64-bit and 32-bit system files • 32-bit system files are copied to %windir%\sysWoW64, likewise, 64-bit system files are installed to %windir%\system32 • %SystemDrive%\Program Files (x86) is the place for 32-bit applications, likewise, %SystemDrive%\Program Files is the place for 64-bit applications • Environment variables are duplicated as well: • ProgramFiles and ProgramFiles(x86) • CommonProgramFiles and CommonProgramFiles(x86)
What Is WoW64? • Once 64-bit Windows is installed, you should be able to run 32-bitWindows applications! • x86 binaries on 64-bit Windows are identical to their counterpart on a native 32-bit Windows x86 system • Compatibility • Feature parity with the native 32-bit Windows Operating System (OS)
How Does WoW64 Work? • WoW64 intercepts system calls from the 32-bit application • Transitions to 64-bit mode • Converts 32-bit data structure into 64-bit aligned structures • Issues the native 64-bit system call • Writes back any output data from the 64-bit system call • Returns to 32-bit mode • Hooks exception dispatching • WoW64 core consists of • WoW64.dll – Manages process and thread initialization, exception dispatching to 32-bit code and intercepts base system calls • WoW64win.dll – Intercepts GUI system calls • WoW64cpu.dll – Manages thread contexts and has processor architecture specific support for switching CPU modes
WoW64 Process Address Space Layout NT Executive Win32k.sys Kernel Mode User Mode Reserved Address Space 0x00000000`7FFEFFFF or 0x00000000`FFFEFFFF 64-bit ntdll.dll WoW64.dll WoW64win.dll WoW64cpu.dll 32-bit ntdll.dll 32-bit modules
WoW64 Process Address Space Layout • Address space is limited to 2GB (or 4GB if the application is marked Large-Address-Aware in the header) • WoW64 processes can NOT load 64-bit DLLs except for the core one! • Likewise, native 64-bit processes can NOT load 32-bit DLLs • LoadLibrary() will fail • Once WoW64 is initialized, 32-bit code executes as if it is running on a native x86 processor
WoW64 Registry • Two views of the registry exist on 64-bit Windows: Native and WoW64 • By default, a native 64-bit Windows application sees the native registry view, and a WoW64 application sees the WoW64 view • Why different WoW64 registry view? • Compatibility • Separates 32-bit application state from 64-bit state • For example: Not supported features stored in the registry • Provides a safe execution environment for both 32-bit and 64-bit applications • For example: a registry value hosting a DLL path
WoW64 Registry Redirection • Certain parts of the system registry are separated • HKEY_LOCAL_MACHINE\Software • HKEY_CLASSES_ROOT • A new key, WoW6432Node, is created at the splitted nodes • When a WoW64 process opens/creates a key • WoW64 redirects the path of the key if it is one of the above by inserting ‘WoW6432Node’ to the above path • Transparent forWin32 applications
WoW64 Registry Reflection • Everything else is shared • API flags to explicitly specify a view of the registry • Can be used in RegOpenKeyEx() or RegCreateKeyEx() • KEY_WoW64_64KEY – explicitly opens a 64-bit key from either a 32-bit or 64-bit application • KEY_WoW64_32KEY – explicitly opens a 64-bit key from either a 32-bit or 64-bit application • %windir%\syswow64\regedit.exe –m launches the 32-bit registry editor • What else is missing? • Registry Reflection
WoW64 Registry Reflection • Enables 64-bit and 32-bit application Inter-Opthrough COM • Mirrors certain registry keys and values between the 32-bit and 64-bit registry views • Happens in real-time • Reflected keys are • HKEY_LOCAL_MACHINE\Software\Classes • HKEY_LOCAL_MACHINE\Software\Ole • HKEY_LOCAL_MACHINE\Software\Rpc • HKEY_LOCAL_MACHINE\Software\COM3 • HKEY_LOCAL_MACHINE\Software\EventSystem • Ownership-based reflection • Helps intelligent reflection of COM servers
WoW64 Registry Reflection • Rules for HKEY_CLASSES_ROOT\CLSID reflection • InProcServer32 and InProcHandler32 arenot reflected • LocalServer32 is reflected • Delete reflected keys only if written byWoW64 reflector
WoW64 File System Redirection • Redirects file-level access from %windir%\system32 to %windir%\syswow64 • Many 32-bit Windows applications hard-codes %windir%\system32 • 32-bit Windows applications which try to open or create a file underneath %windir%\system32\... are automatically redirected to %windir%\syswow64\... file • Helps side-by-side system files installation and compatibility • Some directories are exempted from redirection • Don’t contain bitness-sensitive data • %windir%\system32\spool • %windir%\system32\catroot • %windir%\system32\catroot2 • %windir%\system32\drivers\etc
WoW64 File System Redirection • Turned ON by default for allWoW64 applications • Can be controlled through Wow64EnableWow64FsRedirection() • Exists on platforms starting with Windows Server 2003 • Fails on non 64-bit platforms • Helpful for many 32-bit applications, e.g., Virus Scanners BOOLEAN Wow64EnableWow64FsRedirection ( IN BOOLEAN Wow64FsEnableRedirection );
WoW64 File System Redirection { HANDLE File; WIN32_FIND_DATA FindData; BOOLEAN bRet; // // Disable WoW64 file system redirection // bRet =Wow64EnableWow64FsRedirection(FALSE); File = FindFirstFileA ("%windir%\\system32\\*.*", &FindData); do { . . . } while (FindNextFileA (File, &FindData) != 0); FindClose (File); // // Enable WoW64 file-system redirection // if (bRet == TRUE) { Wow64EnableWow64FsRedirection(TRUE); } }
32-Bit I/O On 64-Bit Windows • Kernel is native on 64-bit Windows and so are all kernel drivers • 32-bit kernel device drivers won’t run on 64-bit Windows • Need to be ported • WoW64 can’t handle I/O buffer for NtDeviceIoControlFile() • I/O buffer is only known to the device driver • Two or more device drivers can use the same IOCTL with different I/O buffers interpretation • 64-bit device drivers needs to support I/O requests from WoW64 applications
32-Bit I/O On 64-Bit Windows • So if the 64-bit kernel device driver… • Receives IOCTLs from user mode applications • And it supports 32-bit and 64-bit applications • And the I/O structures are pointer-dependent or requirea specific alignment • Then the 64-bit kernel device driver needs tosupport WoW64 • What does a kernel device driver need to do tosupport WoW64? • In your IRP_MJ_DEVICE_CONTROL handler, detect if the I/O Request Packet (IRP) originated from a WoW64 application • Use IoIs32bitProcess() exported from ntoskrnl • Convert 32-bit structures into 64-bit
32-Bit I/O On 64-Bit Windows BOOLEAN IoIs32bitProcess( IN PIRP Irp OPTIONAL ) /*+++ Routine Description: This API returns TRUE if the process that originated the IRP is running a 32 bit x86 application. If there is no IRP then a NULL can be passed to the API and that implies that the current process context is used to test if it’s running a 32 bit x86 application. Its assumed a NULL will be passed by drivers executing in the fast io path. Arguments: IRP OPTIONAL. Return Value: TRUE if the process is WoW64, otherwise FALSE. --*/
32-Bit I/O On 64-Bit Windows • Real sample code from fastfat.sys driver… • MOVE_FILE_DATA is pointer-dependent • structure size is different when compiled by a 32-bit or a 64-bit application typedef struct { HANDLEFileHandle; LARGE_INTEGER StartingVcn; LARGE_INTEGER StartingLcn; ULONG ClusterCount; } MOVE_FILE_DATA, *PMOVE_FILE_DATA; NTSTATUS FatUserFsCtrl ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) { . . PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); switch (IrpSp->Parameters.FileSystemControl.FsControlCode) { . . caseFSCTL_MOVE_FILE: Status = FatMoveFile( IrpContext, Irp ); break; }
32-Bit I/O On 64-Bit Windows • Before supporting WoW64… NTSTATUS FatMoveFile ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) { . . InputBuffer = (PMOVE_FILE_DATA) Irp->AssociatedIrp.SystemBuffer; // // Do a quick check on the input buffer. // if (InputBuffer == NULL ||(InputBufferLength < sizeof(MOVE_FILE_DATA)) { FatCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL); return STATUS_BUFFER_TOO_SMALL; } TargetCluster =InputBuffer->StartingLcn.LowPart+ 2; . . }
32-Bit I/O On 64-Bit Windows • After supporting WoW64… typeset struct { HANDLE FileHandle; LARGE_INTEGER StartingVcn; LARGE_INTEGER StartingLcn; ULONG ClusterCount; } MOVE_FILE_DATA, *PMOVE_FILE_DATA; #if defined(_WIN64) // // 32/64 Bit thunking support // structure // typedef struct _MOVE_FILE_DATA32 { UINT32 FileHandle; LARGE_INTEGER StartingVcn; LARGE_INTEGER StartingLcn; ULONG ClusterCount; } MOVE_FILE_DATA32, *PMOVE_FILE_DATA32; #endif NTSTATUS FatMoveFile ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) { #if defined(_WIN64) MOVE_FILE_DATA LocalMoveFileData; PMOVE_FILE_DATA32 MoveFileData32; #endif InputBuffer = (PMOVE_FILE_DATA)Irp->AssociatedIrp.SystemBuffer; #if defined(_WIN64) if (IoIs32bitProcess( Irp )) { if (InputBuffer == NULL || InputBufferLength < sizeof(MOVE_FILE_DATA32)) { FatCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL ); return STATUS_BUFFER_TOO_SMALL; } MoveFileData32 = (PMOVE_FILE_DATA32) InputBuffer; LocalMoveFileData.FileHandle = (HANDLE) LongToHandle( MoveFileData32- >FileHandle ); LocalMoveFileData.StartingVcn = MoveFileData32->StartingVcn; LocalMoveFileData.StartingLcn = MoveFileData32->StartingLcn; LocalMoveFileData.ClusterCount = MoveFileData32->ClusterCount; InputBuffer = &LocalMoveFileData; } else { #endif if (InputBuffer == NULL || InputBufferLength < sizeof(MOVE_FILE_DATA)) { FatCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL ); return STATUS_BUFFER_TOO_SMALL; } #if defined(_WIN64) } #endif TargetCluster = InputBuffer->StartingLcn.LowPart + 2;
32/64 Inter-Op Issues • Pointer data type storage is 64-bit (8 bytes) on 64-bit Windows systems while it is 32-bits (4 bytes) on 32-bit Windows systems • Alignment is different as well • Example • Client/Server application set communicating using shared memory • Client is 32-bit running on 64-bit Windows and server is 64-bit or vice versa • Shared structures are pointer-dependent • Two solutions • 32-bit Client writes compatible 64-bit structures • 64-bit Server doesn’t need to be WoW64 aware • 64-bit Server reads 32-bit and 64-bit structures • 64-bit Server is WoW64 aware • 32-bit Client may need to change if source request is not known to the 64-bit server
32/64 Inter-Op Issues • Solution #1 – Changing 32-bit client code • 32-bit client checks to see if it is running inside WoW64 • IsWow64Process() detects the process type • Writes the appropriate structure based on which OS it is running on typedef struct _SERVER_REQUEST { HANDLE ThreadHandle; PVOID DataBaseAddress; ULONG Count; } SERVER_REQUEST, *PSERVER_REQUEST; #if !defined(_WIN64) typedef struct _SERVER_REQUEST64 { LONGLONG ThreadHandle; ULONGLONG DataBaseAddress; ULONG Count; } SERVER_REQUEST64, *PSERVER_REQUEST64; #endif BOOLEAN SendServerRequest (PSERVER_REQUEST Rq) { #if !defined(_WIN64) SERVER_REQUEST64 Rq64; BOOL WoW64Process; #endif PVOID p = (PVOID) Rq; ULONG size = sizeof (SERVER_REQUEST); #if !defined(_WIN64) if ((IsWow64Process (GetCurrentProcess(), &WoW64Process) == TRUE) && (WoW64Process == TRUE)) { Rq64.ThreadHandle = (LONGLONG)Rq->ThreadHandle; Rq64.DataBaseAddress = (ULONGLONG)(ULONG) Rq->DataBaseAddress; Rq64.Count = Rq->Count; p = (PVOID) &Rq64; size = sizeof (SERVER_REQUEST64); } #endif return WriteRequestToSharedMem (p, size); }
32/64 Inter-Op Issues • Solution #2 – Changing 64-bit server code • 64-bit server checks the source process of the request message • 64-bit server reads structure based on process type typedef struct _SERVER_REQUEST { HANDLE ThreadHandle; PVOID DataBaseAddress; ULONG Count; } SERVER_REQUEST, *PSERVER_REQUEST; #if defined(_WIN64) typedef struct _SERVER_REQUEST32 { LONG ThreadHandle; ULONG DataBaseAddress; ULONG Count; } SERVER_REQUEST32, *PSERVER_REQUEST32; #endif BOOLEAN ProcessServerRequest (PSERVER_REQUEST Rq, HANDLE SourceProcess) { #if defined(_WIN64) PSERVER_REQUEST32 Rq32; BOOL WoW64Process; #endif PVOID p; HANDLE h; ULONG count; #ifdefined(_WIN64) if ((IsWow64Process (SourceProcess, &WoW64Process) == TRUE) && (WoW64Process == TRUE)) { Rq32 = (PSERVER_REQUEST32) Rq; h = LongToHandle (Rq32->ThreadHandle); p = UlongToPtr (Rq32->DataBaseAddress); count = Rq32->Count; } else { #endif DataBaseAddress = Rq->DataBaseAddress; count = Rq->Count; h = Rq->ThreadHandle; #if defined(_WIN64) } #endif return ReadClientData (SourceProcess, DataBaseAddress, count, h); }
Don’t pass addresses above 2GB (or 4GB) to a WoW64 application How to convert data types? 32/64 Inter-Op Issues
WoW64 Platform-Specific Support • GetNativeSystemInfo() retreives information about the native system • No 16-bit support on 64-bit Windows • Win32 APIs for 16-bit support are stubbed out to fail • 32-bit kernel drivers won’t run on 64-bit Windows • Needs to be ported and support WoW64 • WoW64 emulates Win32 applications running on x86 hardware • Target 64-bit platform may not support specific features • Different levels of WoW64 support
WoW64 Debugging • GetThreadContext() and SetThreadContext() works if the target process of the same type • Use user-mode 32-bit debugger to debug WoW64 applications • Debug as if you are running on a native 32-bit Windows OS • Visual C++ 6.0 • User mode debuggers (e.g. ntsd.exe) • Or any other 32-bit debugger package • View only 32-bit loaded modules • Can not be used to debug native 64-bit applications • Use user-mode 64-bit debugger to debug inside WoW64’s 64-bit code • WoW64 debugger extensions – comes with Microsoft debugging tools • Allows to switch between 32-bit and 64-bit modes using !sw command • View all loaded modules (32-bit and 64-bit) • Can debug WoW64 as well as native 64-bit applications
Server SP1/AMD64 • Support for • Running 32-bit ASP pages • .NET Framework 1.1 • Managed code support • Run managed ASP.NET • Visual Studio .NET 2003
Resources • Links • http://msdn.microsoft.com • WoW64 implementation details • http://msdn.microsoft.com/library/en-us/win64/win64/wow64_implementation_details.asp?frame=true • WoW64 debugging • http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win64/win64/debugging_wow64.asp • Porting your driver to Win64 • http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/other_53mv.asp • Debugging tools • http://www.microsoft.com/whdc/ddk/debugging/
Community Resources • Community Sites • http://www.microsoft.com/communities/default.mspx • List of Newsgroups • http://communities2.microsoft.com/communities/newsgroups/en-us/default.aspx • Attend a free chat or webcast • http://www.microsoft.com/communities/chats/default.mspx • http://www.microsoft.com/seminar/events/webcasts/default.mspx • Locate a local user group(s) • http://www.microsoft.com/communities/usergroups/default.mspx • Non-Microsoft Community Sites • http://www.microsoft.com/communities/related/default.mspx