前幾天為了回應一個想模擬ntsd -c q -p 1234 的殺process的程式,就寫了一個提昇至debug權限的class,原本是用c語言的file scope data hidding技術,但為了方便也用在一般的cpp程式中,就改寫成一個class。請指教!
//Header part
//---------------------------------------------------------------------------
#ifndef CTokenPrivH
#define CTokenPrivH
#include
class CTokenPriv
{
private:
TOKEN_PRIVILEGES Priv, PrivOld;
DWORD cbPriv;
DWORD dwError;
HANDLE hToken;
protected:
public:
bool __fastcall SetPriv(const char *szPrivType);
__fastcall CTokenPriv()
{
cbPriv = sizeof(PrivOld);
hToken = 0;
}
__fastcall ~CTokenPriv();
void __fastcall ReStorePriv();
};
//---------------------------------------------------------------------------
#endif
// cpp part
//---------------------------------------------------------------------------
#include "CTokenPriv.h"
//---------------------------------------------------------------------------
__fastcall CTokenPriv::~CTokenPriv()
{
if(hToken)
CloseHandle(hToken);
}
bool __fastcall CTokenPriv::SetPriv(const char *szPrivType)
{
// get current thread token
if (!OpenThreadToken(GetCurrentThread(),
TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
false, &hToken))
{
if (GetLastError() != ERROR_NO_TOKEN)
return false;
// revert to the process token, if not impersonating
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
&hToken))
return false;
}
Priv.PrivilegeCount = 1;
Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(NULL, szPrivType,
&Priv.Privileges[0].Luid);
// try to enable the privilege
if (!AdjustTokenPrivileges(hToken, false, &Priv, sizeof(Priv),
&PrivOld, &cbPriv))
{
dwError = GetLastError();
CloseHandle(hToken);
return SetLastError(dwError), false;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
// the SE_DEBUG_NAME privilege is not in the caller's token
CloseHandle(hToken);
return SetLastError(ERROR_ACCESS_DENIED), false;
}
return true;
}
void __fastcall CTokenPriv::ReStorePriv()
{
// restore original privilege state
AdjustTokenPrivileges(hToken, false, &PrivOld, sizeof(PrivOld),
NULL, NULL);
}
------------------------------------------------------------------------------------------
一個使用的實例: 修改ktop某篇古老的文章,作者忘了…sorry,也許努力查下可以知道是誰寫的…
AnsiString temp = "";
HANDLE hProcessSnap=NULL;
HANDLE hProcess=NULL;
PROCESSENTRY32 pe32={0};
int iProcessCount=0;
PROCESS_MEMORY_COUNTERS pmc={0};
//Create privilege object
CTokenPriv token;
hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pe32.dwSize=sizeof(PROCESSENTRY32);
do
{
temp = temp pe32.szExeFile;
// enable debug privilege
token.SetPriv(SE_DEBUG_NAME);
hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if(hProcess!=NULL)
{
ZeroMemory(&pmc, sizeof(PROCESS_MEMORY_COUNTERS));
pmc.cb=sizeof(PROCESS_MEMORY_COUNTERS);
GetProcessMemoryInfo(hProcess,&pmc,sizeof(PROCESS_MEMORY_COUNTERS));
temp = temp " | " IntToStr(pmc.WorkingSetSize/1024) " K";
}
temp = temp "\n";
ZeroMemory(&pe32, sizeof(PROCESSENTRY32));
pe32.dwSize=sizeof(PROCESSENTRY32);
iProcessCount ;
} while(Process32Next(hProcessSnap, &pe32));
// restore original privilege
token.ReStorePriv();
CloseHandle(hProcessSnap);
ShowMessage(temp);
//hint : 可試著把提昇權限的部份拿掉,比較有何不同…
另外,也可以將限權設定成不同的值,如 SE_SHUTDOWN_NAME,就可以實作windows 關機程式…
希望這小小的class可以方便reuse!