如前所述@eryksun https://stackoverflow.com/users/205580/eryksun我们可以删除映射文件,如果节(文件映射)是在没有创建的情况下创建的SEC_IMAGE https://learn.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createfilemappinga属性有两种方式:
- 打开文件FILE_FLAG_DELETE_ON_CLOSE https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew flag - 该文件是
在所有句柄关闭后立即删除,这
包括指定的句柄和任何其他打开或重复的句柄
手柄。或者我们可以使用NtOpenFile https://learn.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntopenfile or NtCreateFile https://learn.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntcreatefile带有标志的呼叫FILE_DELETE_ON_CLOSE https://learn.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntcreatefile.
- by call ZwDeleteFile https://msdn.microsoft.com/en-us/library/windows/hardware/ff566435(v=vs.85).aspx。真的internal https://github.com/Zer0Mem0ry/ntoskrnl/blob/master/Io/iomgr/misc.c#L291
NtDeleteFile
打开
文件与FILE_DELETE_ON_CLOSE
标志和特殊内部
性格DeleteOnly = TRUE https://github.com/Zer0Mem0ry/ntoskrnl/blob/master/Io/iomgr/misc.c#L339。这是拨打更多电话
高效比较正常打开的文件,然后关闭它句柄。
在代码中看起来像这样。
#ifndef FILE_SHARE_VALID_FLAGS
#define FILE_SHARE_VALID_FLAGS 0x00000007
#endif
NTSTATUS Delete1(PCWSTR FileName)
{
HANDLE hFile = CreateFile(FileName, DELETE, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return RtlGetLastNtStatus();
}
CloseHandle(hFile);
return 0;
}
NTSTATUS Delete2(PCWSTR FileName)
{
UNICODE_STRING ObjectName;
if (RtlDosPathNameToNtPathName_U(FileName, &ObjectName, 0, 0))
{
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };
NTSTATUS status = ZwDeleteFile(&oa);
RtlFreeUnicodeString(&ObjectName);
return status;
}
return STATUS_UNSUCCESSFUL;
}
请注意,调用DeleteFileW https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilew此处失败,状态为 -STATUS_CANNOT_DELETE
。我建议打电话RtlGetLastNtStatus()
在这里代替GetLastError() https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx因为win32映射NTSTATUS
错误代码不是单射的,经常丢失有价值的信息。说STATUS_CANNOT_DELETE
映射到ERROR_ACCESS_DENIED
。但存在巨大的另一个NTSATUS
代码也映射到ERROR_ACCESS_DENIED
. the ERROR_ACCESS_DENIED
不仅STATUS_ACCESS_DENIED
(真实访问被拒绝)。得到STATUS_CANNOT_DELETE
这里提供更多信息比较ERROR_ACCESS_DENIED
. the RtlGetLastNtStatus
具有完全相同的签名GetLastError
并从 ntdll.dll 导出(因此包括ntdll库 or ntdllp库)
extern "C" NTSYSCALLAPI NTSTATUS NTAPI RtlGetLastNtStatus();