Code Diff Analysis for SetParent Infinite Recursion Bug

The previous article, Denial Of Service In Windows 11 22H2, described an infinite recursion bug triggered by a crafted SetParent WINAPI call in the Windows kernel. This bug was not triggered in the Windows Insider Canary build due to code updates. This article will present a comparative analysis of the updated code against the old buggy code. This will be done via a patch diff, typically downloading a target patch.

A patch is typically a collection of files which have been updated to correct various mistakes or bugs from old versions of files. Once the patch is downloaded, the target file(s) are identified to compare the code against that from old files. In this case, the target file was the win32kfull.sys driver. The updated new driver’s version is 10.0.25951.1000, while the old version is 10.0.22621.2283. We loaded the old and new drivers in IDA Pro instead of using Bin Diff as a different approach to diff’ing code. The symbols for both drivers were also available at the Microsoft Symbol Server.

Static comparative analysis

As per the debugger stack trace we shared in the previous blog, the bug was stack exhaustion due to the potentially infinite recursion of the zzzSetWindowCompositionCloak function. The buggy and updated versions of win32kfull.sys were loaded with corresponding symbols in IDA PRO. We can see changes to the code of the zzzSetWindowCompositionCloak function, as illustrated below. For the sake of simplicity, in every illustration, we have included the buggy/old code on the left side and the not-buggy code on the right side, unless otherwise mentioned.

Figure 1. zzzSetWindowCompositionCloak changes

The changes include moving the primary code of ‘zzzSetWindowCompositionCloak’ to the ‘zzzSetWindowCompositionCloakWorker’ function and addition of calls to ‘SDGGetUserSessionState’, ‘AtomicExecutionCheck::AtomicExecutionCheck()’ and ‘AtomicExecutionCheck::Disarm’. Also, note the changes in function prototypes, that is, the number and data type of parameters. The function in the old driver takes three parameters, while that in the updated driver takes two parameters.

Figure 2. Recursion in zzzSetWindowCompositionCloakWorker function

Checking the code of the ‘zzzSetWindowCompositionCloakWorker’ function in an updated driver, we find that recursion is still present, albeit it is for ‘zzzSetWindowCompositionCloakWorker’. We assume the additional calls mentioned above may not directly relate to the bug not getting triggered. 

Comparing the old code for ‘zzzSetWindowCompositionCloak’ with the new code for ‘zzzSetWindowCompositionCloakWorker’, there are a few changes made, like the addition of some checking code and removal of blocks of code. 

Presence of checks

The following checking code is not present in the old buggy driver but is added to the newly updated driver.

Figure 3. Checking code absent from the old driver, present in the new driver

Removal of blocks of code

Apart from the checks introduced, we also see that blocks of code have been removed in the new code, as shown below.

Figure 4.a. Blocks of code from the old buggy driver
Figure 4.b. Those blocks removed from the updated driver

NextOwnedWindow code

There is a call to ‘NextOwnedWindow()’, the return value of which can break out of the loop and, hence, possibly out of the recursion. Checking the code for ‘NextOwnedWindow()’, it is found to have no changes in the new driver. Therefore, the call to ‘NextOwnedWindow()’ in the new driver also possibly returns the same value as that in the old driver.

Figure 5. The ‘NextOwnedWindow’ code from old and updated drivers is the same

Comprehensively, we can make the following assumptions at this stage –  

  1. The code in ‘NextOwnedWindow’ may not be directly responsible for the bug, as this code is the same in both drivers. 
  1. The changes in the ‘zzzSetWindowCompositionCloakWorker’ function in the new driver may be responsible for the bug getting ‘fixed’. 

Dynamic analysis

To confirm which changes were responsible for fixing the bug, we analysed the dynamic code by checking the code execution flow at run time. During this dynamic analysis, we found that the checking code in the updated driver makes the execution exit without even hitting ‘NextOwnedWindow’ or the recursive call to ‘zzzSetWindowComppsitionCloakWorker’.

Figure 6. Dynamic analysis illustrating new checking code causing the execution to exit without hitting recursion

tagWND structure

As per the prototype of function ‘zzzSetWindowCompositionCloakWorker’, the first parameter, in ‘rcx’, is a pointer to tagWND structure. To get a sense of values from this tagWND structure, we will use the definition reversed by Palo Alto Networks’ researchers from the article [1]. This is because Microsoft no longer maintains symbols and documentation for this structure, which has changed. The definition used is from Windows 10 21H1, as the article mentions.

For reader’s reference, we’ve included below the structure definitions from the article [1].

Figure 7.a. tagWND kernel structure as reversed by Palo Alto Networks’ researchers
Figure 7.b. tagWND user-mode structure as reversed by Palo Alto Networks’ researchers

The updated code begins by taking a pointer from offset 0x28 of the input tagWND structure. This is the pointer ‘pWND’, as illustrated in figure 7.a., which points to another tagWND structure containing user-mode tagWND data, as described in figure 7.b.

Figure 8. Dumping data pointed to by pointer at rcx+28h, showing user-mode addresses

The check is performed on byte at offset 0xE9 of this user-mode tagWND data. As shown in Figure 7.b, this byte should be the first from the ‘gap’ array after ‘dwExtraFlag’. As it is used to decide return/not return from ‘zzzSetWindowCompositionCloakWorker’, we can assume that this byte is a flag of some sort. For now, let us call it the ‘windowCompositionCloakFlag’. The ‘windowCompositionCloakFlag’ byte is zero in our analysis, as seen from run time disassembly in Figure 6 – instruction at offset 0x19 of the function zzzSetWindowCompositionCloakWorker. 

Pseudo-algorithm of the fix

As per the disassembly, the following algorithm is carried out in the updated driver. In this algorithm, ‘CloakState_parameter’ is the second parameter passed to ‘zzzSetWindowCompositionCloakWorker’ and ‘value’ is calculated from the ‘windowCompositionCloakFlag’ flag. The ‘value’ is checked against ‘CloakState_parameter’, which fails. Hence, the bug is not triggered.  

  1. Set value = most significant nibble from ‘windowCompositionCloakFlag’ 
  1. If (a penultimate bit of ‘windowCompositionCloakFlag’ is zero) OR (‘windowCompositionCloakFlag’ is signed), then value = value BITWISE_OR 1 
  1. if (value == ‘CloakState_parameter’) then check failed 

return from ‘zzzSetWindowCompositionCloakWorker.’ 

Bibliography

[1] https://unit42.paloaltonetworks.com/win32k-analysis-part-1/#:~:text=The%20tagWND%20structure%2C%20shown%20in,structure%20is%20the%20window%20handle.

Subscribe to our Newsletter
Subscription Form
DOWNLOAD THE DATASHEET

Fill in your details and get your copy of the datasheet in few seconds

CTI Report
DOWNLOAD THE EBOOK

Fill in your details and get your copy of the ebook in your inbox

Ebook Download
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download ICS Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Cloud Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Code Review Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Red Team Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download DevSecOps Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Product Security Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Mobile Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Web App Sample Report

Let’s make cyberspace secure together!

Requirements

Connect Now Form

What our clients are saying!

Trusted by