Hi I was trying to suspend a remote thread, but en route I’m stumbled upon DuplicateHandle failure with error 6, ERROR_INVALID_HANDLE .
The below method works fine for the current process, but if a remote process like “calc” (in the same host machine) is given, the DuplicateHandle fails.
The process runs with Admin priv and the SeDebugPriv and SeSecurityPriv is granted (Process Explorer confirms it), but no use. Any idea?
`
bool DbgHelpWrapper::GetThreadStartAddress( IntPtr processHandle, DWORD processId, DWORD threadID, DWORD *dwStartAddress )
{
// Get ntdll entry points.
HMODULE ntDLLHandle = LoadLibrary(L"ntdll.dll");
tNtQueryInformationThread NtQueryInformationThread = (tNtQueryInformationThread)GetProcAddress(ntDLLHandle, "NtQueryInformationThread");
// Open thread with wrong access rights.
HANDLE hRemoteProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, processId );
HANDLE hRemoteThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadID);
if (hRemoteThread != 0 && hRemoteProcess != 0 )
{
try
{
// Duplicate handle to get correct access rights.
HANDLE temporaryHandle = 0;
DWORD duplicateHandleResult = DuplicateHandle(hRemoteProcess, hRemoteThread, GetCurrentProcess(),
&temporaryHandle, THREAD_QUERY_INFORMATION, FALSE, 0 );
System::Console::WriteLine( String::Format("DuplicateHandle returned {0}", duplicateHandleResult ));
System::Console::WriteLine( String::Format("DuplicateHandle error {0}", Marshal::GetLastWin32Error()));
if (duplicateHandleResult != 0 )
{
try
{
NTSTATUS ntStatus = NtQueryInformationThread(temporaryHandle, ThreadQuerySetWin32StartAddress, dwStartAddress, sizeof(DWORD), NULL);
System::Console::WriteLine( String::Format("NtQueryInformationThread returned {0}", ntStatus ));
if (ntStatus == 0)
{
System::Console::WriteLine( String::Format("StartAddress: {0:X16}", *dwStartAddress ));
return true;
}
else
{
System::Console::WriteLine( String::Format("NtQueryInformationThread error {0}", Marshal::GetLastWin32Error()));
return false;
}
}
finally
{
CloseHandle(temporaryHandle);
}
}
else
{
System::Console::WriteLine( String::Format("Cannot duplicate the thread handle to THREAD_QUERY_INFORMATION rights"));
return false;
}
}
finally
{
// Cleanup
CloseHandle(hRemoteThread);
}
}
else
{
System::Console::WriteLine( String::Format("Cannot open the thread with THREAD_SUSPEND_RESUME rights"));
return FALSE;
}
}
`
You’re telling
DuplicateHandlethathRemoteThreadis a handle inhRemoteProcess, but it isn’t. It’s a handle in your current process – you opened it a few lines before. (The thread is part of the remote process, but the handle to it isn’t.)