|Informative Information for the Uninformed
Next: Process and Thread Identifier Up: Calculating Entropy Sources Previous: Calculating Entropy Sources Contents
System time is a value that one might regard as challenging to recover. After all, it seems impossible to get the 100 nanosecond granularity of the system time that was retrieved when a cookie was being generated. Quite the contrary, actually. There are a few key points that go into being able to recover the system time. First, it's a fact that even though the system time measures granularity in terms of 100 nanosecond intervals, it's really only updated every 15.625 milliseconds (or 10.1 milliseconds for more modern CPUs). To many, 15.625 may seem like an odd number, but for those familiar with the Windows thread scheduler, it can be recognized as the period of the timer interrupt. For that reason, the current system time is only updated as a result of the timer interrupt firing. This fact means that the alignment of the system time that is used when a cookie is generated is known.
Of more interest, though, is the relationship between the system time value and the creation time value associated with a process or its initial thread. Since the minimum granularity of the system time is 15.6 or 10.1 milliseconds, it follows that the granularity of the thread creation time will be the same. In terms of modern CPUs, 15.6 milliseconds is an eternity and is plenty long for the processor to execute all instructions from the creation of the thread to the generation of the security cookie. This fact means that it's possible to assume that the creation time of a process or thread is the same as the system time that was used when the cookie was generated. This assumption doesn't always work, though, and there are indeed cases where the creation time will not equal the system time that was used. These situations are usually a result of the thread that creates the cookie not being immediately scheduled.
Even if this is the case, it would be necessary to be able to obtain the creation time of an arbitrary process or thread. On the surface, this would seem impossible because task manager prevents a non-privileged user from getting the start time of a privileged process, as figure 4.1 shows.
This is all a deception, though, because there does exist functionality that is exposed to non-privileged users that can be used to get this information. One way of getting it is through the use of the native API routine NtQuerySystemInformation. In this case, the SystemProcessesAndThreadsInformation system information class is used to query information about all of the running processes on the system. This information includes the process name, process creation time, and the creation time for each thread in each process. While this information class has been removed in Windows Vista, there are still potential ways of obtaining the creation time information. For example, an attacker could simply crash the vulnerable service once (assuming it's not a critical service) and then wait for it to respawn. Once it respawns, the creation time can be inferred based on the restart delay of the service. Granted, service restarts are limited to three times per day in Vista, but crashing it once should cause no major issues.
Using NtQuerySystemInformation, it's possible to collect some data that can be used to determine the likelihood that the creation time of a thread will be equal to the system time that was used when a GS cookie was generated. To test this, the author used the modified vulnapp.exe executable to extract the system time at the time that the cookie was generated. Following that, a separate program was used to collect the creation time information of the process in question using the native API. The initial thread's creation time was then compared with the system time to see if they were equal. Figure 4.2 shows these differences for a sample of 742 cookies taken from a single machine. In most cases, system time and creation time were equal.
Obviously, the data set describing differences is only relevant to a particular system load. If there are many threads waiting to run during the time that a process is executed, then it is unlikely that the system time will equal the process creation time. In a desktop environment, it's probably safe to assume that the thread will run immediately, but more conclusive evidence may be necessary.
Given these facts, it is apparent that the complete 64-bit system time value can be recovered more often than not with a great degree of accuracy just by simply assuming that thread creation time is the same as the system time value.