openProcess时拒绝访问(GetlastError为5),返回的HANDLE为NULL的解决方法

遇到的问题:在winXP的VS2010里调试好的程序,直接双击exe文件能运行,但是什么都没执行,就是没有按我程序中写的去执行。
找出问题的方法:由于是执行exe文件出的错误,因此用普通的打印语句(printf,cout等)是没用的,我在程序 中每隔几行向一个文件写内容(写日志)或加一个messageBox来判断程序执行到哪儿出现了问题。
具体介绍:最近在写一个进程监控管理的程序,都已经写好了,并且在Win7上运行是OK的,但是把Realease版的exe文件和需要的dll文件放到winXP系统的机器上运行,也能运行,但是,就是不能达到预期的效果,就是需要kill一个进程的时候,它并没有kill掉,好像什么都没执行,后来,通过在程序中每隔几行向一个文件写内容(或弹出messageBox)来调试,发现openProcess的返回HANDLE为NULL。再用GetLastError()打印出错误码,发现为5(拒绝访问)。是权限不够。
     
后来就查资料,发现是权限不够造成的,可以用如下的函数来提升权限(获取权限):
BOOL  EnableDebugPrivilege()
{
  HANDLE hToken;
  BOOL fOk=FALSE;
  if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken)) //Get Token
  {
    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount=1;
    if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid))//Get Luid
      printf("Can't lookup privilege value.\n");
    tp.Privileges[0].Attributes= SE_PRIVILEGE_ENABLED;//这一句很关键,修改其属性为SE_PRIVILEGE_ENABLED
    if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL))//Adjust Token
      printf("Can't adjust privilege value.\n");
    fOk=(GetLastError()==ERROR_SUCCESS);
    CloseHandle(hToken);
  }
    return fOk;
}
在枚举进程之前,加上上述代码解决了我的问题。
     上述代码主要用到了四个API函数:
OpenProcessToken():得到进程的令牌句柄
LookupPrivilegeValue(): 查询进程的权限 
AdjustTokenPrivileges(): 判断令牌权限
GetCurrentProcess(): 得到当前进程的伪句柄
前三个是重点。
其中,
OpenProcessToken()的原型如下:
BOOL OpenProcessToken( 
HANDLE ProcessHandle, 
DWORD DesiredAccess, 
PHANDLE TokenHandle 
);
第一参数是要修改访问权限的进程句柄;第二个参数指定你要进行的操作类型,如要修改令牌我们要指定第二个参数为TOKEN_ADJUST_PRIVILEGES(其它一些参数可参考Platform SDK);第三个参数就是返回的访问令牌指针。通过这个函数我们就可以得到当前进程的访问令牌的句柄(指定函数的第一个参数为GetCurrentProcess()就可以了)。
后面三个的函数原型就不介绍了,可查MSDN。

         要对一个任意进程(包括系统安全进程和服务进程)进行指定了写相关的访问权的OpenProcess操作,只要当前进程具有SeDeDebug权限就可以了。要是一个用户是Administrator或是被给予了相应的权限,就可以具有该权限。可是,就算我们用Administrator帐号对一个系统安全进程执行OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessID)还是会遇到“访问拒绝”的错误。什么原因呢?原来在默认的情况下进程的一些访问权限是没有被使能(Enabled)的,所以我们要做的首先是使能这些权限。与此相关的一些API函数有OpenProcessToken、LookupPrivilegevalue、AdjustTokenPrivileges。我们要修改一个进程的访问令牌,首先要获得进程访问令牌的句柄,这可以通过OpenProcessToken得到。


-----注:在win7上是不需要提上权限的,若用上述代码提升权限,会提升失败。

==============================================================================
另外,还可以参考:
(1)http://www.cppblog.com/steven/articles/51109.html      学习任务管理器中进程管理部分发现问题.
      可以使用进程枚举出所有进程,但是处理进程的时候总是出现问题,无法操作进程,包括访问,结束.代码如下:
 HANDLE hProcess=INVALID_HANDLE_VALUE;
 HANDLE hSnapshot=INVALID_HANDLE_VALUE;
 hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 PROCESSENTRY32 pe;
 Process32First(hSnapshot,&pe);
 do
 {
      // do what you want
      hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe.th32ProcessID);

      if(hProcess==NULL) 

      {

           _stprintf(szTemp,"OpenProcess() fail\n %d\n%s",GetLastError(),pe.szExeFile);
           wsprintf(szExePath,_T("%s"),"not get Process handle OpenProcess()");

     }

    else if(0==GetModuleFileNameEx((HINSTANCE)hProcess,NULL,szExePath,MAX_PATH))

     {
         _stprintf(szTemp,"GetModuleFileName() fail %d\n%s\n%s",GetLastError(),pe.szExeFile,szExePath);
         wsprintf(szExePath,_T("%s"),"not get Process handle GetModuleFileName()");

    }


  }while(Process32Next(hSnapshot,&pe));

 CloseHandle(hSnapshot); 

