﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Game Rambler-随笔分类-System Kernel</title><link>http://www.cppblog.com/Leaf/category/16921.html</link><description>rambling among the forest of games!</description><language>zh-cn</language><lastBuildDate>Fri, 20 May 2011 06:30:10 GMT</lastBuildDate><pubDate>Fri, 20 May 2011 06:30:10 GMT</pubDate><ttl>60</ttl><item><title>Nt vs. Zw - Clearing Confusion On The Native API </title><link>http://www.cppblog.com/Leaf/archive/2011/05/20/146815.html</link><dc:creator>Rambler</dc:creator><author>Rambler</author><pubDate>Fri, 20 May 2011 06:26:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2011/05/20/146815.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/146815.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2011/05/20/146815.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/146815.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/146815.html</trackback:ping><description><![CDATA[<p style="text-align: justify" class="MsoNormal">The NT native API is nothing new. It&#8217;s been discussed ad nauseum, it&#8217;s been exploited by umpteen different utilities, and portions of it have even migrated into the realm of the fully documented and supported in the DDK. Come to think of it, why am I even writing about this then? I think I will just pop in my <em>Kung Faux </em>DVD and watch the Ill Master take care of business&#8230;Oh yeah, now I remember why I started writing this: Believe it or not, people are <em>still</em> confused about certain aspects of the native API. Common questions include:</p>
<p>&nbsp;</p>
<ul><li>Why are there two flavors, NtXxx and ZwXxx?</li><li>Why do my calls to ZwXxx sometimes fail, but sometimes work?</li><li>What does the Zw stand for? Was the name of the original NT developer really Zimbanza Woobie!?</li></ul>
<p align="justify"></p>
<p align="justify">OK, well, maybe people don&#8217;t really ask that last one very often. But for those that do, Zw is entirely random and the developers chose it specifically because it could never mean anything. The other questions do often come up on the NTDEV and NTFSD mailing lists though (see http://www.osronline.com/lists for more info on the NTDEV and NTFSD peer help lists), so it is about time the record was set straight. In order to do this we are going to do a bit of disassembly. All listings will be from an XP SP1 Free build. Also, note that we&#8217;ve got sample driver code to accompany this article that shows you how to use the native system services from Kernel Mode. See the description (and URL) of the sample code provided at the end of this article.</p>
<p align="justify"></p>
<p align="justify">This article assumes that the reader already understands that there <em>is</em> a native API and understands how the native API relates to the other subsystems in Windows. Enough information already exists on this out there that it is not worth repeating in this article. </p>
<p align="justify"></p><strong>
<p align="justify">Vanilla or Chocolate</p></strong>
<p align="justify">First, let&#8217;s do a bit of math that even I can handle. We have two sets of APIs, NtXxx and ZwXxx, and two modes to call them from, User and Kernel. This means that we have four different scenarios under which we can call these routines. Using <strong>XxReadFile</strong> as the example, we have:</p>
<p align="justify"></p>
<ul><li>
<div align="justify">User Mode application calls <strong>NtReadFile</div></strong></li><li>
<div align="justify">User Mode application calls <strong>ZwReadFile</div></strong></li><li>
<div align="justify">Kernel Mode driver calls <strong>NtReadFile</div></strong></li><li>
<div align="justify">Kernel Mode driver calls <strong>ZwReadFile</div></li></ul></strong>
<p align="justify"></p>
<p align="justify">What exactly are the differences in these scenarios? Let us start by talking about the land where no driver writer feels safe, User Mode. </p>
<p align="justify"></p><strong>
<p align="justify">Calling From User Mode</p></strong>
<p align="justify">As you (probably) know, User Mode applications link with <strong>NTDLL.LIB</strong>. Sticking with our example of <strong>XxReadFile</strong>, let&#8217;s compare the disassembly of the <strong>NtReadFile</strong> and <strong>ZwReadFile</strong> routines within <strong>NTDLL</strong>:</p>
<p align="justify"></p><font size="1" face="Lucida Console">
<p style="text-justify: inter-ideograph; text-align: justify; margin: 0in 0in 0pt; mso-layout-grid-align: none" class="MsoNormal"><span style="font-family: 'Lucida Console';background: white; color: black; font-size: 8pt; mso-highlight: white"><font size="1">0: kd&gt; u ntdll!NtReadFile<br />ntdll!NtReadFile:<br />77f761e8 b8b7000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax,0xb7<br />77f761ed ba0003fe7f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edx,0x7ffe0300<br />77f761f2 ffd2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; edx<br />77f761f4 c22400&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp;&nbsp;&nbsp; 0x24</font></span></p>
<p style="text-justify: inter-ideograph; text-align: justify; margin: 0in 0in 0pt; mso-layout-grid-align: none" class="MsoNormal"><span style="font-family: 'Lucida Console';background: white; color: black; font-size: 8pt; mso-highlight: white"><font size="2" face="Times New Roman"><br /></font></span>&nbsp;</p>
<p style="text-justify: inter-ideograph; text-align: justify; margin: 0in 0in 0pt; mso-layout-grid-align: none" class="MsoNormal"><span style="font-family: 'Lucida Console';background: white; color: black; font-size: 8pt; mso-highlight: white"><o:p></o:p></span></p>
<p align="justify"></font><font size="2">That looks to me to be a stub that calls another routine and returns. Further inspection will definitely be necessary, but let&#8217;s just check out <strong>ZwReadFile</strong> before we move on.</p>
<p align="justify"></p></font><font size="2" face="Times New Roman">
<p style="margin: 0in 0in 0pt"><span style="font-family: 'Lucida Console'; font-size: 7.5pt"><font size="1">0: kd&gt; u ntdll!ZwReadFile<br />ntdll!NtReadFile:<br />77f761e8 b8b7000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax,0xb7<br />77f761ed ba0003fe7f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edx,0x7ffe0300<br />77f761f2 ffd2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; edx<br />77f761f4 c22400&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp;&nbsp;&nbsp; 0x24<br /></font><br /></span></p></font><font size="2">
<p align="justify"></p>
<p align="justify">Well look at that! They both point to the exact same place, which means that from a User Mode program it does not matter which routine you call because you are going to end up in the same place anyway. If you pick any other system service call you will notice that they all have this exact format, so our example will apply to any API you choose. The good news is that this article just got a bit shorter and I&#8217;ll be chillin&#8217; with the Ill Master in less time than I thought. </p>
<p align="justify"></p>
<p align="justify">Now let&#8217;s see what exactly is at address <strong>0x7ffe0300</strong>, which is where we jump when we make these calls (and, as mentioned previously, where we jump when we make <em>any</em> native API call from User Mode). </p>
<p align="justify"></p></font><font size="2" face="Times New Roman">
<p align="justify"><font size="1" face="Lucida Console">0: kd&gt; ln 0x7ffe0300<br />(7ffe0300)&nbsp;&nbsp; SharedUserData!SystemCallStub&nbsp;&nbsp; <br />Exact matches:<br />&nbsp;&nbsp;&nbsp; SharedUserData!SystemCallStub</font></p>
<p align="justify"><font size="1" face="Lucida Console">0: kd&gt; u SharedUserData!SystemCallStub<br />SharedUserData!SystemCallStub:<br />7ffe0300 8bd4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edx,esp<br />7ffe0302 0f34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sysenter<br />7ffe0304 c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret</font><br /></p></font><font size="1" face="Lucida Console">
<p align="justify"></p></font><font size="2">
<p align="justify"></p>
<p align="justify">Now how&#8217;s that for a straight-forward routine: Something (turns out it&#8217;s the code that represents which system service was called) gets put into EAX by the caller, then this routine puts a pointer to the top of the User Mode stack into EDX. Ohh, <strong>SYSENTER</strong>, uhm, ah, of course&#8230;Must be a new instruction. Let me see, that was added in&#8230;1997?? Forging ever onward, let us check the Intel documentation for <strong>SYSENTER</strong>. It says here that the <strong>SYSENTER</strong> instruction switches the current thread into Kernel Mode and executes the routine pointed to by the <strong>SYSENTER_EIP_MSR</strong>, which is MSR 0x176. </p>
<p align="justify"></p>
<p align="justify">This is a good time to point out why hooking INT 2E is a bad idea and why old INT 2E hooks will not work. On systems that support <strong>SYSENTER</strong>, INT 2E is simply not used anymore. Your hook is useless if no one is ever going to call it!</p>
<p align="justify"></p>
<p align="justify">Going back to WinDBG, let us execute the <strong>rdmsr</strong> command and see what is in the <strong>SYSENTER_EIP_MSR</strong>:</p>
<p align="justify"></p></font><font size="1" face="Lucida Console">
<p align="justify"><font size="2" face="Times New Roman"><font size="1" face="Lucida Console">0: kd&gt; rdmsr 176<br />msr[176] = 00000000:8053a270</font><br /></font></p>
<p align="justify"></p></font><font size="2">
<p align="justify"></p>
<p align="justify">Very interesting. Let&#8217;s see what that address is:</p>
<p align="justify"></p></font><font size="1" face="Lucida Console">
<p align="justify"><font size="2" face="Times New Roman"><font size="1" face="Lucida Console">0: kd&gt; ln 8053a270<br />(8053a270)&nbsp;&nbsp; nt!KiFastCallEntry&nbsp;&nbsp; |&nbsp; (8053a2fb)&nbsp;&nbsp; nt!KiSystemService<br />Exact matches:<br />&nbsp;&nbsp;&nbsp; nt!KiFastCallEntry</font><br /></font></p>
<p align="justify"></p></font><font size="2">
<p align="justify"></p>
<p align="justify">I will spare all of you the disassembly of <strong>KiFastCallEntry</strong>. It is an interesting read so I suggest it if you are curious, but all the code is going to do is build a trap frame so that when we exit Kernel Mode we can continue executing from where we left off. I will show the very last line of the function though: </p>
<p align="justify"></p></font><font size="1" face="Lucida Console">
<p align="justify">053a2f9 eb5c jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!KiSystemService+0x5c (8053a357)</p></font><font size="2">
<p align="justify"></p>
<p align="justify">We can see here that <strong>KiFastCallEntry</strong> does not actually return, it just does an unconditional jump to some offset into <strong>KiSystemService</strong>. Again sparing the reader large amounts of disassembly, the code in <strong>KiSystemService</strong> eventually takes the service number that was put into EAX on the first line of the call to <strong>XxReadFile</strong> and looks up its entry in the system service table, <strong>KiServiceTable</strong>. Each entry in this table is a pointer to a native API, also known as "system service", routine. Before calling the "system service" routine, the system service dispatch code copies the parameters that are being passed to the system service from the top of the User stack to the top of the Kernel stack. Ah! Guess that&#8217;s why a pointer to the top of the stack is saved into EDX before executing the SYSENTER. </p>
<p align="justify"></p>
<p align="justify">Using the debugger extension DLL accompanying this article, we can see that index 0xb7 points to the kernel version of <strong>NtReadFile</strong>:</p>
<p align="justify"></p></font><font size="1" face="Lucida Console">
<p align="justify">0: kd&gt; !osrexts.sst<br />0: 0x805912c2&nbsp; (nt!NtAcceptConnectPort)<br />1: 0x805d87b0&nbsp; (nt!NtAccessCheck)<br />2: 0x805dc3e4&nbsp; (nt!NtAccessCheckAndAuditAlarm)<br />...<br />b7: 0x8056b2ec&nbsp; (nt!NtReadFile)<br />...<br /></p></font><font size="2">
<p align="justify"></p>
<p align="justify">And, if we look at the address of nt!NtReadFile (address 0x8056b2ec), we see:</p>
<p align="justify"></p></font>
<p align="justify"><font size="1" face="Lucida Console">0: kd&gt; u nt!NtReadFile<br />nt!NtReadFile:<br />8056b2ec 6a58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0x58<br />8056b2ee 6858044e80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0x804e0458<br />8056b2f3 e8e09ffcff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; nt!_SEH_prolog (805352d8)<br />8056b2f8 33ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; edi,edi<br />8056b2fa 897de4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp-0x1c],edi<br />8056b2fd 897de0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp-0x20],edi<br />8056b300 897dd8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp-0x28],edi<br />8056b303 897ddc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp-0x24],edi<br />8056b306 64a124010000&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax,fs:[00000124]<br />8056b30c 8945d4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp-0x2c],eax<br />8056b30f 8a8040010000&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; al,[eax+0x140]<br />8056b315 8845d0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp-0x30],al<br />8056b318 57&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edi<br />8056b319 8d45cc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; eax,[ebp-0x34]<br />8056b31c 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />8056b31d ff75d0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; dword ptr [ebp-0x30]<br /></font></p>
<p align="justify"><font size="1" face="Lucida Console"></font></p><font size="2">
<p align="justify"></p>
<p align="justify">Ah, Finally! It looks like the function that actually implements the read file system service.</p>
<p align="justify"></p>
<p align="justify">So, to summarize the flow of a native API call from User Mode</p>
<p align="justify"></p>
<p>User Mode program calls either <strong>NtXxx</strong> or <strong>ZwXxx</strong>, both of which point to the same location</p>
<p>All native API calls from User Mode have a body that simply loads an index into EAX, executes <strong>SystemCallStub</strong>, and returns</p><strong>
<p>SystemCallStub</strong> saves a pointer to the top of the User Mode stack into EDX and executes a <strong>SYSENTER</strong> instruction</p><strong>
<p>SYSENTER</strong> disables interrupts, switches the thread into Kernel Mode and executes the instruction located in the <strong>SYSENTER_EIP_MSR</strong> (which on XP SP1 is <strong>KiFastCallEntry</strong>)</p><strong>
<p>KiFastCallEntry</strong> builds a trap frame so it knows where to go when returning back to User Mode, enables interrupts, and jumps into <strong>KiSystemService</p>
<p>KiSystemService</strong>, amongst doing other things, copies the parameters from the User stack (pointed to by EDX) and takes the value previously stored in EAX and executes the function located at <strong>KiServiceTable</strong>[EAX]</p>
<p align="justify">The native API now executes in Kernel Mode with the previous mode of the thread set to User Mode. This indicates the caller came from User Mode<em>. If you are going to remember one thing about this exercise, remember this!</em> We&#8217;ll talk about it much more later in this article.</p>
<p align="justify"></p>
<p align="justify">Now that we have gone through a gross amount of detail for the User Mode portion, we should be able to zip right through the Kernel Mode variants. </p>
<p align="justify"></p><strong>
<p align="justify">Calling From Kernel Mode</p></strong>
<p align="justify">As you (should) know, Kernel Mode components link with <strong>NTOSKRNL.LIB</strong>. Let&#8217;s continue to use <strong>XxReadFile</strong> and see what the two variants look like from the kernel side of things. First, let&#8217;s try NtReadFile:</p>
<p align="justify"></p></font>
<p align="justify"><font size="1" face="Lucida Console">0: kd&gt; u nt!NtReadFile<br />nt!NtReadFile:<br />8056b2ec 6a58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0x58<br />8056b2ee 6858044e80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0x804e0458<br />8056b2f3 e8e09ffcff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; nt!_SEH_prolog (805352d8)<br />8056b2f8 33ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; edi,edi<br />...<br /></font></p>
<p align="justify"><font size="1" face="Lucida Console"></font></p><font size="2">
<p align="justify"></p>
<p align="justify">Well, <em>this</em> looks familiar! It&#8217;s the function that implements NtReadFile that was eventually called from User Mode (because it is where the system service table points to). Therefore, notice that if we call NtReadFile from a driver, we just execute the function, bypassing any common system service dispatcher type of entry point. </p>
<p align="justify"></p>
<p align="justify">Going on what I have seen before in User Mode, where NtXxxx and ZwXxxx were identical, when I disassemble <strong>nt!ZwReadFile</strong> I&#8217;d probably expect to see exactly what I saw in <strong>nt!NtReadFile</strong>. Let&#8217;s check:</p>
<p align="justify"></p></font>
<p align="justify"><font size="1" face="Lucida Console">0: kd&gt; u nt!ZwReadFile<br />nt!ZwReadFile:<br />80504d4c b8b7000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax,0xb7<br />80504d51 8d542404&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; edx,[esp+0x4]<br />80504d55 9c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pushfd<br />80504d56 6a08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0x8<br />80504d58 e89e550300&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; nt!KiSystemService (8053a2fb)<br />80504d5d c22400&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp;&nbsp;&nbsp; 0x24<br /></font></p>
<p align="justify"><font size="1" face="Lucida Console"></font></p><font size="2">
<p align="justify"></p>
<p align="justify">Blast! I guess I have got a bit longer before I can lounge. </p>
<p align="justify"></p>
<p align="justify">We see a familiar instruction in the beginning, move 0xb7 into EAX. Then we put a pointer to the parameters that appear on the Kernel stack into EDX, push the EFLAGS and a constant value onto the stack, and finally call <strong>KiSystemService</strong>!? That was the function that we wound-up calling from KiFastCallEntry when we did the SYSENTER from User Mode.</p>
<p align="justify"></p>
<p align="justify">So why aren&#8217;t we executing a <strong>SYSENTER</strong> here? Duh! Because we are already <em>in</em> Kernel Mode, so what is the point of entering it again? The most important thing that is going to happen when we go this route is that we are going to call the native API from Kernel Mode, execute in Kernel Mode, and in the course of going through <strong>KiSystemService</strong> our previous mode will be set to Kernel Mode. Note that this is definitely <em>not</em> the case if we just call the <strong>NtXxx</strong> version from Kernel Mode. In that case, our previous mode stays untouched and we go right to the function and start executing. </p>
<p align="justify"></p>
<p align="justify">So, to summarize the flow of a native API call from Kernel Mode:</p>
<p align="justify"></p>
<p>Case A:</p>
<ul><li>Kernel Mode component calls <strong>NtXxx</strong></li><li>
<div align="justify">This is a direct call to the function that implements the system service. The call <em>does not change previous mode.</div></li></ul></em>
<p align="justify"></p>
<p>Case B:</p>
<ul><li>Kernel Mode component calls ZwXxxx</li><li>This leads to a step that puts the system service code (index value) into EAX, and a pointer to the arguments that have already been pushed onto the (Kernel Mode) stack into EDX.</li><li>Then calls <strong>KiSystemService</strong>, which amongst doing other things, copies the parameters from the location pointed to by EDX and takes the value previously stored in EAX and executes the function located at <strong>KiServiceTable</strong>[EAX].</li><li>
<div align="justify">The native API now executes (still in Kernel Mode) <em>with the previous mode set to Kernel Mode</em>. This indicates the caller came from Kernel Mode.</div></li></ul><strong>
<p align="justify"></p></strong>
<p align="justify">So, it&#8217;s clear that calling NtXxx directly has less overhead, but calling ZwXxxx changes previous mode. So, what&#8217;s up with that? It seems like previous mode must be something pretty important.</p><strong>
<p align="justify"></p>
<p align="justify">Previous Mode</p></strong>
<p align="justify">Time to step back and figure out what all of this means. An important fact to know is that Kernel Mode components by default trust all other Kernel Mode components. Because system services are always processed in Kernel Mode, Windows keeps track of whether the request originated from User Mode or Kernel Mode to determine if the caller is to be implicitly trusted. The system uses the <strong>previous mode</strong> indicator to determine the mode from which a system service call came. When a call comes from User Mode, previous mode is set to User. When a system service processing routine needs to determine whether or not to implicitly trust its caller, it checks the value of previous mode. If previous mode is set to User, the system service processing routine knows the call came from User Mode and thus any parameters passed in to the function need to be validated before they can be used.</p>
<p align="justify"></p>
<p align="justify">This is why the previous mode being set is really the most important part about what we have talked about so far. No matter what a User Mode application does, the system treats its system service request as a User request, coming from User Mode, and goes out of its way to validate the request. All buffers are subject to validation, all access checks are performed, and absolutely no part of the request is implicitly trusted. However, a Kernel Mode request is not as scrutinized and it is assumed that the passed in parameters are valid. </p>
<p align="justify"></p>
<p align="justify">If a Kernel component calls the <strong>ZwXxx</strong> version of a native API, all is well. The previous mode is set to Kernel and the credentials of the Kernel are used. The system service processing routine that is called assumes that any parameters that are passed are valid, because the request came from a Kernel Mode component (and Kernel Mode components implicitly trust each other).</p>
<p align="justify"></p>
<p align="justify">The NtXxxx version of the native system service is the name of the function itself. Thus, when a Kernel Mode component calls the NtXxxx version of the system service, whatever is presently set into previous mode is unchanged. Thus, it is quite possible that the Kernel component could be running on an arbitrary User stack, with the requestor mode set to User. The system service will not know any better, attempt to validate the request parameters, possibly using the credentials of the arbitrary User Mode thread, and thus possibly fail the request. Another problem here is that one step in the validation process for a User Mode request is that all passed in buffers have either <strong>ProbeForRead </strong>or <strong>ProbeForWrite </strong>executed on them, depending on the buffer&#8217;s usage. These routines raise exceptions if executed on Kernel Mode addresses. Therefore, if you pass in Kernel Mode buffers with your request mode set to User, your calls into the native API return STATUS_ACCESS_VIOLATION.</p>
<p align="justify"></p>
<p align="justify">The moral of this bedtime story is that if you are in User Mode, use whatever variant you think makes your code look pretty. In Kernel Mode, use the <strong>ZwXxx</strong> routines and get your previous mode set properly, to Kernel Mode. </p>
<p align="justify"></p>
<p align="justify">If I keep this up I am going to be seriously late for my date with Queenie, but she is just going to have to wait because there is still more to cover. </p>
<p align="justify"></p><strong>
<p align="justify">I&#8217;ll Handle This</p></strong>
<p align="justify">All of the native API calls work with handle values, which index into one of two types of handle tables. A Handle either describes an entry in a table that is effectively a part of the EPROCESS structure (which means it describes an object that is specific to a particular process context) or it describes an entry in a global handle table (which means it describes an object that is visible to <em>all </em>process contexts). This makes for some interesting scenarios. </p>
<p align="justify"></p>
<p align="justify">Say you have an existing driver and you decide that being able to optionally log to a file would be a nice feature. First thing you do is setup two IOCTLs, one to enable the logging and the other to disable the logging. In the handler for the IOCTL, to enable logging, you have the driver call <strong>ZwCreateFile</strong> (remember to use the Zw versions!), which returns you a handle to use to write to the file. So far so good. </p>
<p align="justify"></p></font>
<p align="justify"><font size="1" face="Lucida Console">InitializeObjectAttributes(&amp;oa, &amp;logFileName, OBJ_CASE_INSENSITIVE,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;NULL, NULL);</font></p>
<p align="justify"><font size="1" face="Lucida Console">&nbsp;&nbsp;&nbsp; code = ZwCreateFile(&amp;devExt-&gt;LogFileHandle, GENERIC_WRITE,<br />&nbsp; &nbsp;&nbsp;&nbsp;&amp;oa, &amp;iosb, NULL, FILE_ATTRIBUTE_NORMAL,<br />&nbsp; &nbsp;&nbsp;&nbsp;0, FILE_OVERWRITE_IF,<br />&nbsp; &nbsp;&nbsp;&nbsp;FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,<br />&nbsp; &nbsp;&nbsp;&nbsp;NULL, 0);<br /></font></p>
<p align="justify"><font size="2">From here, you set up a flag in your device extension that indicates that you are logging to a file, and start to add calls to <strong>ZwWriteFile</strong> to all of your dispatch entry points. </p>
<p align="justify"></p></font><font size="2" face="Times New Roman">
<p align="justify">&nbsp;<font size="1" face="Lucida Console">&nbsp; &nbsp;&nbsp; if (devExt-&gt;LoggingEnabled) {</font></p>
<p align="justify"><font size="1" face="Lucida Console">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; code = ZwWriteFile(devExt-&gt;LogFileHandle, NULL, NULL, NULL,<br />&nbsp;&nbsp;&nbsp;&amp;iosb, (PVOID)logMessage,<br />&nbsp;&nbsp;&nbsp;logMessageLen),<br />&nbsp;&nbsp;&nbsp;NULL, NULL);<br />&nbsp;&nbsp; }<br /></font></p>
<p align="justify"></font><font size="2">You note that a restriction of <strong>ZwWriteFile</strong> is that you must call it at PASSIVE_LEVEL, so you setup work items to log your timer DPC and DpcForIsr. Then you enable logging on your device and something weird happens. All of your calls to <strong>ZwWriteFile</strong> in your dispatch entry points succeed, but the ones in your work items return STATUS_INVALID_ HANDLE! How can a handle switch back and forth between being valid and invalid when you have done nothing but open it and write to it?</p>
<p align="justify"></p>
<p align="justify">Remember that you created that handle in your dispatch entry point. Therefore, you could have been running in the process context of the <em>calling application</em> when you created that handle. In this case, your handle references an object in your User Mode application&#8217;s handle table, which is located via its EPROCESS. Your work items are running in the SYSTEM process context, so your call to <strong>ZwWriteFile</strong> is correctly failed with STATUS_INVALID_HANDLE. This is because the handle that you&#8217;re passing in is meaningless in the SYSTEM process&#8217; context. </p>
<p align="justify"></p>
<p align="justify">So what is the answer? Give up on Windows and start a revolution to bring back MULTICS? Luckily, it doesn&#8217;t have to come to that. There is already a built-in solution to this problem. All you need to do is specify OBJ_KERNEL_HANDLE as one of your object&#8217;s attributes and that handle will be good in any context you might end up calling it in. This flag is the cue to the Object Manager that you want the handle to go into the global handle table, making it visible in all process contexts. </p><strong>
<p align="justify"></p></strong></font>
<p align="justify"><font size="1" face="Lucida Console">InitializeObjectAttributes(&amp;oa, &amp;logFileName,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL, NULL);<br /></font></p>
<dir>
<dir><strong><font size="2">
<p align="justify"></p></dir></dir>
<p align="justify">Accompanying Samples</p></strong>
<p align="justify">To see some of what we&#8217;ve talked about in action, this article has an accompanying sample for you to experiment with. The sample driver creates a log file in the root directory of the C: drive in response to an IOCTL. At the beginning of the main C file is a compile time flag <strong>USER_HANDLE</strong>.<strong> </strong>If this flag is not set, then the driver creates the handle as a Kernel Mode handle by using <strong>OBJ_KERNEL_HANDLE</strong>. Otherwise, the driver creates a User Mode handle that is valid only in the application&#8217;s context. The file is then written to using both <strong>NtWriteFile </strong>and <strong>ZwWriteFile </strong>from various parts of the driver. Each call has a full explanation of what NTSTATUS values we expect to be returned and why for both the User and Kernel handle cases. The driver portion of the sample is a legacy driver (non-WDM compliant) and must be installed with a utility such as OSR&#8217;s Driver Loader.</p>
<p align="justify"></p>
<p align="justify">Also included in the samples download is a WinDBG extension DLL that locates the system service table and displays the system services located within it. To use it, simply put <strong>osrexts.dll </strong>into WinDBG&#8217;s extension DLL directory and execute <strong>!osrexts.sst </strong>in the command window.</p>
<p align="justify"></p><strong>
<p align="justify">In Summary</p></strong>
<p align="justify">I hope that this article has finally put to rest the most common problems that people experience with the native API and cleared up the <strong>NtXxx </strong>versus <strong>ZwXxx </strong>question once and for all. </p>
<p align="justify"></p>
<p align="justify">Now, where&#8217;s that DVD&#8230;</p></font>
<p><a class="twitter-share-button" href="http://twitter.com/share" data-count="none">Tweet</a> <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></p>
<p><!--print, email and comment links go here-->

