-2

So I am trying to basically loop trough the processes, find the process id of my process (which works), then open a process with that pid (which also works) and then duplicate it with NtDuplicateObject and protect it with NtSetInformationObject.

The problem is that there's always something wrong. First time I tried it it didn't want to duplicate it, fast forward until now and after commenting out the part where I try to close the old handle (which I can't do and the NtDuplicateObject shouldn't do it either) it gives me a handle but I can't use it for writeprocessmemory or anything like that. I will post the function here and the full code in a hastebin link (in case there are confusions in my code that need some stitching)

HANDLE PROTO_HAND::GrabPerfectHandle(const wchar_t *__processName)
{
    if (__processName == nullptr)
        return reinterpret_cast<HANDLE>(PRH_ERR_BADPARAM);

    NTSTATUS __returnError;

    SYSTEM_PROCESS_INFORMATION *__systemProcessInfo;
    void *__systemInfo;
    void *__allocationBuffer;

    __allocationBuffer = VirtualAlloc(0, 1024 * 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    if (!__allocationBuffer)
        return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTALLOC);

    __systemProcessInfo = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(__allocationBuffer);

    if (!NT_SUCCESS(__returnError = NtQuerySystemInformation(SystemProcessInformation, __systemProcessInfo, 1024 * 1024, 0)))
    {
        if (!VirtualFree(__allocationBuffer, 0, MEM_RELEASE))
            return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTDEALLOC);

        return reinterpret_cast<HANDLE>(PRH_ERR_NTQUERYFAIL);
    }

    while (__systemProcessInfo->NextEntryOffset)
    {
        if (__systemProcessInfo->ImageName.Buffer != nullptr)
        {
            if (wcscmp(__systemProcessInfo->ImageName.Buffer, __processName) == 0)
            {
                HANDLE __basicHandle = OpenProcess(PROCESS_ALL_ACCESS, false, __systemProcessInfo->UniqueProcessId);
                HANDLE __perfectHandle{ 0 };

                if (!__basicHandle)
                {
                    if (!VirtualFree(__allocationBuffer, 0, MEM_RELEASE))
                        return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTDEALLOC);

                    return reinterpret_cast<HANDLE>(PRH_ERR_OPENPROCFAIL);
                }

                if (!NT_SUCCESS(NtDuplicateObject(GetCurrentProcess(), __basicHandle, GetCurrentProcess(), &__perfectHandle, PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ACCESS)))
                {
                    if (!VirtualFree(__allocationBuffer, 0, MEM_RELEASE))
                        return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTDEALLOC);

                    return reinterpret_cast<HANDLE>(PRH_ERR_DUPHANDFAIL);
                }

                /*if(!NtClose(__basicHandle))
                {
                    if (!VirtualFree(__allocationBuffer, 0, MEM_RELEASE))
                        return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTDEALLOC);

                    if(!CloseHandle(__basicHandle))
                        return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTCLOSEHAND);

                    return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTCLOSEHAND);
                }

                if(__basicHandle != nullptr)
                {
                    if (!VirtualFree(__allocationBuffer, 0, MEM_RELEASE))
                        return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTDEALLOC);

                    return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTCLOSEHAND);
                }*/

                _OBJECT_HANDLE_FLAG_INFORMATION __objectInformation{ 0 };
                __objectInformation.ProtectFromClose = { true };

                if (!NT_SUCCESS(NtSetInformationObject(__perfectHandle, ObjectHandleFlagInformation, &__objectInformation, sizeof(_OBJECT_HANDLE_FLAG_INFORMATION))))
                {
                    if (!VirtualFree(__allocationBuffer, 0, MEM_RELEASE))
                        return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTDEALLOC);

                    return reinterpret_cast<HANDLE>(PRH_ERR_PFCFAIL);
                }

                if (!VirtualFree(__allocationBuffer, 0, MEM_RELEASE))
                    return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTDEALLOC);

                return __perfectHandle;
            }
        }

        __systemProcessInfo = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(reinterpret_cast<BYTE*>(__systemProcessInfo) + __systemProcessInfo->NextEntryOffset);
    }

    if (!VirtualFree(__allocationBuffer, 0, MEM_RELEASE))
        return reinterpret_cast<HANDLE>(PRH_ERR_CANNOTDEALLOC);

    return reinterpret_cast<HANDLE>(PRH_ERR_FELLTROUGH);
}

Full : https://hastebin.com/moyehijehe.cpp

Shaggy Doo
  • 15
  • 4

1 Answers1

0

At a cursory glance, I think the problem may be your call of GetProcessHandle. That returns a pseudo-handle (a constant) that the OS knows means 'the current process':

A pseudo handle is a special constant, currently (HANDLE)-1, that is interpreted as the current process handle. For compatibility with future operating systems, it is best to call GetCurrentProcess instead of hard-coding this constant value. The calling process can use a pseudo handle to specify its own process whenever a process handle is required. Pseudo handles are not inherited by child processes.

Now, I may be wrong, as I just glanced at your code, but if you use this API, then you certainly can NOT duplicate any handle returned from it (as it is not a real handle, just a constant).

Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683179(v=vs.85).aspx

I am curious about the disparity between your description of intent and the code. Why iterate through all processes just to find your own process? You can get it's PID with a single API call (e.g. GetProcessID).

So you could change your code to something like (this leaves the pseudo-handle 'leaked', but since it isn't really a handle, nothing is leaked!):

HANDLE hRealHandle=OpenProcess(GetProcesssId(GetCurrentProcess()), ...);

Of course, the NT Native API equivalents are easy to ascertain, if you prefer them, and I'll leave that to you, if this is even helpful.

dyasta
  • 2,056
  • 17
  • 23
  • I don't want to do this with my own process, I want to do it with, well, basically any other process. That was my intent – Shaggy Doo Sep 24 '17 at 17:54
  • Ah, the "*my* process" language confused me. As I look closer at the code, it is unclear if use of this constant would be an issue. Probably not, else you'd have seen it. – dyasta Sep 24 '17 at 22:18