Wednesday, January 17, 2024

Inferno drainer phishing nets scammers $80 million

 

Inferno Drainer Phishing Nets Scammers $80M from Crypto Wallets

Combination chaeap cloud domain's fuels frauds

 

Combination of cheap .cloud domains and fake Shark Tank news fuel unhealthy wellness scams

.SBS gTLD once owned by Australian broadcaster is another source of strife

Scammers are buying up cheap domain names to host sites that sell dodgy health products using fake articles, according to cybercrime disruption outfit Netcraft.

The firm on Tuesday noted that purveyors of legal-but-dubious health products often run fake news campaigns to promote their offerings, often with layouts that mimic prominent news outlets. Some of the stories suggest that judges on entrepreneurial reality shows Shark Tank and Dragons’ Den have backed the products.

The fakery is sprayed across the internet, often to social media. Netcraft suggests it’s hosted on freshly-registered domain names from among the constellation of new global top-level domain names (gTLDs).

Such domains have proliferated in recent years after ICANN decided to allow new gTLDs in 2011.

Not all have proven popular. Netcraft found that domains in the .cloud and .sbs gTLDs can be acquired for $0.99. .sbs once belonged to Australia’s Special Broadcasting Service but was surrendered and re-branded as now branded as “side by side” and suggested as ideal for “social welfare, progressive, and/or virtual-oriented” entities.

Netcraft reckons it’s now being used for the health and Shark Tank scams described above.

“The cheap domain pricing on these TLDs allows criminals to cost-effectively spread their campaigns over a large number of domains,” Netcraft’s analysts wrote. “This makes it harder to perform countermeasures against cyber-attacks, as the campaign can be spread across more infrastructure.”

The firm tracks the use of the .sbs gTLD for health scams and found “a huge spike in the [northern] summer of 2023, with 1,579 distinct IP addresses hosting health product scams in June and 6,725 in July.” In some months, more than half of registrations of .sbs domains were for flaky heath sites.

The .cloud domain was also targeted by health scammers, with around 30 percent of all new registrations being for sickening sites across 2023.

Netcraft isn’t alone in worrying about this stuff: in February 2023 the US Federal Trade Commission asked “Did your favorite Shark Tank celebrity really endorse THAT?” and answered “Probably not.” ®

CiSA warns

 

CISA Warns of Actively Exploited Laravel Framework RCE Flaw

The U.S. Cybersecurity and Infrastructure Security Agency (CISA) has issued a stern warning that’s reverberating through the web development community. The addition of a high-severity flaw in the Laravel Framework to its Known Exploited Vulnerabilities (KEV) catalog is not just a routine update—it’s a red alert for developers and organizations alike.

Using Qualys to Find and Remedy a D...
Using Qualys to Find and Remedy a Dell IDRAC SNMP Vulnerability
Ezoic

Laravel, renowned for its expressive and elegant syntax, has long been the go-to web application framework for developers seeking to craft seamless applications with efficiency and finesse. Its rich features, including dependency injection, database abstraction, and comprehensive testing tools, have made it a beloved choice for crafting innovative web solutions.

However, this popularity comes with a heightened responsibility towards security, tracked as CVE-2018-15133 (CVSS score: 8.1), the vulnerability has been described as a deserialization of untrusted data vulnerability, allowing for remote command execution.

Ezoic

The root cause in this situation is the APP_KEY, the application encryption key. Under normal circumstances, this key remains out of reach from prying eyes. Yet, in the hands of a malicious actor, particularly one familiar with the system like a former employee, it becomes a potent weapon. This vulnerability is a stark reminder that internal threats, often overlooked, can be as damaging as external attacks.

What makes CVE-2018-15133 particularly alarming is its presence in versions of the Laravel Framework through 5.5.40 and 5.6.x through 5.6.29. This wide net means many applications could be at risk, a situation taken seriously by the Federal Civilian Executive Branch (FCEB) agencies. They are mandated to apply vendor-provided patches by February 6, 2024, a clear indication of the severity of this issue.

Ezoic

Monday, January 15, 2024

Finding and exploiting process killer drivers with LOL for $3000

 Alice Climent-Pommeret

Finding and exploiting process killer drivers with LOL for 3000$

CONTENTS

