HANDLE AdvanceOpenProcess(DWORD pid, DWORD dwAccessRights) { HANDLE hProcess = OpenProcess(dwAccessRights, FALSE, pid); if (hProcess == NULL) { HANDLE hpWriteDAC = OpenProcess(WRITE_DAC, FALSE, pid); if (hpWriteDAC == NULL) { HANDLE htok; TOKEN_PRIVILEGES tpOld; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &htok)) { return false; } if (EnableTokenPrivilege(htok, SE_TAKE_OWNERSHIP_NAME, &tpOld)) { HANDLE hpWriteOwner = OpenProcess(WRITE_OWNER, FALSE, pid); if (hpWriteOwner != NULL) { BYTE buf[512]; DWORD cb = sizeof buf; if (GetTokenInformation(htok, TokenUser, buf, cb, &cb)) { DWORD err = SetSecurityInfo(hpWriteOwner, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, ((TOKEN_USER *)(buf))->User.Sid, 0, 0, 0); if (err == ERROR_SUCCESS) { if (!DuplicateHandle(GetCurrentProcess(), hpWriteOwner, GetCurrentProcess(), &hpWriteDAC, WRITE_DAC, FALSE, 0)) { hpWriteDAC = NULL; } } } CloseHandle(hpWriteOwner); } AdjustTokenPrivileges(htok, FALSE, &tpOld, 0, 0, 0); } CloseHandle(htok); } if (hpWriteDAC) { AdjustDacl(hpWriteDAC, dwAccessRights); if (!DuplicateHandle(GetCurrentProcess(), hpWriteDAC, GetCurrentProcess(), &hProcess, dwAccessRights, FALSE, 0)) { hProcess = NULL; } CloseHandle(hpWriteDAC); } } return (hProcess); }
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); }