返回 TI 主页

Overview

CVE-2024-30051 vulnerability was first discovered by Kaspersky, but what Kaspersky discovered initially was not a wild sample, but a simple analysis report of the vulnerability that was uploaded to vt. Later, we found the actual sample ( c4dd780560091c8d2da429c7c689f84b) used by QakBot through the characteristics of the vulnerability in the relevant report . The running effect is shown below. It is interesting that the leaked analysis report and the vulnerability sample appeared in vt on 2024/04/01 and 2024/04/18 respectively. Considering that the actual attack process of the sample is almost the same as that described in the document, and 18 days is too short, we believe that the sample was not developed by a third-party attacker after obtaining the document, but should be the original vulnerability exploitation sample described in the document.

The core problem of the vulnerability lies in dwmcore.dll, the core dll of the dwm process. The specific problem is in the function CCommandBuffer::Initialize. It can be seen that the length of the mempy operation here is controlled by the attacker as len_control. When the memory space of the target address is allocated, size=(len_control/0x90)*0x90. Applying the above formula, if len_control=0x95, the actual allocated memory is only 0x90, and the subsequent memory will cause an out-of-bounds write of 0x5 length.


DWM

To understand the vulnerability, we first need to have a brief understanding of the dwm process in Windows. Dwm is the abbreviation of Desktop Window Manager, which is translated into Chinese as "桌面窗口管理器". It is a core process in the Windows system, responsible for managing windows on the desktop and providing various visual effects. Users can control the related behaviors of dwm through the relevant COM interface calls in dcomp.dll. However, the call of dcomp.dll to dwm is not direct, but cross-kernel. The process is simply user->dcomp.dll->win32kbase (kernel)->dwm.exe (user layer).

This vulnerability mainly involves the DirectComposition object. To trigger the use of the DirectComposition object, the following three core functions are required.

  • NtDCompositionCreateChannel
  • NtDCompositionProcessChannelBatchBuffer
  • NtDCompositionCommitChannel

To create a DirectComposition object, you need to create a channel through the NtDCompositionCreateChannel system call.

typedef NTSTATUS(*pNtDCompositionCreateChannel)(
OUT PHANDLE hChannel,
IN OUT PSIZE_T pSectionSize,
OUT PVOID* pMappedAddress
);

After the channel is created, the specific call command is sent through the NtDCompositionProcessChannelBatchBuffer system call. Each command has its own format, and the command is saved in the pMappedAddress returned by NtDCompositionCreateChannel.

typedef NTSTATUS(*pNtDCompositionProcessChannelBatchBuffer)(
IN PHANDLE hChannel,
IN DWORD dwArgStart,
OUT PDWORD pOutArg1,
OUT PDWORD pOutArg2
\);

The commands involved are as follows:

enum DCOMPOSITION_COMMAND_ID
{
ProcessCommandBufferIterator,
CreateResource,
OpenSharedResource,
ReleaseResource,
GetAnimationTime,
CapturePointer,
OpenSharedResourceHandle,
SetResourceCallbackId,
SetResourceIntegerProperty,
SetResourceFloatProperty,
SetResourceHandleProperty,
SetResourceHandleArrayProperty,
SetResourceBufferProperty,
SetResourceReferenceProperty,
SetResourceReferenceArrayProperty,
SetResourceAnimationProperty,
SetResourceDeletedNotificationTag,
AddVisualChild,
RedirectMouseToHwnd,
SetVisualInputSink,
RemoveVisualChild
};

NtDCompositionCommitChannel generates batch command bufer and sends it to the DWM process. In summary:

The NtDCompositionCreateChannel function creates a communication channel with dwm and obtains a pMappedAddress for sending commands. The NtDCompositionProcessChannelBatchBuffer function sets the required commands in pMappedAddress through the communication channel. NtDCompositionCommitChannel triggers the execution of specific commands and renders the results through the dwm process.