This article describes a quick way to find easy exploitable process killer drivers. There are many ways to identify and exploit process killer drivers. This article is not exhaustive and presents only one (easy) method.

Lately, the use of the BYOVD technique to kill AV and EDR agents seems trending. The ZeroMemoryEx Blackout project, the Terminator tool sold (for 3000$) by spyboy are some recent examples.

Using vulnerable drivers to kill AV and EDR is not brand new, it’s been used by APTs, Red Teamers, and ransomware gangs for quite some time.

However, a few months ago a new projet called LOLDrivers was released.

This awesome project centralizes known vulnerable drivers, enriches them with some of their specifications, and allows you to download them. Its emergence in the landscape is (for me at least) a game changer: it offers a huge, easily accessible playground.

In this article, I will introduce some kernel driver/internals theory and explain how to use the data in LOLDrivers to find interesting drivers. Finally, I will present 2 examples of vulnerable drivers and explain how to quickly reverse them and create a PoC to exploit them.

Let’s go !

Here, I’m going to present a few essential theoretical elements. Since the kernel of the operating system is huge and complex, the elements of this section are volontary simplified. The goal here is to give key elements to understand how a user-mode application communicates with a software driver running in kernel mode.

To communicate with a software driver running in the kernel, an application running in user-mode must use functions from the Windows API performing syscalls.

If you want to know more about syscalls, you can read my previous articles about it here and here.

In a nutshell, the functions from the Windows API performing syscalls are located in ntdll.dll and win32u.dll.

When a function from those DLLs performs a syscall the execution flow is forwarded to the kernel. Then, the code of the related function is located and executed.

That’s where we stopped in the previous articles.

In reality, things don’t stop here. Sure if you use NtWriteFile() in your user-mode application in the end the NtWriteFile() code in ntoskrnl.exe will be executed. But after that, other elements come into play.

Illustration of a possible Nt functions workflow*

Illustration of a possible Nt functions workflow*

The I/O Manager is a set of functions in charge of the communication with drivers for I/O operations (functions starting with Io*). When a Windows API function needs to perform an I/O operation (network operation, filesystem operation, etc), the Kernel code of your function, will end up calling functions of the I/O Manager.

To communicate with the drivers the I/O Manager uses an IRP (I/O Request Packet) data strucuture (details incoming, see a bit below).

The I/O Manager’s job in this case is to create an IRP with elements transmitted from the user-mode call, then locate and send the IRP to the appropriate driver.

Finally, using the information embedded in the IRP, the driver will perform the required task.

If it’s a software driver the end is here (well, not really but simplification remember). However, if it’s a hardware driver, Hardware Abstraction Layer functions of ntoskrnl.exe will be called (functions starting with Hal*).

The purpose of Hal* functions is to communicate with the hardware, you can think of it as the last layer of the kernel before the hardware.

The main purpose of a software driver is to access data structure exclusively accessible in Kernel Mode. In this article, we will focus only on those.

If you want to learn more about the different types of drivers you can check this Microsoft article

IRP (I/O Request Packet) is a data structure, built by the I/O Manager, used to communicate with a driver.

This structure looks like this:

As you can see there is a lot of information, but we’ll focus exclusively on *CurrentStackLocation.

An IRP always comes with at least one IO_STACK_LOCATION structure. A simple action in user-mode can trigger the usage of a series of drivers. This implies that a single IRP can hold several IO_STACK_LOCATION. Depending on the position in the series of drivers, the IO_STACK_LOCATION varies, and the proper one in context is stored in *CurrentStackLocation.

IRP with its IO_STACK_LOCATIONs

IRP with its IO_STACK_LOCATIONs

The IO_STACK_LOCATION structure contains a HUGE union (the Parameters entry):

But don’t get scared! We are going to focus only on MajorFunction and some structures of Parameters.

