就是说要做一个获取目标进程打开的所有文件的功能,我的想法是先遍历目标进程的所有关联文件句柄,然后根据句柄获取被打开文件的源路径,然后就可以根据路径自行打开了。
现在的问题是我不知道是权限问题还是什么原因,目标文件句柄无法被获取全路径(注意这个文件句柄不属于当前进程,也就是说这个文件是被其他程序打开的)
遍历目标进程的所有关联文件句柄的功能已经实现了,代码如下:
#define _WIN32_WINNT 0x0600
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <Psapi.h>
//#include <ntifs.h>
#pragma comment(lib, "Psapi.lib")
#ifndef STATUS_INFO_LENGTH_MISMATCH
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#endif
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef struct _SYSTEM_HANDLE {
ULONG ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedef struct __SYSTEM_HANDLE_INFORMATION {
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
} _R_SYSTEM_HANDLE_INFORMATION, *_R_PSYSTEM_HANDLE_INFORMATION;
#define SystemHandleInformation 16
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypeInformation 2
std::vector<HANDLE> GetProcessHandles(DWORD processId) {
std::vector<HANDLE> handles;
_NtQuerySystemInformation NtQuerySystemInformation =
(_NtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
if (!NtQuerySystemInformation) {
std::cerr << "Could not find NtQuerySystemInformation" << std::endl;
return handles;
}
_R_PSYSTEM_HANDLE_INFORMATION handleInfo;
ULONG handleInfoSize = 0x10000;
ULONG neededSize;
NTSTATUS status;
handleInfo = (_R_PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize,
&neededSize)) == STATUS_INFO_LENGTH_MISMATCH) {
handleInfo = (_R_PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
}
if (!NT_SUCCESS(status)) {
std::cerr << "NtQuerySystemInformation failed" << std::endl;
return handles;
}
for (ULONG i = 0; i < handleInfo->HandleCount; i++) {
SYSTEM_HANDLE handle = handleInfo->Handles[i];
if (handle.ProcessId == processId) {
handles.push_back((HANDLE)handle.Handle);
}
}
free(handleInfo);
return handles;
}
而这段代码也的确可以获取到目标进程的句柄,这里的目标进程,也就是被获取句柄路径的测试程序代码如下:
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
#ifndef STATUS_INFO_LENGTH_MISMATCH
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#endif
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef struct _SYSTEM_HANDLE {
ULONG ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
#define SystemHandleInformation 16
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypeInformation 2
std::vector<HANDLE> GetProcessHandles(DWORD processId) {
std::vector<HANDLE> handles;
_NtQuerySystemInformation NtQuerySystemInformation =
(_NtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
if (!NtQuerySystemInformation) {
std::cerr << "Could not find NtQuerySystemInformation" << std::endl;
return handles;
}
PSYSTEM_HANDLE_INFORMATION handleInfo;
ULONG handleInfoSize = 0x10000;
ULONG neededSize;
NTSTATUS status;
handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize,
&neededSize)) == STATUS_INFO_LENGTH_MISMATCH) {
handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
}
if (!NT_SUCCESS(status)) {
std::cerr << "NtQuerySystemInformation failed" << std::endl;
return handles;
}
for (ULONG i = 0; i < handleInfo->HandleCount; i++) {
SYSTEM_HANDLE handle = handleInfo->Handles[i];
if (handle.ProcessId == processId) {
handles.push_back((HANDLE)handle.Handle);
}
}
free(handleInfo);
return handles;
}
std::string GetFileNameFromHandle(HANDLE hFile) {
char szTemp[UNICODE_STRING_MAX_CHARS];
HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 1, NULL);
if (hFileMap) {
void *pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (pMem) {
if (GetMappedFileNameA(GetCurrentProcess(), pMem, szTemp, sizeof(szTemp))) {
UnmapViewOfFile(pMem);
CloseHandle(hFileMap);
return szTemp;
}
UnmapViewOfFile(pMem);
}
CloseHandle(hFileMap);
}
return "";
}
int main() {
HANDLE hFile = CreateFileA("N:\\OpenedFilesView\\readme.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE) {
std::string fileName = GetFileNameFromHandle(hFile);
std::cout << std::hex << hFile << std::endl;
std::cout << "File name: " << fileName << std::endl;
}
std::cin.get();
CloseHandle(hFile);
return 0;
}
而下面是我现在用的获取文件句柄全路径的代码,获取当前进程的句柄路径是可以的,但是其他程序都不行:
#include <Windows.h>
#include <tchar.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
// Function to get the file path from a handle (wide character version)
EXTERN_C BOOL GetFilePathFromHandleW(HANDLE hFile, LPWSTR lpszPath, UINT cchMax);
// Function to get the file path from a handle (multibyte character version)
EXTERN_C BOOL GetFilePathFromHandleA(HANDLE hFile, LPSTR lpszPath, UINT cchMax);
// Macro to calculate the number of elements in an array
#ifndef _countof
#define _countof(array) (sizeof(array)/sizeof((array)[0]))
#endif
// Function to get the volume name by handle
EXTERN_C BOOL GetVolumeNameByHandle(HANDLE hFile, LPWSTR szVolumeName, UINT cchMax) {
BOOL bResult = FALSE;
WCHAR szBuf[500] = { 0 };
WCHAR *pIter = szBuf;
int i = 0;
BY_HANDLE_FILE_INFORMATION stFileInfo = { 0 };
// Get file information by handle
if (FALSE == GetFileInformationByHandle(hFile, &stFileInfo)) {
OutputDebugString(_T("GetFileInformationByHandle failed."));
return bResult;
}
// Get logical drive strings
if (0 == GetLogicalDriveStringsW(_countof(szBuf), szBuf)) {
OutputDebugString(_T("GetLogicalDriveStringsW failed."));
return bResult;
}
// Iterate through each drive
for (; pIter; pIter += 4) {
DWORD dwVolumeSerialNumber = 0;
// Get volume information
if (GetVolumeInformationW(pIter, NULL, 0, &dwVolumeSerialNumber, NULL, NULL, NULL, 0)) {
// Compare volume serial number with file's volume serial number
if (dwVolumeSerialNumber == stFileInfo.dwVolumeSerialNumber) {
// Copy volume name to output buffer
lstrcpynW(szVolumeName, pIter, cchMax);
bResult = TRUE;
break;
}
}
}
return bResult;
}
// Structure for IO status block
typedef struct _IO_STATUS_BLOCK {
LONG Status;
LONG Information;
} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
// Structure for file name information
typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength;
WCHAR FileName[MAX_PATH];
} FILE_NAME_INFORMATION;
// Import ZwQueryInformationFile function from ntdll.dll
__declspec(dllimport) LONG __stdcall ZwQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG FileInformationLength,
IN ULONG FileInformationClass
);
// Typedef for ZwQueryInformationFile function
typedef LONG(__stdcall *PFN_ZwQueryInformationFile)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG FileInformationLength,
IN ULONG FileInformationClass
);
// Function to get the file path from a handle (wide character version)
EXTERN_C BOOL GetFilePathFromHandleW(HANDLE hFile, LPWSTR lpszPath, UINT cchMax) {
BOOL bResult = FALSE;
WCHAR szValue[MAX_PATH] = { 0 };
IO_STATUS_BLOCK isb = { 0 };
FILE_NAME_INFORMATION fni = { 0 };
HANDLE hNtDll = NULL;
PFN_ZwQueryInformationFile pfn_ZwQueryInformationFile = NULL;
// Check for invalid parameters
if (INVALID_HANDLE_VALUE == hFile || NULL == lpszPath || 0 == cchMax) {
OutputDebugString(_T("Invalid parameters."));
return bResult;
}
// Get handle to ntdll.dll
hNtDll = GetModuleHandle(_T("ntdll.dll"));
if (NULL == hNtDll) {
OutputDebugString(_T("Failed to get handle to ntdll.dll."));
return bResult;
}
// Get address of ZwQueryInformationFile function
pfn_ZwQueryInformationFile = (PFN_ZwQueryInformationFile)GetProcAddress(reinterpret_cast<HMODULE>(hNtDll),
"ZwQueryInformationFile");
if (NULL == pfn_ZwQueryInformationFile) {
OutputDebugString(_T("Failed to get address of ZwQueryInformationFile."));
return bResult;
}
// Call ZwQueryInformationFile function with class 9 (FileNameInformation)
if (0 != pfn_ZwQueryInformationFile(hFile, &isb, &fni, sizeof(fni), 9)) {
OutputDebugString(_T("ZwQueryInformationFile failed."));
return bResult;
}
// Get volume name by handle
if (FALSE == GetVolumeNameByHandle(hFile, szValue, _countof(szValue))) {
OutputDebugString(_T("GetVolumeNameByHandle failed."));
return bResult;
}
// Append file name to volume name
PathAppendW(szValue, fni.FileName);
// Copy full path to output buffer
lstrcpynW(lpszPath, szValue, cchMax);
bResult = TRUE;
return bResult;
}
// Function to get the file path from a handle (multibyte character version)
EXTERN_C BOOL GetFilePathFromHandleA(HANDLE hFile, LPSTR lpszPath, UINT cchMax) {
BOOL bResult = FALSE;
WCHAR szTmep[MAX_PATH] = { 0 };
// Check for invalid parameters
if (INVALID_HANDLE_VALUE == hFile || NULL == lpszPath || 0 == cchMax) {
OutputDebugString(_T("Invalid parameters."));
return bResult;
}
// Call wide character version of GetFilePathFromHandle
if (FALSE == GetFilePathFromHandleW(hFile, szTmep, _countof(szTmep))) {
OutputDebugString(_T("GetFilePathFromHandleW failed."));
return bResult;
}
// Convert wide character string to multibyte character string
if (0 == WideCharToMultiByte(CP_ACP, 0, szTmep, lstrlenW(szTmep), lpszPath, cchMax, NULL, NULL)) {
OutputDebugString(_T("WideCharToMultiByte failed."));
return bResult;
}
bResult = TRUE;
return bResult;
}
#include <iostream>
using namespace std;
int main() {
CHAR RetCHAR[1145];
HANDLE hf/* = CreateFileA("N:\\OpenedFilesView\\readme.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)*/;
cin >> hf;
if (!GetFilePathFromHandleA(hf, RetCHAR, 1145)) {
cout << "fuck!";
}
cout << RetCHAR;
cin.get();
cin.get();
cin.get();
return 0;
}
不胜感激!