farmpoet Profile picture
Aug 19 24 tweets 7 min read Read on X
It's time to take a closer look at CVE-2024-38063 (Windows TCPIP RCE).
I usually don't post partial analysis but since most available info is unreliable I'll do my best to try and shed some light.
This time I'll focus on my workflow and thought process as we go. 🧵
MSFT advisory pretty much tells us where to look.
Our target is the tcpip.sys kernel driver which got an update during last patch tuesday.
For the analysis I picked binaries for Windows 11 23H2, builds 3958 (pre-fix) and 4036 (post).
Diffing shows a single function has changed. Image
In fact, this is the best you could hope for on binary diffing.
Further inspecting the differences on Ipv6pProcessOptions() it comes down to a single change at the end.
A call to IppSendErrorList() has been replaced by IppSendError(). Couldn't get simpler than this right? 😅 Image
Well no, not really. But to tell you why we need to start at the beginning.
Checking the cross-references to the function we have 2 possible code paths: Ipv6pValidateNetBuffer and Ipv6pReceiveDestinationOptions.
The second seems particularly helpful in showing how to reach it. Image
Ipv6 doubled the header size compared to ipv4 so optional data needs to be provided in extension headers to avoid further bloat.
A quick read at RFC 8200 gives us a list of possible extension headers.
Time to fire up a VM with kernel debugging and start sending some packets. Image
We place a breakpoint at Ipv6pProcessOptions and for testing we use scapy to send an ipv6 packet with both Hop-by-Hop and Destination Options header.
Sure enough our breakpoint is hit twice so we print the call stack to check where we're coming from. Image
Further experiments confirm the Hop-By-Hop is called from the validate function and each destination extension header will be hit from the receive destination options (once for each header).
We now do the proper reversing of the function and try to lift the structures used.
To do that we inspect the single argument received which is an opaque structure that contains among other info a _NET_BUFFER_LIST (more on this later).
The function retrieves the first _NET_BUFFER in the list, which contains a packet, and parses a single options header. Image
In summary, the function parses each option in the header using NdisAdvanceNetBufferDataStart() and NdisGetDataBuffer() to walk the buffer.
Along the way, some variables are set to keep track of what's already been parsed and remaining data in the buffer. Image
So ok, it parses option headers and do a bunch of sanity checks. What about the vuln?
Well, ipv6 has a feature which allows the sender to request the packet to be discarded and a notification to be sent back if the destination doesn't know how to handle a specific option. Image
Which gets us to the patch changes. When an option header fails the checks or a request for a packet to be discarded has been received, we have a call to IppSendErrorList (on the pre-patch version).
Now what's the difference from calling IppSendError instead? Image
Remember the function receives a _NET_BUFFER_LIST.
The first field of that struct is a pointer to the next _NET_BUFFER it contains.
So IppSendErrorList just iterates through that single linked list until all packets in that _NET_BUFFER_LIST have been processed. Image
In a low traffic ipv6 network, each list will carry a single _NET_BUFFER with the packet to be processed stored in a MDL. In such case a call to IppSendErrorList would be indifferent from calling IppSendError.
However, what happens if you saturate the link with IPv6 packets?
In that scenario, each _NET_BUFFER_LIST will carry multiple packets yet to be processed and if you insert some packets with a request to be discarded then the IppSendErrorList will also be called for the remaining packets on the list.
Lets do an experiment to check.
Each line on the image are packets arriving at the Ipv6pProcessOptions (marked +), and the calls o IppSendError (marked -).
Observe the first packet being received and being sent to the error function. By the 2nd packet however, you have a list of packets that are unrolled. Image
As more packets go in, the more unprocessed packets will be fed to IppSendError().
Why is this relevant? Remember that IppSendError will parse a discarded packet to send back an ICMP error to the source which involves further manipulation of the buffers. Image
At this point I dare to speculate the vulnerability may possibly be triggered by specially crafting packets which will cause an incorrect parsing by IppSendError.
Why? because some of the offsets tracked during parsing are stored in the opaque structure mentioned previously.
Which means (if I didn't screw up in the analysis so far) that IppSendError will operate on packets yet to be processed packets while consuming offsets stored on the opaque struct.
I haven't experimentaly verified it so feel free to check if you feel so inclined.
But what we've seen so far illustrates a very important point. That the vulnerability can't be triggered with a single packet. In fact, you'll have to flood the destination with packets just to reach the vulnerable path.
This seems to be corroborated by MSFT advisory. Image
The implication is important since the hope for controlled exploitation will hardly succeed. Besides the usual requirement of a kernel pointer leak, controlling the target offsets with a flood of packets (plus eventual normal traffic) seems an unsurpassable barrier.
My current assessment is that at best we're talking about a remote denial of service and full RCE is intractable in this case. Not that a pre-firewall remote DoS isn't bad but 9.8 CVE score seems over the top.
This is my best assessment at the moment.
I won't keep digging into this vuln given the limitations mentioned above but hope it may help other people trying to look into it and, as always, I'm ready to be proven wrong by someone more knowledgeable in reversing network drivers.
⚠️These brief analysis are deceptively time consuming to write so, if you enjoyed reading this please consider giving a follow and/or retweeting the first post in the thread.
Comments on what you'd like to see in future CVE analysis are also welcome.
End 🧵
@_bka_ And you're right, IppSendErrorList is called in other places such as Ipv4pProcessOptions but there you lack the complex parsing logic that exists on ipv6 and the ability to request packets to be discarded. 👍

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with farmpoet

farmpoet Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @f4rmpoet

Aug 22
Let's explore China’s 0-day vulnerability research capabilities.
I’ve long been intrigued by the prolific nature of Chinese teams in discovering vulnerabilities. Over the past months, I’ve gathered some data and analyzed reported vulnerabilities to gain a deeper understanding.🧵 Image
Since September 2021, the Chinese government has mandated that any Chinese researchers, businesses, or even foreign companies operating in China who discover 0-day vulnerabilities must report the details to the Chinese Ministry of Industry and Information Technology (MIIT)
The policy in question was formalized through the "Provisions on the Management of Network Product Security Vulnerabilities" issued by MIIT, which obliges entities to report vulnerabilities within within two days (48 hours) of their discovery. chinalawtranslate.com/en/product-sec…
Read 25 tweets
Jun 29
Some final notes on CVE-2024-30078 (wifi RCE) exploitability.
If you haven't already done so, I recommend you first take a look at my previous thread on the subject.
🧵

As previously noted, the native driver does not account for 4 extra bytes when the ether type is 0x8100 (Vlan tagged net).
Since the packet is rewritten on the original buffer, it will do so 4 bytes ahead of what is was supposed to because of the dot1q header that should exist.
This will not only corrupt the translated packet (which will be later discarded as invalid) but also overwrite up to 2 bytes outside the MDL buffer that holds the packet. [overflowed bytes marked in red]
But is the exploitability feasible? Image
Read 10 tweets
Jun 23
MSFT released a patch for CVE-2024-30078 (Wi-Fi Driver RCE) on June cumulative update, however details on the advisory have been very limited.
I'm leaving some quick notes from a quick reverse engineering of the patch that hopefully will shed a little more light on the issue. 🧵
I am not an expert on wireless network protocols so feel free to correct me or add up on the provided info in the comments or through a DM.
The patch targets Dot11Translate80211ToEthernetNdisPacket() of the native wifi driver (nwifi.sys).
The patch expands on a previous check at the beginning of the function which is described in the pseudocode below:

MDL_packetSize = MDL->ByteCount;
if (MDL->ByteCount < (MAC_frame_size + 8))
return NDIS_STATUS_INVALID_PACKET;
Read 9 tweets
Jan 7, 2022
Inspired by @osxreverser analysis of NSA BPF port-knocking implant, I decided to take a 2nd look at #ShadowBrokers leak of windows implants. Lo and behold, a couple of hardly mentioned kernel drivers (#DoormanGauze and #FlewAvenue) caught my attention. (1/11)
Information publicly available on these drivers is scarce and for the most part flat out wrong. Instead of going for the usual deep-dive blog post, lets try a light-speed tweeter thread analysis. In this thread we'll take a brief look at #DoormanGauze. (2/11)
So, what is #DoormanGauze... In a nutshell, its a plugin for #DanderSpritz / #ExpandingPulley implants implementing an in-kernel mailslot server, allowing for stealthy inter-process communication. This can replace the usual named pipes/windows sockets IPC. (3/11) Image
Read 11 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us!

:(