MajorFunction contains the IRP major function code, which tells the driver what operation it should carry out.

  • IRP_MJ_CREATE: when NtCreateFile() (from user-mode) or ZwCreateFile() (from kernel mode) is called on the driver.
  • IRP_MJ_CLOSE: when NtClose() (from user-mode) or ZwClose() (from kernel mode) is called on the driver.
  • IRP_MJ_DEVICE_CONTROL: when NtDeviceIoControlFile() (from user-mode) or ZwDeviceIoControlFile() (from kernel mode) is called on the driver.
  • IRP_MJ_READ
  • IRP_MJ_WRITE
  • IRP_MJ_CLEANUP
  • IRP_MJ_FILE_SYSTEM_CONTROL
  • IRP_MJ_FLUSH_BUFFERS
  • IRP_MJ_INTERNAL_DEVICE_CONTROL
  • IRP_MJ_PNP
  • IRP_MJ_POWER
  • IRP_MJ_QUERY_INFORMATION
  • IRP_MJ_SET_INFORMATION
  • IRP_MJ_SHUTDOWN
  • IRP_MJ_SYSTEM_CONTROL

We’ll only use IRP_MJ_CREATEIRP_MJ_CLOSE and the most important for us: IRP_MJ_DEVICE_CONTROL.

What you need to remember here, is that when you interact with a driver using functions such as NtCreateFile()NtClose(), or NtDeviceIoControlFile() a value related to the action you want to perform is stored in the MajorFunction element of the IRP that will be built for your driver.

IRP_MJ_DEVICE_CONTROL set in the MajorFunction attribute of the IRP IO_STACK_LOCATION structure

IRP_MJ_DEVICE_CONTROL set in the MajorFunction attribute of the IRP IO_STACK_LOCATION structure

When using the DeviceIoControl()NtDeviceIoControlFile() or ZwDeviceIoControlFile() the structure in the Parameters is DeviceIoControl.

 struct {
      ULONG                   OutputBufferLength;
      ULONG POINTER_ALIGNMENT InputBufferLength;
      ULONG POINTER_ALIGNMENT IoControlCode;
      PVOID                   Type3InputBuffer;
    } DeviceIoControl;

DeviceIoControl() functions are used to communicate with the driver when you want it to perform a specific dedicated action. DeviceIoControl() functions take amongst their parameters:

  • a handle on the drivers that you want to communicate with;
  • an IoControlCode (also called IOCTL).

This code will be stored in the IO_STACK_LOCATION at Parameters.DeviceIoControl.IoControlCode.

You can find more info on the IRP major function code on the Microsoft Documentation.

IOCTL are crucial in the communication between user-mode and drivers. An IOCTL is a 32 bits value used to identify a specific function in a driver.

Let’s say that you developed your EDR product with an agent in user-mode and a kernel driver. You want to be able to kill processes using your kernel mode driver and using a PID provided from the user-mode agent.

To do so you’ll need to use DeviceIoControl() from the agent on the EDR driver. The DeviceIoControl() function will need the IOCTL of the process termination function implemented in the driver and the process PID that you want to kill.

This IOCTL is written by the I/O Manager in the IO_STACK_LOCATION of the IRP during its creation and sent to the EDR driver.

Then the driver uses the current IO_STACK_LOCATION of the IRP to find out which task is required using the MajorFunction field. If the content of the field is IRP_MJ_DEVICE_CONTROL then the IOCTL code will be retrieved in the field Parameters.DeviceIoControl.IoControlCode.

Finally, the driver executes the function in its code related to the IOCTL, which in our case is a process termination function. The PID is retrieved by the function code using a buffer that contains the data (PID in our case) provided via the DeviceIoControl() function.

IOCTL set in the Parameters.DeviceIoControl.IoControlCode attribute of the IRP IO_STACK_LOCATION structure

IOCTL set in the Parameters.DeviceIoControl.IoControlCode attribute of the IRP IO_STACK_LOCATION structure

IOCTL are defined by the driver developers. IOCTL are based on strict rules and cannot be random.

They carry 4 pieces of information:

  • DeviceType: type of device can be one of the following. However, in our case (software driver) most of the time the type is going to be FILE_DEVICE_UNKNOWN (0x22) or a value between 0x8000 and 0xFFFF.
  • FunctionCode: code identifiying the function in your driver. It must be unique for a same device type. The value ranges from 0x800 to 0xFFF. Function codes under 0x800 are restricted to Microsoft.
  • TransferType: indicates how the system will pass data between the caller and the driver handling the IRP.
  • RequiredAccess: indicates the type of access that a caller must request when opening the file object that represents the device (Read, Write, etc).
IOCTL illustration from Microsoft documentation

IOCTL illustration from Microsoft documentation