OpenProcess() 错误ERROR CODE 5:拒绝访问.需要取得相应的权限.
OpenProcessToken函数的功能是打开一个与一进程相联系的访问令牌(access token),它的原型如下: 
BOOL OpenProcessToken( 
  HANDLE ProcessHandle,  
  DWORD DesiredAccess,  
  PHANDLE TokenHandle 
); 


如同MSDN上所说,对于Windows XP Professional,如果一台计算机加入到一个工作组中,而且"Force network logons using local accounts to authenticate as Guest"的限制被激活的话,此函数会失败。 


另外,如果在调用的时候使用了TOKEN_ALL_ACCESS请求,函数也可能会失败。这是因为TOKEN_ALL_ACCESS可能包含了TOKEN_ADJUST_SESSIONID(在Winnt.h中被定义)。TOKEN_ADJUST_SESSIONID是一个新的访问mask,是在Windows 2000和Windows XP中新增的。在Windows NT 4.0中,访问令牌的访问控制列表中是没有这个值的。所以,如果一个应用程序是使用新的Platform SDK中的Winnt.h但却在Windows NT 4.0下运行的话,在调用OpenProcessToken()或者OpenThreadToken时指定了TOKEN_ALL_ACCESS的话,函数也会失败(使用GetLastError()返回的是ERROR_ACCESS_DENIED)。 

typedef struct    _TOKEN_PRIVILEGES { 
  DWORD PrivilegeCount; 
  LUID_AND_ATTRIBUTES PrivilegeCount; 
  LUID_AND_ATTRIBUTES Privileges[]; } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES; 


AdjustTokenPrivileges()函数原型如下:

BOOL AdjustTokenPrivileges(
  HANDLE TokenHandle,              // handle to token
  BOOL TokenHandle,              // handle to token
  BOOL DisableAllPrivileges,       // disabling option
  PTOKEN_PRIVILEGES NewState,      // privilege information
  DWORD NewState,      // privilege information
  DWORD BufferLength,              // size of buffer
  PTOKEN_PRIVILEGES PreviousState, // original state buffer
  PDWORD PreviousState, // original state buffer
  PDWORD ReturnLength              // required buffer size
);

在枚举所有进程之前获取操作权限,就可以避免出错的问题,当然参数要设置为Enable.
具体实现如下:
BOOL ProcessPrivilege(BOOL bEnable)
{
 BOOL                   bResult = TRUE;
 HANDLE               hToken=INVALID_HANDLE_VALUE;
 TOKEN_PRIVILEGES     TokenPrivileges;
 if(OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,&hToken) == 0)
 {
     printf("OpenProcessToken Error: %d\n",GetLastError());
     bResult = FALSE;
 }
 TokenPrivileges.PrivilegeCount           = 1;
 TokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
 LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&TokenPrivileges.Privileges[0].Luid);
 AdjustTokenPrivileges(hToken,FALSE,&TokenPrivileges,sizeof(TOKEN_PRIVILEGES),NULL,NULL);
    if(GetLastError() != ERROR_SUCCESS)
 {
     bResult = FALSE;
 }
 CloseHandle(hToken);
    
 return bResult;

}

这样就OK了。

