前言
有些时候我们需要创建 MountPoint
或 HardLink
测试安全性漏洞。
创建HardLink
创建 HardLink
微软提供了现成的API操作,如下所示
1 2 3 4 5
| BOOL WINAPI CreateHardLink( _In_ LPCTSTR lpFileName, _In_ LPCTSTR lpExistingFileName, _Reserved_ LPSECURITY_ATTRIBUTES lpSecurityAttributes );
|
使用起来特别简单,lpFileName
是创建的新名称路径,lpExistingFileName
是现有文件路径,
lpSecurityAttributes
系统保留设置为NULL,代码如下
1
| CreateHardLink(L"D:\\a.txt", L"D:\\b.txt", NULL);
|
注意:创建 HardLink
需要请求文件的 FILE_WRITE_ATTRIBUTES
权限,不能跨盘符。
创建MountPoint
创建 MountPoint
没有直接的API函数,我们通过发送 FSCTL_SET_REPARSE_POINT
控制码实现,
而控制码对应的输入参数是 REPARSE_DATA_BUFFER
结构体,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; USHORT ReparseDataLength; USHORT Reserved; union { struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; ULONG Flags; WCHAR PathBuffer[1]; } SymbolicLinkReparseBuffer; struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; WCHAR PathBuffer[1]; } MountPointReparseBuffer; struct { UCHAR DataBuffer[1]; } GenericReparseBuffer; }; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
创建MountPoint的代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| BOOL CreateMountPoint(PCWSTR pSrcDir, PCWSTR pDstDir) { if (!pSrcDir || !pSrcDir[0] || !pDstDir || !pDstDir[0]) return FALSE; HANDLE hFile = CreateFileW(pSrcDir, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE;
USHORT nDstSize = (USHORT)((wcslen(pDstDir) + 1) * sizeof(WCHAR)); DWORD dwHdrSize = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer); DWORD dwSize = dwHdrSize + nDstSize + sizeof(REPARSE_DATA_BUFFER::MountPointReparseBuffer); PREPARSE_DATA_BUFFER pReparse = (PREPARSE_DATA_BUFFER)malloc(dwSize); if (!pReparse) { CloseHandle(hFile); return FALSE; }
ZeroMemory(pReparse, dwSize); pReparse->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; pReparse->ReparseDataLength = nDstSize + sizeof(REPARSE_DATA_BUFFER::MountPointReparseBuffer); memcpy(pReparse->MountPointReparseBuffer.PathBuffer, pDstDir, nDstSize); pReparse->MountPointReparseBuffer.SubstituteNameLength = nDstSize - sizeof(WCHAR); pReparse->MountPointReparseBuffer.PrintNameOffset = nDstSize;
DWORD dwRet = 0; BOOL bOK = DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, pReparse, dwSize, NULL, 0, &dwRet, NULL); CloseHandle(hFile); free(pReparse); return bOK; }
|
删除MountPoint的代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| BOOL DeleteMountPoint(PCWSTR pSrcDir) { if (!pSrcDir || !pSrcDir[0]) return FALSE; HANDLE hFile = CreateFileW(pSrcDir, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE;
REPARSE_GUID_DATA_BUFFER stReparse = { 0 }; stReparse.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; DWORD dwSize = REPARSE_GUID_DATA_BUFFER_HEADER_SIZE;
DWORD dwRet = 0; BOOL bOK = DeviceIoControl(hFile, FSCTL_DELETE_REPARSE_POINT, &stReparse, dwSize, NULL, 0, &dwRet, NULL); CloseHandle(hFile); return bOK; }
|
调用方式如下
1 2
| CreateMountPoint(L"\\??\\C:\\aaa", L"\\??\\D:\\bbb"); DeleteMountPoint(L"\\??\\C:\\aaa");
|