To create the IOCTL code the developers use the Windows CTL_CODE macro that takes the 4 arguments:

CTL_CODE(DeviceType, Function, Method, Access)

This performs the following operation on the arguments:

((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))

Let’s do it manually:

DeviceType = FILE_DEVICE_UNKNOWN = 0x22
Access = FILE_ANY_ACCESS = 0x00
Method = METHOD_NEITHER = 0x3
Function = 0x800


Device type = FILE_DEVICE_UNKNOWN = 00100010
Access = FILE_ANY_ACCESS = 00
Method = METHOD_NEITHER = 11
Function = 100000000000

                       00000000000000000000000000000000 (32 bits)
((DeviceType) << 16) =         00100010xxxxxxxxxxxxxxxx
((Access) << 14)     =                 00xxxxxxxxxxxxxx
(Function) << 2     =                   100000000000xx
(Method)                                             11

OR                    ----------------------------------
                      00000000001000100010000000000011

IOCTL CODE = 0x00222003 (or 0x222003)

Another example using a different DeviceType:

DeviceType = 0x8000
Access = FILE_ANY_ACCESS = 0x00
Method = METHOD_NEITHER = 0x3
Function = 0x800

DeviceType = 1000000000000000
Access = FILE_ANY_ACCESS = 00
Method = METHOD_NEITHER = 11
Function = 100000000000
                       00000000000000000000000000000000
((DeviceType) << 16) = 1000000000000000xxxxxxxxxxxxxxxx
((Access) << 14)     =                 00xxxxxxxxxxxxxx
(Function) << 2     =                   100000000000xx
(Method)                                             11

OR                    ----------------------------------
                       10000000000000000010000000000011

IOCTL CODE = 0x80002003

If you want to find more information about IOCTL you can check the Microsoft documentation. If you want to play to decode IOCTL you can check this fun project.

However, a real declaration of IOCTL in a driver looks like this:

#define IOCTL_DESTROY_THE_WORLD	CTL_CODE(0x8000, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_BURN_THE_GALAXY	CTL_CODE(0x8000, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PET_SOME_PUPPIES	CTL_CODE(0x8000, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS)

The DriverEntry() function is the main of Windows drivers, it’s the first called function after driver load.

It takes 2 arguments:

  • DriverObject: pointer to a DRIVER_OBJECT structure.
  • RegistryPath: pointer to a counted Unicode string specifying the path to the driver’s registry key.

Now let’s see an example of a Driver that uses IOCTL from user-mode (the explanations in this chapter are in the code comments!):

In a nutshell, the key elements to keep in mind while reversing a driver searching for juicy IOCTLs:

  • the main of the Windows drivers is the DriverEntry();
  • IRP major function code are associated with specific types of driver operation. A driver communicating with user-land via IOCTL code will use IRP_MJ_CREATEIRP_MJ_CLOSE and IRP_MJ_DEVICE_CONTROL IRP major function code;
  • the function associated to IRP_MJ_DEVICE_CONTROL is the one that will process the IOCTL code in the driver.

To quicky identify potential easy exploitable process killer drivers, I coded a script called LOLDrivers_finder.

This script uses the LOLDriver json file. This file contains technical data: for each available driver in the project, the list of the functions it imports is provided.

A basic process killer driver requires 2 things:

  • a way to get an handle on a process (for instance NtOpenProcess or ZwOpenProcess);
  • a way to terminate the process (for instance NtTerminateProcess or ZwTerminateProcess).

The script checks all the imported functions for each driver in the json file. If a driver has in its imported functions Nt/ZwOpenProcess AND Nt/ZwTerminateProcess then it will be selected as a potential process killer drivers.

Yes, I KNOW moment.

Of course there are lots of way to exploit drivers to kill processes.

There are also lots of way to retrieve a handle on a process or kill it without using these functions.

Finally, yes functions can be imported dynamically or retrieved by parsing the ntdll EAT.

So yes this script will miss them. However, this quick and dirty script will also find real and easy exploitable process killers drivers.

Obvious warning here, not all drivers in the output are process killers drivers or exploitable with just the right IOCTL

In this section, I’m going to quickly analyze 2 drivers retrieved with the LOLDrivers_finder script.

To do so, I start with ZwTerminateProcess() and then backtrack all paths that lead to it (via cross-referencing function calls).