--------------------------------------------------------------------
(2)http://blog.csdn.net/stonesharp/article/details/7709674
-------------------------------------------------------------------
(3)http://bbs.csdn.net/topics/50003733
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们需要注入AC.exe进程,然后使用D3D绘制文字。这里提供一种思路: 1. 使用CreateRemoteThread函数创建一个远程线程,使得线程在AC.exe进程空间中执行。 2. 在远程线程中使用LoadLibraryA函数加载d3d9.dll,并获取Direct3DCreate9函数的地址。 3. 使用Direct3DCreate9函数创建IDirect3D9对象,并获取IDirect3DDevice9对象。 4. 创建ID3DXFont对象,并使用DrawText函数绘制文字。 5. 释放资源并退出线程。 下面是示例代码: ```c++ #include <Windows.h> #include <iostream> #include <d3d9.h> #include <d3dx9.h> // 字体大小 const int FONT_SIZE = 30; // 需要绘制的文字 const char* TEXT_TO_DRAW = "我厉害吧"; // AC.exe进程名 const char* PROCESS_NAME = "AC.exe"; void DrawTextInACProcess() { // 获取AC.exe进程句柄 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessIdByName(PROCESS_NAME)); if (hProcess == NULL) { std::cout << "OpenProcess failed, error code: " << GetLastError() << std::endl; return; } // 加载d3d9.dll LPVOID pLoadLibrary = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); if (pLoadLibrary == NULL) { std::cout << "GetProcAddress failed, error code: " << GetLastError() << std::endl; CloseHandle(hProcess); return; } // 在AC.exe进程中加载d3d9.dll LPVOID pRemoteLibraryPath = VirtualAllocEx(hProcess, NULL, strlen("d3d9.dll") + 1, MEM_COMMIT, PAGE_READWRITE); if (pRemoteLibraryPath == NULL) { std::cout << "VirtualAllocEx failed, error code: " << GetLastError() << std::endl; CloseHandle(hProcess); return; } if (!WriteProcessMemory(hProcess, pRemoteLibraryPath, "d3d9.dll", strlen("d3d9.dll") + 1, NULL)) { std::cout << "WriteProcessMemory failed, error code: " << GetLastError() << std::endl; VirtualFreeEx(hProcess, pRemoteLibraryPath, strlen("d3d9.dll") + 1, MEM_RELEASE); CloseHandle(hProcess); return; } HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibrary, pRemoteLibraryPath, 0, NULL); if (hRemoteThread == NULL) { std::cout << "CreateRemoteThread failed, error code: " << GetLastError() << std::endl; VirtualFreeEx(hProcess, pRemoteLibraryPath, strlen("d3d9.dll") + 1, MEM_RELEASE); CloseHandle(hProcess); return; } WaitForSingleObject(hRemoteThread, INFINITE); VirtualFreeEx(hProcess, pRemoteLibraryPath, strlen("d3d9.dll") + 1, MEM_RELEASE); // 获取Direct3DCreate9函数地址 LPVOID pDirect3DCreate9 = (LPVOID)GetProcAddress(GetModuleHandleA("d3d9.dll"), "Direct3DCreate9"); if (pDirect3DCreate9 == NULL) { std::cout << "GetProcAddress failed, error code: " << GetLastError() << std::endl; CloseHandle(hProcess); return; } // 在AC.exe进程中创建IDirect3D9对象 IDirect3D9* pD3D9 = NULL; HANDLE hRemoteD3D9 = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pDirect3DCreate9, NULL, 0, NULL); if (hRemoteD3D9 == NULL) { std::cout << "CreateRemoteThread failed, error code: " << GetLastError() << std::endl; CloseHandle(hProcess); return; } WaitForSingleObject(hRemoteD3D9, INFINITE); DWORD dwRemoteD3D9; if (!GetExitCodeThread(hRemoteD3D9, &dwRemoteD3D9)) { std::cout << "GetExitCodeThread failed, error code: " << GetLastError() << std::endl; CloseHandle(hRemoteD3D9); CloseHandle(hProcess); return; } pD3D9 = (IDirect3D9*)dwRemoteD3D9; CloseHandle(hRemoteD3D9); // 在AC.exe进程中创建IDirect3DDevice9对象 IDirect3DDevice9* pD3DDevice9 = NULL; D3DPRESENT_PARAMETERS d3dpp = { 0 }; d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; HANDLE hRemoteD3DDevice9 = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)&pD3D9->CreateDevice, NULL, 0, NULL); if (hRemoteD3DDevice9 == NULL) { std::cout << "CreateRemoteThread failed, error code: " << GetLastError() << std::endl; CloseHandle(hProcess); return; } WaitForSingleObject(hRemoteD3DDevice9, INFINITE); DWORD dwRemoteD3DDevice9; if (!GetExitCodeThread(hRemoteD3DDevice9, &dwRemoteD3DDevice9)) { std::cout << "GetExitCodeThread failed, error code: " << GetLastError() << std::endl; CloseHandle(hRemoteD3DDevice9); CloseHandle(hProcess); return; } pD3DDevice9 = (IDirect3DDevice9*)dwRemoteD3DDevice9; CloseHandle(hRemoteD3DDevice9); // 创建ID3DXFont对象 ID3DXFont* pFont = NULL; if (FAILED(D3DXCreateFont(pD3DDevice9, FONT_SIZE, 0, FW_NORMAL, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &pFont))) { std::cout << "D3DXCreateFont failed" << std::endl; pD3DDevice9->Release(); pD3D9->Release(); CloseHandle(hProcess); return; } // 绘制文字 RECT rect = { 100, 100, 0, 0 }; pFont->DrawText(NULL, TEXT_TO_DRAW, -1, &rect, DT_LEFT | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255, 0, 255, 0)); // 释放资源 pFont->Release(); pD3DDevice9->Release(); pD3D9->Release(); CloseHandle(hProcess); } DWORD GetProcessIdByName(const char* name) { DWORD pid = 0; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snapshot != INVALID_HANDLE_VALUE) { PROCESSENTRY32 processEntry; processEntry.dwSize = sizeof(processEntry); if (Process32First(snapshot, &processEntry)) { do { if (strcmp(processEntry.szExeFile, name) == 0) { pid = processEntry.th32ProcessID; break; } } while (Process32Next(snapshot, &processEntry)); } CloseHandle(snapshot); } return pid; } int main() { DrawTextInACProcess(); return 0; } ``` 需要注意的是,由于AC.exe可能使用了反作弊措施,导致无法注入代码,因此可能需要使用更复杂的技术手段,比如DLL注入或代码挂载等。此处仅提供一种基本思路,具体实现需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值