typedef NTSTATUS(*pNtDCompositionCommitChannel)(
IN HANDLE hChannel,
OUT PDWORD out1,
OUT PDWORD out2,
IN DWORD flag,
IN HANDLE Object
);

Vulnerability Sample Analysis

After the sample runs, it first calls the RtlGetVersion function to obtain the current system version, and uses it to initialize several core constants in subsequent utilization.

Dynamically obtain the API address of the following functions.

Then, the following four functions are hooked through the functions fun_hookInit/fun_hookSpecialfunInstall:

  • NtDCompositionCommitChannel
  • NtDCompositionCreateChannel
  • RtlCreateHeap
  • RtlAllocateHeap

The hook here, in summary, is the generation of the intermediate jump code completed by the fun_hookInit function, as shown below:

fun_hookSpecialfunInstall completes the target function hook.

Let's take a closer look at what operations are performed after these four functions are hooked. Among them, RtlCreateHeap/RtlAllocateHeap are operations for heap creation and allocation. When the parameter a2 of RtlCreateHeap is passed in the base address of the heap object allocation, hookpro saves the returned heap object as pointer_specialHeapobject. For the RtlAllocateHeap function, when RtlAllocateHeap allocates the heap, if the corresponding heap object is the pointer_specialHeapobject saved in the previous RtlCreateHeap hook, the heap address allocated at this time is returned. In summary, the creation process of the heap object passed in the heap base address is monitored here, and the allocated heap address is saved.

For the hook of the function fun_hookProNtDCompositionCreateChannel, it will monitor the first creation of NtDCompositionCreateChannel, and obtain the pMappedAddress corresponding to the Channel and save it as pointer_pMappedAddress.

The hook for the function NtDCompositionCommitChannel is more complicated. From the previous article, we know that NtDCompositionCommitChannel is used to generate batch command bufer and send it to the DWM process. Here, when hooking, we will ensure that it is the first call of NtDCompositionCommitChannel, and search for the field 0x120 in the memory obtained in the previous heap allocation of pointer_specialHeapalloc. Find and modify the field to var_contrulLen. The utilization in different environments is different. Here is 0x23f (var_contrulLen (0x1B0) + 0x8f), and then 0x23f / 0x90 = 4. Seeing this, we can basically guess that 0x23f at this position is len_control controlled by the attacker in the vulnerability.

According to 0x23f/0x90 = 4, 4 copies are made. The copied content is the memory with a length of 0x90 starting from len_control+0x2c, and is saved in sequence. In addition, the values of two addresses in the copied content are set to 0.

Then NtDCompositionProcessChannelBatchBuffer is called four times. The command used here is SetResourceIntegerProperty. The resource numbers are from 1 to 4, and the corresponding Propertyid 4 of the resource is set to the value 1000.

After the hook is completed, the vulnerability is triggered through the fun_trigger function to complete the privilege escalation operation.

In fun_trigger, a window class is first registered, the function fun_windowsInit is called to complete the subsequent definition of the related window, and then the function DirectComposition::CDevice::Commit is called.

First, let's look at fun_windowsInit, which creates a window named test based on the window class registered earlier.

The subsequent code is more complicated. In summary, a 2D drawing factory interface is created through D2D1CreateFactory, and a surface and a visual are created using the factory interface. Here, the surface can be simply understood as a canvas, and the visual can be understood as a picture frame. After drawing on the canvas, the visual picture frame is placed and associated with the previous test window. After fun_windowsInit returns, the current DirectComposition scene is submitted to the graphics hardware for rendering through the function DirectComposition::CDevice::Commit.

After completing the test window graphics hardware drawing, the subsequent s1.dll is released.

According to the previously detected version, we enter the specified version of the exploit flow. Here we enter the exploit type of var_osVersiontype=2. The function NtDCompositionCreateChannel opens a Channel, and calls NtDCompositionProcessChannelBatchBuffer through the Channel. The function is called 0x10000 times. The instruction passed in each call is CreateResource. The corresponding resource ids created range from 0x14 to 0x10014, and the resource type is CHolographicInteropTextureMarshaler.

