说明:我遇到了一个问题,我正在尝试打开一个进程并读取该进程的内存。它在我的VS 2013 IDE中调试时工作正常但是,如果我构建它并以管理员身份运行独立可执行文件(或更低的凭据),则无法正常打开进程,我收到错误代码5,这是拒绝访问
让我感到困惑的是它在IDE中运行良好但不支持独立可执行文件。我不明白为什么VS 2013拥有比以管理员身份运行程序更高的凭据。
代码的链接在这里:
https://floobits.com/Simple2012/Simple_Bot
The important section is memoryReading.cpp line 30-35
问题摘要如下: 1。在Visual Studio 2013中一切正常。 2。尝试打开“该”进程时,独立可执行文件被拒绝访问。 3. 可执行文件以管理员的完全权限运行,IDE也是如此。
我想更加详细地理解这一点,所以我有两个关键问题,如果有人心情愉快,我希望得到一个非常详细的解释。
问题1:如何使用独立的可执行文件打开进程?
问题2:为什么会出现这种问题?
如果您遗失任何信息,请不要犹豫,我会尽快加入。我还尝试对某些部分进行高亮处理,使其阅读更加舒适,并快速简单地了解问题。
答案 0 :(得分:0)
我试图打开一个进程并读取该进程的内存。它在调试时工作正常
这是因为您的用户帐户有SE_DEBUG_NAME
(SeDebugPrivilege
)。开发人员使用SE_DEBUG_NAME
进行开发很常见,但不建议使用。
您应该开发为常规用户帐户,以确保您不会遇到这些意外的依赖关系。
让我感到困惑的是它在IDE中运行良好,但没有使用独立的可执行文件......
现在问题已经解决......
问题1:如何使用独立可执行文件打开进程?
问题2:为什么会出现这种问题?
有几种方法可以解决它。
首先,你可以"编译"通过在清单选项中设置/MANIFESTUAC:level=requireAdministrator
来获得权限。 "编译"中的权限有点误导,因为UAC仍然会提示您。请参阅MSDN上的/MANIFESTUAC
。
其次,您可以在程序的属性中设置"以管理员身份运行" 。右键单击可执行文件,然后选择兼容性选项卡。请参阅Technet上的Configure Applications to Always Run as an Administrator。 UAC会提示您。
第三,您可以右键单击您的可执行文件,然后选择"以管理员身份运行" 。您需要在每次调用程序时执行此操作。 UAC会提示您。
"以管理员身份运行" 是不够的。您现在需要启用一两个权限。这是因为Windows 不启动了启用所有权限的进程(与Linux / Unix和su
或sudo
不同)。在Privilege Constants中列出的特权中,有三个或四个有趣的特权:
SE_ASSIGNPRIMARYTOKEN_NAME
SE_DEBUG_NAME
SE_TCB_NAME
SE_INCREASE_QUOTA_NAME
这是我用来启用权限的代码,例如"SeDebugPrivilege"
:
BOOL CUserPrivilege::EnablePrivilege( LPCTSTR pszPrivilege, BOOL bEnabled ){
// Returned to caller
BOOL bResult = FALSE;
// Thread or Process token
HANDLE hToken = NULL;
__try {
bResult = OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &hToken );
if( !bResult )
{
bResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken );
assert( TRUE == bResult );
if( FALSE == bResult ) { __leave; }
}
bResult = EnablePrivilege( hToken, pszPrivilege, bEnabled );
DWORD dwError = GetLastError();
assert( TRUE == bResult || ( ERROR_SUCCESS == GetLastError() || ERROR_NOT_ALL_ASSIGNED == dwError ) );
// We're only enabling one privilege. If we get back
// ERROR_NOT_ALL_ASSIGNED, then we failed.
if( ERROR_NOT_ALL_ASSIGNED == dwError ) { bResult = FALSE; }
}
__finally {
if( NULL != hToken ) {
CloseHandle( hToken ); hToken = NULL;
}
}
return bResult;
}
BOOL CUserPrivilege::EnablePrivilege( HANDLE hToken, LPCTSTR pszPrivilege, BOOL bEnabled )
{
BOOL bResult = FALSE;
__try {
LUID luid;
TOKEN_PRIVILEGES priv;
bResult = LookupPrivilegeValue( NULL, pszPrivilege, &luid );
assert( TRUE == bResult );
if( FALSE == bResult ) { __leave; }
priv.PrivilegeCount = 1;
priv.Privileges[0].Luid = luid;
priv.Privileges[0].Attributes =
(bEnabled ? SE_PRIVILEGE_ENABLED : FALSE );
bResult = AdjustTokenPrivileges( hToken, FALSE, &priv, sizeof(priv), NULL, NULL );
// We're only enabling one privilege. If we get back
// ERROR_NOT_ALL_ASSIGNED, we failed.
if( ERROR_NOT_ALL_ASSIGNED == GetLastError() ) { bResult = FALSE; }
if( FALSE == bResult ) { __leave; }
bResult = TRUE;
}
__finally { ; }
return bResult;
}
您可以使用与以下类似的代码检查您拥有的权限:
CUserPrivilege::Status CUserPrivilege::HasPrivilege( LPCTSTR pszPrivilege )
{
// Returned to caller
Status status = Error;
// Thread or Process token
HANDLE hToken = NULL;
// Scratch
BOOL bResult = FALSE;
__try {
bResult = OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken );
if( !bResult )
{
bResult = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken );
assert( TRUE == bResult );
if( FALSE == bResult ) { __leave; }
}
status = HasPrivilege( hToken, pszPrivilege );
}
__finally {
if( NULL != hToken ) {
CloseHandle( hToken ); hToken = NULL;
}
}
return status;
}
CUserPrivilege::Status CUserPrivilege::HasPrivilege( HANDLE hToken, LPCTSTR pszPrivilege )
{
// Returned to caller
Status status = Error;
// Scratch
BOOL bResult = FALSE;
PBYTE pBuffer = NULL;
TOKEN_PRIVILEGES* pTokenInfo = NULL;
__try
{
LUID uid = { 0, 0 };
bResult = LookupPrivilegeValue( NULL, pszPrivilege, &uid );
assert( TRUE == bResult );
if( FALSE == bResult ) { __leave; }
DWORD dwRequired = 0;
bResult = GetTokenInformation( hToken, TokenPrivileges, NULL, 0, &dwRequired );
assert( FALSE == bResult );
if( TRUE == bResult || 0 == dwRequired ) { __leave; }
pBuffer = new BYTE[dwRequired];
assert( NULL != pBuffer );
if( NULL == pBuffer ) { __leave; }
DWORD dwSize = dwRequired;
bResult = GetTokenInformation( hToken, TokenPrivileges, pBuffer, dwSize, &dwRequired );
assert( TRUE == bResult );
if( FALSE == bResult || dwSize != dwRequired ) { __leave; }
pTokenInfo = (TOKEN_PRIVILEGES*)pBuffer;
DWORD count = pTokenInfo->PrivilegeCount;
// Status changed...
status = Missing;
for( DWORD i = 0; i<count; i++ )
{
if( pTokenInfo->Privileges[i].Luid.HighPart == uid.HighPart &&
pTokenInfo->Privileges[i].Luid.LowPart == uid.LowPart )
{
DWORD attrib = pTokenInfo->Privileges[i].Attributes;
if( (attrib & SE_PRIVILEGE_ENABLED) ||
(attrib & SE_PRIVILEGE_ENABLED_BY_DEFAULT) )
{
status = Enabled;
}
else if( (attrib & SE_PRIVILEGE_REMOVED) )
{
status = Disabled;
}
break;
}
}
}
__finally
{
if( NULL != pBuffer ) {
delete[] pBuffer; pBuffer = NULL;
}
}
return status;
}
这里是代码中提到的Status
枚举:
enum Status { Missing = -1, Error = 0, Disabled = 1, Enabled = 2 };