How to Obtain a Handle to Any Process with SeDebugPrivilegeLast reviewed: September 25, 1995Article ID: Q131065 |
The information in this article applies to:
SUMMARYIn Windows NT, you can retrieve a handle to any process in the system by enabling the SeDebugPrivilege in the calling process. The calling process can then call the OpenProcess() Win32 API to obtain a handle with PROCESS_ALL_ACCESS.
MORE INFORMATIONThis functionality is provided for system-level debugging purposes. For debugging non-system processes, it is not necessary to grant or enable this privilege. This privilege allows the caller all access to the process, including the ability to call TerminateProcess(), CreateRemoteThread(), and other potentially dangerous Win32 APIs on the target process. Take great care when granting SeDebugPrivilege to users or groups.
Sample CodeThe following source code illustrates how to obtain SeDebugPrivilege in order to get a handle to a process with PROCESS_ALL_ACCESS. The sample code then calls TerminateProcess on the resultant process handle.
/*++The SeDebugPrivilege allows you to open any process for debugging purposes. After enabling the privilege, you can open a target process by using OpenProcess() with PROCESS_ALL_ACCESS. By default, this privilege is granted only to SYSTEM and the local Administrators group. User Manager | Policies | User Rights | Show Advanced User Rights | Debug Programs can be used to grant or revoke this privilege to arbitrary users or groups. WARNING: This privilege allows all access to a process. A malevolent user could open a system process, create a remote thread in the system process, and execute code in the system security context. Great care must be used when giving out this privilege --*/
#define RTN_OK 0 #define RTN_USAGE 1 #define RTN_ERROR 13 #include <windows.h> #include <stdio.h>BOOL SetPrivilege( HANDLE hToken, // token handle LPCTSTR Privilege, // Privilege to enable/disable BOOL bEnablePrivilege // TRUE to enable. FALSE to disable ); void DisplayError(LPTSTR szAPI); int main(int argc, char *argv[]){ HANDLE hProcess; HANDLE hToken; int dwRetVal=RTN_OK; // assume success from main() // show correct usage for kill if (argc != 2) { fprintf(stderr,"Usage: %s [ProcessId]\n", argv[0]); return RTN_USAGE; } if(!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken )) return RTN_ERROR; // enable SeDebugPrivilege if(!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE)) { DisplayError("SetPrivilege"); // close token handle CloseHandle(hToken); // indicate failure return RTN_ERROR; } // open the process if((hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, atoi(argv[1]) // PID from commandline )) == NULL) { DisplayError("OpenProcess"); return RTN_ERROR; } // disable SeDebugPrivilege SetPrivilege(hToken, SE_DEBUG_NAME, FALSE); if(!TerminateProcess(hProcess, 0xffffffff)) { DisplayError("TerminateProcess"); dwRetVal=RTN_ERROR; } // close handles CloseHandle(hToken); CloseHandle(hProcess); return dwRetVal;} BOOL SetPrivilege( HANDLE hToken, // token handle LPCTSTR Privilege, // Privilege to enable/disable BOOL bEnablePrivilege // TRUE to enable. FALSE to disable ){ TOKEN_PRIVILEGES tp; LUID luid; TOKEN_PRIVILEGES tpPrevious; DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES); if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE; // // first pass. get current privilege setting // tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0; AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious ); if (GetLastError() != ERROR_SUCCESS) return FALSE; // // second pass. set privilege based on previous setting // tpPrevious.PrivilegeCount = 1; tpPrevious.Privileges[0].Luid = luid; if(bEnablePrivilege) { tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); } else { tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); } AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL ); if (GetLastError() != ERROR_SUCCESS) return FALSE; return TRUE;}
void DisplayError( LPTSTR szAPI // pointer to failed API name ){ LPTSTR MessageBuffer; DWORD dwBufferLength; fprintf(stderr,"%s() error!\n", szAPI); if(dwBufferLength=FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), GetSystemDefaultLangID(), (LPTSTR) &MessageBuffer, 0, NULL )) { DWORD dwBytesWritten; // // Output message string on stderr // WriteFile( GetStdHandle(STD_ERROR_HANDLE), MessageBuffer, dwBufferLength, &dwBytesWritten, NULL ); // // free the buffer allocated by the system // LocalFree(MessageBuffer); }}
|
Additional reference words: 3.10 3.50 3.51 OpenProcess TerminateProcess
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |