-1

I want to retrieve all file paths that are accessed by processes in my OS. List of processes is retrieved and those has correct handle values. So now I want to use GetFinalPathNameByHandle function to get path to those files, but Path variable is the same for all records. I need a hand here guys.

Source code is here: http://pastebin.com/nU26Vcsd or here if pastebin is not accessible http://hastebin.com/wahudogawa.avrasm

Line 66 is where I need help. Path is the same for each file handler of the tested process and is equal to the path where this program is executed( and not the process start folder).

I run it as: testprogram.exe | grep 5231 where 5231 is a PID of the process I need.

Results looks like:

PID: 5231        FileHandlePid: 44       The final path is: \Device\HarddiskVolume4\KillFileHandle\C++\Debug

While those should be like:

PID: 5231        FileHandlePid: 44       The final path is: \Device\HarddiskVolume2\Users\username\AppData\Roaming\testapp

Or correct me please if I am wrong in expected result.


Latest addition:

Thanks to @Raymond Chen comments I am trying to move forward and use DuplicateHandle() funtion. So far I've updated code (hardcoded pid for now, sorry) , added HandleValueTemp, trying to pass it to DuplicateHandle. The output is changed to nonprintable characters.

for (i = 0; i < hCount; ++i)
if ((hFirstEntry[i].ObjectType == 28))
{
    HANDLE TargetHandleValueTemp = (HANDLE)hFirstEntry[i].HandleValue;
    HANDLE SourceProcHandleTemp = OpenProcess(PROCESS_DUP_HANDLE, FALSE, hFirstEntry[i].OwnerPid);

    if (!DuplicateHandle(SourceProcHandleTemp, (HANDLE)hFirstEntry[i].HandleValue, GetCurrentProcess(), &TargetHandleValueTemp, 0, FALSE, DUPLICATE_SAME_ACCESS))
    {
        cout << "Error in DuplicateHandle"
    }

    CloseHandle(SourceProcHandleTemp);
    TCHAR Path[MAX_PATH];
    DWORD dwret = GetFinalPathNameByHandle(TargetHandleValueTemp, Path, MAX_PATH, 0);
    _tprintf(TEXT("PID: %d\tFileHandle: %d\tThe final path is: %s\n"), hFirstEntry[i].OwnerPid, TargetHandleValueTemp, Path);
    CloseHandle(TargetHandleValueTemp);
}

Digging further and looking in comments from time to time. Maybe this code can be useful to someone else here.

Artur Korobeynyk
  • 955
  • 1
  • 9
  • 24
  • 1
    Undocumented APIs are undocumented. Also, handles don't work like that. – Raymond Chen Oct 21 '14 at 13:57
  • I'm trying to use this answer as a basis for implementation: http://stackoverflow.com/a/25430061/677176 – Artur Korobeynyk Oct 21 '14 at 14:01
  • 1
    "This is assuming all the files you need to delete are owned by the process doing the deletion." Also, forcing handles closed can cause data corruption and other "impossible" bugs. You are creating short-term relief at a cost of long-term pain. Also, include the code here rather on an external site. – Raymond Chen Oct 21 '14 at 14:03
  • That is what I need. I am not developing an application, I need to access files owned and locked by tested application and corrupt those in any way (removing or adding some random bits) from my code. So this is more a stability test then an app itself. – Artur Korobeynyk Oct 21 '14 at 14:06
  • 2
    "If any of the files belong to another process you will need an extra step using DuplicateHandle()." But in this case, you aren't trying to force the handle closed. Also, you would be better off having a debugging or unit testing hook so the tested application can explicitly provide the handle instead of making you go hunting for it. That way, you can avoid using undocumented APIs. – Raymond Chen Oct 21 '14 at 14:12
  • Thanks @Raymond. I am trying to move further with DuplicateHandle(). Updated question description. Will try to see what could be done next. – Artur Korobeynyk Oct 21 '14 at 14:54
  • I get the impression you are just fumbling around without trying to understand what you're doing. Read the documentation for `DuplicateHandle` to see what the parameters are supposed to be. – Raymond Chen Oct 21 '14 at 15:29
  • Updated look. DuplicateHandle now works without throwing an error. But Path variable after GetFinalPathByName still has not printable characters. Ideas @RaymondChen? – Artur Korobeynyk Oct 21 '14 at 20:16
  • 1
    You aren't checking for errors from GetFinalPathByName. – Harry Johnston Oct 21 '14 at 20:43
  • You are right @HarryJohnston . GetFinalPathByName returns error code 6, which is "The handle is invalid". So no idea further. – Artur Korobeynyk Oct 22 '14 at 07:06
  • 1
    Soon found the reason. Looks like in Windows 8.1 the SystemHandleInformation ObjectType for files should be 30 and not 28 as in previous versions. Now works – Artur Korobeynyk Oct 22 '14 at 07:10