After that, the ReleaseResource command is called through NtDCompositionProcessChannelBatchBuffer to release the previously created resources. The ID of the target resource to be released ranges from 0x14 to 0x7000, with an interval of 0x20. It can be seen that this is an obvious spray operation. After this step is completed, a hole will appear in this continuous CHolographicInteropTextureMarshaler memory every 0x20 CHolographicInteropTextureMarshaler objects.

Get the memory pointer pointer_specialHeapalloc allocated in the previous hook and initialize the memory after the specified offset v35, pass v35 as a parameter to the function fun_gadgetInit, and then call the function ShowWindow to display the image drawn by DirectComposition::CDevice::Commit through the configured window test.

The content of the fun_gadgetInit function is very simple. It is used to configure the content of v35 passed in earlier. There are three important locations.

  • 0x0: _fnGESTURE
  • 0x50: LoadLibraryA
  • 0x58:s1.dll path

The final memory of v35 is as follows

Finally, ReleaseResource is called again through the function NtDCompositionProcessChannelBatchBuffer to release the remaining resources.

Static analysis shows that the vulnerability itself is an out-of-bounds write. The attacker uses spray to modify the CHolographicInteropTextureMarshaler resource through out-of-bounds write . However, there are many questions about the details of the exploit.

  1. What are the locations and functions of the several hooks?
  2. What role does pointer_specialHeapalloc in the hook play, and what is the significance of the memory layout of v35 after this memory?
  3. How is the length controlled by the attacker modified and ultimately used to cause the out-of-bounds error?
  4. Whether the vulnerability is achieved by destroying CHolographicInteropTextureMarshaler to achieve code execution?
  5. Where is the location where the vulnerability is written and where is the location where the code is executed?

Debug analysis

With the above questions, we started the relevant debugging. First, we will look at the four hook functions. Here we take the function NtDCompositionCommitChannel as an example. The NtDCompositionCommitChannel function call is shown below, and the subsequent kernel part is entered through syscall.

After hooking, you can see that the corresponding part is modified to a jmp jump, which eventually points to the hookpro function.

The return address here stores the two instructions that were overwritten by the jmp during the previous hook, and finally points back to the previous syscall code part, thus completing the hook return.

Set breakpoints for these four hookpro functions respectively to see where the hook is triggered in the specific use sample. The first is the hook for the NtDCompositionCreateChannel function. This hook will be triggered at the first call. Through the stack backtrace, we can see that the location where the first NtDCompositionCreateChannel hook is triggered is at the DCompositionCreateDevice position of fun_windowsInit.

The other three function hooks are triggered when DirectComposition::CDevice::Commit submits the current DirectComposition scene to the graphics hardware for rendering. The specific function call process is as follows.

DirectComposition::CDevice::Commit will call DirectComposition::CDevice::AllocateSharedMemory to generate a SharedMemory. The following location of this function will trigger the corresponding RtlCreateHeap/RtlAllocateHeap hook.

DirectComposition::CSharedSection::Create is shown below. You can see that when the hook is triggered, the base address of RtlCreateHeap is actually a section of memory mapped by MapViewOfFile, which is essentially a CShareSection resource. DirectComposition::CSharedSection is an important class in the Windows DirectComposition API. It is used to share memory between different DirectComposition visual objects. CSharedSection is essentially a memory block that is mapped to different process spaces and can also be used for data sharing in dwm processes and win32kbase.sys.

