![](/img/trans.png)
[英]CreateFile always returns error 5 (Access is denied) when trying to open directory for reading
[英]Denied access trying to open process
说明:我陷入了一个问题,我正在尝试打开一个进程并读取该进程的内存。 在我的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 .尝试打开“ the”进程时,拒绝独立可执行文件的访问。 3.可执行文件以具有管理员身份的完整权限运行,IDE也是如此。
我想更详细地了解这一点,所以我有两个关键问题,如果有人心情愉快,我希望有一个非常详细的解释。
问题1:如何使用独立的可执行文件打开进程?
问题2:为什么这个问题会这样发生?
如果您缺少任何信息,请随时询问,我会尽快添加。 我还尝试对某些部分进行高级处理,以使阅读起来更轻松,并快速而又简短地了解问题。
我正在尝试打开一个进程并读取该进程的内存。 调试时一切正常
这是因为您的用户帐户具有SE_DEBUG_NAME
( SeDebugPrivilege
) 。 开发人员使用SE_DEBUG_NAME
进行开发很常见,但不建议这样做。
您应该以常规用户帐户身份进行开发,以确保不会得到此类意外的依赖关系。
让我感到困惑的是,它在IDE中可以正常工作,但不能与独立的可执行文件一起工作...
现在问题解决了...
问题1:如何使用独立的可执行文件打开进程?
问题2:为什么这个问题会这样发生?
有几种方法可以修复它。
首先,您可以通过在清单选项中设置/MANIFESTUAC:level=requireAdministrator
来“编译”特权。 “编译特权”有点误导,因为UAC仍会提示您。 请参阅MSDN上的/MANIFESTUAC
。
其次,您可以在程序的属性上设置“以管理员身份运行” 。 右键单击可执行文件,然后选择“ 兼容性”选项卡。 请参阅将应用程序配置为始终以管理员身份在Technet上运行 。 UAC将提示您。
第三,您可以右键单击您的可执行文件,然后选择“以管理员身份运行” 。 您需要在每次调用程序时执行此操作。 UAC将提示您。
仅以“以管理员身份运行”还不够。 您现在需要启用一两个特权。 这是因为启用了所有权限Windows 不启动程序(不象Linux / Unix和su
或sudo
)。 在特权常量中列出的特权中 ,以下是三个或四个有趣的特权 :
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 };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.