opening a process with SE_DEBUG_NAME privilege

To open a process successfully, the opener should be allowed in the DACL ( discretionary access control list ). So, I also tried adding an ACE, Access Control Entries, to the DACL. At least all who tried seem to think that way after reading MSDN documents. Yeah..

Then, this kind of code will be written.

HANDLE hProcess, hCommandEventLocal, hAllocationEventLocal;

BOOL isOK;
HANDLE hToken;

///////////////////////////////////////////////
// Setting SE_DEBUG_NAME
// First, get an access token for the process
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, processId ); // 1
if( hProcess == NULL )
{
	PrintError(”Failing in getting a process handle with PROCESS_QUERY_INFORMATION at %d (Error Code : %d)”,
				__LINE__, GetLastError());
	return E_FAIL;
}

// Second, get the access token for the process
isOK = OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ); // 2
if( !isOK )
{
	PrintError(”Failing in getting a token handle at %d (Error Code : %d)”,
				__LINE__, GetLastError());
	return E_FAIL;
}

SetPrivilege( hToken, SE_DEBUG_NAME, TRUE );

CloseHandle( hToken );
CloseHandle( hProcess );

//////////////////////////////////////////////////////////////////////

hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, processId ); // 3

The code looks reasonable, doesn’t it?
While writing this code, I found one thing weird.
To open a process with PROCESS_DUP_HANDLE, you need a SeDebugPrivilege. To set SeDebugPrivilege, i.e SE_DEBUG_NAME, you need a token. To get a token, you need an open handle to the process. Oh.. circular dependency!!!!!
So, I tried opening a process with PROCESS_QUERY_INFORMATION.
However this fails at 2. Why? I don’t know there is no explanation on MSDN documents.

Huge barrier!!!!

However, I found a post from MSDN community forum. He also tried codes shown above, but found out the correct way to achieve the goal.
How?

HANDLE hProcess, hCommandEventLocal, hAllocationEventLocal;

BOOL isOK;
HANDLE hToken;
HANDLE hCurrentProcess;
hCurrentProcess = GetCurrentProcess(); // 1
isOK = OpenProcessToken( hCurrentProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );
if( !isOK )
{
    return E_FAIL;
}

SetPrivilege( hToken, SE_DEBUG_NAME, TRUE );

//////////////////////////////////////////////////////////////////////

hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, processId );

Differences are to open current process instead of the target process, and set the token of the current process to have the SeDebugPrivilege. The the token of the current process have all the privilege to open other processes the way it wants.

Weird!!!! Isn’t it? It is totally different approach than the direction set by the MSDN documents.
Yeah…. MSDN documents.. as usual.

But if you think more, you can figure out why it works.
Probably default DACL can have an ACE like “allow any process with SeDebugPrivilege to open any process anyway it wants.”.
Then it is reasonable.
Why doesn’t MSDN document have this kind of explanation?
Um………………..

P.S. There is a related post at bits and bytes blog.

4 responses to this post.

  1. Yup, you got to open the current process, instead of the target process, I am surprised if MSDN has mentioned this wrongly. :)

    Reply

  2. Posted by jongampark on September 30, 2008 at 11:19 PM

    Well, actually MSDN didn’t explain anything. So, I can’t say that it explained about it “wrongly”. Problem is that it makes people who read the document think the way I thought. :)

    Reply

  3. Posted by Coder on July 15, 2009 at 4:11 AM

    This is how i do mine. Could come in usefull for anyone. Hasn’t failed me yet.

    BOOL SetPrivilege( HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege )
    {
    TOKEN_PRIVILEGES pTokenPrivileges;
    LUID luid;

    if( !LookupPrivilegeValue( NULL, lpszPrivilege, &luid ) ) { return FALSE; }

    pTokenPrivileges.PrivilegeCount = 1;
    pTokenPrivileges.Privileges[ 0 ].Luid = luid;

    if( bEnablePrivilege ) { pTokenPrivileges.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED; }

    else { pTokenPrivileges.Privileges[ 0 ].Attributes = 0; }

    if( !AdjustTokenPrivileges( hToken, FALSE, &pTokenPrivileges, sizeof( TOKEN_PRIVILEGES ), NULL, NULL ) ) { return FALSE; }

    if( GetLastError( ) == ERROR_NOT_ALL_ASSIGNED ) { return FALSE; }

    return TRUE;
    }

    void SetProcessPrivilege( )
    {
    HANDLE pToken = NULL;

    OpenProcessToken( GetCurrentProcess( ), TOKEN_ALL_ACCESS, &pToken );
    SetPrivilege( pToken, SE_DEBUG_NAME, true );
    }

    Reply

Leave a comment