Then DirectComposition::CSharedSection::Allocate is called to allocate a memory of length 0x228 on this CSharedSection. The allocated memory address will be captured by RtlAllocateHeap hook and saved as pointer_specialHeapalloc. After DirectComposition::CDevice::AllocateSharedMemory returns, the position of pointer_specialHeapalloc+0x74 is passed as a parameter to DirectComposition::CPrimitiveGroup::WriteCommandBuffer to set CommandBuffer. Careful friends can find that the core function triggering the vulnerability is CCommandBuffer::Initialize, which is the initialization process of the CCommandBuffer object. In the exploit code, the attacker renders DirectComposition::CDevice::Commit after drawing graphics in 2D and associating the corresponding window. When DirectComposition::CDevice::Commit submits the current DirectComposition scene to the graphics hardware for rendering, the hook modifies the CCommandBuffer in the corresponding CSharedSection to trigger the vulnerability.

The relevant function calling process in DirectComposition::CDevice::Commit is as follows.

You can see that when DirectComposition::CDevice::Commit triggers NtDCompositionCommitChannel When hooking, the memory of pointer_specialHeapalloc CSharedSection is as follows:

  • 0x48 is the corresponding length field, which is the core of triggering the vulnerability. The attacker can control
  • 0x74 , which is composed of memory blocks of 0x90 length.

After the NtDCompositionCommitChannel hook is completed, the corresponding control_len has been modified to 0x23f, and the subsequent CCommandBuffer memory block is copied to 4, because control_len/0x90 = 0x23f/0x90 = 4 in the final vulnerable function, and the number of memory blocks needs to be satisfied.

After the malicious CCommandBuffer in CSharedSection is constructed, it enters the spray part of the vulnerability, where the heap object in the dwm process is created by allocating 0x10000 CHolographicInteropTextureMarshaler resources. It can be seen that the size of a CHolographicInteropTextureMarshaler object is 0x1B0 . After that, a CHolographicInteropTextureMarshaler object is released every 0x20 resource numbers, which will cause a 0x1B0 size memory hole to appear in the heap space of consecutive CHolographicInteropTextureMarshaler objects.

Here you can see that the heap size of the generated CHolographicInteropTextureMarshaler object is 0x1B0 .

The stack when the CHolographicInteropTextureMarshaler object is created is as follows:

Construct the fourth 0x90 memory block of CommandBuffer in pointer_specialHeapalloc, which is the v35 mentioned above.

The memory block structure is constructed by the fun_gadgetInit function as shown below

When the Showwindow function runs, the DirectComposition::CDevice::Commit function is submitted to the graphics hardware for rendering. The rendering effect is finally displayed in the test window and the vulnerable function CCommandBuffer::Initialize is triggered.

The malicious buffer controlled by the attacker in the vulnerable function CCommandBuffer::Initialize has a second parameter of type ID2D1PrivateCompositorBuffer

Through stack backtrace, we can know that the parameter is generated in the function CD2DSharedBuffer::CreateFromSharedSection. The first parameter of this function is the shared memory between the program and dwm, and the second parameter is the corresponding modified length 23f.

The ID2D1PrivateCompositorBuffer generated in CD2DSharedBuffer::CreateFromSharedSection is very simple. The object length is 0x28 and is written in the format of shared memory address/size.

The generated ID2D1PrivateCompositorBuffer is as follows

We officially enter the vulnerable function CCommandBuffer::Initialize. The call stack at this time is as follows. When showwindow submits the DirectComposition::CDevice::Commit function to the graphics hardware for rendering and the effect is finally displayed in the test window, the vulnerable function will be triggered.

Enter the vulnerability logic in CCommandBuffer::Initialize exp len_control = 23f, (2f3/90)*0x90 = 1b0. The memory allocated at the final calculation is 0x1b0, which can perfectly fill the hole of the CHolographicInteropTextureMarshaler object allocated in the previous spray. The actual required length is 0x23f, which will cause a memory overflow of 8f length.

Allocate memory of size 0x1b0 .

Due to the previous spray operation, the allocated space of 0x1b0 will be directly allocated to the hole in the CHolographicInteropTextureMarshaler sequence memory, forming the following memory form:

CHolographicInteropTextureMarshaleri + hole + CHolographicInteropTextureMarshaleri1

Once the copy is completed, the CHolographicInteropTextureMarshaleri1 object will be destroyed. As shown below, the first red box is the target copy address 0x1b0 we allocated, and the content in the second red box is the CHolographicInteropTextureMarshaleri+1 object.

The copied content is the malicious CommandBuffer that we constructed earlier by hooking pointer_specialHeapalloc, the core of which is the two pointers in the red box.

Here 00007ffa819ad5f0 is a virtual pointer.

The effect after overwriting is as follows. The first pointer is _fnGESTURE and the second pointer is LoadLibraryA.

the memory read breakpoint under the first _fnGESTURE pointer.

You can see this when the sample tries to release all remaining CHolographicInteropTextureMarshaler resources.

The memory read breakpoint is set, and this is the release operation for CHolographicInteropTextureMarshaler resources.

Here, the dwmcore!CComposition::Channel_DeleteResource function obtains the malicious pointer corresponding to the destroyed CHolographicInteropTextureMarshaler object and calls poi(evilpointer)+0x10. The malicious pointer set by the attacker will eventually find the function __fnTOUCHHITTESTING through the above method.

The __fnTOUCHHITTESTING function is shown below. It directly uses rcx+0x50 as the function address and rcx+0x28 as the first parameter of the function.

Entering __fnTOUCHHITTESTING, the content of rcx is as follows. It can be seen that rcx+0x50 points to the maliciously constructed loadLibrary, and the value of rcx+0x28 is 0x58.

But when the FixupCallbackPointers function is executed, rcx+0x28 points to the dll path at 0x58.

This eventually results in arbitrary DLL loading and code execution.

S1.dll has already been loaded.

Now let's summarize the process of exploiting this vulnerability

  1. Draw on window test through D2D1CreateFactory and DirectComposition::CDevice::Commit. This call will cause the corresponding CommandBuffer to be generated during DirectComposition::CDevice::Commit, and the CommandBuffer will be modified by the hook being used.
  2. Call NtDCompositionProcessChannelBatchBuffer In the dwm process, spray a series of CHolographicInteropTextureMarshaler resources and release one of the resources every 0 x20 to generate a series of holes.
  3. Display the test window through showwindow, which will cause the CommandBuffer submitted by DirectComposition::CDevice::Commit to be called in the CCommandBuffer::Initialize vulnerability function of the dwm process, thereby occupying a hole released by CHolographicInteropTextureMarshaler and implementing the duplication of the CHolographicInteropTextureMarshaler1 resource that follows it.
  4. Call NtDCompositionProcessChannelBatchBuffer to release the remaining CHolographicInteropTextureMarshaler resources, which will cause the maliciously modified function pointer in the overwritten CHolographicInteropTextureMarshaler1 resource to be called, thereby calling loadlibrary to load the malicious dll in a controllable way with the first parameter through the maliciously constructed __fnTOUCHHITTESTING.

The detailed breakdown is shown in the figure below:


Exploit loading

The code for S1.dll is simple, releasing a piece of shellcode via RtlDecompressBuffer and calling it via CreateThread.

shellcode will simply decrypt an s2.exe.

The s2.exe first releases a s3.dll through the RtlDecompressBuffer as well, after which it executes the fun_triggerWinloginload function.

Two variables are first initialized in fun_triggerWinloginload by the system version.

After that, we dynamically get the address of some system api and hook the function MapViewOfFile in the same way as in the previous utilization program.

The MapViewOfFile hookpro function first executes MapViewOfFile and sleeps for a period of time to determine whether the corresponding returned mapped memory offset 0x10 is 0x1FFEEFFEE.

After that start the assignment operation on this MapViewOfFile.

The assignment looks like this

