問題
在枚舉/結(jié)束系統(tǒng)進(jìn)程或操作系統(tǒng)服務(wù)時(shí),會(huì)出現(xiàn)權(quán)限不足而失敗的情況,這時(shí)就需要提升自己進(jìn)程到系統(tǒng)權(quán)限
前置知識(shí)
windows的每個(gè)用戶登錄系統(tǒng)后萎津,系統(tǒng)會(huì)產(chǎn)生一個(gè)訪問令牌(access token)兆蕉,其中關(guān)聯(lián)了當(dāng)前用戶的權(quán)限信息,用戶登錄后創(chuàng)建的每一個(gè)進(jìn)程都含有用戶access token的拷貝悼枢,當(dāng)進(jìn)程試圖執(zhí)行某些需要特殊權(quán)限的操作或是訪問受保護(hù)的內(nèi)核對(duì)象時(shí),系統(tǒng)會(huì)檢查其acess token中的權(quán)限信息以決定是否授權(quán)操作。Administrator組成員的access token中會(huì)含有一些可以執(zhí)行系統(tǒng)級(jí)操作的特權(quán)(privileges) 畸冲,如終止任意進(jìn)程、關(guān)閉/重啟系統(tǒng)观腊、加載設(shè)備驅(qū)動(dòng)和更改系統(tǒng)時(shí)間等邑闲,不過這些特權(quán)默認(rèn)是被禁用的,當(dāng)Administrator組成員創(chuàng)建的進(jìn)程中包含一些需要特權(quán)的操作時(shí)梧油,進(jìn)程必須首先打開這些禁用的特權(quán)以提升自己的權(quán)限苫耸,否則系統(tǒng)將拒絕進(jìn)程的操作。注意儡陨,非Administrator組成員創(chuàng)建的進(jìn)程無法提升自身的權(quán)限褪子,因此下面提到的進(jìn)程均指Administrator組成員創(chuàng)建的進(jìn)程。(命令行輸入net user可查看或net user 具體用戶名稱)
Windows以字符串的形式表示系統(tǒng)特權(quán)骗村,如“SeCreatePagefilePrivilege”表示該特權(quán)用于創(chuàng)建頁面文件嫌褪,“SeDebugPrivilege”表示該特權(quán)可用于調(diào)試及更改其它進(jìn)程的內(nèi)存,為了便于在代碼中引用這些字符串胚股,微軟在winnt.h中定義了一組宏笼痛,如 #define SE_DEBUG_NAME TEXT("SeDebugPrivilege")。完整的特權(quán)列表可以查閱msdn的security一章信轿。雖然Windows使用字符串表示特權(quán)晃痴,但查詢或更改特權(quán)的API需要LUID來引用相應(yīng)的特權(quán)残吩,LUID表示local unique identifier,它是一個(gè)64位值倘核,在當(dāng)前系統(tǒng)中是唯一的泣侮。為了提升進(jìn)程權(quán)限到指定的特權(quán),我們必須先找到該特權(quán)對(duì)應(yīng)的LUID紧唱,這時(shí)要調(diào)用LookupPrivilegeValue函數(shù)活尊。
簡介
要對(duì)一個(gè)任意進(jìn)程(包括系統(tǒng)安全進(jìn)程和服務(wù)進(jìn)程)進(jìn)行指定了寫相關(guān)的訪問權(quán)的OpenProcess操作,只要當(dāng)前進(jìn)程具有SeDeDebug權(quán)限就可以了漏益。要是一個(gè)用戶是Administrator或是被給予了相應(yīng)的權(quán)限蛹锰,就可以具有該權(quán)限〈掳蹋可是铜犬,就算我們用Administrator帳號(hào)對(duì)一個(gè)系統(tǒng)安全進(jìn)程執(zhí)OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessID)還是會(huì)遇到“訪問拒絕”的錯(cuò)誤。什么原因呢轻庆?原來在默認(rèn)的情況下進(jìn)程的一些訪問權(quán)限是沒有被啟用(Enabled)的癣猾,所以我們要做的首先是啟用這些權(quán)限。
流程
1.打開進(jìn)程訪問令牌
2.取得特權(quán)的LUID值
3.調(diào)整訪問令牌特權(quán)值
使用函數(shù)
OpenProcessToken();
LookupPrivilegeValue();
AdjustTokenPrivileges();
函數(shù)介紹及大致流程
首先要獲得進(jìn)程訪問令牌的句柄余爆,這可以通過OpenProcessToken得到纷宇,函數(shù)的原型如下:
BOOL OpenProcessToken(
HANDLE ProcessHandle, //要修改訪問權(quán)限的進(jìn)程句柄
DWORD DesiredAccess, //要對(duì)令牌進(jìn)行何種操作
PHANDLE TokenHandle //返回的訪問令牌指針
);
第一參數(shù)是要修改訪問權(quán)限的進(jìn)程句柄蛾方;第三個(gè)參數(shù)就是返回的訪問令牌指針像捶;第二個(gè)參數(shù)指定你要進(jìn)行的操作類型,如要修改訪問令牌的特權(quán)桩砰,我們要指定第二個(gè)參數(shù)TOKEN_ADJUST_PRIVILEGES拓春。通過這個(gè)函數(shù)我們就可以得到當(dāng)前進(jìn)程的訪問令牌的句柄(指定函數(shù)的第一個(gè)參數(shù)為GetCurrentProcess()就可以了)。接著我們可以調(diào)用AdjustTokenPrivileges對(duì)這個(gè)訪問令牌進(jìn)行修改五芝。
AdjustTokenPrivileges的原型如下:
BOOL AdjustTokenPrivileges(
HANDLE TokenHandle, // handle to token
BOOL DisableAllPrivileges, // disabling option
PTOKEN_PRIVILEGES NewState, // privilege information
DWORD BufferLength, // size of buffer
PTOKEN_PRIVILEGES PreviousState, // original state buffer
PDWORD ReturnLength // required buffer size
);
第一個(gè)參數(shù)是訪問令牌的句柄痘儡;第二個(gè)參數(shù)決定是進(jìn)行權(quán)限修改還是喪失(Disable)所有權(quán)限辕万;第三個(gè)參數(shù)指明要修改的權(quán)限枢步,是一個(gè)指向TOKEN_PRIVILEGES結(jié)構(gòu)的指針,該結(jié)構(gòu)包含一個(gè)數(shù)組渐尿,數(shù)據(jù)組的每個(gè)項(xiàng)指明了權(quán)限的類型和要進(jìn)行的操作; 第四個(gè)參數(shù)是結(jié)構(gòu)PreviousState 指針?biāo)赶虻木彌_區(qū)的大小醉途,如果PreviousState參數(shù)為空,該參數(shù)應(yīng)為NULL砖茸;第五個(gè)參數(shù)也是一個(gè)指向TOKEN_PRIVILEGES結(jié)構(gòu)的指針隘擎,存放修改前的訪問權(quán)限的信息,可空凉夯;最后一個(gè)參數(shù)為實(shí)際PRIVILEGES NewState結(jié)構(gòu)返回的大小货葬。在使用這個(gè)函數(shù)前再看一下TOKEN_PRIVILEGES這個(gè)結(jié)構(gòu)采幌,其聲明如下:
typedef struct _TOKEN_PRIVILEGES {
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
PrivilegeCount指的數(shù)組元素的個(gè)數(shù),接著是一個(gè)LUID_AND_ATTRIBUTES類型的數(shù)組震桶,再來看一下LUID_AND_ATTRIBUTES這個(gè)結(jié)構(gòu)的內(nèi)容休傍,聲明如下:
typedef struct _LUID_AND_ATTRIBUTES {
LUID Luid;
DWORD Attributes;
} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES
第二個(gè)參數(shù)就指明了我們要進(jìn)行的操作類型,其特權(quán)屬性Attributes可以是如下常量:
SE_PRIVILEGE_ENABLED //使特權(quán)有效
SE_PRIVILEGE_ENABLED_BY_DEFAULT //使特權(quán)默認(rèn)有效
SE_PRIVILEGE_REMOVED //移除該特權(quán)
SE_PRIVILEGE_USED_FOR_ACCESS //取得對(duì)象或服務(wù)的訪問權(quán)
要使用一個(gè)權(quán)限就指定Attributes為SE_PRIVILEGE_ENABLED蹲姐。第一個(gè)參數(shù)就是指權(quán)限的類型磨取,是一個(gè)LUID的值,LUID就是指locally unique identifier(局部唯一標(biāo)識(shí)符)柴墩,我想GUID大家是比較熟悉的忙厌,和GUID的要求保證全局唯一不同,LUID只要保證局部唯一江咳,就是指在系統(tǒng)的每一次運(yùn)行期間保證是唯一的就可以了逢净。另外和GUID相同的一點(diǎn),LUID也是一個(gè)64位的值歼指,相信大家都看過GUID那一大串的值汹胃,我們要怎么樣才能知道一個(gè)權(quán)限對(duì)應(yīng)的LUID值是多少呢?
這就要用到另外一個(gè)API函數(shù)LookupPrivilegevalue东臀,其原形如下:
BOOL LookupPrivilegevalue(
LPCTSTR lpSystemName, // system name
LPCTSTR lpName, // privilege name
PLUID lpLuid // locally unique identifier
);
第一個(gè)參數(shù)是系統(tǒng)的名稱着饥,如果是本地系統(tǒng)只要指明為NULL就可以了,第三個(gè)參數(shù)就是返回LUID的指針惰赋,第二個(gè)參數(shù)就是指明了權(quán)限的名稱宰掉,如“SeDebugPrivilege”。在Winnt.h中還定義了一些權(quán)限名稱的宏赁濒,如:
#define SE_BACKUP_NAME TEXT("SeBackupPrivilege")
#define SE_RESTORE_NAME TEXT("SeRestorePrivilege")
#define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")
#define SE_DEBUG_NAME TEXT("SeDebugPrivilege")
這樣通過這三個(gè)函數(shù)的調(diào)用轨奄,我們就可以用OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessID)來打獲得任意進(jìn)程的句柄,并且指定了所有的訪問權(quán)
代碼實(shí)現(xiàn)
#include <stdio.h>
#include <windows.h>
int main(void)
{
HANDLE token_handle;
//打開訪問令牌
if(!OpenProcessToken(GetCurrentProcess(), //要修改權(quán)限的進(jìn)程句柄
TOKEN_ALL_ACCESS, //要對(duì)令牌進(jìn)行何種操作
&token_handle //訪問令牌
))
{
printf("openProcessToken error");
}
LUID luid;
if(!LookupPrivilegeValue(NULL, //查看的系統(tǒng)拒炎,本地為NULL
SE_DEBUG_NAME, //要查看的特權(quán)名稱
&luid //用來接收標(biāo)識(shí)符
))
{
printf("lookupPrivilegevalue error");
}
TOKEN_PRIVILEGES tkp;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//調(diào)整訪問令牌權(quán)限
if(!AdjustTokenPrivileges(token_handle, //令牌句柄
FALSE, //是否禁用權(quán)限
&tkp, //新的特權(quán)的權(quán)限信息
sizeof(tkp), //特權(quán)信息大小
NULL, //用來接收特權(quán)信息當(dāng)前狀態(tài)的buffer
NULL //緩沖區(qū)大小
))
{
printf("adjust error");
}
printf("sucessful");
return 0;
}
第五篇~~~~~~~~~~~~~~~
“長到這么大挪拟,我說不出來我最愛的一部電影,說不出我來我最愛的一首歌击你,說不出來我最愛的一個(gè)人玉组。時(shí)常覺得人生其實(shí)沒有那么有趣,偶爾也會(huì)質(zhì)疑活著的意義丁侄,所有來自書上和別人口中的意義都不曾說服過我惯雳。但今天突然覺得,大概人生中最大的意義就是用余生去找那些最愛吧鸿摇∈埃” ——德卡先生的信箱
給我點(diǎn)十個(gè)贊我就買杯可樂慶祝下