Background
I have developed a layered driver based on minifilter and using the Shadow File Object (SFO) technology to merge a directory from another disk into the system disk for use. In the vast majority of cases, it works well and the merged files and programs can be used normally.
Can someone help me? If I can't solve this problem, I will be beaten up by my boss.
Problem description
If an EXE uses the socket() API, it can succeed without being redirected by SFO. However, once the EXE is redirected by SFO, the API will fail and return error code 10022.
EXE code:
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (nResult != 0) {
printf("WSAStartup failed: %d\n", nResult);
return 1;
}
DWORD dwBytesReturned = 0;
DWORD dwRetVal = 0;
system("pause");
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET) {
printf("socket failed: %d\n", WSAGetLastError());
getchar();
return 1;
}
else
{
printf("success\n");
}
system("pause");
return 0;
}
SFO Driver code:
NTSTATUS FltCreateFileWithParam(_In_ PFLT_INSTANCE Instance, _In_ PUNICODE_STRING pusPath, _In_ ParamCreate *Param, _Out_ PIO_STATUS_BLOCK StatusBlock, _Out_ HANDLE *pHandle, _Out_ PFILE_OBJECT *pFileobj)
{
if (NULL == Instance || NULL == pusPath || NULL == Param || NULL == pHandle || NULL == pFileobj)
{
return STATUS_INVALID_PARAMETER;
}
NTSTATUS status = STATUS_SUCCESS;
HANDLE handle = NULL;
PFILE_OBJECT FileObj = NULL;
OBJECT_ATTRIBUTES ObjAttr = { 0 };
IO_STATUS_BLOCK IoStatus = { 0 };
IO_DRIVER_CREATE_CONTEXT CreateContext = { 0 };
InitializeObjectAttributes(&ObjAttr, pusPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_FORCE_ACCESS_CHECK, NULL, NULL);
IoInitializeDriverCreateContext(&CreateContext);
CreateContext.ExtraCreateParameter = Param->m_EcpList;
CreateContext.TxnParameters = Param->m_TransactionPB;
status = FltCreateFileEx2(g_FltObj,
Instance,
&handle,
&FileObj,
Param->m_DesiredAccess,
&ObjAttr,
&IoStatus,
&Param->m_AllocSize,
Param->m_FileAttribute,
Param->m_ShareAccess,
Param->m_Disposition,
Param->m_Options & ~FILE_OPEN_BY_FILE_ID,
Param->m_EaBuffer,
Param->m_EaLen,
Param->m_Flags,
&CreateContext
);
if (NT_SUCCESS(status))
{
*pHandle = handle;
*pFileobj = FileObj;
*StatusBlock = IoStatus;
}
return status;
}
void SfoResetFileObj(PFILE_OBJECT DstFileObj, PFILE_OBJECT SrcFileObj)
{
DstFileObj->LockOperation = SrcFileObj->LockOperation;
DstFileObj->ReadAccess = SrcFileObj->ReadAccess;
DstFileObj->WriteAccess = SrcFileObj->WriteAccess;
DstFileObj->DeleteAccess = SrcFileObj->DeleteAccess;
DstFileObj->SharedRead = SrcFileObj->SharedRead;
DstFileObj->SharedWrite = SrcFileObj->SharedWrite;
DstFileObj->SharedDelete = SrcFileObj->SharedDelete;
DstFileObj->LastLock = SrcFileObj->LastLock;
InterlockedExchange((LONG*)&DstFileObj->Flags, (DstFileObj->Flags & ~ACTIVE_FLAGS) | (SrcFileObj->Flags & ACTIVE_FLAGS));
return;
}
void SfoRepairFakeObj(PFILE_OBJECT FakeFileObj, PFILE_OBJECT ShadowFileObj)
{
if (NULL == FakeFileObj || NULL == ShadowFileObj)
{
return;
}
FakeFileObj->Vpb = FakeFileObj->DeviceObject->Vpb;
FakeFileObj->SectionObjectPointer = ShadowFileObj->SectionObjectPointer;
FakeFileObj->PrivateCacheMap = ShadowFileObj->PrivateCacheMap;
FakeFileObj->DeletePending = ShadowFileObj->DeletePending;
SfoResetFileObj(FakeFileObj, ShadowFileObj);
if (SfoCheckIsShadow(FakeFileObj))
{
auto FsContext2 = (FakeFsContext2 *)FakeFileObj->FsContext2;
auto FsContext = (FakeFsContext *)FakeFileObj->FsContext;
ExAcquireFastMutex(FsContext->FastMutex);
FsContext->AllocationSize = *FsContext2->AllocationSize;
FsContext->FileSize = *FsContext2->FileSize;
FsContext->ValidDataLength = *FsContext2->ValidDataLength;
ExReleaseFastMutex(FsContext->FastMutex);
}
return;
}
NTSTATUS SfoSetRedirect(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ PFLT_INSTANCE RedirectInstance,
_In_ PUNICODE_STRING pusRedirectPath,
_Out_ PFILE_OBJECT *pRedirectFileObj)
{
HANDLE RedirectHandle = NULL;
FILE_OBJECT* RedirectFileObj = NULL;
IO_STATUS_BLOCK IoBlock = { 0 };
ParamCreate Param(Data);
NTSTATUS status = FltCreateFileWithParam(RedirectInstance, pusRedirectPath, &Param, &IoBlock, &RedirectHandle, &RedirectFileObj);
Data->IoStatus.Status = status;
Data->IoStatus.Information = IoBlock.Information;
if (NT_SUCCESS(Data->IoStatus.Status))
{
*pRedirectFileObj = RedirectFileObj;
//Generate Fake File Object
auto FakeFcb = new(TAG_SFO) FakeFsContext(pusRedirectPath, pusRedirectPath);
auto FakeCcb = new(TAG_SFO) FakeFsContext2(RedirectInstance, RedirectFileObj, RedirectHandle);
FltObjects->FileObject->FsContext = FakeFcb;
FltObjects->FileObject->FsContext2 = FakeCcb;
SfoRepairFakeObj(FltObjects->FileObject, RedirectFileObj);
FltSetCallbackDataDirty(Data);
}
else
{
DbgWarning("create shadow file failed,0x%08x,%wZ", status, pusRedirectPath);
}
return status;
}
Related links
I found some relevant information on the forum, but I didn't find any related reasons or solutions. If you can help me, I would be very grateful.
If you need more information, please contact me.