As we know from the previous analysis, dwm as a window in the desktop management display process, other processes and dwm communication, such as our exp, are through the dcomp and kernel win32kbase.sys, and in the win32kbase.sys to generate the corresponding resources and feed back to the dwm process, there is a problem if the corresponding processes and If the communication between the corresponding process and the dwm requires a large amount of data, it will be a very troublesome thing to transit through the kernel again. Therefore, the previously mentioned resource CSharedSection was born to be used for sharing data between the process and the dwm, and the sharing here is in fact the DirectComposition::CDevice::AllocateSharedMemory mentioned earlier.

Just the previous utilization is to modify the CCommandBuffer after the CSharedSection 0x74, but through observation, we can see that the CSharedSection also saves the virtual table pointers of some objects in the communication process, at this time, s2.exe is located in the process of dwm, so we can get the CSharedSection by the hook designated by MayViewOfFile to get the section of CSharedSection and modify the virtual table pointer similar to the use of _fnGESTURE to load any dll, so as to control the behavior of the corresponding communication process, if the communication process is the system privileges, then you can play the effect of lifting the power of the sample is to try to modify the target process is the In this sample, the target process that is trying to be modified is consent.exe, and here the exploit sample finally executes ShellExecuteA(0i64, "runas", "C:\\\Windows\\\\System32\\\cmd.exe", 0i64, 0i64, 1); to realize the interaction between consent.exe and dwm.

In fact, when the dwm process loaded s1.dll, the privilege escalation was not completed. The attacker took such a long detour to modify the virtual table pointer of the consent.exe process object in CSharedSection by hooking the MapViewOfFile of the dwm process to load the dll. The reason for the privilege escalation is that dwm itself has permission restrictions. It can be seen that the consent.exe uac process finally loaded s3.dll and popped up a root shell through s3.dll.

The corresponding call stack here is shown below:

The main use of exp in the call ShellExecuteA(0i64, "runas", "C:\\\Windows\\\System32\\cmd.exe", 0i64, 0i64, 1), which will lead to the trigger of an administrator's cmd, which triggers the uac, whose invocation process is svchost -> consent.exe, at this point consent.exe will perform a rendering operation with dwm, and the function dcomp!DirectComposition::CSharedSection::Allocate will be called in the consent process, which is used to allocate a section of shared memory of CSharedSection .

Here on return you can see that two pointers have been placed in the memory corresponding to the function's return.

The two dummy tables point to the following two functions.

  • CMILRefCountImpl::AddReference
  • DirectComposition::CCompositorSynchronizedObject::SafeToModify

And at the same time in our dwm, s3 triggers the mapping of the corresponding shared memory, which is thus captured by the set hookpro, this memory corresponds to the mapping in the consent at the address 0x1f16b6c120, and in the previous analysis we know that the address allocated in the consent starts at 0x1f16b6c720.

So the operation in hookpro is to construct a section of malicious pointer call memory and write backward the two pointers at 0x1f16b6c720 to point to the malicious pointer call memory constructed at the low address of this shared memory, as shown below, and when this memory is mapped back to the consent process the pointers in 0x1f16b6c720 are already pointing to the maliciously constructed malicious pointer call memory.

At this point the shared memory in consent.exe has been modified (locations 720 & 740).

Call dcomp!DirectComposition::CDelayedDestructionObject::Release when the uac trigger completes, which uses the pointer CMILRefCountImpl::AddReference at the first position modified earlier.

As shown below, the final call method poi(poi(evilpoint)+0x18) in dcomp!DirectComposition::CDelayedDestructionObject::Release points to the combase!NdrProxyForwardingFunction3 pointer constructed in our malicious memory.

The combase!NdrProxyForwardingFunction3 function is shown below and its code is simple.

To summarize, the code executes poi(poi(evilpoint+0x20)+0x18)(poi(evilpoint+0x20)) with the following pseudo-code, which ends up addressing the USER32!_fnCOPYDATA function constructed in tmalicious memory through the replaced pointer at the second original DirectComposition::CCompositorSynchronizedObject: :SafeToModify,and uses the replaced address as a parameter.