This way, I will find (at least) a path and get a general idea on how this terminate function is called and if it’s possible to trigger it from user-land.

The first candidate is the Avast AswArPot.sys anti-rootkit driver.

First, we open and seek references in the code for ZwTerminateProcess() (in IDA you search in the import tab and use the cross-reference feature).

Lucky for us, the function is only used once in the code.

function code using ZwTerminateProcess()

function code using ZwTerminateProcess()

ZwOpenProcess() retrieves a process handle just before passing it as an argument to ZwTerminateProcess(). Good. Now let’s see, using the cross-reference magic, where this chunk of code is called.

function calling our terminate code

function calling our terminate code

In this snippet, we can see a lot of case with 32 bits hexadecimal code… Well this looks a lot like the IOCTL switch case, doesn’t it? We can clearly see the value linked to our “terminate function”, is 0x9988C094.

Let’s continue our function call moonwalk and check the calling function with the cross-reference.

function retrieving the IOCTL and checking the major function code

function retrieving the IOCTL and checking the major function code

Now, we see the CurrentStackLocation being retrieved, the SystemBuffer which is one of the buffer that can be used to store user-input data, the IoControlCode and the MajorFunction value being checked.

The decimal value for the major function code IRP_MJ_DEVICE_CONTROL is 14 (or 0x0e) and 2 for IRP_MJ_CLOSE. You can check it here or on your machine if you have the WDK installed.

So basically: a check is performed on the major function code to behave differently depending on whether IRP_MJ_CLOSE or IRP_MJ_DEVICE_CONTROL is received.

Our path of interest to the terminate code requires major function code IRP_MJ_DEVICE_CONTROL. The required arguments have IOCTL and input buffer, which is logical.

Let’s moonwalk one more time.

device check and call to the function we came from

device check and call to the function we came from

Here there’s not much to see, but the first line is of interest. The device object is checked in the if statement. But why a device would need to be checked?

&lsquo;else&rsquo; statement code

‘else’ statement code

If we go a little bit further in the code we have an else statement following a similar function (I know it’s similar because I checked it already be we are not going to do it again here).

We walk back the calling flow one more time.

Device and symbolic link creation. MajorFunction initialization

Device and symbolic link creation. MajorFunction initialization

In this function 2 strings are available: aswSP_ArPot2 and avgSP_ArPot2. One of those strings will be selected to create the device and symbolic link name.

We won’t see here the code in charge of thE selection but, basically, the value in the if statement is a flag set according to the driver’s name in the registry key pointed by the RegistryPath of the DriverEntry.

If the driver name starts with asw then aswSP_ArPot2 will be used. Otherwise, if it starts with avg it will be avgSP_ArPot2.

Finally, if the driver name doesn’t start with any of those, an error will be triggered.

Let’s get back to rest of this code.

We have a CreateDevice() and an IoCreateSymbolicLink() function. We saw why it’s used earlier in the DriverEntry chapter.

The interesting thing here is the memset64() function after the IoCreateSymbolicLink().

If the symbolic link is successfully created, then Major_Dispatch_function() (where we come from) address is set the in the MajorFunction attribute of the driver object.

In this code one unique function dispatches all the IRPs.

However, In our DriverEntry() example we used a more common approach by using differents functions to handle specific IRPs.

Now, we moonwalk again.

Two functions using a driver object in argument

Two functions using a driver object in argument

We see 2 functions using the driver object a1 as an argument. We come from Device_Arpot2(), so let’s check this Device_Avar().

Device and symbolic link creation for Avar

Device and symbolic link creation for Avar

It looks pretty much like our Device_Arpot2() code. But unlike Device_Arpot2(), we don’t see any manipulation of the drivers object attribute MajorFunction.

However, we see that the Avar_Device variable is set with the newly created Avar device object.

This means that at least 2 devices will be available for this driver after load (Arpot2 and Avar).

This solves our mystery on the device object check that we saw here:

device check and call to the function we came from

device check and call to the function we came from

The purpose of this check is to dispatch the IRPs to the appropriate device.

Now, we have all the information, we need!

  • the device in charge of our process termination function is the Avar one;
  • the IOCTL is 0x9988C094;
  • our vulnerable driver name is **asw**ArPot, this means that the device name will be **asw**SP_Avar.

