Попытка захватить, продублировать и защитить ручку с помощью NTDLL
Поэтому я пытаюсь в основном циклически проходить через процессы, находить идентификатор процесса моего процесса (который работает), затем открывать процесс с этим pid (который также работает), а затем дублировать его с помощью NtDuplicateObject и защищать его с помощью NtSetInformationObject.
Проблема в том, что всегда что-то не так. В первый раз, когда я попробовал это, он не хотел дублировать это, перемотка вперед до настоящего момента и после комментирования части, где я пытаюсь закрыть старый дескриптор (что я не могу сделать, и NtDuplicateObject не должен это делать) дает мне дескриптор, но я не могу использовать его для записи процесса или что-то подобное. Я опубликую функцию здесь и полный код в ссылке на 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);
}
1 ответ
На первый взгляд, я думаю, что проблема может заключаться в вашем вызове GetProcessHandle. Это возвращает псевдо-дескриптор (константа), который знает ОС, означает "текущий процесс":
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
Мне любопытно о несоответствии между вашим описанием намерений и кодом. Зачем повторять все процессы, чтобы найти свой собственный процесс? Вы можете получить его PID с помощью одного вызова API (например, GetProcessID).
Таким образом, вы можете изменить свой код на что-то вроде (это оставляет псевдо-дескриптор "просочившимся", но, поскольку это не действительно дескриптор, ничего не просочилось!)
HANDLE hRealHandle=OpenProcess(GetProcesssId(GetCurrentProcess()), ...);
Конечно, эквиваленты NT Native API легко определить, если вы предпочитаете их, и я оставлю это вам, если это даже полезно.