试图抓取,复制和保护与NTDLL的句柄
问题描述:
所以我试图基本上循环低谷的进程,找到我的进程(工程)的进程ID,然后打开一个进程与该PID(这也适用)和然后用NtDuplicateObject复制它并用NtSetInformationObject保护它。试图抓取,复制和保护与NTDLL的句柄
问题是总会有些问题。第一次尝试时,它不想复制它,直到现在快进了,然后在注释掉我试图关闭旧句柄的部分(我不能这样做,NtDuplicateObject也不应该这样做)给我一个句柄,但我不能用它来写writeprocessmemory或类似的东西。我将张贴在这里的功能,并在hastebin链接的完整代码(如果有在我的代码需要一些拼接的混乱)
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);
}
答
在粗略地看一眼,我认为问题可能是您拨打GetProcessHandle。返回一个伪句柄(常量),该OS知道的意思是“当前进程”:
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.
现在,我可能是错的,因为我只是看了看你的代码,但如果你使用这个API,那么你肯定不能复制从它返回的任何句柄(因为它不是一个真正的句柄,只是一个常量)。
编号:https://msdn.microsoft.com/en-us/library/windows/desktop/ms683179(v=vs.85).aspx
我很好奇你的意图和代码的描述之间的差距。为什么遍历所有进程只是为了找到自己的进程?您可以通过一个API调用获得它的PID(例如GetProcessID)。
所以,你可以将代码更改为类似(这留下的伪句柄“泄漏”,但由于它是不是一个真正的手柄,没有泄漏!):
HANDLE hRealHandle=OpenProcess(GetProcesssId(GetCurrentProcess()), ...);
当然, NT Native API的等价物很容易确定,如果你更喜欢它们,我会把它留给你,如果这甚至有帮助。
我不想用我自己的过程做到这一点,我想要做的,基本上任何其他过程。那是我的意图 –
啊,“我的*进程”语言让我困惑。当我仔细观察代码时,不清楚使用这个常量是否会成为问题。可能不会,否则你会看到它。 –