Здравствуйте, Hare, Вы писали:
H>Как можно получить Handle чужого процесса?
вот линк на кусок кода от "производителя":
ms-help://MS.MSDNQTR.2005APR.1033/perfmon/base/taking_a_snapshot_and_viewing_processes.htm
если есть 2005й мсдн должен сработать.
Вообще там все просто — делают снимок текущих процессов CreateToolhelp32Snapshot().
и дальше можно ходить по нему Process32First/Process32Next,
Другой вариант — пожрать память самому
и позвать EnumProcesses(), а получив
ID, звать OpenProcess(), как советовал SkyKnight...
Здравствуйте, Hare, Вы писали:
H>Как можно получить Handle чужого процесса?
Есть 3 базовых способа получать чужие process handles:
—
OpenProcess
—
DuplicateHandle — тоже вполне вариант кому-то что-то отдать
— Inheritance (see
CreateProcess and friends)
+ Native API от ntdll.dll
Есть несколько широко известных вспомогательных оберток над приведенным добром:
— PSAPI (
Platform SDK: Performance Monitoring Enumerating All Processes)
— PDH (
Platform SDK: Performance Monitoring Enumerating Process Objects)
И соотв оберток уровнем повыше (для VB и .Net любителей к примеру), ибо можно до процесса добраться
— через WMI (
Platform SDK: Windows Management Instrumentation Win32_Process)
— через
Process.Handle Property of System.Diagnostics.Process component
Наверняка есть еще тонна оберток разного уровня, но это все суть обертки над базовыми ср-ми + знание внутренних структур у native ф-ий. к примеру в PSAPI все ИМХО построено на вызове из ntdll.dll
NtQueryInformationProcess и т.п. системных информационных сервисов для "внутреннего" пользования. Впрочем они уже давно секреты Полишинеля)
2 deadSLAYER: ссылку можно давать не на локальный MSDN, а пользуясь тагом MSDN как показано выше
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Здравствуйте, Hare, Вы писали:
H>Как можно получить Handle чужого процесса?
GetProcessHandleWithEnoughRights
//--------------------------------------------------------------------
// based on Keith Brown (MSJ August 1999 column)
//
BOOL AdjustDacl(HANDLE h, DWORD DesiredAccess)
{
// the WORLD Sid is trivial to form programmatically (S-1-1-0)
SID world = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, 0 };
EXPLICIT_ACCESS ea =
{
DesiredAccess,
SET_ACCESS,
NO_INHERITANCE,
{
0, NO_MULTIPLE_TRUSTEE,
TRUSTEE_IS_SID,
TRUSTEE_IS_USER,
reinterpret_cast<LPTSTR>(&world)
}
};
ACL* pdacl = 0;
DWORD err = SetEntriesInAcl(1, &ea, 0, &pdacl);
if (err == ERROR_SUCCESS)
{
err = SetSecurityInfo(h, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, pdacl, 0);
LocalFree(pdacl);
return(err == ERROR_SUCCESS);
}
else
return(FALSE);
};
// Useful helper function for enabling a single privilege
BOOL EnableTokenPrivilege(HANDLE htok, LPCTSTR szPrivilege, TOKEN_PRIVILEGES& tpOld)
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (LookupPrivilegeValue(0, szPrivilege, &tp.Privileges[0].Luid))
{
// htok must have been opened with the following permissions:
// TOKEN_QUERY (to get the old priv setting)
// TOKEN_ADJUST_PRIVILEGES (to adjust the priv)
DWORD cbOld = sizeof tpOld;
if (AdjustTokenPrivileges(htok, FALSE, &tp, cbOld, &tpOld, &cbOld))
// Note that AdjustTokenPrivileges may succeed, and yet
// some privileges weren't actually adjusted.
// You've got to check GetLastError() to be sure!
return(ERROR_NOT_ALL_ASSIGNED != GetLastError());
else
return(FALSE);
}
else
return(FALSE);
}
BOOL EnablePrivilege(LPCTSTR szPrivilege)
{
BOOL bReturn = FALSE;
HANDLE hToken;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
return(FALSE);
TOKEN_PRIVILEGES tpOld;
bReturn = (EnableTokenPrivilege(hToken, szPrivilege, tpOld));
// don't forget to close the token handle
::CloseHandle(hToken);
return(bReturn);
}
// Corresponding restoration helper function
BOOL RestoreTokenPrivilege(HANDLE htok, const TOKEN_PRIVILEGES& tpOld)
{
return(AdjustTokenPrivileges(htok, FALSE, const_cast<TOKEN_PRIVILEGES*>(&tpOld), 0, 0, 0));
}
HANDLE GetProcessHandleWithEnoughRights(DWORD PID, DWORD AccessRights)
{
HANDLE hProcess = ::OpenProcess(AccessRights, FALSE, PID);
if (hProcess == NULL)
{
HANDLE hpWriteDAC = OpenProcess(WRITE_DAC, FALSE, PID);
if (hpWriteDAC == NULL)
{
// hmm, we don't have permissions to modify the DACL...
// time to take ownership...
HANDLE htok;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &htok))
return(FALSE);
TOKEN_PRIVILEGES tpOld;
if (EnableTokenPrivilege(htok, SE_TAKE_OWNERSHIP_NAME, tpOld))
{
// SeTakeOwnershipPrivilege allows us to open objects with
// WRITE_OWNER, but that's about it, so we'll update the owner,
// and dup the handle so we can get WRITE_DAC permissions.
HANDLE hpWriteOwner = OpenProcess(WRITE_OWNER, FALSE, PID);
if (hpWriteOwner != NULL)
{
BYTE buf[512]; // this should always be big enough
DWORD cb = sizeof buf;
if (GetTokenInformation(htok, TokenUser, buf, cb, &cb))
{
DWORD err =
SetSecurityInfo(
hpWriteOwner,
SE_KERNEL_OBJECT,
OWNER_SECURITY_INFORMATION,
reinterpret_cast<TOKEN_USER*>(buf)->User.Sid,
0, 0, 0
);
if (err == ERROR_SUCCESS)
{
// now that we're the owner, we've implicitly got WRITE_DAC
// permissions, so ask the system to reevaluate our request,
// giving us a handle with WRITE_DAC permissions
if (
!DuplicateHandle(
GetCurrentProcess(),
hpWriteOwner,
GetCurrentProcess(),
&hpWriteDAC,
WRITE_DAC, FALSE, 0
)
)
hpWriteDAC = NULL;
}
}
// don't forget to close handle
::CloseHandle(hpWriteOwner);
}
// not truly necessary in this app,
// but included for completeness
RestoreTokenPrivilege(htok, tpOld);
}
// don't forget to close the token handle
::CloseHandle(htok);
}
if (hpWriteDAC)
{
// we've now got a handle that allows us WRITE_DAC permission
AdjustDacl(hpWriteDAC, AccessRights);
// now that we've granted ourselves permission to access
// the process, ask the system to reevaluate our request,
// giving us a handle with right permissions
if (
!DuplicateHandle(
GetCurrentProcess(),
hpWriteDAC,
GetCurrentProcess(),
&hProcess,
AccessRights,
FALSE,
0
)
)
hProcess = NULL;
CloseHandle(hpWriteDAC);
}
}
return(hProcess);
}