Install the vulnerable driver:

sc.exe create aswArPot.sys binPath= C:\windows\temp\aswArPot.bin type= kernel && sc.exe start aswArPot.sys

Then, retrieve an handle on the appropriate device :

CreateFileA("\\\\.\\aswSP_Avar", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

And send the kill IOCTL with the PID of our target using DeviceIoControl

DeviceIoControl(hDevice, 0x9988c094, &pid, sizeof(pid), NULL, 0, &lpBytesReturned, NULL);

VOILA, you now have a PoC that allows you to kill any protected process using a vulnerable driver. EASY PEASY!

You can find the full PoC code here.

This driver is associated to the anti-virus & anti-rootkit program PowerTool.

To find this one, I modified the search criteria of my LOLDrivers_finder script.

As I said earlier, there are many ways to retrieve a handle on a running process. The usual one (searched by default in the script) is to use Zw/NtOpenProcess.

Still, you can also use the kernel function PsLookupProcessByProcessId() to retrieve a pointer to the EPROCESS structure of a running process using its PID (documentation here). EPROCESS is a data structure representing the process object in the kernel (documentation here).

You then pass this pointer to the ObOpenObjectByPointer() kernel function to retrieve a handle on the process (documentation here).

To find drivers using PsLookupProcessByProcessId() and ObOpenObjectByPointer() with LOLDrivers_finder, I replaced:

OPEN_FUNCTIONS = ["ZwOpenProcess", "NtOpenProcess"]
...
...
functions_list = [TERMINATE_FUNCTIONS, OPEN_FUNCTIONS]

by

OPEN_FUNCTIONS = ["PsLookupProcessByProcessId"]
OPEN_FUNCTIONS2 = ["ObOpenObjectByPointer"]
...
...
functions_list = [TERMINATE_FUNCTIONS, OPEN_FUNCTIONS, OPEN_FUNCTIONS2]

(Yes… I will modify the script to be more flexible… eventually…)

Now, let’s analyze this driver!

As usual we go directly where ZwTerminateProcess() is called.

Code that terminate the process

Code that terminate the process

Like in our previous case, we see that the process handle retrieved is passed to ZwTerminateProcess().

Instead of searching for ZwOpenProcess(), search for PsLookupProcessByProcessId() used with ObOpenObjectByPointer().

Let’s moonwalk.

IOCTL check

IOCTL check

We land on a else statement. If the IOCTL is not 0x22211C then substract 0x22201C.

This result is used in a switch case where 0x18 is the value leading to our terminate_process function().

Calculation on the IOCTL

Calculation on the IOCTL

We go a little bit up on the code to check the value of the if statement. Here the checked condition is if the IOCTLis greater than 0x22211C.

In a nutshell, the IOCTL leading to our terminate_process function() must be:

  1. inferior to 0x22211C;
  2. not equal to 0x22211C;
  3. the IOCTL value substracted by 0x22201C gives 0x18.

Retrieving the IOCTL is simple:

0x22201C + 0x18 = 0x222034

Now we moonwalk one last time.

Basic DriverEntry

Basic DriverEntry

Well, we end up directly in the DriverEntry()!

The function handling IRP_MJ_DEVICE_CONTROL (MajorFunction[14]) is the one we came from (IOCTL_Dispatch).

There is only one device with the name KevP64.

The PoC comes as follow:

Install the vulnerable driver:

sc.exe create kEvP64.sys binPath= C:\windows\temp\kEvP64.bin type= kernel && sc.exe start kEvP64.sys

Retrieve a handle on the device :

CreateFileA("\\\\.\\KevP64", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

Send the kill IOCTL with the PID of the target using DeviceIoControl:

 DeviceIoControl(hDevice, 0x222034, &pid, sizeof(pid), NULL, 0, &lpBytesReturned, NULL);

And again… VOILA!

The full PoC code is here.

You can find the drivers and some extra information on the PoCs on the ‘Killers’ repository.

I hope you enjoyed this post!

If you want to go deeper on the Windows kernel driver subject, I recommand :

Thanks to M. and @r00tbsd for the proofreading!

Telegram founder arrested

  Aug 25, 2024  Ravie Lakshmanan Pavel Durov, founder and chief executive of the popular messaging app Telegram, was arrested in France on ...