C
chupper
Guest
Hi, I've seen lots of posts about this on line, but it appears that no
one ever gets it to work.
I'm trying to open a process, other than mine, and get the username
the process is running as.
I've found .net code which does this via
System.Management.ManagementObject, but it's slow, apparently runs via
WMI, and I'd just rather do it natively.
Taskmanager does it fine.
I'm running as local admin and trying to view the owner of a process
that was spawned with the runas cmd.
Yet I can't. I get access denied no matter what I do. What am I
missing? Why does the wmi work? It's got to be just using winapi
down below anyway, perhaps it's because of the privileges the wmi
service is running as?
Here's my code, mostly copied, I believe via a MS page.
Can someone tell me what I need to do?
I've tried adjusting my token and the other processes.
Would it be easier to just ::CreateRemoteThread and do it the hard
way?
I can't get past the OpenProcessToken when the proc handle is the
handle to the remote process.
I've tried many combinations of access rights.
Here's the current code.
void sysLog( LPTSTR lpFrom )
{
WCHAR s[512];
DWORD dwErr = ::GetLastError();
::ZeroMemory( s, 512 );
if( (FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwErr,
0,
s,
512,
NULL ) ) == 0 )
{
::std::wcout << lpFrom << L" FormatMessage error ::GetLastError()
was " << dwErr << std::endl;
}
else
{
::std::wcout << lpFrom << L" Error: " << dwErr << L" " << s <<
std::endl;
}
}
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
BOOL GetCurrentUserAndDomain( DWORD dwPID,
PTSTR szUser, PDWORD pcchUser,
PTSTR szDomain, PDWORD pcchDomain)
{
BOOL fSuccess = FALSE;
HANDLE hToken = NULL;
PTOKEN_USER ptiUser = NULL;
DWORD cbti = 0;
SID_NAME_USE snu;
HANDLE hProc = NULL;
HANDLE hProcSelf = NULL;
HANDLE hTokenSelf = NULL;
__try
{
// not needed if dwPID is the id of this process
hProcSelf = ::OpenProcess( PROCESS_ALL_ACCESS,
FALSE,
::GetCurrentProcessId() );
::OpenProcessToken( hProcSelf,
TOKEN_ADJUST_PRIVILEGES,
&hTokenSelf);
SetPrivilege( hTokenSelf, SE_DEBUG_NAME, TRUE );
// always fails
//SetPrivilege( hTokenSelf, SE_TCB_NAME, TRUE );
//SetPrivilege( hTokenSelf, SE_IMPERSONATE_NAME, TRUE );
hProc = ::OpenProcess( PROCESS_QUERY_INFORMATION,
FALSE,
dwPID );
if( NULL == hProc )
{
sysLog( L"OpenProcess" );
__leave;
}
// fails here always
if( 0 == ::OpenProcessToken( hProc,
TOKEN_QUERY,
&hToken))
{
sysLog( L"OpenProcessToken" );
__leave;
}
// always fails
//SetPrivilege( hToken, SE_DEBUG_NAME, TRUE );
//SetPrivilege( hTokenSelf, SE_TCB_NAME, TRUE );
//SetPrivilege( hToken, SE_IMPERSONATE_NAME, TRUE );
// Obtain the size of the user information in the token.
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti))
{
sysLog( L"GetTokenInformation" );
// Call should have failed due to zero-length buffer.
__leave;
}
else
{
// Call should have failed due to zero-length buffer.
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
sysLog( L"GetTokenInformation" );
__leave;
}
}
// Allocate buffer for user information in the token.
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbti);
if (!ptiUser)
{
sysLog( L"GetTokenInformation" );
__leave;
}
// Retrieve the user information from the token.
if (!GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti))
{
sysLog( L"GetTokenInformation" );
__leave;
}
// Retrieve user name and domain name based on user's SID.
if (!LookupAccountSid( NULL, ptiUser->User.Sid, szUser, pcchUser,
szDomain, pcchDomain, &snu))
{
sysLog( L"GetTokenInformation" );
__leave;
}
fSuccess = TRUE;
}
__finally
{
if( hTokenSelf )
::CloseHandle( hTokenSelf );
// Free resources.
if( hProcSelf )
::CloseHandle( hProcSelf );
if (hToken)
::CloseHandle(hToken);
if (ptiUser)
::HeapFree:GetProcessHeap(), 0, ptiUser);
if( hProc )
::CloseHandle( hProc );
}
return fSuccess;
}
// http://win32.mvps.org/
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szUN[64];
TCHAR szD[64];
DWORD dwUNSize = 64;
DWORD dwDSize = 64;
DWORD dwPID = 0;
BOOL bStatus = FALSE;
if( argc == 2 )
{
dwPID = (DWORD)_ttoi( argv[1] );
std::wcout << "Looking up user account for pid: " << dwPID <<
std::endl;
bStatus = GetCurrentUserAndDomain( dwPID, szUN, &dwUNSize, szD,
&dwDSize );
}
else
{
dwPID = ::GetCurrentProcessId();
std::wcout << "Looking up user account for current process pid: " <<
dwPID << std::endl;
bStatus = GetCurrentUserAndDomain( dwPID, szUN, &dwUNSize, szD,
&dwDSize );
}
if( bStatus )
std::wcout << L"User: " << szUN << " Domain: " << szD << std::endl;
}
one ever gets it to work.
I'm trying to open a process, other than mine, and get the username
the process is running as.
I've found .net code which does this via
System.Management.ManagementObject, but it's slow, apparently runs via
WMI, and I'd just rather do it natively.
Taskmanager does it fine.
I'm running as local admin and trying to view the owner of a process
that was spawned with the runas cmd.
Yet I can't. I get access denied no matter what I do. What am I
missing? Why does the wmi work? It's got to be just using winapi
down below anyway, perhaps it's because of the privileges the wmi
service is running as?
Here's my code, mostly copied, I believe via a MS page.
Can someone tell me what I need to do?
I've tried adjusting my token and the other processes.
Would it be easier to just ::CreateRemoteThread and do it the hard
way?
I can't get past the OpenProcessToken when the proc handle is the
handle to the remote process.
I've tried many combinations of access rights.
Here's the current code.
void sysLog( LPTSTR lpFrom )
{
WCHAR s[512];
DWORD dwErr = ::GetLastError();
::ZeroMemory( s, 512 );
if( (FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwErr,
0,
s,
512,
NULL ) ) == 0 )
{
::std::wcout << lpFrom << L" FormatMessage error ::GetLastError()
was " << dwErr << std::endl;
}
else
{
::std::wcout << lpFrom << L" Error: " << dwErr << L" " << s <<
std::endl;
}
}
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
BOOL GetCurrentUserAndDomain( DWORD dwPID,
PTSTR szUser, PDWORD pcchUser,
PTSTR szDomain, PDWORD pcchDomain)
{
BOOL fSuccess = FALSE;
HANDLE hToken = NULL;
PTOKEN_USER ptiUser = NULL;
DWORD cbti = 0;
SID_NAME_USE snu;
HANDLE hProc = NULL;
HANDLE hProcSelf = NULL;
HANDLE hTokenSelf = NULL;
__try
{
// not needed if dwPID is the id of this process
hProcSelf = ::OpenProcess( PROCESS_ALL_ACCESS,
FALSE,
::GetCurrentProcessId() );
::OpenProcessToken( hProcSelf,
TOKEN_ADJUST_PRIVILEGES,
&hTokenSelf);
SetPrivilege( hTokenSelf, SE_DEBUG_NAME, TRUE );
// always fails
//SetPrivilege( hTokenSelf, SE_TCB_NAME, TRUE );
//SetPrivilege( hTokenSelf, SE_IMPERSONATE_NAME, TRUE );
hProc = ::OpenProcess( PROCESS_QUERY_INFORMATION,
FALSE,
dwPID );
if( NULL == hProc )
{
sysLog( L"OpenProcess" );
__leave;
}
// fails here always
if( 0 == ::OpenProcessToken( hProc,
TOKEN_QUERY,
&hToken))
{
sysLog( L"OpenProcessToken" );
__leave;
}
// always fails
//SetPrivilege( hToken, SE_DEBUG_NAME, TRUE );
//SetPrivilege( hTokenSelf, SE_TCB_NAME, TRUE );
//SetPrivilege( hToken, SE_IMPERSONATE_NAME, TRUE );
// Obtain the size of the user information in the token.
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti))
{
sysLog( L"GetTokenInformation" );
// Call should have failed due to zero-length buffer.
__leave;
}
else
{
// Call should have failed due to zero-length buffer.
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
sysLog( L"GetTokenInformation" );
__leave;
}
}
// Allocate buffer for user information in the token.
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbti);
if (!ptiUser)
{
sysLog( L"GetTokenInformation" );
__leave;
}
// Retrieve the user information from the token.
if (!GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti))
{
sysLog( L"GetTokenInformation" );
__leave;
}
// Retrieve user name and domain name based on user's SID.
if (!LookupAccountSid( NULL, ptiUser->User.Sid, szUser, pcchUser,
szDomain, pcchDomain, &snu))
{
sysLog( L"GetTokenInformation" );
__leave;
}
fSuccess = TRUE;
}
__finally
{
if( hTokenSelf )
::CloseHandle( hTokenSelf );
// Free resources.
if( hProcSelf )
::CloseHandle( hProcSelf );
if (hToken)
::CloseHandle(hToken);
if (ptiUser)
::HeapFree:GetProcessHeap(), 0, ptiUser);
if( hProc )
::CloseHandle( hProc );
}
return fSuccess;
}
// http://win32.mvps.org/
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szUN[64];
TCHAR szD[64];
DWORD dwUNSize = 64;
DWORD dwDSize = 64;
DWORD dwPID = 0;
BOOL bStatus = FALSE;
if( argc == 2 )
{
dwPID = (DWORD)_ttoi( argv[1] );
std::wcout << "Looking up user account for pid: " << dwPID <<
std::endl;
bStatus = GetCurrentUserAndDomain( dwPID, szUN, &dwUNSize, szD,
&dwDSize );
}
else
{
dwPID = ::GetCurrentProcessId();
std::wcout << "Looking up user account for current process pid: " <<
dwPID << std::endl;
bStatus = GetCurrentUserAndDomain( dwPID, szUN, &dwUNSize, szD,
&dwDSize );
}
if( bStatus )
std::wcout << L"User: " << szUN << " Domain: " << szD << std::endl;
}