In vulnerability research, and computer security, we often deal strictly in the intangible. There are times however when tangible attack vectors can play a big part in real-world attacks. In a lot of cases it is USB memory sticks and related that play a common physical role in aiding attacks. From Stuxnet leveraging USB to bridge air gap networks to BadUSB there are many examples worth taking note. That is why this weeks Microsoft Security Bulletin MS14-063
vulnerability in FastFat caught our eEye.
The immediate thing that struck us interesting about this vulnerability is the list of affected operating systems: Server 2003, Vista, and Server 2008. Why not Windows 7? The FastFat driver should not have changed much between OS releases. It was with that odd hunch we started to investigate the patched file fastfat.sys. Starting with Windows Server 2003r2.
We started with binary diffing analysis of Windows Server 2003r2 and fastfat.sys version 5.2.3790.3959 (Unpatched) vs fastfat.sys version 5.2.3790.5425 (Patched). Between the two versions there were very few changes and no added or removed functions.
_FatCommonWrite(), while a monster of a function, contains only 2 basic block changes. The first one we examined involves ExAllocatePoolWithTag() and is likely the security change.
Figure 1 - Relevant basic block in FatCommonWrite - pre-patch
Here, in the pre-patch we are examining some byte that is 0x96 into a structure and performing an allocation if it is bigger than two. If this is the case, the size of the allocation is determined by that offset into the structure.
Let's take a look at the post-patch scenario.
Figure 2 - Relevant basic block in FatCommonWrite - post-patch
Here we can see that the ExAllocatePoolWithTag() call is now manipulating the byte at offset 0x96 into that structure. Specifically it is multiplying it by 24. It is likely that this is the size of a structure that is being allocated, which was forgotten in the pre-patch.
So, it looks like an incorrect assumption was made pre-patch about the size of the allocation produced by ExAllocatePoolWithTag which will likely lead to a buffer overflow later in the function.
A quick search on www.google.com shows that this disassembly lines up pretty closely with some Windows 2000 code from write.c.
Figure 3 - Corresponding Windows 2000 code from google.com search.
So, it appears that Vcb->Bpb.Fats is the culprit. Here Bpb refers to Bios parameter block, and the member it’s accessing is the BPB_NumFATs.
Figure 4 - FAT BPB Documentation - http://staff.washington.edu/dittrich/misc/fatgen103.pdf
In the pre-patched Server 2003r2 code and in the Windows 2000 code above, if Bpb.Fats > 2 then the allocation does not multiply BPB_NumFATs by the size of an IO_RUN. We can tell that an IO_RUN structure is 24 bytes by looking at VAR_158 (which is a stack buffer containing 2 IO_RUN structures) in FatCommonWrite in the Server 2003r2 patch. We can see that VAR_158 is of size 48, so one IO_RUN must be 24. We could also work this out in windbg or draw the conclusion by the fact that the post-patch allocation multiplies the number of fats by 24.
So that is kind of the root cause of the issue, and is pretty cool, but why is Windows 7 not vulnerable?
Lets look at the _FatCommonWrite() function from fastfat.sys version 6.1.7600.16385 from Windows 7.
Figure 5 - Relevant basic block from FatCommonWrite in Windows 7
Well that’s weird. It appears to be taking accessing the BPB_NumFATs member (at a slightly different offset in the interal struct) and taking into account the size of an IO_RUN structure when allocating.
It is very likely that this is the same fix
as MS14-063, except the modified date on this DLL is somewhere in 2009. That is to say that this vulnerability has been patched in more recent operating systems while older, yet still supported, operating systems had still been vulnerable.
This means that for many years now a vulnerability has existed in Windows 2003, 2008, Vista and XP systems while Windows 7 and above systems were fixed either accidentally or by a developer not taking the time to backport this fix into older, but still supported, operating systems.