{"id":191,"date":"2007-11-01T07:00:38","date_gmt":"2007-11-01T12:00:38","guid":{"rendered":"http:\/\/www.nynaeve.net\/?p=191"},"modified":"2019-12-13T17:45:33","modified_gmt":"2019-12-13T22:45:33","slug":"how-does-one-retrieve-the-32-bit-context-of-a-wow64-program-from-a-64-bit-process-on-windows-server-2003-x64","status":"publish","type":"post","link":"http:\/\/www.nynaeve.net\/?p=191","title":{"rendered":"How does one retrieve the 32-bit context of a Wow64 program from a 64-bit process on Windows Server 2003 x64?"},"content":{"rendered":"<p>Recently, <a title=\"Jimmy\" href=\"http:\/\/www.nynaeve.net\/?p=129#comment-19324\">Jimmy<\/a> asked me what the recommended way to retrieve the 32-bit context of a Wow64 application on Windows XP x64 \/ Windows Server 2003 x64 was.<\/p>\n<p>I originally responded that the best way to do this was to use <a title=\"Wow64GetThreadContext\" href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms681665.aspx\">Wow64GetThreadContext<\/a>, but Jimmy mentioned that this doesn&#8217;t exist on Windows XP x64 \/ Windows Server 2003 x64.  Sure enough, I checked and it&#8217;s really not there, which is rather a bummer if one is trying to implement a 64-bit debugger process capable of debugging 32-bit processes on pre-Vista operating systems.<\/p>\n<p>Normally, I don&#8217;t typically recommend using undocumented implementation details in production code, but in this case, there seems to be little choice as there&#8217;s no documented mechanism to perform this operation prior to Vista.  Because Vista introduces a documented way to perform this task, going an undocumented route is at least <em>slightly<\/em> less questionable, as there&#8217;s an upper bound on what operating systems need to be supported, and major changes to the implementation of things on downlevel operating systems are rarer than with new operating system releases.<\/p>\n<p>Clearly, this is not always the case; Windows XP Service Pack 2 changed an enormous amount of things, for instance.  However, as a general rule, service packs tend to be relatively conservative with this sort of thing.  That&#8217;s not that one has <em>carte blanche<\/em> with using undocumented implementation details on downlevel platforms, but perhaps one can sleep a bit easier at night knowing that things are less likely to break than in the next Windows release.<\/p>\n<p>I had <a title=\"Beware GetThreadContext on Wow64\" href=\"http:\/\/www.nynaeve.net\/?p=129\">previously mentioned<\/a> that the Wow64 layer takes a rather unexpected approach to how to implement <em>GetThreadContext<\/em> and <em>SetThreadContext<\/em>.  While I mentioned at a high level what was going on, I didn&#8217;t really go into the details all that much.<\/p>\n<p>The basic implementation of these routines is to determine whether the thread is running in 64-bit mode or not (determined by examining the <em>SegCs<\/em> value of the 64-bit context record for the thread as returned by <em>NtGetContextThread<\/em>).  If the thread is running in 64-bit mode, and the thread is a Wow64 thread, then an assumption can be made that the thread is in the middle of a callout to the Wow64 layer (say, a system call).<\/p>\n<p>In this case, the 32-bit context is saved at a well-known location by the process that translates from running in 32-bit mode to running in 64-bit mode for system calls and other voluntary, user mode &#8220;32-bit break out&#8221; events.  Specifically, the Wow64 layer repurposes the second TLS slot of each 64-bit thread (that is, <em>Teb->TlsSlots[ 1 ]<\/em>) to point to a structure of the following layout:<\/p>\n<pre>\r\ntypedef struct _WOW64_THREAD_INFO\r\n{\r\n   ULONG UnknownPrefix;\r\n   WOW64_CONTEXT Wow64Context;\r\n   ULONG UnknownSuffix;\r\n} WOW64_THREAD_INFO, * PWOW64_THREAD_INFO;\r\n<\/pre>\n<p>(<em>The real structure name is not known.<\/em>.)<\/p>\n<p>Normally, system components <a title=\"Thread Local Storage, part 8: Wrap-up\" href=\"http:\/\/www.nynaeve.net\/?p=190\">do not use the TLS array<\/a>, but the Wow64 layer is an exception.  Because there is not normally any third party 64-bit code running in a Wow64 process, the Wow64 layer is free to do what it wants with the <em>TlsSlots<\/em> array of the 64-bit TEB for a Wow64 thread.  (Each Wow64 thread has its own, separate 32-bit TEB, so this does not interfere with the operation of TLS by the 32-bit program that is currently executing.)<\/p>\n<p>In the case where the requested Wow64 is in a 64-bit Wow64 callout, all one needs to do is to retrieve the base address of the 64-bit TEB of the thread in question, read the second entry in the <em>TlsSlots<\/em> array, and then read the <em>WOW64_CONTEXT<\/em> structure out of the memory block referred to by the second 64-bit TLS slot.<\/p>\n<p>The other case that is significant is that where the Wow64 thread is running 32-bit code and is not in a Wow64 callout.  In this case, because Wow64 runs x86 code natively, one simply needs to capture the 64-bit context of the desired thread and truncate all of the 64-bit registers to their 32-bit counterparts.<\/p>\n<p>Setting the context of a Wow64 thread works exactly like retrieving the context of a Wow64 thread, except in reverse; one either modifies the 64-bit thread context if the thread is running 32-bit code, or one modifies the saved context record based off of the 64-bit TEB of the desired thread (which will be restored when the thread resumes execution).<\/p>\n<p>I have posted a <a title=\"Wow64GetThreadContext implementation\" href=\"http:\/\/www.nynaeve.net\/Code\/GetThreadWow64Context.cpp\">basic implementation<\/a> of a version of <em>Wow64&shy;GetThreadContext<\/em> that operates on pre-Windows-Vista platforms.  Note that this implementation is incomplete; it does not translate floating point registers, nor does it only act on the subset of registers requested by the caller in <em>CONTEXT::ContextFlags<\/em>.  The provided code also does not implement <em>Wow64&shy;SetThreadContext<\/em>; implementing the &#8220;set&#8221; operation and extending the &#8220;get&#8221; operation to fully conform to <em>GetThreadContext<\/em> semantics are left as an exercise for the reader.<\/p>\n<p>This code will operate on Vista x64 as well, although I would strongly recommend using the <a title=\"Wow64GetThreadContext\" href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms681665.aspx\">documented API<\/a> on Vista and later platforms instead.<\/p>\n<p><em>Note that the operation of Wow64 on IA64 platforms is completely different from that on x64.  This information does not apply in any way to the IA64 version of Wow64.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, Jimmy asked me what the recommended way to retrieve the 32-bit context of a Wow64 application on Windows XP x64 \/ Windows Server 2003 x64 was. I originally responded that the best way to do this was to use Wow64GetThreadContext, but Jimmy mentioned that this doesn&#8217;t exist on Windows XP x64 \/ Windows Server [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[10,4,5],"tags":[17,19,20],"_links":{"self":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/191"}],"collection":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=191"}],"version-history":[{"count":1,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/191\/revisions"}],"predecessor-version":[{"id":531,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/191\/revisions\/531"}],"wp:attachment":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=191"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=191"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=191"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}