9.8 KiB
SyncProvider
The Cloud Filter API provides functionality that allows a cloud sync engine to synchronize files between a remote environment and a local client. This functionality is typically used by cloud file synchronization processes such as OneDrive, so that files hosted in the cloud can be represented and accessed from Windows Explorer.
Through this API, a sync engine (or sync provider; Microsoft seems to use both terms interchangeably) can project cloud files by creating placeholders. Placeholders are files on disk that have three states:
- Dehydrated: This is the initial state when creating a placeholder. It means that although the file representation exists on disk, its content is not present locally and can only be obtained if the sync provider is available.
- Hydrated: The file content is present on the local disk, so the file can be used normally. At any time, the placeholder can be dehydrated, returning to the previous state.
- Hydrated and pinned: The placeholder content is on disk and its presence is guaranteed at all times (we do not care about this state for the activities described in this document).
The first access to the content of a dehydrated placeholder is intercepted by the CldFlt minifilter (default altitude: 180451). Before allowing the original request on the file to continue on its path, the minifilter asks the sync provider for the placeholder content so it can hydrate it. When it receives a response from the sync provider, placeholder hydration is performed by calling the FltWriteFileEx function to write the content to disk. Once the placeholder is correctly hydrated, the original request can continue on its path and complete as appropriate.
If we read the documentation for the FltWriteFileEx function, we will see that in the Remarks section it states that this function "causes a write request to be sent to the minifilter driver instances attached below the initiating instance and to the file system. The specified instance and the instances attached above it do not receive the write request". Since AV and EDR minifilters are always loaded at altitudes higher than CldFlt (altitude ranges are officially assigned and documented by Microsoft), this means that this write is invisible to endpoint protection software, which allows writing any content to disk without it being statically analyzed (if we do it correctly). Additionally, although we have described the sending of data from a sync provider as a response to a request from CldFlt, the reality is that a provider can proactively hydrate one of its placeholders at any time following the same procedure.
With all this, we have what we need to abuse Cloud Filter API functionality to write malware to disk without it being statically analyzed. Specifically, the SyncProvider project will launch a malicious provider that performs a double hydration on a placeholder to evade all malware scanning. Initially, upon receiving a hydration request, the malicious provider will return the contents of a non-malicious file, which can be scanned by the security solution without raising suspicion. After a few seconds, the provider will proactively perform a second hydration of the placeholder, this time sending the malware’s contents, which will be written to disk without being analyzed. The procedure is as follows:
- Launch
sync_provider.exeand complete the requested information.
- Sync root directory: Directory where the malicious placeholder will be created. In this test, the path
C:\Temp\Testis inserted. - Backing file 1: Legitimate local file. In the proof of concept documented here,
C:\Windows\System32\certutil.exewill be used, although in real environments it is not recommended to use binaries resident inSystem32(they can trigger other alerts for executing binaries outside their usual directory). This file must have a size greater than or equal to that of our malware, since its information will be used to create the placeholder. The content of this file will be used for the first hydration of the placeholder. - Backing file 2: Local or remote (SMB) path where the malware to be dropped is located (
.exefile). Ideally it should be hosted remotely but, in either case, it is recommended to encrypt the file beforehand using thexor_file.pyscript (simple XOR; the provider will perform the decryption in memory before the second hydration). In this test,Mimikatzwill be used as the binary to drop, since it is widely known malware with a signature detected by practically any endpoint protection solution. The content of this file will be used for the second hydration of the placeholder. - Placeholder name: Name of the placeholder to create inside
sync root directory. In this test,notmimi.exe. - Decryption key: If
Backing file 2has been encrypted, the same encryption key used must be passed here. - Mode: This document only reflects the behavior of mode
2.
C:\Path\To\Puzzle\bin>sync_provider.exe
Sync root directory: C:\Temp\Test
Backing file 1 (benign file): C:\Windows\System32\certutil.exe
Backing file 2 (payload): C:\Temp\mimi_encrypted
Placeholder name: notmimi.exe
Decryption key (empty = unencrypted payload): test1234
Select mode (1 or 2): 2 # Always set it to mode 2
[+] Sync root sucessfully registered.
[+] Connection to sync root established. Connection key: 0x210aaa86060
[+] Placeholder created: C:\Temp\Test\notmimi.exe
[+] Provider status set to CF_PROVIDER_STATUS_IDLE.
-
Once the placeholder is registered, execute it (double click,
CreateProcess, whatever). The process creation routine internally ends up callingNtCreateSection, which ultimately triggers theIRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATIONcallback of all minifilters that requested it. On a device without AV/EDR,IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATIONfromCldFltwould trigger directly, which would cause the placeholder to be hydrated before section creation. However, as shown in the video at the end of this document, on devices protected withMicrosoft Defender(the minifilters of several EDRs behave exactly the same), the behavior is different, since the AV intercepts the original section creation and requests full hydration of the placeholder in order to perform a prior security analysis. Only when that analysis completes without detecting anything malicious (and leaves the placeholder already in hydrated state) is the original section creation allowed to pass and the process launched (which, in our case, will executecertutil.exe). In this first hydration, the sync provider sends the content ofBacking file 1, that is, completely legitimate content, so the security solution scan does not detect anything malicious. -
After a few seconds (I introduce this delay to avoid corruption when launching the process), the sync provider hydrates the placeholder a second time proactively (without being asked), except that in this case the content it provides is that of
Backing file 2, so the malware can be written to disk without being analyzed. -
On occasion (this does not happen on all systems), even after the second hydration has been performed and the content on disk is that of
Backing file 2, later executions of the binary still launchBacking file 1. This is because the content is cached, so we must force the system to discard this content and use the content on disk for subsequent executions. This can be done programmatically in several ways, but we can also do it conveniently withRight Click -> Propertieson the placeholder. -
Once the cached content has been discarded (if necessary), the next execution will launch
MimikatzwithoutMicrosoft Defenderdetecting it, despite executing highly recognizable malicious code. The reason it is not detected (apart from the fact that there is no visibility into the write to disk) is that the AV considers that the file has not been modified since the last scan. If we analyze the activity with Procmon, we can see that, when launchingMimikatz, the AV checks the USN Journal and the metadata of the file's corresponding MFT entry to determine whether it has been modified since the last scan. However, and for some reason I do not know, the hydration performed byCldFltis not recorded in either of these two sources of truth as a file modification operation (conjecture: I suppose because of the use of theFLTFL_IO_OPERATION_PAGINGflag when callingFltWriteFileEx, although this is only a hypothesis). Therefore, since the AV has already recently scanned the file (initial execution ofBacking file 1) without finding anything malicious, has not seen any write to it becauseCldFltis at a lower altitude, and no checked source of truth indicates file modification, the malware is allowed to execute without being reanalyzed.
This same behavior has also been detected in numerous EDRs. However, although the malware write goes unnoticed by all endpoint protection solutions due to what was discussed previously, some EDRs do reanalyze the binary when receiving a process creation callback regardless of whether it has been recently analyzed or not, which allows them to detect the payload at runtime. For this reason, in this type of environment it is necessary to combine this technique with the use of bindlinks described here.
- Once execution is finished, the registered sync provider must be removed. To do this, first dehydrate the file (pressing
1in the tool console) and then unregister the provider (pressing2).