1 Answers1

0

Thanks to @RaymondChen and @HarryJohnston comments in question I was able to get to working result. I leave it here for case when someone else needs that. The code is a bit crappy but further formatting is up to you. Remember to update OwnerPid in loop to your own when testing.

#include <Windows.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <iostream>

#define START_ALLOC                 0x1000
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define SystemHandleInformation     0x10

typedef long(__stdcall *NtQSI)(
ULONG  SystemInformationClass,
PVOID  SystemInformation,
ULONG  SystemInformationLength,
PULONG ReturnLength
);

typedef struct _SYSTEM_HANDLE_ENTRY {
ULONG  OwnerPid;
BYTE   ObjectType;
BYTE   HandleFlags;
USHORT HandleValue;
PVOID  ObjectPointer;
ACCESS_MASK  AccessMask;
} SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY;

int main()
{
HMODULE hNtDll = NULL;
NtQSI   pNtQSI = NULL;
PVOID   pMem = NULL;
ULONG   allocSize = START_ALLOC;
ULONG   retVal = 0;
// --------------------------------
ULONG   hCount = 0;
PSYSTEM_HANDLE_ENTRY hFirstEntry = NULL;
// --------------------------------
ULONG   i;

hNtDll = LoadLibraryA("NTDLL.dll");

if (!hNtDll)
    return 1;

pNtQSI = (NtQSI)GetProcAddress(hNtDll, "NtQuerySystemInformation");

if (!pNtQSI) {
    FreeLibrary(hNtDll);
    return 2;
}

pMem = malloc(allocSize);

while (pNtQSI(SystemHandleInformation, pMem, allocSize, &retVal)
    == STATUS_INFO_LENGTH_MISMATCH) {
    pMem = realloc(pMem, allocSize *= 2);
}

hCount = *(ULONG*)pMem;
hFirstEntry = (PSYSTEM_HANDLE_ENTRY)((PBYTE)pMem + 4);

for (i = 0; i < hCount; ++i)
if ((hFirstEntry[i].ObjectType == 30) && (hFirstEntry[i].OwnerPid == 5628))
{
    HANDLE TargetHandleValueTemp = (HANDLE)hFirstEntry[i].HandleValue;
    HANDLE SourceProcHandleTemp = OpenProcess(PROCESS_DUP_HANDLE, FALSE, hFirstEntry[i].OwnerPid);

    if (!DuplicateHandle(SourceProcHandleTemp, (HANDLE)hFirstEntry[i].HandleValue, GetCurrentProcess(), &TargetHandleValueTemp, 0, FALSE, DUPLICATE_SAME_ACCESS))
    {
        TargetHandleValueTemp = (HANDLE)hFirstEntry[i].HandleValue;
    }

    CloseHandle(SourceProcHandleTemp);
    TCHAR Path[MAX_PATH];
    DWORD dwret = GetFinalPathNameByHandle(TargetHandleValueTemp, Path, MAX_PATH, 0);
    _tprintf(TEXT("PID: %d\tFileHandle: %d\tThe final path is: %s\n"), hFirstEntry[i].OwnerPid, TargetHandleValueTemp, Path);
    CloseHandle(TargetHandleValueTemp);
}

free(pMem);
FreeLibrary(hNtDll);
}
Artur Korobeynyk
  • 955
  • 1
  • 9
  • 24