<p><strong><font color="#585885" size="4" face="Arial, Helvetica, sans-serif">Related Articles</font></strong><font size="1" face="Arial, Helvetica, sans-serif"><br /><a href="http://www.osronline.com/article.cfm?article=91">Going Native - Using the NT API for File I/O</a> <br /><a href="http://www.osronline.com/article.cfm?article=471">OSR Press Comes Through Again: Classic NT Driver Book Now Available</a> <br /></font><!-- BEGIN: Determine if we should display the post comments link -->

<p><font color="#585885" size="1" face="Arial, Helvetica, sans-serif"><strong><font size="4">User Comments</font></strong><br /><font size="2" face="Arial, Helvetica, sans-serif">Rate this article and give us feedback. Do you find anything missing? Share your opinion with the community!<br /></font><a href="http://www.osronline.com/articleCommentPost.cfm?id=257#comments"><img border="0" align="absMiddle" src="http://www.osronline.com/images/default/template/addbutton.gif"  alt="" /> Post Your Comment</a><br /><br /><!-- increase varCounter beyond Len of string to exit loop --></font><font size="1" face="Arial, Helvetica, sans-serif"></font><font size="1" face="Arial, Helvetica, sans-serif"></font><font size="1" face="Arial, Helvetica, sans-serif"></font><!-- END: Determine if we should display the post comments link --><font size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"Nt vs. Zw - Clearing Confusion On The Native API"</strong> </font><br />Nice article!! 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><em><font class="tsTextListItalic" size="2">Rating:</font></em> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <br /></font><font size="1" face="Arial, Helvetica, sans-serif">03-Dec-09, Netmonk Paul</font> <br />
<hr align="left" size="1" width="250" />
<font size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"Native Mode vs. Native API"</strong> </font><br />I would like to know how to utilize these functions in Native Mode, I.E. like autochk does. I have tried using this example and use build to create a simple executable that will run from the BootExecute key of the session manager, like autochk, but i can't get it to build. 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><em><font class="tsTextListItalic" size="2">Rating:</font></em> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <br /></font><font size="1" face="Arial, Helvetica, sans-serif">02-Nov-05, Ketema Harris</font> <br />
<hr align="left" size="1" width="250" />
<font size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"AMD64?"</strong> </font><br />Excelent article. Do you have any idea how these things are implemented in XP x64? The KiServiceTable doesn't seem to store pointers to functions. Or, maybe i got it wrong... Thanks. 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><em><font class="tsTextListItalic" size="2">Rating:</font></em> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <br /></font><font size="1" face="Arial, Helvetica, sans-serif">21-Jul-05, Marius Negrutiu</font> <br />
<hr align="left" size="1" width="250" />
<font color="#800000" size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"In answer to the previous 2 comments"</strong> </font><br />Thanks to all for commenting... 
<p>In response to Ben Kial's post from 7 Jul 05, in which he says "only SOME of the kernel side NtXXX APIs are implemented in ntoskrnl.exe" 
<p>Sorry, but this is not correct. The functions might not be exported, but they are there. Specifically, I checked NtProtectVirtualMemory, and it is indeed in ntoskrnl.exe (it's part of the memory manager). 
<p>In response to Sean Park's comment from 8 Jul 05, in which he says "NtXxx functions expect user mode parameters... while ZwXxx functions are for kernel drivers." 
<p>Sorry, but this is not correct. The difference between the NT and ZW APIs is as stated in this article. This is not a topic about which we're GUESSING. We're giving you the definitively correct answers. 
<p>Peter 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><font size="1" face="Arial, Helvetica, sans-serif">08-Jul-05, Peter Viscarola</font> <br />
<hr align="left" size="1" width="250" />
<font size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"Not all NtXXX are in ntoskrnl.exe"</strong> </font><br />Very nice article! However, I found that only some of the kernel side NtXXX APIs are implemented in ntoskrnl.exe (or ntoskrnl.lib). For example, for API# 0x89 
<p>89: 0x80574045 (nt!NtProtectVirtualMemory) 
<p>it does not exit in ntoskrnl.exe. Does anybody know which .dll or .exe contain "nt!NtProtectVirtualMemory"? 
<p>Thanks, 
<p>Ben 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><em><font class="tsTextListItalic" size="2">Rating:</font></em> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <br /></font><font size="1" face="Arial, Helvetica, sans-serif">07-Jul-05, Ben Kial</font> <br />
<hr align="left" size="1" width="250" />
<font color="#800000" size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"RE: What exactly is an MSR?"</strong> </font><br />An MSR is a "Model-Specific Register". That is, it's a register that's specific to a certain type of processor and it may or may not be available in previous or future versions of the processor. The entire list of Intel MSRs and the processors on which they're supported is in Appendix B of the Intel Architecture Software Developer's Manual: Volume 3. 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><font size="1" face="Arial, Helvetica, sans-serif">04-Sep-03, Scott Noone</font> <br />
<hr align="left" size="1" width="250" />
<font size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"What exactly is an MSR?"</strong> </font><br />I have one other question. You mention MSRs in your article. Try as I might, I have been unable to locate a concise explanation of what the heck they are. Can you point me to one (or, better yet, give me one). Thanks.... 
<p>Dan 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><font size="1" face="Arial, Helvetica, sans-serif">04-Sep-03, Dan Chernin</font> <br />
<hr align="left" size="1" width="250" />
<font color="#800000" size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"RE: NTxxx functions from kernel mode"</strong> </font><br />Is there ANY time you want to call the NtXxxx variant from Kernel Mode? Well, yes. But it's typically unnecessarily risky. 
<p>Consider the case where (a) You know that you've been called directly from User Mode (so previous mode = user and current mode = kernel), and (b) You want to perform a request on behalf of the calling user. You want to use the user's access right, user's privileges, and you're passing arguments in that you received from user mode. In this case, you might call the NtXxxx variant of the function. This will cause the system service to perform checks and parameter validation just like the call came directly from the user. 
<p>I say this is unnecessary because you could just as easily -- and probably more securely -- performed those same checks within your driver before calling the ZwXxxx variant of the function. 
<p>What's MOST important is that you understand the difference between the two calls, and that you default to calling the ZwXxx variant unless you have some very specific reason why you want to call the NtXxx flavor. 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><font size="1" face="Arial, Helvetica, sans-serif">04-Sep-03, Peter Viscarola</font> <br />
<hr align="left" size="1" width="250" />
<font size="2" face="Arial, Helvetica, sans-serif"><font color="#585885"><strong>"NTxxx functions from kernel mode"</strong> </font><br />I guess my only question after reading this very good article is this: is there ever a situation where you WOULD call an NTxxx function directly? If not--as appears to be the case--what's the purpose of having the NTxxx symbol, aside from convenience? 
<p></font><font size="1" face="Arial, Helvetica, sans-serif"><em><font class="tsTextListItalic" size="2">Rating:</font></em> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <img align="absBottom" src="http://www.osronline.com/images/default/template/ThumbsUp.gif"  alt="" /> <br /></font><font size="1" face="Arial, Helvetica, sans-serif">04-Sep-03, Dan Chernin</font> <br /></p></font></font></font></font> <img src ="http://www.cppblog.com/Leaf/aggbug/146815.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Rambler</a> 2011-05-20 14:26 <a href="http://www.cppblog.com/Leaf/archive/2011/05/20/146815.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>