The following call to USER32!_fnCOPYDATA is made at this point, and the argument is the address of the original second replacement pointer.

USER32!_fnCOPYDATA is similar to the previous USER32!__fnTOUCHHITTESTING, i.e., the widget function used to implement the loadlibaray function for arbitrary dll loading when the first argument can be controlled.

USER32!_fnCOPYDATA parameter for the malicious constructed memory in the malicious virtual table2, with the virtual table address accordingly to get offset 0x68 at 0x28 malicious memory constructed loadlibrary and s3 path, so as to call loadlibrary load the final s3 code, the implementation of the code is very simple directly pop-up a cmd.

We have since summarized the entire post-utilization portion of the exploit as follows

  1. exp by triggering a vulnerability to get code execution privileges in dwm, and on success dwm load the first stage of s1.dll.
  2. s1.dll releases a piece of shellcode and executes it, and the shellcode releases s2.exe and executes it.
  3. exp execute ShellExecuteA(0i64, "runas", "C:\\\Windows\\\System32\\\cmd.exe", 0i64, 0i64, 1); to realize the interaction between consent.exe and dwm, and the consent.exe process generates the corresponding sharedSection.
  4. s2.exe executes in dwm, will hook dwm in mapviewofile, when monitoring the specified memory mapping crosses the boundary to modify the consent.exe process to generate the corresponding sharedSection in the two virtual tables.
  5. two dummy tables in sharedSection in consent.exe trigger the execution into the malicious dummy table pointer set by the attacker, load the final s3.dll and create a cmd via NdrProxyForwardingFunction3/__fnCOPYDATA/LoadLibraryA execution flow. Realize the final power lift.

In the end, we merged the flowchart of the vulnerability exploitation and the flow of the subsequent exploitation, and the technical flow of the entire sample exploitation can be summarized into the following one big picture:

QakBot, also known as QBot, QuackBot and Pinkslipbot, is a banking Trojan that has been around for over a decade. It was discovered in the wild in 2007, and has been continuously maintained and developed since then. In the past ten years, no cases of using 0day in QakBot-related attacks have been found, until CVE-2024-30051 appeared in the first half of this year. through the analysis above, we can see that the developers of the whole sample have studied the internal mechanism of Windows very thoroughly, and during the analysis process, I was often surprised by the techniques used in its exploitation. In the analysis process, I also often for its use in the use of techniques and patted, as a long history of banking Trojans, QakBot has enough economic strength for the 0day armament supplement, so at present we can not determine whether the vulnerability exploitation samples are QakBot internal self-research, but as mentioned in the annual report released by the end of 2023 Qianxin Threat Intelligence Center, all kinds of signs are indicating an increasing number of non-traditional means of exploitation, and the number of non-traditional means of exploitation is increasing. There are signs that more and more non-traditional APT groups, and have the financial strength to attack organizations, such as ransom, to the old banking Trojans are suspected to be through the network arms dealers to purchase and frequent use of 0day vulnerabilities, and such behavior in the future will become more and more common.


Reference Links

[1] https://conference.hitb.org/hitbsecconf2023ams/materials/D1T1%20-%20The%20Lost%20World%20of%20DirectComposition-%20Hunting% 20Windows%20Desktop%20Window%20Manager%20Bugs%20-%20Zhang%20WangJunjie,%20YiSheng%20He%20&%20Wenyue%20Li.pdf

[2] https://www.zerodayinitiative.com/blog/2021/5/3/cve-2021-26900-privilege-escalation-via-a-use-after-free-vulnerability-in-win32k

[3] https://github.com/progmboy/cansecwest2017

[4] https://blog.talosintelligence.com/snapshot-fuzzing-direct-composition-with-wtf/

[5] https://securelist.com/cve-2024-30051/112618/

[6] https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-30051

VULNERABILITY CVE-2024-30051